diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/AUTHORS heat-14.0.0/AUTHORS --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/AUTHORS 2020-04-10 16:59:07.000000000 +0000 +++ heat-14.0.0/AUTHORS 2020-05-13 10:50:31.000000000 +0000 @@ -94,6 +94,7 @@ Colleen Murphy Colleen Murphy Crag Wolfe +Cédric Ollivier Dan Dan Prince Daniel Givens @@ -160,6 +161,7 @@ Harald Jensås He Jie Xu He Yongli +Hervé Beraud Hironori Shiina Hongbin Lu Hongbin Lu diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/bin/heat-api heat-14.0.0/bin/heat-api --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/bin/heat-api 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/bin/heat-api 2020-05-13 10:48:27.000000000 +0000 @@ -18,6 +18,9 @@ An OpenStack REST API to Heat. """ +import os +import sys + from oslo_log import log as logging @@ -27,8 +30,6 @@ 'system level heat binaries installed to start ' 'any of the heat services.') -import os -import sys # If ../heat/__init__.py exists, add ../ to Python search path, so that # it will override what happens to be installed in /usr/(local/)lib/python... @@ -39,6 +40,6 @@ if os.path.exists(os.path.join(POSSIBLE_TOPDIR, 'heat', '__init__.py')): sys.path.insert(0, POSSIBLE_TOPDIR) -from heat.cmd import api +from heat.cmd import api # noqa: E402 api.main() diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/bin/heat-api-cfn heat-14.0.0/bin/heat-api-cfn --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/bin/heat-api-cfn 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/bin/heat-api-cfn 2020-05-13 10:48:27.000000000 +0000 @@ -20,6 +20,9 @@ AMQP RPC to implement them. """ +import os +import sys + from oslo_log import log as logging @@ -29,9 +32,6 @@ 'the system level heat binaries installed to start ' 'any of the heat services.') -import os -import sys - # If ../heat/__init__.py exists, add ../ to Python search path, so that # it will override what happens to be installed in /usr/(local/)lib/python... POSSIBLE_TOPDIR = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), @@ -41,6 +41,6 @@ if os.path.exists(os.path.join(POSSIBLE_TOPDIR, 'heat', '__init__.py')): sys.path.insert(0, POSSIBLE_TOPDIR) -from heat.cmd import api_cfn +from heat.cmd import api_cfn # noqa: E402 api_cfn.main() diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/bin/heat-engine heat-14.0.0/bin/heat-engine --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/bin/heat-engine 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/bin/heat-engine 2020-05-13 10:48:27.000000000 +0000 @@ -20,6 +20,10 @@ engine. """ + +import os +import sys + from oslo_log import log as logging @@ -29,8 +33,6 @@ 'Please use the system level heat binaries installed to ' 'start any of the heat services.') -import os -import sys # If ../heat/__init__.py exists, add ../ to Python search path, so that # it will override what happens to be installed in /usr/(local/)lib/python... @@ -41,6 +43,6 @@ if os.path.exists(os.path.join(POSSIBLE_TOPDIR, 'heat', '__init__.py')): sys.path.insert(0, POSSIBLE_TOPDIR) -from heat.cmd import engine +from heat.cmd import engine # noqa: E402 engine.main() diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/bin/heat-manage heat-14.0.0/bin/heat-manage --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/bin/heat-manage 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/bin/heat-manage 2020-05-13 10:48:27.000000000 +0000 @@ -13,6 +13,10 @@ # See the License for the specific language governing permissions and # limitations under the License. + +import os +import sys + from oslo_log import log as logging @@ -21,8 +25,6 @@ LOG.warning('DEPRECATED: `heat-manage` script is deprecated. Please use ' 'the system level heat-manage binary.') -import os -import sys # If ../heat/__init__.py exists, add ../ to Python search path, so that # it will override what happens to be installed in /usr/(local/)lib/python... @@ -32,6 +34,6 @@ if os.path.exists(os.path.join(POSSIBLE_TOPDIR, 'heat', '__init__.py')): sys.path.insert(0, POSSIBLE_TOPDIR) -from heat.cmd import manage +from heat.cmd import manage # noqa: E402 manage.main() diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/ChangeLog heat-14.0.0/ChangeLog --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/ChangeLog 2020-04-10 16:59:06.000000000 +0000 +++ heat-14.0.0/ChangeLog 2020-05-13 10:50:30.000000000 +0000 @@ -1,8 +1,37 @@ CHANGES ======= +14.0.0 +------ + +* New resource OS::Neutron::QoSMinimumBandwidthRule +* Add Ironic Port resource type support +* Mark OS::Neutron::QoSDscpMarkingRule as admin only +* Imported Translations from Zanata +* Imported Translations from Zanata +* Remove six and python 2.7 full support +* Remove six and python 2.7 full support +* Remove six and python 2.7 full support +* Remove six and python 2.7 full support +* Remove six and python 2.7 full support +* Remove six and python 2.7 full support +* Remove six and python 2.7 full support +* Remove six and python 2.7 full support +* Remove six and python 2.7 full support +* Remove six and python 2.7 full support +* Prepare the six and python 2.7 support dropping +* Fix hacking warnings +* Update hacking for Python3 +* Fix doc building with Sphinx 3 +* Reduce Heat engine workers +* Imported Translations from Zanata +* Fix genconfig tox env +* Add ironic client plugin support +* Sync lower contraint with test-requirement * Imported Translations from Zanata +* Filter by project id in list\_security\_groups * Keep db model and migration scripts in sync +* Retry transactions for DBConnectionError * Add Octavia Quota Resource for lbaas quota parameters * Support allowed\_cidrs for Octavia listener * Handle OS::Mistral::Workflow resource replacement properly @@ -21,10 +50,12 @@ * Docs: Fix links broken since Train release * Docs: Fix link broken since Stein release * Docs: use extrefs to link to other projects' docs +* Add group property for OS::Heat::MultipartMime * Add support for Octavia's Flavor and FlavorProfile resources * Fix Designate Zone ID lookup for real * Remove image upload dependency on g-reg * New resource OS::Neutron::ExtraRouteSet +* Use random exponential delay * Fix OS::Neutron::ExtraRoute delete with IPv6 * Heat templates doesn't support AZ for trove cluster * Migrate heat-functional-non-apache to zuul v3 diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/contrib/heat_docker/heat_docker/resources/docker_container.py heat-14.0.0/contrib/heat_docker/heat_docker/resources/docker_container.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/contrib/heat_docker/heat_docker/resources/docker_container.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/contrib/heat_docker/heat_docker/resources/docker_container.py 2020-05-13 10:48:27.000000000 +0000 @@ -17,7 +17,6 @@ import distutils from oslo_log import log as logging -import six from heat.common import exception from heat.common.i18n import _ @@ -340,7 +339,7 @@ def _parse_networkinfo_ports(self, networkinfo): tcp = [] udp = [] - for port, info in six.iteritems(networkinfo['Ports']): + for port, info in networkinfo['Ports'].items(): p = port.split('/') if not info or len(p) != 2 or 'HostPort' not in info[0]: continue diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/contrib/heat_docker/heat_docker/tests/test_docker_container.py heat-14.0.0/contrib/heat_docker/heat_docker/tests/test_docker_container.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/contrib/heat_docker/heat_docker/tests/test_docker_container.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/contrib/heat_docker/heat_docker/tests/test_docker_container.py 2020-05-13 10:48:27.000000000 +0000 @@ -15,7 +15,6 @@ # under the License. import mock -import six from heat.common import exception from heat.common.i18n import _ @@ -126,7 +125,7 @@ exc = self.assertRaises(exception.ResourceInError, docker_res.check_create_complete, 'foo') - self.assertIn("Container startup failed", six.text_type(exc)) + self.assertIn("Container startup failed", str(exc)) def test_start_with_bindings_and_links(self): t = template_format.parse(template) @@ -331,7 +330,7 @@ args = dict(arg=arg, min_version=min_version) expected = _('"%(arg)s" is not supported for API version ' '< "%(min_version)s"') % args - self.assertEqual(expected, six.text_type(msg)) + self.assertEqual(expected, str(msg)) def test_start_with_read_only_for_low_api_version(self): self.arg_for_low_api_version('read_only', True, '1.16') diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/debian/changelog heat-14.0.0/debian/changelog --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/debian/changelog 2020-04-10 17:00:14.000000000 +0000 +++ heat-14.0.0/debian/changelog 2020-05-13 20:51:44.000000000 +0000 @@ -1,3 +1,14 @@ +heat (1:14.0.0-0ubuntu1) groovy; urgency=medium + + * d/watch: Scope to 14.x series and get tarballs from opendev.org. + * d/control: Align (Build-)Depends with upstream. + * d/p/monkey-patch-original-current-thread.patch: Cherry-picked + from upstream review (https://review.opendev.org/#/c/727181/) + to fix Python 3.8 monkey patching (LP: #1863021). + * New upstream release for OpenStack Ussuri (LP: #1877642). + + -- Corey Bryant Wed, 13 May 2020 16:51:44 -0400 + heat (1:14.0.0~b3~git2020041012.2ef9f4bf3-0ubuntu1) focal; urgency=medium * New upstream snapshot for OpenStack Ussuri. diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/debian/control heat-14.0.0/debian/control --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/debian/control 2020-04-10 17:00:14.000000000 +0000 +++ heat-14.0.0/debian/control 2020-05-13 20:51:44.000000000 +0000 @@ -40,6 +40,7 @@ python3-greenlet (>= 0.4.10), python3-hacking (>= 0.12.0), python3-heatclient (>= 1.10.0), + python3-ironicclient (>= 2.8.0), python3-keystoneauth1 (>= 3.18.0), python3-keystoneclient (>= 1:3.8.0), python3-keystonemiddleware (>= 4.17.0), @@ -181,6 +182,7 @@ python3-gnocchiclient (>= 3.3.1), python3-greenlet (>= 0.4.10), python3-heatclient (>= 1.10.0), + python3-ironicclient (>= 2.8.0), python3-keystoneauth1 (>= 3.18.0), python3-keystoneclient (>= 1:3.8.0), python3-keystonemiddleware (>= 4.17.0), diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/debian/patches/monkey-patch-original-current-thread.patch heat-14.0.0/debian/patches/monkey-patch-original-current-thread.patch --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/debian/patches/monkey-patch-original-current-thread.patch 1970-01-01 00:00:00.000000000 +0000 +++ heat-14.0.0/debian/patches/monkey-patch-original-current-thread.patch 2020-05-13 20:51:44.000000000 +0000 @@ -0,0 +1,89 @@ +From 8fd17214a97322a8a0136e50ced1d65a7d9dd75e Mon Sep 17 00:00:00 2001 +From: Corey Bryant +Date: Mon, 4 May 2020 13:18:10 -0400 +Subject: [PATCH] Monkey patch original current_thread _active + +Monkey patch the original current_thread to use the up-to-date _active +global variable. This solution is based on that documented at: +https://github.com/eventlet/eventlet/issues/592 + +Change-Id: I0540923755ac3969b584eeba2e19c037a7f2c261 +Story: 2007614 +--- + heat/cmd/all.py | 6 ++++++ + heat/cmd/api.py | 6 ++++++ + heat/cmd/api_cfn.py | 6 ++++++ + heat/cmd/engine.py | 6 ++++++ + 4 files changed, 24 insertions(+) + +diff --git a/heat/cmd/all.py b/heat/cmd/all.py +index 526bc7fa2..d9c7dd0d6 100644 +--- a/heat/cmd/all.py ++++ b/heat/cmd/all.py +@@ -20,6 +20,12 @@ An OpenStack Heat server that can run all services. + + import eventlet + eventlet.monkey_patch(os=False) ++# Monkey patch the original current_thread to use the up-to-date _active ++# global variable. See https://bugs.launchpad.net/bugs/1863021 and ++# https://github.com/eventlet/eventlet/issues/592 ++import __original_module_threading as orig_threading ++import threading # noqa ++orig_threading.current_thread.__globals__['_active'] = threading._active + + import sys + +diff --git a/heat/cmd/api.py b/heat/cmd/api.py +index b8ea0111c..4ab22b0d6 100644 +--- a/heat/cmd/api.py ++++ b/heat/cmd/api.py +@@ -20,6 +20,12 @@ An OpenStack ReST API to Heat. + + import eventlet + eventlet.monkey_patch(os=False) ++# Monkey patch the original current_thread to use the up-to-date _active ++# global variable. See https://bugs.launchpad.net/bugs/1863021 and ++# https://github.com/eventlet/eventlet/issues/592 ++import __original_module_threading as orig_threading ++import threading # noqa ++orig_threading.current_thread.__globals__['_active'] = threading._active + + import sys + +diff --git a/heat/cmd/api_cfn.py b/heat/cmd/api_cfn.py +index bc7cd5b02..2a44605e5 100644 +--- a/heat/cmd/api_cfn.py ++++ b/heat/cmd/api_cfn.py +@@ -22,6 +22,12 @@ AMQP RPC to implement them. + + import eventlet + eventlet.monkey_patch(os=False) ++# Monkey patch the original current_thread to use the up-to-date _active ++# global variable. See https://bugs.launchpad.net/bugs/1863021 and ++# https://github.com/eventlet/eventlet/issues/592 ++import __original_module_threading as orig_threading ++import threading # noqa ++orig_threading.current_thread.__globals__['_active'] = threading._active + + import sys + +diff --git a/heat/cmd/engine.py b/heat/cmd/engine.py +index f30081d7e..b969a4c22 100644 +--- a/heat/cmd/engine.py ++++ b/heat/cmd/engine.py +@@ -22,6 +22,12 @@ engine. + + import eventlet + eventlet.monkey_patch() ++# Monkey patch the original current_thread to use the up-to-date _active ++# global variable. See https://bugs.launchpad.net/bugs/1863021 and ++# https://github.com/eventlet/eventlet/issues/592 ++import __original_module_threading as orig_threading ++import threading # noqa ++orig_threading.current_thread.__globals__['_active'] = threading._active + + import sys + +-- +2.25.1 + diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/debian/patches/series heat-14.0.0/debian/patches/series --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/debian/patches/series 2020-04-10 17:00:14.000000000 +0000 +++ heat-14.0.0/debian/patches/series 2020-05-13 20:51:44.000000000 +0000 @@ -1 +1,2 @@ sudoers_patch.patch +monkey-patch-original-current-thread.patch diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/debian/watch heat-14.0.0/debian/watch --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/debian/watch 2020-04-10 17:00:14.000000000 +0000 +++ heat-14.0.0/debian/watch 2020-05-13 20:51:44.000000000 +0000 @@ -1,3 +1,3 @@ version=3 opts="uversionmangle=s/\.([a-zA-Z])/~$1/;s/%7E/~/;s/\.0b/~b/;s/\.0rc/~rc/" \ - https://tarballs.openstack.org/heat openstack-heat-(13\.\d.*)\.tar\.gz + https://tarballs.opendev.org/openstack/heat openstack-heat-(14\.\d.*)\.tar\.gz diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/devstack/lib/heat heat-14.0.0/devstack/lib/heat --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/devstack/lib/heat 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/devstack/lib/heat 2020-05-13 10:48:27.000000000 +0000 @@ -78,6 +78,7 @@ fi HEAT_PLUGIN_DIR=${HEAT_PLUGIN_DIR:-$DATA_DIR/heat/plugins} ENABLE_HEAT_PLUGINS=${ENABLE_HEAT_PLUGINS:-} +HEAT_ENGINE_WORKERS=${HEAT_ENGINE_WORKERS:=$(( ($(nproc)/4)<2 ? 2 : ($(nproc)/4) ))} # Functions # --------- @@ -135,6 +136,9 @@ # logging iniset $HEAT_CONF DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL + # reduce Heat engine workers + iniset $HEAT_CONF DEFAULT num_engine_workers "$HEAT_ENGINE_WORKERS" + local no_format="False" if [[ "$HEAT_USE_APACHE" == "True" && "$WSGI_MODE" != "uwsgi" ]]; then no_format="True" diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/doc/source/ext/resources.py heat-14.0.0/doc/source/ext/resources.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/doc/source/ext/resources.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/doc/source/ext/resources.py 2020-05-13 10:48:27.000000000 +0000 @@ -19,7 +19,6 @@ from docutils import core from docutils import nodes from docutils.parsers import rst -import six from heat.common.i18n import _ from heat.engine import attributes @@ -433,7 +432,7 @@ else: filtered_resources[name] = [cls] - return sorted(six.iteritems(filtered_resources)) + return sorted(filtered_resources.items()) def _load_all_resources(): diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/doc/source/glossary.rst heat-14.0.0/doc/source/glossary.rst --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/doc/source/glossary.rst 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/doc/source/glossary.rst 2020-05-13 10:48:27.000000000 +0000 @@ -24,10 +24,10 @@ CFN An abbreviated form of "AWS CloudFormation". - Constraint + constraint Defines valid input :term:`parameters` for a :term:`template`. - Dependency + dependency When a :term:`resource` must wait for another resource to finish creation before being created itself. Heat adds an implicit dependency when a resource references another resource or one of @@ -35,7 +35,7 @@ dependency can also be created by the user in the template definition. - Environment + environment Used to affect the run-time behavior of the template. Provides a way to override the default resource implementation and parameters passed to Heat. See :ref:`Environments`. @@ -48,8 +48,8 @@ HOT An acronym for ":term:`Heat Orchestration Template`". - Input parameters - See :term:`Parameters`. + input parameters + See :term:`parameters`. Metadata May refer to :term:`Resource Metadata`, :term:`Nova Instance @@ -60,14 +60,14 @@ retrieve instance-specific data. See :nova-doc:`Nova Metadata service documentation `. - Multi-region + multi-region A feature of Heat that supports deployment to multiple regions. - Nested resource + nested resource A :term:`resource` instantiated as part of a :term:`nested stack`. - Nested stack + nested stack A :term:`template` referenced by URL inside of another template. Used to reduce redundant resource definitions and group complex architectures into logical groups. @@ -81,42 +81,42 @@ OpenStack Open source software for building private and public clouds. - Orchestrate + orchestrate Arrange or direct the elements of a situation to produce a desired effect. - Outputs + outputs A top-level block in a :term:`template` that defines what data will be returned by a stack after instantiation. - Parameters + parameters A top-level block in a :term:`template` that defines what data can be passed to customise a template when it is used to create or update a :term:`stack`. - Provider resource + provider resource A :term:`resource` implemented by a :term:`provider template`. The parent resource's properties become the :term:`nested stack's ` parameters. - Provider template + provider template Allows user-definable :term:`resource providers ` to be specified via :term:`nested stacks `. The nested stack's :term:`outputs` become the parent stack's :term:`attributes `. - Resource + resource An element of OpenStack infrastructure instantiated from a - particular :term:`resource provider`. See also :term:`Nested + particular :term:`resource provider`. See also :term:`nested resource`. - Resource attribute + resource attribute Data that can be obtained from a :term:`resource`, e.g. a server's public IP or name. Usually passed to another resource's :term:`properties ` or added to the stack's :term:`outputs`. - Resource group + resource group A :term:`resource provider` that creates one or more identically configured :term:`resources ` or :term:`nested resources `. @@ -127,37 +127,37 @@ .. _AWS::CloudFormation::Init (AWS CloudFormation User Guide): https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-init.html - Resource plugin + resource plugin Python code that understands how to instantiate and manage a :term:`resource`. See `Heat Resource Plugins (OpenStack wiki)`_. .. _Heat Resource Plugins (OpenStack wiki): https://wiki.openstack.org/wiki/Heat/Plugins#Heat_Resource_Plugins - Resource property + resource property Data utilized for the instantiation of a :term:`resource`. Can be defined statically in a :term:`template` or passed in as :term:`input parameters `. - Resource provider + resource provider The implementation of a particular resource type. May be a - :term:`Resource plugin` or a :term:`Provider template`. + :term:`resource plugin` or a :term:`provider template`. - Stack + stack A collection of instantiated :term:`resources ` that are defined in a single :term:`template`. - Stack resource + stack resource A :term:`resource provider` that allows the management of a :term:`nested stack` as a :term:`resource` in a parent stack. - Template + template An orchestration document that details everything needed to carry out an :term:`orchestration `. - Template resource - See :term:`Provider resource`. + template resource + See :term:`provider resource`. - User data + user data A :term:`resource property` that contains a user-provided data blob. User data gets passed to `cloud-init`_ to automatically configure instances at boot time. See also :nova-doc:`Nova User data @@ -165,7 +165,7 @@ .. _cloud-init: https://cloudinit.readthedocs.io/ - Wait condition + wait condition A :term:`resource provider` that provides a way to communicate data or events from servers back to the orchestration engine. Most commonly used to pause the creation of the diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/api/aws/exception.py heat-14.0.0/heat/api/aws/exception.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/api/aws/exception.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/api/aws/exception.py 2020-05-13 10:48:27.000000000 +0000 @@ -17,7 +17,6 @@ """Heat API exception subclasses - maps API response errors to AWS Errors.""" from oslo_utils import reflection -import six import webob.exc from heat.common.i18n import _ @@ -322,7 +321,7 @@ ex_type = ex_type[:-len('_Remote')] safe = getattr(ex, 'safe', False) - detail = six.text_type(ex) if safe else None + detail = str(ex) if safe else None if ex_type in inval_param_errors: return HeatInvalidParameterValueError(detail=detail) diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/api/middleware/fault.py heat-14.0.0/heat/api/middleware/fault.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/api/middleware/fault.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/api/middleware/fault.py 2020-05-13 10:48:27.000000000 +0000 @@ -24,7 +24,6 @@ from oslo_config import cfg from oslo_utils import reflection -import six import webob from heat.common import exception @@ -127,7 +126,7 @@ if is_remote: ex_type = ex_type[:-len('_Remote')] - full_message = six.text_type(ex) + full_message = str(ex) if '\n' in full_message and is_remote: message, msg_trace = full_message.split('\n', 1) elif traceback_marker in full_message: diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/api/openstack/v1/actions.py heat-14.0.0/heat/api/openstack/v1/actions.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/api/openstack/v1/actions.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/api/openstack/v1/actions.py 2020-05-13 10:48:27.000000000 +0000 @@ -11,7 +11,6 @@ # License for the specific language governing permissions and limitations # under the License. -import six from webob import exc from heat.api.openstack.v1 import util @@ -57,7 +56,7 @@ if len(body) > 1: raise exc.HTTPBadRequest(_("Multiple actions specified")) - ac = next(six.iterkeys(body)) + ac = next(iter(body.keys())) if ac not in self.ACTIONS: raise exc.HTTPBadRequest(_("Invalid action %s specified") % ac) diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/api/openstack/v1/events.py heat-14.0.0/heat/api/openstack/v1/events.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/api/openstack/v1/events.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/api/openstack/v1/events.py 2020-05-13 10:48:27.000000000 +0000 @@ -13,7 +13,6 @@ import itertools -import six from webob import exc from heat.api.openstack.v1 import util @@ -133,7 +132,7 @@ params[key] = param_utils.extract_int( key, params[key], allow_zero=True) except ValueError as e: - raise exc.HTTPBadRequest(six.text_type(e)) + raise exc.HTTPBadRequest(str(e)) if resource_name is None: if not filter_params: diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/api/openstack/v1/__init__.py heat-14.0.0/heat/api/openstack/v1/__init__.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/api/openstack/v1/__init__.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/api/openstack/v1/__init__.py 2020-05-13 10:48:27.000000000 +0000 @@ -12,7 +12,6 @@ # under the License. import routes -import six from heat.api.openstack.v1 import actions from heat.api.openstack.v1 import build_info @@ -51,7 +50,7 @@ for r in routes: url = path_prefix + r['url'] methods = r['method'] - if isinstance(methods, six.string_types): + if isinstance(methods, str): methods = [methods] methods_str = ','.join(methods) mapper.connect(r['name'], url, controller=controller, diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/api/openstack/v1/resources.py heat-14.0.0/heat/api/openstack/v1/resources.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/api/openstack/v1/resources.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/api/openstack/v1/resources.py 2020-05-13 10:48:27.000000000 +0000 @@ -13,7 +13,6 @@ import itertools -import six from webob import exc from heat.api.openstack.v1 import util @@ -89,7 +88,7 @@ try: return extractor(key, req.params[key]) except ValueError as e: - raise exc.HTTPBadRequest(six.text_type(e)) + raise exc.HTTPBadRequest(str(e)) else: return default @@ -111,7 +110,7 @@ rpc_api.PARAM_WITH_DETAIL])) if invalid_keys: raise exc.HTTPBadRequest(_('Invalid filter parameters %s') % - six.text_type(list(invalid_keys))) + str(list(invalid_keys))) nested_depth = self._extract_to_param(req, rpc_api.PARAM_NESTED_DEPTH, @@ -186,7 +185,7 @@ RES_UPDATE_MARK_UNHEALTHY, body[RES_UPDATE_MARK_UNHEALTHY]) except ValueError as e: - raise exc.HTTPBadRequest(six.text_type(e)) + raise exc.HTTPBadRequest(str(e)) data[RES_UPDATE_STATUS_REASON] = body.get(RES_UPDATE_STATUS_REASON, "") self.rpc_client.resource_mark_unhealthy(req.context, diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/api/openstack/v1/software_configs.py heat-14.0.0/heat/api/openstack/v1/software_configs.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/api/openstack/v1/software_configs.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/api/openstack/v1/software_configs.py 2020-05-13 10:48:27.000000000 +0000 @@ -11,7 +11,6 @@ # License for the specific language governing permissions and limitations # under the License. -import six from webob import exc from heat.api.openstack.v1 import util @@ -42,7 +41,7 @@ try: return param_utils.extract_bool(name, value) except ValueError as e: - raise exc.HTTPBadRequest(six.text_type(e)) + raise exc.HTTPBadRequest(str(e)) def _index(self, req, use_admin_cnxt=False): whitelist = { diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/api/openstack/v1/stacks.py heat-14.0.0/heat/api/openstack/v1/stacks.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/api/openstack/v1/stacks.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/api/openstack/v1/stacks.py 2020-05-13 10:48:27.000000000 +0000 @@ -15,8 +15,7 @@ import contextlib from oslo_log import log as logging -import six -from six.moves.urllib import parse +from urllib import parse from webob import exc from heat.api.openstack.v1 import util @@ -79,7 +78,7 @@ try: yield except ValueError as parse_ex: - mdict = {'type': data_type, 'error': six.text_type(parse_ex)} + mdict = {'type': data_type, 'error': str(parse_ex)} msg = _("%(type)s not in valid format: %(error)s") % mdict raise exc.HTTPBadRequest(msg) @@ -101,7 +100,7 @@ try: adopt_data = template_format.simple_parse(adopt_data) template_format.validate_template_limit( - six.text_type(adopt_data['template'])) + str(adopt_data['template'])) return adopt_data['template'] except (ValueError, KeyError) as ex: err_reason = _('Invalid adopt data: %s') % ex @@ -109,7 +108,7 @@ elif self.PARAM_TEMPLATE in self.data: template_data = self.data[self.PARAM_TEMPLATE] if isinstance(template_data, dict): - template_format.validate_template_limit(six.text_type( + template_format.validate_template_limit(str( template_data)) return template_data @@ -188,7 +187,7 @@ try: return param_utils.extract_bool(name, value) except ValueError as e: - raise exc.HTTPBadRequest(six.text_type(e)) + raise exc.HTTPBadRequest(str(e)) def _extract_int_param(self, name, value, allow_zero=True, allow_negative=False): @@ -196,13 +195,13 @@ return param_utils.extract_int(name, value, allow_zero, allow_negative) except ValueError as e: - raise exc.HTTPBadRequest(six.text_type(e)) + raise exc.HTTPBadRequest(str(e)) def _extract_tags_param(self, tags): try: return param_utils.extract_tags(tags) except ValueError as e: - raise exc.HTTPBadRequest(six.text_type(e)) + raise exc.HTTPBadRequest(str(e)) def _index(self, req, use_admin_cnxt=False): filter_whitelist = { @@ -392,7 +391,7 @@ if not is_update and key in args: msg = _("%s flag only supported in stack update (or update " "preview) request.") % key - raise exc.HTTPBadRequest(six.text_type(msg)) + raise exc.HTTPBadRequest(str(msg)) return args @util.registered_policy_enforce @@ -700,7 +699,7 @@ req.params.get(rpc_api.TEMPLATE_TYPE)) except ValueError as ex: msg = _("Template type is not supported: %s") % ex - raise exc.HTTPBadRequest(six.text_type(msg)) + raise exc.HTTPBadRequest(str(msg)) return self.rpc_client.generate_template(req.context, type_name, @@ -753,10 +752,7 @@ def _populate_response_header(self, response, location, status): response.status = status - if six.PY2: - response.headers['Location'] = location.encode('utf-8') - else: - response.headers['Location'] = location + response.headers['Location'] = location response.headers['Content-Type'] = 'application/json' return response @@ -764,7 +760,7 @@ self._populate_response_header(response, result['stack']['links'][0]['href'], 201) - response.body = six.b(self.to_json(result)) + response.body = self.to_json(result).encode('latin-1') return response diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/api/openstack/v1/util.py heat-14.0.0/heat/api/openstack/v1/util.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/api/openstack/v1/util.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/api/openstack/v1/util.py 2020-05-13 10:48:27.000000000 +0000 @@ -11,7 +11,8 @@ # License for the specific language governing permissions and limitations # under the License. -import six +import functools + from webob import exc from heat.common.i18n import _ @@ -41,7 +42,7 @@ def _policy_enforce(handler, is_registered_policy=False): - @six.wraps(handler) + @functools.wraps(handler) def handle_stack_method(controller, req, tenant_id, **kwargs): if req.context.tenant_id != tenant_id and not req.context.is_admin: raise exc.HTTPForbidden() @@ -77,7 +78,7 @@ def _identified_stack(handler, is_registered_policy=False): - @six.wraps(handler) + @functools.wraps(handler) def handle_stack_method(controller, req, stack_name, stack_id, **kwargs): stack_identity = identifier.HeatIdentifier(req.context.tenant_id, stack_name, @@ -126,7 +127,7 @@ """ allowed_params = {} - for key, get_type in six.iteritems(whitelist): + for key, get_type in whitelist.items(): assert get_type in PARAM_TYPES value = None diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/api/openstack/v1/views/views_common.py heat-14.0.0/heat/api/openstack/v1/views/views_common.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/api/openstack/v1/views/views_common.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/api/openstack/v1/views/views_common.py 2020-05-13 10:48:27.000000000 +0000 @@ -11,7 +11,7 @@ # License for the specific language governing permissions and limitations # under the License. -from six.moves.urllib import parse as urlparse +from urllib import parse as urlparse def get_collection_links(request, items): diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/api/versions.py heat-14.0.0/heat/api/versions.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/api/versions.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/api/versions.py 2020-05-13 10:48:27.000000000 +0000 @@ -13,9 +13,9 @@ """Controller that returns information on the heat API versions.""" +import http.client + from oslo_serialization import jsonutils -import six -from six.moves import http_client import webob.dec @@ -43,11 +43,11 @@ body = jsonutils.dumps(dict(versions=version_objs)) response = webob.Response(request=req, - status=http_client.MULTIPLE_CHOICES, + status=http.client.MULTIPLE_CHOICES, content_type='application/json') # NOTE(pas-ha) in WebOb, Response.body accepts only bytes, # and Response.text accepts only unicode. - response.text = six.text_type(body) + response.text = str(body) return response diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/cmd/all.py heat-14.0.0/heat/cmd/all.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/cmd/all.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/cmd/all.py 2020-05-13 10:48:27.000000000 +0000 @@ -15,6 +15,9 @@ An OpenStack Heat server that can run all services. """ + +# flake8: noqa: E402 + import eventlet eventlet.monkey_patch(os=False) @@ -24,7 +27,6 @@ import oslo_i18n as i18n from oslo_log import log as logging from oslo_service import systemd -import six from heat.cmd import api from heat.cmd import api_cfn @@ -65,15 +67,15 @@ def launch_all(setup_logging=True): - if setup_logging: - logging.register_options(cfg.CONF) - cfg.CONF(project='heat', prog='heat-all', - version=version.version_info.version_string()) - if setup_logging: - logging.setup(cfg.CONF, 'heat-all') - config.set_config_defaults() - messaging.setup() - return _start_service_threads(set(cfg.CONF.heat_all.enabled_services)) + if setup_logging: + logging.register_options(cfg.CONF) + cfg.CONF(project='heat', prog='heat-all', + version=version.version_info.version_string()) + if setup_logging: + logging.setup(cfg.CONF, 'heat-all') + config.set_config_defaults() + messaging.setup() + return _start_service_threads(set(cfg.CONF.heat_all.enabled_services)) def main(): @@ -83,5 +85,5 @@ systemd.notify_once() [service.wait() for service in services] except RuntimeError as e: - msg = six.text_type(e) + msg = str(e) sys.exit("ERROR: %s" % msg) diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/cmd/api_cfn.py heat-14.0.0/heat/cmd/api_cfn.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/cmd/api_cfn.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/cmd/api_cfn.py 2020-05-13 10:48:27.000000000 +0000 @@ -18,6 +18,8 @@ AMQP RPC to implement them. """ +# flake8: noqa: E402 + import eventlet eventlet.monkey_patch(os=False) @@ -28,7 +30,6 @@ from oslo_log import log as logging from oslo_reports import guru_meditation_report as gmr from oslo_service import systemd -import six from heat.common import config from heat.common import messaging @@ -74,5 +75,5 @@ systemd.notify_once() server.wait() except RuntimeError as e: - msg = six.text_type(e) + msg = str(e) sys.exit("ERROR: %s" % msg) diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/cmd/api.py heat-14.0.0/heat/cmd/api.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/cmd/api.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/cmd/api.py 2020-05-13 10:48:27.000000000 +0000 @@ -16,6 +16,8 @@ An OpenStack ReST API to Heat. """ +# flake8: noqa: E402 + import eventlet eventlet.monkey_patch(os=False) @@ -26,7 +28,6 @@ from oslo_log import log as logging from oslo_reports import guru_meditation_report as gmr from oslo_service import systemd -import six from heat.common import config from heat.common import messaging @@ -70,5 +71,5 @@ systemd.notify_once() server.wait() except RuntimeError as e: - msg = six.text_type(e) + msg = str(e) sys.exit("ERROR: %s" % msg) diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/cmd/engine.py heat-14.0.0/heat/cmd/engine.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/cmd/engine.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/cmd/engine.py 2020-05-13 10:48:27.000000000 +0000 @@ -18,6 +18,8 @@ engine. """ +# flake8: noqa: E402 + import eventlet eventlet.monkey_patch() diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/cmd/manage.py heat-14.0.0/heat/cmd/manage.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/cmd/manage.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/cmd/manage.py 2020-05-13 10:48:27.000000000 +0000 @@ -19,7 +19,6 @@ from oslo_config import cfg from oslo_log import log -from six import moves from heat.common import context from heat.common import exception @@ -106,7 +105,7 @@ "intended to recover from specific crashes.")) print(_("It is advised to shutdown all Heat engines beforehand.")) print(_("Continue ? [y/N]")) - data = moves.input() + data = input() if not data.lower().startswith('y'): return ctxt = context.get_admin_context() @@ -224,6 +223,7 @@ ServiceManageCommand.add_service_parsers(subparsers) + command_opt = cfg.SubCommandOpt('command', title='Commands', help=_('Show available commands.'), diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/cmd/status.py heat-14.0.0/heat/cmd/status.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/cmd/status.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/cmd/status.py 2020-05-13 10:48:27.000000000 +0000 @@ -50,5 +50,6 @@ return upgradecheck.main( cfg.CONF, project='heat', upgrade_command=Checks()) + if __name__ == '__main__': sys.exit(main()) diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/common/config.py heat-14.0.0/heat/common/config.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/common/config.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/common/config.py 2020-05-13 10:48:27.000000000 +0000 @@ -183,6 +183,11 @@ 'this limitation, any nova feature supported with ' 'microversion number above max_nova_api_microversion ' 'will not be available.')), + cfg.FloatOpt('max_ironic_api_microversion', + help=_('Maximum ironic API version for client plugin. With ' + 'this limitation, any ironic feature supported with ' + 'microversion number above ' + 'max_ironic_api_microversion will not be available.')), cfg.IntOpt('event_purge_batch_size', min=1, default=200, diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/common/context.py heat-14.0.0/heat/common/context.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/common/context.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/common/context.py 2020-05-13 10:48:27.000000000 +0000 @@ -11,6 +11,8 @@ # License for the specific language governing permissions and limitations # under the License. +import functools + from keystoneauth1 import access from keystoneauth1.identity import access as access_plugin from keystoneauth1.identity import generic @@ -23,7 +25,6 @@ import oslo_messaging from oslo_middleware import request_id as oslo_request_id from oslo_utils import importutils -import six from heat.common import config from heat.common import endpoint_utils @@ -407,7 +408,7 @@ def request_context(func): - @six.wraps(func) + @functools.wraps(func) def wrapped(self, ctx, *args, **kwargs): try: return func(self, ctx, *args, **kwargs) diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/common/environment_util.py heat-14.0.0/heat/common/environment_util.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/common/environment_util.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/common/environment_util.py 2020-05-13 10:48:27.000000000 +0000 @@ -13,7 +13,6 @@ import collections from oslo_serialization import jsonutils -import six from heat.common import environment_format as env_fmt from heat.common import exception @@ -62,10 +61,10 @@ old_v = old.get(k) old[k] = merge_map(old_v, v, deep_merge) if old_v else v elif (isinstance(v, collections.Sequence) and - not isinstance(v, six.string_types)): + not isinstance(v, str)): old_v = old.get(k) old[k] = merge_list(old_v, v) if old_v else v - elif isinstance(v, six.string_types): + elif isinstance(v, str): old[k] = ''.join([old.get(k, ''), v]) else: old[k] = v @@ -76,14 +75,14 @@ def parse_param(p_val, p_schema): try: if p_schema.type == p_schema.MAP: - if not isinstance(p_val, six.string_types): + if not isinstance(p_val, str): p_val = jsonutils.dumps(p_val) if p_val: return jsonutils.loads(p_val) elif not isinstance(p_val, collections.Sequence): raise ValueError() except (ValueError, TypeError) as err: - msg = _("Invalid parameter in environment %s.") % six.text_type(err) + msg = _("Invalid parameter in environment %s.") % str(err) raise ValueError(msg) return p_val diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/common/exception.py heat-14.0.0/heat/common/exception.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/common/exception.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/common/exception.py 2020-05-13 10:48:27.000000000 +0000 @@ -21,8 +21,6 @@ from oslo_log import log as logging from oslo_utils import excutils -import six - from heat.common.i18n import _ _FATAL_EXCEPTION_FORMAT_ERRORS = False @@ -38,7 +36,6 @@ } -@six.python_2_unicode_compatible class HeatException(Exception): """Base Heat Exception. @@ -71,7 +68,7 @@ # kwargs doesn't match a variable in the message # log the issue and the kwargs LOG.exception('Exception in string format operation') - for name, value in six.iteritems(kwargs): + for name, value in kwargs.items(): LOG.error("%(name)s: %(value)s", {'name': name, 'value': value}) # noqa @@ -222,7 +219,7 @@ if path is not None: if isinstance(path, list): self.path = path - elif isinstance(path, six.string_types): + elif isinstance(path, str): self.path = [path] result_path = '' @@ -247,7 +244,7 @@ resource=None): if path is None: path = [] - elif isinstance(path, six.string_types): + elif isinstance(path, str): path = [path] if resource is not None and not path: @@ -263,8 +260,8 @@ # oslo.messaging. self.args = error.args else: - str_error = six.text_type(type(error).__name__) - message = six.text_type(error) + str_error = str(type(error).__name__) + message = str(error) else: str_error = error @@ -331,8 +328,8 @@ path = exception_or_error.path else: self.exc = exception_or_error - error = six.text_type(type(self.exc).__name__) - message = six.text_type(self.exc) + error = str(type(self.exc).__name__) + message = str(self.exc) path = res_path else: self.exc = None @@ -418,7 +415,7 @@ """Raised when resource update requires replacement.""" def __init__(self, resource_name='Unknown'): msg = _("The Resource %s requires replacement.") % resource_name - super(Exception, self).__init__(six.text_type(msg)) + super(Exception, self).__init__(str(msg)) class ResourceUnknownStatus(HeatException): @@ -443,7 +440,7 @@ class UpdateInProgress(Exception): def __init__(self, resource_name='Unknown'): msg = _("The resource %s is already being updated.") % resource_name - super(Exception, self).__init__(six.text_type(msg)) + super(Exception, self).__init__(str(msg)) class HTTPExceptionDisguise(Exception): diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/common/grouputils.py heat-14.0.0/heat/common/grouputils.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/common/grouputils.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/common/grouputils.py 2020-05-13 10:48:27.000000000 +0000 @@ -11,8 +11,6 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from heat.common import exception from heat.common.i18n import _ from heat.engine import status @@ -122,7 +120,7 @@ """ resources = [] if group.nested(): - resources = [r for r in six.itervalues(group.nested()) + resources = [r for r in group.nested().values() if include_failed or r.status != r.FAILED] return sorted(resources, diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/common/i18n.py heat-14.0.0/heat/common/i18n.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/common/i18n.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/common/i18n.py 2020-05-13 10:48:27.000000000 +0000 @@ -17,29 +17,10 @@ # recommendations from # https://docs.openstack.org/oslo.i18n/latest/user/usage.html -import six - import oslo_i18n as i18n -from oslo_utils import encodeutils _translators = i18n.TranslatorFactory(domain='heat') # The primary translation function using the well-known name "_" _ = _translators.primary - - -def repr_wrapper(klass): - """A decorator that defines __repr__ method under Python 2. - - Under Python 2 it will encode repr return value to str type. - Under Python 3 it does nothing. - """ - if six.PY2: - if '__repr__' not in klass.__dict__: - raise ValueError("@repr_wrapper cannot be applied " - "to %s because it doesn't define __repr__()." % - klass.__name__) - klass._repr = klass.__repr__ - klass.__repr__ = lambda self: encodeutils.safe_encode(self._repr()) - return klass diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/common/identifier.py heat-14.0.0/heat/common/identifier.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/common/identifier.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/common/identifier.py 2020-05-13 10:48:27.000000000 +0000 @@ -15,7 +15,7 @@ import re from oslo_utils import encodeutils -from six.moves.urllib import parse as urlparse +from urllib import parse as urlparse from heat.common.i18n import _ diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/common/password_gen.py heat-14.0.0/heat/common/password_gen.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/common/password_gen.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/common/password_gen.py 2020-05-13 10:48:27.000000000 +0000 @@ -12,11 +12,10 @@ # under the License. import collections +import io import random as random_module import string -import six - # NOTE(pas-ha) Heat officially supports only POSIX::Linux platform # where os.urandom() and random.SystemRandom() are available @@ -88,19 +87,19 @@ :param char_classes: Iterable over classes of characters from which to generate a password """ - char_buffer = six.StringIO() + char_buffer = io.StringIO() all_allowed_chars = set() # Add the minimum number of chars from each char class for char_class in char_classes: all_allowed_chars |= char_class.allowed_chars allowed_chars = tuple(char_class.allowed_chars) - for i in six.moves.xrange(char_class.min_count): + for i in range(char_class.min_count): char_buffer.write(random.choice(allowed_chars)) # Fill up rest with random chars from provided classes combined_chars = tuple(all_allowed_chars) - for i in six.moves.xrange(max(0, length - char_buffer.tell())): + for i in range(max(0, length - char_buffer.tell())): char_buffer.write(random.choice(combined_chars)) # Shuffle string diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/common/plugin_loader.py heat-14.0.0/heat/common/plugin_loader.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/common/plugin_loader.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/common/plugin_loader.py 2020-05-13 10:48:27.000000000 +0000 @@ -19,12 +19,12 @@ for them before loading them. """ +import functools import pkgutil import sys import types from oslo_log import log as logging -import six LOG = logging.getLogger(__name__) @@ -46,7 +46,7 @@ package_name = _module_name(parent_package_name, subpackage_name) package = types.ModuleType(package_name) - package.__path__ = ([path] if isinstance(path, six.string_types) + package.__path__ = ([path] if isinstance(path, str) else list(path)) sys.modules[package_name] = package @@ -75,7 +75,7 @@ # Make this accessible through the parent package for static imports local_name = module_name.partition(package.__name__ + '.')[2] module_components = local_name.split('.') - parent = six.moves.reduce(getattr, module_components[:-1], package) + parent = functools.reduce(getattr, module_components[:-1], package) setattr(parent, module_components[-1], module) return module diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/common/pluginutils.py heat-14.0.0/heat/common/pluginutils.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/common/pluginutils.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/common/pluginutils.py 2020-05-13 10:48:27.000000000 +0000 @@ -12,7 +12,6 @@ # under the License. from oslo_log import log as logging -import six LOG = logging.getLogger(__name__) @@ -23,5 +22,5 @@ '"%(message)s". Not using %(name)s.', {'module_name': entrypoint.module_name, 'message': getattr(exception, 'message', - six.text_type(exception)), + str(exception)), 'name': entrypoint.name}) diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/common/policy.py heat-14.0.0/heat/common/policy.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/common/policy.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/common/policy.py 2020-05-13 10:48:27.000000000 +0000 @@ -21,7 +21,6 @@ from oslo_log import log as logging from oslo_policy import policy from oslo_utils import excutils -import six from heat.common import exception from heat.common.i18n import _ @@ -151,7 +150,7 @@ except policy.PolicyNotRegistered: result = True except self.exc as ex: - LOG.info(six.text_type(ex)) + LOG.info(str(ex)) raise if not result: if self.exc: diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/common/serializers.py heat-14.0.0/heat/common/serializers.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/common/serializers.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/common/serializers.py 2020-05-13 10:48:27.000000000 +0000 @@ -23,7 +23,6 @@ from lxml import etree from oslo_log import log as logging from oslo_serialization import jsonutils -import six LOG = logging.getLogger(__name__) @@ -34,7 +33,7 @@ def sanitizer(obj): if isinstance(obj, datetime.datetime): return obj.isoformat() - return six.text_type(obj) + return str(obj) response = jsonutils.dumps(data, default=sanitizer) @@ -46,7 +45,7 @@ def default(self, response, result): response.content_type = 'application/json' - response.body = six.b(self.to_json(result)) + response.body = self.to_json(result).encode('latin-1') # Escape XML serialization for these keys, as the AWS API defines them as @@ -75,11 +74,11 @@ else: self.object_to_element(value, subelement) else: - element.text = six.text_type(obj) + element.text = str(obj) def to_xml(self, data): # Assumption : root node is dict with single key - root = next(six.iterkeys(data)) + root = next(iter(data.keys())) eltree = etree.Element(root) self.object_to_element(data.get(root), eltree) response = etree.tostring(eltree) diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/common/short_id.py heat-14.0.0/heat/common/short_id.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/common/short_id.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/common/short_id.py 2020-05-13 10:48:27.000000000 +0000 @@ -19,8 +19,6 @@ import base64 import uuid -import six - from heat.common.i18n import _ @@ -30,12 +28,12 @@ Padding is added at the end (i.e. after the least-significant bit) if required. """ - shifts = six.moves.xrange(num_bits - 8, -8, -8) + shifts = range(num_bits - 8, -8, -8) def byte_at(off): return (value >> off if off >= 0 else value << -off) & 0xff - return b''.join(six.int2byte(byte_at(offset)) for offset in shifts) + return b''.join(bytes((byte_at(offset),)) for offset in shifts) def get_id(source_uuid): @@ -43,7 +41,7 @@ The supplied UUID must be a version 4 UUID object. """ - if isinstance(source_uuid, six.string_types): + if isinstance(source_uuid, str): source_uuid = uuid.UUID(source_uuid) if source_uuid.version != 4: raise ValueError(_('Invalid UUID version (%d)') % source_uuid.version) diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/common/template_format.py heat-14.0.0/heat/common/template_format.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/common/template_format.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/common/template_format.py 2020-05-13 10:48:27.000000000 +0000 @@ -15,7 +15,6 @@ from oslo_config import cfg from oslo_serialization import jsonutils -import six import yaml from heat.common import exception @@ -73,7 +72,7 @@ except yaml.YAMLError as yea: if tmpl_url is None: tmpl_url = '[root stack]' - yea = six.text_type(yea) + yea = str(yea) msg = _('Error parsing template %(tmpl)s ' '%(yea)s') % {'tmpl': tmpl_url, 'yea': yea} raise ValueError(msg) @@ -111,7 +110,7 @@ # TODO(ricolin): Move this validation to api side. # Validate nested stack template. - validate_template_limit(six.text_type(tmpl_str)) + validate_template_limit(str(tmpl_str)) tpl = simple_parse(tmpl_str, tmpl_url) # Looking for supported version keys in the loaded template @@ -136,7 +135,7 @@ def top_level_items(tpl): yield ("HeatTemplateFormatVersion", '2012-12-12') - for k, v in six.iteritems(tpl): + for k, v in tpl.items(): if k != 'AWSTemplateFormatVersion': yield k, v diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/common/urlfetch.py heat-14.0.0/heat/common/urlfetch.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/common/urlfetch.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/common/urlfetch.py 2020-05-13 10:48:27.000000000 +0000 @@ -14,12 +14,14 @@ """Utility for fetching a resource (e.g. a template) from a URL.""" import socket +import urllib.error +import urllib.parse +import urllib.request from oslo_config import cfg from oslo_log import log as logging import requests from requests import exceptions -from six.moves import urllib from heat.common import exception from heat.common.i18n import _ diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/common/wsgi.py heat-14.0.0/heat/common/wsgi.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/common/wsgi.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/common/wsgi.py 2020-05-13 10:48:27.000000000 +0000 @@ -40,7 +40,6 @@ from oslo_utils import importutils from paste.deploy import loadwsgi from routes import middleware -import six import webob.dec import webob.exc @@ -648,7 +647,7 @@ resp = req.get_response(self.application) print(("*" * 40) + " RESPONSE HEADERS") - for (key, value) in six.iteritems(resp.headers): + for (key, value) in resp.headers.items(): print(key, "=", value) print('') @@ -823,7 +822,7 @@ raise exception.RequestLimitExceeded(message=msg) return jsonutils.loads(datastring) except ValueError as ex: - raise webob.exc.HTTPBadRequest(six.text_type(ex)) + raise webob.exc.HTTPBadRequest(str(ex)) def default(self, request): if self.has_body(request): @@ -1004,8 +1003,7 @@ return exc -@six.add_metaclass(abc.ABCMeta) -class BasePasteFactory(object): +class BasePasteFactory(object, metaclass=abc.ABCMeta): """A base class for paste app and filter factories. Sub-classes must override the KEY class attribute and provide diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/db/sqlalchemy/api.py heat-14.0.0/heat/db/sqlalchemy/api.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/db/sqlalchemy/api.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/db/sqlalchemy/api.py 2020-05-13 10:48:27.000000000 +0000 @@ -28,7 +28,6 @@ from oslo_utils import excutils from oslo_utils import timeutils import osprofiler.sqlalchemy -import six import sqlalchemy from sqlalchemy import and_ from sqlalchemy import func @@ -90,29 +89,31 @@ return get_facade().get_session() -def retry_on_deadlock(func): +def retry_on_db_error(func): @functools.wraps(func) def try_func(context, *args, **kwargs): if (context.session.transaction is None or not context.session.autocommit): wrapped = oslo_db_api.wrap_db_retry(max_retries=3, retry_on_deadlock=True, + retry_on_disconnect=True, retry_interval=0.5, inc_retry_interval=True)(func) return wrapped(context, *args, **kwargs) else: try: return func(context, *args, **kwargs) - except db_exception.DBDeadlock: + except (db_exception.DBDeadlock, db_exception.DBConnectionError): with excutils.save_and_reraise_exception(): - LOG.debug('Not retrying on DBDeadlock ' - 'because transaction not closed') + LOG.debug('Not retrying on DBDeadlock and ' + 'DBConnectionError because ' + 'transaction not closed') return try_func def update_and_save(context, obj, values): with context.session.begin(subtransactions=True): - for k, v in six.iteritems(values): + for k, v in values.items(): setattr(obj, k, v) @@ -265,7 +266,7 @@ return results -@retry_on_deadlock +@retry_on_db_error def resource_purge_deleted(context, stack_id): filters = {'stack_id': stack_id, 'action': 'DELETE', 'status': 'COMPLETE'} query = context.session.query(models.Resource) @@ -286,7 +287,7 @@ values['atomic_key'] = atomic_key + 1 -@retry_on_deadlock +@retry_on_db_error def resource_update(context, resource_id, values, atomic_key, expected_engine_id=None): return _try_resource_update(context, resource_id, values, atomic_key, @@ -483,7 +484,7 @@ return resource_ref -@retry_on_deadlock +@retry_on_db_error def resource_create_replacement(context, existing_res_id, existing_res_values, new_res_values, @@ -663,7 +664,7 @@ :param mapping: a mapping from keys to DB column names :returns: filtered list of sort keys """ - if isinstance(sort_keys, six.string_types): + if isinstance(sort_keys, str): sort_keys = [sort_keys] return [mapping[key] for key in sort_keys or [] if key in mapping] @@ -807,7 +808,7 @@ return stack_ref -@retry_on_deadlock +@retry_on_db_error def stack_update(context, stack_id, values, exp_trvsl=None): session = context.session with session.begin(subtransactions=True): @@ -865,7 +866,9 @@ @oslo_db_api.wrap_db_retry(max_retries=3, retry_on_deadlock=True, - retry_interval=0.5, inc_retry_interval=True, + retry_on_disconnect=True, + retry_interval=0.5, + inc_retry_interval=True, exception_checker=_is_duplicate_error) def stack_lock_create(context, stack_id, engine_id): with db_context.writer.independent.using(context) as session: @@ -951,7 +954,7 @@ else: user_creds_ref.update(values) method, password = crypt.encrypt(values['password']) - if len(six.text_type(password)) > 255: + if len(str(password)) > 255: raise exception.Error(_("Length of OS_PASSWORD after encryption" " exceeds Heat limit (255 chars)")) user_creds_ref.password = password @@ -1163,7 +1166,7 @@ return retval -@retry_on_deadlock +@retry_on_db_error def event_create(context, values): if 'stack_id' in values and cfg.CONF.max_events_per_stack: # only count events and purge on average @@ -1177,7 +1180,7 @@ _delete_event_rows(context, values['stack_id'], cfg.CONF.event_purge_batch_size) except db_exception.DBError as exc: - LOG.error('Failed to purge events: %s', six.text_type(exc)) + LOG.error('Failed to purge events: %s', str(exc)) event_ref = models.Event() event_ref.update(values) event_ref.save(context.session) @@ -1575,7 +1578,7 @@ return rows_deleted -@retry_on_deadlock +@retry_on_db_error def sync_point_create(context, values): values['entity_id'] = str(values['entity_id']) sync_point_ref = models.SyncPoint() @@ -1591,7 +1594,7 @@ ) -@retry_on_deadlock +@retry_on_db_error def sync_point_update_input_data(context, entity_id, traversal_id, is_update, atomic_key, input_data): @@ -1666,7 +1669,7 @@ not param_schemata[param_name].hidden): continue encrypted_val = crypt.encrypt( - six.text_type(param_val), encryption_key) + str(param_val), encryption_key) env['parameters'][param_name] = encrypted_val encrypted_params.append(param_name) needs_update = True diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/db/sqlalchemy/filters.py heat-14.0.0/heat/db/sqlalchemy/filters.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/db/sqlalchemy/filters.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/db/sqlalchemy/filters.py 2020-05-13 10:48:27.000000000 +0000 @@ -11,8 +11,6 @@ # License for the specific language governing permissions and limitations # under the License. -import six - def exact_filter(query, model, filters): """Applies exact match filtering to a query. @@ -33,7 +31,7 @@ if filters is None: filters = {} - for key, value in six.iteritems(filters): + for key, value in filters.items(): if isinstance(value, (list, tuple, set, frozenset)): column_attr = getattr(model, key) query = query.filter(column_attr.in_(value)) diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/api.py heat-14.0.0/heat/engine/api.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/api.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/api.py 2020-05-13 10:48:27.000000000 +0000 @@ -15,7 +15,6 @@ from oslo_log import log as logging from oslo_utils import timeutils -import six from heat.common.i18n import _ from heat.common import param_utils @@ -65,7 +64,7 @@ raise ValueError(_('Invalid tags, not a list: %s') % tags) for tag in tags: - if not isinstance(tag, six.string_types): + if not isinstance(tag, str): raise ValueError(_('Invalid tag, "%s" is not a string') % tag) if len(tag) > 80: @@ -188,7 +187,7 @@ except Exception as ex: # We don't need error raising, just adding output_error to # resulting dict. - result.update({rpc_api.OUTPUT_ERROR: six.text_type(ex)}) + result.update({rpc_api.OUTPUT_ERROR: str(ex)}) finally: result.update({rpc_api.OUTPUT_VALUE: value}) @@ -212,7 +211,7 @@ rpc_api.STACK_UPDATED_TIME: updated_time, rpc_api.STACK_DELETION_TIME: deleted_time, rpc_api.STACK_NOTIFICATION_TOPICS: [], # TODO(therve) Not implemented - rpc_api.STACK_PARAMETERS: stack.parameters.map(six.text_type), + rpc_api.STACK_PARAMETERS: stack.parameters.map(str), rpc_api.STACK_DESCRIPTION: stack.t[stack.t.DESCRIPTION], rpc_api.STACK_TMPL_DESCRIPTION: stack.t[stack.t.DESCRIPTION], rpc_api.STACK_CAPABILITIES: [], # TODO(?) Not implemented yet diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/attributes.py heat-14.0.0/heat/engine/attributes.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/attributes.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/attributes.py 2020-05-13 10:48:27.000000000 +0000 @@ -12,12 +12,11 @@ # under the License. import collections +import functools from oslo_utils import strutils -import six from heat.common.i18n import _ -from heat.common.i18n import repr_wrapper from heat.engine import constraints as constr from heat.engine import support @@ -139,7 +138,6 @@ ALL_ATTRIBUTES = '*' -@repr_wrapper class Attributes(collections.Mapping): """Models a collection of Resource Attributes.""" @@ -208,14 +206,14 @@ def _validate_type(self, attrib, value): if attrib.schema.type == attrib.schema.STRING: - if not isinstance(value, six.string_types): + if not isinstance(value, str): LOG.warning("Attribute %(name)s is not of type " "%(att_type)s", {'name': attrib.name, 'att_type': attrib.schema.STRING}) elif attrib.schema.type == attrib.schema.LIST: if (not isinstance(value, collections.Sequence) - or isinstance(value, six.string_types)): + or isinstance(value, str)): LOG.warning("Attribute %(name)s is not of type " "%(att_type)s", {'name': attrib.name, @@ -298,7 +296,7 @@ def __repr__(self): return ("Attributes for %s:\n\t" % self._resource_name + - '\n\t'.join(six.itervalues(self))) + '\n\t'.join(self.values())) def select_from_attribute(attribute_value, path): @@ -313,12 +311,12 @@ collections.Sequence)): raise TypeError(_("Can't traverse attribute path")) - if not isinstance(key, (six.string_types, int)): + if not isinstance(key, (str, int)): raise TypeError(_('Path components in attributes must be strings')) return collection[key] try: - return six.moves.reduce(get_path_component, path, attribute_value) + return functools.reduce(get_path_component, path, attribute_value) except (KeyError, IndexError, TypeError): return None diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/cfn/functions.py heat-14.0.0/heat/engine/cfn/functions.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/cfn/functions.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/cfn/functions.py 2020-05-13 10:48:27.000000000 +0000 @@ -14,7 +14,6 @@ import collections from oslo_serialization import jsonutils -import six from heat.api.aws import utils as aws_utils from heat.common import exception @@ -39,7 +38,7 @@ try: self._mapname, self._mapkey, self._mapvalue = self.args except ValueError as ex: - raise KeyError(six.text_type(ex)) + raise KeyError(str(ex)) def result(self): mapping = self.stack.t.maps[function.resolve(self._mapname)] @@ -160,7 +159,7 @@ # Handle by returning an empty string return '' - if isinstance(strings, six.string_types): + if isinstance(strings, str): # might be serialized json. try: strings = jsonutils.loads(strings) @@ -170,7 +169,7 @@ raise ValueError(_('"%(fn_name)s": %(err)s') % fmt_data) if isinstance(strings, collections.Mapping): - if not isinstance(index, six.string_types): + if not isinstance(index, str): raise TypeError(_('Index to "%s" must be a string') % self.fn_name) return strings.get(index, '') @@ -181,8 +180,8 @@ pass if (isinstance(strings, collections.Sequence) and - not isinstance(strings, six.string_types)): - if not isinstance(index, six.integer_types): + not isinstance(strings, str)): + if not isinstance(index, int): raise TypeError(_('Index to "%s" must be an integer') % self.fn_name) @@ -230,7 +229,7 @@ fmt_data = {'fn_name': self.fn_name, 'example': example} - if isinstance(self.args, (six.string_types, collections.Mapping)): + if isinstance(self.args, (str, collections.Mapping)): raise TypeError(_('Incorrect arguments to "%(fn_name)s" ' 'should be: %(example)s') % fmt_data) @@ -243,10 +242,10 @@ def result(self): strings = function.resolve(self._strings) - if not isinstance(self._delim, six.string_types): + if not isinstance(self._delim, str): raise TypeError(_("Delimiter for %s must be string") % self.fn_name) - if not isinstance(strings, six.string_types): + if not isinstance(strings, str): raise TypeError(_("String to split must be string; got %s") % type(strings)) @@ -279,7 +278,7 @@ fmt_data = {'fn_name': self.fn_name, 'example': example} - if isinstance(self.args, (six.string_types, collections.Mapping)): + if isinstance(self.args, (str, collections.Mapping)): raise TypeError(_('Incorrect arguments to "%(fn_name)s" ' 'should be: %(example)s') % fmt_data) @@ -306,7 +305,7 @@ def result(self): resolved = function.resolve(self.args) - if not isinstance(resolved, six.string_types): + if not isinstance(resolved, str): raise TypeError(_('"%s" argument must be a string') % self.fn_name) return resolved @@ -342,10 +341,10 @@ ''' raise TypeError(_('Wrong Arguments try: "%s"') % correct) - if not isinstance(self._keyname, six.string_types): + if not isinstance(self._keyname, str): raise TypeError(_('%s Key Name must be a string') % self.fn_name) - if not isinstance(self._valuename, six.string_types): + if not isinstance(self._valuename, str): raise TypeError(_('%s Value Name must be a string') % self.fn_name) def result(self): @@ -355,7 +354,7 @@ raise TypeError(_('Member list must be a list')) def item(s): - if not isinstance(s, six.string_types): + if not isinstance(s, str): raise TypeError(_("Member list items must be strings")) return s.split('=', 1) @@ -430,7 +429,7 @@ '[condition]') % self.fn_name if (not self.args or not isinstance(self.args, collections.Sequence) or - isinstance(self.args, six.string_types)): + isinstance(self.args, str)): raise ValueError(msg) if len(self.args) != 1: raise ValueError(msg) diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/cfn/template.py heat-14.0.0/heat/engine/cfn/template.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/cfn/template.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/cfn/template.py 2020-05-13 10:48:27.000000000 +0000 @@ -13,8 +13,6 @@ import functools -import six - from heat.common import exception from heat.common.i18n import _ from heat.engine.cfn import functions as cfn_funcs @@ -98,12 +96,12 @@ def param_schemata(self, param_defaults=None): params = self.t.get(self.PARAMETERS) or {} pdefaults = param_defaults or {} - for name, schema in six.iteritems(params): + for name, schema in params.items(): if name in pdefaults: params[name][parameters.DEFAULT] = pdefaults[name] return dict((name, parameters.Schema.from_dict(name, schema)) - for name, schema in six.iteritems(params)) + for name, schema in params.items()) def get_section_name(self, section): return section @@ -124,7 +122,7 @@ defn_data = dict(self._rsrc_defn_args(stack, name, snippet)) except (TypeError, ValueError, KeyError) as ex: - msg = six.text_type(ex) + msg = str(ex) raise exception.StackValidationFailed(message=msg) defn = rsrc_defn.ResourceDefinition(name, **defn_data) @@ -135,7 +133,7 @@ enabled = conditions.is_enabled(cond_name) except ValueError as exc: path = [self.RESOURCES, name, self.RES_CONDITION] - message = six.text_type(exc) + message = str(exc) raise exception.StackValidationFailed(path=path, message=message) if not enabled: @@ -234,7 +232,7 @@ yield ('condition', self._parse_resource_field(self.RES_CONDITION, - (six.string_types, bool, + (str, bool, function.Function), 'string or boolean', name, data, parse_cond)) diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/check_resource.py heat-14.0.0/heat/engine/check_resource.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/check_resource.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/check_resource.py 2020-05-13 10:48:27.000000000 +0000 @@ -13,8 +13,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import six - import eventlet.queue import functools @@ -83,7 +81,7 @@ 'during resource %s' % rsrc.action) rsrc.state_set(rsrc.action, rsrc.FAILED, - six.text_type(status_reason)) + str(status_reason)) return True elif (rs_obj.engine_id is None and rs_obj.current_template_id == prev_template_id): @@ -105,11 +103,11 @@ def _retrigger_new_traversal(self, cnxt, current_traversal, is_update, stack_id, rsrc_id): - latest_stack = parser.Stack.load(cnxt, stack_id=stack_id, - force_reload=True) - if current_traversal != latest_stack.current_traversal: - self.retrigger_check_resource(cnxt, is_update, rsrc_id, - latest_stack) + latest_stack = parser.Stack.load(cnxt, stack_id=stack_id, + force_reload=True) + if current_traversal != latest_stack.current_traversal: + self.retrigger_check_resource(cnxt, is_update, rsrc_id, + latest_stack) def _handle_stack_timeout(self, cnxt, stack): failure_reason = u'Timed out' @@ -177,13 +175,13 @@ except exception.ResourceFailure as ex: action = ex.action or rsrc.action reason = 'Resource %s failed: %s' % (action, - six.text_type(ex)) + str(ex)) self._handle_resource_failure(cnxt, is_update, rsrc.id, stack, reason) except scheduler.Timeout: self._handle_resource_failure(cnxt, is_update, rsrc.id, stack, u'Timed out') - except CancelOperation as ex: + except CancelOperation: # Stack is already marked FAILED, so we just need to retrigger # in case a new traversal has started and is waiting on us. self._retrigger_new_traversal(cnxt, current_traversal, is_update, @@ -323,7 +321,7 @@ rsrc, stack) except BaseException as exc: with excutils.save_and_reraise_exception(): - msg = six.text_type(exc) + msg = str(exc) LOG.exception("Unexpected exception in resource check.") self._handle_resource_failure(cnxt, is_update, rsrc.id, stack, msg) diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/clients/client_plugin.py heat-14.0.0/heat/engine/clients/client_plugin.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/clients/client_plugin.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/clients/client_plugin.py 2020-05-13 10:48:27.000000000 +0000 @@ -21,7 +21,6 @@ from oslo_utils import excutils import requests -import six from heat.common import config from heat.common import exception as heat_exception @@ -29,8 +28,7 @@ cfg.CONF.import_opt('client_retry_limit', 'heat.common.config') -@six.add_metaclass(abc.ABCMeta) -class ClientPlugin(object): +class ClientPlugin(object, metaclass=abc.ABCMeta): # Module which contains all exceptions classes which the client # may emit @@ -139,11 +137,10 @@ if self.exceptions_module: if isinstance(self.exceptions_module, list): for m in self.exceptions_module: - if type(ex) in six.itervalues(m.__dict__): + if type(ex) in m.__dict__.values(): return True else: - return type(ex) in six.itervalues( - self.exceptions_module.__dict__) + return type(ex) in self.exceptions_module.__dict__.values() return False def is_not_found(self, ex): diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/clients/__init__.py heat-14.0.0/heat/engine/clients/__init__.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/clients/__init__.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/clients/__init__.py 2020-05-13 10:48:27.000000000 +0000 @@ -16,7 +16,6 @@ from oslo_config import cfg from oslo_log import log as logging from oslo_utils import importutils -import six from stevedore import enabled from heat.common import exception @@ -95,7 +94,7 @@ context) except (ImportError, RuntimeError, cfg.NoSuchOptError) as err: msg = _('Invalid cloud_backend setting in heat.conf ' - 'detected - %s') % six.text_type(err) + 'detected - %s') % str(err) LOG.error(msg) raise exception.Invalid(reason=msg) diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/clients/microversion_mixin.py heat-14.0.0/heat/engine/clients/microversion_mixin.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/clients/microversion_mixin.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/clients/microversion_mixin.py 2020-05-13 10:48:27.000000000 +0000 @@ -13,13 +13,10 @@ import abc -import six - from heat.common import exception -@six.add_metaclass(abc.ABCMeta) -class MicroversionMixin(object): +class MicroversionMixin(object, metaclass=abc.ABCMeta): """Mixin For microversion support.""" def client(self, version=None): diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/clients/os/ironic.py heat-14.0.0/heat/engine/clients/os/ironic.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/clients/os/ironic.py 1970-01-01 00:00:00.000000000 +0000 +++ heat-14.0.0/heat/engine/clients/os/ironic.py 2020-05-13 10:48:27.000000000 +0000 @@ -0,0 +1,82 @@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from ironicclient.common.apiclient import exceptions as ic_exc +from ironicclient.v1 import client as ironic_client +from oslo_config import cfg + +from heat.common import exception +from heat.engine.clients import client_plugin +from heat.engine import constraints + +CLIENT_NAME = 'ironic' + + +class IronicClientPlugin(client_plugin.ClientPlugin): + + service_types = [BAREMETAL] = ['baremetal'] + IRONIC_API_VERSION = 1.58 + max_ironic_api_microversion = cfg.CONF.max_ironic_api_microversion + max_microversion = max_ironic_api_microversion if ( + max_ironic_api_microversion is not None and ( + IRONIC_API_VERSION > max_ironic_api_microversion) + ) else IRONIC_API_VERSION + + def _create(self): + interface = self._get_client_option(CLIENT_NAME, 'endpoint_type') + args = { + 'interface': interface, + 'service_type': self.BAREMETAL, + 'session': self.context.keystone_session, + 'region_name': self._get_region_name(), + 'os_ironic_api_version': self.max_microversion + } + client = ironic_client.Client(**args) + return client + + def is_not_found(self, ex): + return isinstance(ex, ic_exc.NotFound) + + def is_over_limit(self, ex): + return isinstance(ex, ic_exc.RequestEntityTooLarge) + + def is_conflict(self, ex): + return isinstance(ex, ic_exc.Conflict) + + def _get_rsrc_name_or_id(self, value, entity, entity_msg): + entity_client = getattr(self.client(), entity) + try: + return entity_client.get(value).uuid + except ic_exc.NotFound: + # Ironic cli will find the value either is name or id, + # so no need to call list() here. + raise exception.EntityNotFound(entity=entity_msg, + name=value) + + def get_portgroup(self, value): + return self._get_rsrc_name_or_id(value, entity='portgroup', + entity_msg='PortGroup') + + def get_node(self, value): + return self._get_rsrc_name_or_id(value, entity='node', + entity_msg='Node') + + +class PortGroupConstraint(constraints.BaseCustomConstraint): + resource_client_name = CLIENT_NAME + resource_getter_name = 'get_portgroup' + + +class NodeConstraint(constraints.BaseCustomConstraint): + resource_client_name = CLIENT_NAME + resource_getter_name = 'get_node' diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/clients/os/neutron/__init__.py heat-14.0.0/heat/engine/clients/os/neutron/__init__.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/clients/os/neutron/__init__.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/clients/os/neutron/__init__.py 2020-05-13 10:48:27.000000000 +0000 @@ -167,7 +167,11 @@ seclist.append(sg) else: if not all_groups: - response = self.client().list_security_groups() + # filtering by project_id so that if the user + # has access to multiple (like admin) + # only groups from the token scope are returned + response = self.client().list_security_groups( + project_id=self.context.project_id) all_groups = response['security_groups'] same_name_groups = [g for g in all_groups if g['name'] == sg] groups = [g['id'] for g in same_name_groups] @@ -176,15 +180,7 @@ elif len(groups) == 1: seclist.append(groups[0]) else: - # for admin roles, can get the other users' - # securityGroups, so we should match the tenant_id with - # the groups, and return the own one - own_groups = [g['id'] for g in same_name_groups - if g['tenant_id'] == self.context.tenant_id] - if len(own_groups) == 1: - seclist.append(own_groups[0]) - else: - raise exception.PhysicalResourceNameAmbiguity(name=sg) + raise exception.PhysicalResourceNameAmbiguity(name=sg) return seclist def _resolve_resource_path(self, resource): diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/clients/os/nova.py heat-14.0.0/heat/engine/clients/os/nova.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/clients/os/nova.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/clients/os/nova.py 2020-05-13 10:48:27.000000000 +0000 @@ -18,6 +18,7 @@ import os import pkgutil import string +from urllib import parse as urlparse from neutronclient.common import exceptions as q_exceptions from novaclient import api_versions @@ -27,8 +28,6 @@ from oslo_log import log as logging from oslo_serialization import jsonutils from oslo_utils import netutils -import six -from six.moves.urllib import parse as urlparse import tenacity from heat.common import exception @@ -225,7 +224,7 @@ """ # not checking with is_uuid_like as most tests use strings e.g. '1234' - if isinstance(server, six.string_types): + if isinstance(server, str): server = self.fetch_server(server) if server is None: return False @@ -607,7 +606,7 @@ "nova server metadata needs to be a Map.")) return dict((key, (value if isinstance(value, - six.string_types) + str) else jsonutils.dumps(value)) ) for (key, value) in metadata.items()) @@ -675,7 +674,7 @@ except exceptions.UnsupportedConsoleType as ex: url = ex.message except Exception as e: - url = _('Cannot get console url: %s') % six.text_type(e) + url = _('Cannot get console url: %s') % str(e) return url diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/clients/os/sahara.py heat-14.0.0/heat/engine/clients/os/sahara.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/clients/os/sahara.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/clients/os/sahara.py 2020-05-13 10:48:27.000000000 +0000 @@ -16,7 +16,6 @@ from oslo_config import cfg from saharaclient.api import base as sahara_base from saharaclient import client as sahara_client -import six from heat.common import exception from heat.common.i18n import _ @@ -117,7 +116,7 @@ raise exception.Error( _("Error retrieving %(entity)s list from sahara: " "%(err)s") % dict(entity=resource_name, - err=six.text_type(ex))) + err=str(ex))) num_matches = len(obj_list) if num_matches == 0: raise exception.EntityNotFound(entity=resource_name or 'entity', diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/clients/os/swift.py heat-14.0.0/heat/engine/clients/os/swift.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/clients/os/swift.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/clients/os/swift.py 2020-05-13 10:48:27.000000000 +0000 @@ -17,10 +17,9 @@ import logging import random import time +from urllib import parse from oslo_config import cfg -import six -from six.moves.urllib import parse from swiftclient import client as sc from swiftclient import exceptions from swiftclient import utils as swiftclient_utils @@ -98,8 +97,8 @@ if key_header not in self.client().head_account(): self.client().post_account({ key_header: hashlib.sha224( - six.b(six.text_type( - random.getrandbits(256)))).hexdigest()[:32]}) + str(random.getrandbits(256)).encode( + "latin-1")).hexdigest()[:32]}) key = self.client().head_account()[key_header] @@ -173,5 +172,5 @@ 'container %(container)s, ' 'reason: %(reason)s.') % {'container': files_container, - 'reason': six.text_type(cex)}) + 'reason': str(cex)}) return files diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/clients/os/zaqar.py heat-14.0.0/heat/engine/clients/os/zaqar.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/clients/os/zaqar.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/clients/os/zaqar.py 2020-05-13 10:48:27.000000000 +0000 @@ -11,8 +11,6 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from oslo_log import log as logging from zaqarclient.queues.v2 import client as zaqarclient from zaqarclient.transport import errors as zaqar_errors @@ -75,7 +73,7 @@ return isinstance(ex, zaqar_errors.ResourceNotFound) def get_queue(self, queue_name): - if not isinstance(queue_name, six.string_types): + if not isinstance(queue_name, str): raise TypeError(_('Queue name must be a string')) if not (0 < len(queue_name) <= 64): raise ValueError(_('Queue name length must be 1-64')) diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/conditions.py heat-14.0.0/heat/engine/conditions.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/conditions.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/conditions.py 2020-05-13 10:48:27.000000000 +0000 @@ -13,8 +13,6 @@ import collections -import six - from heat.common.i18n import _ from heat.common import exception @@ -31,7 +29,7 @@ self._resolved = {} def validate(self): - for name, cond in six.iteritems(self._conditions): + for name, cond in self._conditions.items(): self._check_condition_type(name, cond) function.validate(cond) @@ -56,7 +54,7 @@ if isinstance(condition_name, bool): return condition_name - if not (isinstance(condition_name, six.string_types) and + if not (isinstance(condition_name, str) and condition_name in self._conditions): raise ValueError(_('Invalid condition "%s"') % condition_name) diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/constraint/common_constraints.py heat-14.0.0/heat/engine/constraint/common_constraints.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/constraint/common_constraints.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/constraint/common_constraints.py 2020-05-13 10:48:27.000000000 +0000 @@ -15,7 +15,6 @@ import eventlet import netaddr import pytz -import six from neutron_lib.api import validators from oslo_utils import timeutils @@ -35,7 +34,7 @@ def validate(self, value, context, template=None): self._error_message = 'Invalid IP address' - if not isinstance(value, six.string_types): + if not isinstance(value, str): return False msg = validators.validate_ip_address(value) if msg is not None: @@ -59,7 +58,7 @@ self._error_message = ("'%(value)s' not in valid format." " Reason: %(reason)s") % { 'value': value, - 'reason': six.text_type(ex)} + 'reason': str(ex)} return False return True @@ -114,7 +113,7 @@ return False return True except Exception as ex: - self._error_message = 'Invalid net cidr %s ' % six.text_type(ex) + self._error_message = 'Invalid net cidr %s ' % str(ex) return False @@ -158,7 +157,7 @@ return True except Exception as ex: self._error_message = _( - 'Invalid CRON expression: %s') % six.text_type(ex) + 'Invalid CRON expression: %s') % str(ex) return False @@ -172,7 +171,7 @@ return True except Exception as ex: self._error_message = _( - 'Invalid timezone: %s') % six.text_type(ex) + 'Invalid timezone: %s') % str(ex) return False @@ -190,5 +189,5 @@ except Exception as ex: self._error_message = (_( 'Expiration {0} is invalid: {1}').format(value, - six.text_type(ex))) + str(ex))) return False diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/constraints.py heat-14.0.0/heat/engine/constraints.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/constraints.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/constraints.py 2020-05-13 10:48:27.000000000 +0000 @@ -21,7 +21,6 @@ from oslo_log import log from oslo_utils import reflection from oslo_utils import strutils -import six from heat.common import cache from heat.common import exception @@ -149,7 +148,7 @@ if isinstance(self.schema, AnyIndexDict): self.schema.value.validate(context) else: - for nested_schema in six.itervalues(self.schema): + for nested_schema in self.schema.values(): nested_schema.validate(context) def _validate_default(self, context): @@ -195,9 +194,9 @@ elif self.type == self.NUMBER: return Schema.str_to_num(value) elif self.type == self.STRING: - return six.text_type(value) + return str(value) elif self.type == self.BOOLEAN: - return strutils.bool_from_string(six.text_type(value), + return strutils.bool_from_string(str(value), strict=True) except ValueError: raise ValueError(_('Value "%(val)s" is invalid for data type ' @@ -215,7 +214,7 @@ if type(constraint) not in skipped: constraint.validate(value, self, context) except ValueError as ex: - raise exception.StackValidationFailed(message=six.text_type(ex)) + raise exception.StackValidationFailed(message=str(ex)) def __getitem__(self, key): if key == self.TYPE: @@ -265,7 +264,7 @@ self.value = value def __getitem__(self, key): - if key != self.ANYTHING and not isinstance(key, six.integer_types): + if key != self.ANYTHING and not isinstance(key, int): raise KeyError(_('Invalid key %s') % key) return self.value @@ -277,7 +276,6 @@ return 1 -@six.python_2_unicode_compatible class Constraint(collections.Mapping): """Parent class for constraints on allowable values for a Property. @@ -353,7 +351,7 @@ self.max = max for param in (min, max): - if not isinstance(param, (float, six.integer_types, type(None))): + if not isinstance(param, (float, int, type(None))): raise exception.InvalidSchemaError( message=_('min/max must be numeric')) @@ -422,7 +420,7 @@ super(Length, self).__init__(min, max, description) for param in (min, max): - if not isinstance(param, (six.integer_types, type(None))): + if not isinstance(param, (int, type(None))): msg = _('min/max length must be integral') raise exception.InvalidSchemaError(message=msg) @@ -471,7 +469,7 @@ 'an offset value specified.')) for param in (step, offset): - if not isinstance(param, (float, six.integer_types, type(None))): + if not isinstance(param, (float, int, type(None))): raise exception.InvalidSchemaError( message=_('step/offset must be numeric')) @@ -543,7 +541,7 @@ def __init__(self, allowed, description=None): super(AllowedValues, self).__init__(description) if (not isinstance(allowed, collections.Sequence) or - isinstance(allowed, six.string_types)): + isinstance(allowed, str)): raise exception.InvalidSchemaError( message=_('AllowedValues must be a list')) self.allowed = tuple(allowed) @@ -589,7 +587,7 @@ def __init__(self, pattern, description=None): super(AllowedPattern, self).__init__(description) - if not isinstance(pattern, six.string_types): + if not isinstance(pattern, str): raise exception.InvalidSchemaError( message=_('AllowedPattern must be a string')) self.pattern = pattern @@ -701,13 +699,13 @@ try: self.validate_with_client(context.clients, value_to_validate) except self.expected_exceptions as e: - self._error_message = six.text_type(e) + self._error_message = str(e) return False else: return True class_name = reflection.get_class_name(self, fully_qualified=False) cache_value_prefix = "{0}:{1}".format(class_name, - six.text_type(context.tenant_id)) + str(context.tenant_id)) validation_result = check_cache_or_validate_value( cache_value_prefix, value) # if validation failed we should not store it in cache diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/dependencies.py heat-14.0.0/heat/engine/dependencies.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/dependencies.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/dependencies.py 2020-05-13 10:48:27.000000000 +0000 @@ -14,19 +14,14 @@ import collections import itertools -import six - from heat.common import exception from heat.common.i18n import _ -from heat.common.i18n import repr_wrapper class CircularDependencyException(exception.HeatException): msg_fmt = _("Circular Dependency Found: %(cycle)s") -@repr_wrapper -@six.python_2_unicode_compatible class Node(object): """A node in a dependency graph.""" @@ -94,15 +89,14 @@ def __str__(self): """Return a human-readable string representation of the node.""" - text = '{%s}' % ', '.join(six.text_type(n) for n in self) - return six.text_type(text) + text = '{%s}' % ', '.join(str(n) for n in self) + return str(text) def __repr__(self): """Return a string representation of the node.""" return repr(self.require) -@six.python_2_unicode_compatible class Graph(collections.defaultdict): """A mutable mapping of objects to nodes in a dependency graph.""" @@ -134,7 +128,7 @@ for rqd in node: yield (rqr, rqd) return itertools.chain.from_iterable(outgoing_edges(*i) - for i in six.iteritems(self)) + for i in self.items()) def __delitem__(self, key): """Delete the node given by the specified key from the graph.""" @@ -149,10 +143,10 @@ def __str__(self): """Convert the graph to a human-readable string.""" - pairs = ('%s: %s' % (six.text_type(k), six.text_type(v)) - for k, v in six.iteritems(self)) + pairs = ('%s: %s' % (str(k), str(v)) + for k, v in self.items()) text = '{%s}' % ', '.join(pairs) - return six.text_type(text) + return str(text) @staticmethod def toposort(graph): @@ -160,8 +154,8 @@ This is a destructive operation for the graph. """ - for iteration in six.moves.xrange(len(graph)): - for key, node in six.iteritems(graph): + for iteration in range(len(graph)): + for key, node in graph.items(): if not node: yield key del graph[key] @@ -169,11 +163,9 @@ else: # There are nodes remaining, but none without # dependencies: a cycle - raise CircularDependencyException(cycle=six.text_type(graph)) + raise CircularDependencyException(cycle=str(graph)) -@repr_wrapper -@six.python_2_unicode_compatible class Dependencies(object): """Helper class for calculating a dependency graph.""" @@ -230,8 +222,8 @@ return itertools.chain([(rqr, key)], get_edges(rqr)) # Get the edge list for each node that requires the current node - edge_lists = six.moves.map(requirer_edges, - self._graph[key].required_by()) + edge_lists = map(requirer_edges, + self._graph[key].required_by()) # Combine the lists into one long list return itertools.chain.from_iterable(edge_lists) @@ -266,7 +258,7 @@ def __str__(self): """Return a human-readable string repr of the dependency graph.""" - return six.text_type(self._graph) + return str(self._graph) def __repr__(self): """Return a consistent string representation of the object.""" diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/environment.py heat-14.0.0/heat/engine/environment.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/environment.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/environment.py 2020-05-13 10:48:27.000000000 +0000 @@ -21,7 +21,6 @@ from oslo_config import cfg from oslo_log import log from oslo_utils import fnmatch -import six from heat.common import environment_format as env_fmt from heat.common import exception @@ -54,7 +53,7 @@ def is_hook_definition(key, value): is_valid_hook = False if key == 'hooks': - if isinstance(value, six.string_types): + if isinstance(value, str): is_valid_hook = valid_hook_type(value) elif isinstance(value, collections.Sequence): is_valid_hook = all(valid_hook_type(hook) for hook in value) @@ -71,7 +70,7 @@ def is_valid_restricted_action(key, value): valid_action = False if key == 'restricted_actions': - if isinstance(value, six.string_types): + if isinstance(value, str): valid_action = valid_restricted_actions(value) elif isinstance(value, collections.Sequence): valid_action = all(valid_restricted_actions( @@ -101,7 +100,7 @@ if name.endswith(('.yaml', '.template')): # a template url for the resource "Type" klass = TemplateResourceInfo - elif not isinstance(value, six.string_types): + elif not isinstance(value, str): klass = ClassResourceInfo elif value.endswith(('.yaml', '.template')): # a registered template @@ -344,10 +343,8 @@ if info.value.support_status.message is not None: details = { 'name': info.name, - 'status': six.text_type( - info.value.support_status.status), - 'message': six.text_type( - info.value.support_status.message) + 'status': str(info.value.support_status.status), + 'message': str(info.value.support_status.message) } LOG.warning('%(name)s is %(status)s. %(message)s', details) @@ -364,7 +361,7 @@ if show_all or isinstance(registry[name], TemplateResourceInfo): msg = ('%(p)sRegistered: %(t)s' % {'p': prefix, - 't': six.text_type(registry[name])}) + 't': str(registry[name])}) LOG.info(msg) def remove_item(self, info): @@ -394,11 +391,11 @@ """ ress = self._registry['resources'] restricted_actions = set() - for name_pattern, resource in six.iteritems(ress): + for name_pattern, resource in ress.items(): if fnmatch.fnmatchcase(resource_name, name_pattern): if 'restricted_actions' in resource: actions = resource['restricted_actions'] - if isinstance(actions, six.string_types): + if isinstance(actions, str): restricted_actions.add(actions) elif isinstance(actions, collections.Sequence): restricted_actions |= set(actions) @@ -429,11 +426,11 @@ everything. """ ress = self._registry['resources'] - for name_pattern, resource in six.iteritems(ress): + for name_pattern, resource in ress.items(): if fnmatch.fnmatchcase(resource_name, name_pattern): if 'hooks' in resource: hooks = resource['hooks'] - if isinstance(hooks, six.string_types): + if isinstance(hooks, str): if hook == hooks: return True elif isinstance(hooks, collections.Sequence): @@ -444,7 +441,7 @@ def remove_resources_except(self, resource_name): ress = self._registry['resources'] new_resources = {} - for name, res in six.iteritems(ress): + for name, res in ress.items(): if fnmatch.fnmatchcase(resource_name, name): new_resources.update(res) if resource_name in ress: @@ -477,7 +474,7 @@ # handle: "OS::*" -> "Dreamhost::*" def is_a_glob(resource_type): return resource_type.endswith('*') - globs = six.moves.filter(is_a_glob, iter(self._registry)) + globs = filter(is_a_glob, iter(self._registry)) for pattern in globs: if self._registry[pattern].matches(resource_type): yield self._registry[pattern] @@ -550,7 +547,7 @@ msg = _('Non-empty resource type is required ' 'for resource "%s"') % resource_name raise exception.StackValidationFailed(message=msg) - elif not isinstance(resource_type, six.string_types): + elif not isinstance(resource_type, str): msg = _('Resource "%s" type is not a string') % resource_name raise exception.StackValidationFailed(message=msg) @@ -558,7 +555,7 @@ info = self.get_resource_info(resource_type, resource_name=resource_name) except exception.EntityNotFound as exc: - raise exception.StackValidationFailed(message=six.text_type(exc)) + raise exception.StackValidationFailed(message=str(exc)) return info.get_class_to_instantiate() @@ -590,7 +587,7 @@ if support_status is not None and not support.is_valid_status( support_status): msg = (_('Invalid support status and should be one of %s') % - six.text_type(support.SUPPORT_STATUSES)) + str(support.SUPPORT_STATUSES)) raise exception.Invalid(reason=msg) def is_resource(key): @@ -650,7 +647,7 @@ } return [resource_description(name, cls, with_description) - for name, cls in six.iteritems(self._registry) + for name, cls in self._registry.items() if (is_resource(name) and name_matches(name) and status_matches(cls) and @@ -693,7 +690,7 @@ if env_fmt.PARAMETERS in env: self.params = env[env_fmt.PARAMETERS] else: - self.params = dict((k, v) for (k, v) in six.iteritems(env) + self.params = dict((k, v) for (k, v) in env.items() if k not in (env_fmt.PARAMETER_DEFAULTS, env_fmt.ENCRYPTED_PARAM_NAMES, env_fmt.EVENT_SINKS, diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/function.py heat-14.0.0/heat/engine/function.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/function.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/function.py 2020-05-13 10:48:27.000000000 +0000 @@ -16,14 +16,11 @@ import itertools import weakref -import six - from heat.common import exception from heat.common.i18n import _ -@six.add_metaclass(abc.ABCMeta) -class Function(object): +class Function(metaclass=abc.ABCMeta): """Abstract base class for template functions.""" def __init__(self, stack, fn_name, args): @@ -98,13 +95,13 @@ return all_dep_attrs(self.args) def res_dep_attrs(resource_name): - return six.moves.zip(itertools.repeat(resource_name), - self.dep_attrs(resource_name)) + return zip(itertools.repeat(resource_name), + self.dep_attrs(resource_name)) resource_names = self.stack.enabled_rsrc_names() - return itertools.chain.from_iterable(six.moves.map(res_dep_attrs, - resource_names)) + return itertools.chain.from_iterable(map(res_dep_attrs, + resource_names)) def __reduce__(self): """Return a representation of the function suitable for pickling. @@ -160,8 +157,7 @@ __hash__ = None -@six.add_metaclass(abc.ABCMeta) -class Macro(Function): +class Macro(Function, metaclass=abc.ABCMeta): """Abstract base class for template macros. A macro differs from a function in that it controls how the template is @@ -260,7 +256,7 @@ if isinstance(snippet, collections.Mapping): return dict((k, resolve(v)) for k, v in snippet.items()) - elif (not isinstance(snippet, six.string_types) and + elif (not isinstance(snippet, str) and isinstance(snippet, collections.Iterable)): return [resolve(v) for v in snippet] @@ -270,7 +266,7 @@ def validate(snippet, path=None): if path is None: path = [] - elif isinstance(path, six.string_types): + elif isinstance(path, str): path = [path] if isinstance(snippet, Function): @@ -281,11 +277,11 @@ except Exception as e: raise exception.StackValidationFailed( path=path + [snippet.fn_name], - message=six.text_type(e)) + message=str(e)) elif isinstance(snippet, collections.Mapping): - for k, v in six.iteritems(snippet): + for k, v in snippet.items(): validate(v, path + [k]) - elif (not isinstance(snippet, six.string_types) and + elif (not isinstance(snippet, str) and isinstance(snippet, collections.Iterable)): basepath = list(path) parent = basepath.pop() if basepath else '' @@ -305,13 +301,13 @@ elif isinstance(snippet, collections.Mapping): def mkpath(key): - return '.'.join([path, six.text_type(key)]) + return '.'.join([path, str(key)]) deps = (dependencies(value, mkpath(key)) for key, value in snippet.items()) return itertools.chain.from_iterable(deps) - elif (not isinstance(snippet, six.string_types) and + elif (not isinstance(snippet, str) and isinstance(snippet, collections.Iterable)): def mkpath(idx): return ''.join([path, '[%d]' % idx]) @@ -340,7 +336,7 @@ elif isinstance(snippet, collections.Mapping): attrs = (dep_attrs(val, resource_name) for val in snippet.values()) return itertools.chain.from_iterable(attrs) - elif (not isinstance(snippet, six.string_types) and + elif (not isinstance(snippet, str) and isinstance(snippet, collections.Iterable)): attrs = (dep_attrs(value, resource_name) for value in snippet) return itertools.chain.from_iterable(attrs) @@ -363,7 +359,7 @@ elif isinstance(snippet, collections.Mapping): res_attrs = (all_dep_attrs(value) for value in snippet.values()) return itertools.chain.from_iterable(res_attrs) - elif (not isinstance(snippet, six.string_types) and + elif (not isinstance(snippet, str) and isinstance(snippet, collections.Iterable)): res_attrs = (all_dep_attrs(value) for value in snippet) return itertools.chain.from_iterable(res_attrs) diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/hot/functions.py heat-14.0.0/heat/engine/hot/functions.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/hot/functions.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/hot/functions.py 2020-05-13 10:48:27.000000000 +0000 @@ -12,14 +12,14 @@ # under the License. import collections +import functools import hashlib import itertools from oslo_config import cfg from oslo_log import log as logging from oslo_serialization import jsonutils -import six -from six.moves.urllib import parse as urlparse +from urllib import parse as urlparse import yaql from yaql.language import exceptions @@ -76,7 +76,7 @@ raise ValueError(_('Function "%s" must have arguments') % self.fn_name) - if isinstance(args, six.string_types): + if isinstance(args, str): param_name = args path_components = [] elif isinstance(args, collections.Sequence): @@ -86,7 +86,7 @@ raise TypeError(_('Argument to "%s" must be string or list') % self.fn_name) - if not isinstance(param_name, six.string_types): + if not isinstance(param_name, str): raise TypeError(_('Parameter name in "%s" must be string') % self.fn_name) @@ -100,12 +100,12 @@ collections.Sequence)): raise TypeError(_('"%s" can\'t traverse path') % self.fn_name) - if not isinstance(key, (six.string_types, int)): + if not isinstance(key, (str, int)): raise TypeError(_('Path components in "%s" ' 'must be strings') % self.fn_name) if isinstance(collection, collections.Sequence - ) and isinstance(key, six.string_types): + ) and isinstance(key, str): try: key = int(key) except ValueError: @@ -116,7 +116,7 @@ return collection[key] try: - return six.moves.reduce(get_path_component, path_components, + return functools.reduce(get_path_component, path_components, parameter) except (KeyError, IndexError, TypeError): return '' @@ -168,7 +168,7 @@ def _parse_args(self): if (not isinstance(self.args, collections.Sequence) or - isinstance(self.args, six.string_types)): + isinstance(self.args, str)): raise TypeError(_('Argument to "%s" must be a list') % self.fn_name) @@ -200,7 +200,7 @@ attrs = [self._attr_path()] except Exception as exc: LOG.debug("Ignoring exception calculating required attributes" - ": %s %s", type(exc).__name__, six.text_type(exc)) + ": %s %s", type(exc).__name__, str(exc)) attrs = [] else: attrs = [] @@ -400,13 +400,13 @@ return '' if not isinstance(value, - (six.string_types, six.integer_types, + (str, int, float, bool)): raise TypeError(_('"%(name)s" params must be strings or numbers, ' 'param %(param)s is not valid') % {'name': self.fn_name, 'param': param}) - return six.text_type(value) + return str(value) def result(self): template = function.resolve(self._string) @@ -415,7 +415,7 @@ if self._strict: unreplaced_keys = set(mapping) - if not isinstance(template, six.string_types): + if not isinstance(template, str): raise TypeError(_('"%s" template must be a string') % self.fn_name) if not isinstance(mapping, collections.Mapping): @@ -426,7 +426,7 @@ return strings placeholder = keys[0] - if not isinstance(placeholder, six.string_types): + if not isinstance(placeholder, str): raise TypeError(_('"%s" param placeholders must be strings') % self.fn_name) @@ -490,7 +490,7 @@ else: _raise_empty_param_value_error() - if not isinstance(value, (six.string_types, six.integer_types, + if not isinstance(value, (str, int, float, bool)): if isinstance(value, (collections.Mapping, collections.Sequence)): if not self._allow_empty_value and len(value) == 0: @@ -507,7 +507,7 @@ raise TypeError(_('"%s" params must be strings, numbers, ' 'list or map.') % self.fn_name) - ret_value = six.text_type(value) + ret_value = str(value) if not self._allow_empty_value and not ret_value: _raise_empty_param_value_error() return ret_value @@ -553,7 +553,7 @@ assert self.files is not None, "No stack definition in Function" args = function.resolve(self.args) - if not (isinstance(args, six.string_types)): + if not (isinstance(args, str)): raise TypeError(_('Argument to "%s" must be a string') % self.fn_name) @@ -603,19 +603,19 @@ strings = function.resolve(self._strings) if strings is None: strings = [] - if (isinstance(strings, six.string_types) or + if (isinstance(strings, str) or not isinstance(strings, collections.Sequence)): raise TypeError(_('"%s" must operate on a list') % self.fn_name) delim = function.resolve(self._delim) - if not isinstance(delim, six.string_types): + if not isinstance(delim, str): raise TypeError(_('"%s" delimiter must be a string') % self.fn_name) def ensure_string(s): if s is None: return '' - if not isinstance(s, six.string_types): + if not isinstance(s, str): raise TypeError( _('Items to join must be strings not %s' ) % (repr(s)[:200])) @@ -668,7 +668,7 @@ strings = [] for jl in r_joinlists: if jl: - if (isinstance(jl, six.string_types) or + if (isinstance(jl, str) or not isinstance(jl, collections.Sequence)): raise TypeError(_('"%s" must operate on ' 'a list') % self.fn_name) @@ -676,7 +676,7 @@ strings += jl delim = function.resolve(self._delim) - if not isinstance(delim, six.string_types): + if not isinstance(delim, str): raise TypeError(_('"%s" delimiter must be a string') % self.fn_name) @@ -685,7 +685,7 @@ ) % (repr(s)[:200]) if s is None: return '' - elif isinstance(s, six.string_types): + elif isinstance(s, str): return s elif isinstance(s, (collections.Mapping, collections.Sequence)): try: @@ -801,7 +801,7 @@ repl_keys = ensure_map(repl_map.get('keys', {})) repl_values = ensure_map(repl_map.get('values', {})) ret_map = {} - for k, v in six.iteritems(in_map): + for k, v in in_map.items(): key = repl_keys.get(k) if key is None: key = k @@ -930,12 +930,12 @@ def _valid_arg(self, arg): if not (isinstance(arg, (collections.Sequence, function.Function)) and - not isinstance(arg, six.string_types)): + not isinstance(arg, str)): raise TypeError(_('The values of the "for_each" argument to ' '"%s" must be lists') % self.fn_name) def _do_replacement(self, keys, values, template): - if isinstance(template, six.string_types): + if isinstance(template, str): for (key, value) in zip(keys, values): template = template.replace(key, value) return template @@ -951,7 +951,7 @@ def result(self): for_each = function.resolve(self._for_each) - keys, lists = six.moves.zip(*for_each.items()) + keys, lists = zip(*for_each.items()) # use empty list for references(None) else validation will fail value_lens = [] @@ -970,7 +970,7 @@ 'loop.') % self.fn_name) template = function.resolve(self._template) - iter_func = itertools.product if self._nested_loop else six.moves.zip + iter_func = itertools.product if self._nested_loop else zip return [self._do_replacement(keys, replacements, template) for replacements in iter_func(*values)] @@ -996,7 +996,7 @@ if not (isinstance(arg, (collections.Sequence, collections.Mapping, function.Function)) and - not isinstance(arg, six.string_types)): + not isinstance(arg, str)): raise TypeError(_('The values of the "for_each" argument to ' '"%s" must be lists or maps') % self.fn_name) @@ -1067,7 +1067,7 @@ def validate_usage(self, args): if not (isinstance(args, list) and - all([isinstance(a, six.string_types) for a in args])): + all([isinstance(a, str) for a in args])): msg = _('Argument to function "%s" must be a list of strings') raise TypeError(msg % self.fn_name) @@ -1075,18 +1075,15 @@ msg = _('Function "%s" usage: ["", ""]') raise ValueError(msg % self.fn_name) - if six.PY3: - algorithms = hashlib.algorithms_available - else: - algorithms = hashlib.algorithms + algorithms = hashlib.algorithms_available if args[0].lower() not in algorithms: msg = _('Algorithm must be one of %s') - raise ValueError(msg % six.text_type(algorithms)) + raise ValueError(msg % str(algorithms)) def digest(self, algorithm, value): _hash = hashlib.new(algorithm) - _hash.update(six.b(value)) + _hash.update(value.encode('latin-1')) return _hash.hexdigest() @@ -1121,7 +1118,7 @@ 'example': example} self.fn_name = fn_name - if isinstance(args, (six.string_types, collections.Mapping)): + if isinstance(args, (str, collections.Mapping)): raise TypeError(_('Incorrect arguments to "%(fn_name)s" ' 'should be: %(example)s') % self.fmt_data) @@ -1214,7 +1211,7 @@ self._parse(self._expression) def _parse(self, expression): - if not isinstance(expression, six.string_types): + if not isinstance(expression, str): raise TypeError(_('The "expression" argument to %s must ' 'contain a string.') % self.fn_name) @@ -1282,7 +1279,7 @@ try: if (not self.args or not isinstance(self.args, collections.Sequence) or - isinstance(self.args, six.string_types)): + isinstance(self.args, str)): raise ValueError() condition, value_if_true, value_if_false = self.args except ValueError: @@ -1311,7 +1308,7 @@ def _check_args(self): if not (isinstance(self.args, collections.Sequence) and - not isinstance(self.args, six.string_types)): + not isinstance(self.args, str)): msg = _('Arguments to "%s" must be a list of conditions') raise ValueError(msg % self.fn_name) if not self.args or len(self.args) < 2: @@ -1406,7 +1403,7 @@ def _parse_args(self): if (not isinstance(self.args, collections.Sequence) or - isinstance(self.args, six.string_types)): + isinstance(self.args, str)): raise TypeError(_('Argument to "%s" must be a list') % self.fn_name) @@ -1476,7 +1473,7 @@ elif arg == self.PORT: port = args[arg] if not isinstance(port, function.Function): - if not isinstance(port, six.integer_types): + if not isinstance(port, int): try: port = int(port) except ValueError: @@ -1493,7 +1490,7 @@ 'must be in range 1-65535') % port) else: if not isinstance(args[arg], (function.Function, - six.string_types)): + str)): raise TypeError(_('The "%(arg)s" argument to ' '"%(fn_name)s" must be a string') % {'arg': arg, @@ -1544,7 +1541,7 @@ port = args.get(self.PORT, '') if port: yield ':' - yield six.text_type(port) + yield str(port) path = urlparse.quote(args.get(self.PATH, '')) @@ -1584,7 +1581,7 @@ def result(self): args = function.resolve(self.args) - if (isinstance(args, six.string_types) or + if (isinstance(args, str) or not isinstance(args, collections.Sequence)): raise TypeError(_('Incorrect arguments to "%(fn_name)s" ' 'should be: %(example)s') % self.fmt_data) @@ -1593,7 +1590,7 @@ if m is None: return [] elif (isinstance(m, collections.Sequence) and - not isinstance(m, six.string_types)): + not isinstance(m, str)): return m else: msg = _('Incorrect arguments: Items to concat must be lists. ' diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/hot/template.py heat-14.0.0/heat/engine/hot/template.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/hot/template.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/hot/template.py 2020-05-13 10:48:27.000000000 +0000 @@ -12,8 +12,6 @@ import functools -import six - from heat.common import exception from heat.common.i18n import _ from heat.engine.cfn import functions as cfn_funcs @@ -159,7 +157,7 @@ if not attrs: raise exception.StackValidationFailed(message=message) try: - for attr, attr_value in six.iteritems(attrs): + for attr, attr_value in attrs.items(): if attr not in allowed_keys: raise KeyError(err_msg % attr) if sub_section not in attrs: @@ -183,7 +181,7 @@ for name, attrs in sorted(data.items()): cfn_object = {} - for attr, attr_value in six.iteritems(attrs): + for attr, attr_value in attrs.items(): cfn_attr = mapping[attr] if cfn_attr is not None: cfn_object[cfn_attr] = attr_value @@ -201,18 +199,18 @@ def get_section_name(self, section): cfn_to_hot_attrs = dict( - zip(six.itervalues(self._HOT_TO_CFN_ATTRS), - six.iterkeys(self._HOT_TO_CFN_ATTRS))) + zip(self._HOT_TO_CFN_ATTRS.values(), + self._HOT_TO_CFN_ATTRS.keys())) return cfn_to_hot_attrs.get(section, section) def param_schemata(self, param_defaults=None): parameter_section = self.t.get(self.PARAMETERS) or {} pdefaults = param_defaults or {} - for name, schema in six.iteritems(parameter_section): + for name, schema in parameter_section.items(): if name in pdefaults: parameter_section[name]['default'] = pdefaults[name] - params = six.iteritems(parameter_section) + params = parameter_section.items() return dict((name, self.param_schema_class.from_dict(name, schema)) for name, schema in params) @@ -228,7 +226,7 @@ valid_keys = frozenset(self._RESOURCE_KEYS) def defns(): - for name, snippet in six.iteritems(resources): + for name, snippet in resources.items(): try: invalid_keys = set(snippet) - valid_keys if invalid_keys: @@ -239,7 +237,7 @@ defn_data = dict(self._rsrc_defn_args(stack, name, snippet)) except (TypeError, ValueError, KeyError) as ex: - msg = six.text_type(ex) + msg = str(ex) raise exception.StackValidationFailed(message=msg) defn = rsrc_defn.ResourceDefinition(name, **defn_data) @@ -250,7 +248,7 @@ enabled = conditions.is_enabled(cond_name) except ValueError as exc: path = [self.RESOURCES, name, self.RES_CONDITION] - message = six.text_type(exc) + message = str(exc) raise exception.StackValidationFailed(path=path, message=message) if not enabled: @@ -490,7 +488,7 @@ tmpl, template_id, files, env) self._parser_condition_functions = {} - for n, f in six.iteritems(self.functions): + for n, f in self.functions.items(): if not f == hot_funcs.Removed: self._parser_condition_functions[n] = function.Invalid else: @@ -512,14 +510,14 @@ yield ('external_id', self._parse_resource_field(self.RES_EXTERNAL_ID, - (six.string_types, + (str, function.Function), 'string', name, data, parse)) yield ('condition', self._parse_resource_field(self.RES_CONDITION, - (six.string_types, bool, + (str, bool, function.Function), 'string_or_boolean', name, data, parse_cond)) diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/node_data.py heat-14.0.0/heat/engine/node_data.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/node_data.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/node_data.py 2020-05-13 10:48:27.000000000 +0000 @@ -11,8 +11,6 @@ # License for the specific language governing permissions and limitations # under the License. -import six - class NodeData(object): """Data about a node in the graph, to be passed along to other nodes.""" @@ -53,8 +51,8 @@ """Return a dict of all available top-level attribute values.""" attrs = {k: v for k, v in self._attributes.items() - if isinstance(k, six.string_types)} - for v in six.itervalues(attrs): + if isinstance(k, str)} + for v in attrs.values(): if isinstance(v, Exception): raise v return attrs @@ -69,7 +67,7 @@ def attribute_names(self): """Iterate over valid top-level attribute names.""" for key in self._attributes: - if isinstance(key, six.string_types): + if isinstance(key, str): yield key else: yield key[0] @@ -80,7 +78,7 @@ This is the format that is serialised and stored in the database's SyncPoints. """ - for v in six.itervalues(self._attributes): + for v in self._attributes.values(): if isinstance(v, Exception): raise v diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/output.py heat-14.0.0/heat/engine/output.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/output.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/output.py 2020-05-13 10:48:27.000000000 +0000 @@ -13,7 +13,6 @@ import collections import copy -import six from heat.common import exception from heat.engine import function @@ -47,8 +46,7 @@ if self._deps is None: try: required_resources = function.dependencies(self._value) - self._deps = set(six.moves.map(lambda rp: rp.name, - required_resources)) + self._deps = set(map(lambda rp: rp.name, required_resources)) except (exception.InvalidTemplateAttribute, exception.InvalidTemplateReference): # This output ain't gonna work anyway @@ -83,7 +81,7 @@ if self._description is None: return 'No description given' - return six.text_type(self._description) + return str(self._description) def render_hot(self): def items(): diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/parameters.py heat-14.0.0/heat/engine/parameters.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/parameters.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/parameters.py 2020-05-13 10:48:27.000000000 +0000 @@ -18,7 +18,6 @@ from oslo_serialization import jsonutils from oslo_utils import encodeutils from oslo_utils import strutils -import six from heat.common import exception from heat.common.i18n import _ @@ -87,8 +86,7 @@ message=_('Default must be a comma-delimited list ' 'string: %s') % err) elif self.type == self.LIST and isinstance(self.default, list): - default_value = [(six.text_type(x)) - for x in self.default] + default_value = [(str(x)) for x in self.default] try: self.validate_constraints(default_value, context, [constr.CustomConstraint]) @@ -184,7 +182,6 @@ return super(Schema, self).__getitem__(key) -@six.python_2_unicode_compatible class Parameter(object): """A template parameter.""" @@ -247,10 +244,10 @@ else: raise exception.UserParameterMissing(key=self.name) except exception.StackValidationFailed as ex: - msg = err_msg % dict(name=self.name, exp=six.text_type(ex)) + msg = err_msg % dict(name=self.name, exp=str(ex)) raise exception.StackValidationFailed(message=msg) except exception.InvalidSchemaError as ex: - msg = err_msg % dict(name=self.name, exp=six.text_type(ex)) + msg = err_msg % dict(name=self.name, exp=str(ex)) raise exception.InvalidSchemaError(message=msg) def value(self): @@ -302,13 +299,13 @@ @classmethod def _value_as_text(cls, value): - return six.text_type(value) + return str(value) def __str__(self): """Return a string representation of the parameter.""" value = self.value() if self.hidden(): - return six.text_type('******') + return str('******') else: return self._value_as_text(value) @@ -330,7 +327,7 @@ try: Schema.str_to_num(val) except (ValueError, TypeError) as ex: - raise exception.StackValidationFailed(message=six.text_type(ex)) + raise exception.StackValidationFailed(message=str(ex)) self.schema.validate_value(val, context) def value(self): @@ -346,7 +343,7 @@ try: strutils.bool_from_string(val, strict=True) except ValueError as ex: - raise exception.StackValidationFailed(message=six.text_type(ex)) + raise exception.StackValidationFailed(message=str(ex)) self.schema.validate_value(val, context) def value(self): @@ -402,12 +399,12 @@ def parse(self, value): # only parse when value is not already a list if isinstance(value, list): - return [(six.text_type(x)) for x in value] + return [(str(x)) for x in value] try: return param_utils.delim_string_to_list(value) except (KeyError, AttributeError) as err: message = _('Value must be a comma-delimited list string: %s') - raise ValueError(message % six.text_type(err)) + raise ValueError(message % str(err)) return value def value(self): @@ -432,7 +429,7 @@ try: parsed = self.parse(val) except ValueError as ex: - raise exception.StackValidationFailed(message=six.text_type(ex)) + raise exception.StackValidationFailed(message=str(ex)) self.schema.validate_value(parsed, context) @@ -448,7 +445,7 @@ def parse(self, value): try: val = value - if not isinstance(val, six.string_types): + if not isinstance(val, str): # turn off oslo_serialization's clever to_primitive() val = jsonutils.dumps(val, default=None) if val: @@ -481,12 +478,11 @@ try: parsed = self.parse(val) except ValueError as ex: - raise exception.StackValidationFailed(message=six.text_type(ex)) + raise exception.StackValidationFailed(message=str(ex)) self.schema.validate_value(parsed, context) -@six.add_metaclass(abc.ABCMeta) -class Parameters(collections.Mapping): +class Parameters(collections.Mapping, metaclass=abc.ABCMeta): """Parameters of a stack. The parameters of a stack, with type checking, defaults, etc. specified by @@ -513,7 +509,7 @@ schemata = self.tmpl.param_schemata() user_parameters = (user_parameter(si) for si in - six.iteritems(schemata)) + schemata.items()) pseudo_parameters = self._pseudo_parameters(stack_identifier) self.params = dict((p.name, @@ -534,7 +530,7 @@ """ self._validate_user_parameters() - for param in six.itervalues(self.params): + for param in self.params.values(): param.validate(validate_value, context) def __contains__(self, key): @@ -560,7 +556,7 @@ function) and return the resulting dictionary. """ return dict((n, func(p)) - for n, p in six.iteritems(self.params) if filter_func(p)) + for n, p in self.params.items() if filter_func(p)) def set_stack_id(self, stack_identifier): """Set the StackId pseudo parameter value.""" diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/plugin_manager.py heat-14.0.0/heat/engine/plugin_manager.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/plugin_manager.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/plugin_manager.py 2020-05-13 10:48:27.000000000 +0000 @@ -17,7 +17,6 @@ from oslo_config import cfg from oslo_log import log -import six from heat.common import plugin_loader @@ -49,15 +48,14 @@ 'heat.engine') def modules(): - pkg_modules = six.moves.map(plugin_loader.load_modules, - packages()) + pkg_modules = map(plugin_loader.load_modules, packages()) return itertools.chain.from_iterable(pkg_modules) self.modules = list(modules()) def map_to_modules(self, function): """Iterate over the results of calling a function on every module.""" - return six.moves.map(function, self.modules) + return map(function, self.modules) class PluginMapping(object): @@ -72,7 +70,7 @@ mappings provided by that module. Any other arguments passed will be passed to the mapping functions. """ - if isinstance(names, six.string_types): + if isinstance(names, str): names = [names] self.names = ['%s_mapping' % name for name in names] @@ -109,5 +107,5 @@ Mappings are returned as a list of (key, value) tuples. """ mod_dicts = plugin_manager.map_to_modules(self.load_from_module) - return itertools.chain.from_iterable(six.iteritems(d) for d + return itertools.chain.from_iterable(d.items() for d in mod_dicts) diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/properties_group.py heat-14.0.0/heat/engine/properties_group.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/properties_group.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/properties_group.py 2020-05-13 10:48:27.000000000 +0000 @@ -11,8 +11,6 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from heat.common import exception from heat.common.i18n import _ @@ -78,7 +76,7 @@ self.validate_schema(item) elif isinstance(item, list): for name in item: - if not isinstance(name, six.string_types): + if not isinstance(name, str): raise exception.InvalidSchemaError(message=next_msg) else: raise exception.InvalidSchemaError(message=next_msg) diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/properties.py heat-14.0.0/heat/engine/properties.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/properties.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/properties.py 2020-05-13 10:48:27.000000000 +0000 @@ -14,7 +14,6 @@ import collections from oslo_serialization import jsonutils -import six from heat.common import exception from heat.common.i18n import _ @@ -274,9 +273,9 @@ def _get_string(self, value): if value is None: value = self.has_default() and self.default() or '' - if not isinstance(value, six.string_types): + if not isinstance(value, str): if isinstance(value, (bool, int)): - value = six.text_type(value) + value = str(value) else: raise ValueError(_('Value must be a string; got %r') % value) return value @@ -306,24 +305,23 @@ # via a provider resource, in particular lists-of-dicts which # cannot be handled correctly via comma_delimited_list if self.schema.allow_conversion: - if isinstance(value, six.string_types): + if isinstance(value, str): return value elif isinstance(value, collections.Sequence): return jsonutils.dumps(value) raise TypeError(_('"%s" is not a map') % value) - return dict(self._get_children(six.iteritems(value), + return dict(self._get_children(value.items(), validate=validate, translation=translation)) def _get_list(self, value, validate=False, translation=None): if value is None: value = self.has_default() and self.default() or [] - if self.schema.allow_conversion and isinstance(value, - six.string_types): - value = param_utils.delim_string_to_list(value) + if self.schema.allow_conversion and isinstance(value, str): + value = param_utils.delim_string_to_list(value) if (not isinstance(value, collections.Sequence) or - isinstance(value, six.string_types)): + isinstance(value, str)): raise TypeError(_('"%s" is not a list') % repr(value)) return [v[1] for v in self._get_children(enumerate(value), @@ -341,7 +339,7 @@ value = self.has_default() and self.default() or False if isinstance(value, bool): return value - if isinstance(value, six.string_types): + if isinstance(value, str): normalised = value.lower() if normalised not in ['true', 'false']: raise ValueError(_('"%s" is not a valid boolean') % normalised) @@ -432,7 +430,7 @@ else: path = [key] raise exception.StackValidationFailed( - path=path, message=six.text_type(e)) + path=path, message=str(e)) # are there unimplemented Properties if not prop.implemented() and key in self.data: @@ -488,7 +486,7 @@ # the resolver function could raise any number of exceptions, # so handle this generically except Exception as e: - raise ValueError(six.text_type(e)) + raise ValueError(str(e)) def _get_property_value(self, key, validate=False): if key not in self: @@ -658,7 +656,7 @@ return {}, {} param_prop_defs = [param_prop_def_items(n, s, template_type) - for n, s in six.iteritems(schemata(schema)) + for n, s in schemata(schema).items() if s.implemented] param_items, prop_items = zip(*param_prop_defs) return dict(param_items), dict(prop_items) diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resource.py heat-14.0.0/heat/engine/resource.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resource.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resource.py 2020-05-13 10:48:27.000000000 +0000 @@ -23,7 +23,6 @@ from oslo_log import log as logging from oslo_utils import excutils from oslo_utils import reflection -import six from heat.common import exception from heat.common.i18n import _ @@ -80,7 +79,7 @@ msg = (_("The resource %(res)s could not perform " "scaling action: %(reason)s") % {'res': res_name, 'reason': reason}) - super(Exception, self).__init__(six.text_type(msg)) + super(Exception, self).__init__(str(msg)) class PollDelay(Exception): @@ -97,7 +96,6 @@ self.period = period -@six.python_2_unicode_compatible class Resource(status.ResourceStatus): BASE_ATTRIBUTES = (SHOW, ) = (attributes.SHOW_ATTR, ) @@ -190,7 +188,7 @@ ex = exception.ResourceTypeUnavailable( resource_type=resource_type, service_name=cls.default_client_name, - reason=six.text_type(exc)) + reason=str(exc)) raise ex else: if not svc_available: @@ -198,7 +196,7 @@ resource_type=resource_type, service_name=cls.default_client_name, reason=reason) - LOG.info(six.text_type(ex)) + LOG.info(str(ex)) raise ex def __init__(self, name, definition, stack): @@ -453,7 +451,7 @@ def calc_update_allowed(self, props): update_allowed_set = set(self.update_allowed_properties) - for (psk, psv) in six.iteritems(props.props): + for (psk, psv) in props.props.items(): if psv.update_allowed(): update_allowed_set.add(psk) return update_allowed_set @@ -517,7 +515,7 @@ "not setting metadata", {'name': self.name, 'id': self.id, 'st': db_res.status}) raise exception.ResourceNotAvailable(resource_name=self.name) - LOG.debug('Setting metadata for %s', six.text_type(self)) + LOG.debug('Setting metadata for %s', str(self)) if refresh: metadata = merge_metadata(metadata, db_res.rsrc_metadata) if db_res.update_metadata(metadata): @@ -657,7 +655,7 @@ """ update_allowed_set = self.calc_update_allowed(after_props) immutable_set = set() - for (psk, psv) in six.iteritems(after_props.props): + for (psk, psv) in after_props.props.items(): if psv.immutable(): immutable_set.add(psk) @@ -672,7 +670,7 @@ # already been validated. LOG.warning('Ignoring error in old property value ' '%(prop_name)s: %(msg)s', - {'prop_name': key, 'msg': six.text_type(exc)}) + {'prop_name': key, 'msg': str(exc)}) return True return before != after_props.get(key) @@ -707,13 +705,13 @@ if self.resource_id is not None: text = '%s "%s" [%s] %s' % (class_name, self.name, self.resource_id, - six.text_type(self.stack)) + str(self.stack)) else: text = '%s "%s" %s' % (class_name, self.name, - six.text_type(self.stack)) + str(self.stack)) else: text = '%s "%s"' % (class_name, self.name) - return six.text_type(text) + return str(text) def add_explicit_dependencies(self, deps): """Add all dependencies explicitly specified in the template. @@ -918,27 +916,27 @@ try: set_in_progress() yield - except exception.UpdateInProgress as ex: + except exception.UpdateInProgress: with excutils.save_and_reraise_exception(): LOG.info('Update in progress for %s', self.name) except expected_exceptions as ex: with excutils.save_and_reraise_exception(): - self.state_set(action, self.COMPLETE, six.text_type(ex), + self.state_set(action, self.COMPLETE, str(ex), lock=lock_release) - LOG.debug('%s', six.text_type(ex)) + LOG.debug('%s', str(ex)) except Exception as ex: LOG.info('%(action)s: %(info)s', {"action": action, - "info": six.text_type(self)}, + "info": str(self)}, exc_info=True) failure = exception.ResourceFailure(ex, self, action) - self.state_set(action, self.FAILED, six.text_type(failure), + self.state_set(action, self.FAILED, str(failure), lock=lock_release) raise failure except BaseException as exc: with excutils.save_and_reraise_exception(): try: - reason = six.text_type(exc) + reason = str(exc) msg = '%s aborted' % action if reason: msg += ' (%s)' % reason @@ -1107,7 +1105,7 @@ """ def get_attrs(attrs, cacheable_only=False): for attr in attrs: - path = (attr,) if isinstance(attr, six.string_types) else attr + path = (attr,) if isinstance(attr, str) else attr if (cacheable_only and (self.attributes.get_cache_mode(path[0]) == attributes.Schema.CACHE_NONE)): @@ -1201,7 +1199,7 @@ action = self.CREATE if (self.action, self.status) != (self.INIT, self.COMPLETE): exc = exception.Error(_('State %s invalid for create') - % six.text_type(self.state)) + % str(self.state)) raise exception.ResourceFailure(exc, self, action) if self.external_id is not None: @@ -1329,7 +1327,7 @@ # save the resource data if data and isinstance(data, dict): - for key, value in six.iteritems(data): + for key, value in data.items(): self.data_set(key, value) # save the resource metadata @@ -1417,7 +1415,7 @@ if 'replace' in restricted_actions: ex = exception.ResourceActionRestricted(action='replace') failure = exception.ResourceFailure(ex, self, self.UPDATE) - self._add_event(self.UPDATE, self.FAILED, six.text_type(ex)) + self._add_event(self.UPDATE, self.FAILED, str(ex)) raise failure else: raise UpdateReplace(self.name) @@ -1452,7 +1450,7 @@ except Exception as e: failure = exception.ResourceFailure(e, self, self.action) self.state_set(self.UPDATE, self.FAILED, - six.text_type(failure)) + str(failure)) raise failure self.replaced_by = None @@ -1582,16 +1580,16 @@ # if any exception happen, we should set the resource to # FAILED, then raise ResourceFailure failure = exception.ResourceFailure(e, self, action) - self.state_set(action, self.FAILED, six.text_type(failure)) + self.state_set(action, self.FAILED, str(failure)) raise failure @classmethod def check_is_substituted(cls, new_res_type): - support_status = getattr(cls, 'support_status', None) - if support_status: - is_substituted = support_status.is_substituted(new_res_type) - return is_substituted - return False + support_status = getattr(cls, 'support_status', None) + if support_status: + is_substituted = support_status.is_substituted(new_res_type) + return is_substituted + return False def _persist_update_no_change(self, new_template_id): """Persist an update where the resource is unchanged.""" @@ -1659,7 +1657,7 @@ self._prepare_update_replace(action) except exception.ResourceActionRestricted as ae: failure = exception.ResourceFailure(ae, self, action) - self._add_event(action, self.FAILED, six.text_type(ae)) + self._add_event(action, self.FAILED, str(ae)) raise failure if not needs_update: @@ -1793,7 +1791,7 @@ (self.action != self.SUSPEND and self.status != self.COMPLETE)): exc = exception.Error(_('State %s invalid for suspend') - % six.text_type(self.state)) + % str(self.state)) raise exception.ResourceFailure(exc, self, action) LOG.info('suspending %s', self) @@ -1814,7 +1812,7 @@ (self.RESUME, self.FAILED), (self.RESUME, self.COMPLETE)): exc = exception.Error(_('State %s invalid for resume') - % six.text_type(self.state)) + % str(self.state)) raise exception.ResourceFailure(exc, self, action) LOG.info('resuming %s', self) @@ -2038,7 +2036,7 @@ while True: count += 1 LOG.info('delete %(name)s attempt %(attempt)d' % - {'name': six.text_type(self), 'attempt': count+1}) + {'name': str(self), 'attempt': count+1}) if count: delay = timeutils.retry_backoff_delay(count, jitter_max=2.0) @@ -2091,7 +2089,7 @@ rs = {'action': self.action, 'status': self.status, - 'status_reason': six.text_type(self.status_reason), + 'status_reason': str(self.status_reason), 'stack_id': self.stack.id, 'physical_resource_id': self.resource_id, 'name': self.name, @@ -2119,7 +2117,7 @@ self.context, self.id, rs) if lock != self.LOCK_NONE: LOG.error('No calling_engine_id in store() %s', - six.text_type(rs)) + str(rs)) else: self._store_with_lock(rs, lock) else: @@ -2145,7 +2143,7 @@ self._incr_atomic_key(self._atomic_key) else: LOG.info('Resource %s is locked or does not exist', - six.text_type(self)) + str(self)) LOG.debug('Resource id:%(resource_id)s locked or does not exist. ' 'Expected atomic_key:%(atomic_key)s, ' 'accessing from engine_id:%(engine_id)s', @@ -2370,9 +2368,9 @@ logic specific to the resource implementation. """ if self.resource_id is not None: - return six.text_type(self.resource_id) + return str(self.resource_id) else: - return six.text_type(self.name) + return str(self.name) def FnGetRefId(self): """For the intrinsic function Ref. @@ -2384,7 +2382,7 @@ def physical_resource_name_or_FnGetRefId(self): res_name = self.physical_resource_name() if res_name is not None: - return six.text_type(res_name) + return str(res_name) else: return Resource.get_reference_id(self) @@ -2438,13 +2436,13 @@ hook = details['unset_hook'] if not environment.valid_hook_type(hook): msg = (_('Invalid hook type "%(hook)s" for %(resource)s') % - {'hook': hook, 'resource': six.text_type(self)}) + {'hook': hook, 'resource': str(self)}) raise exception.InvalidBreakPointHook(message=msg) if not self.has_hook(hook): msg = (_('The "%(hook)s" hook is not defined ' 'on %(resource)s') % - {'hook': hook, 'resource': six.text_type(self)}) + {'hook': hook, 'resource': str(self)}) raise exception.InvalidBreakPointHook(message=msg) def _unset_hook(self, details): @@ -2453,7 +2451,7 @@ hook = details['unset_hook'] self.clear_hook(hook) LOG.info('Clearing %(hook)s hook on %(resource)s', - {'hook': hook, 'resource': six.text_type(self)}) + {'hook': hook, 'resource': str(self)}) self._add_event(self.action, self.status, "Hook %s is cleared" % hook) @@ -2464,7 +2462,7 @@ def get_string_details(): if details is None: return 'No signal details provided' - if isinstance(details, six.string_types): + if isinstance(details, str): return details if isinstance(details, dict): if all(k in details for k in ('previous', 'current', @@ -2490,8 +2488,8 @@ # No spam required return LOG.info('signal %(name)s : %(msg)s', - {'name': six.text_type(self), - 'msg': six.text_type(ex)}, + {'name': str(self), + 'msg': str(ex)}, exc_info=True) failure = exception.ResourceFailure(ex, self) raise failure diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/alarm_base.py heat-14.0.0/heat/engine/resources/alarm_base.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/alarm_base.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/alarm_base.py 2020-05-13 10:48:27.000000000 +0000 @@ -17,7 +17,7 @@ from heat.engine import resource from heat.engine import support -from six.moves.urllib import parse as urlparse +from urllib import parse COMMON_PROPERTIES = ( @@ -231,7 +231,7 @@ for queue in kwargs.pop(queue_type, []): query = {'queue_name': queue} - yield 'trust+zaqar://?%s' % urlparse.urlencode(query) + yield 'trust+zaqar://?%s' % parse.urlencode(query) action_props = {arg_types[0]: list(get_urls(*arg_types)) for arg_types in ((ALARM_ACTIONS, ALARM_QUEUES), diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/aws/autoscaling/autoscaling_group.py heat-14.0.0/heat/engine/resources/aws/autoscaling/autoscaling_group.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/aws/autoscaling/autoscaling_group.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/aws/autoscaling/autoscaling_group.py 2020-05-13 10:48:27.000000000 +0000 @@ -13,7 +13,6 @@ from oslo_log import log as logging from oslo_utils import excutils -import six from heat.common import exception from heat.common import grouputils @@ -327,7 +326,7 @@ with excutils.save_and_reraise_exception(): try: notif.update({'suffix': 'error', - 'message': six.text_type(resize_ex), + 'message': str(resize_ex), 'capacity': grouputils.get_size(self), }) notification.send(**notif) diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/aws/autoscaling/launch_config.py heat-14.0.0/heat/engine/resources/aws/autoscaling/launch_config.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/aws/autoscaling/launch_config.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/aws/autoscaling/launch_config.py 2020-05-13 10:48:27.000000000 +0000 @@ -11,9 +11,6 @@ # License for the specific language governing permissions and limitations # under the License. - -import six - from heat.common import exception from heat.common.i18n import _ from heat.engine import constraints @@ -200,7 +197,7 @@ for sg in server.security_groups] } lc_props = function.resolve(self.properties.data) - for key, value in six.iteritems(instance_props): + for key, value in instance_props.items(): # the properties which are specified in launch configuration, # will override the attributes from the instance lc_props.setdefault(key, value) diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/aws/autoscaling/scaling_policy.py heat-14.0.0/heat/engine/resources/aws/autoscaling/scaling_policy.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/aws/autoscaling/scaling_policy.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/aws/autoscaling/scaling_policy.py 2020-05-13 10:48:27.000000000 +0000 @@ -11,8 +11,6 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from heat.common import exception from heat.common.i18n import _ from heat.engine import attributes @@ -101,9 +99,9 @@ def get_reference_id(self): if self.resource_id is not None: - return six.text_type(self._get_ec2_signed_url()) + return str(self._get_ec2_signed_url()) else: - return six.text_type(self.name) + return str(self.name) def resource_mapping(): diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/aws/cfn/stack.py heat-14.0.0/heat/engine/resources/aws/cfn/stack.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/aws/cfn/stack.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/aws/cfn/stack.py 2020-05-13 10:48:27.000000000 +0000 @@ -12,7 +12,6 @@ # under the License. from requests import exceptions -import six from heat.common import exception from heat.common.i18n import _ @@ -95,7 +94,7 @@ def get_reference_id(self): identifier = self.nested_identifier() if identifier is None: - return six.text_type(self.name) + return str(self.name) return identifier.arn() diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/aws/cfn/wait_condition_handle.py heat-14.0.0/heat/engine/resources/aws/cfn/wait_condition_handle.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/aws/cfn/wait_condition_handle.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/aws/cfn/wait_condition_handle.py 2020-05-13 10:48:27.000000000 +0000 @@ -11,8 +11,6 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from heat.engine.resources import signal_responder from heat.engine.resources import wait_condition as wc_base from heat.engine import support @@ -39,9 +37,9 @@ def get_reference_id(self): if self.resource_id: wc = signal_responder.WAITCONDITION - return six.text_type(self._get_ec2_signed_url(signal_type=wc)) + return str(self._get_ec2_signed_url(signal_type=wc)) else: - return six.text_type(self.name) + return str(self.name) def metadata_update(self, new_metadata=None): """DEPRECATED. Should use handle_signal instead.""" diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/aws/ec2/eip.py heat-14.0.0/heat/engine/resources/aws/ec2/eip.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/aws/ec2/eip.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/aws/ec2/eip.py 2020-05-13 10:48:27.000000000 +0000 @@ -12,7 +12,6 @@ # under the License. from oslo_log import log as logging -import six from heat.common import exception from heat.common.i18n import _ @@ -138,13 +137,13 @@ def get_reference_id(self): eip = self._ipaddress() if eip: - return six.text_type(eip) + return str(eip) else: - return six.text_type(self.name) + return str(self.name) def _resolve_attribute(self, name): if name == self.ALLOCATION_ID: - return six.text_type(self.resource_id) + return str(self.resource_id) class ElasticIpAssociation(resource.Resource): diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/aws/ec2/instance.py heat-14.0.0/heat/engine/resources/aws/ec2/instance.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/aws/ec2/instance.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/aws/ec2/instance.py 2020-05-13 10:48:27.000000000 +0000 @@ -15,9 +15,6 @@ from oslo_config import cfg from oslo_log import log as logging -import six - -cfg.CONF.import_opt('max_server_name_length', 'heat.common.config') from heat.common import exception from heat.common.i18n import _ @@ -28,6 +25,9 @@ from heat.engine import resource from heat.engine.resources import scheduler_hints as sh + +cfg.CONF.import_opt('max_server_name_length', 'heat.common.config') + LOG = logging.getLogger(__name__) @@ -396,7 +396,7 @@ LOG.info('%(name)s._resolve_attribute(%(attname)s) == %(res)s', {'name': self.name, 'attname': name, 'res': res}) - return six.text_type(res) if res else None + return str(res) if res else None def _port_data_delete(self): # delete the port data which implicit-created @@ -415,7 +415,7 @@ unsorted_nics = [] for entry in network_interfaces: nic = (entry - if not isinstance(entry, six.string_types) + if not isinstance(entry, str) else {'NetworkInterfaceId': entry, 'DeviceIndex': len(unsorted_nics)}) unsorted_nics.append(nic) @@ -520,7 +520,7 @@ hint = tm[self.NOVA_SCHEDULER_HINT_KEY] hint_value = tm[self.NOVA_SCHEDULER_HINT_VALUE] if hint in scheduler_hints: - if isinstance(scheduler_hints[hint], six.string_types): + if isinstance(scheduler_hints[hint], str): scheduler_hints[hint] = [scheduler_hints[hint]] scheduler_hints[hint].append(hint_value) else: diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/aws/ec2/internet_gateway.py heat-14.0.0/heat/engine/resources/aws/ec2/internet_gateway.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/aws/ec2/internet_gateway.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/aws/ec2/internet_gateway.py 2020-05-13 10:48:27.000000000 +0000 @@ -11,8 +11,6 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from heat.common import exception from heat.common.i18n import _ from heat.engine import properties @@ -102,7 +100,7 @@ default_client_name = 'neutron' def _vpc_route_tables(self, ignore_errors=False): - for res in six.itervalues(self.stack): + for res in self.stack.values(): if res.has_interface('AWS::EC2::RouteTable'): try: vpc_id = self.properties[self.VPC_ID] diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/aws/ec2/security_group.py heat-14.0.0/heat/engine/resources/aws/ec2/security_group.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/aws/ec2/security_group.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/aws/ec2/security_group.py 2020-05-13 10:48:27.000000000 +0000 @@ -11,8 +11,6 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from heat.common import exception from heat.common.i18n import _ from heat.engine import properties @@ -169,12 +167,12 @@ rule['direction'] = 'egress' for rule in updated[self.sg.SECURITY_GROUP_INGRESS]: rule['direction'] = 'ingress' - updated_rules = list(six.itervalues(updated)) + updated_rules = list(updated.values()) updated_all = updated_rules[0] + updated_rules[1] ids_to_delete = [id for id, rule in existing.items() if rule not in updated_all] rules_to_create = [rule for rule in updated_all - if rule not in six.itervalues(existing)] + if rule not in existing.values()] return ids_to_delete, rules_to_create diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/aws/iam/user.py heat-14.0.0/heat/engine/resources/aws/iam/user.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/aws/iam/user.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/aws/iam/user.py 2020-05-13 10:48:27.000000000 +0000 @@ -12,7 +12,6 @@ # under the License. from oslo_log import log as logging -import six from heat.common import exception from heat.common.i18n import _ @@ -80,7 +79,7 @@ # If a non-string (e.g embedded IAM dict policy) is passed, we # ignore the policy (don't reject it because we previously ignored # and we don't want to break templates which previously worked - if not isinstance(policy, six.string_types): + if not isinstance(policy, str): LOG.debug("Ignoring policy %s, must be string " "resource name", policy) continue @@ -118,7 +117,7 @@ def access_allowed(self, resource_name): policies = (self.properties[self.POLICIES] or []) for policy in policies: - if not isinstance(policy, six.string_types): + if not isinstance(policy, str): LOG.debug("Ignoring policy %s, must be string " "resource name", policy) continue diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/aws/lb/loadbalancer.py heat-14.0.0/heat/engine/resources/aws/lb/loadbalancer.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/aws/lb/loadbalancer.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/aws/lb/loadbalancer.py 2020-05-13 10:48:27.000000000 +0000 @@ -14,7 +14,6 @@ from oslo_config import cfg from oslo_log import log as logging -import six from heat.common import exception from heat.common.i18n import _ @@ -623,7 +622,7 @@ 'Interval must be larger than Timeout'} def get_reference_id(self): - return six.text_type(self.name) + return str(self.name) def _resolve_attribute(self, name): """We don't really support any of these yet.""" diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/aws/s3/s3.py heat-14.0.0/heat/engine/resources/aws/s3/s3.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/aws/s3/s3.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/aws/s3/s3.py 2020-05-13 10:48:27.000000000 +0000 @@ -10,8 +10,7 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. -import six -from six.moves.urllib import parse as urlparse +from urllib import parse from heat.common import exception from heat.common.i18n import _ @@ -165,11 +164,11 @@ self.client_plugin().ignore_not_found(ex) def get_reference_id(self): - return six.text_type(self.resource_id) + return str(self.resource_id) def _resolve_attribute(self, name): url = self.client().get_auth()[0] - parsed = list(urlparse.urlparse(url)) + parsed = list(parse.urlparse(url)) if name == self.DOMAIN_NAME: return parsed[1].split(':')[0] elif name == self.WEBSITE_URL: diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/aodh/alarm.py heat-14.0.0/heat/engine/resources/openstack/aodh/alarm.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/aodh/alarm.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/openstack/aodh/alarm.py 2020-05-13 10:48:27.000000000 +0000 @@ -11,8 +11,6 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from heat.common.i18n import _ from heat.engine import constraints from heat.engine import properties @@ -157,7 +155,7 @@ # make sure the matching_metadata appears in the query like this: # {field: metadata.$prefix.x, ...} - for m_k, m_v in six.iteritems(mmd): + for m_k, m_v in mmd.items(): key = 'metadata.%s' % prefix if m_k.startswith('metadata.'): m_k = m_k[len('metadata.'):] @@ -168,7 +166,7 @@ # NOTE(prazumovsky): type of query value must be a string, but # matching_metadata value type can not be a string, so we # must convert value to a string type. - query.append(dict(field=key, op='eq', value=six.text_type(m_v))) + query.append(dict(field=key, op='eq', value=str(m_v))) if self.MATCHING_METADATA in kwargs: del kwargs[self.MATCHING_METADATA] if self.QUERY in kwargs: diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/barbican/container.py heat-14.0.0/heat/engine/resources/openstack/barbican/container.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/barbican/container.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/openstack/barbican/container.py 2020-05-13 10:48:27.000000000 +0000 @@ -11,8 +11,6 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from heat.common import exception from heat.common.i18n import _ from heat.engine import attributes @@ -192,12 +190,12 @@ } def create_container(self): - info = dict((k, v) for k, v in six.iteritems(self.properties) + info = dict((k, v) for k, v in self.properties.items() if v is not None) return self.client_plugin().create_certificate(**info) def get_refs(self): - return [v for k, v in six.iteritems(self.properties) + return [v for k, v in self.properties.items() if (k != self.NAME and v is not None)] @@ -239,12 +237,12 @@ } def create_container(self): - info = dict((k, v) for k, v in six.iteritems(self.properties) + info = dict((k, v) for k, v in self.properties.items() if v is not None) return self.client_plugin().create_rsa(**info) def get_refs(self): - return [v for k, v in six.iteritems(self.properties) + return [v for k, v in self.properties.items() if (k != self.NAME and v is not None)] diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/barbican/order.py heat-14.0.0/heat/engine/resources/openstack/barbican/order.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/barbican/order.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/openstack/barbican/order.py 2020-05-13 10:48:27.000000000 +0000 @@ -11,8 +11,6 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from heat.common import exception from heat.common.i18n import _ from heat.engine import attributes @@ -228,8 +226,8 @@ raise exception.ResourcePropertyDependency( prop1=self.PROFILE, prop2=self.CA_ID ) - declared_props = sorted([k for k, v in six.iteritems( - self.properties) if k != self.TYPE and v is not None]) + declared_props = sorted([k for k, v in self.properties.items() + if k != self.TYPE and v is not None]) allowed_props = sorted(self.ALLOWED_PROPERTIES_FOR_TYPE[ self.properties[self.TYPE]]) diff = sorted(set(declared_props) - set(allowed_props)) diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/cinder/volume.py heat-14.0.0/heat/engine/resources/openstack/cinder/volume.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/cinder/volume.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/openstack/cinder/volume.py 2020-05-13 10:48:27.000000000 +0000 @@ -13,7 +13,6 @@ from oslo_log import log as logging from oslo_serialization import jsonutils -import six from heat.common import exception from heat.common.i18n import _ @@ -310,7 +309,7 @@ cinder = self.client() vol = cinder.volumes.get(self.resource_id) if name == self.METADATA_ATTR: - return six.text_type(jsonutils.dumps(vol.metadata)) + return str(jsonutils.dumps(vol.metadata)) elif name == self.METADATA_VALUES_ATTR: return vol.metadata if name == self.DISPLAY_NAME_ATTR: @@ -319,7 +318,7 @@ return vol.description elif name == self.ATTACHMENTS_LIST: return vol.attachments - return six.text_type(getattr(vol, name)) + return str(getattr(vol, name)) def check_create_complete(self, vol_id): complete = super(CinderVolume, self).check_create_complete(vol_id) @@ -355,7 +354,7 @@ if self.client_plugin().is_client_exception(ex): raise exception.Error(_( "Failed to extend volume %(vol)s - %(err)s") % { - 'vol': self.resource_id, 'err': six.text_type(ex)}) + 'vol': self.resource_id, 'err': str(ex)}) else: raise return True diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/designate/recordset.py heat-14.0.0/heat/engine/resources/openstack/designate/recordset.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/designate/recordset.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/openstack/designate/recordset.py 2020-05-13 10:48:27.000000000 +0000 @@ -11,8 +11,6 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from heat.common import exception from heat.common.i18n import _ from heat.engine import constraints @@ -99,7 +97,7 @@ entity = 'recordsets' def handle_create(self): - args = dict((k, v) for k, v in six.iteritems(self.properties) if v) + args = dict((k, v) for k, v in self.properties.items() if v) args['type_'] = args.pop(self.TYPE) if not args.get(self.NAME): args[self.NAME] = self.physical_resource_name() diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/designate/zone.py heat-14.0.0/heat/engine/resources/openstack/designate/zone.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/designate/zone.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/openstack/designate/zone.py 2020-05-13 10:48:27.000000000 +0000 @@ -10,7 +10,6 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. -import six from heat.common import exception from heat.common.i18n import _ @@ -122,7 +121,7 @@ raise_invalid_exception(self.SECONDARY, self.MASTERS) def handle_create(self): - args = dict((k, v) for k, v in six.iteritems(self.properties) if v) + args = dict((k, v) for k, v in self.properties.items() if v) args['type_'] = args.pop(self.TYPE) zone = self.client().zones.create(**args) diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/glance/image.py heat-14.0.0/heat/engine/resources/openstack/glance/image.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/glance/image.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/openstack/glance/image.py 2020-05-13 10:48:27.000000000 +0000 @@ -217,8 +217,8 @@ def get_live_resource_data(self): image_data = super(GlanceWebImage, self).get_live_resource_data() if image_data.get('status') in ('deleted', 'killed'): - raise exception.EntityNotFound(entity='Resource', - name=self.name) + raise exception.EntityNotFound(entity='Resource', + name=self.name) return image_data def parse_live_resource_data(self, resource_properties, resource_data): @@ -479,8 +479,8 @@ def get_live_resource_data(self): image_data = super(GlanceImage, self).get_live_resource_data() if image_data.get('status') in ('deleted', 'killed'): - raise exception.EntityNotFound(entity='Resource', - name=self.name) + raise exception.EntityNotFound(entity='Resource', + name=self.name) return image_data def parse_live_resource_data(self, resource_properties, resource_data): diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/heat/autoscaling_group.py heat-14.0.0/heat/engine/resources/openstack/heat/autoscaling_group.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/heat/autoscaling_group.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/openstack/heat/autoscaling_group.py 2020-05-13 10:48:27.000000000 +0000 @@ -11,8 +11,6 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from oslo_log import log as logging from heat.common import exception @@ -212,9 +210,9 @@ return resource.Resource.get_reference_id(self) def _attribute_output_name(self, *attr_path): - return ', '.join(six.text_type(a) for a in attr_path) + return ', '.join(str(a) for a in attr_path) - def get_attribute(self, key, *path): + def get_attribute(self, key, *path): # noqa: C901 if key == self.CURRENT_SIZE: return grouputils.get_size(self) @@ -284,7 +282,7 @@ def _nested_output_defns(self, resource_names, get_attr_fn, get_res_fn): for attr in self.referenced_attrs(): - if isinstance(attr, six.string_types): + if isinstance(attr, str): key, path = attr, [] else: key, path = attr[0], list(attr[1:]) diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/heat/instance_group.py heat-14.0.0/heat/engine/resources/openstack/heat/instance_group.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/heat/instance_group.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/openstack/heat/instance_group.py 2020-05-13 10:48:27.000000000 +0000 @@ -12,7 +12,6 @@ # under the License. import functools -import six from oslo_log import log as logging @@ -460,7 +459,7 @@ def _nested_output_defns(self, resource_names, get_attr_fn, get_res_fn): for attr in self.referenced_attrs(): - if isinstance(attr, six.string_types): + if isinstance(attr, str): key = attr else: key = attr[0] diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/heat/multi_part.py heat-14.0.0/heat/engine/resources/openstack/heat/multi_part.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/heat/multi_part.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/openstack/heat/multi_part.py 2020-05-13 10:48:27.000000000 +0000 @@ -45,9 +45,9 @@ support_status = support.SupportStatus(version='2014.1') PROPERTIES = ( - PARTS, CONFIG, FILENAME, TYPE, SUBTYPE + PARTS, CONFIG, FILENAME, TYPE, SUBTYPE, GROUP ) = ( - 'parts', 'config', 'filename', 'type', 'subtype' + 'parts', 'config', 'filename', 'type', 'subtype', 'group' ) TYPES = ( @@ -57,6 +57,14 @@ ) properties_schema = { + GROUP: properties.Schema( + properties.Schema.STRING, + _('Namespace to group this multi-part configs by when delivered ' + 'to a server. This may imply what configuration tool is going ' + 'to perform the configuration.'), + support_status=support.SupportStatus(version='14.0.0'), + default='Heat::Ungrouped' + ), PARTS: properties.Schema( properties.Schema.LIST, _('Parts belonging to this message.'), @@ -96,7 +104,7 @@ props = { rpc_api.SOFTWARE_CONFIG_NAME: self.physical_resource_name(), rpc_api.SOFTWARE_CONFIG_CONFIG: self.get_message(), - rpc_api.SOFTWARE_CONFIG_GROUP: 'Heat::Ungrouped' + rpc_api.SOFTWARE_CONFIG_GROUP: self.properties[self.GROUP] } sc = self.rpc_client().create_software_config(self.context, **props) self.resource_id_set(sc[rpc_api.SOFTWARE_CONFIG_ID]) diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/heat/none_resource.py heat-14.0.0/heat/engine/resources/openstack/heat/none_resource.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/heat/none_resource.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/openstack/heat/none_resource.py 2020-05-13 10:48:27.000000000 +0000 @@ -11,7 +11,6 @@ # License for the specific language governing permissions and limitations # under the License. -import six import uuid from heat.engine import properties @@ -47,7 +46,7 @@ self.translate_properties(self.properties, client_resolve) def handle_create(self): - self.resource_id_set(six.text_type(uuid.uuid4())) + self.resource_id_set(str(uuid.uuid4())) # set is_placeholder flag when resource trying to replace original # resource with a placeholder resource. self.data_set(self.IS_PLACEHOLDER, 'True') diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/heat/random_string.py heat-14.0.0/heat/engine/resources/openstack/heat/random_string.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/heat/random_string.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/openstack/heat/random_string.py 2020-05-13 10:48:27.000000000 +0000 @@ -11,8 +11,6 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from heat.common import exception from heat.common.i18n import _ from heat.common import password_gen @@ -235,7 +233,7 @@ if self.resource_id is not None: return self.data().get('value') else: - return six.text_type(self.name) + return str(self.name) def resource_mapping(): diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/heat/remote_stack.py heat-14.0.0/heat/engine/resources/openstack/heat/remote_stack.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/heat/remote_stack.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/openstack/heat/remote_stack.py 2020-05-13 10:48:27.000000000 +0000 @@ -13,7 +13,6 @@ from oslo_log import log as logging from oslo_serialization import jsonutils -import six import tempfile from heat.common import auth_plugin @@ -49,7 +48,7 @@ try: self._cacert_temp_file = tempfile.NamedTemporaryFile() self._cacert_temp_file.write( - six.text_type(self._cacert).encode('utf-8')) + str(self._cacert).encode('utf-8')) # Add seek func to make sure the writen context will flush to # tempfile with python 2.7. we can use flush() for python 2.7 # but not 3.5. @@ -266,7 +265,7 @@ location = "remote cloud" else: location = 'region "%s"' % self._region_name - exc_info = dict(location=location, exc=six.text_type(ex)) + exc_info = dict(location=location, exc=str(ex)) msg = _('Cannot establish connection to Heat endpoint at ' '%(location)s due to "%(exc)s"') % exc_info raise exception.StackValidationFailed(message=msg) @@ -287,7 +286,7 @@ location = "remote cloud" else: location = 'region "%s"' % self._region_name - exc_info = dict(location=location, exc=six.text_type(ex)) + exc_info = dict(location=location, exc=str(ex)) msg = _('Failed validating stack template using Heat endpoint at ' '%(location)s due to "%(exc)s"') % exc_info raise exception.StackValidationFailed(message=msg) diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/heat/resource_chain.py heat-14.0.0/heat/engine/resources/openstack/heat/resource_chain.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/heat/resource_chain.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/openstack/heat/resource_chain.py 2020-05-13 10:48:27.000000000 +0000 @@ -12,7 +12,6 @@ # under the License. import functools -import six from oslo_log import log as logging @@ -155,7 +154,7 @@ return {} def _attribute_output_name(self, *attr_path): - return ', '.join(six.text_type(a) for a in attr_path) + return ', '.join(str(a) for a in attr_path) def get_attribute(self, key, *path): if key == self.ATTR_ATTRIBUTES and not path: @@ -198,7 +197,7 @@ def _nested_output_defns(self, resource_names, get_attr_fn, get_res_fn): for attr in self.referenced_attrs(): - if isinstance(attr, six.string_types): + if isinstance(attr, str): key, path = attr, [] else: key, path = attr[0], list(attr[1:]) @@ -227,7 +226,7 @@ @staticmethod def _resource_names(resource_types): """Returns a list of unique resource names to create.""" - return [six.text_type(i) for i, t in enumerate(resource_types)] + return [str(i) for i, t in enumerate(resource_types)] def _build_resource_definition(self, resource_name, resource_type, depends_on=None): diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/heat/resource_group.py heat-14.0.0/heat/engine/resources/openstack/heat/resource_group.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/heat/resource_group.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/openstack/heat/resource_group.py 2020-05-13 10:48:27.000000000 +0000 @@ -15,7 +15,6 @@ import copy import functools import itertools -import six from oslo_log import log as logging @@ -306,7 +305,7 @@ first_name = next(self._resource_names()) test_tmpl = self._assemble_nested([first_name], include_all=True) - res_def = next(six.itervalues(test_tmpl.resource_definitions(None))) + res_def = next(iter(test_tmpl.resource_definitions(None).values())) # make sure we can resolve the nested resource type self.stack.env.get_class_to_instantiate(res_def.resource_type) @@ -339,12 +338,12 @@ if self.REMOVAL_RSRC_LIST in r: # Tolerate string or int list values for n in r[self.REMOVAL_RSRC_LIST]: - str_n = six.text_type(n) + str_n = str(n) if (str_n in current_blacklist or self.resource_id is None or str_n in insp.member_names(include_failed=True)): yield str_n - elif isinstance(n, six.string_types): + elif isinstance(n, str): try: refids = self.get_output(self.REFS_MAP) except (exception.NotFound, @@ -399,9 +398,9 @@ def is_blacklisted(name): return name in name_blacklist - candidates = six.moves.map(six.text_type, itertools.count()) + candidates = map(str, itertools.count()) - return itertools.islice(six.moves.filterfalse(is_blacklisted, + return itertools.islice(itertools.filterfalse(is_blacklisted, candidates), size) @@ -488,7 +487,7 @@ def _attribute_output_name(self, *attr_path): if attr_path[0] == self.REFS: return self.REFS - return ', '.join(six.text_type(a) for a in attr_path) + return ', '.join(str(a) for a in attr_path) def get_attribute(self, key, *path): if key == self.REMOVED_RSRC_LIST: @@ -546,7 +545,7 @@ def _nested_output_defns(self, resource_names, get_attr_fn, get_res_fn): for attr in self.referenced_attrs(): - if isinstance(attr, six.string_types): + if isinstance(attr, str): key, path = attr, [] else: key, path = attr[0], list(attr[1:]) @@ -611,7 +610,7 @@ if isinstance(snippet, collections.Mapping): return dict((k, ignore_param_resolve(v)) for k, v in snippet.items()) - elif (not isinstance(snippet, six.string_types) and + elif (not isinstance(snippet, str) and isinstance(snippet, collections.Iterable)): return [ignore_param_resolve(v) for v in snippet] @@ -639,7 +638,7 @@ def recurse(x): return self._handle_repl_val(res_name, x) - if isinstance(val, six.string_types): + if isinstance(val, str): return val.replace(repl_var, res_name) elif isinstance(val, collections.Mapping): return {k: recurse(v) for k, v in val.items()} @@ -706,7 +705,7 @@ old_resources = sorted(valid_resources, key=replace_priority) existing_names = set(n for n, d in valid_resources) - new_names = six.moves.filterfalse(lambda n: n in existing_names, + new_names = itertools.filterfalse(lambda n: n in existing_names, names) res_def = self.get_resource_def(include_all) definitions = scl_template.member_definitions( diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/heat/scaling_policy.py heat-14.0.0/heat/engine/resources/openstack/heat/scaling_policy.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/heat/scaling_policy.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/openstack/heat/scaling_policy.py 2020-05-13 10:48:27.000000000 +0000 @@ -12,7 +12,6 @@ # under the License. from oslo_log import log as logging -import six from heat.common import exception from heat.common.i18n import _ @@ -186,9 +185,9 @@ if self.resource_id is None: return if name == self.ALARM_URL: - return six.text_type(self._get_ec2_signed_url()) + return str(self._get_ec2_signed_url()) elif name == self.SIGNAL_URL: - return six.text_type(self._get_heat_signal_url()) + return str(self._get_heat_signal_url()) def resource_mapping(): diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/heat/software_deployment.py heat-14.0.0/heat/engine/resources/openstack/heat/software_deployment.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/heat/software_deployment.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/openstack/heat/software_deployment.py 2020-05-13 10:48:27.000000000 +0000 @@ -12,8 +12,7 @@ # under the License. import copy -import six -from six import itertools +import itertools import uuid from oslo_config import cfg @@ -749,7 +748,7 @@ def _nested_output_defns(self, resource_names, get_attr_fn, get_res_fn): for attr in self.referenced_attrs(): - key = attr if isinstance(attr, six.string_types) else attr[0] + key = attr if isinstance(attr, str) else attr[0] n_attr = self._member_attribute_name(key) output_name = self._attribute_output_name(self.ATTR_ATTRIBUTES, n_attr) diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/heat/structured_config.py heat-14.0.0/heat/engine/resources/openstack/heat/structured_config.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/heat/structured_config.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/openstack/heat/structured_config.py 2020-05-13 10:48:27.000000000 +0000 @@ -15,8 +15,6 @@ import copy import functools -import six - from heat.common import exception from heat.common.i18n import _ from heat.engine import constraints @@ -150,8 +148,8 @@ def get_input_key_arg(snippet, input_key): if len(snippet) != 1: return None - fn_name, fn_arg = next(six.iteritems(snippet)) - if (fn_name == input_key and isinstance(fn_arg, six.string_types)): + fn_name, fn_arg = next(iter(snippet.items())) + if (fn_name == input_key and isinstance(fn_arg, str)): return fn_arg @staticmethod @@ -175,8 +173,8 @@ check_input_val ) - return dict((k, parse(v)) for k, v in six.iteritems(snippet)) - elif (not isinstance(snippet, six.string_types) and + return dict((k, parse(v)) for k, v in snippet.items()) + elif (not isinstance(snippet, str) and isinstance(snippet, collections.Iterable)): return [parse(v) for v in snippet] else: diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/heat/swiftsignal.py heat-14.0.0/heat/engine/resources/openstack/heat/swiftsignal.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/heat/swiftsignal.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/openstack/heat/swiftsignal.py 2020-05-13 10:48:27.000000000 +0000 @@ -14,8 +14,7 @@ from oslo_log import log as logging from oslo_serialization import jsonutils from oslo_utils import timeutils -import six -from six.moves.urllib import parse +from urllib import parse from heat.common import exception from heat.common.i18n import _ @@ -344,7 +343,7 @@ def _resolve_attribute(self, key): if key == self.DATA: - return six.text_type(jsonutils.dumps(self.get_data())) + return str(jsonutils.dumps(self.get_data())) def resource_mapping(): diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/heat/test_resource.py heat-14.0.0/heat/engine/resources/openstack/heat/test_resource.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/heat/test_resource.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/openstack/heat/test_resource.py 2020-05-13 10:48:27.000000000 +0000 @@ -14,7 +14,6 @@ import datetime import eventlet from oslo_utils import timeutils -import six from heat.common.i18n import _ from heat.engine import attributes @@ -218,12 +217,12 @@ obj.get(entity_id) except Exception as exc: LOG.debug('%s.%s(%s) %s' % (client_name, self.entity, - entity_id, six.text_type(exc))) + entity_id, str(exc))) else: # just sleep some more eventlet.sleep(1) - if isinstance(started_at, six.string_types): + if isinstance(started_at, str): started_at = timeutils.parse_isotime(started_at) started_at = timeutils.normalize_time(started_at) diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/heat/wait_condition.py heat-14.0.0/heat/engine/resources/openstack/heat/wait_condition.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/heat/wait_condition.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/openstack/heat/wait_condition.py 2020-05-13 10:48:27.000000000 +0000 @@ -14,7 +14,6 @@ from oslo_log import log as logging from oslo_serialization import jsonutils from oslo_utils import timeutils -import six from heat.common.i18n import _ from heat.engine import attributes @@ -158,7 +157,7 @@ 'key': key, 'res': res}) - return six.text_type(jsonutils.dumps(res)) + return str(jsonutils.dumps(res)) def resource_mapping(): diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/ironic/port.py heat-14.0.0/heat/engine/resources/openstack/ironic/port.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/ironic/port.py 1970-01-01 00:00:00.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/openstack/ironic/port.py 2020-05-13 10:48:27.000000000 +0000 @@ -0,0 +1,240 @@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from heat.common import exception +from heat.common.i18n import _ +from heat.engine import attributes +from heat.engine import constraints +from heat.engine import properties +from heat.engine import resource +from heat.engine import support +from heat.engine import translation + + +class Port(resource.Resource): + """A resource that creates a ironic port. + + Node UUID and physical hardware address for the Port (MAC address in + most cases) are needed (all Ports must be associated to a Node when + created). + """ + + support_status = support.SupportStatus(version='13.0.0') + + default_client_name = 'ironic' + + entity = 'port' + + PROPERTIES = ( + NODE, ADDRESS, PORTGROUP, LOCAL_LINK_CONNECTION, PXE_ENABLED, + PHYSICAL_NETWORK, EXTRA, IS_SMARTNIC, + ) = ( + 'node', 'address', 'portgroup', 'local_link_connection', 'pxe_enabled', + 'physical_network', 'extra', 'is_smartnic', + ) + PROPERTIES_MIN_SUPPORT_VERSION = ( + (PXE_ENABLED, 1.19), + (LOCAL_LINK_CONNECTION, 1.191), + (PORTGROUP, 1.24), (PHYSICAL_NETWORK, 1.34), + (IS_SMARTNIC, 1.53) + ) + + ATTRIBUTES = ( + ADDRESS_ATTR, NODE_UUID_ATTR, PORTGROUP_UUID_ATTR, + LOCAL_LINK_CONNECTION_ATTR, PXE_ENABLED_ATTR, PHYSICAL_NETWORK_ATTR, + INTERNAL_INFO_ATTR, EXTRA_ATTR, IS_SMARTNIC_ATTR, + ) = ( + 'address', 'node_uuid', 'portgroup_uuid', + 'local_link_connection', 'pxe_enabled', 'physical_network', + 'internal_info', 'extra', 'is_smartnic', + ) + attributes_schema = { + ADDRESS_ATTR: attributes.Schema( + _('Physical hardware address of this network Port, typically the ' + 'hardware MAC address.'), + type=attributes.Schema.STRING + ), + NODE_UUID_ATTR: attributes.Schema( + _('UUID of the Node this resource belongs to.'), + type=attributes.Schema.STRING + ), + PORTGROUP_UUID_ATTR: attributes.Schema( + _('UUID of the Portgroup this resource belongs to.'), + type=attributes.Schema.STRING + ), + LOCAL_LINK_CONNECTION_ATTR: attributes.Schema( + _('The Port binding profile. If specified, must contain switch_id ' + '(only a MAC address or an OpenFlow based datapath_id of the ' + 'switch are accepted in this field) and port_id (identifier of ' + 'the physical port on the switch to which node\'s port is ' + 'connected to) fields. switch_info is an optional string field ' + 'to be used to store any vendor-specific information.'), + type=attributes.Schema.MAP + ), + PXE_ENABLED_ATTR: attributes.Schema( + _('Indicates whether PXE is enabled or disabled on the Port.'), + type=attributes.Schema.BOOLEAN + ), + PHYSICAL_NETWORK_ATTR: attributes.Schema( + _('The name of the physical network to which a port is connected. ' + 'May be empty.'), + type=attributes.Schema.STRING + ), + INTERNAL_INFO_ATTR: attributes.Schema( + _('Internal metadata set and stored by the Port. This field is ' + 'read-only.'), + type=attributes.Schema.MAP + ), + EXTRA_ATTR: attributes.Schema( + _('A set of one or more arbitrary metadata key and value pairs.'), + type=attributes.Schema.MAP + ), + IS_SMARTNIC_ATTR: attributes.Schema( + _('Indicates whether the Port is a Smart NIC port.'), + type=attributes.Schema.BOOLEAN + )} + + properties_schema = { + NODE: properties.Schema( + properties.Schema.STRING, + _('UUID or name of the Node this resource belongs to.'), + constraints=[ + constraints.CustomConstraint('ironic.node') + ], + required=True, + update_allowed=True + ), + ADDRESS: properties.Schema( + properties.Schema.STRING, + _('Physical hardware address of this network Port, typically the ' + 'hardware MAC address.'), + required=True, + update_allowed=True + ), + PORTGROUP: properties.Schema( + properties.Schema.STRING, + _('UUID or name of the Portgroup this resource belongs to.'), + constraints=[ + constraints.CustomConstraint('ironic.portgroup') + ], + update_allowed=True, + ), + LOCAL_LINK_CONNECTION: properties.Schema( + properties.Schema.MAP, + _('The Port binding profile. If specified, must contain switch_id ' + '(only a MAC address or an OpenFlow based datapath_id of the ' + 'switch are accepted in this field) and port_id (identifier of ' + 'the physical port on the switch to which node\'s port is ' + 'connected to) fields. switch_info is an optional string field ' + 'to be used to store any vendor-specific information.'), + update_allowed=True, + ), + PXE_ENABLED: properties.Schema( + properties.Schema.BOOLEAN, + _('Indicates whether PXE is enabled or disabled on the Port.'), + update_allowed=True, + ), + PHYSICAL_NETWORK: properties.Schema( + properties.Schema.STRING, + _('The name of the physical network to which a port is connected. ' + 'May be empty.'), + update_allowed=True, + ), + EXTRA: properties.Schema( + properties.Schema.MAP, + _('A set of one or more arbitrary metadata key and value pairs.'), + update_allowed=True, + ), + IS_SMARTNIC: properties.Schema( + properties.Schema.BOOLEAN, + _('Indicates whether the Port is a Smart NIC port.'), + update_allowed=True, + ) + } + + def translation_rules(self, props): + return [ + translation.TranslationRule( + props, + translation.TranslationRule.RESOLVE, + [self.NODE], + client_plugin=self.client_plugin('ironic'), + finder='get_node'), + translation.TranslationRule( + props, + translation.TranslationRule.RESOLVE, + [self.PORTGROUP], + client_plugin=self.client_plugin('ironic'), + finder='get_portgroup'), + ] + + def _resolve_attribute(self, name): + if self.resource_id is None: + return + port = self.client().port.get(self.resource_id) + return getattr(port, name, None) + + def _check_supported(self, properties): + # TODO(ricolin) Implement version support in property schema. + for k, v in self.PROPERTIES_MIN_SUPPORT_VERSION: + if k in properties and properties[k] is not None and ( + self.client_plugin().max_microversion < v + ): + raise exception.NotSupported( + feature="OS::Ironic::Port with %s property" % k) + + def handle_create(self): + args = dict(self.properties.items()) + self._check_supported(args) + args['node_uuid'] = args.pop(self.NODE) + if self.PORTGROUP in args: + args['portgroup_uuid'] = args.pop(self.PORTGROUP) + port = self.client().port.create(**args) + self.resource_id_set(port.uuid) + return port.uuid + + def check_create_complete(self, id): + try: + self.client().port.get(id) + except Exception as exc: + self.client_plugin().ignore_not_found(exc) + return False + return True + + def handle_update(self, json_snippet, tmpl_diff, prop_diff): + if prop_diff: + self._check_supported(prop_diff) + if self.NODE in prop_diff: + prop_diff['node_uuid'] = prop_diff.pop(self.NODE) + if self.PORTGROUP in prop_diff: + prop_diff['portgroup_uuid'] = prop_diff.pop(self.PORTGROUP) + patch = [{'op': 'replace', 'path': '/' + k, 'value': v} + for k, v in prop_diff.items()] + self.client().port.update(self.resource_id, patch) + return self.resource_id, prop_diff + + def check_delete_complete(self, id): + if not id: + return True + try: + self.client().port.get(id) + except Exception as exc: + self.client_plugin().ignore_not_found(exc) + return True + return False + + +def resource_mapping(): + return { + 'OS::Ironic::Port': Port, + } diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/keystone/region.py heat-14.0.0/heat/engine/resources/openstack/keystone/region.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/keystone/region.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/openstack/keystone/region.py 2020-05-13 10:48:27.000000000 +0000 @@ -11,7 +11,7 @@ # License for the specific language governing permissions and limitations # under the License. -from six.moves.urllib import parse +from urllib import parse from heat.common.i18n import _ from heat.engine import constraints diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/magnum/bay.py heat-14.0.0/heat/engine/resources/openstack/magnum/bay.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/magnum/bay.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/openstack/magnum/bay.py 2020-05-13 10:48:27.000000000 +0000 @@ -11,8 +11,6 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from heat.common import exception from heat.common.i18n import _ from heat.engine import constraints @@ -129,7 +127,7 @@ def handle_update(self, json_snippet, tmpl_diff, prop_diff): if prop_diff: patch = [{'op': 'replace', 'path': '/' + k, 'value': v} - for k, v in six.iteritems(prop_diff)] + for k, v in prop_diff.items()] self.client().bays.update(self.resource_id, patch) return self.resource_id diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/magnum/cluster.py heat-14.0.0/heat/engine/resources/openstack/magnum/cluster.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/magnum/cluster.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/openstack/magnum/cluster.py 2020-05-13 10:48:27.000000000 +0000 @@ -11,8 +11,6 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from heat.common import exception from heat.common.i18n import _ from heat.engine import attributes @@ -218,7 +216,7 @@ def handle_update(self, json_snippet, tmpl_diff, prop_diff): if prop_diff: patch = [{'op': 'replace', 'path': '/' + k, 'value': v} - for k, v in six.iteritems(prop_diff)] + for k, v in prop_diff.items()] self.client().clusters.update(self.resource_id, patch) return self.resource_id diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/magnum/cluster_template.py heat-14.0.0/heat/engine/resources/openstack/magnum/cluster_template.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/magnum/cluster_template.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/openstack/magnum/cluster_template.py 2020-05-13 10:48:27.000000000 +0000 @@ -11,8 +11,6 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from heat.common import exception from heat.common.i18n import _ from heat.engine import constraints @@ -290,7 +288,7 @@ def handle_update(self, json_snippet, tmpl_diff, prop_diff): if prop_diff: patch = [{'op': 'replace', 'path': '/' + k, 'value': v} - for k, v in six.iteritems(prop_diff)] + for k, v in prop_diff.items()] self.client().cluster_templates.update(self.resource_id, patch) return self.resource_id diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/manila/share.py heat-14.0.0/heat/engine/resources/openstack/manila/share.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/manila/share.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/openstack/manila/share.py 2020-05-13 10:48:27.000000000 +0000 @@ -13,7 +13,6 @@ from oslo_log import log as logging from oslo_utils import encodeutils -import six from heat.common import exception from heat.common.i18n import _ @@ -197,7 +196,7 @@ if self.resource_id is None: return share = self._request_share() - return six.text_type(getattr(share, name)) + return str(getattr(share, name)) def handle_create(self): # Request IDs of entities from manila @@ -345,7 +344,7 @@ result[self.ACCESS_RULES] = [] for rule in rules: result[self.ACCESS_RULES].append( - {(k, v) for (k, v) in six.iteritems(rule) + {(k, v) for (k, v) in rule.items() if k in self._ACCESS_RULE_PROPERTIES}) return result diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/mistral/external_resource.py heat-14.0.0/heat/engine/resources/openstack/mistral/external_resource.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/mistral/external_resource.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/openstack/mistral/external_resource.py 2020-05-13 10:48:27.000000000 +0000 @@ -13,7 +13,6 @@ from oslo_log import log as logging from oslo_serialization import jsonutils -import six from heat.common import exception from heat.common.i18n import _ @@ -212,7 +211,7 @@ LOG.debug('ExternalResource id set to %(rid)s from Mistral ' 'execution %(eid)s output' % {'eid': execution_id, 'rid': rsrc_id}) - self.resource_id_set(six.text_type(rsrc_id)[:255]) + self.resource_id_set(str(rsrc_id)[:255]) return success def _resolve_attribute(self, name): diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/mistral/workflow.py heat-14.0.0/heat/engine/resources/openstack/mistral/workflow.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/mistral/workflow.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/openstack/mistral/workflow.py 2020-05-13 10:48:27.000000000 +0000 @@ -442,11 +442,11 @@ error=_('Signal data error'), message=message) if params is not None and not isinstance(params, dict): - message = (_('Params must be a map, find a ' - '%s') % type(params)) - raise exception.StackValidationFailed( - error=_('Signal data error'), - message=message) + message = (_('Params must be a map, find a ' + '%s') % type(params)) + raise exception.StackValidationFailed( + error=_('Signal data error'), + message=message) def validate(self): super(Workflow, self).validate() diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/neutron/lbaas/pool.py heat-14.0.0/heat/engine/resources/openstack/neutron/lbaas/pool.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/neutron/lbaas/pool.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/openstack/neutron/lbaas/pool.py 2020-05-13 10:48:27.000000000 +0000 @@ -197,8 +197,8 @@ if (self.properties[self.LISTENER] is None and self.properties[self.LOADBALANCER] is None): - raise exception.PropertyUnspecifiedError(self.LISTENER, - self.LOADBALANCER) + raise exception.PropertyUnspecifiedError(self.LISTENER, + self.LOADBALANCER) if self.properties[self.SESSION_PERSISTENCE] is not None: session_p = self.properties[self.SESSION_PERSISTENCE] diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/neutron/qos.py heat-14.0.0/heat/engine/resources/openstack/neutron/qos.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/neutron/qos.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/openstack/neutron/qos.py 2020-05-13 10:48:27.000000000 +0000 @@ -292,9 +292,96 @@ return [self.resource_id, self.policy_id] +class QoSMinimumBandwidthRule(QoSRule): + """A resource for guaranteeing bandwidth. + + This rule can be associated with a QoS policy, and then the policy + can be used by a neutron port to provide guaranteed bandwidth QoS + capabilities. + + Depending on drivers the guarantee may be enforced on two levels. + First when a server is placed (scheduled) on physical infrastructure + and/or second in the data plane of the physical hypervisor. For details + please see Neutron documentation: + + https://docs.openstack.org/neutron/latest/admin/config-qos-min-bw.html + + The default policy usage of this resource is limited to + administrators only. + """ + + entity = 'minimum_bandwidth_rule' + + required_service_extension = 'qos-bw-minimum-ingress' + + support_status = support.SupportStatus( + status=support.SUPPORTED, + version='14.0.0', + ) + + PROPERTIES = ( + MIN_BANDWIDTH, DIRECTION + ) = ( + 'min_kbps', 'direction' + ) + + properties_schema = { + MIN_BANDWIDTH: properties.Schema( + properties.Schema.INTEGER, + _('Min bandwidth in kbps.'), + required=True, + update_allowed=True, + constraints=[ + constraints.Range(min=0), + ], + ), + DIRECTION: properties.Schema( + properties.Schema.STRING, + _('Traffic direction from the point of view of the port.'), + update_allowed=True, + constraints=[ + constraints.AllowedValues(['egress', 'ingress']), + ], + default='egress', + ), + } + + properties_schema.update(QoSRule.properties_schema) + + def handle_create(self): + props = self.prepare_properties(self.properties, + self.physical_resource_name()) + props.pop(self.POLICY) + + rule = self.client().create_minimum_bandwidth_rule( + self.policy_id, + {'minimum_bandwidth_rule': props})['minimum_bandwidth_rule'] + + self.resource_id_set(rule['id']) + + def handle_delete(self): + if self.resource_id is None: + return + + with self.client_plugin().ignore_not_found: + self.client().delete_minimum_bandwidth_rule( + self.resource_id, self.policy_id) + + def handle_update(self, json_snippet, tmpl_diff, prop_diff): + if prop_diff: + self.client().update_minimum_bandwidth_rule( + self.resource_id, + self.policy_id, + {'minimum_bandwidth_rule': prop_diff}) + + def _res_get_args(self): + return [self.resource_id, self.policy_id] + + def resource_mapping(): return { 'OS::Neutron::QoSPolicy': QoSPolicy, 'OS::Neutron::QoSBandwidthLimitRule': QoSBandwidthLimitRule, - 'OS::Neutron::QoSDscpMarkingRule': QoSDscpMarkingRule + 'OS::Neutron::QoSDscpMarkingRule': QoSDscpMarkingRule, + 'OS::Neutron::QoSMinimumBandwidthRule': QoSMinimumBandwidthRule, } diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/neutron/sfc/flow_classifier.py heat-14.0.0/heat/engine/resources/openstack/neutron/sfc/flow_classifier.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/neutron/sfc/flow_classifier.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/openstack/neutron/sfc/flow_classifier.py 2020-05-13 10:48:27.000000000 +0000 @@ -181,8 +181,8 @@ if self.resource_id is None: return with self.client_plugin().ignore_not_found: - self.client_plugin().delete_ext_resource('flow_classifier', - self.resource_id) + self.client_plugin().delete_ext_resource('flow_classifier', + self.resource_id) def resource_mapping(): diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/neutron/sfc/port_pair.py heat-14.0.0/heat/engine/resources/openstack/neutron/sfc/port_pair.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/neutron/sfc/port_pair.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/openstack/neutron/sfc/port_pair.py 2020-05-13 10:48:27.000000000 +0000 @@ -118,8 +118,8 @@ if self.resource_id is None: return with self.client_plugin().ignore_not_found: - self.client_plugin().delete_ext_resource('port_pair', - self.resource_id) + self.client_plugin().delete_ext_resource('port_pair', + self.resource_id) def resource_mapping(): diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/neutron/taas/tap_flow.py heat-14.0.0/heat/engine/resources/openstack/neutron/taas/tap_flow.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/neutron/taas/tap_flow.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/openstack/neutron/taas/tap_flow.py 2020-05-13 10:48:27.000000000 +0000 @@ -135,8 +135,8 @@ if self.resource_id is None: return with self.client_plugin().ignore_not_found: - self.client_plugin().delete_ext_resource('tap_flow', - self.resource_id) + self.client_plugin().delete_ext_resource('tap_flow', + self.resource_id) def check_create_complete(self, data): return self.client_plugin().check_ext_resource_status( diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/neutron/taas/tap_service.py heat-14.0.0/heat/engine/resources/openstack/neutron/taas/tap_service.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/neutron/taas/tap_service.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/openstack/neutron/taas/tap_service.py 2020-05-13 10:48:27.000000000 +0000 @@ -99,8 +99,8 @@ if self.resource_id is None: return with self.client_plugin().ignore_not_found: - self.client_plugin().delete_ext_resource('tap_service', - self.resource_id) + self.client_plugin().delete_ext_resource('tap_service', + self.resource_id) def check_create_complete(self, data): return self.client_plugin().check_ext_resource_status( diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/octavia/pool.py heat-14.0.0/heat/engine/resources/openstack/octavia/pool.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/resources/openstack/octavia/pool.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/resources/openstack/octavia/pool.py 2020-05-13 10:48:27.000000000 +0000 @@ -188,8 +188,8 @@ super(Pool, self).validate() if (self.properties[self.LISTENER] is None and self.properties[self.LOADBALANCER] is None): - raise exception.PropertyUnspecifiedError(self.LISTENER, - self.LOADBALANCER) + raise exception.PropertyUnspecifiedError(self.LISTENER, + self.LOADBALANCER) if self.properties[self.SESSION_PERSISTENCE] is not None: session_p = self.properties[self.SESSION_PERSISTENCE] diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/rsrc_defn.py heat-14.0.0/heat/engine/rsrc_defn.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/rsrc_defn.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/rsrc_defn.py 2020-05-13 10:48:27.000000000 +0000 @@ -18,7 +18,6 @@ import six from heat.common import exception -from heat.common.i18n import repr_wrapper from heat.engine import function from heat.engine import properties @@ -37,7 +36,6 @@ ) -@repr_wrapper class ResourceDefinition(object): """A definition of a resource, independent of any template format.""" diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/scheduler.py heat-14.0.0/heat/engine/scheduler.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/scheduler.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/scheduler.py 2020-05-13 10:48:27.000000000 +0000 @@ -21,7 +21,6 @@ import six from heat.common.i18n import _ -from heat.common.i18n import repr_wrapper from heat.common import timeutils LOG = logging.getLogger(__name__) @@ -296,7 +295,7 @@ return self.__nonzero__() -def wrappertask(task): +def wrappertask(task): # noqa: C901 """Decorator for a task that needs to drive a subtask. This is essentially a replacement for the Python 3-only "yield from" @@ -365,7 +364,6 @@ return wrapper -@repr_wrapper class DependencyTaskGroup(object): """Task which manages group of subtasks that have ordering dependencies.""" diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/stack.py heat-14.0.0/heat/engine/stack.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/stack.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/stack.py 2020-05-13 10:48:27.000000000 +0000 @@ -716,9 +716,9 @@ self.user_creds_id = new_creds.id if self.convergence: - # create a traversal ID - self.current_traversal = uuidutils.generate_uuid() - s['current_traversal'] = self.current_traversal + # create a traversal ID + self.current_traversal = uuidutils.generate_uuid() + s['current_traversal'] = self.current_traversal new_s = stack_object.Stack.create(self.context, s) self.id = new_s.id @@ -1872,7 +1872,7 @@ else: self.clients.client('keystone').delete_trust( trust_id) - except Exception as ex: + except Exception: # We want the admin to be able to delete the stack # Do not FAIL a delete when we cannot delete a trust. # We already carry through and delete the credentials diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/support.py heat-14.0.0/heat/engine/support.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/support.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/support.py 2020-05-13 10:48:27.000000000 +0000 @@ -54,11 +54,11 @@ self.previous_status = None def to_dict(self): - return {'status': self.status, - 'message': self.message, - 'version': self.version, - 'previous_status': self.previous_status.to_dict() - if self.previous_status is not None else None} + return {'status': self.status, + 'message': self.message, + 'version': self.version, + 'previous_status': self.previous_status.to_dict() + if self.previous_status is not None else None} def is_substituted(self, substitute_class): if self.substitute_class is None: diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/update.py heat-14.0.0/heat/engine/update.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/engine/update.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/engine/update.py 2020-05-13 10:48:27.000000000 +0000 @@ -15,7 +15,6 @@ import six from heat.common import exception -from heat.common.i18n import repr_wrapper from heat.engine import dependencies from heat.engine import resource from heat.engine import scheduler @@ -25,7 +24,6 @@ LOG = logging.getLogger(__name__) -@repr_wrapper class StackUpdate(object): """A Task to perform the update of an existing stack to a new template.""" diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/hacking/checks.py heat-14.0.0/heat/hacking/checks.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/hacking/checks.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/hacking/checks.py 2020-05-13 10:48:27.000000000 +0000 @@ -15,6 +15,8 @@ import re +from hacking import core + """ Guidelines for writing new hacking checks @@ -31,6 +33,7 @@ """ +@core.flake8ext def no_log_warn(logical_line): """Disallow 'LOG.warn(' @@ -42,6 +45,7 @@ yield(0, 'Heat301 Use LOG.warning() rather than LOG.warn()') +@core.flake8ext def check_python3_no_iteritems(logical_line): msg = ("Heat302: Use dict.items() instead of dict.iteritems().") @@ -49,6 +53,7 @@ yield(0, msg) +@core.flake8ext def check_python3_no_iterkeys(logical_line): msg = ("Heat303: Use dict.keys() instead of dict.iterkeys().") @@ -56,15 +61,9 @@ yield(0, msg) +@core.flake8ext def check_python3_no_itervalues(logical_line): msg = ("Heat304: Use dict.values() instead of dict.itervalues().") if re.search(r".*\.itervalues\(\)", logical_line): yield(0, msg) - - -def factory(register): - register(no_log_warn) - register(check_python3_no_iteritems) - register(check_python3_no_iterkeys) - register(check_python3_no_itervalues) diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/locale/de/LC_MESSAGES/heat.po heat-14.0.0/heat/locale/de/LC_MESSAGES/heat.po --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/locale/de/LC_MESSAGES/heat.po 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/locale/de/LC_MESSAGES/heat.po 2020-05-13 10:48:27.000000000 +0000 @@ -9,15 +9,16 @@ # Robert Simai , 2016. #zanata # Frank Kloeker , 2018. #zanata # Andreas Jaeger , 2019. #zanata +# Andreas Jaeger , 2020. #zanata msgid "" msgstr "" "Project-Id-Version: heat VERSION\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" -"POT-Creation-Date: 2019-12-20 05:37+0000\n" +"POT-Creation-Date: 2020-04-24 12:33+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2019-10-01 06:39+0000\n" +"PO-Revision-Date: 2020-04-25 08:04+0000\n" "Last-Translator: Andreas Jaeger \n" "Language: de\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" @@ -372,6 +373,11 @@ msgstr "%(type)s nicht im gültigen Format: %(error)s" #, python-format +msgid "%(value)s is out of range (min: %(min)s, max: %(max)s)" +msgstr "" +"%(value)s ist außerhalb des gültigen Bereichs (min: %(min)s, max: %(max)s)" + +#, python-format msgid "%s Key Name must be a string" msgstr "%s Schlüsselname muss eine Zeichenfolge sein" @@ -10005,6 +10011,12 @@ msgstr "" "Schlüsselersetzung %s kollidiert mit einem Schlüssel in der Ausgabekarte" +#, python-format +msgid "length (%(length)d) is out of range (min: %(min)s, max: %(max)s)" +msgstr "" +"Länge (%(length)d) ist außerhalb des gültigen Bereichs (min: %(min)s, max: " +"%(max)s)" + msgid "limit cannot be less than 4" msgstr "Limit kann nicht weniger als 4 sein" diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/objects/resource.py heat-14.0.0/heat/objects/resource.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/objects/resource.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/objects/resource.py 2020-05-13 10:48:27.000000000 +0000 @@ -41,7 +41,7 @@ def retry_on_conflict(func): wrapper = tenacity.retry( stop=tenacity.stop_after_attempt(11), - wait=tenacity.wait_random(max=2), + wait=tenacity.wait_random_exponential(multiplier=0.5, max=60), retry=tenacity.retry_if_exception_type( exception.ConcurrentTransaction), reraise=True) diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/policies/resource_types.py heat-14.0.0/heat/policies/resource_types.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/policies/resource_types.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/policies/resource_types.py 2020-05-13 10:48:27.000000000 +0000 @@ -51,6 +51,12 @@ name=POLICY_ROOT % 'OS::Neutron::QoSBandwidthLimitRule', check_str=base.RULE_PROJECT_ADMIN), policy.RuleDefault( + name=POLICY_ROOT % 'OS::Neutron::QoSDscpMarkingRule', + check_str=base.RULE_PROJECT_ADMIN), + policy.RuleDefault( + name=POLICY_ROOT % 'OS::Neutron::QoSMinimumBandwidthRule', + check_str=base.RULE_PROJECT_ADMIN), + policy.RuleDefault( name=POLICY_ROOT % 'OS::Neutron::Segment', check_str=base.RULE_PROJECT_ADMIN), policy.RuleDefault( diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/tests/aws/test_instance.py heat-14.0.0/heat/tests/aws/test_instance.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/tests/aws/test_instance.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/tests/aws/test_instance.py 2020-05-13 10:48:27.000000000 +0000 @@ -1385,7 +1385,8 @@ self.nclient.create_port.assert_called_with({'port': props}) if not all_uuids: - self.nclient.list_security_groups.assert_called_once_with() + self.nclient.list_security_groups.assert_called_once_with( + project_id=mock.ANY) def _get_fake_properties(self, sg='one'): fake_groups_list = { diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/tests/clients/test_ironic_client.py heat-14.0.0/heat/tests/clients/test_ironic_client.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/tests/clients/test_ironic_client.py 1970-01-01 00:00:00.000000000 +0000 +++ heat-14.0.0/heat/tests/clients/test_ironic_client.py 2020-05-13 10:48:27.000000000 +0000 @@ -0,0 +1,77 @@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from ironicclient import exceptions as ic_exc +import mock + +from heat.engine.clients.os import ironic as ic +from heat.tests import common +from heat.tests import utils + + +class IronicClientPluginTest(common.HeatTestCase): + + def test_create(self): + context = utils.dummy_context() + plugin = context.clients.client_plugin('ironic') + client = plugin.client() + self.assertEqual('http://server.test:5000/v3', + client.port.api.session.auth.endpoint) + + +class fake_resource(object): + def __init__(self, id=None, name=None): + self.uuid = id + self.name = name + + +class PortGroupConstraintTest(common.HeatTestCase): + def setUp(self): + super(PortGroupConstraintTest, self).setUp() + self.ctx = utils.dummy_context() + self.mock_port_group_get = mock.Mock() + self.ctx.clients.client_plugin( + 'ironic').client().portgroup.get = self.mock_port_group_get + self.constraint = ic.PortGroupConstraint() + + def test_validate(self): + self.mock_port_group_get.return_value = fake_resource( + id='my_port_group') + self.assertTrue(self.constraint.validate( + 'my_port_group', self.ctx)) + + def test_validate_fail(self): + self.mock_port_group_get.side_effect = ic_exc.NotFound() + self.assertFalse(self.constraint.validate( + "bad_port_group", self.ctx)) + + +class NodeConstraintTest(common.HeatTestCase): + def setUp(self): + super(NodeConstraintTest, self).setUp() + self.ctx = utils.dummy_context() + self.mock_node_get = mock.Mock() + self.ctx.clients.client_plugin( + 'ironic').client().node.get = self.mock_node_get + self.constraint = ic.NodeConstraint() + + def test_validate(self): + self.mock_node_get.return_value = fake_resource( + id='my_node') + self.assertTrue(self.constraint.validate( + 'my_node', self.ctx)) + + def test_validate_fail(self): + self.mock_node_get.side_effect = ic_exc.NotFound() + self.assertFalse(self.constraint.validate( + "bad_node", self.ctx)) diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/tests/clients/test_neutron_client.py heat-14.0.0/heat/tests/clients/test_neutron_client.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/tests/clients/test_neutron_client.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/tests/clients/test_neutron_client.py 2020-05-13 10:48:27.000000000 +0000 @@ -66,28 +66,6 @@ self.neutron_client.list_security_groups.return_value = fake_list self.assertEqual(expected_groups, self.neutron_plugin.get_secgroup_uuids(sgs_non_uuid)) - # test only one belong to the tenant - fake_list = { - 'security_groups': [ - { - 'tenant_id': 'test_tenant_id', - 'id': '0389f747-7785-4757-b7bb-2ab07e4b09c3', - 'name': 'security_group_1', - 'security_group_rules': [], - 'description': 'no protocol' - }, - { - 'tenant_id': 'not_test_tenant_id', - 'id': '384ccd91-447c-4d83-832c-06974a7d3d05', - 'name': 'security_group_1', - 'security_group_rules': [], - 'description': 'no protocol' - } - ] - } - self.neutron_client.list_security_groups.return_value = fake_list - self.assertEqual(expected_groups, - self.neutron_plugin.get_secgroup_uuids(sgs_non_uuid)) # test there are two securityGroups with same name, and the two # all belong to the tenant fake_list = { diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/tests/convergence/framework/message_processor.py heat-14.0.0/heat/tests/convergence/framework/message_processor.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/tests/convergence/framework/message_processor.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/tests/convergence/framework/message_processor.py 2020-05-13 10:48:27.000000000 +0000 @@ -112,4 +112,5 @@ """Delete all the messages from the queue.""" self.queue.clear() + __all__ = ['MessageProcessor', 'asynchronous'] diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/tests/convergence/framework/processes.py heat-14.0.0/heat/tests/convergence/framework/processes.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/tests/convergence/framework/processes.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/tests/convergence/framework/processes.py 2020-05-13 10:48:27.000000000 +0000 @@ -41,4 +41,5 @@ self.engine.clear() self.worker.clear() + Processes() diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/tests/convergence/framework/reality.py heat-14.0.0/heat/tests/convergence/framework/reality.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/tests/convergence/framework/reality.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/tests/convergence/framework/reality.py 2020-05-13 10:48:27.000000000 +0000 @@ -48,4 +48,5 @@ prop_name) return res_data.value + reality = RealityStore() diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/tests/db/test_utils.py heat-14.0.0/heat/tests/db/test_utils.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/tests/db/test_utils.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/tests/db/test_utils.py 2020-05-13 10:48:27.000000000 +0000 @@ -26,7 +26,7 @@ and c.name == cname): return True else: - return False + return False class DBMigrationUtilsTest(common.HeatTestCase): diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/tests/engine/test_dependencies.py heat-14.0.0/heat/tests/engine/test_dependencies.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/tests/engine/test_dependencies.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/tests/engine/test_dependencies.py 2020-05-13 10:48:27.000000000 +0000 @@ -57,16 +57,16 @@ def test_single_node(self): d = dependencies.Dependencies([('only', None)]) - l = list(iter(d)) - self.assertEqual(1, len(l)) - self.assertEqual('only', l[0]) + li = list(iter(d)) + self.assertEqual(1, len(li)) + self.assertEqual('only', li[0]) def test_disjoint(self): d = dependencies.Dependencies([('1', None), ('2', None)]) - l = list(iter(d)) - self.assertEqual(2, len(l)) - self.assertIn('1', l) - self.assertIn('2', l) + li = list(iter(d)) + self.assertEqual(2, len(li)) + self.assertIn('1', li) + self.assertIn('2', li) def test_single_fwd(self): self._dep_test_fwd(('second', 'first')) @@ -170,9 +170,9 @@ def test_single_partial(self): d = dependencies.Dependencies([('last', 'first')]) p = d['last'] - l = list(iter(p)) - self.assertEqual(1, len(l)) - self.assertEqual('last', l[0]) + li = list(iter(p)) + self.assertEqual(1, len(li)) + self.assertEqual('last', li[0]) def test_simple_partial(self): d = dependencies.Dependencies([('last', 'middle'), diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/tests/engine/test_scheduler.py heat-14.0.0/heat/tests/engine/test_scheduler.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/tests/engine/test_scheduler.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/tests/engine/test_scheduler.py 2020-05-13 10:48:27.000000000 +0000 @@ -18,7 +18,6 @@ import mock import six -from heat.common.i18n import repr_wrapper from heat.common import timeutils from heat.engine import dependencies from heat.engine import scheduler @@ -1242,9 +1241,9 @@ self.assertEqual('f', scheduler.task_description(f)) def test_lambda(self): - l = lambda: None + lam = lambda: None # noqa: E731 - self.assertEqual('', scheduler.task_description(l)) + self.assertEqual('', scheduler.task_description(lam)) def test_method(self): class C(object): @@ -1273,7 +1272,6 @@ self.assertEqual('o', scheduler.task_description(C())) def test_unicode(self): - @repr_wrapper @six.python_2_unicode_compatible class C(object): def __str__(self): diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/tests/__init__.py heat-14.0.0/heat/tests/__init__.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/tests/__init__.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/tests/__init__.py 2020-05-13 10:48:27.000000000 +0000 @@ -18,6 +18,7 @@ def fake_translate_msgid(msgid, domain, desired_locale=None): return msgid + i18n.enable_lazy() # To ensure messages don't really get translated while running tests. diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/tests/openstack/heat/test_multi_part.py heat-14.0.0/heat/tests/openstack/heat/test_multi_part.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/tests/openstack/heat/test_multi_part.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/tests/openstack/heat/test_multi_part.py 2020-05-13 10:48:27.000000000 +0000 @@ -31,7 +31,7 @@ self.ctx = utils.dummy_context() self.init_config() - def init_config(self, parts=None): + def init_config(self, parts=None, group='Heat::Ungrouped'): parts = parts or [] stack = parser.Stack( self.ctx, 'software_config_test_stack', @@ -41,13 +41,15 @@ 'config_mysql': { 'Type': 'OS::Heat::MultipartMime', 'Properties': { + 'group': group, 'parts': parts }}}})) self.config = stack['config_mysql'] self.rpc_client = mock.MagicMock() self.config._rpc_client = self.rpc_client - def test_handle_create(self): + def _test_create(self, group='Heat::Ungrouped'): + self.init_config(group=group) config_id = 'c8a19429-7fde-47ea-a42f-40045488226c' sc = {'id': config_id} self.rpc_client.create_software_config.return_value = sc @@ -59,9 +61,15 @@ self.assertEqual({ 'name': self.config.physical_resource_name(), 'config': self.config.message, - 'group': 'Heat::Ungrouped' + 'group': group }, kwargs) + def test_handle_create(self): + self._test_create() + + def test_handle_create_with_group(self): + self._test_create(group='script') + def test_get_message_not_none(self): self.config.message = 'Not none' result = self.config.get_message() diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/tests/openstack/ironic/test_port.py heat-14.0.0/heat/tests/openstack/ironic/test_port.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/tests/openstack/ironic/test_port.py 1970-01-01 00:00:00.000000000 +0000 +++ heat-14.0.0/heat/tests/openstack/ironic/test_port.py 2020-05-13 10:48:27.000000000 +0000 @@ -0,0 +1,275 @@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import copy +from ironicclient.common.apiclient import exceptions as ic_exc +import mock +from oslo_config import cfg + +from heat.common import exception +from heat.common import template_format +from heat.engine.clients.os import ironic as ic +from heat.engine import resource +from heat.engine.resources.openstack.ironic import port +from heat.engine import scheduler +from heat.engine import template +from heat.tests import common +from heat.tests import utils + +cfg.CONF.import_opt('max_ironic_api_microversion', 'heat.common.config') + +port_template = ''' + heat_template_version: rocky + resources: + test_port: + type: OS::Ironic::Port + properties: + node: node_1 + address: 52:54:00:4d:e1:5e + portgroup: pg1 + local_link_connection: + switch_info: brbm + port_id: ovs-node-1i1 + switch_id: 70:4d:7b:88:ff:3a + pxe_enabled: true + physical_network: fake_phy_net + extra: {} + is_smartnic: false +''' + + +min_port_template = ''' + heat_template_version: ocata + resources: + test_port: + type: OS::Ironic::Port + properties: + node: node_2 + address: 54:54:00:4d:e1:5e +''' + +RESOURCE_TYPE = 'OS::Ironic::Port' + + +class TestIronicPort(common.HeatTestCase): + def setUp(self): + super(TestIronicPort, self).setUp() + cfg.CONF.set_override('max_ironic_api_microversion', 1.11) + cfg.CONF.set_override('action_retry_limit', 0) + self.fake_node_name = 'node_1' + self.fake_portgroup_name = 'pg1' + + self.resource_id = '9cc6fd32-f711-4e1f-a82d-59e6ae074e95' + self.fake_name = 'test_port' + self.fake_address = u'52:54:00:4d:e1:5e' + self.fake_node_uuid = u'22767a68-a7f2-45fe-bc08-335a83e2b919' + self.fake_portgroup_uuid = '92972f88-a1e7-490f-866c-b6704d65c4de' + self.fake_local_link_connection = {'switch_info': 'brbm', + 'port_id': 'ovs-node-1i1', + 'switch_id': '70:4d:7b:88:ff:3a'} + self.fake_internal_info = {'foo': 'bar'} + self.fake_pxe_enabled = True + self.fake_physical_network = 'fake_phy_net' + self.fake_internal_info = {} + self.fake_extra = {} + self.fake_is_smartnic = False + resource._register_class(RESOURCE_TYPE, port.Port) + t = template_format.parse(port_template) + self.stack = utils.parse_stack(t) + resource_defns = self.stack.t.resource_definitions(self.stack) + self.rsrc_defn = resource_defns[self.fake_name] + self.client = mock.Mock() + self.patchobject(port.Port, 'client', return_value=self.client) + self.m_fgn = self.patchobject(ic.IronicClientPlugin, + 'get_node') + self.m_fgpg = self.patchobject(ic.IronicClientPlugin, + 'get_portgroup') + self.m_fgn.return_value = self.fake_node_uuid + self.m_fgpg.return_value = self.fake_portgroup_uuid + self._mock_get_client() + + def _mock_get_client(self): + value = mock.MagicMock( + address=self.fake_address, + node_uuid=self.fake_node_uuid, + portgroup_uuid=self.fake_portgroup_uuid, + local_link_connection=self.fake_local_link_connection, + pxe_enabled=self.fake_pxe_enabled, + physical_network=self.fake_physical_network, + internal_info=self.fake_internal_info, + extra=self.fake_extra, + is_smartnic=self.fake_is_smartnic, + uuid=self.resource_id, + ) + value.to_dict.return_value = value.__dict__ + self.client.port.get.return_value = value + + def _create_resource(self, name, snippet, stack, get_exception=None): + value = mock.MagicMock(uuid=self.resource_id) + self.client.port.create.return_value = value + get_rv = mock.MagicMock() + if get_exception: + self.client.port.get.side_effect = get_exception + else: + self.client.port.get.return_value = get_rv + p = port.Port(name, snippet, stack) + return p + + def test_port_create(self): + b = self._create_resource('port', self.rsrc_defn, self.stack) + # validate the properties + self.assertEqual( + self.fake_node_name, + b.properties.get(port.Port.NODE)) + self.assertEqual( + self.fake_address, + b.properties.get(port.Port.ADDRESS)) + self.assertEqual( + self.fake_portgroup_name, + b.properties.get(port.Port.PORTGROUP)) + self.assertEqual( + self.fake_local_link_connection, + b.properties.get(port.Port.LOCAL_LINK_CONNECTION)) + self.assertEqual( + self.fake_pxe_enabled, + b.properties.get(port.Port.PXE_ENABLED)) + self.assertEqual( + self.fake_physical_network, + b.properties.get(port.Port.PHYSICAL_NETWORK)) + self.assertEqual( + self.fake_extra, + b.properties.get(port.Port.EXTRA)) + self.assertEqual( + self.fake_is_smartnic, + b.properties.get(port.Port.IS_SMARTNIC)) + scheduler.TaskRunner(b.create)() + self.assertEqual(self.resource_id, b.resource_id) + expected = [mock.call(self.fake_node_name), + mock.call(self.fake_node_uuid)] + self.assertEqual(expected, self.m_fgn.call_args_list) + expected = [mock.call(self.fake_portgroup_name), + mock.call(self.fake_portgroup_uuid)] + self.assertEqual(expected, self.m_fgpg.call_args_list) + self.client.port.create.assert_called_once_with( + address=self.fake_address, + extra=self.fake_extra, + is_smartnic=self.fake_is_smartnic, + local_link_connection=self.fake_local_link_connection, + node_uuid=self.fake_node_uuid, + physical_network=self.fake_physical_network, + portgroup_uuid=self.fake_portgroup_uuid, + pxe_enabled=self.fake_pxe_enabled) + + def _property_not_supported(self, property_name, version): + t = template_format.parse(min_port_template) + new_t = copy.deepcopy(t) + new_t['resources'][self.fake_name]['properties'][ + property_name] = self.rsrc_defn._properties[property_name] + rsrc_defns = template.Template(new_t).resource_definitions( + self.stack) + new_port = rsrc_defns[self.fake_name] + p = self._create_resource('port-with-%s' % property_name, + new_port, self.stack) + + p.client_plugin().max_microversion = version - 0.01 + + feature = "OS::Ironic::Port with %s property" % property_name + err = self.assertRaises(exception.ResourceFailure, + scheduler.TaskRunner(p.create)) + self.assertEqual("NotSupported: resources.port-with-%(key)s: " + "%(feature)s is not supported." % { + 'feature': feature, 'key': property_name}, + str(err)) + + def test_port_create_with_pxe_enabled_not_supported(self): + self._property_not_supported(port.Port.PXE_ENABLED, 1.19) + + def test_port_create_with_local_link_connection_not_supported(self): + self._property_not_supported(port.Port.LOCAL_LINK_CONNECTION, 1.19) + + def test_port_create_with_portgroup_not_supported(self): + self._property_not_supported(port.Port.PORTGROUP, 1.24) + + def test_port_create_with_physical_network_not_supported(self): + self._property_not_supported(port.Port.PHYSICAL_NETWORK, 1.34) + + def test_port_create_with_is_smartnic_not_supported(self): + self._property_not_supported(port.Port.IS_SMARTNIC, 1.53) + + def test_port_check_create_complete(self): + b = self._create_resource('port', self.rsrc_defn, self.stack) + self.assertTrue(b.check_create_complete(self.resource_id)) + + def test_port_check_create_complete_with_not_found(self): + b = self._create_resource('port', self.rsrc_defn, self.stack, + get_exception=ic_exc.NotFound) + self.assertFalse(b.check_create_complete(self.resource_id)) + + def test_port_check_create_complete_with_non_not_found_exception(self): + b = self._create_resource('port', self.rsrc_defn, self.stack, + get_exception=ic_exc.Conflict()) + exc = self.assertRaises(ic_exc.Conflict, b.check_create_complete, + self.resource_id) + self.assertIn('Conflict', str(exc)) + + def _port_update(self, exc_msg=None): + b = self._create_resource('port', self.rsrc_defn, self.stack) + scheduler.TaskRunner(b.create)() + if exc_msg: + self.client.port.update.side_effect = ic_exc.Conflict(exc_msg) + t = template_format.parse(port_template) + new_t = copy.deepcopy(t) + new_extra = {'foo': 'bar'} + m_pg = mock.Mock(extra=new_extra) + self.client.port.get.return_value = m_pg + new_t['resources'][self.fake_name]['properties']['extra'] = new_extra + rsrc_defns = template.Template(new_t).resource_definitions(self.stack) + new_port = rsrc_defns[self.fake_name] + if exc_msg: + exc = self.assertRaises( + exception.ResourceFailure, + scheduler.TaskRunner(b.update, new_port)) + self.assertIn(exc_msg, str(exc)) + else: + scheduler.TaskRunner(b.update, new_port)() + self.client.port.update.assert_called_once_with( + self.resource_id, + [{'op': 'replace', 'path': '/extra', 'value': new_extra}]) + + def test_port_update(self): + self._port_update() + + def test_port_update_failed(self): + exc_msg = ("Port 9cc6fd32-f711-4e1f-a82d-59e6ae074e95 can not have " + "any connectivity attributes (pxe_enabled, portgroup_id, " + "physical_network, local_link_connection) updated unless " + "node 9ccee9ec-92a5-4580-9242-82eb7f454d3f is in a enroll, " + "inspecting, inspect wait, manageable state or in " + "maintenance mode.") + self._port_update(exc_msg) + + def test_port_check_delete_complete_with_no_id(self): + b = self._create_resource('port', self.rsrc_defn, self.stack) + self.assertTrue(b.check_delete_complete(None)) + + def test_port_check_delete_complete_with_not_found(self): + b = self._create_resource('port', self.rsrc_defn, self.stack, + get_exception=ic_exc.NotFound) + self.assertTrue(b.check_delete_complete(self.resource_id)) + + def test_port_check_delete_complete_with_exception(self): + b = self._create_resource('port', self.rsrc_defn, self.stack, + get_exception=ic_exc.Conflict()) + exc = self.assertRaises(ic_exc.Conflict, + b.check_delete_complete, self.resource_id) + self.assertIn('Conflict', str(exc)) diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/tests/openstack/neutron/test_qos.py heat-14.0.0/heat/tests/openstack/neutron/test_qos.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/tests/openstack/neutron/test_qos.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/tests/openstack/neutron/test_qos.py 2020-05-13 10:48:27.000000000 +0000 @@ -58,6 +58,18 @@ tenant_id: d66c74c01d6c41b9846088c1ad9634d0 ''' +minimum_bandwidth_rule_template = ''' +heat_template_version: 2016-04-08 +description: This template to define a neutron minimum bandwidth rule. +resources: + my_minimum_bandwidth_rule: + type: OS::Neutron::QoSMinimumBandwidthRule + properties: + policy: 477e8273-60a7-4c41-b683-fdb0bc7cd151 + min_kbps: 1000 + tenant_id: d66c74c01d6c41b9846088c1ad9634d0 +''' + class NeutronQoSPolicyTest(common.HeatTestCase): def setUp(self): @@ -392,3 +404,114 @@ self.neutronclient.show_dscp_marking_rule.assert_called_once_with( self.dscp_marking_rule.resource_id, self.policy_id) + + +class NeutronQoSMinimumBandwidthRuleTest(common.HeatTestCase): + def setUp(self): + super(NeutronQoSMinimumBandwidthRuleTest, self).setUp() + + self.ctx = utils.dummy_context() + tpl = template_format.parse(minimum_bandwidth_rule_template) + self.stack = stack.Stack( + self.ctx, + 'neutron_minimum_bandwidth_rule_test', + template.Template(tpl) + ) + + self.neutronclient = mock.MagicMock() + self.patchobject(neutron.NeutronClientPlugin, 'has_extension', + return_value=True) + self.minimum_bandwidth_rule = self.stack['my_minimum_bandwidth_rule'] + self.minimum_bandwidth_rule.client = mock.MagicMock( + return_value=self.neutronclient) + self.find_mock = self.patchobject( + neutron.neutronV20, + 'find_resourceid_by_name_or_id') + self.policy_id = '477e8273-60a7-4c41-b683-fdb0bc7cd151' + self.find_mock.return_value = self.policy_id + + def test_rule_handle_create(self): + rule = { + 'minimum_bandwidth_rule': { + 'id': 'cf0eab12-ef8b-4a62-98d0-70576583c17a', + 'min_kbps': 1000, + 'direction': 'egress', + 'tenant_id': 'd66c74c01d6c41b9846088c1ad9634d0' + } + } + + create_props = {'min_kbps': 1000, + 'direction': 'egress', + 'tenant_id': 'd66c74c01d6c41b9846088c1ad9634d0'} + self.neutronclient.create_minimum_bandwidth_rule.return_value = rule + + self.minimum_bandwidth_rule.handle_create() + self.assertEqual('cf0eab12-ef8b-4a62-98d0-70576583c17a', + self.minimum_bandwidth_rule.resource_id) + self.neutronclient.create_minimum_bandwidth_rule.\ + assert_called_once_with( + self.policy_id, + {'minimum_bandwidth_rule': create_props}) + + def test_rule_handle_delete(self): + rule_id = 'cf0eab12-ef8b-4a62-98d0-70576583c17a' + self.minimum_bandwidth_rule.resource_id = rule_id + self.neutronclient.delete_minimum_bandwidth_rule.return_value = None + + self.assertIsNone(self.minimum_bandwidth_rule.handle_delete()) + self.neutronclient.delete_minimum_bandwidth_rule.\ + assert_called_once_with(rule_id, self.policy_id) + + def test_rule_handle_delete_not_found(self): + rule_id = 'cf0eab12-ef8b-4a62-98d0-70576583c17a' + self.minimum_bandwidth_rule.resource_id = rule_id + not_found = self.neutronclient.NotFound + self.neutronclient.delete_minimum_bandwidth_rule.side_effect =\ + not_found + + self.assertIsNone(self.minimum_bandwidth_rule.handle_delete()) + self.neutronclient.delete_minimum_bandwidth_rule.\ + assert_called_once_with(rule_id, self.policy_id) + + def test_rule_handle_delete_resource_id_is_none(self): + self.minimum_bandwidth_rule.resource_id = None + self.assertIsNone(self.minimum_bandwidth_rule.handle_delete()) + self.assertEqual(0, + self.neutronclient.minimum_bandwidth_rule.call_count) + + def test_rule_handle_update(self): + rule_id = 'cf0eab12-ef8b-4a62-98d0-70576583c17a' + self.minimum_bandwidth_rule.resource_id = rule_id + + prop_diff = { + 'min_kbps': 500 + } + + self.minimum_bandwidth_rule.handle_update( + json_snippet={}, + tmpl_diff={}, + prop_diff=prop_diff.copy()) + + self.neutronclient.update_minimum_bandwidth_rule.\ + assert_called_once_with( + rule_id, + self.policy_id, + {'minimum_bandwidth_rule': prop_diff}) + + def test_rule_get_attr(self): + self.minimum_bandwidth_rule.resource_id = 'test rule' + rule = { + 'minimum_bandwidth_rule': { + 'id': 'cf0eab12-ef8b-4a62-98d0-70576583c17a', + 'min_kbps': 1000, + 'direction': 'egress', + 'tenant_id': 'd66c74c01d6c41b9846088c1ad9634d0' + } + } + self.neutronclient.show_minimum_bandwidth_rule.return_value = rule + + self.assertEqual(rule['minimum_bandwidth_rule'], + self.minimum_bandwidth_rule.FnGetAtt('show')) + + self.neutronclient.show_minimum_bandwidth_rule.assert_called_once_with( + self.minimum_bandwidth_rule.resource_id, self.policy_id) diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/tests/test_constraints.py heat-14.0.0/heat/tests/test_constraints.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/tests/test_constraints.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/tests/test_constraints.py 2020-05-13 10:48:27.000000000 +0000 @@ -81,16 +81,16 @@ self.assertRaises(ValueError, r.validate, 6) def test_length_validate(self): - l = constraints.Length(min=5, max=5, description='a range') - l.validate('abcde') + cl = constraints.Length(min=5, max=5, description='a range') + cl.validate('abcde') def test_length_min_fail(self): - l = constraints.Length(min=5, description='a range') - self.assertRaises(ValueError, l.validate, 'abcd') + cl = constraints.Length(min=5, description='a range') + self.assertRaises(ValueError, cl.validate, 'abcd') def test_length_max_fail(self): - l = constraints.Length(max=5, description='a range') - self.assertRaises(ValueError, l.validate, 'abcdef') + cl = constraints.Length(max=5, description='a range') + self.assertRaises(ValueError, cl.validate, 'abcdef') def test_modulo_validate(self): r = constraints.Modulo(step=2, offset=1, description='a modulo') @@ -196,8 +196,8 @@ s = constraints.Schema(constraints.Schema.STRING, 'A string', default='wibble', constraints=[constraints.Length(4, 8)]) - l = constraints.Schema(constraints.Schema.LIST, 'A list', schema=s) - self.assertEqual(d, dict(l)) + ls = constraints.Schema(constraints.Schema.LIST, 'A list', schema=s) + self.assertEqual(d, dict(ls)) def test_schema_map_schema(self): d = { @@ -252,8 +252,8 @@ constraints=[constraints.Length(4, 8)]) m = constraints.Schema(constraints.Schema.MAP, 'A map', schema={'Foo': s}) - l = constraints.Schema(constraints.Schema.LIST, 'A list', schema=m) - self.assertEqual(d, dict(l)) + ls = constraints.Schema(constraints.Schema.LIST, 'A list', schema=m) + self.assertEqual(d, dict(ls)) def test_invalid_type(self): self.assertRaises(exception.InvalidSchemaError, constraints.Schema, diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/tests/test_convg_stack.py heat-14.0.0/heat/tests/test_convg_stack.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/tests/test_convg_stack.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/tests/test_convg_stack.py 2020-05-13 10:48:27.000000000 +0000 @@ -194,7 +194,7 @@ [[4, False], [3, False]], [[4, False], [4, True]]]), sorted(stack_db.current_deps['edges'])) - ''' + r''' To visualize: G(7, True) H(6, True) diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/tests/test_properties.py heat-14.0.0/heat/tests/test_properties.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/tests/test_properties.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/tests/test_properties.py 2020-05-13 10:48:27.000000000 +0000 @@ -71,8 +71,8 @@ s = properties.Schema(properties.Schema.STRING, 'A string', default='wibble', constraints=[constraints.Length(4, 8)]) - l = properties.Schema(properties.Schema.LIST, 'A list', schema=s) - self.assertEqual(d, dict(l)) + ls = properties.Schema(properties.Schema.LIST, 'A list', schema=s) + self.assertEqual(d, dict(ls)) def test_schema_map_schema(self): d = { @@ -137,8 +137,8 @@ constraints=[constraints.Length(4, 8)]) m = properties.Schema(properties.Schema.MAP, 'A map', schema={'Foo': s}) - l = properties.Schema(properties.Schema.LIST, 'A list', schema=m) - self.assertEqual(d, dict(l)) + ls = properties.Schema(properties.Schema.LIST, 'A list', schema=m) + self.assertEqual(d, dict(ls)) def test_all_resource_schemata(self): for resource_type in resources.global_env().get_types(): @@ -292,7 +292,7 @@ self.assertEqual('[a-z]*', c.pattern) def test_from_legacy_list(self): - l = properties.Schema.from_legacy({ + ls = properties.Schema.from_legacy({ 'Type': 'List', 'Default': ['wibble'], 'Schema': { @@ -301,15 +301,15 @@ 'MaxLength': 8, } }) - self.assertEqual(properties.Schema.LIST, l.type) - self.assertEqual(['wibble'], l.default) + self.assertEqual(properties.Schema.LIST, ls.type) + self.assertEqual(['wibble'], ls.default) - ss = l.schema[0] + ss = ls.schema[0] self.assertEqual(properties.Schema.STRING, ss.type) self.assertEqual('wibble', ss.default) def test_from_legacy_map(self): - l = properties.Schema.from_legacy({ + ls = properties.Schema.from_legacy({ 'Type': 'Map', 'Schema': { 'foo': { @@ -318,9 +318,9 @@ } } }) - self.assertEqual(properties.Schema.MAP, l.type) + self.assertEqual(properties.Schema.MAP, ls.type) - ss = l.schema['foo'] + ss = ls.schema['foo'] self.assertEqual(properties.Schema.STRING, ss.type) self.assertEqual('wibble', ss.default) diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/tests/test_stack_lock.py heat-14.0.0/heat/tests/test_stack_lock.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/tests/test_stack_lock.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/tests/test_stack_lock.py 2020-05-13 10:48:27.000000000 +0000 @@ -36,7 +36,7 @@ stack_object.Stack, 'get_by_id', return_value=stack) class TestThreadLockException(Exception): - pass + pass def test_successful_acquire_new_lock(self): mock_create = self.patchobject(stack_lock_object.StackLock, diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/tests/test_urlfetch.py heat-14.0.0/heat/tests/test_urlfetch.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/tests/test_urlfetch.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/tests/test_urlfetch.py 2020-05-13 10:48:27.000000000 +0000 @@ -11,10 +11,13 @@ # License for the specific language governing permissions and limitations # under the License. +import io +import urllib.error +import urllib.request + from oslo_config import cfg import requests from requests import exceptions -import six from heat.common import urlfetch from heat.tests import common @@ -42,15 +45,15 @@ def test_file_scheme_supported(self): data = '{ "foo": "bar" }' url = 'file:///etc/profile' - mock_open = self.patchobject(six.moves.urllib.request, 'urlopen') - mock_open.return_value = six.moves.cStringIO(data) + mock_open = self.patchobject(urllib.request, 'urlopen') + mock_open.return_value = io.StringIO(data) self.assertEqual(data, urlfetch.get(url, allowed_schemes=['file'])) mock_open.assert_called_once_with(url) def test_file_scheme_failure(self): url = 'file:///etc/profile' - mock_open = self.patchobject(six.moves.urllib.request, 'urlopen') - mock_open.side_effect = six.moves.urllib.error.URLError('oops') + mock_open = self.patchobject(urllib.request, 'urlopen') + mock_open.side_effect = urllib.error.URLError('oops') self.assertRaises(urlfetch.URLFetchError, urlfetch.get, url, allowed_schemes=['file']) mock_open.assert_called_once_with(url) @@ -109,5 +112,5 @@ mock_get.return_value = response exception = self.assertRaises(urlfetch.URLFetchError, urlfetch.get, url) - self.assertIn("Template exceeds", six.text_type(exception)) + self.assertIn("Template exceeds", str(exception)) mock_get.assert_called_once_with(url, stream=True) diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/tests/test_vpc.py heat-14.0.0/heat/tests/test_vpc.py --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat/tests/test_vpc.py 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat/tests/test_vpc.py 2020-05-13 10:48:27.000000000 +0000 @@ -532,7 +532,7 @@ 'name': self.nic_name, 'admin_state_up': True} if security_groups: - self._port['security_groups'] = security_groups + self._port['security_groups'] = security_groups self.mockclient.create_port.return_value = { 'port': { diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat_integrationtests/config-generator.conf heat-14.0.0/heat_integrationtests/config-generator.conf --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat_integrationtests/config-generator.conf 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat_integrationtests/config-generator.conf 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -[DEFAULT] -output_file = heat_integrationtests/heat_integrationtests.conf.sample -wrap_width = 79 -namespace = heat_integrationtests.common.config diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat_integrationtests/README.rst heat-14.0.0/heat_integrationtests/README.rst --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/heat_integrationtests/README.rst 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/heat_integrationtests/README.rst 2020-05-13 10:48:27.000000000 +0000 @@ -20,6 +20,7 @@ If the Heat Tempest Plugin is also installed, the tests from that will be run as well. -If custom configuration is required, add it in the file -``heat_integrationtests/heat_integrationtests.conf``. A sample configuration is -available in ``heat_integrationtests/heat_integrationtests.conf.sample`` +These tests require both tempest and heat tempest plugin installed. +If custom configuration is required, it should be configured in the +heat tempest plugin configuration of the tempest config +(see heat tempest plugin and tempest docs for more info). diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/lower-constraints.txt heat-14.0.0/lower-constraints.txt --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/lower-constraints.txt 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/lower-constraints.txt 2020-05-13 10:48:27.000000000 +0000 @@ -28,13 +28,11 @@ extras==1.0.0 fasteners==0.14.1 fixtures==3.0.0 -flake8==2.5.5 future==0.16.0 futurist==1.6.0 gitdb2==2.0.3 GitPython==2.1.8 greenlet==0.4.13 -hacking==0.12.0 idna==2.6 iso8601==0.1.12 Jinja2==2.10 @@ -84,7 +82,6 @@ Paste==2.0.3 PasteDeploy==1.5.0 pbr==2.0.0 -pep8==1.5.7 pika-pool==0.1.3 pika==0.10.0 ply==3.11 @@ -94,7 +91,7 @@ pyasn1==0.4.2 pycadf==2.7.0 pycparser==2.18 -pyflakes==0.8.1 +Pygments==2.2.0 pyinotify==0.9.6 PyMySQL==0.7.6 PyNaCl==1.2.1 @@ -110,6 +107,7 @@ python-editor==1.0.3 python-glanceclient==2.8.0 python-heatclient==1.10.0 +python-ironicclient==2.8.0 python-keystoneclient==3.8.0 python-magnumclient==2.3.0 python-manilaclient==1.16.0 diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/openstack_heat.egg-info/entry_points.txt heat-14.0.0/openstack_heat.egg-info/entry_points.txt --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/openstack_heat.egg-info/entry_points.txt 2020-04-10 16:59:07.000000000 +0000 +++ heat-14.0.0/openstack_heat.egg-info/entry_points.txt 2020-05-13 10:50:31.000000000 +0000 @@ -14,6 +14,7 @@ designate = heat.engine.clients.os.designate:DesignateClientPlugin glance = heat.engine.clients.os.glance:GlanceClientPlugin heat = heat.engine.clients.os.heat_plugin:HeatClientPlugin +ironic = heat.engine.clients.os.ironic:IronicClientPlugin keystone = heat.engine.clients.os.keystone:KeystoneClientPlugin magnum = heat.engine.clients.os.magnum:MagnumClientPlugin manila = heat.engine.clients.os.manila:ManilaClientPlugin @@ -48,6 +49,8 @@ glance.image = heat.engine.clients.os.glance:ImageConstraint ip_addr = heat.engine.constraint.common_constraints:IPConstraint ip_or_cidr = heat.engine.constraint.common_constraints:IPCIDRConstraint +ironic.node = heat.engine.clients.os.ironic:NodeConstraint +ironic.portgroup = heat.engine.clients.os.ironic:PortGroupConstraint iso_8601 = heat.engine.constraint.common_constraints:ISO8601Constraint keystone.domain = heat.engine.clients.os.keystone.keystone_constraints:KeystoneDomainConstraint keystone.group = heat.engine.clients.os.keystone.keystone_constraints:KeystoneGroupConstraint diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/openstack_heat.egg-info/pbr.json heat-14.0.0/openstack_heat.egg-info/pbr.json --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/openstack_heat.egg-info/pbr.json 2020-04-10 16:59:07.000000000 +0000 +++ heat-14.0.0/openstack_heat.egg-info/pbr.json 2020-05-13 10:50:31.000000000 +0000 @@ -1 +1 @@ -{"git_version": "2ef9f4bf3", "is_release": false} \ No newline at end of file +{"git_version": "084c9b3ea", "is_release": true} \ No newline at end of file diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/openstack_heat.egg-info/PKG-INFO heat-14.0.0/openstack_heat.egg-info/PKG-INFO --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/openstack_heat.egg-info/PKG-INFO 2020-04-10 16:59:07.000000000 +0000 +++ heat-14.0.0/openstack_heat.egg-info/PKG-INFO 2020-05-13 10:50:31.000000000 +0000 @@ -1,6 +1,6 @@ Metadata-Version: 1.2 Name: openstack-heat -Version: 13.1.0.dev154 +Version: 14.0.0 Summary: OpenStack Orchestration Home-page: https://docs.openstack.org/heat/latest/ Author: OpenStack @@ -84,6 +84,7 @@ * https://opendev.org/openstack/python-octaviaclient.git (Load-balancer service) * https://opendev.org/openstack/python-senlinclient (Clustering service) * https://opendev.org/openstack/python-vitrageclient.git (RCA service) + * https://opendev.org/openstack/python-ironicclient (baremetal provisioning service) Platform: UNKNOWN diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/openstack_heat.egg-info/requires.txt heat-14.0.0/openstack_heat.egg-info/requires.txt --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/openstack_heat.egg-info/requires.txt 2020-04-10 16:59:07.000000000 +0000 +++ heat-14.0.0/openstack_heat.egg-info/requires.txt 2020-05-13 10:50:31.000000000 +0000 @@ -1,10 +1,5 @@ +pbr!=2.1.0,>=2.0.0 Babel!=2.4.0,>=2.3.4 -PasteDeploy>=1.5.0 -PyYAML>=3.12 -Routes>=2.3.1 -SQLAlchemy!=1.1.5,!=1.1.6,!=1.1.7,!=1.1.8,>=1.0.10 -WebOb>=1.7.1 -aodhclient>=0.9.0 croniter>=0.3.4 cryptography>=2.1 eventlet!=0.18.3,!=0.20.1,!=0.21.0,!=0.23.0,!=0.25.0,>=0.18.2 @@ -15,8 +10,8 @@ neutron-lib>=1.14.0 openstacksdk>=0.11.2 oslo.cache>=1.26.0 -oslo.concurrency>=3.26.0 oslo.config>=5.2.0 +oslo.concurrency>=3.26.0 oslo.context>=2.19.2 oslo.db>=4.27.0 oslo.i18n>=3.15.3 @@ -29,15 +24,17 @@ oslo.service!=1.28.1,>=1.24.0 oslo.upgradecheck>=0.1.0 oslo.utils>=3.37.0 -oslo.versionedobjects>=1.31.2 osprofiler>=1.4.0 -pbr!=2.1.0,>=2.0.0 +oslo.versionedobjects>=1.31.2 +PasteDeploy>=1.5.0 +aodhclient>=0.9.0 python-barbicanclient>=4.5.2 python-blazarclient>=1.0.1 python-cinderclient>=3.3.0 python-designateclient>=2.7.0 python-glanceclient>=2.8.0 python-heatclient>=1.10.0 +python-ironicclient>=2.8.0 python-keystoneclient>=3.8.0 python-magnumclient>=2.3.0 python-manilaclient>=1.16.0 @@ -54,9 +51,13 @@ python-zaqarclient>=1.3.0 python-zunclient>=3.4.0 pytz>=2013.6 +PyYAML>=3.12 requests>=2.14.2 +tenacity>=4.4.0 +Routes>=2.3.1 six>=1.10.0 +SQLAlchemy!=1.1.5,!=1.1.6,!=1.1.7,!=1.1.8,>=1.0.10 sqlalchemy-migrate>=0.11.0 stevedore>=1.20.0 -tenacity>=4.4.0 +WebOb>=1.7.1 yaql>=1.1.3 diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/openstack_heat.egg-info/SOURCES.txt heat-14.0.0/openstack_heat.egg-info/SOURCES.txt --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/openstack_heat.egg-info/SOURCES.txt 2020-04-10 16:59:07.000000000 +0000 +++ heat-14.0.0/openstack_heat.egg-info/SOURCES.txt 2020-05-13 10:50:32.000000000 +0000 @@ -366,6 +366,7 @@ heat/engine/clients/os/designate.py heat/engine/clients/os/glance.py heat/engine/clients/os/heat_plugin.py +heat/engine/clients/os/ironic.py heat/engine/clients/os/magnum.py heat/engine/clients/os/manila.py heat/engine/clients/os/mistral.py @@ -483,6 +484,8 @@ heat/engine/resources/openstack/heat/value.py heat/engine/resources/openstack/heat/wait_condition.py heat/engine/resources/openstack/heat/wait_condition_handle.py +heat/engine/resources/openstack/ironic/__init__.py +heat/engine/resources/openstack/ironic/port.py heat/engine/resources/openstack/keystone/__init__.py heat/engine/resources/openstack/keystone/domain.py heat/engine/resources/openstack/keystone/endpoint.py @@ -786,6 +789,7 @@ heat/tests/clients/test_designate_client.py heat/tests/clients/test_glance_client.py heat/tests/clients/test_heat_client.py +heat/tests/clients/test_ironic_client.py heat/tests/clients/test_keystone_client.py heat/tests/clients/test_magnum_client.py heat/tests/clients/test_manila_client.py @@ -912,6 +916,8 @@ heat/tests/openstack/heat/test_swiftsignal.py heat/tests/openstack/heat/test_value.py heat/tests/openstack/heat/test_waitcondition.py +heat/tests/openstack/ironic/__init__.py +heat/tests/openstack/ironic/test_port.py heat/tests/openstack/keystone/__init__.py heat/tests/openstack/keystone/test_domain.py heat/tests/openstack/keystone/test_endpoint.py @@ -1036,7 +1042,6 @@ heat_integrationtests/README.rst heat_integrationtests/__init__.py heat_integrationtests/cleanup_test_env.sh -heat_integrationtests/config-generator.conf heat_integrationtests/prepare_test_env.sh heat_integrationtests/prepare_test_network.sh heat_integrationtests/common/__init__.py @@ -1205,6 +1210,7 @@ releasenotes/notes/neutron-l2gw-support-9fbb690bb5648f76.yaml releasenotes/notes/neutron-lbaas-v2-resources-c0ebbeb9bc9f7a42.yaml releasenotes/notes/neutron-port-network-attribute-14d2eeb481b25fa8.yaml +releasenotes/notes/neutron-qos-minimum-bandwidth-rule-cb38db4ebc27688e.yaml releasenotes/notes/neutron-quota-resource-7fa5e4df8287bf77.yaml releasenotes/notes/neutron-segment-support-a7d44af499838a4e.yaml releasenotes/notes/nova-quota-resource-84350f0467ce2d40.yaml @@ -1252,10 +1258,13 @@ releasenotes/notes/support-files-from-swift-f27fd2d788d67580.yaml releasenotes/notes/support-handling-empty-string-for-volume-az-22ad78eb0f931954.yaml releasenotes/notes/support-ignition-93daac40f43a2cfe.yaml +releasenotes/notes/support-ironic-client-plugin-b7b91b7090579c81.yaml +releasenotes/notes/support-ironic-port-resource-type-304284a7c508d5d5.yaml releasenotes/notes/support-rbac-for-qos-policy-a55434654e1dd953.yaml releasenotes/notes/support-shared-servies-multi-region-mode-d9f167fb52d9c0a8.yaml releasenotes/notes/support_case_insensitive_user_name_search-92d6126d8be2ce4f.yaml releasenotes/notes/support_remote_stack_override_ssl_options-69c82b351920af57.yaml +releasenotes/notes/support_set_group_for_multipart-79b5819b9b3a82ad.yaml releasenotes/notes/sync-queens-releasenote-13f68851f7201e37.yaml releasenotes/notes/system-random-string-38a14ae2cb6f4a24.yaml releasenotes/notes/template-validate-improvements-52ecf5125c9efeda.yaml diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/PKG-INFO heat-14.0.0/PKG-INFO --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/PKG-INFO 2020-04-10 16:59:08.140907300 +0000 +++ heat-14.0.0/PKG-INFO 2020-05-13 10:50:32.000000000 +0000 @@ -1,6 +1,6 @@ Metadata-Version: 1.2 Name: openstack-heat -Version: 13.1.0.dev154 +Version: 14.0.0 Summary: OpenStack Orchestration Home-page: https://docs.openstack.org/heat/latest/ Author: OpenStack @@ -84,6 +84,7 @@ * https://opendev.org/openstack/python-octaviaclient.git (Load-balancer service) * https://opendev.org/openstack/python-senlinclient (Clustering service) * https://opendev.org/openstack/python-vitrageclient.git (RCA service) + * https://opendev.org/openstack/python-ironicclient (baremetal provisioning service) Platform: UNKNOWN diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/README.rst heat-14.0.0/README.rst --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/README.rst 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/README.rst 2020-05-13 10:48:27.000000000 +0000 @@ -76,3 +76,4 @@ * https://opendev.org/openstack/python-octaviaclient.git (Load-balancer service) * https://opendev.org/openstack/python-senlinclient (Clustering service) * https://opendev.org/openstack/python-vitrageclient.git (RCA service) +* https://opendev.org/openstack/python-ironicclient (baremetal provisioning service) diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/releasenotes/notes/neutron-qos-minimum-bandwidth-rule-cb38db4ebc27688e.yaml heat-14.0.0/releasenotes/notes/neutron-qos-minimum-bandwidth-rule-cb38db4ebc27688e.yaml --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/releasenotes/notes/neutron-qos-minimum-bandwidth-rule-cb38db4ebc27688e.yaml 1970-01-01 00:00:00.000000000 +0000 +++ heat-14.0.0/releasenotes/notes/neutron-qos-minimum-bandwidth-rule-cb38db4ebc27688e.yaml 2020-05-13 10:48:27.000000000 +0000 @@ -0,0 +1,7 @@ +--- +features: + - | + New resource ``OS::Neutron::QoSMinimumBandwidthRule`` to support + ``minimum_bandwidth_rules`` in Neutron QoS. This resource depends + on Neutron API extension ``qos-bw-minimum-ingress`` and according + to the default policy it is admin-only. diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/releasenotes/notes/support-ironic-client-plugin-b7b91b7090579c81.yaml heat-14.0.0/releasenotes/notes/support-ironic-client-plugin-b7b91b7090579c81.yaml --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/releasenotes/notes/support-ironic-client-plugin-b7b91b7090579c81.yaml 1970-01-01 00:00:00.000000000 +0000 +++ heat-14.0.0/releasenotes/notes/support-ironic-client-plugin-b7b91b7090579c81.yaml 2020-05-13 10:48:27.000000000 +0000 @@ -0,0 +1,7 @@ +--- +features: + - | + Introduce a Ironic client plugin module that will be used by the Ironic's + resources. + Support only ironicclient version >=2.8.0 to get allocation functionality + support. diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/releasenotes/notes/support-ironic-port-resource-type-304284a7c508d5d5.yaml heat-14.0.0/releasenotes/notes/support-ironic-port-resource-type-304284a7c508d5d5.yaml --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/releasenotes/notes/support-ironic-port-resource-type-304284a7c508d5d5.yaml 1970-01-01 00:00:00.000000000 +0000 +++ heat-14.0.0/releasenotes/notes/support-ironic-port-resource-type-304284a7c508d5d5.yaml 2020-05-13 10:48:27.000000000 +0000 @@ -0,0 +1,4 @@ +--- +features: + - | + New resource type ``OS::Ironic::Port`` is now supported in orchestration service. diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/releasenotes/notes/support_set_group_for_multipart-79b5819b9b3a82ad.yaml heat-14.0.0/releasenotes/notes/support_set_group_for_multipart-79b5819b9b3a82ad.yaml --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/releasenotes/notes/support_set_group_for_multipart-79b5819b9b3a82ad.yaml 1970-01-01 00:00:00.000000000 +0000 +++ heat-14.0.0/releasenotes/notes/support_set_group_for_multipart-79b5819b9b3a82ad.yaml 2020-05-13 10:48:27.000000000 +0000 @@ -0,0 +1,8 @@ +--- +features: + - | + Add ``group`` property to ``OS::Heat::MultipartMime``. This allow you to + set group for entire multipart cofig resource like ``group`` property in + ``OS::Heat::SoftwareConfig``. Aware that, you must make sure all configs + in MultipartMime works with ``group``. Default value is + ``Heat::Ungrouped``. diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po heat-14.0.0/releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po 2020-05-13 10:48:27.000000000 +0000 @@ -6,11 +6,11 @@ msgstr "" "Project-Id-Version: openstack-heat\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-04-08 03:44+0000\n" +"POT-Creation-Date: 2020-04-23 14:20+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2020-04-07 08:12+0000\n" +"PO-Revision-Date: 2020-04-18 07:28+0000\n" "Last-Translator: Andi Chandler \n" "Language-Team: English (United Kingdom)\n" "Language: en_GB\n" @@ -63,11 +63,14 @@ msgid "11.0.2" msgstr "11.0.2" +msgid "11.0.3" +msgstr "11.0.3" + msgid "12.0.0" msgstr "12.0.0" -msgid "12.0.0-23" -msgstr "12.0.0-23" +msgid "12.0.0-24" +msgstr "12.0.0-24" msgid "12.0.0.0rc1" msgstr "12.0.0.0rc1" @@ -75,12 +78,12 @@ msgid "13.0.0" msgstr "13.0.0" -msgid "13.0.0-16" -msgstr "13.0.0-16" - msgid "13.0.0.0rc1" msgstr "13.0.0.0rc1" +msgid "13.0.1" +msgstr "13.0.1" + msgid "5.0.1" msgstr "5.0.1" @@ -964,6 +967,15 @@ "resources." msgid "" +"Introduce a Ironic client plugin module that will be used by the Ironic's " +"resources. Support only ironicclient version >=2.8.0 to get allocation " +"functionality support." +msgstr "" +"Introduce a Ironic client plugin module that will be used by the Ironic's " +"resources. Support only ironicclient version >=2.8.0 to get allocation " +"functionality support." + +msgid "" "Introduce a Vitrage client plugin module that will be used by the Vitrage " "resources." msgstr "" diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/requirements.txt heat-14.0.0/requirements.txt --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/requirements.txt 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/requirements.txt 2020-05-13 10:48:27.000000000 +0000 @@ -38,6 +38,7 @@ python-designateclient>=2.7.0 # Apache-2.0 python-glanceclient>=2.8.0 # Apache-2.0 python-heatclient>=1.10.0 # Apache-2.0 +python-ironicclient>=2.8.0 # Apache-2.0 python-keystoneclient>=3.8.0 # Apache-2.0 python-magnumclient>=2.3.0 # Apache-2.0 python-manilaclient>=1.16.0 # Apache-2.0 diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/setup.cfg heat-14.0.0/setup.cfg --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/setup.cfg 2020-04-10 16:59:08.140907300 +0000 +++ heat-14.0.0/setup.cfg 2020-05-13 10:50:32.000000000 +0000 @@ -68,6 +68,7 @@ designate = heat.engine.clients.os.designate:DesignateClientPlugin glance = heat.engine.clients.os.glance:GlanceClientPlugin heat = heat.engine.clients.os.heat_plugin:HeatClientPlugin + ironic = heat.engine.clients.os.ironic:IronicClientPlugin keystone = heat.engine.clients.os.keystone:KeystoneClientPlugin magnum = heat.engine.clients.os.magnum:MagnumClientPlugin manila = heat.engine.clients.os.manila:ManilaClientPlugin @@ -165,6 +166,8 @@ senlin.profile_type = heat.engine.clients.os.senlin:ProfileTypeConstraint trove.flavor = heat.engine.clients.os.trove:FlavorConstraint zaqar.queue = heat.engine.clients.os.zaqar:QueueConstraint + ironic.portgroup = heat.engine.clients.os.ironic:PortGroupConstraint + ironic.node = heat.engine.clients.os.ironic:NodeConstraint heat.stack_lifecycle_plugins = heat.event_sinks = zaqar-queue = heat.engine.clients.os.zaqar:ZaqarEventSink diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/test-requirements.txt heat-14.0.0/test-requirements.txt --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/test-requirements.txt 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/test-requirements.txt 2020-05-13 10:48:27.000000000 +0000 @@ -3,7 +3,7 @@ # process, which may cause wedges in the gate later. # Hacking already pins down pep8, pyflakes and flake8 -hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0 +hacking>=3.0,<3.1.0 # Apache-2.0 bandit!=1.6.0,>=1.1.0 # Apache-2.0 coverage!=4.4,>=4.0 # Apache-2.0 fixtures>=3.0.0 # Apache-2.0/BSD diff -Nru heat-14.0.0~b3~git2020041012.2ef9f4bf3/tox.ini heat-14.0.0/tox.ini --- heat-14.0.0~b3~git2020041012.2ef9f4bf3/tox.ini 2020-04-10 16:59:02.000000000 +0000 +++ heat-14.0.0/tox.ini 2020-05-13 10:48:27.000000000 +0000 @@ -30,13 +30,14 @@ # B110: Try, Except, Pass detected. # B310: Audit url open for permitted schemes # B311: Standard pseudo-random generators are not suitable for security/cryptographic purposes + # B322: The input method is safe in Python 3. # B404: Import of subprocess module # B410: Import of lxml module # B504: Test for SSL use with no version specified # B506: Test for use of yaml load # B603: Test for use of subprocess with shell equals true # B607: Test for starting a process with a partial path - bandit -r heat -x tests --skip B101,B104,B107,B110,B310,B311,B404,B410,B504,B506,B603,B607 + bandit -r heat -x tests --skip B101,B104,B107,B110,B310,B311,B322,B404,B410,B504,B506,B603,B607 doc8 {posargs} [testenv:venv] @@ -81,7 +82,6 @@ [testenv:genconfig] commands = oslo-config-generator --config-file=config-generator.conf - oslo-config-generator --config-file=heat_integrationtests/config-generator.conf [testenv:genpolicy] commands = @@ -108,8 +108,16 @@ [flake8] show-source = true +# E123 closing bracket does not match indentation of opening bracket's line +# E226 missing whitespace around arithmetic operator +# E241 multiple spaces after ',' +# E305 expected 2 blank lines after class or function definition, found 1 +# E402 module level import not at top of file +# W503 line break before binary operator +# W504 line break after binary operator +ignore = E123,E226,E241,E402,W503,W504 exclude=.*,dist,*lib/python*,*egg,build,*convergence/scenarios/* -max-complexity=20 +max-complexity=23 [doc8] ignore = D001 @@ -117,7 +125,14 @@ [hacking] import_exceptions = heat.common.i18n -local-check-factory = heat.hacking.checks.factory + +[flake8:local-plugins] +extension = + Heat301 = checks:no_log_warn + Heat302 = checks:check_python3_no_iteritems + Heat303 = checks:check_python3_no_iterkeys + Heat304 = checks:check_python3_no_itervalues +paths = ./heat/hacking [testenv:debug] commands = oslo_debug_helper {posargs}