Merge ~ajkavanagh/ubuntu/+source/heat:master into ~ubuntu-openstack-dev/ubuntu/+source/heat:master
- Git
- lp:~ajkavanagh/ubuntu/+source/heat
- master
- Merge into master
Proposed by
James Page
Status: | Merged |
---|---|
Merged at revision: | ad629122a96c14fb5a219bf914d6503c8824de84 |
Proposed branch: | ~ajkavanagh/ubuntu/+source/heat:master |
Merge into: | ~ubuntu-openstack-dev/ubuntu/+source/heat:master |
Diff against target: |
2798 lines (+766/-583) 84 files modified
.pre-commit-config.yaml (+1/-1) .zuul.yaml (+8/-0) AUTHORS (+3/-0) ChangeLog (+25/-0) HACKING.rst (+4/-4) PKG-INFO (+85/-84) config-generator.conf (+3/-0) debian/changelog (+8/-2) debian/patches/drop-zun.patch (+3/-3) debian/patches/series (+0/-1) debian/patches/sudoers_patch.patch (+1/-1) dev/null (+0/-63) devstack/lib/heat (+0/-11) doc/source/conf.py (+4/-3) doc/source/operating_guides/upgrades_guide.rst (+1/-1) doc/source/template_guide/multi-clouds.rst (+1/-1) heat/api/openstack/v1/util.py (+8/-2) heat/cloudinit/loguserdata.py (+0/-53) heat/cloudinit/part_handler.py (+1/-1) heat/common/cache.py (+56/-47) heat/common/config.py (+13/-0) heat/common/plugin_loader.py (+3/-1) heat/db/api.py (+30/-1) heat/engine/clients/os/keystone/fake_keystoneclient.py (+1/-1) heat/engine/clients/os/keystone/heat_keystoneclient.py (+2/-2) heat/engine/constraint/common_constraints.py (+12/-3) heat/engine/hot/functions.py (+7/-2) heat/engine/resource.py (+1/-1) heat/engine/resources/openstack/monasca/alarm_definition.py (+8/-4) heat/engine/resources/openstack/monasca/notification.py (+9/-4) heat/engine/resources/openstack/neutron/port.py (+1/-1) heat/engine/resources/openstack/neutron/security_group.py (+1/-1) heat/engine/resources/openstack/sahara/cluster.py (+9/-0) heat/engine/resources/openstack/sahara/data_source.py (+8/-1) heat/engine/resources/openstack/sahara/image.py (+8/-1) heat/engine/resources/openstack/sahara/job.py (+8/-1) heat/engine/resources/openstack/sahara/job_binary.py (+8/-1) heat/engine/resources/openstack/sahara/templates.py (+8/-1) heat/engine/resources/openstack/senlin/res_base.py (+8/-1) heat/engine/service.py (+35/-1) heat/engine/service_software_config.py (+7/-0) heat/engine/stack.py (+3/-2) heat/hacking/checks.py (+9/-9) heat/objects/snapshot.py (+7/-2) heat/objects/software_config.py (+4/-0) heat/objects/software_deployment.py (+5/-0) heat/tests/api/cfn/test_api_cfn_v1.py (+4/-4) heat/tests/api/openstack_v1/test_routes.py (+2/-2) heat/tests/api/openstack_v1/test_stacks.py (+2/-2) heat/tests/clients/test_swift_client.py (+12/-2) heat/tests/constraints/test_common_constraints.py (+10/-1) heat/tests/convergence/framework/engine_wrapper.py (+4/-4) heat/tests/db/test_sqlalchemy_api.py (+83/-33) heat/tests/engine/service/test_software_config.py (+20/-3) heat/tests/engine/service/test_stack_snapshot.py (+13/-0) heat/tests/engine/test_resource_type.py (+1/-2) heat/tests/openstack/aodh/test_alarm.py (+10/-1) heat/tests/openstack/heat/test_none_resource.py (+1/-1) heat/tests/openstack/heat/test_remote_stack.py (+1/-1) heat/tests/openstack/heat/test_software_deployment.py (+1/-1) heat/tests/openstack/neutron/test_neutron_floating_ip.py (+3/-3) heat/tests/test_common_context.py (+1/-1) heat/tests/test_convg_stack.py (+2/-2) heat/tests/test_environment.py (+2/-5) heat/tests/test_loguserdata.py (+1/-74) heat/tests/test_resource.py (+6/-6) heat/tests/test_stack_delete.py (+4/-4) heat/tests/test_template_format.py (+5/-5) openstack_heat.egg-info/PKG-INFO (+85/-84) openstack_heat.egg-info/SOURCES.txt (+2/-0) openstack_heat.egg-info/entry_points.txt (+6/-0) openstack_heat.egg-info/pbr.json (+1/-1) openstack_heat.egg-info/requires.txt (+6/-1) releasenotes/config.yaml (+1/-1) releasenotes/notes/deprecate-inactive-project-rsc-caracal-ba0b0005f67580f9.yaml (+10/-0) releasenotes/notes/limit-resources-aeb2f24e705840de.yaml (+26/-0) releasenotes/source/victoria.rst (+1/-1) releasenotes/source/wallaby.rst (+1/-1) releasenotes/source/xena.rst (+1/-1) releasenotes/source/yoga.rst (+1/-1) requirements.txt (+2/-1) setup.cfg (+2/-0) test-requirements.txt (+1/-9) tox.ini (+5/-6) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu OpenStack uploaders | Pending | ||
Review via email: mp+463034@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml |
2 | index 0ae225c..ee085de 100644 |
3 | --- a/.pre-commit-config.yaml |
4 | +++ b/.pre-commit-config.yaml |
5 | @@ -22,7 +22,7 @@ repos: |
6 | - id: flake8 |
7 | name: flake8 |
8 | additional_dependencies: |
9 | - - hacking>=3.1.0,<3.2.0 |
10 | + - hacking>=6.1.0,<6.2.0 |
11 | language: python |
12 | entry: flake8 |
13 | files: '^.*\.py$' |
14 | diff --git a/.zuul.yaml b/.zuul.yaml |
15 | index 5cc2149..6072137 100644 |
16 | --- a/.zuul.yaml |
17 | +++ b/.zuul.yaml |
18 | @@ -188,6 +188,12 @@ |
19 | - ^releasenotes/.*$ |
20 | |
21 | - job: |
22 | + name: grenade-heat-multinode-skip-level |
23 | + parent: grenade-heat-multinode |
24 | + vars: |
25 | + grenade_from_branch: stable/2023.1 |
26 | + |
27 | +- job: |
28 | name: heat-tox-py310-with-sqlalchemy-2x |
29 | parent: openstack-tox-py310 |
30 | description: | |
31 | @@ -215,6 +221,7 @@ |
32 | check: |
33 | jobs: |
34 | - grenade-heat-multinode |
35 | + - grenade-heat-multinode-skip-level |
36 | - heat-functional |
37 | - heat-functional-legacy |
38 | - heat-functional-centos-9-stream |
39 | @@ -222,5 +229,6 @@ |
40 | gate: |
41 | jobs: |
42 | - grenade-heat-multinode |
43 | + - grenade-heat-multinode-skip-level |
44 | - heat-functional |
45 | - heat-functional-legacy |
46 | diff --git a/AUTHORS b/AUTHORS |
47 | index b95d2a9..4807711 100644 |
48 | --- a/AUTHORS |
49 | +++ b/AUTHORS |
50 | @@ -116,6 +116,7 @@ Dave Wilde <david.wilde@rackspace.com> |
51 | David Hill <dhill@redhat.com> |
52 | David J Peacock <david.j.peacock@gmail.com> |
53 | David Rabel <rabel@b1-systems.de> |
54 | +David Vallee Delisle <dvd@redhat.com> |
55 | Deepak Tiwari <deepak.tiwari@aricent.com> |
56 | Deliang Fan <fandeliang@letv.com> |
57 | Denes Nemeth <denes.nemeth@nokia.com> |
58 | @@ -196,6 +197,7 @@ Jaime Guerrero <jg3755@att.com> |
59 | Jake Yip <jake.yip@ardc.edu.au> |
60 | James Combs <cornracker@gmail.com> |
61 | James E. Blair <jeblair@redhat.com> |
62 | +James Page <james.page@canonical.com> |
63 | James Reeves <james.reeves5546@gmail.com> |
64 | James Slagle <jslagle@redhat.com> |
65 | Jamie Lennox <jamielennox@gmail.com> |
66 | @@ -563,6 +565,7 @@ liusheng <liusheng@huawei.com> |
67 | liyi <liyi8611@gmail.com> |
68 | liyi <liyi@liyideMacBook-Pro.local> |
69 | lizheming <lizheming.li@huawei.com> |
70 | +lujiefsi <lujie@ict.ac.cn> |
71 | lvdongbing <dongbing.lv@kylin-cloud.com> |
72 | maniksidana019 <manik@voereir.com> |
73 | matthew-fuller <mfuller@suse.com> |
74 | diff --git a/ChangeLog b/ChangeLog |
75 | index c4eb64a..3b1c682 100644 |
76 | --- a/ChangeLog |
77 | +++ b/ChangeLog |
78 | @@ -1,6 +1,31 @@ |
79 | CHANGES |
80 | ======= |
81 | |
82 | +22.0.0.0rc1 |
83 | +----------- |
84 | + |
85 | +* Update regex to detect closed branch |
86 | +* Restore tests disabled because of libvirt bug |
87 | +* Fix access by admin users to resources in different projects |
88 | +* reno: Update master for unmaintained/xena |
89 | +* reno: Update master for unmaintained/wallaby |
90 | +* reno: Update master for unmaintained/victoria |
91 | +* Stop using deprecated implicit\_prefix option |
92 | +* reno: Update master for unmaintained/yoga |
93 | +* Add skip level upgrade job |
94 | +* Fix minor typos in documentation |
95 | +* common: Replace deprecated importlib API (2/2) |
96 | +* Remove logic for cloud-init < 0.6.0 |
97 | +* Drop unused default password in create\_stack\_user |
98 | +* Bump hacking (again) |
99 | +* Use zoneinfo instead of pytz if available |
100 | +* Allow more options to limit number of resources |
101 | +* Fix inconsistent naming in db api |
102 | +* Stop unnecessary usage of 'self' |
103 | +* tests: Fix unit tests using has\_calls |
104 | +* Deprecate resources for inactive services |
105 | +* Bump hacking |
106 | +* Adding oslo.config entry points for yaql and cache opts |
107 | * Add recent release names |
108 | * Drop remaining references to the removed bin scripts |
109 | * Remove deprecated wrappertask decorator |
110 | diff --git a/HACKING.rst b/HACKING.rst |
111 | index 618cfa3..d16d300 100644 |
112 | --- a/HACKING.rst |
113 | +++ b/HACKING.rst |
114 | @@ -50,8 +50,8 @@ done in the OpenStack CI systems. |
115 | Heat Specific Commandments |
116 | -------------------------- |
117 | |
118 | -- [Heat301] Use LOG.warning() rather than LOG.warn(). |
119 | -- [Heat302] Python 3: do not use dict.iteritems. |
120 | -- [Heat303] Python 3: do not use dict.iterkeys. |
121 | -- [Heat304] Python 3: do not use dict.itervalues. |
122 | +- [HE301] Use LOG.warning() rather than LOG.warn(). |
123 | +- [HE302] Python 3: do not use dict.iteritems. |
124 | +- [HE303] Python 3: do not use dict.iterkeys. |
125 | +- [HE304] Python 3: do not use dict.itervalues. |
126 | |
127 | diff --git a/PKG-INFO b/PKG-INFO |
128 | index d68f1ed..9541147 100644 |
129 | --- a/PKG-INFO |
130 | +++ b/PKG-INFO |
131 | @@ -1,10 +1,93 @@ |
132 | -Metadata-Version: 2.1 |
133 | +Metadata-Version: 1.2 |
134 | Name: openstack-heat |
135 | -Version: 21.1.0.dev70 |
136 | +Version: 22.0.0.0rc1 |
137 | Summary: OpenStack Orchestration |
138 | Home-page: https://docs.openstack.org/heat/latest/ |
139 | Author: OpenStack |
140 | Author-email: openstack-discuss@lists.openstack.org |
141 | +License: UNKNOWN |
142 | +Description: ======================== |
143 | + Team and repository tags |
144 | + ======================== |
145 | + |
146 | + .. image:: https://governance.openstack.org/tc/badges/heat.svg |
147 | + :target: https://governance.openstack.org/tc/reference/tags/index.html |
148 | + |
149 | + .. Change things from this point on |
150 | + |
151 | + ==== |
152 | + Heat |
153 | + ==== |
154 | + |
155 | + Heat is a service to orchestrate multiple composite cloud applications using |
156 | + templates, through both an OpenStack-native REST API and a |
157 | + CloudFormation-compatible Query API. |
158 | + |
159 | + Why heat? It makes the clouds rise and keeps them there. |
160 | + |
161 | + Getting Started |
162 | + --------------- |
163 | + |
164 | + If you'd like to run from the master branch, you can clone the git repo: |
165 | + |
166 | + git clone https://opendev.org/openstack/heat |
167 | + |
168 | + |
169 | + * Documentation: https://docs.openstack.org/heat/latest |
170 | + * Template samples: https://opendev.org/openstack/heat-templates |
171 | + * Agents: https://opendev.org/openstack/heat-agents |
172 | + * Release Notes: https://docs.openstack.org/releasenotes/heat/ |
173 | + |
174 | + Python client |
175 | + ------------- |
176 | + |
177 | + * Documentation: https://docs.openstack.org/python-heatclient/latest |
178 | + * Source: https://opendev.org/openstack/python-heatclient |
179 | + |
180 | + Report a Story (a bug/blueprint) |
181 | + -------------------------------- |
182 | + |
183 | + If you'd like to report a Story (we used to call a bug/blueprint), you can |
184 | + report it under Report a story in |
185 | + `Heat's StoryBoard <https://storyboard.openstack.org/#!/project/989>`_. |
186 | + If you must report the story under other sub-project of heat, you can find |
187 | + them all in `Heat StoryBoard Group <https://storyboard.openstack.org/#!/project_group/82>`_. |
188 | + if you encounter any issue. |
189 | + |
190 | + References |
191 | + ---------- |
192 | + * https://docs.amazonwebservices.com/AWSCloudFormation/latest/APIReference/API_CreateStack.html |
193 | + * https://docs.amazonwebservices.com/AWSCloudFormation/latest/UserGuide/create-stack.html |
194 | + * https://docs.amazonwebservices.com/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html |
195 | + * https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=tosca |
196 | + |
197 | + We have integration with |
198 | + ------------------------ |
199 | + * https://opendev.org/openstack/python-novaclient (instance) |
200 | + * https://opendev.org/openstack/python-keystoneclient (auth) |
201 | + * https://opendev.org/openstack/python-swiftclient (object storage) |
202 | + * https://opendev.org/openstack/python-neutronclient (networking) |
203 | + * https://opendev.org/openstack/python-aodhclient (alarming service) |
204 | + * https://opendev.org/openstack/python-cinderclient (block storage) |
205 | + * https://opendev.org/openstack/python-glanceclient (image service) |
206 | + * https://opendev.org/openstack/python-troveclient (database as a Service) |
207 | + * https://opendev.org/openstack/python-saharaclient (hadoop cluster) |
208 | + * https://opendev.org/openstack/python-barbicanclient (key management service) |
209 | + * https://opendev.org/openstack/python-designateclient (DNS service) |
210 | + * https://opendev.org/openstack/python-magnumclient (container service) |
211 | + * https://opendev.org/openstack/python-manilaclient (shared file system service) |
212 | + * https://opendev.org/openstack/python-mistralclient (workflow service) |
213 | + * https://opendev.org/openstack/python-zaqarclient (messaging service) |
214 | + * https://opendev.org/openstack/python-monascaclient (monitoring service) |
215 | + * https://opendev.org/openstack/python-zunclient (container management service) |
216 | + * https://opendev.org/openstack/python-blazarclient (reservation service) |
217 | + * https://opendev.org/openstack/python-octaviaclient.git (Load-balancer service) |
218 | + * https://opendev.org/openstack/python-senlinclient (Clustering service) |
219 | + * https://opendev.org/openstack/python-vitrageclient.git (RCA service) |
220 | + * https://opendev.org/openstack/python-ironicclient (baremetal provisioning service) |
221 | + |
222 | + |
223 | +Platform: UNKNOWN |
224 | Classifier: Environment :: OpenStack |
225 | Classifier: Intended Audience :: Information Technology |
226 | Classifier: Intended Audience :: System Administrators |
227 | @@ -18,85 +101,3 @@ Classifier: Programming Language :: Python :: 3.9 |
228 | Classifier: Programming Language :: Python :: 3.10 |
229 | Classifier: Programming Language :: Python :: 3.11 |
230 | Requires-Python: >=3.8 |
231 | -License-File: LICENSE |
232 | - |
233 | -======================== |
234 | -Team and repository tags |
235 | -======================== |
236 | - |
237 | -.. image:: https://governance.openstack.org/tc/badges/heat.svg |
238 | - :target: https://governance.openstack.org/tc/reference/tags/index.html |
239 | - |
240 | -.. Change things from this point on |
241 | - |
242 | -==== |
243 | -Heat |
244 | -==== |
245 | - |
246 | -Heat is a service to orchestrate multiple composite cloud applications using |
247 | -templates, through both an OpenStack-native REST API and a |
248 | -CloudFormation-compatible Query API. |
249 | - |
250 | -Why heat? It makes the clouds rise and keeps them there. |
251 | - |
252 | -Getting Started |
253 | ---------------- |
254 | - |
255 | -If you'd like to run from the master branch, you can clone the git repo: |
256 | - |
257 | - git clone https://opendev.org/openstack/heat |
258 | - |
259 | - |
260 | -* Documentation: https://docs.openstack.org/heat/latest |
261 | -* Template samples: https://opendev.org/openstack/heat-templates |
262 | -* Agents: https://opendev.org/openstack/heat-agents |
263 | -* Release Notes: https://docs.openstack.org/releasenotes/heat/ |
264 | - |
265 | -Python client |
266 | -------------- |
267 | - |
268 | -* Documentation: https://docs.openstack.org/python-heatclient/latest |
269 | -* Source: https://opendev.org/openstack/python-heatclient |
270 | - |
271 | -Report a Story (a bug/blueprint) |
272 | --------------------------------- |
273 | - |
274 | -If you'd like to report a Story (we used to call a bug/blueprint), you can |
275 | -report it under Report a story in |
276 | -`Heat's StoryBoard <https://storyboard.openstack.org/#!/project/989>`_. |
277 | -If you must report the story under other sub-project of heat, you can find |
278 | -them all in `Heat StoryBoard Group <https://storyboard.openstack.org/#!/project_group/82>`_. |
279 | -if you encounter any issue. |
280 | - |
281 | -References |
282 | ----------- |
283 | -* https://docs.amazonwebservices.com/AWSCloudFormation/latest/APIReference/API_CreateStack.html |
284 | -* https://docs.amazonwebservices.com/AWSCloudFormation/latest/UserGuide/create-stack.html |
285 | -* https://docs.amazonwebservices.com/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html |
286 | -* https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=tosca |
287 | - |
288 | -We have integration with |
289 | ------------------------- |
290 | -* https://opendev.org/openstack/python-novaclient (instance) |
291 | -* https://opendev.org/openstack/python-keystoneclient (auth) |
292 | -* https://opendev.org/openstack/python-swiftclient (object storage) |
293 | -* https://opendev.org/openstack/python-neutronclient (networking) |
294 | -* https://opendev.org/openstack/python-aodhclient (alarming service) |
295 | -* https://opendev.org/openstack/python-cinderclient (block storage) |
296 | -* https://opendev.org/openstack/python-glanceclient (image service) |
297 | -* https://opendev.org/openstack/python-troveclient (database as a Service) |
298 | -* https://opendev.org/openstack/python-saharaclient (hadoop cluster) |
299 | -* https://opendev.org/openstack/python-barbicanclient (key management service) |
300 | -* https://opendev.org/openstack/python-designateclient (DNS service) |
301 | -* https://opendev.org/openstack/python-magnumclient (container service) |
302 | -* https://opendev.org/openstack/python-manilaclient (shared file system service) |
303 | -* https://opendev.org/openstack/python-mistralclient (workflow service) |
304 | -* https://opendev.org/openstack/python-zaqarclient (messaging service) |
305 | -* https://opendev.org/openstack/python-monascaclient (monitoring service) |
306 | -* https://opendev.org/openstack/python-zunclient (container management service) |
307 | -* https://opendev.org/openstack/python-blazarclient (reservation service) |
308 | -* https://opendev.org/openstack/python-octaviaclient.git (Load-balancer service) |
309 | -* https://opendev.org/openstack/python-senlinclient (Clustering service) |
310 | -* https://opendev.org/openstack/python-vitrageclient.git (RCA service) |
311 | -* https://opendev.org/openstack/python-ironicclient (baremetal provisioning service) |
312 | - |
313 | diff --git a/config-generator.conf b/config-generator.conf |
314 | index deb30da..115880d 100644 |
315 | --- a/config-generator.conf |
316 | +++ b/config-generator.conf |
317 | @@ -1,16 +1,19 @@ |
318 | [DEFAULT] |
319 | output_file = etc/heat/heat.conf.sample |
320 | wrap_width = 79 |
321 | +namespace = heat.common.cache |
322 | namespace = heat.common.config |
323 | namespace = heat.common.context |
324 | namespace = heat.common.crypt |
325 | namespace = heat.engine.clients.os.keystone.heat_keystoneclient |
326 | +namespace = heat.engine.hot.functions |
327 | namespace = heat.common.wsgi |
328 | namespace = heat.engine.clients |
329 | namespace = heat.engine.notification |
330 | namespace = heat.engine.resources |
331 | namespace = heat.api.aws.ec2token |
332 | namespace = keystonemiddleware.auth_token |
333 | +namespace = oslo.cache |
334 | namespace = oslo.messaging |
335 | namespace = oslo.middleware |
336 | namespace = oslo.cache |
337 | diff --git a/debian/changelog b/debian/changelog |
338 | index 53d777f..c31a8e4 100644 |
339 | --- a/debian/changelog |
340 | +++ b/debian/changelog |
341 | @@ -1,8 +1,14 @@ |
342 | -heat (1:21.0.0+git2024011916.2df46d4c-0ubuntu2) UNRELEASED; urgency=medium |
343 | +heat (1:22.0.0~rc1-0ubuntu1) UNRELEASED; urgency=medium |
344 | |
345 | + [ James Page ] |
346 | * d/watch: Track Caracal series releases. |
347 | |
348 | - -- James Page <james.page@ubuntu.com> Tue, 19 Mar 2024 15:37:42 +0000 |
349 | + [ Alex Kavanagh (Canonical Work Key) ] |
350 | + * New upstream release canadidate (rc1) for OpenStack Caracal |
351 | + * d/p/*: Refresh. |
352 | + * d/p/python3.13-compat dropped as patch added upstream. |
353 | + |
354 | + -- Alex Kavanagh (Canonical Work Key) <alex.kavanagh@canonical.com> Mon, 25 Mar 2024 11:56:44 +0000 |
355 | |
356 | heat (1:21.0.0+git2024011916.2df46d4c-0ubuntu1) noble; urgency=medium |
357 | |
358 | diff --git a/debian/patches/drop-zun.patch b/debian/patches/drop-zun.patch |
359 | index 2e4d9f9..988ba4d 100644 |
360 | --- a/debian/patches/drop-zun.patch |
361 | +++ b/debian/patches/drop-zun.patch |
362 | @@ -8,12 +8,12 @@ Forwarded: no |
363 | |
364 | --- a/requirements.txt |
365 | +++ b/requirements.txt |
366 | -@@ -50,7 +50,6 @@ |
367 | +@@ -50,7 +50,6 @@ python-swiftclient>=3.2.0 # Apache-2.0 |
368 | python-troveclient>=2.2.0 # Apache-2.0 |
369 | python-vitrageclient>=2.7.0 # Apache-2.0 |
370 | python-zaqarclient>=1.3.0 # Apache-2.0 |
371 | -python-zunclient>=3.4.0 # Apache-2.0 |
372 | - pytz>=2013.6 # MIT |
373 | + pytz>=2013.6;python_version<"3.9" # MIT |
374 | PyYAML>=5.1 # MIT |
375 | requests>=2.23.0 # Apache-2.0 |
376 | --- a/heat/tests/openstack/zun/test_container.py |
377 | @@ -1250,7 +1250,7 @@ Forwarded: no |
378 | - } |
379 | --- a/setup.cfg |
380 | +++ b/setup.cfg |
381 | -@@ -87,7 +87,6 @@ |
382 | +@@ -89,7 +89,6 @@ heat.clients = |
383 | trove = heat.engine.clients.os.trove:TroveClientPlugin |
384 | vitrage = heat.engine.clients.os.vitrage:VitrageClientPlugin |
385 | zaqar = heat.engine.clients.os.zaqar:ZaqarClientPlugin |
386 | diff --git a/debian/patches/python3.12-compat.patch b/debian/patches/python3.12-compat.patch |
387 | deleted file mode 100644 |
388 | index 2b056da..0000000 |
389 | --- a/debian/patches/python3.12-compat.patch |
390 | +++ /dev/null |
391 | @@ -1,63 +0,0 @@ |
392 | -Description: Use assert_has_calls in unit tests |
393 | - Test when executed under Python 3.12 FAIL due to: |
394 | - AttributeError: 'has_calls' is not a valid assertion |
395 | - Use correct assert_has_calls instead |
396 | - |
397 | - This also revealed a problem with the expected parameters |
398 | - on one of the calls in the test_software_config module. |
399 | -Author: James Page <james.page@ubuntu.com> |
400 | -Forwarded: no |
401 | - |
402 | ---- a/heat/tests/engine/service/test_software_config.py |
403 | -+++ b/heat/tests/engine/service/test_software_config.py |
404 | -@@ -753,12 +753,12 @@ |
405 | - } |
406 | - self.engine.software_config._push_metadata_software_deployments( |
407 | - self.ctx, '1234', None) |
408 | -- res_upd.has_calls( |
409 | -+ res_upd.assert_has_calls([ |
410 | - mock.call(self.ctx, '1234', |
411 | - {'rsrc_metadata': result_metadata}, 1), |
412 | - mock.call(self.ctx, '1234', |
413 | -- {'rsrc_metadata': result_metadata}, 2), |
414 | -- ) |
415 | -+ {}, 2), |
416 | -+ ]) |
417 | - |
418 | - put.assert_called_once_with( |
419 | - 'http://192.168.2.2/foo/bar', json.dumps(result_metadata)) |
420 | ---- a/heat/tests/test_resource.py |
421 | -+++ b/heat/tests/test_resource.py |
422 | -@@ -4092,8 +4092,8 @@ |
423 | - service_type='test_type', |
424 | - service_name=(generic_rsrc.ResourceWithDefaultClientName |
425 | - .default_client_name)) |
426 | -- mock_client_plugin.has_extension.has_calls( |
427 | -- [('foo'), ('bar')]) |
428 | -+ mock_client_plugin.has_extension.assert_has_calls( |
429 | -+ [mock.call('foo'), mock.call('bar')]) |
430 | - |
431 | - @mock.patch.object(clients.OpenStackClients, 'client_plugin') |
432 | - def test_service_deployed_required_extension_true_list( |
433 | -@@ -4118,8 +4118,8 @@ |
434 | - service_type='test_type', |
435 | - service_name=(generic_rsrc.ResourceWithDefaultClientName |
436 | - .default_client_name)) |
437 | -- mock_client_plugin.has_extension.has_calls( |
438 | -- [('foo'), ('bar')]) |
439 | -+ mock_client_plugin.has_extension.assert_has_calls( |
440 | -+ [mock.call('foo'), mock.call('bar')]) |
441 | - |
442 | - @mock.patch.object(clients.OpenStackClients, 'client_plugin') |
443 | - def test_service_deployed_required_extension_true_list_fail( |
444 | -@@ -4144,8 +4144,8 @@ |
445 | - service_type='test_type', |
446 | - service_name=(generic_rsrc.ResourceWithDefaultClientName |
447 | - .default_client_name)) |
448 | -- mock_client_plugin.has_extension.has_calls( |
449 | -- [('foo'), ('bar')]) |
450 | -+ mock_client_plugin.has_extension.assert_has_calls( |
451 | -+ [mock.call('foo'), mock.call('bar')]) |
452 | - |
453 | - |
454 | - class TestLiveStateUpdate(common.HeatTestCase): |
455 | diff --git a/debian/patches/series b/debian/patches/series |
456 | index 33e20eb..e394474 100644 |
457 | --- a/debian/patches/series |
458 | +++ b/debian/patches/series |
459 | @@ -1,4 +1,3 @@ |
460 | drop-zun.patch |
461 | sudoers_patch.patch |
462 | install-missing-files.patch |
463 | -python3.12-compat.patch |
464 | diff --git a/debian/patches/sudoers_patch.patch b/debian/patches/sudoers_patch.patch |
465 | index 02b91b4..4fc05da 100644 |
466 | --- a/debian/patches/sudoers_patch.patch |
467 | +++ b/debian/patches/sudoers_patch.patch |
468 | @@ -3,7 +3,7 @@ Author: Chuck Short <zulcss@ubuntu.com> |
469 | Forwarded: Not needed. |
470 | --- a/heat/engine/clients/os/nova.py |
471 | +++ b/heat/engine/clients/os/nova.py |
472 | -@@ -360,8 +360,8 @@ |
473 | +@@ -360,8 +360,8 @@ class NovaClientPlugin(microversion_mixi |
474 | # |
475 | # See bug https://bugs.launchpad.net/heat/+bug/1257410 |
476 | boothook_custom_user = r"""useradd -m %s |
477 | diff --git a/devstack/lib/heat b/devstack/lib/heat |
478 | index 6d02e7d..198b3d3 100644 |
479 | --- a/devstack/lib/heat |
480 | +++ b/devstack/lib/heat |
481 | @@ -449,20 +449,9 @@ function configure_tempest_for_heat { |
482 | SKIP_SCENARIO_TEST_LIST+=',AodhAlarmTest' |
483 | # Skip CfnInitIntegrationTest as latest fedora images don't have heat-cfntools |
484 | SKIP_SCENARIO_TEST_LIST+=',CfnInitIntegrationTest' |
485 | - if is_ubuntu; then |
486 | - # Skip a few tests failing because of a known libvirt issue in Jammy |
487 | - # https://bugs.launchpad.net/nova/+bug/1998274 |
488 | - SKIP_SCENARIO_TEST_LIST+=',BasicResourcesTest' |
489 | - fi |
490 | iniset $TEMPEST_CONFIG heat_plugin skip_scenario_test_list $SKIP_SCENARIO_TEST_LIST |
491 | |
492 | SKIP_FUNCTIONAL_TEST_LIST='NotificationTest' |
493 | - if is_ubuntu; then |
494 | - # Skip a few tests failing because of a known libvirt issue in Jammy |
495 | - # https://bugs.launchpad.net/nova/+bug/1998274 |
496 | - SKIP_FUNCTIONAL_TEST_LIST+=',UpdateStackTest.test_stack_update_with_replacing_userdata' |
497 | - SKIP_FUNCTIONAL_TEST_LIST+=',CancelUpdateTest.test_cancel_update_server_with_port' |
498 | - fi |
499 | iniset $TEMPEST_CONFIG heat_plugin skip_functional_test_list $SKIP_FUNCTIONAL_TEST_LIST |
500 | |
501 | openstack flavor show m1.heat_int || openstack flavor create m1.heat_int --ram 1024 --vcpus 2 --disk 10 |
502 | diff --git a/doc/source/conf.py b/doc/source/conf.py |
503 | index 5c41d69..6d4c2d6 100644 |
504 | --- a/doc/source/conf.py |
505 | +++ b/doc/source/conf.py |
506 | @@ -33,8 +33,9 @@ from oslo_config import cfg |
507 | |
508 | BASE_DIR = os.path.dirname(os.path.abspath(__file__)) |
509 | ROOT = os.path.abspath(os.path.join(BASE_DIR, "..", "..")) |
510 | -CONTRIB_DIR = os.path.join(ROOT, 'contrib') |
511 | -PLUGIN_DIRS = glob.glob(os.path.join(CONTRIB_DIR, '*')) |
512 | +# TODO(tkajinam): Fix this |
513 | +# CONTRIB_DIR = os.path.join(ROOT, 'contrib') |
514 | +# PLUGIN_DIRS = glob.glob(os.path.join(CONTRIB_DIR, '*')) |
515 | ENV_DIR = os.path.join(ROOT, "etc", "heat", "environment.d") |
516 | TEMP_ENV_DIR = tempfile.mkdtemp() |
517 | |
518 | @@ -48,7 +49,7 @@ sys.path.insert(0, ROOT) |
519 | sys.path.insert(0, BASE_DIR) |
520 | |
521 | cfg.CONF.import_opt('plugin_dirs', 'heat.common.config') |
522 | -cfg.CONF.set_override(name='plugin_dirs', override=PLUGIN_DIRS) |
523 | +# cfg.CONF.set_override(name='plugin_dirs', override=PLUGIN_DIRS) |
524 | |
525 | cfg.CONF.import_opt('environment_dir', 'heat.common.config') |
526 | cfg.CONF.set_override(name='environment_dir', override=TEMP_ENV_DIR) |
527 | diff --git a/doc/source/operating_guides/upgrades_guide.rst b/doc/source/operating_guides/upgrades_guide.rst |
528 | index e1dfa08..6144184 100644 |
529 | --- a/doc/source/operating_guides/upgrades_guide.rst |
530 | +++ b/doc/source/operating_guides/upgrades_guide.rst |
531 | @@ -40,7 +40,7 @@ Cold Upgrades |
532 | Heat already supports "`cold-upgrades`_", where the heat services have to be |
533 | down during the upgrade. For time-consuming upgrades, it may be unacceptable |
534 | for the services to be unavailable for a long period of time. This type of |
535 | -upgrade is quite simple, follow the bellow steps: |
536 | +upgrade is quite simple, follow the below steps: |
537 | |
538 | 1. Stop all heat-api and heat-engine services. |
539 | |
540 | diff --git a/doc/source/template_guide/multi-clouds.rst b/doc/source/template_guide/multi-clouds.rst |
541 | index e6266db..0038725 100644 |
542 | --- a/doc/source/template_guide/multi-clouds.rst |
543 | +++ b/doc/source/template_guide/multi-clouds.rst |
544 | @@ -124,7 +124,7 @@ To create a remote stack, you can simply use an :ref:`OS::Heat::Stack` resource |
545 | in your template. |
546 | |
547 | In resource properties, provide `credential_secret_id` (Barbican secret ID |
548 | -from the secret we just builded for credential) under `context` property. |
549 | +from the secret we just built for credential) under `context` property. |
550 | |
551 | Here is an template example for you: |
552 | |
553 | diff --git a/heat/api/openstack/v1/util.py b/heat/api/openstack/v1/util.py |
554 | index ee2b92d..556f6f2 100644 |
555 | --- a/heat/api/openstack/v1/util.py |
556 | +++ b/heat/api/openstack/v1/util.py |
557 | @@ -29,9 +29,15 @@ def registered_policy_enforce(handler): |
558 | """ |
559 | @functools.wraps(handler) |
560 | def handle_stack_method(controller, req, tenant_id, **kwargs): |
561 | + # NOTE(tkajinam): Heat uses stack owner's project id in redirect URI. |
562 | + # So admin might be redirected to different project id when accessing |
563 | + # resources in a different project. Use project id in context to |
564 | + # bypass project_id check, because admin should have access to all |
565 | + # projects. |
566 | + if req.context.is_admin and req.context.project_id: |
567 | + tenant_id = req.context.tenant_id |
568 | _target = {"project_id": tenant_id} |
569 | - |
570 | - if req.context.tenant_id != tenant_id and not req.context.is_admin: |
571 | + if req.context.tenant_id != tenant_id: |
572 | raise exc.HTTPForbidden() |
573 | allowed = req.context.policy.enforce( |
574 | context=req.context, |
575 | diff --git a/heat/cloudinit/loguserdata.py b/heat/cloudinit/loguserdata.py |
576 | index 14d17f2..810e353 100755 |
577 | --- a/heat/cloudinit/loguserdata.py |
578 | +++ b/heat/cloudinit/loguserdata.py |
579 | @@ -11,61 +11,19 @@ |
580 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
581 | # License for the specific language governing permissions and limitations |
582 | # under the License. |
583 | -"true" '''\' |
584 | -# NOTE(vgridnev): ubuntu trusty by default has python3, |
585 | -# but pkg_resources can't be imported. |
586 | -echo "import pkg_resources" | python3 2>/dev/null |
587 | -has_py3=$? |
588 | -echo "import pkg_resources" | python2 2>/dev/null |
589 | -has_py2=$? |
590 | -echo "import pkg_resources" | /usr/libexec/platform-python 2>/dev/null |
591 | -has_platform-py=$? |
592 | - |
593 | -if [ $has_py3 = 0 ]; then |
594 | - interpreter="python3" |
595 | -elif [ $has_py2 = 0 ]; then |
596 | - interpreter="python" |
597 | -elif [ $has_platform-py = 0 ]; then |
598 | - interpreter="/usr/libexec/platform-python" |
599 | -else |
600 | - interpreter="python" |
601 | -fi |
602 | -exec $interpreter "$0" |
603 | -''' |
604 | |
605 | import datetime |
606 | import errno |
607 | import logging |
608 | import os |
609 | -import re |
610 | import subprocess |
611 | import sys |
612 | |
613 | -from packaging import version |
614 | -import pkg_resources |
615 | - |
616 | |
617 | VAR_PATH = '/var/lib/heat-cfntools' |
618 | LOG = logging.getLogger('heat-provision') |
619 | |
620 | |
621 | -def chk_ci_version(): |
622 | - try: |
623 | - v = version.Version( |
624 | - pkg_resources.get_distribution('cloud-init').version) |
625 | - return v >= version.Version('0.6.0') |
626 | - except Exception: |
627 | - pass |
628 | - data = subprocess.Popen(['cloud-init', '--version'], |
629 | - stdout=subprocess.PIPE, |
630 | - stderr=subprocess.PIPE).communicate() |
631 | - if data[0]: |
632 | - raise Exception() |
633 | - # data[1] has such format: 'cloud-init 0.7.5\n', need to parse version |
634 | - v = re.split(' |\n', data[1])[1].split('.') |
635 | - return tuple(v) >= tuple(['0', '6', '0']) |
636 | - |
637 | - |
638 | def init_logging(): |
639 | LOG.setLevel(logging.INFO) |
640 | LOG.addHandler(logging.StreamHandler()) |
641 | @@ -106,17 +64,6 @@ def call(args): |
642 | |
643 | |
644 | def main(): |
645 | - |
646 | - try: |
647 | - if not chk_ci_version(): |
648 | - # pre 0.6.0 - user data executed via cloudinit, not this helper |
649 | - LOG.error('Unable to log provisioning, need a newer version of ' |
650 | - 'cloud-init') |
651 | - return -1 |
652 | - except Exception: |
653 | - LOG.warning('Can not determine the version of cloud-init. It is ' |
654 | - 'possible to get errors while logging provisioning.') |
655 | - |
656 | userdata_path = os.path.join(VAR_PATH, 'cfn-userdata') |
657 | os.chmod(userdata_path, int("700", 8)) |
658 | |
659 | diff --git a/heat/cloudinit/part_handler.py b/heat/cloudinit/part_handler.py |
660 | index 50318f3..cf879fe 100644 |
661 | --- a/heat/cloudinit/part_handler.py |
662 | +++ b/heat/cloudinit/part_handler.py |
663 | @@ -19,7 +19,7 @@ import sys |
664 | |
665 | |
666 | def list_types(): |
667 | - return(["text/x-cfninitdata"]) |
668 | + return ["text/x-cfninitdata"] |
669 | |
670 | |
671 | def handle_part(data, ctype, filename, payload): |
672 | diff --git a/heat/common/cache.py b/heat/common/cache.py |
673 | index 3e011fd..6dc1d95 100644 |
674 | --- a/heat/common/cache.py |
675 | +++ b/heat/common/cache.py |
676 | @@ -21,6 +21,56 @@ from oslo_config import cfg |
677 | |
678 | from heat.common.i18n import _ |
679 | |
680 | +constraint_cache_group = cfg.OptGroup('constraint_validation_cache') |
681 | +constraint_cache_opts = [ |
682 | + cfg.IntOpt('expiration_time', default=60, |
683 | + help=_( |
684 | + 'TTL, in seconds, for any cached item in the ' |
685 | + 'dogpile.cache region used for caching of validation ' |
686 | + 'constraints.')), |
687 | + cfg.BoolOpt("caching", default=True, |
688 | + help=_( |
689 | + 'Toggle to enable/disable caching when Orchestration ' |
690 | + 'Engine validates property constraints of stack. ' |
691 | + 'During property validation with constraints ' |
692 | + 'Orchestration Engine caches requests to other ' |
693 | + 'OpenStack services. Please note that the global ' |
694 | + 'toggle for oslo.cache(enabled=True in [cache] group) ' |
695 | + 'must be enabled to use this feature.')) |
696 | +] |
697 | + |
698 | +extension_cache_group = cfg.OptGroup('service_extension_cache') |
699 | +extension_cache_opts = [ |
700 | + cfg.IntOpt('expiration_time', default=3600, |
701 | + help=_( |
702 | + 'TTL, in seconds, for any cached item in the ' |
703 | + 'dogpile.cache region used for caching of service ' |
704 | + 'extensions.')), |
705 | + cfg.BoolOpt('caching', default=True, |
706 | + help=_( |
707 | + 'Toggle to enable/disable caching when Orchestration ' |
708 | + 'Engine retrieves extensions from other OpenStack ' |
709 | + 'services. Please note that the global toggle for ' |
710 | + 'oslo.cache(enabled=True in [cache] group) must be ' |
711 | + 'enabled to use this feature.')) |
712 | +] |
713 | + |
714 | +find_cache_group = cfg.OptGroup('resource_finder_cache') |
715 | +find_cache_opts = [ |
716 | + cfg.IntOpt('expiration_time', default=3600, |
717 | + help=_( |
718 | + 'TTL, in seconds, for any cached item in the ' |
719 | + 'dogpile.cache region used for caching of OpenStack ' |
720 | + 'service finder functions.')), |
721 | + cfg.BoolOpt('caching', default=True, |
722 | + help=_( |
723 | + 'Toggle to enable/disable caching when Orchestration ' |
724 | + 'Engine looks for other OpenStack service resources ' |
725 | + 'using name or id. Please note that the global ' |
726 | + 'toggle for oslo.cache(enabled=True in [cache] group) ' |
727 | + 'must be enabled to use this feature.')) |
728 | +] |
729 | + |
730 | |
731 | def register_cache_configurations(conf): |
732 | """Register all configurations required for oslo.cache. |
733 | @@ -35,65 +85,24 @@ def register_cache_configurations(conf): |
734 | core.configure(conf) |
735 | |
736 | # register heat specific configurations |
737 | - constraint_cache_group = cfg.OptGroup('constraint_validation_cache') |
738 | - constraint_cache_opts = [ |
739 | - cfg.IntOpt('expiration_time', default=60, |
740 | - help=_( |
741 | - 'TTL, in seconds, for any cached item in the ' |
742 | - 'dogpile.cache region used for caching of validation ' |
743 | - 'constraints.')), |
744 | - cfg.BoolOpt("caching", default=True, |
745 | - help=_( |
746 | - 'Toggle to enable/disable caching when Orchestration ' |
747 | - 'Engine validates property constraints of stack. ' |
748 | - 'During property validation with constraints ' |
749 | - 'Orchestration Engine caches requests to other ' |
750 | - 'OpenStack services. Please note that the global ' |
751 | - 'toggle for oslo.cache(enabled=True in [cache] group) ' |
752 | - 'must be enabled to use this feature.')) |
753 | - ] |
754 | conf.register_group(constraint_cache_group) |
755 | conf.register_opts(constraint_cache_opts, group=constraint_cache_group) |
756 | |
757 | - extension_cache_group = cfg.OptGroup('service_extension_cache') |
758 | - extension_cache_opts = [ |
759 | - cfg.IntOpt('expiration_time', default=3600, |
760 | - help=_( |
761 | - 'TTL, in seconds, for any cached item in the ' |
762 | - 'dogpile.cache region used for caching of service ' |
763 | - 'extensions.')), |
764 | - cfg.BoolOpt('caching', default=True, |
765 | - help=_( |
766 | - 'Toggle to enable/disable caching when Orchestration ' |
767 | - 'Engine retrieves extensions from other OpenStack ' |
768 | - 'services. Please note that the global toggle for ' |
769 | - 'oslo.cache(enabled=True in [cache] group) must be ' |
770 | - 'enabled to use this feature.')) |
771 | - ] |
772 | conf.register_group(extension_cache_group) |
773 | conf.register_opts(extension_cache_opts, group=extension_cache_group) |
774 | |
775 | - find_cache_group = cfg.OptGroup('resource_finder_cache') |
776 | - find_cache_opts = [ |
777 | - cfg.IntOpt('expiration_time', default=3600, |
778 | - help=_( |
779 | - 'TTL, in seconds, for any cached item in the ' |
780 | - 'dogpile.cache region used for caching of OpenStack ' |
781 | - 'service finder functions.')), |
782 | - cfg.BoolOpt('caching', default=True, |
783 | - help=_( |
784 | - 'Toggle to enable/disable caching when Orchestration ' |
785 | - 'Engine looks for other OpenStack service resources ' |
786 | - 'using name or id. Please note that the global ' |
787 | - 'toggle for oslo.cache(enabled=True in [cache] group) ' |
788 | - 'must be enabled to use this feature.')) |
789 | - ] |
790 | conf.register_group(find_cache_group) |
791 | conf.register_opts(find_cache_opts, group=find_cache_group) |
792 | |
793 | return conf |
794 | |
795 | |
796 | +def list_opts(): |
797 | + yield constraint_cache_group.name, constraint_cache_opts |
798 | + yield extension_cache_group.name, extension_cache_opts |
799 | + yield find_cache_group.name, find_cache_opts |
800 | + |
801 | + |
802 | # variable that stores an initialized cache region for heat |
803 | _REGION = None |
804 | |
805 | diff --git a/heat/common/config.py b/heat/common/config.py |
806 | index 1e1df6f..c6a1dfc 100644 |
807 | --- a/heat/common/config.py |
808 | +++ b/heat/common/config.py |
809 | @@ -152,6 +152,19 @@ engine_opts = [ |
810 | default=512, |
811 | help=_('Maximum number of stacks any one tenant may have ' |
812 | 'active at one time. -1 stands for unlimited.')), |
813 | + cfg.IntOpt('max_software_configs_per_tenant', |
814 | + default=4096, |
815 | + help=_('Maximum number of software configs any one tenant may ' |
816 | + 'have active at one time. -1 stands for unlimited.')), |
817 | + cfg.IntOpt('max_software_deployments_per_tenant', |
818 | + default=4096, |
819 | + help=_('Maximum number of software deployments any one tenant ' |
820 | + 'may have active at one time.' |
821 | + '-1 stands for unlimited.')), |
822 | + cfg.IntOpt('max_snapshots_per_stack', |
823 | + default=32, |
824 | + help=_('Maximum number of snapshot any one stack may have ' |
825 | + 'active at one time. -1 stands for unlimited.')), |
826 | cfg.IntOpt('action_retry_limit', |
827 | default=5, |
828 | help=_('Number of times to retry to bring a ' |
829 | diff --git a/heat/common/plugin_loader.py b/heat/common/plugin_loader.py |
830 | index 9023374..7ea933d 100644 |
831 | --- a/heat/common/plugin_loader.py |
832 | +++ b/heat/common/plugin_loader.py |
833 | @@ -20,6 +20,7 @@ for them before loading them. |
834 | """ |
835 | |
836 | import functools |
837 | +import importlib.util |
838 | import pkgutil |
839 | import sys |
840 | import types |
841 | @@ -70,7 +71,8 @@ def _import_module(importer, module_name, package): |
842 | if module_spec is None: |
843 | return None |
844 | |
845 | - module = module_spec.loader.load_module(module_name) |
846 | + module = importlib.util.module_from_spec(module_spec) |
847 | + module_spec.loader.exec_module(module) |
848 | |
849 | # Make this accessible through the parent package for static imports |
850 | local_name = module_name.partition(package.__name__ + '.')[2] |
851 | diff --git a/heat/db/api.py b/heat/db/api.py |
852 | index 70aab59..0d03547 100644 |
853 | --- a/heat/db/api.py |
854 | +++ b/heat/db/api.py |
855 | @@ -1431,6 +1431,14 @@ def software_config_get_all(context, limit=None, marker=None): |
856 | limit=limit, marker=marker).all() |
857 | |
858 | |
859 | +@context_manager.reader |
860 | +def software_config_count_all(context): |
861 | + query = context.session.query(models.SoftwareConfig) |
862 | + if not context.is_admin: |
863 | + query = query.filter_by(tenant=context.tenant_id) |
864 | + return query.count() |
865 | + |
866 | + |
867 | @context_manager.writer |
868 | def software_config_delete(context, config_id): |
869 | config = _software_config_get(context, config_id) |
870 | @@ -1510,6 +1518,21 @@ def software_deployment_get_all(context, server_id=None): |
871 | return query.all() |
872 | |
873 | |
874 | +@context_manager.reader |
875 | +def software_deployment_count_all(context): |
876 | + sd = models.SoftwareDeployment |
877 | + query = context.session.query(sd) |
878 | + if not context.is_admin: |
879 | + query = query.filter( |
880 | + sqlalchemy.or_( |
881 | + sd.tenant == context.tenant_id, |
882 | + sd.stack_user_project_id == context.tenant_id, |
883 | + ) |
884 | + ) |
885 | + |
886 | + return query.count() |
887 | + |
888 | + |
889 | @context_manager.writer |
890 | def software_deployment_update(context, deployment_id, values): |
891 | deployment = _software_deployment_get(context, deployment_id) |
892 | @@ -1582,11 +1605,17 @@ def snapshot_delete(context, snapshot_id): |
893 | |
894 | |
895 | @context_manager.reader |
896 | -def snapshot_get_all(context, stack_id): |
897 | +def snapshot_get_all_by_stack(context, stack_id): |
898 | return context.session.query(models.Snapshot).filter_by( |
899 | stack_id=stack_id, tenant=context.tenant_id) |
900 | |
901 | |
902 | +@context_manager.reader |
903 | +def snapshot_count_all_by_stack(context, stack_id): |
904 | + return context.session.query(models.Snapshot).filter_by( |
905 | + stack_id=stack_id, tenant=context.tenant_id).count() |
906 | + |
907 | + |
908 | # service |
909 | |
910 | |
911 | diff --git a/heat/engine/clients/os/keystone/fake_keystoneclient.py b/heat/engine/clients/os/keystone/fake_keystoneclient.py |
912 | index 9715c95..d2d2879 100644 |
913 | --- a/heat/engine/clients/os/keystone/fake_keystoneclient.py |
914 | +++ b/heat/engine/clients/os/keystone/fake_keystoneclient.py |
915 | @@ -51,7 +51,7 @@ class FakeKeystoneClient(object): |
916 | secret = self.secret |
917 | self.creds = FakeCred() |
918 | |
919 | - def create_stack_user(self, username, password=''): |
920 | + def create_stack_user(self, username, password): |
921 | self.username = username |
922 | return self.user_id |
923 | |
924 | diff --git a/heat/engine/clients/os/keystone/heat_keystoneclient.py b/heat/engine/clients/os/keystone/heat_keystoneclient.py |
925 | index 7f993ec..2cf8ee9 100644 |
926 | --- a/heat/engine/clients/os/keystone/heat_keystoneclient.py |
927 | +++ b/heat/engine/clients/os/keystone/heat_keystoneclient.py |
928 | @@ -277,13 +277,13 @@ class KsClientWrapper(object): |
929 | return trust_context |
930 | |
931 | def _get_username(self, username): |
932 | - if(len(username) > 255): |
933 | + if len(username) > 255: |
934 | LOG.warning("Truncating the username %s to the last 255 " |
935 | "characters.", username) |
936 | # get the last 255 characters of the username |
937 | return username[-255:] |
938 | |
939 | - def create_stack_user(self, username, password=''): |
940 | + def create_stack_user(self, username, password): |
941 | """Create a user defined as part of a stack. |
942 | |
943 | The user is defined either via template or created internally by a |
944 | diff --git a/heat/engine/constraint/common_constraints.py b/heat/engine/constraint/common_constraints.py |
945 | index cef2571..5588ef7 100644 |
946 | --- a/heat/engine/constraint/common_constraints.py |
947 | +++ b/heat/engine/constraint/common_constraints.py |
948 | @@ -14,7 +14,13 @@ |
949 | import croniter |
950 | import eventlet |
951 | import netaddr |
952 | -import pytz |
953 | + |
954 | +try: |
955 | + import zoneinfo |
956 | +except ImportError: |
957 | + # zoneinfo is available in Python >= 3.9 |
958 | + import pytz |
959 | + zoneinfo = None |
960 | |
961 | from neutron_lib.api import validators |
962 | from oslo_utils import timeutils |
963 | @@ -106,7 +112,7 @@ class CIDRConstraint(constraints.BaseCustomConstraint): |
964 | |
965 | def validate(self, value, context, template=None): |
966 | try: |
967 | - netaddr.IPNetwork(value, implicit_prefix=True) |
968 | + netaddr.IPNetwork(netaddr.cidr_abbrev_to_verbose(value)) |
969 | msg = validators.validate_subnet(value) |
970 | if msg is not None: |
971 | self._error_message = msg |
972 | @@ -167,7 +173,10 @@ class TimezoneConstraint(constraints.BaseCustomConstraint): |
973 | if not value: |
974 | return True |
975 | try: |
976 | - pytz.timezone(value) |
977 | + if zoneinfo: |
978 | + zoneinfo.ZoneInfo(value) |
979 | + else: |
980 | + pytz.timezone(value) |
981 | return True |
982 | except Exception as ex: |
983 | self._error_message = _( |
984 | diff --git a/heat/engine/hot/functions.py b/heat/engine/hot/functions.py |
985 | index ec4bb9d..0e63574 100644 |
986 | --- a/heat/engine/hot/functions.py |
987 | +++ b/heat/engine/hot/functions.py |
988 | @@ -31,7 +31,8 @@ from heat.engine import function |
989 | |
990 | LOG = logging.getLogger(__name__) |
991 | |
992 | -opts = [ |
993 | +yaql_group = cfg.OptGroup('yaql') |
994 | +yaql_opts = [ |
995 | cfg.IntOpt('limit_iterators', |
996 | default=200, |
997 | help=_('The maximum number of elements in collection ' |
998 | @@ -41,7 +42,11 @@ opts = [ |
999 | help=_('The maximum size of memory in bytes that ' |
1000 | 'expression can take for its evaluation.')) |
1001 | ] |
1002 | -cfg.CONF.register_opts(opts, group='yaql') |
1003 | +cfg.CONF.register_opts(yaql_opts, group=yaql_group) |
1004 | + |
1005 | + |
1006 | +def list_opts(): |
1007 | + yield yaql_group.name, yaql_opts |
1008 | |
1009 | |
1010 | class GetParam(function.Function): |
1011 | diff --git a/heat/engine/resource.py b/heat/engine/resource.py |
1012 | index c8e5c0e..e40fdb9 100644 |
1013 | --- a/heat/engine/resource.py |
1014 | +++ b/heat/engine/resource.py |
1015 | @@ -809,7 +809,7 @@ class Resource(status.ResourceStatus): |
1016 | if endpoint_exists: |
1017 | req_extension = cls.required_service_extension |
1018 | if not req_extension: |
1019 | - return(True, None) |
1020 | + return (True, None) |
1021 | if isinstance(req_extension, str): |
1022 | req_extension = re.split(' |,', req_extension) |
1023 | for ext in req_extension: |
1024 | diff --git a/heat/engine/resources/openstack/monasca/alarm_definition.py b/heat/engine/resources/openstack/monasca/alarm_definition.py |
1025 | index 3af1fa2..dea669e 100644 |
1026 | --- a/heat/engine/resources/openstack/monasca/alarm_definition.py |
1027 | +++ b/heat/engine/resources/openstack/monasca/alarm_definition.py |
1028 | @@ -32,11 +32,15 @@ class MonascaAlarmDefinition(resource.Resource): |
1029 | """ |
1030 | |
1031 | support_status = support.SupportStatus( |
1032 | - version='7.0.0', |
1033 | + version='22.0.0', |
1034 | + status=support.DEPRECATED, |
1035 | + message=_('Monasca project was marked inactive'), |
1036 | previous_status=support.SupportStatus( |
1037 | - version='5.0.0', |
1038 | - status=support.UNSUPPORTED |
1039 | - )) |
1040 | + version='7.0.0', |
1041 | + previous_status=support.SupportStatus( |
1042 | + version='5.0.0', |
1043 | + status=support.UNSUPPORTED |
1044 | + ))) |
1045 | |
1046 | default_client_name = 'monasca' |
1047 | |
1048 | diff --git a/heat/engine/resources/openstack/monasca/notification.py b/heat/engine/resources/openstack/monasca/notification.py |
1049 | index 8074bd0..65a155d 100644 |
1050 | --- a/heat/engine/resources/openstack/monasca/notification.py |
1051 | +++ b/heat/engine/resources/openstack/monasca/notification.py |
1052 | @@ -32,11 +32,16 @@ class MonascaNotification(resource.Resource): |
1053 | """ |
1054 | |
1055 | support_status = support.SupportStatus( |
1056 | - version='7.0.0', |
1057 | + version='22.0.0', |
1058 | + status=support.DEPRECATED, |
1059 | + message=_('Monasca project was marked inactive'), |
1060 | previous_status=support.SupportStatus( |
1061 | - version='5.0.0', |
1062 | - status=support.UNSUPPORTED |
1063 | - )) |
1064 | + version='7.0.0', |
1065 | + status=support.SUPPORTED, |
1066 | + previous_status=support.SupportStatus( |
1067 | + version='5.0.0', |
1068 | + status=support.SUPPORTED |
1069 | + ))) |
1070 | |
1071 | default_client_name = 'monasca' |
1072 | |
1073 | diff --git a/heat/engine/resources/openstack/neutron/port.py b/heat/engine/resources/openstack/neutron/port.py |
1074 | index a06fbf3..58f3029 100644 |
1075 | --- a/heat/engine/resources/openstack/neutron/port.py |
1076 | +++ b/heat/engine/resources/openstack/neutron/port.py |
1077 | @@ -545,7 +545,7 @@ class Port(neutron.NeutronResource): |
1078 | ).get_secgroup_uuids(['default']) |
1079 | |
1080 | if self.REPLACEMENT_POLICY in props: |
1081 | - del(props[self.REPLACEMENT_POLICY]) |
1082 | + del props[self.REPLACEMENT_POLICY] |
1083 | |
1084 | def _store_config_default_properties(self, attrs): |
1085 | """A method for storing properties default values. |
1086 | diff --git a/heat/engine/resources/openstack/neutron/security_group.py b/heat/engine/resources/openstack/neutron/security_group.py |
1087 | index 0bd867c..f88d589 100644 |
1088 | --- a/heat/engine/resources/openstack/neutron/security_group.py |
1089 | +++ b/heat/engine/resources/openstack/neutron/security_group.py |
1090 | @@ -180,7 +180,7 @@ class SecurityGroup(neutron.NeutronResource): |
1091 | |
1092 | if 'remote_mode' in rule: |
1093 | remote_mode = rule.get(self.RULE_REMOTE_MODE) |
1094 | - del(rule[self.RULE_REMOTE_MODE]) |
1095 | + del rule[self.RULE_REMOTE_MODE] |
1096 | |
1097 | if remote_mode == self.RULE_REMOTE_GROUP_ID: |
1098 | rule[self.RULE_REMOTE_IP_PREFIX] = None |
1099 | diff --git a/heat/engine/resources/openstack/sahara/cluster.py b/heat/engine/resources/openstack/sahara/cluster.py |
1100 | index 05a0def..6dc45a6 100644 |
1101 | --- a/heat/engine/resources/openstack/sahara/cluster.py |
1102 | +++ b/heat/engine/resources/openstack/sahara/cluster.py |
1103 | @@ -49,6 +49,15 @@ class SaharaCluster(resource.Resource): |
1104 | should specify a keypair. |
1105 | """ |
1106 | |
1107 | + support_status = support.SupportStatus( |
1108 | + version='22.0.0', |
1109 | + status=support.DEPRECATED, |
1110 | + message=_('Sahara project was marked inactive'), |
1111 | + previous_status=support.SupportStatus( |
1112 | + version='5.0.0', |
1113 | + status=support.SUPPORTED |
1114 | + )) |
1115 | + |
1116 | PROPERTIES = ( |
1117 | NAME, PLUGIN_NAME, HADOOP_VERSION, CLUSTER_TEMPLATE_ID, |
1118 | KEY_NAME, IMAGE, MANAGEMENT_NETWORK, IMAGE_ID, |
1119 | diff --git a/heat/engine/resources/openstack/sahara/data_source.py b/heat/engine/resources/openstack/sahara/data_source.py |
1120 | index ff41bf4..c793f89 100644 |
1121 | --- a/heat/engine/resources/openstack/sahara/data_source.py |
1122 | +++ b/heat/engine/resources/openstack/sahara/data_source.py |
1123 | @@ -26,7 +26,14 @@ class DataSource(resource.Resource): |
1124 | or output data and any credentials needed to access the location. |
1125 | """ |
1126 | |
1127 | - support_status = support.SupportStatus(version='5.0.0') |
1128 | + support_status = support.SupportStatus( |
1129 | + version='22.0.0', |
1130 | + status=support.DEPRECATED, |
1131 | + message=_('Sahara project was marked inactive'), |
1132 | + previous_status=support.SupportStatus( |
1133 | + version='5.0.0', |
1134 | + status=support.SUPPORTED |
1135 | + )) |
1136 | |
1137 | PROPERTIES = ( |
1138 | NAME, TYPE, URL, DESCRIPTION, CREDENTIALS |
1139 | diff --git a/heat/engine/resources/openstack/sahara/image.py b/heat/engine/resources/openstack/sahara/image.py |
1140 | index dc60c72..152fbb1 100644 |
1141 | --- a/heat/engine/resources/openstack/sahara/image.py |
1142 | +++ b/heat/engine/resources/openstack/sahara/image.py |
1143 | @@ -26,7 +26,14 @@ class SaharaImageRegistry(resource.Resource): |
1144 | Allows to register an image in the sahara image registry and add tags. |
1145 | """ |
1146 | |
1147 | - support_status = support.SupportStatus(version='6.0.0') |
1148 | + support_status = support.SupportStatus( |
1149 | + version='22.0.0', |
1150 | + status=support.DEPRECATED, |
1151 | + message=_('Sahara project was marked inactive'), |
1152 | + previous_status=support.SupportStatus( |
1153 | + version='5.0.0', |
1154 | + status=support.SUPPORTED |
1155 | + )) |
1156 | |
1157 | PROPERTIES = ( |
1158 | IMAGE, USERNAME, DESCRIPTION, TAGS |
1159 | diff --git a/heat/engine/resources/openstack/sahara/job.py b/heat/engine/resources/openstack/sahara/job.py |
1160 | index cda9679..63ca204 100644 |
1161 | --- a/heat/engine/resources/openstack/sahara/job.py |
1162 | +++ b/heat/engine/resources/openstack/sahara/job.py |
1163 | @@ -33,7 +33,14 @@ class SaharaJob(signal_responder.SignalResponder, resource.Resource): |
1164 | job binary objects. Can be launched using resource-signal. |
1165 | """ |
1166 | |
1167 | - support_status = support.SupportStatus(version='8.0.0') |
1168 | + support_status = support.SupportStatus( |
1169 | + version='22.0.0', |
1170 | + status=support.DEPRECATED, |
1171 | + message=_('Sahara project was marked inactive'), |
1172 | + previous_status=support.SupportStatus( |
1173 | + version='8.0.0', |
1174 | + status=support.SUPPORTED |
1175 | + )) |
1176 | |
1177 | PROPERTIES = ( |
1178 | NAME, TYPE, MAINS, LIBS, DESCRIPTION, |
1179 | diff --git a/heat/engine/resources/openstack/sahara/job_binary.py b/heat/engine/resources/openstack/sahara/job_binary.py |
1180 | index 85cf705..f1e05af 100644 |
1181 | --- a/heat/engine/resources/openstack/sahara/job_binary.py |
1182 | +++ b/heat/engine/resources/openstack/sahara/job_binary.py |
1183 | @@ -29,7 +29,14 @@ class JobBinary(resource.Resource): |
1184 | credentials needed to retrieve the file. |
1185 | """ |
1186 | |
1187 | - support_status = support.SupportStatus(version='5.0.0') |
1188 | + support_status = support.SupportStatus( |
1189 | + version='22.0.0', |
1190 | + status=support.DEPRECATED, |
1191 | + message=_('Sahara project was marked inactive'), |
1192 | + previous_status=support.SupportStatus( |
1193 | + version='5.0.0', |
1194 | + status=support.SUPPORTED |
1195 | + )) |
1196 | |
1197 | PROPERTIES = ( |
1198 | NAME, URL, DESCRIPTION, CREDENTIALS |
1199 | diff --git a/heat/engine/resources/openstack/sahara/templates.py b/heat/engine/resources/openstack/sahara/templates.py |
1200 | index 0f52a2a..c49ee01 100644 |
1201 | --- a/heat/engine/resources/openstack/sahara/templates.py |
1202 | +++ b/heat/engine/resources/openstack/sahara/templates.py |
1203 | @@ -44,7 +44,14 @@ class SaharaNodeGroupTemplate(resource.Resource): |
1204 | configurations for those processes. |
1205 | """ |
1206 | |
1207 | - support_status = support.SupportStatus(version='2014.2') |
1208 | + support_status = support.SupportStatus( |
1209 | + version='22.0.0', |
1210 | + status=support.DEPRECATED, |
1211 | + message=_('Sahara project was marked inactive'), |
1212 | + previous_status=support.SupportStatus( |
1213 | + version='2014.2', |
1214 | + status=support.SUPPORTED |
1215 | + )) |
1216 | |
1217 | PROPERTIES = ( |
1218 | NAME, PLUGIN_NAME, HADOOP_VERSION, FLAVOR, DESCRIPTION, |
1219 | diff --git a/heat/engine/resources/openstack/senlin/res_base.py b/heat/engine/resources/openstack/senlin/res_base.py |
1220 | index a294df1..3df3fd6 100644 |
1221 | --- a/heat/engine/resources/openstack/senlin/res_base.py |
1222 | +++ b/heat/engine/resources/openstack/senlin/res_base.py |
1223 | @@ -14,6 +14,7 @@ |
1224 | |
1225 | from oslo_log import log as logging |
1226 | |
1227 | +from heat.common.i18n import _ |
1228 | from heat.engine import resource |
1229 | from heat.engine import support |
1230 | |
1231 | @@ -23,7 +24,13 @@ LOG = logging.getLogger(__name__) |
1232 | class BaseSenlinResource(resource.Resource): |
1233 | """A base class for Senlin resources.""" |
1234 | |
1235 | - support_status = support.SupportStatus(version='6.0.0') |
1236 | + support_status = support.SupportStatus( |
1237 | + version='22.0.0', |
1238 | + status=support.DEPRECATED, |
1239 | + message=_('Senlin project was marked inactive'), |
1240 | + previous_status=support.SupportStatus( |
1241 | + version='6.0.0', |
1242 | + )) |
1243 | |
1244 | default_client_name = 'senlin' |
1245 | |
1246 | diff --git a/heat/engine/service.py b/heat/engine/service.py |
1247 | index 9019ddb..037c912 100644 |
1248 | --- a/heat/engine/service.py |
1249 | +++ b/heat/engine/service.py |
1250 | @@ -73,6 +73,10 @@ from heat.rpc import worker_api as rpc_worker_api |
1251 | cfg.CONF.import_opt('engine_life_check_timeout', 'heat.common.config') |
1252 | cfg.CONF.import_opt('max_resources_per_stack', 'heat.common.config') |
1253 | cfg.CONF.import_opt('max_stacks_per_tenant', 'heat.common.config') |
1254 | +cfg.CONF.import_opt('max_snapshots_per_stack', 'heat.common.config') |
1255 | +cfg.CONF.import_opt('max_software_configs_per_tenant', 'heat.common.config') |
1256 | +cfg.CONF.import_opt('max_software_deployments_per_tenant', |
1257 | + 'heat.common.config') |
1258 | cfg.CONF.import_opt('enable_stack_abandon', 'heat.common.config') |
1259 | cfg.CONF.import_opt('enable_stack_adopt', 'heat.common.config') |
1260 | cfg.CONF.import_opt('convergence_engine', 'heat.common.config') |
1261 | @@ -2124,6 +2128,17 @@ class EngineService(service.ServiceBase): |
1262 | raise exception.ActionInProgress(stack_name=stack.name, |
1263 | action=stack.action) |
1264 | |
1265 | + # Do not enforce the limit, following the stack limit |
1266 | + if not cnxt.is_admin: |
1267 | + stack_limit = cfg.CONF.max_snapshots_per_stack |
1268 | + count_all = snapshot_object.Snapshot.count_all_by_stack(cnxt, |
1269 | + stack.id) |
1270 | + if (stack_limit >= 0 and count_all >= stack_limit): |
1271 | + message = _("You have reached the maximum snapshots " |
1272 | + "per stack, %d. Please delete some " |
1273 | + "snapshots.") % stack_limit |
1274 | + raise exception.RequestLimitExceeded(message=message) |
1275 | + |
1276 | lock = stack_lock.StackLock(cnxt, stack.id, self.engine_id) |
1277 | |
1278 | with lock.thread_lock(): |
1279 | @@ -2198,7 +2213,7 @@ class EngineService(service.ServiceBase): |
1280 | @context.request_context |
1281 | def stack_list_snapshots(self, cnxt, stack_identity): |
1282 | s = self._get_stack(cnxt, stack_identity) |
1283 | - data = snapshot_object.Snapshot.get_all(cnxt, s.id) |
1284 | + data = snapshot_object.Snapshot.get_all_by_stack(cnxt, s.id) |
1285 | return [api.format_snapshot(snapshot) for snapshot in data] |
1286 | |
1287 | @context.request_context |
1288 | @@ -2219,6 +2234,15 @@ class EngineService(service.ServiceBase): |
1289 | @context.request_context |
1290 | def create_software_config(self, cnxt, group, name, config, |
1291 | inputs, outputs, options): |
1292 | + # Do not enforce the limit, following the stack limit |
1293 | + if not cnxt.is_admin: |
1294 | + tenant_limit = cfg.CONF.max_software_configs_per_tenant |
1295 | + count_all = self.software_config.count_software_config(cnxt) |
1296 | + if (tenant_limit >= 0 and count_all >= tenant_limit): |
1297 | + message = _("You have reached the maximum software configs " |
1298 | + "per tenant, %d. " |
1299 | + "Please delete some configs.") % tenant_limit |
1300 | + raise exception.RequestLimitExceeded(message=message) |
1301 | return self.software_config.create_software_config( |
1302 | cnxt, |
1303 | group=group, |
1304 | @@ -2257,6 +2281,16 @@ class EngineService(service.ServiceBase): |
1305 | input_values, action, status, |
1306 | status_reason, stack_user_project_id, |
1307 | deployment_id=None): |
1308 | + # Do not enforce the limit, following the stack limit |
1309 | + if not cnxt.is_admin: |
1310 | + tenant_limit = cfg.CONF.max_software_deployments_per_tenant |
1311 | + count_all = self.software_config.count_software_deployment(cnxt) |
1312 | + if (tenant_limit >= 0 and |
1313 | + count_all >= tenant_limit): |
1314 | + message = _("You have reached the maximum software " |
1315 | + "deployments per tenant, %d. " |
1316 | + "Please delete some deployments.") % tenant_limit |
1317 | + raise exception.RequestLimitExceeded(message=message) |
1318 | return self.software_config.create_software_deployment( |
1319 | cnxt, server_id=server_id, |
1320 | config_id=config_id, |
1321 | diff --git a/heat/engine/service_software_config.py b/heat/engine/service_software_config.py |
1322 | index 1c1fcb4..ce5001b 100644 |
1323 | --- a/heat/engine/service_software_config.py |
1324 | +++ b/heat/engine/service_software_config.py |
1325 | @@ -52,6 +52,9 @@ class SoftwareConfigService(object): |
1326 | for sc in scs] |
1327 | return result |
1328 | |
1329 | + def count_software_config(self, cnxt): |
1330 | + return software_config_object.SoftwareConfig.count_all(cnxt) |
1331 | + |
1332 | def create_software_config(self, cnxt, group, name, config, |
1333 | inputs, outputs, options): |
1334 | |
1335 | @@ -81,6 +84,10 @@ class SoftwareConfigService(object): |
1336 | result = [api.format_software_deployment(sd) for sd in all_sd] |
1337 | return result |
1338 | |
1339 | + def count_software_deployment(self, cnxt): |
1340 | + return software_deployment_object.SoftwareDeployment.count_all( |
1341 | + cnxt) |
1342 | + |
1343 | def metadata_software_deployments(self, cnxt, server_id): |
1344 | if not server_id: |
1345 | raise ValueError(_('server_id must be specified')) |
1346 | diff --git a/heat/engine/stack.py b/heat/engine/stack.py |
1347 | index c7ebec1..caad797 100644 |
1348 | --- a/heat/engine/stack.py |
1349 | +++ b/heat/engine/stack.py |
1350 | @@ -1343,7 +1343,7 @@ class Stack(collections.abc.Mapping): |
1351 | elif create_if_missing: |
1352 | kwargs = self.get_kwargs_for_cloning(keep_tags=True) |
1353 | kwargs['owner_id'] = self.id |
1354 | - del(kwargs['prev_raw_template_id']) |
1355 | + del kwargs['prev_raw_template_id'] |
1356 | prev = type(self)(self.context, self._backup_name(), |
1357 | copy.deepcopy(self.t), |
1358 | **kwargs) |
1359 | @@ -2132,7 +2132,8 @@ class Stack(collections.abc.Mapping): |
1360 | |
1361 | def delete_all_snapshots(self): |
1362 | """Remove all snapshots for this stack.""" |
1363 | - snapshots = snapshot_object.Snapshot.get_all(self.context, self.id) |
1364 | + snapshots = snapshot_object.Snapshot.get_all_by_stack( |
1365 | + self.context, self.id) |
1366 | for snapshot in snapshots: |
1367 | self.delete_snapshot(snapshot) |
1368 | snapshot_object.Snapshot.delete(self.context, snapshot.id) |
1369 | diff --git a/heat/hacking/checks.py b/heat/hacking/checks.py |
1370 | index 4c39435..dcce567 100644 |
1371 | --- a/heat/hacking/checks.py |
1372 | +++ b/heat/hacking/checks.py |
1373 | @@ -26,7 +26,7 @@ Guidelines for writing new hacking checks |
1374 | - Pick numbers in the range H3xx. Find the current test with |
1375 | the highest allocated number and then pick the next value. |
1376 | - Keep the test method code in the source file ordered based |
1377 | - on the Heat3xx value. |
1378 | + on the HE3xx value. |
1379 | - List the new rule in the top level HACKING.rst file |
1380 | - Add test cases for each new rule to heat/tests/test_hacking.py |
1381 | |
1382 | @@ -39,31 +39,31 @@ def no_log_warn(logical_line): |
1383 | |
1384 | https://bugs.launchpad.net/tempest/+bug/1508442 |
1385 | |
1386 | - Heat301 |
1387 | + HE301 |
1388 | """ |
1389 | if logical_line.startswith('LOG.warn('): |
1390 | - yield(0, 'Heat301 Use LOG.warning() rather than LOG.warn()') |
1391 | + yield (0, 'HE301 Use LOG.warning() rather than LOG.warn()') |
1392 | |
1393 | |
1394 | @core.flake8ext |
1395 | def check_python3_no_iteritems(logical_line): |
1396 | - msg = ("Heat302: Use dict.items() instead of dict.iteritems().") |
1397 | + msg = ("HE302: Use dict.items() instead of dict.iteritems().") |
1398 | |
1399 | if re.search(r".*\.iteritems\(\)", logical_line): |
1400 | - yield(0, msg) |
1401 | + yield (0, msg) |
1402 | |
1403 | |
1404 | @core.flake8ext |
1405 | def check_python3_no_iterkeys(logical_line): |
1406 | - msg = ("Heat303: Use dict.keys() instead of dict.iterkeys().") |
1407 | + msg = ("HE303: Use dict.keys() instead of dict.iterkeys().") |
1408 | |
1409 | if re.search(r".*\.iterkeys\(\)", logical_line): |
1410 | - yield(0, msg) |
1411 | + yield (0, msg) |
1412 | |
1413 | |
1414 | @core.flake8ext |
1415 | def check_python3_no_itervalues(logical_line): |
1416 | - msg = ("Heat304: Use dict.values() instead of dict.itervalues().") |
1417 | + msg = ("HE304: Use dict.values() instead of dict.itervalues().") |
1418 | |
1419 | if re.search(r".*\.itervalues\(\)", logical_line): |
1420 | - yield(0, msg) |
1421 | + yield (0, msg) |
1422 | diff --git a/heat/objects/snapshot.py b/heat/objects/snapshot.py |
1423 | index 23d569a..8cd53aa 100644 |
1424 | --- a/heat/objects/snapshot.py |
1425 | +++ b/heat/objects/snapshot.py |
1426 | @@ -70,6 +70,11 @@ class Snapshot( |
1427 | db_api.snapshot_delete(context, snapshot_id) |
1428 | |
1429 | @classmethod |
1430 | - def get_all(cls, context, stack_id): |
1431 | + def get_all_by_stack(cls, context, stack_id): |
1432 | return [cls._from_db_object(context, cls(), db_snapshot) |
1433 | - for db_snapshot in db_api.snapshot_get_all(context, stack_id)] |
1434 | + for db_snapshot |
1435 | + in db_api.snapshot_get_all_by_stack(context, stack_id)] |
1436 | + |
1437 | + @classmethod |
1438 | + def count_all_by_stack(cls, context, stack_id): |
1439 | + return db_api.snapshot_count_all_by_stack(context, stack_id) |
1440 | diff --git a/heat/objects/software_config.py b/heat/objects/software_config.py |
1441 | index e0d9d42..df2cafb 100644 |
1442 | --- a/heat/objects/software_config.py |
1443 | +++ b/heat/objects/software_config.py |
1444 | @@ -66,5 +66,9 @@ class SoftwareConfig( |
1445 | return [cls._from_db_object(context, cls(), sc) for sc in scs] |
1446 | |
1447 | @classmethod |
1448 | + def count_all(cls, context, **kwargs): |
1449 | + return db_api.software_config_count_all(context, **kwargs) |
1450 | + |
1451 | + @classmethod |
1452 | def delete(cls, context, config_id): |
1453 | db_api.software_config_delete(context, config_id) |
1454 | diff --git a/heat/objects/software_deployment.py b/heat/objects/software_deployment.py |
1455 | index 564a484..d7cbc65 100644 |
1456 | --- a/heat/objects/software_deployment.py |
1457 | +++ b/heat/objects/software_deployment.py |
1458 | @@ -78,6 +78,11 @@ class SoftwareDeployment( |
1459 | context, server_id)] |
1460 | |
1461 | @classmethod |
1462 | + def count_all(cls, context): |
1463 | + return db_api.software_deployment_count_all( |
1464 | + context) |
1465 | + |
1466 | + @classmethod |
1467 | def update_by_id(cls, context, deployment_id, values): |
1468 | """Note this is a bit unusual as it returns the object. |
1469 | |
1470 | diff --git a/heat/tests/api/cfn/test_api_cfn_v1.py b/heat/tests/api/cfn/test_api_cfn_v1.py |
1471 | index 88d3764..f078521 100644 |
1472 | --- a/heat/tests/api/cfn/test_api_cfn_v1.py |
1473 | +++ b/heat/tests/api/cfn/test_api_cfn_v1.py |
1474 | @@ -266,8 +266,8 @@ class CfnStackControllerTest(common.HeatTestCase): |
1475 | u'stack_status': u'COMPLETE', |
1476 | u'description': u'blah', |
1477 | u'disable_rollback': 'true', |
1478 | - u'timeout_mins':60, |
1479 | - u'capabilities':[]}] |
1480 | + u'timeout_mins': 60, |
1481 | + u'capabilities': []}] |
1482 | |
1483 | self.m_call.side_effect = [identity, engine_resp] |
1484 | |
1485 | @@ -358,8 +358,8 @@ class CfnStackControllerTest(common.HeatTestCase): |
1486 | u'stack_status': u'COMPLETE', |
1487 | u'description': u'blah', |
1488 | u'disable_rollback': 'true', |
1489 | - u'timeout_mins':60, |
1490 | - u'capabilities':[]}] |
1491 | + u'timeout_mins': 60, |
1492 | + u'capabilities': []}] |
1493 | |
1494 | self.m_call.return_value = engine_resp |
1495 | |
1496 | diff --git a/heat/tests/api/openstack_v1/test_routes.py b/heat/tests/api/openstack_v1/test_routes.py |
1497 | index 29d1ae4..e929423 100644 |
1498 | --- a/heat/tests/api/openstack_v1/test_routes.py |
1499 | +++ b/heat/tests/api/openstack_v1/test_routes.py |
1500 | @@ -28,8 +28,8 @@ class RoutesTest(common.HeatTestCase): |
1501 | class_name = reflection.get_class_name(route['controller'].controller, |
1502 | fully_qualified=False) |
1503 | self.assertEqual(controller, class_name) |
1504 | - del(route['action']) |
1505 | - del(route['controller']) |
1506 | + del route['action'] |
1507 | + del route['controller'] |
1508 | self.assertEqual(params, route) |
1509 | |
1510 | def setUp(self): |
1511 | diff --git a/heat/tests/api/openstack_v1/test_stacks.py b/heat/tests/api/openstack_v1/test_stacks.py |
1512 | index ff0a575..da92d27 100644 |
1513 | --- a/heat/tests/api/openstack_v1/test_stacks.py |
1514 | +++ b/heat/tests/api/openstack_v1/test_stacks.py |
1515 | @@ -1608,7 +1608,7 @@ class StackControllerTest(tools.ControllerTest, common.HeatTestCase): |
1516 | u'stack_status': u'COMPLETE', |
1517 | u'description': u'blah', |
1518 | u'disable_rollback': True, |
1519 | - u'timeout_mins':60, |
1520 | + u'timeout_mins': 60, |
1521 | u'capabilities': [], |
1522 | } |
1523 | ] |
1524 | @@ -1674,7 +1674,7 @@ class StackControllerTest(tools.ControllerTest, common.HeatTestCase): |
1525 | u'stack_status': u'COMPLETE', |
1526 | u'description': u'blah', |
1527 | u'disable_rollback': True, |
1528 | - u'timeout_mins':60, |
1529 | + u'timeout_mins': 60, |
1530 | u'capabilities': [], |
1531 | } |
1532 | ] |
1533 | diff --git a/heat/tests/clients/test_swift_client.py b/heat/tests/clients/test_swift_client.py |
1534 | index ae04ae4..8ad43f7 100644 |
1535 | --- a/heat/tests/clients/test_swift_client.py |
1536 | +++ b/heat/tests/clients/test_swift_client.py |
1537 | @@ -14,7 +14,13 @@ |
1538 | import datetime |
1539 | from unittest import mock |
1540 | |
1541 | -import pytz |
1542 | +try: |
1543 | + import zoneinfo |
1544 | +except ImportError: |
1545 | + # zoneinfo is available in Python >= 3.9 |
1546 | + import pytz |
1547 | + zoneinfo = None |
1548 | + |
1549 | from testtools import matchers |
1550 | |
1551 | from heat.engine.clients.os import swift |
1552 | @@ -126,8 +132,12 @@ class SwiftUtilsTest(SwiftClientPluginTestCase): |
1553 | |
1554 | def test_parse_last_modified(self): |
1555 | self.assertIsNone(self.swift_plugin.parse_last_modified(None)) |
1556 | + if zoneinfo: |
1557 | + tz = zoneinfo.ZoneInfo('GMT') |
1558 | + else: |
1559 | + tz = pytz.timezone('GMT') |
1560 | now = datetime.datetime( |
1561 | - 2015, 2, 5, 1, 4, 40, 0, pytz.timezone('GMT')) |
1562 | + 2015, 2, 5, 1, 4, 40, 0, tz) |
1563 | now_naive = datetime.datetime( |
1564 | 2015, 2, 5, 1, 4, 40, 0) |
1565 | last_modified = now.strftime('%a, %d %b %Y %H:%M:%S %Z') |
1566 | diff --git a/heat/tests/constraints/test_common_constraints.py b/heat/tests/constraints/test_common_constraints.py |
1567 | index c466b06..03399bf 100644 |
1568 | --- a/heat/tests/constraints/test_common_constraints.py |
1569 | +++ b/heat/tests/constraints/test_common_constraints.py |
1570 | @@ -13,6 +13,12 @@ |
1571 | |
1572 | from unittest import mock |
1573 | |
1574 | +try: |
1575 | + import zoneinfo |
1576 | +except ImportError: |
1577 | + # zoneinfo is available in Python >= 3.9 |
1578 | + zoneinfo = None |
1579 | + |
1580 | from heat.engine.constraint import common_constraints as cc |
1581 | from heat.tests import common |
1582 | from heat.tests import utils |
1583 | @@ -279,7 +285,10 @@ class TimezoneConstraintTest(common.HeatTestCase): |
1584 | |
1585 | def test_validation_error(self): |
1586 | timezone = "wrong_timezone" |
1587 | - expected = "Invalid timezone: '%s'" % timezone |
1588 | + err = timezone |
1589 | + if zoneinfo: |
1590 | + err = "No time zone found with key %s" % timezone |
1591 | + expected = "Invalid timezone: '%s'" % err |
1592 | |
1593 | self.assertFalse(self.constraint.validate(timezone, self.ctx)) |
1594 | self.assertEqual( |
1595 | diff --git a/heat/tests/convergence/framework/engine_wrapper.py b/heat/tests/convergence/framework/engine_wrapper.py |
1596 | index c1fb47c..062229c 100644 |
1597 | --- a/heat/tests/convergence/framework/engine_wrapper.py |
1598 | +++ b/heat/tests/convergence/framework/engine_wrapper.py |
1599 | @@ -54,13 +54,13 @@ class Engine(message_processor.MessageProcessor): |
1600 | if props: |
1601 | props_def = {} |
1602 | for prop_name, prop_value in props.items(): |
1603 | - if type(prop_value) == scenario_template.GetRes: |
1604 | - prop_res = getattr(prop_value, "target_name") |
1605 | - prop_value = {'get_resource': prop_res} |
1606 | - elif type(prop_value) == scenario_template.GetAtt: |
1607 | + if isinstance(prop_value, scenario_template.GetAtt): |
1608 | prop_res = getattr(prop_value, "target_name") |
1609 | prop_attr = getattr(prop_value, "attr") |
1610 | prop_value = {'get_attr': [prop_res, prop_attr]} |
1611 | + elif isinstance(prop_value, scenario_template.GetRes): |
1612 | + prop_res = getattr(prop_value, "target_name") |
1613 | + prop_value = {'get_resource': prop_res} |
1614 | props_def[prop_name] = prop_value |
1615 | res_defn["properties"] = props_def |
1616 | if depends: |
1617 | diff --git a/heat/tests/db/test_sqlalchemy_api.py b/heat/tests/db/test_sqlalchemy_api.py |
1618 | index 5689f2e..26166a9 100644 |
1619 | --- a/heat/tests/db/test_sqlalchemy_api.py |
1620 | +++ b/heat/tests/db/test_sqlalchemy_api.py |
1621 | @@ -1121,6 +1121,13 @@ class SqlAlchemyTest(common.HeatTestCase): |
1622 | tenant_id='admin_tenant') |
1623 | self._test_software_config_get_all(get_ctx=admin_ctx) |
1624 | |
1625 | + def test_software_config_count_all(self): |
1626 | + self.assertEqual(0, db_api.software_config_count_all(self.ctx)) |
1627 | + self._create_software_config_record() |
1628 | + self._create_software_config_record() |
1629 | + self._create_software_config_record() |
1630 | + self.assertEqual(3, db_api.software_config_count_all(self.ctx)) |
1631 | + |
1632 | def test_software_config_delete(self): |
1633 | scf_id = self._create_software_config_record() |
1634 | |
1635 | @@ -1250,6 +1257,17 @@ class SqlAlchemyTest(common.HeatTestCase): |
1636 | deployments = db_api.software_deployment_get_all(admin_ctx) |
1637 | self.assertEqual(1, len(deployments)) |
1638 | |
1639 | + def test_software_deployment_count_all(self): |
1640 | + self.assertEqual(0, db_api.software_deployment_count_all(self.ctx)) |
1641 | + values = self._deployment_values() |
1642 | + deployment = db_api.software_deployment_create(self.ctx, values) |
1643 | + self.assertIsNotNone(deployment) |
1644 | + deployment = db_api.software_deployment_create(self.ctx, values) |
1645 | + self.assertIsNotNone(deployment) |
1646 | + deployment = db_api.software_deployment_create(self.ctx, values) |
1647 | + self.assertIsNotNone(deployment) |
1648 | + self.assertEqual(3, db_api.software_deployment_count_all(self.ctx)) |
1649 | + |
1650 | def test_software_deployment_update(self): |
1651 | deployment_id = str(uuid.uuid4()) |
1652 | err = self.assertRaises(exception.NotFound, |
1653 | @@ -1421,7 +1439,7 @@ class SqlAlchemyTest(common.HeatTestCase): |
1654 | |
1655 | self.assertIn(snapshot_id, str(err)) |
1656 | |
1657 | - def test_snapshot_get_all(self): |
1658 | + def test_snapshot_get_all_by_stack(self): |
1659 | template = create_raw_template(self.ctx) |
1660 | user_creds = create_user_creds(self.ctx) |
1661 | stack = create_stack(self.ctx, template, user_creds) |
1662 | @@ -1429,12 +1447,44 @@ class SqlAlchemyTest(common.HeatTestCase): |
1663 | 'stack_id': stack.id} |
1664 | snapshot = db_api.snapshot_create(self.ctx, values) |
1665 | self.assertIsNotNone(snapshot) |
1666 | - [snapshot] = db_api.snapshot_get_all(self.ctx, stack.id) |
1667 | + [snapshot] = db_api.snapshot_get_all_by_stack(self.ctx, stack.id) |
1668 | self.assertIsNotNone(snapshot) |
1669 | self.assertEqual(values['tenant'], snapshot.tenant) |
1670 | self.assertEqual(values['status'], snapshot.status) |
1671 | self.assertIsNotNone(snapshot.created_at) |
1672 | |
1673 | + def test_snapshot_count_all_by_stack(self): |
1674 | + template = create_raw_template(self.ctx) |
1675 | + user_creds = create_user_creds(self.ctx) |
1676 | + stack1 = create_stack(self.ctx, template, user_creds) |
1677 | + stack2 = create_stack(self.ctx, template, user_creds) |
1678 | + values = [ |
1679 | + { |
1680 | + 'tenant': self.ctx.tenant_id, |
1681 | + 'status': 'IN_PROGRESS', |
1682 | + 'stack_id': stack1.id, |
1683 | + 'name': 'snp1' |
1684 | + }, |
1685 | + { |
1686 | + 'tenant': self.ctx.tenant_id, |
1687 | + 'status': 'IN_PROGRESS', |
1688 | + 'stack_id': stack1.id, |
1689 | + 'name': 'snp1' |
1690 | + }, |
1691 | + { |
1692 | + 'tenant': self.ctx.tenant_id, |
1693 | + 'status': 'IN_PROGRESS', |
1694 | + 'stack_id': stack2.id, |
1695 | + 'name': 'snp2' |
1696 | + } |
1697 | + ] |
1698 | + for val in values: |
1699 | + self.assertIsNotNone(db_api.snapshot_create(self.ctx, val)) |
1700 | + self.assertEqual(2, db_api.snapshot_count_all_by_stack(self.ctx, |
1701 | + stack1.id)) |
1702 | + self.assertEqual(1, db_api.snapshot_count_all_by_stack(self.ctx, |
1703 | + stack2.id)) |
1704 | + |
1705 | |
1706 | def create_raw_template(context, **kwargs): |
1707 | t = template_format.parse(wp_template) |
1708 | @@ -2493,13 +2543,13 @@ class DBAPIResourceTest(common.HeatTestCase): |
1709 | [self.assertIn(val['name'], names) for val in values] |
1710 | |
1711 | def test_resource_get_all_by_stack(self): |
1712 | - self.stack1 = create_stack(self.ctx, self.template, self.user_creds) |
1713 | - self.stack2 = create_stack(self.ctx, self.template, self.user_creds) |
1714 | + stack1 = create_stack(self.ctx, self.template, self.user_creds) |
1715 | + stack2 = create_stack(self.ctx, self.template, self.user_creds) |
1716 | values = [ |
1717 | {'name': 'res1', 'stack_id': self.stack.id}, |
1718 | {'name': 'res2', 'stack_id': self.stack.id}, |
1719 | {'name': 'res3', 'stack_id': self.stack.id}, |
1720 | - {'name': 'res4', 'stack_id': self.stack1.id}, |
1721 | + {'name': 'res4', 'stack_id': stack1.id}, |
1722 | ] |
1723 | [create_resource(self.ctx, self.stack, False, **val) |
1724 | for val in values] |
1725 | @@ -2530,7 +2580,7 @@ class DBAPIResourceTest(common.HeatTestCase): |
1726 | self.assertEqual('res2', resources.get('res2').name) |
1727 | |
1728 | self.assertEqual({}, db_api.resource_get_all_by_stack( |
1729 | - self.ctx, self.stack2.id)) |
1730 | + self.ctx, stack2.id)) |
1731 | |
1732 | def test_resource_get_all_active_by_stack(self): |
1733 | values = [ |
1734 | @@ -2555,8 +2605,8 @@ class DBAPIResourceTest(common.HeatTestCase): |
1735 | self.assertIn(res.name, ['res2', 'res3', 'res4', 'res5', 'res6']) |
1736 | |
1737 | def test_resource_get_all_by_root_stack(self): |
1738 | - self.stack1 = create_stack(self.ctx, self.template, self.user_creds) |
1739 | - self.stack2 = create_stack(self.ctx, self.template, self.user_creds) |
1740 | + stack1 = create_stack(self.ctx, self.template, self.user_creds) |
1741 | + stack2 = create_stack(self.ctx, self.template, self.user_creds) |
1742 | |
1743 | create_resource(self.ctx, self.stack, name='res1', |
1744 | root_stack_id=self.stack.id) |
1745 | @@ -2564,7 +2614,7 @@ class DBAPIResourceTest(common.HeatTestCase): |
1746 | root_stack_id=self.stack.id) |
1747 | create_resource(self.ctx, self.stack, name='res3', |
1748 | root_stack_id=self.stack.id) |
1749 | - create_resource(self.ctx, self.stack1, name='res4', |
1750 | + create_resource(self.ctx, stack1, name='res4', |
1751 | root_stack_id=self.stack.id) |
1752 | |
1753 | # Test for all resources in a stack |
1754 | @@ -2596,7 +2646,7 @@ class DBAPIResourceTest(common.HeatTestCase): |
1755 | sorted(resource_names)) |
1756 | |
1757 | self.assertEqual({}, db_api.resource_get_all_by_root_stack( |
1758 | - self.ctx, self.stack2.id)) |
1759 | + self.ctx, stack2.id)) |
1760 | |
1761 | def test_resource_purge_deleted_by_stack(self): |
1762 | val = {'name': 'res1', 'action': rsrc.Resource.DELETE, |
1763 | @@ -2944,14 +2994,14 @@ class DBAPIEventTest(common.HeatTestCase): |
1764 | self.assertEqual({'foo2': 'ev_bar'}, ret_event.rsrc_prop_data.data) |
1765 | |
1766 | def test_event_get_all_by_tenant(self): |
1767 | - self.stack1 = create_stack(self.ctx, self.template, self.user_creds, |
1768 | - tenant='tenant1') |
1769 | - self.stack2 = create_stack(self.ctx, self.template, self.user_creds, |
1770 | - tenant='tenant2') |
1771 | + stack1 = create_stack(self.ctx, self.template, self.user_creds, |
1772 | + tenant='tenant1') |
1773 | + stack2 = create_stack(self.ctx, self.template, self.user_creds, |
1774 | + tenant='tenant2') |
1775 | values = [ |
1776 | - {'stack_id': self.stack1.id, 'resource_name': 'res1'}, |
1777 | - {'stack_id': self.stack1.id, 'resource_name': 'res2'}, |
1778 | - {'stack_id': self.stack2.id, 'resource_name': 'res3'}, |
1779 | + {'stack_id': stack1.id, 'resource_name': 'res1'}, |
1780 | + {'stack_id': stack1.id, 'resource_name': 'res2'}, |
1781 | + {'stack_id': stack2.id, 'resource_name': 'res3'}, |
1782 | ] |
1783 | [create_event(self.ctx, **val) for val in values] |
1784 | |
1785 | @@ -2984,38 +3034,38 @@ class DBAPIEventTest(common.HeatTestCase): |
1786 | self.assertEqual(1, len(events)) |
1787 | |
1788 | def test_event_get_all_by_stack(self): |
1789 | - self.stack1 = create_stack(self.ctx, self.template, self.user_creds) |
1790 | - self.stack2 = create_stack(self.ctx, self.template, self.user_creds) |
1791 | + stack1 = create_stack(self.ctx, self.template, self.user_creds) |
1792 | + stack2 = create_stack(self.ctx, self.template, self.user_creds) |
1793 | values = [ |
1794 | - {'stack_id': self.stack1.id, 'resource_name': 'res1'}, |
1795 | - {'stack_id': self.stack1.id, 'resource_name': 'res2'}, |
1796 | - {'stack_id': self.stack2.id, 'resource_name': 'res3'}, |
1797 | + {'stack_id': stack1.id, 'resource_name': 'res1'}, |
1798 | + {'stack_id': stack1.id, 'resource_name': 'res2'}, |
1799 | + {'stack_id': stack2.id, 'resource_name': 'res3'}, |
1800 | ] |
1801 | [create_event(self.ctx, **val) for val in values] |
1802 | |
1803 | self.ctx.project_id = 'tenant1' |
1804 | - events = db_api.event_get_all_by_stack(self.ctx, self.stack1.id) |
1805 | + events = db_api.event_get_all_by_stack(self.ctx, stack1.id) |
1806 | self.assertEqual(2, len(events)) |
1807 | |
1808 | self.ctx.project_id = 'tenant2' |
1809 | - events = db_api.event_get_all_by_stack(self.ctx, self.stack2.id) |
1810 | + events = db_api.event_get_all_by_stack(self.ctx, stack2.id) |
1811 | self.assertEqual(1, len(events)) |
1812 | |
1813 | def test_event_count_all_by_stack(self): |
1814 | - self.stack1 = create_stack(self.ctx, self.template, self.user_creds) |
1815 | - self.stack2 = create_stack(self.ctx, self.template, self.user_creds) |
1816 | + stack1 = create_stack(self.ctx, self.template, self.user_creds) |
1817 | + stack2 = create_stack(self.ctx, self.template, self.user_creds) |
1818 | values = [ |
1819 | - {'stack_id': self.stack1.id, 'resource_name': 'res1'}, |
1820 | - {'stack_id': self.stack1.id, 'resource_name': 'res2'}, |
1821 | - {'stack_id': self.stack2.id, 'resource_name': 'res3'}, |
1822 | + {'stack_id': stack1.id, 'resource_name': 'res1'}, |
1823 | + {'stack_id': stack1.id, 'resource_name': 'res2'}, |
1824 | + {'stack_id': stack2.id, 'resource_name': 'res3'}, |
1825 | ] |
1826 | [create_event(self.ctx, **val) for val in values] |
1827 | |
1828 | self.assertEqual(2, db_api.event_count_all_by_stack(self.ctx, |
1829 | - self.stack1.id)) |
1830 | + stack1.id)) |
1831 | |
1832 | self.assertEqual(1, db_api.event_count_all_by_stack(self.ctx, |
1833 | - self.stack2.id)) |
1834 | + stack2.id)) |
1835 | |
1836 | |
1837 | class DBAPIServiceTest(common.HeatTestCase): |
1838 | @@ -3440,9 +3490,9 @@ class ResetStackStatusTests(common.HeatTestCase): |
1839 | db_api.reset_stack_status(self.ctx, self.stack.id) |
1840 | |
1841 | grandchild = db_api.stack_get(self.ctx, grandchild.id) |
1842 | - self.stack = db_api.stack_get(self.ctx, self.stack.id) |
1843 | + stack = db_api.stack_get(self.ctx, self.stack.id) |
1844 | resource = db_api.resource_get(self.ctx, resource.id) |
1845 | self.assertEqual('FAILED', grandchild.status) |
1846 | self.assertEqual('FAILED', resource.status) |
1847 | self.assertIsNone(resource.engine_id) |
1848 | - self.assertEqual('FAILED', self.stack.status) |
1849 | + self.assertEqual('FAILED', stack.status) |
1850 | diff --git a/heat/tests/engine/service/test_software_config.py b/heat/tests/engine/service/test_software_config.py |
1851 | index 470f3e9..90645c3 100644 |
1852 | --- a/heat/tests/engine/service/test_software_config.py |
1853 | +++ b/heat/tests/engine/service/test_software_config.py |
1854 | @@ -15,6 +15,7 @@ import datetime |
1855 | from unittest import mock |
1856 | import uuid |
1857 | |
1858 | +from oslo_config import cfg |
1859 | from oslo_messaging.rpc import dispatcher |
1860 | from oslo_serialization import jsonutils as json |
1861 | from oslo_utils import timeutils |
1862 | @@ -169,6 +170,14 @@ class SoftwareConfigServiceTest(common.HeatTestCase): |
1863 | config['outputs']) |
1864 | self.assertEqual(kwargs['options'], config['options']) |
1865 | |
1866 | + def test_create_config_exceeds_max_per_tenant(self): |
1867 | + cfg.CONF.set_override('max_software_configs_per_tenant', 0) |
1868 | + ex = self.assertRaises(dispatcher.ExpectedException, |
1869 | + self._create_software_config) |
1870 | + self.assertEqual(exception.RequestLimitExceeded, ex.exc_info[0]) |
1871 | + self.assertIn("You have reached the maximum software configs " |
1872 | + "per tenant", str(ex.exc_info[1])) |
1873 | + |
1874 | def test_create_software_config_structured(self): |
1875 | kwargs = { |
1876 | 'group': 'json-file', |
1877 | @@ -504,6 +513,14 @@ class SoftwareConfigServiceTest(common.HeatTestCase): |
1878 | self.assertEqual(deployment_id, deployment['id']) |
1879 | self.assertEqual(kwargs['input_values'], deployment['input_values']) |
1880 | |
1881 | + def test_create_deployment_exceeds_max_per_tenant(self): |
1882 | + cfg.CONF.set_override('max_software_deployments_per_tenant', 0) |
1883 | + ex = self.assertRaises(dispatcher.ExpectedException, |
1884 | + self._create_software_deployment) |
1885 | + self.assertEqual(exception.RequestLimitExceeded, ex.exc_info[0]) |
1886 | + self.assertIn("You have reached the maximum software deployments" |
1887 | + " per tenant", str(ex.exc_info[1])) |
1888 | + |
1889 | def test_create_software_deployment_invalid_stack_user_project_id(self): |
1890 | sc_kwargs = { |
1891 | 'group': 'Heat::Chef', |
1892 | @@ -753,12 +770,12 @@ class SoftwareConfigServiceTest(common.HeatTestCase): |
1893 | } |
1894 | self.engine.software_config._push_metadata_software_deployments( |
1895 | self.ctx, '1234', None) |
1896 | - res_upd.has_calls( |
1897 | + res_upd.assert_has_calls([ |
1898 | mock.call(self.ctx, '1234', |
1899 | {'rsrc_metadata': result_metadata}, 1), |
1900 | mock.call(self.ctx, '1234', |
1901 | - {'rsrc_metadata': result_metadata}, 2), |
1902 | - ) |
1903 | + {}, 2), |
1904 | + ]) |
1905 | |
1906 | put.assert_called_once_with( |
1907 | 'http://192.168.2.2/foo/bar', json.dumps(result_metadata)) |
1908 | diff --git a/heat/tests/engine/service/test_stack_snapshot.py b/heat/tests/engine/service/test_stack_snapshot.py |
1909 | index 57e2e26..2d0e0b4 100644 |
1910 | --- a/heat/tests/engine/service/test_stack_snapshot.py |
1911 | +++ b/heat/tests/engine/service/test_stack_snapshot.py |
1912 | @@ -99,6 +99,19 @@ class SnapshotServiceTest(common.HeatTestCase): |
1913 | mock_load.assert_called_once_with(self.ctx, stack=mock.ANY) |
1914 | |
1915 | @mock.patch.object(stack.Stack, 'load') |
1916 | + def test_create_snapshot_exceeds_max_per_stack(self, mock_load): |
1917 | + stk = self._create_stack('stack_snapshot_exceeds_max') |
1918 | + mock_load.return_value = stk |
1919 | + |
1920 | + cfg.CONF.set_override('max_snapshots_per_stack', 0) |
1921 | + ex = self.assertRaises(dispatcher.ExpectedException, |
1922 | + self.engine.stack_snapshot, |
1923 | + self.ctx, stk.identifier(), 'snap_none') |
1924 | + self.assertEqual(exception.RequestLimitExceeded, ex.exc_info[0]) |
1925 | + self.assertIn("You have reached the maximum snapshots per stack", |
1926 | + str(ex.exc_info[1])) |
1927 | + |
1928 | + @mock.patch.object(stack.Stack, 'load') |
1929 | def test_create_snapshot_action_in_progress(self, mock_load): |
1930 | stack_name = 'stack_snapshot_action_in_progress' |
1931 | stk = self._create_stack(stack_name) |
1932 | diff --git a/heat/tests/engine/test_resource_type.py b/heat/tests/engine/test_resource_type.py |
1933 | index eab8ea8..ff23e70 100644 |
1934 | --- a/heat/tests/engine/test_resource_type.py |
1935 | +++ b/heat/tests/engine/test_resource_type.py |
1936 | @@ -42,8 +42,7 @@ class ResourceTypeTest(common.HeatTestCase): |
1937 | mock_is_service_available): |
1938 | mock_is_service_available.return_value = (True, None) |
1939 | resources = self.eng.list_resource_types(self.ctx, "DEPRECATED") |
1940 | - self.assertEqual(set(['OS::Aodh::Alarm']), |
1941 | - set(resources)) |
1942 | + self.assertIn('OS::Aodh::Alarm', resources) |
1943 | |
1944 | @mock.patch.object(res.Resource, 'is_service_available') |
1945 | def test_list_resource_types_supported(self, |
1946 | diff --git a/heat/tests/openstack/aodh/test_alarm.py b/heat/tests/openstack/aodh/test_alarm.py |
1947 | index 48b756f..609cc9d 100644 |
1948 | --- a/heat/tests/openstack/aodh/test_alarm.py |
1949 | +++ b/heat/tests/openstack/aodh/test_alarm.py |
1950 | @@ -16,6 +16,12 @@ import copy |
1951 | import json |
1952 | from unittest import mock |
1953 | |
1954 | +try: |
1955 | + import zoneinfo |
1956 | +except ImportError: |
1957 | + # zoneinfo is available in Python >= 3.9 |
1958 | + zoneinfo = None |
1959 | + |
1960 | from heat.common import exception |
1961 | from heat.common import template_format |
1962 | from heat.engine.clients.os import aodh |
1963 | @@ -579,11 +585,14 @@ class AodhAlarmTest(common.HeatTestCase): |
1964 | exception.ResourceFailure, |
1965 | scheduler.TaskRunner(rsrc.update, snippet) |
1966 | ) |
1967 | + err = timezone |
1968 | + if zoneinfo: |
1969 | + err = "No time zone found with key %s" % timezone |
1970 | self.assertEqual( |
1971 | "StackValidationFailed: resources.MEMAlarmHigh: Property error: " |
1972 | "Properties.time_constraints[0].timezone: Error " |
1973 | "validating value '%s': Invalid timezone: '%s'" |
1974 | - % (timezone, timezone), |
1975 | + % (timezone, err), |
1976 | error.message) |
1977 | |
1978 | def test_alarm_live_state(self): |
1979 | diff --git a/heat/tests/openstack/heat/test_none_resource.py b/heat/tests/openstack/heat/test_none_resource.py |
1980 | index 7344b36..28e0879 100644 |
1981 | --- a/heat/tests/openstack/heat/test_none_resource.py |
1982 | +++ b/heat/tests/openstack/heat/test_none_resource.py |
1983 | @@ -76,7 +76,7 @@ outputs: |
1984 | before_refid = self.rsrc.FnGetRefId() |
1985 | self.assertIsNotNone(before_refid) |
1986 | new_t = self.t.copy() |
1987 | - del(new_t['resources']['none']['properties']['ignored']) |
1988 | + del new_t['resources']['none']['properties']['ignored'] |
1989 | utils.update_stack(self.stack, new_t) |
1990 | self.assertEqual((self.stack.UPDATE, self.stack.COMPLETE), |
1991 | self.stack.state) |
1992 | diff --git a/heat/tests/openstack/heat/test_remote_stack.py b/heat/tests/openstack/heat/test_remote_stack.py |
1993 | index b5df410..bbfb0e3 100644 |
1994 | --- a/heat/tests/openstack/heat/test_remote_stack.py |
1995 | +++ b/heat/tests/openstack/heat/test_remote_stack.py |
1996 | @@ -368,7 +368,7 @@ class RemoteStackTest(tests_common.HeatTestCase): |
1997 | ca_cert=ca_cert) |
1998 | self.assertEqual(ca_cert, rsrc._cacert) |
1999 | self.assertEqual(ca_cert, rsrc.cacert) |
2000 | - self.assertTrue('/tmp/' in rsrc._ssl_verify) |
2001 | + self.assertIn('/tmp/', rsrc._ssl_verify) |
2002 | |
2003 | def test_create_with_insecure(self): |
2004 | rsrc = self._create_with_remote_credential(insecure=True) |
2005 | diff --git a/heat/tests/openstack/heat/test_software_deployment.py b/heat/tests/openstack/heat/test_software_deployment.py |
2006 | index 307ec57..db9cf50 100644 |
2007 | --- a/heat/tests/openstack/heat/test_software_deployment.py |
2008 | +++ b/heat/tests/openstack/heat/test_software_deployment.py |
2009 | @@ -1318,7 +1318,7 @@ class SoftwareDeploymentTest(common.HeatTestCase): |
2010 | mock.call('swift_signal_url')], |
2011 | self.deployment.data_delete.mock_calls) |
2012 | |
2013 | - del(dep_data['swift_signal_object_name']) |
2014 | + del dep_data['swift_signal_object_name'] |
2015 | self.deployment.physical_resource_name = mock.Mock() |
2016 | self.deployment._delete_swift_signal_url() |
2017 | self.assertFalse(self.deployment.physical_resource_name.called) |
2018 | diff --git a/heat/tests/openstack/neutron/test_neutron_floating_ip.py b/heat/tests/openstack/neutron/test_neutron_floating_ip.py |
2019 | index 6915c10..2ffdf1d 100644 |
2020 | --- a/heat/tests/openstack/neutron/test_neutron_floating_ip.py |
2021 | +++ b/heat/tests/openstack/neutron/test_neutron_floating_ip.py |
2022 | @@ -156,10 +156,10 @@ class NeutronFloatingIPTest(common.HeatTestCase): |
2023 | raise ex |
2024 | |
2025 | def find_network_port(self, value): |
2026 | - return('9c1eb3fe-7bba-479d-bd43-fdb0bc7cd151') |
2027 | + return '9c1eb3fe-7bba-479d-bd43-fdb0bc7cd151' |
2028 | |
2029 | def find_network_ip(self, value): |
2030 | - return('477e8273-60a7-4c41-b683-1d497e53c384') |
2031 | + return '477e8273-60a7-4c41-b683-1d497e53c384' |
2032 | |
2033 | self.ctx = utils.dummy_context() |
2034 | tpl = template_format.parse(neutron_floating_template) |
2035 | @@ -694,7 +694,7 @@ class NeutronFloatingIPTest(common.HeatTestCase): |
2036 | |
2037 | # test update FloatingIp with None port_id |
2038 | props = copy.deepcopy(fip.properties.data) |
2039 | - del(props['port_id']) |
2040 | + del props['port_id'] |
2041 | update_snippet = rsrc_defn.ResourceDefinition(fip.name, fip.type(), |
2042 | stack.t.parse(stack.defn, |
2043 | props)) |
2044 | diff --git a/heat/tests/test_common_context.py b/heat/tests/test_common_context.py |
2045 | index 95a08ec..91401d2 100644 |
2046 | --- a/heat/tests/test_common_context.py |
2047 | +++ b/heat/tests/test_common_context.py |
2048 | @@ -125,7 +125,7 @@ class TestRequestContext(common.HeatTestCase): |
2049 | user_domain_id=ctx_origin.get('user_domain_id'), |
2050 | project_domain_id=ctx_origin.get('project_domain_id')) |
2051 | ctx_dict = ctx.to_dict() |
2052 | - del(ctx_dict['request_id']) |
2053 | + del ctx_dict['request_id'] |
2054 | self.assertEqual(ctx_origin, ctx_dict) |
2055 | |
2056 | def test_request_context_from_dict(self): |
2057 | diff --git a/heat/tests/test_convg_stack.py b/heat/tests/test_convg_stack.py |
2058 | index c001af1..722da9a 100644 |
2059 | --- a/heat/tests/test_convg_stack.py |
2060 | +++ b/heat/tests/test_convg_stack.py |
2061 | @@ -549,14 +549,14 @@ class StackConvergenceCreateUpdateDeleteTest(common.HeatTestCase): |
2062 | |
2063 | # Ensure that snapshot is not deleted on stack update |
2064 | stack.converge_stack(template=stack.t, action=stack.UPDATE) |
2065 | - db_snapshot_obj = snapshot_objects.Snapshot.get_all( |
2066 | + db_snapshot_obj = snapshot_objects.Snapshot.get_all_by_stack( |
2067 | stack.context, stack.id) |
2068 | self.assertEqual('fake_snapshot', db_snapshot_obj[0].name) |
2069 | self.assertEqual(stack.id, db_snapshot_obj[0].stack_id) |
2070 | |
2071 | # Ensure that snapshot is deleted on stack delete |
2072 | stack.converge_stack(template=stack.t, action=stack.DELETE) |
2073 | - self.assertEqual([], snapshot_objects.Snapshot.get_all( |
2074 | + self.assertEqual([], snapshot_objects.Snapshot.get_all_by_stack( |
2075 | stack.context, stack.id)) |
2076 | self.assertTrue(mock_cr.called) |
2077 | |
2078 | diff --git a/heat/tests/test_environment.py b/heat/tests/test_environment.py |
2079 | index 6de00dc..de39e15 100644 |
2080 | --- a/heat/tests/test_environment.py |
2081 | +++ b/heat/tests/test_environment.py |
2082 | @@ -12,7 +12,6 @@ |
2083 | # under the License. |
2084 | |
2085 | import os.path |
2086 | -import sys |
2087 | from unittest import mock |
2088 | |
2089 | import fixtures |
2090 | @@ -47,7 +46,7 @@ class EnvironmentTest(common.HeatTestCase): |
2091 | u'resource_registry': {u'resources': {}}} |
2092 | env = environment.Environment(old) |
2093 | self.assertEqual(expected, env.env_as_dict()) |
2094 | - del(expected['encrypted_param_names']) |
2095 | + del expected['encrypted_param_names'] |
2096 | self.assertEqual(expected, env.user_env_as_dict()) |
2097 | |
2098 | def test_load_new_env(self): |
2099 | @@ -59,7 +58,7 @@ class EnvironmentTest(common.HeatTestCase): |
2100 | u'resources': {}}} |
2101 | env = environment.Environment(new_env) |
2102 | self.assertEqual(new_env, env.env_as_dict()) |
2103 | - del(new_env['encrypted_param_names']) |
2104 | + del new_env['encrypted_param_names'] |
2105 | self.assertEqual(new_env, env.user_env_as_dict()) |
2106 | |
2107 | def test_global_registry(self): |
2108 | @@ -183,7 +182,6 @@ def constraint_mapping(): |
2109 | plugin_file = os.path.join(plugin_dir.path, 'test.py') |
2110 | with open(plugin_file, 'w+') as ef: |
2111 | ef.write(constraint_content) |
2112 | - self.addCleanup(sys.modules.pop, "heat.engine.plugins.test") |
2113 | cfg.CONF.set_override('plugin_dirs', plugin_dir.path) |
2114 | |
2115 | env = environment.Environment({}) |
2116 | @@ -202,7 +200,6 @@ def constraint_mapping(): |
2117 | plugin_file = os.path.join(plugin_dir.path, 'test.py') |
2118 | with open(plugin_file, 'w+') as ef: |
2119 | ef.write(constraint_content) |
2120 | - self.addCleanup(sys.modules.pop, "heat.engine.plugins.test") |
2121 | cfg.CONF.set_override('plugin_dirs', plugin_dir.path) |
2122 | |
2123 | env = environment.Environment({}) |
2124 | diff --git a/heat/tests/test_loguserdata.py b/heat/tests/test_loguserdata.py |
2125 | index 7bb1700..09b214a 100644 |
2126 | --- a/heat/tests/test_loguserdata.py |
2127 | +++ b/heat/tests/test_loguserdata.py |
2128 | @@ -21,68 +21,8 @@ from heat.cloudinit import loguserdata |
2129 | from heat.tests import common |
2130 | |
2131 | |
2132 | -class FakeCiVersion(object): |
2133 | - def __init__(self, version): |
2134 | - self.version = version |
2135 | - |
2136 | - |
2137 | class LoguserdataTest(common.HeatTestCase): |
2138 | |
2139 | - @mock.patch('pkg_resources.get_distribution') |
2140 | - def test_ci_version_with_pkg_resources(self, mock_get): |
2141 | - # Setup |
2142 | - returned_versions = [ |
2143 | - FakeCiVersion('0.5.0'), |
2144 | - FakeCiVersion('0.5.9'), |
2145 | - FakeCiVersion('0.6.0'), |
2146 | - FakeCiVersion('0.7.0'), |
2147 | - FakeCiVersion('1.0'), |
2148 | - FakeCiVersion('2.0'), |
2149 | - ] |
2150 | - mock_get.side_effect = returned_versions |
2151 | - |
2152 | - # Test & Verify |
2153 | - self.assertFalse(loguserdata.chk_ci_version()) |
2154 | - self.assertFalse(loguserdata.chk_ci_version()) |
2155 | - self.assertTrue(loguserdata.chk_ci_version()) |
2156 | - self.assertTrue(loguserdata.chk_ci_version()) |
2157 | - self.assertTrue(loguserdata.chk_ci_version()) |
2158 | - self.assertTrue(loguserdata.chk_ci_version()) |
2159 | - self.assertEqual(6, mock_get.call_count) |
2160 | - |
2161 | - @mock.patch('pkg_resources.get_distribution') |
2162 | - @mock.patch('subprocess.Popen') |
2163 | - def test_ci_version_with_subprocess(self, mock_popen, |
2164 | - mock_get_distribution): |
2165 | - # Setup |
2166 | - mock_get_distribution.side_effect = Exception() |
2167 | - |
2168 | - popen_return = [ |
2169 | - [None, 'cloud-init 0.0.5\n'], |
2170 | - [None, 'cloud-init 0.7.5\n'], |
2171 | - ] |
2172 | - mock_popen.return_value = mock.MagicMock() |
2173 | - mock_popen.return_value.communicate.side_effect = popen_return |
2174 | - |
2175 | - # Test & Verify |
2176 | - self.assertFalse(loguserdata.chk_ci_version()) |
2177 | - self.assertTrue(loguserdata.chk_ci_version()) |
2178 | - self.assertEqual(2, mock_get_distribution.call_count) |
2179 | - |
2180 | - @mock.patch('pkg_resources.get_distribution') |
2181 | - @mock.patch('subprocess.Popen') |
2182 | - def test_ci_version_with_subprocess_exception(self, mock_popen, |
2183 | - mock_get_distribution): |
2184 | - # Setup |
2185 | - mock_get_distribution.side_effect = Exception() |
2186 | - mock_popen.return_value = mock.MagicMock() |
2187 | - mock_popen.return_value.communicate.return_value = ['non-empty', |
2188 | - 'irrelevant'] |
2189 | - |
2190 | - # Test |
2191 | - self.assertRaises(Exception, loguserdata.chk_ci_version) # noqa |
2192 | - self.assertEqual(1, mock_get_distribution.call_count) |
2193 | - |
2194 | @mock.patch('subprocess.Popen') |
2195 | def test_call(self, mock_popen): |
2196 | # Setup |
2197 | @@ -141,12 +81,10 @@ class LoguserdataTest(common.HeatTestCase): |
2198 | # Verify |
2199 | self.assertEqual(os.EX_SOFTWARE, return_code) |
2200 | |
2201 | - @mock.patch('pkg_resources.get_distribution') |
2202 | @mock.patch('os.chmod') |
2203 | @mock.patch('heat.cloudinit.loguserdata.call') |
2204 | - def test_main(self, mock_call, mock_chmod, mock_get): |
2205 | + def test_main(self, mock_call, mock_chmod): |
2206 | # Setup |
2207 | - mock_get.return_value = FakeCiVersion('1.0') |
2208 | mock_call.return_value = 10 |
2209 | |
2210 | # Test |
2211 | @@ -156,14 +94,3 @@ class LoguserdataTest(common.HeatTestCase): |
2212 | expected_path = os.path.join(loguserdata.VAR_PATH, 'cfn-userdata') |
2213 | mock_chmod.assert_called_once_with(expected_path, int('700', 8)) |
2214 | self.assertEqual(10, return_code) |
2215 | - |
2216 | - @mock.patch('pkg_resources.get_distribution') |
2217 | - def test_main_failed_ci_version(self, mock_get): |
2218 | - # Setup |
2219 | - mock_get.return_value = FakeCiVersion('0.0.0') |
2220 | - |
2221 | - # Test |
2222 | - return_code = loguserdata.main() |
2223 | - |
2224 | - # Verify |
2225 | - self.assertEqual(-1, return_code) |
2226 | diff --git a/heat/tests/test_resource.py b/heat/tests/test_resource.py |
2227 | index d360916..231d728 100644 |
2228 | --- a/heat/tests/test_resource.py |
2229 | +++ b/heat/tests/test_resource.py |
2230 | @@ -4092,8 +4092,8 @@ class ResourceAvailabilityTest(common.HeatTestCase): |
2231 | service_type='test_type', |
2232 | service_name=(generic_rsrc.ResourceWithDefaultClientName |
2233 | .default_client_name)) |
2234 | - mock_client_plugin.has_extension.has_calls( |
2235 | - [('foo'), ('bar')]) |
2236 | + mock_client_plugin.has_extension.assert_has_calls( |
2237 | + [mock.call('foo'), mock.call('bar')]) |
2238 | |
2239 | @mock.patch.object(clients.OpenStackClients, 'client_plugin') |
2240 | def test_service_deployed_required_extension_true_list( |
2241 | @@ -4118,8 +4118,8 @@ class ResourceAvailabilityTest(common.HeatTestCase): |
2242 | service_type='test_type', |
2243 | service_name=(generic_rsrc.ResourceWithDefaultClientName |
2244 | .default_client_name)) |
2245 | - mock_client_plugin.has_extension.has_calls( |
2246 | - [('foo'), ('bar')]) |
2247 | + mock_client_plugin.has_extension.assert_has_calls( |
2248 | + [mock.call('foo'), mock.call('bar')]) |
2249 | |
2250 | @mock.patch.object(clients.OpenStackClients, 'client_plugin') |
2251 | def test_service_deployed_required_extension_true_list_fail( |
2252 | @@ -4144,8 +4144,8 @@ class ResourceAvailabilityTest(common.HeatTestCase): |
2253 | service_type='test_type', |
2254 | service_name=(generic_rsrc.ResourceWithDefaultClientName |
2255 | .default_client_name)) |
2256 | - mock_client_plugin.has_extension.has_calls( |
2257 | - [('foo'), ('bar')]) |
2258 | + mock_client_plugin.has_extension.assert_has_calls( |
2259 | + [mock.call('foo'), mock.call('bar')]) |
2260 | |
2261 | |
2262 | class TestLiveStateUpdate(common.HeatTestCase): |
2263 | diff --git a/heat/tests/test_stack_delete.py b/heat/tests/test_stack_delete.py |
2264 | index 51fb26a..d509ed2 100644 |
2265 | --- a/heat/tests/test_stack_delete.py |
2266 | +++ b/heat/tests/test_stack_delete.py |
2267 | @@ -73,7 +73,7 @@ class StackTest(common.HeatTestCase): |
2268 | } |
2269 | snapshot_object.Snapshot.create(self.ctx, snapshot_fake) |
2270 | |
2271 | - self.assertIsNotNone(snapshot_object.Snapshot.get_all( |
2272 | + self.assertIsNotNone(snapshot_object.Snapshot.get_all_by_stack( |
2273 | self.ctx, stack_id)) |
2274 | |
2275 | self.stack.delete() |
2276 | @@ -81,7 +81,7 @@ class StackTest(common.HeatTestCase): |
2277 | self.assertIsNone(db_s) |
2278 | self.assertEqual((stack.Stack.DELETE, stack.Stack.COMPLETE), |
2279 | self.stack.state) |
2280 | - self.assertEqual([], snapshot_object.Snapshot.get_all( |
2281 | + self.assertEqual([], snapshot_object.Snapshot.get_all_by_stack( |
2282 | self.ctx, stack_id)) |
2283 | |
2284 | def test_delete_with_snapshot_after_stack_add_resource(self): |
2285 | @@ -104,7 +104,7 @@ class StackTest(common.HeatTestCase): |
2286 | } |
2287 | snapshot_object.Snapshot.create(self.ctx, snapshot_fake) |
2288 | |
2289 | - self.assertIsNotNone(snapshot_object.Snapshot.get_all( |
2290 | + self.assertIsNotNone(snapshot_object.Snapshot.get_all_by_stack( |
2291 | self.ctx, stack_id)) |
2292 | |
2293 | new_tmpl = {'heat_template_version': 'queens', |
2294 | @@ -121,7 +121,7 @@ class StackTest(common.HeatTestCase): |
2295 | self.assertIsNone(db_s) |
2296 | self.assertEqual((stack.Stack.DELETE, stack.Stack.COMPLETE), |
2297 | self.stack.state) |
2298 | - self.assertEqual([], snapshot_object.Snapshot.get_all( |
2299 | + self.assertEqual([], snapshot_object.Snapshot.get_all_by_stack( |
2300 | self.ctx, stack_id)) |
2301 | |
2302 | def test_delete_user_creds(self): |
2303 | diff --git a/heat/tests/test_template_format.py b/heat/tests/test_template_format.py |
2304 | index 3ce127c..aeb2368 100644 |
2305 | --- a/heat/tests/test_template_format.py |
2306 | +++ b/heat/tests/test_template_format.py |
2307 | @@ -56,12 +56,12 @@ class JsonToYamlTest(common.HeatTestCase): |
2308 | |
2309 | self.assertEqual(u'2012-12-12', yml[u'HeatTemplateFormatVersion']) |
2310 | self.assertNotIn(u'AWSTemplateFormatVersion', yml) |
2311 | - del(yml[u'HeatTemplateFormatVersion']) |
2312 | + del yml[u'HeatTemplateFormatVersion'] |
2313 | |
2314 | jsn = template_format.parse(json_str) |
2315 | |
2316 | if u'AWSTemplateFormatVersion' in jsn: |
2317 | - del(jsn[u'AWSTemplateFormatVersion']) |
2318 | + del jsn[u'AWSTemplateFormatVersion'] |
2319 | |
2320 | self.assertEqual(yml, jsn) |
2321 | |
2322 | @@ -189,7 +189,7 @@ class JsonYamlResolvedCompareTest(common.HeatTestCase): |
2323 | def compare_stacks(self, json_file, yaml_file, parameters): |
2324 | t1 = self.load_template(json_file) |
2325 | t2 = self.load_template(yaml_file) |
2326 | - del(t1[u'AWSTemplateFormatVersion']) |
2327 | + del t1[u'AWSTemplateFormatVersion'] |
2328 | t1[u'HeatTemplateFormatVersion'] = t2[u'HeatTemplateFormatVersion'] |
2329 | stack1 = utils.parse_stack(t1, parameters) |
2330 | stack2 = utils.parse_stack(t2, parameters) |
2331 | @@ -197,10 +197,10 @@ class JsonYamlResolvedCompareTest(common.HeatTestCase): |
2332 | # compare resources separately so that resolved static data |
2333 | # is compared |
2334 | t1nr = dict(stack1.t.t) |
2335 | - del(t1nr['Resources']) |
2336 | + del t1nr['Resources'] |
2337 | |
2338 | t2nr = dict(stack2.t.t) |
2339 | - del(t2nr['Resources']) |
2340 | + del t2nr['Resources'] |
2341 | self.assertEqual(t1nr, t2nr) |
2342 | |
2343 | self.assertEqual(set(stack1), set(stack2)) |
2344 | diff --git a/openstack_heat.egg-info/PKG-INFO b/openstack_heat.egg-info/PKG-INFO |
2345 | index d68f1ed..9541147 100644 |
2346 | --- a/openstack_heat.egg-info/PKG-INFO |
2347 | +++ b/openstack_heat.egg-info/PKG-INFO |
2348 | @@ -1,10 +1,93 @@ |
2349 | -Metadata-Version: 2.1 |
2350 | +Metadata-Version: 1.2 |
2351 | Name: openstack-heat |
2352 | -Version: 21.1.0.dev70 |
2353 | +Version: 22.0.0.0rc1 |
2354 | Summary: OpenStack Orchestration |
2355 | Home-page: https://docs.openstack.org/heat/latest/ |
2356 | Author: OpenStack |
2357 | Author-email: openstack-discuss@lists.openstack.org |
2358 | +License: UNKNOWN |
2359 | +Description: ======================== |
2360 | + Team and repository tags |
2361 | + ======================== |
2362 | + |
2363 | + .. image:: https://governance.openstack.org/tc/badges/heat.svg |
2364 | + :target: https://governance.openstack.org/tc/reference/tags/index.html |
2365 | + |
2366 | + .. Change things from this point on |
2367 | + |
2368 | + ==== |
2369 | + Heat |
2370 | + ==== |
2371 | + |
2372 | + Heat is a service to orchestrate multiple composite cloud applications using |
2373 | + templates, through both an OpenStack-native REST API and a |
2374 | + CloudFormation-compatible Query API. |
2375 | + |
2376 | + Why heat? It makes the clouds rise and keeps them there. |
2377 | + |
2378 | + Getting Started |
2379 | + --------------- |
2380 | + |
2381 | + If you'd like to run from the master branch, you can clone the git repo: |
2382 | + |
2383 | + git clone https://opendev.org/openstack/heat |
2384 | + |
2385 | + |
2386 | + * Documentation: https://docs.openstack.org/heat/latest |
2387 | + * Template samples: https://opendev.org/openstack/heat-templates |
2388 | + * Agents: https://opendev.org/openstack/heat-agents |
2389 | + * Release Notes: https://docs.openstack.org/releasenotes/heat/ |
2390 | + |
2391 | + Python client |
2392 | + ------------- |
2393 | + |
2394 | + * Documentation: https://docs.openstack.org/python-heatclient/latest |
2395 | + * Source: https://opendev.org/openstack/python-heatclient |
2396 | + |
2397 | + Report a Story (a bug/blueprint) |
2398 | + -------------------------------- |
2399 | + |
2400 | + If you'd like to report a Story (we used to call a bug/blueprint), you can |
2401 | + report it under Report a story in |
2402 | + `Heat's StoryBoard <https://storyboard.openstack.org/#!/project/989>`_. |
2403 | + If you must report the story under other sub-project of heat, you can find |
2404 | + them all in `Heat StoryBoard Group <https://storyboard.openstack.org/#!/project_group/82>`_. |
2405 | + if you encounter any issue. |
2406 | + |
2407 | + References |
2408 | + ---------- |
2409 | + * https://docs.amazonwebservices.com/AWSCloudFormation/latest/APIReference/API_CreateStack.html |
2410 | + * https://docs.amazonwebservices.com/AWSCloudFormation/latest/UserGuide/create-stack.html |
2411 | + * https://docs.amazonwebservices.com/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html |
2412 | + * https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=tosca |
2413 | + |
2414 | + We have integration with |
2415 | + ------------------------ |
2416 | + * https://opendev.org/openstack/python-novaclient (instance) |
2417 | + * https://opendev.org/openstack/python-keystoneclient (auth) |
2418 | + * https://opendev.org/openstack/python-swiftclient (object storage) |
2419 | + * https://opendev.org/openstack/python-neutronclient (networking) |
2420 | + * https://opendev.org/openstack/python-aodhclient (alarming service) |
2421 | + * https://opendev.org/openstack/python-cinderclient (block storage) |
2422 | + * https://opendev.org/openstack/python-glanceclient (image service) |
2423 | + * https://opendev.org/openstack/python-troveclient (database as a Service) |
2424 | + * https://opendev.org/openstack/python-saharaclient (hadoop cluster) |
2425 | + * https://opendev.org/openstack/python-barbicanclient (key management service) |
2426 | + * https://opendev.org/openstack/python-designateclient (DNS service) |
2427 | + * https://opendev.org/openstack/python-magnumclient (container service) |
2428 | + * https://opendev.org/openstack/python-manilaclient (shared file system service) |
2429 | + * https://opendev.org/openstack/python-mistralclient (workflow service) |
2430 | + * https://opendev.org/openstack/python-zaqarclient (messaging service) |
2431 | + * https://opendev.org/openstack/python-monascaclient (monitoring service) |
2432 | + * https://opendev.org/openstack/python-zunclient (container management service) |
2433 | + * https://opendev.org/openstack/python-blazarclient (reservation service) |
2434 | + * https://opendev.org/openstack/python-octaviaclient.git (Load-balancer service) |
2435 | + * https://opendev.org/openstack/python-senlinclient (Clustering service) |
2436 | + * https://opendev.org/openstack/python-vitrageclient.git (RCA service) |
2437 | + * https://opendev.org/openstack/python-ironicclient (baremetal provisioning service) |
2438 | + |
2439 | + |
2440 | +Platform: UNKNOWN |
2441 | Classifier: Environment :: OpenStack |
2442 | Classifier: Intended Audience :: Information Technology |
2443 | Classifier: Intended Audience :: System Administrators |
2444 | @@ -18,85 +101,3 @@ Classifier: Programming Language :: Python :: 3.9 |
2445 | Classifier: Programming Language :: Python :: 3.10 |
2446 | Classifier: Programming Language :: Python :: 3.11 |
2447 | Requires-Python: >=3.8 |
2448 | -License-File: LICENSE |
2449 | - |
2450 | -======================== |
2451 | -Team and repository tags |
2452 | -======================== |
2453 | - |
2454 | -.. image:: https://governance.openstack.org/tc/badges/heat.svg |
2455 | - :target: https://governance.openstack.org/tc/reference/tags/index.html |
2456 | - |
2457 | -.. Change things from this point on |
2458 | - |
2459 | -==== |
2460 | -Heat |
2461 | -==== |
2462 | - |
2463 | -Heat is a service to orchestrate multiple composite cloud applications using |
2464 | -templates, through both an OpenStack-native REST API and a |
2465 | -CloudFormation-compatible Query API. |
2466 | - |
2467 | -Why heat? It makes the clouds rise and keeps them there. |
2468 | - |
2469 | -Getting Started |
2470 | ---------------- |
2471 | - |
2472 | -If you'd like to run from the master branch, you can clone the git repo: |
2473 | - |
2474 | - git clone https://opendev.org/openstack/heat |
2475 | - |
2476 | - |
2477 | -* Documentation: https://docs.openstack.org/heat/latest |
2478 | -* Template samples: https://opendev.org/openstack/heat-templates |
2479 | -* Agents: https://opendev.org/openstack/heat-agents |
2480 | -* Release Notes: https://docs.openstack.org/releasenotes/heat/ |
2481 | - |
2482 | -Python client |
2483 | -------------- |
2484 | - |
2485 | -* Documentation: https://docs.openstack.org/python-heatclient/latest |
2486 | -* Source: https://opendev.org/openstack/python-heatclient |
2487 | - |
2488 | -Report a Story (a bug/blueprint) |
2489 | --------------------------------- |
2490 | - |
2491 | -If you'd like to report a Story (we used to call a bug/blueprint), you can |
2492 | -report it under Report a story in |
2493 | -`Heat's StoryBoard <https://storyboard.openstack.org/#!/project/989>`_. |
2494 | -If you must report the story under other sub-project of heat, you can find |
2495 | -them all in `Heat StoryBoard Group <https://storyboard.openstack.org/#!/project_group/82>`_. |
2496 | -if you encounter any issue. |
2497 | - |
2498 | -References |
2499 | ----------- |
2500 | -* https://docs.amazonwebservices.com/AWSCloudFormation/latest/APIReference/API_CreateStack.html |
2501 | -* https://docs.amazonwebservices.com/AWSCloudFormation/latest/UserGuide/create-stack.html |
2502 | -* https://docs.amazonwebservices.com/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html |
2503 | -* https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=tosca |
2504 | - |
2505 | -We have integration with |
2506 | ------------------------- |
2507 | -* https://opendev.org/openstack/python-novaclient (instance) |
2508 | -* https://opendev.org/openstack/python-keystoneclient (auth) |
2509 | -* https://opendev.org/openstack/python-swiftclient (object storage) |
2510 | -* https://opendev.org/openstack/python-neutronclient (networking) |
2511 | -* https://opendev.org/openstack/python-aodhclient (alarming service) |
2512 | -* https://opendev.org/openstack/python-cinderclient (block storage) |
2513 | -* https://opendev.org/openstack/python-glanceclient (image service) |
2514 | -* https://opendev.org/openstack/python-troveclient (database as a Service) |
2515 | -* https://opendev.org/openstack/python-saharaclient (hadoop cluster) |
2516 | -* https://opendev.org/openstack/python-barbicanclient (key management service) |
2517 | -* https://opendev.org/openstack/python-designateclient (DNS service) |
2518 | -* https://opendev.org/openstack/python-magnumclient (container service) |
2519 | -* https://opendev.org/openstack/python-manilaclient (shared file system service) |
2520 | -* https://opendev.org/openstack/python-mistralclient (workflow service) |
2521 | -* https://opendev.org/openstack/python-zaqarclient (messaging service) |
2522 | -* https://opendev.org/openstack/python-monascaclient (monitoring service) |
2523 | -* https://opendev.org/openstack/python-zunclient (container management service) |
2524 | -* https://opendev.org/openstack/python-blazarclient (reservation service) |
2525 | -* https://opendev.org/openstack/python-octaviaclient.git (Load-balancer service) |
2526 | -* https://opendev.org/openstack/python-senlinclient (Clustering service) |
2527 | -* https://opendev.org/openstack/python-vitrageclient.git (RCA service) |
2528 | -* https://opendev.org/openstack/python-ironicclient (baremetal provisioning service) |
2529 | - |
2530 | diff --git a/openstack_heat.egg-info/SOURCES.txt b/openstack_heat.egg-info/SOURCES.txt |
2531 | index adfe427..04faf9d 100644 |
2532 | --- a/openstack_heat.egg-info/SOURCES.txt |
2533 | +++ b/openstack_heat.egg-info/SOURCES.txt |
2534 | @@ -1144,6 +1144,7 @@ releasenotes/notes/delay-resource-7d44c512081026c8.yaml |
2535 | releasenotes/notes/delay-resource-e20ba61f31799f6e.yaml |
2536 | releasenotes/notes/deployment-swift-data-server-property-51fd4f9d1671fc90.yaml |
2537 | releasenotes/notes/deprecate-heat-manage-migrate_properties_data-command-754c94ef87626a82.yaml |
2538 | +releasenotes/notes/deprecate-inactive-project-rsc-caracal-ba0b0005f67580f9.yaml |
2539 | releasenotes/notes/deprecate-json-formatted-policy-file-ac2f98b31ece0baf.yaml |
2540 | releasenotes/notes/deprecate-nova-floatingip-resources-d5c9447a199be402.yaml |
2541 | releasenotes/notes/deprecate-nova-quota-injected_file-properties-6c6fd7f5231e4c40.yaml |
2542 | @@ -1190,6 +1191,7 @@ releasenotes/notes/know-limit-releasenote-4d21fc4d91d136d9.yaml |
2543 | releasenotes/notes/lbaasv2-hidden-a8f82ddfdba911eb.yaml |
2544 | releasenotes/notes/legacy-client-races-ba7a60cef5ec1694.yaml |
2545 | releasenotes/notes/legacy-stack-user-id-cebbad8b0f2ed490.yaml |
2546 | +releasenotes/notes/limit-resources-aeb2f24e705840de.yaml |
2547 | releasenotes/notes/magnum-resource-update-0f617eec45ef8ef7.yaml |
2548 | releasenotes/notes/make_url-function-d76737adb1e54801.yaml |
2549 | releasenotes/notes/manual-rollback-failed-replacement-08ebb9271617fe9d.yaml |
2550 | diff --git a/openstack_heat.egg-info/entry_points.txt b/openstack_heat.egg-info/entry_points.txt |
2551 | index 46a5aef..f3bb439 100644 |
2552 | --- a/openstack_heat.egg-info/entry_points.txt |
2553 | +++ b/openstack_heat.egg-info/entry_points.txt |
2554 | @@ -117,6 +117,9 @@ zaqar.queue = heat.engine.clients.os.zaqar:QueueConstraint |
2555 | [heat.event_sinks] |
2556 | zaqar-queue = heat.engine.clients.os.zaqar:ZaqarEventSink |
2557 | |
2558 | +[heat.stack_lifecycle_plugins] |
2559 | + |
2560 | + |
2561 | [heat.templates] |
2562 | AWSTemplateFormatVersion.2010-09-09 = heat.engine.cfn.template:CfnTemplate |
2563 | HeatTemplateFormatVersion.2012-12-12 = heat.engine.cfn.template:HeatTemplate |
2564 | @@ -140,12 +143,14 @@ heat_template_version.wallaby = heat.engine.hot.template:HOTemplate20210416 |
2565 | |
2566 | [oslo.config.opts] |
2567 | heat.api.aws.ec2token = heat.api.aws.ec2token:list_opts |
2568 | +heat.common.cache = heat.common.cache:list_opts |
2569 | heat.common.config = heat.common.config:list_opts |
2570 | heat.common.context = heat.common.context:list_opts |
2571 | heat.common.crypt = heat.common.crypt:list_opts |
2572 | heat.common.wsgi = heat.common.wsgi:list_opts |
2573 | heat.engine.clients = heat.engine.clients:list_opts |
2574 | heat.engine.clients.os.keystone.heat_keystoneclient = heat.engine.clients.os.keystone.heat_keystoneclient:list_opts |
2575 | +heat.engine.hot.functions = heat.engine.hot.functions:list_opts |
2576 | heat.engine.notification = heat.engine.notification:list_opts |
2577 | heat.engine.resources = heat.engine.resources:list_opts |
2578 | heat_integrationtests.common.config = heat_integrationtests.common.config:list_opts |
2579 | @@ -162,3 +167,4 @@ heat = heat.policies:list_rules |
2580 | [wsgi_scripts] |
2581 | heat-wsgi-api = heat.httpd.heat_api:init_application |
2582 | heat-wsgi-api-cfn = heat.httpd.heat_api_cfn:init_application |
2583 | + |
2584 | diff --git a/openstack_heat.egg-info/pbr.json b/openstack_heat.egg-info/pbr.json |
2585 | index a9140ec..3a193c6 100644 |
2586 | --- a/openstack_heat.egg-info/pbr.json |
2587 | +++ b/openstack_heat.egg-info/pbr.json |
2588 | @@ -1 +1 @@ |
2589 | -{"git_version": "2df46d4c5", "is_release": false} |
2590 | \ No newline at end of file |
2591 | +{"git_version": "8892f32a2", "is_release": true} |
2592 | \ No newline at end of file |
2593 | diff --git a/openstack_heat.egg-info/requires.txt b/openstack_heat.egg-info/requires.txt |
2594 | index 0f71ad6..481fafb 100644 |
2595 | --- a/openstack_heat.egg-info/requires.txt |
2596 | +++ b/openstack_heat.egg-info/requires.txt |
2597 | @@ -55,8 +55,13 @@ python-troveclient>=2.2.0 |
2598 | python-vitrageclient>=2.7.0 |
2599 | python-zaqarclient>=1.3.0 |
2600 | python-zunclient>=3.4.0 |
2601 | -pytz>=2013.6 |
2602 | requests>=2.23.0 |
2603 | stevedore>=3.1.0 |
2604 | tenacity>=6.1.0 |
2605 | yaql>=1.1.3 |
2606 | + |
2607 | +[:(python_version<"3.9")] |
2608 | +pytz>=2013.6 |
2609 | + |
2610 | +[:(python_version>="3.9")] |
2611 | +tzdata>=2022.4 |
2612 | diff --git a/releasenotes/config.yaml b/releasenotes/config.yaml |
2613 | index 225dc0e..d72ed66 100644 |
2614 | --- a/releasenotes/config.yaml |
2615 | +++ b/releasenotes/config.yaml |
2616 | @@ -1,4 +1,4 @@ |
2617 | --- |
2618 | branch_name_re: '^stable/\w+$' |
2619 | release_tag_re: '((?:[\d.ab]|rc)+)' |
2620 | -closed_branch_tag_re: '^(\w+)-eol$' |
2621 | +closed_branch_tag_re: '^(\w+)-eo[lm]$' |
2622 | diff --git a/releasenotes/notes/deprecate-inactive-project-rsc-caracal-ba0b0005f67580f9.yaml b/releasenotes/notes/deprecate-inactive-project-rsc-caracal-ba0b0005f67580f9.yaml |
2623 | new file mode 100644 |
2624 | index 0000000..edfa948 |
2625 | --- /dev/null |
2626 | +++ b/releasenotes/notes/deprecate-inactive-project-rsc-caracal-ba0b0005f67580f9.yaml |
2627 | @@ -0,0 +1,10 @@ |
2628 | +--- |
2629 | +deprecations: |
2630 | + - | |
2631 | + The following resources have been deprecated, because monasca, sahara and |
2632 | + senlin were marked inactive and will not get deliverables for the 2024.1 |
2633 | + release. These resources will be removed in ``23.0.0`` release. |
2634 | + |
2635 | + - ``OS::Monasca::*`` |
2636 | + - ``OS::Sahara::*`` |
2637 | + - ``OS::Senlin::*`` |
2638 | diff --git a/releasenotes/notes/limit-resources-aeb2f24e705840de.yaml b/releasenotes/notes/limit-resources-aeb2f24e705840de.yaml |
2639 | new file mode 100644 |
2640 | index 0000000..7e9a02b |
2641 | --- /dev/null |
2642 | +++ b/releasenotes/notes/limit-resources-aeb2f24e705840de.yaml |
2643 | @@ -0,0 +1,26 @@ |
2644 | +--- |
2645 | +features: |
2646 | + - | |
2647 | + Heat now supports limiting number of software configs, software |
2648 | + deployments, stack snapshots which users can create, by the following |
2649 | + config options. These limits are not enforced for users with admin role. |
2650 | + |
2651 | + - ``[DEFAULT] max_software_configis_per_tenant`` |
2652 | + - ``[DEFAULT] max_software_deployments_per_tenant`` |
2653 | + - ``[DEFAULT] max_snapshots_per_stack`` |
2654 | + |
2655 | +upgrade: |
2656 | + - | |
2657 | + Now the following limits are enforced by default, unless a request user |
2658 | + has admin role. |
2659 | + |
2660 | + - Maximum number of software configs per project is 4096 |
2661 | + - Maximum number of software deployments per project is 4096 |
2662 | + - Maximum number of stack snapshots per tenant is 32 |
2663 | + |
2664 | + Set the following options in case the limits should be increased. Limits |
2665 | + can be disabled by setting -1 to these options. |
2666 | + |
2667 | + - ``[DEFAULT] max_software_configis_per_tenant`` |
2668 | + - ``[DEFAULT] max_software_deployments_per_tenant`` |
2669 | + - ``[DEFAULT] max_snapshots_per_stack`` |
2670 | diff --git a/releasenotes/source/victoria.rst b/releasenotes/source/victoria.rst |
2671 | index 4efc7b6..8ce9334 100644 |
2672 | --- a/releasenotes/source/victoria.rst |
2673 | +++ b/releasenotes/source/victoria.rst |
2674 | @@ -3,4 +3,4 @@ Victoria Series Release Notes |
2675 | ============================= |
2676 | |
2677 | .. release-notes:: |
2678 | - :branch: stable/victoria |
2679 | + :branch: unmaintained/victoria |
2680 | diff --git a/releasenotes/source/wallaby.rst b/releasenotes/source/wallaby.rst |
2681 | index d77b565..bcf35c5 100644 |
2682 | --- a/releasenotes/source/wallaby.rst |
2683 | +++ b/releasenotes/source/wallaby.rst |
2684 | @@ -3,4 +3,4 @@ Wallaby Series Release Notes |
2685 | ============================ |
2686 | |
2687 | .. release-notes:: |
2688 | - :branch: stable/wallaby |
2689 | + :branch: unmaintained/wallaby |
2690 | diff --git a/releasenotes/source/xena.rst b/releasenotes/source/xena.rst |
2691 | index 1be85be..d19eda4 100644 |
2692 | --- a/releasenotes/source/xena.rst |
2693 | +++ b/releasenotes/source/xena.rst |
2694 | @@ -3,4 +3,4 @@ Xena Series Release Notes |
2695 | ========================= |
2696 | |
2697 | .. release-notes:: |
2698 | - :branch: stable/xena |
2699 | + :branch: unmaintained/xena |
2700 | diff --git a/releasenotes/source/yoga.rst b/releasenotes/source/yoga.rst |
2701 | index 7cd5e90..43cafde 100644 |
2702 | --- a/releasenotes/source/yoga.rst |
2703 | +++ b/releasenotes/source/yoga.rst |
2704 | @@ -3,4 +3,4 @@ Yoga Series Release Notes |
2705 | ========================= |
2706 | |
2707 | .. release-notes:: |
2708 | - :branch: stable/yoga |
2709 | + :branch: unmaintained/yoga |
2710 | diff --git a/requirements.txt b/requirements.txt |
2711 | index 04ebf4e..f25280d 100644 |
2712 | --- a/requirements.txt |
2713 | +++ b/requirements.txt |
2714 | @@ -51,10 +51,11 @@ python-troveclient>=2.2.0 # Apache-2.0 |
2715 | python-vitrageclient>=2.7.0 # Apache-2.0 |
2716 | python-zaqarclient>=1.3.0 # Apache-2.0 |
2717 | python-zunclient>=3.4.0 # Apache-2.0 |
2718 | -pytz>=2013.6 # MIT |
2719 | +pytz>=2013.6;python_version<"3.9" # MIT |
2720 | PyYAML>=5.1 # MIT |
2721 | requests>=2.23.0 # Apache-2.0 |
2722 | tenacity>=6.1.0 # Apache-2.0 |
2723 | +tzdata>=2022.4;python_version>="3.9" # MIT |
2724 | Routes>=2.3.1 # MIT |
2725 | SQLAlchemy>=1.4.0 # MIT |
2726 | stevedore>=3.1.0 # Apache-2.0 |
2727 | diff --git a/setup.cfg b/setup.cfg |
2728 | index b89a99c..8e8cf4e 100644 |
2729 | --- a/setup.cfg |
2730 | +++ b/setup.cfg |
2731 | @@ -47,10 +47,12 @@ wsgi_scripts = |
2732 | heat-wsgi-api = heat.httpd.heat_api:init_application |
2733 | heat-wsgi-api-cfn = heat.httpd.heat_api_cfn:init_application |
2734 | oslo.config.opts = |
2735 | + heat.common.cache = heat.common.cache:list_opts |
2736 | heat.common.config = heat.common.config:list_opts |
2737 | heat.common.context = heat.common.context:list_opts |
2738 | heat.common.crypt = heat.common.crypt:list_opts |
2739 | heat.engine.clients.os.keystone.heat_keystoneclient = heat.engine.clients.os.keystone.heat_keystoneclient:list_opts |
2740 | + heat.engine.hot.functions = heat.engine.hot.functions:list_opts |
2741 | heat.common.wsgi = heat.common.wsgi:list_opts |
2742 | heat.engine.clients = heat.engine.clients:list_opts |
2743 | heat.engine.notification = heat.engine.notification:list_opts |
2744 | diff --git a/test-requirements.txt b/test-requirements.txt |
2745 | index 10f00a0..bea7ec6 100644 |
2746 | --- a/test-requirements.txt |
2747 | +++ b/test-requirements.txt |
2748 | @@ -1,13 +1,5 @@ |
2749 | -# The order of packages is significant, because pip processes them in the order |
2750 | -# of appearance. Changing the order has an impact on the overall integration |
2751 | -# process, which may cause wedges in the gate later. |
2752 | - |
2753 | # Hacking already pins down pep8, pyflakes and flake8 |
2754 | -hacking>=3.0.1,<3.1.0 # Apache-2.0 |
2755 | -# remove this pyflakes from here once you bump the |
2756 | -# hacking to 3.2.0 or above. hacking 3.2.0 takes |
2757 | -# care of pyflakes version compatibilty. |
2758 | -pyflakes>=2.1.1 |
2759 | +hacking>=6.1.0,<6.2.0 # Apache-2.0 |
2760 | |
2761 | bandit!=1.6.0,>=1.1.0 # Apache-2.0 |
2762 | coverage!=4.4,>=4.0 # Apache-2.0 |
2763 | diff --git a/tox.ini b/tox.ini |
2764 | index 6cd81ae..7dbbd6c 100644 |
2765 | --- a/tox.ini |
2766 | +++ b/tox.ini |
2767 | @@ -101,7 +101,6 @@ deps = |
2768 | # The following bandit tests are being skipped: |
2769 | # B101: Test for use of assert |
2770 | # B104: Test for binding to all interfaces |
2771 | -# B107: Test for use of hard-coded password argument defaults |
2772 | # B110: Try, Except, Pass detected. |
2773 | # B113: Requests call without timeout |
2774 | # B310: Audit url open for permitted schemes |
2775 | @@ -112,7 +111,7 @@ deps = |
2776 | # B506: Test for use of yaml load |
2777 | # B603: Test for use of subprocess with shell equals true |
2778 | # B607: Test for starting a process with a partial path |
2779 | -commands = bandit -r heat -x tests --skip B101,B104,B107,B110,B113,B310,B311,B404,B410,B504,B506,B603,B607 |
2780 | +commands = bandit -r heat -x tests --skip B101,B104,B110,B113,B310,B311,B404,B410,B504,B506,B603,B607 |
2781 | |
2782 | [flake8] |
2783 | show-source = true |
2784 | @@ -132,10 +131,10 @@ import_exceptions = heat.common.i18n |
2785 | |
2786 | [flake8:local-plugins] |
2787 | extension = |
2788 | - Heat301 = checks:no_log_warn |
2789 | - Heat302 = checks:check_python3_no_iteritems |
2790 | - Heat303 = checks:check_python3_no_iterkeys |
2791 | - Heat304 = checks:check_python3_no_itervalues |
2792 | + HE301 = checks:no_log_warn |
2793 | + HE302 = checks:check_python3_no_iteritems |
2794 | + HE303 = checks:check_python3_no_iterkeys |
2795 | + HE304 = checks:check_python3_no_itervalues |
2796 | paths = ./heat/hacking |
2797 | |
2798 | [testenv:debug] |