Merge ~freyes/ubuntu/+source/python-magnumclient:stable/ussuri into ~ubuntu-openstack-dev/ubuntu/+source/python-magnumclient:stable/ussuri
- Git
- lp:~freyes/ubuntu/+source/python-magnumclient
- stable/ussuri
- Merge into stable/ussuri
Proposed by
Felipe Reyes
Status: | Merged |
---|---|
Merged at revision: | aa914fe1e7e667083e2f0e13ac977d7814de789a |
Proposed branch: | ~freyes/ubuntu/+source/python-magnumclient:stable/ussuri |
Merge into: | ~ubuntu-openstack-dev/ubuntu/+source/python-magnumclient:stable/ussuri |
Diff against target: |
4474 lines (+2850/-341) 56 files modified
.zuul.yaml (+3/-6) AUTHORS (+143/-0) CONTRIBUTING.rst (+1/-1) ChangeLog (+624/-0) PKG-INFO (+61/-0) README.rst (+6/-6) debian/changelog (+11/-0) debian/patches/series (+0/-2) debian/watch (+2/-2) dev/null (+0/-79) doc/requirements.txt (+2/-1) magnumclient/common/cliutils.py (+2/-2) magnumclient/common/httpclient.py (+11/-8) magnumclient/common/utils.py (+69/-35) magnumclient/exceptions.py (+8/-8) magnumclient/osc/plugin.py (+6/-4) magnumclient/osc/v1/cluster_templates.py (+21/-1) magnumclient/osc/v1/clusters.py (+170/-10) magnumclient/osc/v1/nodegroups.py (+301/-0) magnumclient/shell.py (+7/-6) magnumclient/tests/osc/unit/osc_fakes.py (+2/-5) magnumclient/tests/osc/unit/v1/fakes.py (+86/-2) magnumclient/tests/osc/unit/v1/test_cluster_templates.py (+6/-4) magnumclient/tests/osc/unit/v1/test_clusters.py (+69/-9) magnumclient/tests/osc/unit/v1/test_nodegroups.py (+333/-0) magnumclient/tests/test_httpclient.py (+4/-5) magnumclient/tests/test_utils.py (+20/-20) magnumclient/tests/utils.py (+3/-3) magnumclient/tests/v1/shell_test_base.py (+29/-29) magnumclient/tests/v1/test_bays_shell.py (+0/-9) magnumclient/tests/v1/test_clusters.py (+43/-0) magnumclient/tests/v1/test_clusters_shell.py (+0/-11) magnumclient/tests/v1/test_clustertemplates.py (+6/-1) magnumclient/tests/v1/test_clustertemplates_shell.py (+3/-1) magnumclient/tests/v1/test_nodegroups.py (+333/-0) magnumclient/v1/basemodels.py (+1/-1) magnumclient/v1/bays_shell.py (+2/-2) magnumclient/v1/client.py (+2/-0) magnumclient/v1/cluster_templates_shell.py (+8/-0) magnumclient/v1/clusters.py (+34/-0) magnumclient/v1/clusters_shell.py (+2/-3) magnumclient/v1/nodegroups.py (+84/-0) python_magnumclient.egg-info/PKG-INFO (+61/-0) python_magnumclient.egg-info/SOURCES.txt (+128/-0) python_magnumclient.egg-info/dependency_links.txt (+1/-0) python_magnumclient.egg-info/entry_points.txt (+36/-0) python_magnumclient.egg-info/not-zip-safe (+1/-0) python_magnumclient.egg-info/pbr.json (+1/-0) python_magnumclient.egg-info/requires.txt (+15/-0) python_magnumclient.egg-info/top_level.txt (+1/-0) releasenotes/source/index.rst (+2/-0) releasenotes/source/stein.rst (+6/-0) releasenotes/source/train.rst (+6/-0) setup.cfg (+57/-47) test-requirements.txt (+2/-2) tox.ini (+15/-16) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu OpenStack uploaders | Pending | ||
Review via email:
|
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/.gitignore b/.gitignore |
2 | deleted file mode 100644 |
3 | index 17ed160..0000000 |
4 | --- a/.gitignore |
5 | +++ /dev/null |
6 | @@ -1,54 +0,0 @@ |
7 | -*.py[cod] |
8 | - |
9 | -# C extensions |
10 | -*.so |
11 | - |
12 | -# Packages |
13 | -*.egg* |
14 | -dist |
15 | -build |
16 | -eggs |
17 | -parts |
18 | -bin |
19 | -var |
20 | -sdist |
21 | -develop-eggs |
22 | -.installed.cfg |
23 | -lib |
24 | -lib64 |
25 | - |
26 | -# Installer logs |
27 | -pip-log.txt |
28 | - |
29 | -# Unit test / coverage reports |
30 | -.coverage |
31 | -.tox |
32 | -cover |
33 | -cover-master |
34 | -.stestr/ |
35 | -.venv |
36 | - |
37 | -# Translations |
38 | -*.mo |
39 | - |
40 | -# Mr Developer |
41 | -.mr.developer.cfg |
42 | -.project |
43 | -.pydevproject |
44 | -.idea |
45 | - |
46 | -# Complexity |
47 | -output/*.html |
48 | -output/*/index.html |
49 | - |
50 | -# Sphinx |
51 | -doc/build |
52 | - |
53 | -# pbr generates these |
54 | -AUTHORS |
55 | -ChangeLog |
56 | - |
57 | -# Editors |
58 | -*~ |
59 | -.*.swp |
60 | -*.DS_Store |
61 | diff --git a/.gitreview b/.gitreview |
62 | deleted file mode 100644 |
63 | index 2616d47..0000000 |
64 | --- a/.gitreview |
65 | +++ /dev/null |
66 | @@ -1,4 +0,0 @@ |
67 | -[gerrit] |
68 | -host=review.openstack.org |
69 | -port=29418 |
70 | -project=openstack/python-magnumclient.git |
71 | diff --git a/.zuul.yaml b/.zuul.yaml |
72 | index 241ca5d..c946e34 100644 |
73 | --- a/.zuul.yaml |
74 | +++ b/.zuul.yaml |
75 | @@ -1,18 +1,15 @@ |
76 | - project: |
77 | templates: |
78 | - - openstack-python-jobs |
79 | - - openstack-python35-jobs |
80 | - - openstack-python36-jobs |
81 | - check-requirements |
82 | + - openstack-cover-jobs |
83 | + - openstack-lower-constraints-jobs |
84 | + - openstack-python3-ussuri-jobs |
85 | - publish-openstack-docs-pti |
86 | check: |
87 | jobs: |
88 | - - openstack-tox-lower-constraints |
89 | - build-openstack-releasenotes |
90 | - openstack-tox-cover: |
91 | voting: false |
92 | - |
93 | gate: |
94 | jobs: |
95 | - - openstack-tox-lower-constraints |
96 | - build-openstack-releasenotes |
97 | diff --git a/AUTHORS b/AUTHORS |
98 | new file mode 100644 |
99 | index 0000000..add3f74 |
100 | --- /dev/null |
101 | +++ b/AUTHORS |
102 | @@ -0,0 +1,143 @@ |
103 | +Aaron-DH <dinghh@awcloud.com> |
104 | +Abhishek Chanda <abhishek.becs@gmail.com> |
105 | +Abhishek Chanda <abhishek@cloudscaling.com> |
106 | +Adrian Otto <adrian.otto@rackspace.com> |
107 | +Akhila Kishore <akhila.kishore@intel.com> |
108 | +Amey Bhide <abhide@vmware.com> |
109 | +Andreas Jaeger <aj@suse.com> |
110 | +Andreas Jaeger <aj@suse.de> |
111 | +Andrew Melton <andrew.melton@rackspace.com> |
112 | +Anh Tran <anhtt@vn.fujitsu.com> |
113 | +Bharat Kunwar <b.kunwar@gmail.com> |
114 | +Bharat Kunwar <bharat@stackhpc.com> |
115 | +Bharath Thiruveedula <bharath_ves@hotmail.com> |
116 | +Boris Pilka <boris.pilka@x-works.io> |
117 | +Cedric Brandily <zzelle@gmail.com> |
118 | +Christoph Jansen <jansen.christoph@yahoo.de> |
119 | +Clenimar Filemon <clenimar.filemon@gmail.com> |
120 | +Corey Bryant <corey.bryant@canonical.com> |
121 | +Corey O'Brien <corey.obrien@rackspace.com> |
122 | +Costin GamenČ› <costin@cern.ch> |
123 | +Dai Dang Van <daidv@vn.fujitsu.com> |
124 | +Dane LeBlanc <leblancd@cisco.com> |
125 | +Daneyon Hansen <danehans@cisco.com> |
126 | +Daniel Abad <d.abad@cern.ch> |
127 | +Davanum Srinivas <davanum@gmail.com> |
128 | +Davanum Srinivas <dims@linux.vnet.ibm.com> |
129 | +David Liu <david.liu@cn.ibm.com> |
130 | +David Rabel <rabel@b1-systems.de> |
131 | +Doug Hellmann <doug@doughellmann.com> |
132 | +Eli Qiao <liyong.qiao@intel.com> |
133 | +Eric Brown <browne@vmware.com> |
134 | +Erik Olof Gunnar Andersson <eandersson@blizzard.com> |
135 | +Fang Fenghua <449171342@qq.com> |
136 | +Fang fenghua <449171342@qq.com> |
137 | +Feilong Wang <flwang@catalyst.net.nz> |
138 | +Feng Shengqin <feng.shengqin@zte.com.cn> |
139 | +Flavio Percoco <flaper87@gmail.com> |
140 | +Ghanshyam Mann <gmann@ghanshyammann.com> |
141 | +Haiwei Xu <xu-haiwei@mxw.nes.nec.co.jp> |
142 | +Hangdong Zhang <hdzhang@fiberhome.com> |
143 | +Hieu LE <hieulq@vn.fujitsu.com> |
144 | +Hongbin Lu <hongbin.lu@huawei.com> |
145 | +Hongbin Lu <hongbin034@gmail.com> |
146 | +Hongbn Lu <hongbin.lu@huawei.com> |
147 | +Hua Wang <wanghua.humble@gmail.com> |
148 | +Ian Cordasco <graffatcolmingov@gmail.com> |
149 | +Jake Yip <jake.yip@unimelb.edu.au> |
150 | +James Page <james.page@ubuntu.com> |
151 | +Janek Lehr <jjlehr@us.ibm.com> |
152 | +Janonymous <janonymous.codevulture@gmail.com> |
153 | +Jason Dunsmore <jasondunsmore@gmail.com> |
154 | +Jay Lau (Guangya Liu) <liugya@cn.ibm.com> |
155 | +Jay Lau <liugya@cn.ibm.com> |
156 | +Jennifer Carlucci <joffter@us.ibm.com> |
157 | +Jeremy Stanley <fungi@yuggoth.org> |
158 | +Johannes Grassler <johannes.grassler@suse.com> |
159 | +Kennan <wkq5325@gmail.com> |
160 | +Kennan <wkqwu@cn.ibm.com> |
161 | +Kiran_totad <kiran.totad@nectechnologies.in> |
162 | +Lan Qi song <lqslan@cn.ibm.com> |
163 | +Lin Yang <lin.a.yang@intel.com> |
164 | +Lucky samadhiya <lucky.samadhiya@nectechnologies.in> |
165 | +M V P Nitesh <m.nitesh@nectechnologies.in> |
166 | +Madhuri <madhuri.kumari@intel.com> |
167 | +Madhuri Kumari <madhuri.kumari@intel.com> |
168 | +Madhuri Kumari <madhuri.kumari@nectechnologies.in> |
169 | +Madhuri Kumari <madhuri.rai07@gmail.com> |
170 | +Manjeet Singh Bhatia <manjeet.s.bhatia@intel.com> |
171 | +Mark Goddard <mark@stackhpc.com> |
172 | +Michael Lekkas <lekkasmi@uk.ibm.com> |
173 | +Michal Arbet <michal.arbet@ultimum.io> |
174 | +Mike Fedosin <mfedosin@gmail.com> |
175 | +Monty Taylor <mordred@inaugust.com> |
176 | +Motohiro OTSUKA <ootsuka@mxs.nes.nec.co.jp> |
177 | +Murali Allada <murali.allada@rackspace.com> |
178 | +Namrata <sitlani.namrata@yahoo.in> |
179 | +Nguyen Hai <nguyentrihai93@gmail.com> |
180 | +Niall Bunting <niall.bunting@hpe.com> |
181 | +OTSUKA, Yuanying <ootsuka@mxs.nes.nec.co.jp> |
182 | +OTSUKA, Yuanying <yuanying@fraction.jp> |
183 | +OpenStack Release Bot <infra-root@openstack.org> |
184 | +PanFengyun <fengyun.pan@easystack.cn> |
185 | +Pavlo Shchelokovskyy <shchelokovskyy@gmail.com> |
186 | +Rajiv Kumar <rajiv.kumar@nectechnologies.in> |
187 | +Ricardo Rocha <rocha.porto@gmail.com> |
188 | +Sergey Vilgelm <sergey@vilgelm.info> |
189 | +Spyros Trigazis <spyridon.trigazis@cern.ch> |
190 | +Spyros Trigazis <strigazi@gmail.com> |
191 | +Stephen Watson <stephen.watson@intel.com> |
192 | +Steven Dake <sdake@redhat.com> |
193 | +Steven Dake <stdake@cisco.com> |
194 | +Surojit Pathak <suro@yahoo-inc.com> |
195 | +Swapnil Kulkarni (coolsvap) <me@coolsvap.net> |
196 | +Theodoros Tsioutsias <theodoros.tsioutsias@cern.ch> |
197 | +Tom Cammann <tom.cammann@hp.com> |
198 | +Tom Cammann <tom.cammann@hpe.com> |
199 | +Tovin Seven <vinhnt@vn.fujitsu.com> |
200 | +Vieri <15050873171@163.com> |
201 | +Vijendar Komalla <vijendar.komalla@RACKSPACE.COM> |
202 | +Vikas Choudhary <choudharyvikas16@gmail.com> |
203 | +Vilobh Meshram <vilobhmm@yahoo-inc.com> |
204 | +Vipul Nayyar <nayyar_vipul@yahoo.com> |
205 | +Vivek Jain <vivek.jain.openstack@gmail.com> |
206 | +Vu Cong Tuan <tuanvc@vn.fujitsu.com> |
207 | +Wanlong Gao <wanlong.gao@easystack.cn> |
208 | +Wenzhi Yu <wenzhi_yu@163.com> |
209 | +XiaojueGuan <guanalbertjone@gmail.com> |
210 | +Yang Hongyang <hongyang.yang@easystack.cn> |
211 | +Yolanda Robla <yolanda.robla-mota@hp.com> |
212 | +Zhenguo Niu <niuzhenguo@huawei.com> |
213 | +chenaidong1 <chen.aidong@zte.com.cn> |
214 | +chenlx <chenlx@fiberhome.com> |
215 | +coldmoment <yan.zhiwei1@zte.com.cn> |
216 | +coldmoment <ztehypervisor@zte.com.cn> |
217 | +digambar <digambar_patil1@persistent.co.in> |
218 | +digambar <digambarpatil15@yahoo.co.in> |
219 | +gecong1973 <ge.cong@zte.com.cn> |
220 | +guo yunxian <yunxian.guo@easystack.cn> |
221 | +houming-wang <houming.wang@easystack.cn> |
222 | +jacky06 <zhang.min@99cloud.net> |
223 | +kavithahr <kavitha.r@nectechnologies.in> |
224 | +maliki <imran.malik@emc.com> |
225 | +melissaml <ma.lei@99cloud.net> |
226 | +npraveen35 <npraveen35@gmail.com> |
227 | +pawnesh.kumar <pawnesh.kumar@nectechnologies.in> |
228 | +phelanm <phelanm@gmail.com> |
229 | +qingszhao <zhao.daqing@99cloud.net> |
230 | +rajat29 <rajat.sharma@nectechnologies.in> |
231 | +ricolin <rico.l@inwinstack.com> |
232 | +ricolin <rico.lin@easystack.cn> |
233 | +shu-mutou <shu-mutou@rf.jp.nec.com> |
234 | +space <fengzhr@awcloud.com> |
235 | +sunjia <sunjia@inspur.com> |
236 | +ting.wang <ting.wang@easystack.cn> |
237 | +venkatamahesh <venkatamaheshkotha@gmail.com> |
238 | +wangbo <wangbo_bupt@163.com> |
239 | +wangqun <bjwqun@cn.ibm.com> |
240 | +xiexs <xiexs@cn.fujitsu.com> |
241 | +yanghuichan <yanghc@fiberhome.com> |
242 | +yatin <yatin.karel@nectechnologies.in> |
243 | +yatin <ykarel@redhat.com> |
244 | +yatin karel <yatin.karel@nectechnologies.in> |
245 | +yatinkarel <yatin.karel@nectechnologies.in> |
246 | diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst |
247 | index c82011a..771dc9f 100644 |
248 | --- a/CONTRIBUTING.rst |
249 | +++ b/CONTRIBUTING.rst |
250 | @@ -13,4 +13,4 @@ Pull requests submitted through GitHub will be ignored. |
251 | |
252 | Bugs should be filed on Launchpad, not GitHub: |
253 | |
254 | - https://bugs.launchpad.net/python-magnumclient |
255 | \ No newline at end of file |
256 | + https://bugs.launchpad.net/python-magnumclient |
257 | diff --git a/ChangeLog b/ChangeLog |
258 | new file mode 100644 |
259 | index 0000000..6646705 |
260 | --- /dev/null |
261 | +++ b/ChangeLog |
262 | @@ -0,0 +1,624 @@ |
263 | +CHANGES |
264 | +======= |
265 | + |
266 | +3.0.1 |
267 | +----- |
268 | + |
269 | +* Labels override |
270 | +* Rename variables to address pep8 error |
271 | +* Update TOX/UPPER\_CONSTRAINTS\_FILE for stable/ussuri |
272 | +* Update .gitreview for stable/ussuri |
273 | + |
274 | +3.0.0 |
275 | +----- |
276 | + |
277 | +* Update master for stable/train |
278 | +* Update hacking for Python3 |
279 | +* Drop py27 tests |
280 | +* Bugfix: Use fields option for cluster template list |
281 | + |
282 | +2.17.0 |
283 | +------ |
284 | + |
285 | +* Allow cluster config for any cluster state |
286 | +* Add nodegroup CRUD commands |
287 | +* Replace git.openstack.org URLs with opendev.org URLs |
288 | + |
289 | +2.15.0 |
290 | +------ |
291 | + |
292 | +* Support network, subnet and FIP when creating cluster |
293 | + |
294 | +2.14.0 |
295 | +------ |
296 | + |
297 | +* Add Python 3 Train unit tests |
298 | +* Conditional hidden arg for backward compatibility |
299 | +* Fix coverage test |
300 | +* Blacklist bandit 1.6.0 and cap Sphinx on Python2 |
301 | +* Display project\_id for cluster show |
302 | +* OpenDev Migration Patch |
303 | +* Dropping the py35 testing |
304 | + |
305 | +2.13.0 |
306 | +------ |
307 | + |
308 | +* Add nodegroup list/show commands |
309 | +* Support upgrade API |
310 | +* Support resize api |
311 | +* Update master for stable/stein |
312 | +* Support health\_status on client side |
313 | +* python3 fixes |
314 | + |
315 | +2.12.0 |
316 | +------ |
317 | + |
318 | +* Keystone auth support |
319 | +* add python 3.7 unit test job |
320 | +* Add hidden property to cluster template |
321 | +* Fix py37 compatibility |
322 | +* Use oslo\_serialization instead of the json module directly |
323 | +* Use template for lower-constraints |
324 | +* Change openstack-dev to openstack-discuss |
325 | +* Add Python 3.6 classifier to setup.cfg |
326 | +* add python 3.6 unit test job |
327 | +* Trivial: Update pypi url to new url |
328 | + |
329 | +2.11.0 |
330 | +------ |
331 | + |
332 | +* Fix crash on Service catalog empty 403 response |
333 | +* add python 3.6 unit test job |
334 | +* switch documentation job to new PTI |
335 | +* import zuul job settings from project-config |
336 | +* Add release notes for magnum client |
337 | +* [k8s] Add embed certs to config |
338 | + |
339 | +2.10.0 |
340 | +------ |
341 | + |
342 | +* Switch to stestr |
343 | +* osc: Don't pass parameters with null value |
344 | +* Update links in README |
345 | +* fix tox python3 overrides |
346 | +* Fix entrypoints for quotas |
347 | +* Follow the new PTI for document build |
348 | +* add lower-constraints job |
349 | +* OSC command for magnum quota's |
350 | +* Add deprecation warnings to magnum client commands |
351 | +* Replace six.iteritems() with dict.items() in python-magnumclient |
352 | +* OSC command for ca-show, ca-sign, ca-roatate and stats-list |
353 | +* Now cluster-template-update works for "labels" |
354 | +* Make cluster-config rbac compatible for kubebernetes |
355 | + |
356 | +2.8.0 |
357 | +----- |
358 | + |
359 | +* Add disable floating ip parameter |
360 | +* Updated from global requirements |
361 | +* Cleanup test-requirements |
362 | +* Updated from global requirements |
363 | +* Updated from global requirements |
364 | +* Set --labels default to None on cluster create |
365 | +* OSC: Add --flavor to coe cluster create |
366 | +* Add missing master\_flavor\_id in cluster attributes |
367 | +* Avoid tox\_install.sh for constraints support |
368 | +* Updated from global requirements |
369 | +* Replace six.iteritems() with .items() |
370 | +* OSC: Add --master-flavor to coe cluster create |
371 | +* Make cluster config --force a boolean |
372 | +* Updated from global requirements |
373 | +* Add --labels for cluster-create |
374 | +* OSC: Add --labels to coe cluster create |
375 | +* Add oslo.log as requirement |
376 | +* OSC: Add magnum service-list command |
377 | +* Now \`name\` is a positional argument in cluster creation |
378 | +* OSC: Remove unused files |
379 | +* inline comment typo fix |
380 | + |
381 | +2.7.0 |
382 | +----- |
383 | + |
384 | +* Remove log translations |
385 | +* Updated from global requirements |
386 | +* OSC: Add cluster config command |
387 | +* OSC 4/4 Add remaining cluster commands |
388 | +* OSC 3/4 Add remaining CT commands |
389 | +* OSC 2/4 Add Cluster Create and List |
390 | +* Updated from global requirements |
391 | +* OSC 1/4 Add CT create and UT framework |
392 | +* Remove docker-volume-size from cluster-list |
393 | +* Updated from global requirements |
394 | +* Make cluster name positional in ca-show |
395 | +* remove slash from kubernetes cluster context name |
396 | +* Update the documentation link for doc migration |
397 | +* Updated from global requirements |
398 | +* Updated from global requirements |
399 | +* switch to openstackdocstheme |
400 | +* Don't set a default for docker\_volume\_size |
401 | +* Updated from global requirements |
402 | +* Make --profile load from environment variables |
403 | +* Add --docker-volume-size for cluster-create |
404 | +* Updated from global requirements |
405 | +* Change assertTrue(isinstance()) by optimal assert |
406 | + |
407 | +2.6.0 |
408 | +----- |
409 | + |
410 | +* Add the support for 'detail' flag |
411 | +* Updated from global requirements |
412 | +* Replace assertRaisesRegexp with assertRaisesRegex |
413 | +* Updated from global requirements |
414 | +* Updated from global requirements |
415 | +* Magnum client suport insecure\_registry |
416 | +* Use assertIsNone(...) instead of assertEqual(None, ...) |
417 | +* Updated from global requirements |
418 | +* Updated from global requirements |
419 | +* Make --cluster option required for ca-rotate |
420 | +* Move cover.sh to the tools directory |
421 | +* Remove support for keyapir UUID |
422 | +* Fix wrong path reference |
423 | +* Update .gitignore to ignore .eggs |
424 | +* Increase Test coverage |
425 | +* The python 3.4 support is removed |
426 | +* Correct mistake from OSprofiler help |
427 | +* Fix UT for duplicate name args test case |
428 | +* Updated from global requirements |
429 | +* Add magnum client support for resource quotas |
430 | +* Update test requirement |
431 | +* Allow name as positional argument |
432 | +* Print exception details on update failure |
433 | +* Simplify magnumclient.shell.OpenStackMagnumShell.main() |
434 | +* Compare test coverage with the master branch |
435 | +* Updated from global requirements |
436 | + |
437 | +2.5.0 |
438 | +----- |
439 | + |
440 | +* Add usage docs for magnum client |
441 | +* Updated from global requirements |
442 | +* Increase UT Coverage |
443 | +* Add the OSC 'cluster template list' command |
444 | +* Add osc-lib to requirements.txt |
445 | +* Add ca-rotate command to magnumclient |
446 | + |
447 | +2.4.0 |
448 | +----- |
449 | + |
450 | +* Adding stats-list command to magnum client |
451 | +* Added link for modindex |
452 | +* Increase UT Coverage |
453 | +* Fix passing TLS\_VERIFIED in clusters/bays\_shell |
454 | +* Increase UT Coverage |
455 | +* Integrate OSprofiler in Magnum Client |
456 | +* Remove H903 error in sources |
457 | +* Updated from global requirements |
458 | +* Fix: swarm cluster-config, bay-config with tls\_disabled |
459 | +* Updated from global requirements |
460 | +* Pass 'api\_version' to create HTTPClient |
461 | +* Mark help messages for Translation |
462 | +* Allow cluster-config on cluster status 'ROLLBACK\_COMPLETE' |
463 | +* Add OSC command for cluster\_templates list |
464 | +* Rollback cluster/bay on update failure |
465 | +* Updated from global requirements |
466 | +* Magnum cluster-config/bay-config compatible with py3 |
467 | +* Updated from global requirements |
468 | +* Show team and repo badges on README |
469 | +* Remove Not used Classes/Methods from apiclient.base |
470 | +* Use assert\_called\_\*/assert\_not\_called to verify mock calls |
471 | +* Fix: some typos in unit test |
472 | +* Use assert\_called\_\*/assert\_not\_called to verify mock calls |
473 | +* Renames \*-id parameters |
474 | +* Implement Parameter Deprecation |
475 | +* Use assert\_called\_\*/assert\_not\_called to verify mock calls |
476 | +* Add a deprecation message to the bay\* commands' help text |
477 | +* Updated from global requirements |
478 | +* Increase UT coverage |
479 | +* Remove invalid check for 'manifest' path |
480 | +* Updated from global requirements |
481 | +* Add .venv directory to .gitignore |
482 | +* Enable DeprecationWarning in test environments |
483 | +* Updated from global requirements |
484 | +* Add \_\_ne\_\_ built-in function |
485 | +* Add missing options for HTTPClient if auth\_token given |
486 | +* Updated from global requirements |
487 | +* Remove white space between print and () |
488 | +* Add --keypair-id for cluster-create |
489 | +* Replace assertTrue(a in b) with assertIn(a, b) |
490 | +* Updated from global requirements |
491 | +* Fix the generated k8s config file |
492 | +* cluster-config return absolute path |
493 | +* delete python bytecode including pyo before every test run |
494 | +* Fix a keyward arguement error on bay-config |
495 | +* Add magnum.bash\_completion This can support the function of autocomplete for magnum's commands |
496 | +* Cluster creation command returns complete cluster uuid |
497 | +* Sync tools/tox\_install.sh |
498 | + |
499 | +2.3.0 |
500 | +----- |
501 | + |
502 | +* Updated from global requirements |
503 | +* Magnum client to support sync and async bay opts |
504 | +* Add microversioning support for httpclient |
505 | +* Add floating\_ip\_enabled attributes to baymodel |
506 | +* Cleanup coverage configuration |
507 | +* Fixes bay\_uuid parameter issue in functional tests |
508 | +* Fix to use HttpClient if token is given |
509 | +* Updates certificate CLI to use cluster |
510 | +* Updated from global requirements |
511 | +* Adds 'cluster' and 'cluster template' |
512 | +* Append value using comma if key exists in label |
513 | +* bay-config return absolute path |
514 | +* Updated from global requirements |
515 | +* Use testr coverage feature |
516 | +* Use upper constraints for all jobs in tox.ini |
517 | +* Updated from global requirements |
518 | +* Enabled magnum client to display detailed information |
519 | +* Updated from global requirements |
520 | +* Add Python 3.5 classifier and venv |
521 | +* Base OSC plugin support |
522 | +* Use os-client-config in shell |
523 | +* Remove discover from test-requirements |
524 | +* Increase unit test coverage for module baymodels |
525 | +* Update the magnum client to send the latest version |
526 | +* Updated from global requirements |
527 | +* Add shell command bay-config |
528 | +* Display baymodel info with bay-show command |
529 | + |
530 | +2.2.0 |
531 | +----- |
532 | + |
533 | +* Updated from global requirements |
534 | +* Bay\_create\_timeout should be set to 60 default |
535 | +* Prints '-' instead of 'None' when data is None |
536 | +* Updated from global requirements |
537 | +* Pass a flag to disable LB in baymodels |
538 | +* Log appropriate error while exception |
539 | +* Add fixed\_subnet attributes to baymodel |
540 | +* Updated from global requirements |
541 | +* Support OS\_PROJECT\_\* env variables |
542 | +* Completely remove openstack common modules |
543 | +* Updated from global requirements |
544 | +* Add docker-storage-driver argument to baymodel |
545 | +* Updated from global requirements |
546 | +* Updated from global requirements |
547 | +* Updated from global requirements |
548 | +* Tox test should respect upper-constraints |
549 | +* Switch to a new service type "container-infra" |
550 | +* Add mesos\_slave\_executor\_environment\_variables validate in CLI |
551 | +* Add some fields back to bay\_list |
552 | +* Updated from global requirements |
553 | +* Add '--fields' to show more columns for bay-list |
554 | +* Update the home-page with developer documentation |
555 | +* Correcting help messages of baymodel |
556 | +* Add python3 to python classifiers |
557 | +* Add '--fields' to show more columns for baymodel-list |
558 | +* Corrected spacing mistake in baymodels\_shell.py |
559 | +* Updated from global requirements |
560 | +* Fix the bug when some value in labels has comma, it will fail |
561 | +* Remove k8s pods, rcs, svc and container API calls |
562 | + |
563 | +2.1.0 |
564 | +----- |
565 | + |
566 | +* Updated from global requirements |
567 | +* Add endpoint\_override parameter to python-magnumclient |
568 | +* Updated from global requirements |
569 | +* Revert "Parameter format change for ca-show and ca-sign" |
570 | +* Updated from global requirements |
571 | +* Parameter format change for ca-show and ca-sign |
572 | +* Updated from global requirements |
573 | +* Fix the container-list with --limit 'a negative number' |
574 | +* Remove the update function of container |
575 | +* Add missing user message |
576 | +* Add marker/limit/sort-key/sort-dir features for bay-list |
577 | +* Add marker/limit/sort-key/sort-dir features for container-list |
578 | +* Allow semicolons in list of labels |
579 | +* Add unit tests for MServiceManager.list() method |
580 | +* Add unit tests for ContainerManager.list() method |
581 | +* Add unit tests for BayModelManager.list() method |
582 | +* Add unit tests for BayManager.list() method |
583 | +* Adapt http response error message parsing |
584 | + |
585 | +2.0.0 |
586 | +----- |
587 | + |
588 | +* Fix incorrect initialization of OrderedDict |
589 | +* Remove bandit.yaml in favor of defaults |
590 | +* Revert "Completely remove openstack common modules" |
591 | +* Use six.u instead of u'' |
592 | +* Completely remove openstack common modules |
593 | +* Add param for magnum baymodel-list |
594 | +* Move bandit into pep8 |
595 | +* Client : Create BayModel with server type(VM/BM) |
596 | +* Updated from global requirements |
597 | +* Sync with oslo-incubator |
598 | +* Updated from global requirements |
599 | +* Remove node object from magnumclient |
600 | +* Exception not catched when bay create failed |
601 | +* Fix a spell typo |
602 | +* The rc-list should contain bay\_uuid |
603 | +* Remove unused attribute "ssh\_authorized\_key" |
604 | +* Update translation setup |
605 | +* Fix incorrect help message |
606 | +* Add Keystone v3 compatibility |
607 | +* Updated from global requirements |
608 | +* Adds Container Volume Model volume\_driver support |
609 | +* Python 3.4 compatibility |
610 | +* Add --insecure option |
611 | +* Fix endpoint\_types |
612 | +* Updated from global requirements |
613 | +* Replace six.iteritems(dict) with dict.items() |
614 | +* Change the endpoint env varible |
615 | +* Prevent list rcs when bay is not ready |
616 | +* raise exception when create rc with invalid bay status |
617 | +* raise exception when create container with invalid bay status |
618 | +* raise exception when create pod with invalid bay status |
619 | +* Revert "Pass environment variables of proxy to tox" |
620 | +* Add debug testenv in tox |
621 | +* Remove check for bay state on ca-sign and ca-show |
622 | +* Fix bypass\_url and errors with no headers |
623 | +* Remove unnecessary check when create bay |
624 | +* Fix test\_keys\_and\_vals\_to\_strs dict assert |
625 | +* Add unit test for pod-create with invalid bay status |
626 | +* Prevent list pods while bay is not ready |
627 | +* Updated from global requirements |
628 | +* Python 3 deprecated the logger.warn method in favor of warning |
629 | +* Remove references to \_i18n and apiclient.exceptions |
630 | +* Handle list object when print a dict |
631 | +* Put py34 first in the env order of tox |
632 | +* Updated from global requirements |
633 | +* Packages missing from requirements.txt |
634 | +* Add type validation and default for some parameter |
635 | +* Add py3 compatibility for unicode builtin |
636 | +* Add optional parameter --bay when doing container list |
637 | +* Updated from global requirements |
638 | +* Drop py33 support |
639 | +* use wild card for passing env variables |
640 | +* Add registry\_enabled option to baymodel-create |
641 | +* Improve client master\_count validation |
642 | +* Improve client node\_count validation |
643 | +* Fix default bay create timeout |
644 | +* Remove py26 support |
645 | +* Fix POD CLI to work with Object from Bay |
646 | +* Fix RC CLI to work with Object from Bay |
647 | +* Add .idea directory to .gitignore |
648 | +* Fix Service CLI to work with Object from Bay |
649 | +* Handle faultstring when using SessionClient |
650 | +* fix wrong function description |
651 | +* fix exceptions.from\_response() parameter |
652 | +* Fix the ouput of 'container-create' when it fails |
653 | +* Make bandit included in test-requirements.txt |
654 | +* Correct help message of '--name' for baymodel-create |
655 | +* Remove test\_shell\_args.py |
656 | + |
657 | +1.1.0 |
658 | +----- |
659 | + |
660 | +* Revise help message of '--docker-volume-size' for baymodel-create |
661 | +* Updated from global requirements |
662 | +* Improve readme contents |
663 | +* Split v1 shell sub-command into specific files |
664 | +* Updated from global requirements |
665 | +* Fix RC CLI to work with Object from Bay changes |
666 | +* Update baymodel-update help doc |
667 | +* Delete python bytecode before every test run |
668 | +* Add .DS\_Store to .gitignore |
669 | +* Updated from global requirements |
670 | +* Use keystoneauth to create a Session |
671 | +* Make image as required for do\_container\_create |
672 | +* Add test for container\_create |
673 | +* Add unversioned client constructor |
674 | +* Fix rc cli to work with bay identifier |
675 | +* Updated from global requirements |
676 | +* Updated from global requirements |
677 | +* Add the introduce of the command "magnum help ca-show" |
678 | +* Add the introduce of the command "magnum help ca-sign" |
679 | + |
680 | +1.0.0.0b1 |
681 | +--------- |
682 | + |
683 | +* Updated from global requirements |
684 | +* Pass bay\_ident to k8s objects methods |
685 | +* Add an option to specify container memory size |
686 | +* Add support for 'baymodel-update' in python-client |
687 | +* Support for public baymodels |
688 | +* Rename 'insecure' baymodel attribute to 'tls\_disabled' |
689 | +* Client: Pass bay\_uuid to Service Read/Write API |
690 | +* Client: Pass bay\_uuid to Pod Read/Write API |
691 | +* Client: Pass bay\_uuid to RC Read/Write API |
692 | +* Add insecure flag to baymodel |
693 | +* Magnum show cmds display dictionaries with unicode u chars |
694 | +* Adding 'magnum service-list' |
695 | +* Add certificates operations |
696 | +* Change ignore-errors to ignore\_errors |
697 | +* Add support for python >= 3.4 |
698 | +* Updated from global requirements |
699 | +* Adds Labels Support |
700 | +* Adds Container Network Model network\_driver support |
701 | +* Update help message for coe service related command |
702 | +* Add missed space between two words |
703 | +* Updated from global requirements |
704 | +* Rename existing service-\* to coe-service-\* |
705 | +* Updated from global requirements |
706 | +* Remove name from test token |
707 | +* This adds proxy feature in magnum client |
708 | +* Updated from global requirements |
709 | +* Updated from global requirements |
710 | +* Updated from global requirements |
711 | +* Add support for multiple master nodes |
712 | +* Updated from global requirements |
713 | +* Remove uuidutils from openstack.common |
714 | +* Updated from global requirements |
715 | +* Updated from global requirements |
716 | +* Remove H803 rule |
717 | +* Updated from global requirements |
718 | +* Updated from global requirements |
719 | +* Updated from global requirements |
720 | +* Rename image\_id to image when create a container |
721 | +* Updated from global requirements |
722 | +* Add missing dependency oslo.serialization |
723 | +* Updated from global requirements |
724 | +* Add additional arguments to CLI for container-create |
725 | +* Pass environment variables of proxy to tox |
726 | +* Change container-execute to container-exec |
727 | +* Updated from global requirements |
728 | +* Sync from latest oslo-incubator |
729 | +* Updated from global requirements |
730 | +* Fix translation setup |
731 | + |
732 | +0.2.1 |
733 | +----- |
734 | + |
735 | +* Make metavar's consistent |
736 | +* Setup for translation |
737 | +* Updated from global requirements |
738 | +* Bump up to newer hacking |
739 | +* Add support of container resource management with "name" |
740 | +* Add support for container status |
741 | +* Drop use of 'oslo' namespace package |
742 | + |
743 | +0.2.0 |
744 | +----- |
745 | + |
746 | +* Remove links attribute from pod show |
747 | +* Log the correct url in debug mode |
748 | +* Add heat timeout to bay-create for magnum client |
749 | +* Add coe attribute to BayModel creation |
750 | +* Add bay\_uuid to container create |
751 | +* Update README to work with release tools |
752 | +* Add support for pod name in pod-update command |
753 | + |
754 | +0.1.0 |
755 | +----- |
756 | + |
757 | +* Add bay status check when rc create |
758 | +* Add bay status check when service create |
759 | +* fix a typo in log |
760 | +* Add bay status check when pod create |
761 | +* Rename swarm-token to discovery-url |
762 | +* Support pass command field when create a container |
763 | +* Delegate magnum url search to url\_for method |
764 | +* Remove side effect in get\_keystoneclient |
765 | +* Add unittests for magnumclient.v1.client module |
766 | +* Correct mock use in TestCommandLineArgument.setUp |
767 | +* Uncap library requirements for liberty |
768 | +* Support update a replication controller |
769 | +* Support update a service |
770 | +* Add swarm\_token to bay-create call |
771 | +* Support update a pod |
772 | +* Authenticate once |
773 | +* Add error info detail for magnum cli |
774 | +* Update bandit for latest usage |
775 | +* Add tox bandit support for python-magnumclient |
776 | +* Remove unused get\_projects\_list method |
777 | +* Add support for bay name in bay-update command |
778 | +* Allow bay name when replication controller is created |
779 | +* Update .gitreview for project rename |
780 | +* Allow baymodel name when bay is created |
781 | +* Allow bay name when pod is created |
782 | +* Allow bay name when service is created |
783 | +* Support keystone region |
784 | +* Rename k8s specific bay attributes |
785 | +* Add support of baymodel resource management with "name" |
786 | +* Add support of rc resource management with "name" |
787 | +* Add support of service resource management with "name" |
788 | +* Allow specification of ssh\_authorized\_key |
789 | + |
790 | +0.0.1 |
791 | +----- |
792 | + |
793 | +* Add support of pod resource management with "name" |
794 | +* Remove some default values for baymodel create |
795 | +* Add support of bay resource management with "name" |
796 | +* Fix container exec output |
797 | +* Fix the container logs output |
798 | +* Make baymodel-create fail when no argument passed |
799 | +* Display bay status column |
800 | +* tidy up language on one shell help command |
801 | +* Allow adding master flavor id to baymodel |
802 | +* Allow specification of fixed\_network |
803 | +* Allow specification of docker\_volume\_size |
804 | +* Support multiple args in some magnum commands |
805 | +* Remove '--id' option from magnum commands |
806 | +* Make bay-create fail when no argument passed |
807 | +* Adding test for magnumclient argument parsing |
808 | +* Add support for updating a bay |
809 | +* Adding tests for v1/shell.py |
810 | +* Adding test for shell.py |
811 | +* Container logs should use HTTP GET |
812 | +* Add help info for container operations |
813 | +* Update help message for baymodel operations |
814 | +* Add help for magnum object show |
815 | +* Remove 'desc' from container output |
816 | +* Rename \`resource\`\_data/url attributes to manifest/manifest\_url |
817 | +* Default version should be v1 in magnum |
818 | +* Fix an error on not finding log handler |
819 | +* Add id as required for bay-show/delete |
820 | +* Revert "Fix an error on not finding log handler" |
821 | +* Change rc\_data to replicationcontroller\_data |
822 | +* Fix an error on not finding log handler |
823 | +* Make replication controller client works |
824 | +* Remove 'desc' from docker creation attribute |
825 | +* Update test\_update to test\_pod\_update for pod client test |
826 | +* Add client test for k8s replication controller |
827 | +* Add client test for k8s service |
828 | +* Add client test for magnum containers |
829 | +* Add client test for magnum baymodel |
830 | +* Add client test for magnum bay |
831 | +* Add client test for magnum node |
832 | +* Support file path as a service manifest data |
833 | +* Adjusted CLI argument names to use dashes rather than underscores |
834 | +* Add client test for test\_pods |
835 | +* Support file path as a pod data |
836 | +* Add unit test for magnumclient/common/httpclient.py |
837 | +* Add unit test for magnumclient/common/utils.py |
838 | +* Update K8S Pod and Service input parameter |
839 | +* Make id as required when delete or show object info |
840 | +* Construct URI properly for container-execute |
841 | +* Add k8s replication support for magnum client |
842 | +* Ensure a id string is passed when --id is used |
843 | +* Change folder of api to v1 for magumclient |
844 | +* Get container-list CLI working |
845 | +* Do not advertise py33 compatibility |
846 | +* Set HTTP PUT Content-Length for container actions |
847 | +* Implement container actions |
848 | +* Add image\_id attribute for container |
849 | +* Service create only need service filename |
850 | +* pod create only need pod filename |
851 | +* Implement client for service operations |
852 | +* Update parmater name for \_show\_pod |
853 | +* Add baymodel\_id to bay\_create |
854 | +* Add flavor\_id property to baymodel object |
855 | +* Implement pod client CLI |
856 | +* Make bay-create operate again as a result of baymodel |
857 | +* Make bay create work with new bay model structure |
858 | +* Type and image\_id are removed from server |
859 | +* Don't show links when showing bay |
860 | +* Make baymodel-list only show name and UUID |
861 | +* Make baymodel not show links |
862 | +* Implement baymodel in client |
863 | +* Add node object to the python client |
864 | +* Add image\_id and node\_count to bay-create |
865 | +* Workflow documentation is now in infra-manual |
866 | +* Make separate Bay objects for each bay object |
867 | +* Complete implementation of bay operations |
868 | +* Docstring cleanups |
869 | +* Delete bay rather then container when requested |
870 | +* Misc cleanups |
871 | +* Make container in sync with bays and pods |
872 | +* Make pod objects work in ReST Client API |
873 | +* Make bay objects work in ReST Client API |
874 | +* Modify container list attributes |
875 | +* Implements basic container operations |
876 | +* Add client resources and managers |
877 | +* Update apiclient from oslo-incubator |
878 | +* Add apiclient library from oslo-incubator |
879 | +* Added default service type |
880 | +* Skeleton for the cli client |
881 | +* Include the auth module from oslo |
882 | +* Sync common code from oslo-incubator |
883 | +* Added project required files |
884 | +* Add service API methods to what should be implemented |
885 | +* Boilerplate client for communicating with ReST API |
886 | +* Initial commit |
887 | diff --git a/PKG-INFO b/PKG-INFO |
888 | new file mode 100644 |
889 | index 0000000..8045ab2 |
890 | --- /dev/null |
891 | +++ b/PKG-INFO |
892 | @@ -0,0 +1,61 @@ |
893 | +Metadata-Version: 1.1 |
894 | +Name: python-magnumclient |
895 | +Version: 3.0.1 |
896 | +Summary: Client library for Magnum API |
897 | +Home-page: https://docs.openstack.org/python-magnumclient/latest/ |
898 | +Author: OpenStack |
899 | +Author-email: openstack-discuss@lists.openstack.org |
900 | +License: UNKNOWN |
901 | +Description: ======================== |
902 | + Team and repository tags |
903 | + ======================== |
904 | + |
905 | + .. image:: https://governance.openstack.org/tc/badges/python-magnumclient.svg |
906 | + :target: https://governance.openstack.org/tc/reference/tags/index.html |
907 | + |
908 | + .. Change things from this point on |
909 | + |
910 | + Python bindings to the Magnum API |
911 | + ================================= |
912 | + |
913 | + .. image:: https://img.shields.io/pypi/v/python-magnumclient.svg |
914 | + :target: https://pypi.org/project/python-magnumclient/ |
915 | + :alt: Latest Version |
916 | + |
917 | + .. image:: https://img.shields.io/pypi/dm/python-magnumclient.svg |
918 | + :target: https://pypi.org/project/python-magnumclient/ |
919 | + :alt: Downloads |
920 | + |
921 | + This is a client library for Magnum built on the Magnum API. It |
922 | + provides a Python API (the ``magnumclient`` module) and a command-line |
923 | + tool (``magnum``). |
924 | + |
925 | + Development takes place via the usual OpenStack processes as outlined |
926 | + in the `developer guide |
927 | + <https://docs.openstack.org/infra/manual/developers.html>`_. |
928 | + |
929 | + * License: Apache License, Version 2.0 |
930 | + * `PyPi`_ - package installation |
931 | + * `Online Documentation`_ |
932 | + * `Launchpad project`_ - release management |
933 | + * `Bugs`_ - issue tracking |
934 | + * `Source`_ |
935 | + |
936 | + .. _PyPi: https://pypi.org/project/python-magnumclient |
937 | + .. _Online Documentation: https://docs.openstack.org/python-magnumclient/latest/ |
938 | + .. _Launchpad project: https://launchpad.net/python-magnumclient |
939 | + .. _Bugs: https://bugs.launchpad.net/python-magnumclient |
940 | + .. _Source: https://opendev.org/openstack/python-magnumclient |
941 | + |
942 | + |
943 | +Platform: UNKNOWN |
944 | +Classifier: Environment :: OpenStack |
945 | +Classifier: Intended Audience :: Information Technology |
946 | +Classifier: Intended Audience :: System Administrators |
947 | +Classifier: License :: OSI Approved :: Apache Software License |
948 | +Classifier: Operating System :: POSIX :: Linux |
949 | +Classifier: Programming Language :: Python |
950 | +Classifier: Programming Language :: Python :: 2 |
951 | +Classifier: Programming Language :: Python :: 3 |
952 | +Classifier: Programming Language :: Python :: 3.6 |
953 | +Classifier: Programming Language :: Python :: 3.7 |
954 | diff --git a/README.rst b/README.rst |
955 | index 2b7cf2b..c39cfb8 100644 |
956 | --- a/README.rst |
957 | +++ b/README.rst |
958 | @@ -2,8 +2,8 @@ |
959 | Team and repository tags |
960 | ======================== |
961 | |
962 | -.. image:: http://governance.openstack.org/badges/python-magnumclient.svg |
963 | - :target: http://governance.openstack.org/reference/tags/index.html |
964 | +.. image:: https://governance.openstack.org/tc/badges/python-magnumclient.svg |
965 | + :target: https://governance.openstack.org/tc/reference/tags/index.html |
966 | |
967 | .. Change things from this point on |
968 | |
969 | @@ -11,11 +11,11 @@ Python bindings to the Magnum API |
970 | ================================= |
971 | |
972 | .. image:: https://img.shields.io/pypi/v/python-magnumclient.svg |
973 | - :target: https://pypi.python.org/pypi/python-magnumclient/ |
974 | + :target: https://pypi.org/project/python-magnumclient/ |
975 | :alt: Latest Version |
976 | |
977 | .. image:: https://img.shields.io/pypi/dm/python-magnumclient.svg |
978 | - :target: https://pypi.python.org/pypi/python-magnumclient/ |
979 | + :target: https://pypi.org/project/python-magnumclient/ |
980 | :alt: Downloads |
981 | |
982 | This is a client library for Magnum built on the Magnum API. It |
983 | @@ -33,8 +33,8 @@ in the `developer guide |
984 | * `Bugs`_ - issue tracking |
985 | * `Source`_ |
986 | |
987 | -.. _PyPi: https://pypi.python.org/pypi/python-magnumclient |
988 | +.. _PyPi: https://pypi.org/project/python-magnumclient |
989 | .. _Online Documentation: https://docs.openstack.org/python-magnumclient/latest/ |
990 | .. _Launchpad project: https://launchpad.net/python-magnumclient |
991 | .. _Bugs: https://bugs.launchpad.net/python-magnumclient |
992 | -.. _Source: https://git.openstack.org/cgit/openstack/python-magnumclient |
993 | +.. _Source: https://opendev.org/openstack/python-magnumclient |
994 | diff --git a/debian/changelog b/debian/changelog |
995 | index 67e2c7c..7860985 100644 |
996 | --- a/debian/changelog |
997 | +++ b/debian/changelog |
998 | @@ -1,3 +1,14 @@ |
999 | +python-magnumclient (3.0.1-0ubuntu1) UNRELEASED; urgency=medium |
1000 | + |
1001 | + * d/watch: Scope to 3.x series. |
1002 | + * New stable point release for OpenStack Ussuri (LP: #1996229). |
1003 | + * d/p/fix-py37-compatibility.patch: Dropped. Fixed in new stable point |
1004 | + release. |
1005 | + * d/p/Fix-failing-to-parse-json-error-msg.patch: Dropped. Fixed in new |
1006 | + stable point release. |
1007 | + |
1008 | + -- Felipe Reyes <felipe.reyes@canonical.com> Fri, 12 May 2023 12:18:49 -0400 |
1009 | + |
1010 | python-magnumclient (2.11.0-0ubuntu6) focal; urgency=medium |
1011 | |
1012 | * d/p/Fix-failing-to-parse-json-error-msg.patch: Fix failing to parse json |
1013 | diff --git a/debian/patches/Fix-failing-to-parse-json-error-msg.patch b/debian/patches/Fix-failing-to-parse-json-error-msg.patch |
1014 | deleted file mode 100644 |
1015 | index 3bb25d8..0000000 |
1016 | --- a/debian/patches/Fix-failing-to-parse-json-error-msg.patch |
1017 | +++ /dev/null |
1018 | @@ -1,38 +0,0 @@ |
1019 | -From f7551a6bac103070ff456098fe2631409620d492 Mon Sep 17 00:00:00 2001 |
1020 | -From: Tobias Urdin <tobias.urdin@binero.se> |
1021 | -Date: Wed, 18 Nov 2020 11:46:44 +0100 |
1022 | -Subject: [PATCH] Fix failing to parse json error msg |
1023 | - |
1024 | -It assumes its a requests response but could |
1025 | -be a HTTPResponse from urllib. |
1026 | - |
1027 | -Story: 2008789 |
1028 | -Task: 42183 |
1029 | - |
1030 | -Change-Id: I7306d167a17284c7f478ec1c1599a8d4b32040c2 |
1031 | ---- |
1032 | - magnumclient/common/httpclient.py | 3 +++ |
1033 | - 1 file changed, 3 insertions(+) |
1034 | - |
1035 | -Index: python-magnumclient-2.11.0/magnumclient/common/httpclient.py |
1036 | -=================================================================== |
1037 | ---- python-magnumclient-2.11.0.orig/magnumclient/common/httpclient.py |
1038 | -+++ python-magnumclient-2.11.0/magnumclient/common/httpclient.py |
1039 | -@@ -23,6 +23,7 @@ import socket |
1040 | - import ssl |
1041 | - |
1042 | - from keystoneauth1 import adapter |
1043 | -+from oslo_serialization import jsonutils |
1044 | - from oslo_utils import importutils |
1045 | - import six |
1046 | - import six.moves.urllib.parse as urlparse |
1047 | -@@ -65,6 +66,9 @@ def _extract_error_json(body, resp): |
1048 | - try: |
1049 | - body_json = resp.json() |
1050 | - return _extract_error_json_text(body_json) |
1051 | -+ except AttributeError: |
1052 | -+ body_json = jsonutils.loads(body) |
1053 | -+ return _extract_error_json_text(body_json) |
1054 | - except ValueError: |
1055 | - return {} |
1056 | - else: |
1057 | diff --git a/debian/patches/fix-py37-compatibility.patch b/debian/patches/fix-py37-compatibility.patch |
1058 | deleted file mode 100644 |
1059 | index 29e3459..0000000 |
1060 | --- a/debian/patches/fix-py37-compatibility.patch |
1061 | +++ /dev/null |
1062 | @@ -1,47 +0,0 @@ |
1063 | -From 5deb538930d98bf83e11bfb1dacb509982226540 Mon Sep 17 00:00:00 2001 |
1064 | -From: Michal Arbet <michal.arbet@ultimum.io> |
1065 | -Date: Wed, 6 Feb 2019 14:11:07 +0100 |
1066 | -Subject: [PATCH] Fix py37 compatibility |
1067 | - |
1068 | -Unit tests are failing under python3.7. |
1069 | -Generators which explicitly raise StopIteration can generally be |
1070 | -changed to simply return instead. This will be compatible with |
1071 | -all existing Python versions. |
1072 | - |
1073 | -PEP Documentation for this change: |
1074 | -https://www.python.org/dev/peps/pep-0479/ |
1075 | - |
1076 | -Change-Id: I4ae2049d8a2469d0a37077bdc722481e68d7cc49 |
1077 | -Closes-Bug: #1814890 |
1078 | ---- |
1079 | - magnumclient/common/httpclient.py | 7 +++++-- |
1080 | - 1 file changed, 5 insertions(+), 2 deletions(-) |
1081 | - |
1082 | -diff --git a/magnumclient/common/httpclient.py b/magnumclient/common/httpclient.py |
1083 | -index ce9e4c9..038fb21 100644 |
1084 | ---- a/magnumclient/common/httpclient.py |
1085 | -+++ b/magnumclient/common/httpclient.py |
1086 | -@@ -406,7 +406,10 @@ class ResponseBodyIterator(object): |
1087 | - |
1088 | - def __iter__(self): |
1089 | - while True: |
1090 | -- yield self.next() |
1091 | -+ try: |
1092 | -+ yield self.next() |
1093 | -+ except StopIteration: |
1094 | -+ return |
1095 | - |
1096 | - def __bool__(self): |
1097 | - return hasattr(self, 'items') |
1098 | -@@ -418,7 +421,7 @@ class ResponseBodyIterator(object): |
1099 | - if chunk: |
1100 | - return chunk |
1101 | - else: |
1102 | -- raise StopIteration() |
1103 | -+ raise StopIteration |
1104 | - |
1105 | - |
1106 | - def _construct_http_client(*args, **kwargs): |
1107 | --- |
1108 | -2.31.1 |
1109 | - |
1110 | diff --git a/debian/patches/series b/debian/patches/series |
1111 | index 5b19bc2..e69de29 100644 |
1112 | --- a/debian/patches/series |
1113 | +++ b/debian/patches/series |
1114 | @@ -1,2 +0,0 @@ |
1115 | -fix-py37-compatibility.patch |
1116 | -Fix-failing-to-parse-json-error-msg.patch |
1117 | diff --git a/debian/watch b/debian/watch |
1118 | index e38e2ce..b2923cb 100644 |
1119 | --- a/debian/watch |
1120 | +++ b/debian/watch |
1121 | @@ -1,3 +1,3 @@ |
1122 | version=3 |
1123 | -opts="uversionmangle=s/\.(b|rc)/~$1/" \ |
1124 | -https://github.com/openstack/python-magnumclient/tags .*/(\d[\d\.]+)\.tar\.gz |
1125 | +opts="uversionmangle=s/\.([a-zA-Z])/~$1/;s/%7E/~/;s/\.0b/~b/;s/\.0rc/~rc/" \ |
1126 | +https://tarballs.opendev.org/openstack/python-magnumclient/ python-magnumclient-(3\.\d.*)\.tar\.gz |
1127 | diff --git a/doc/requirements.txt b/doc/requirements.txt |
1128 | index 0dff061..711fb97 100644 |
1129 | --- a/doc/requirements.txt |
1130 | +++ b/doc/requirements.txt |
1131 | @@ -1,3 +1,4 @@ |
1132 | -sphinx!=1.6.6,>=1.6.2 # BSD |
1133 | +sphinx!=1.6.6,!=1.6.7,>=1.6.2,<2.0.0;python_version=='2.7' # BSD |
1134 | +sphinx!=1.6.6,!=1.6.7,>=1.6.2;python_version>='3.4' # BSD |
1135 | openstackdocstheme>=1.18.1 # Apache-2.0 |
1136 | reno>=2.5.0 # Apache-2.0 |
1137 | diff --git a/magnumclient/common/cliutils.py b/magnumclient/common/cliutils.py |
1138 | index 34ab129..7061f3b 100644 |
1139 | --- a/magnumclient/common/cliutils.py |
1140 | +++ b/magnumclient/common/cliutils.py |
1141 | @@ -404,8 +404,8 @@ def get_service_type(f): |
1142 | return getattr(f, 'service_type', None) |
1143 | |
1144 | |
1145 | -def pretty_choice_list(l): |
1146 | - return ', '.join("'%s'" % i for i in l) |
1147 | +def pretty_choice_list(lst): |
1148 | + return ', '.join("'%s'" % i for i in lst) |
1149 | |
1150 | |
1151 | def exit(msg=''): |
1152 | diff --git a/magnumclient/common/httpclient.py b/magnumclient/common/httpclient.py |
1153 | index 8e5d90f..038fb21 100644 |
1154 | --- a/magnumclient/common/httpclient.py |
1155 | +++ b/magnumclient/common/httpclient.py |
1156 | @@ -16,13 +16,13 @@ |
1157 | # under the License. |
1158 | |
1159 | import copy |
1160 | -import json |
1161 | import logging |
1162 | import os |
1163 | import socket |
1164 | import ssl |
1165 | |
1166 | from keystoneauth1 import adapter |
1167 | +from oslo_serialization import jsonutils |
1168 | from oslo_utils import importutils |
1169 | import six |
1170 | import six.moves.urllib.parse as urlparse |
1171 | @@ -43,7 +43,7 @@ def _extract_error_json_text(body_json): |
1172 | error_json = {} |
1173 | if 'error_message' in body_json: |
1174 | raw_msg = body_json['error_message'] |
1175 | - error_json = json.loads(raw_msg) |
1176 | + error_json = jsonutils.loads(raw_msg) |
1177 | elif 'error' in body_json: |
1178 | error_body = body_json['error'] |
1179 | error_json = {'faultstring': error_body['title'], |
1180 | @@ -69,7 +69,7 @@ def _extract_error_json(body, resp): |
1181 | return {} |
1182 | else: |
1183 | try: |
1184 | - body_json = json.loads(body) |
1185 | + body_json = jsonutils.loads(body) |
1186 | return _extract_error_json_text(body_json) |
1187 | except ValueError: |
1188 | return {} |
1189 | @@ -228,7 +228,7 @@ class HTTPClient(object): |
1190 | kwargs['headers'].setdefault('Accept', 'application/json') |
1191 | |
1192 | if 'body' in kwargs: |
1193 | - kwargs['body'] = json.dumps(kwargs['body']) |
1194 | + kwargs['body'] = jsonutils.dumps(kwargs['body']) |
1195 | |
1196 | resp, body_iter = self._http_request(url, method, **kwargs) |
1197 | content_type = resp.getheader('content-type', None) |
1198 | @@ -239,7 +239,7 @@ class HTTPClient(object): |
1199 | if 'application/json' in content_type: |
1200 | body = ''.join([chunk for chunk in body_iter]) |
1201 | try: |
1202 | - body = json.loads(body) |
1203 | + body = jsonutils.loads(body) |
1204 | except ValueError: |
1205 | LOG.error('Could not decode response body as JSON') |
1206 | else: |
1207 | @@ -373,7 +373,7 @@ class SessionClient(adapter.LegacyJsonAdapter): |
1208 | kwargs['headers'].setdefault('Content-Type', 'application/json') |
1209 | kwargs['headers'].setdefault('Accept', 'application/json') |
1210 | if 'body' in kwargs: |
1211 | - kwargs['data'] = json.dumps(kwargs.pop('body')) |
1212 | + kwargs['data'] = jsonutils.dumps(kwargs.pop('body')) |
1213 | |
1214 | resp = self._http_request(url, method, **kwargs) |
1215 | body = resp.content |
1216 | @@ -406,7 +406,10 @@ class ResponseBodyIterator(object): |
1217 | |
1218 | def __iter__(self): |
1219 | while True: |
1220 | - yield self.next() |
1221 | + try: |
1222 | + yield self.next() |
1223 | + except StopIteration: |
1224 | + return |
1225 | |
1226 | def __bool__(self): |
1227 | return hasattr(self, 'items') |
1228 | @@ -418,7 +421,7 @@ class ResponseBodyIterator(object): |
1229 | if chunk: |
1230 | return chunk |
1231 | else: |
1232 | - raise StopIteration() |
1233 | + raise StopIteration |
1234 | |
1235 | |
1236 | def _construct_http_client(*args, **kwargs): |
1237 | diff --git a/magnumclient/common/utils.py b/magnumclient/common/utils.py |
1238 | index 99676da..4a8cfb1 100644 |
1239 | --- a/magnumclient/common/utils.py |
1240 | +++ b/magnumclient/common/utils.py |
1241 | @@ -15,8 +15,6 @@ |
1242 | # License for the specific language governing permissions and limitations |
1243 | # under the License. |
1244 | |
1245 | -import base64 |
1246 | -import json |
1247 | import os |
1248 | |
1249 | from cryptography.hazmat.backends import default_backend |
1250 | @@ -25,6 +23,8 @@ from cryptography.hazmat.primitives import hashes |
1251 | from cryptography.hazmat.primitives import serialization |
1252 | from cryptography import x509 |
1253 | from cryptography.x509.oid import NameOID |
1254 | +from oslo_serialization import base64 |
1255 | +from oslo_serialization import jsonutils |
1256 | |
1257 | from magnumclient import exceptions as exc |
1258 | from magnumclient.i18n import _ |
1259 | @@ -64,7 +64,7 @@ def split_and_deserialize(string): |
1260 | raise exc.CommandError(_('Attributes must be a list of ' |
1261 | 'PATH=VALUE not "%s"') % string) |
1262 | try: |
1263 | - value = json.loads(value) |
1264 | + value = jsonutils.loads(value) |
1265 | except ValueError: |
1266 | pass |
1267 | |
1268 | @@ -100,7 +100,7 @@ def handle_labels(labels): |
1269 | if 'mesos_slave_executor_env_file' in labels: |
1270 | environment_variables_data = handle_json_from_file( |
1271 | labels['mesos_slave_executor_env_file']) |
1272 | - labels['mesos_slave_executor_env_variables'] = json.dumps( |
1273 | + labels['mesos_slave_executor_env_variables'] = jsonutils.dumps( |
1274 | environment_variables_data) |
1275 | return labels |
1276 | |
1277 | @@ -118,12 +118,12 @@ def format_labels(lbls, parse_comma=True): |
1278 | lbls = lbls[0].replace(';', ',').split(',') |
1279 | |
1280 | labels = {} |
1281 | - for l in lbls: |
1282 | + for lbl in lbls: |
1283 | try: |
1284 | - (k, v) = l.split(('='), 1) |
1285 | + (k, v) = lbl.split(('='), 1) |
1286 | except ValueError: |
1287 | raise exc.CommandError(_('labels must be a list of KEY=VALUE ' |
1288 | - 'not %s') % l) |
1289 | + 'not %s') % lbl) |
1290 | if k not in labels: |
1291 | labels[k] = v |
1292 | else: |
1293 | @@ -146,7 +146,7 @@ def handle_json_from_file(json_arg): |
1294 | try: |
1295 | with open(json_arg, 'r') as f: |
1296 | json_arg = f.read().strip() |
1297 | - json_arg = json.loads(json_arg) |
1298 | + json_arg = jsonutils.loads(json_arg) |
1299 | except IOError as e: |
1300 | err = _("Cannot get JSON from file '%(file)s'. " |
1301 | "Error: %(err)s") % {'err': e, 'file': json_arg} |
1302 | @@ -160,11 +160,11 @@ def handle_json_from_file(json_arg): |
1303 | |
1304 | |
1305 | def config_cluster(cluster, cluster_template, cfg_dir, force=False, |
1306 | - certs=None): |
1307 | + certs=None, use_keystone=False): |
1308 | """Return and write configuration for the given cluster.""" |
1309 | if cluster_template.coe == 'kubernetes': |
1310 | return _config_cluster_kubernetes(cluster, cluster_template, cfg_dir, |
1311 | - force, certs) |
1312 | + force, certs, use_keystone) |
1313 | elif (cluster_template.coe == 'swarm' |
1314 | or cluster_template.coe == 'swarm-mode'): |
1315 | return _config_cluster_swarm(cluster, cluster_template, cfg_dir, |
1316 | @@ -172,7 +172,7 @@ def config_cluster(cluster, cluster_template, cfg_dir, force=False, |
1317 | |
1318 | |
1319 | def _config_cluster_kubernetes(cluster, cluster_template, cfg_dir, |
1320 | - force=False, certs=None): |
1321 | + force=False, certs=None, use_keystone=False): |
1322 | """Return and write configuration for the given kubernetes cluster.""" |
1323 | cfg_file = "%s/config" % cfg_dir |
1324 | if cluster_template.tls_disabled or certs is None: |
1325 | @@ -193,30 +193,64 @@ def _config_cluster_kubernetes(cluster, cluster_template, cfg_dir, |
1326 | "- name: %(name)s'\n" |
1327 | % {'name': cluster.name, 'api_address': cluster.api_address}) |
1328 | else: |
1329 | - cfg = ("apiVersion: v1\n" |
1330 | - "clusters:\n" |
1331 | - "- cluster:\n" |
1332 | - " certificate-authority-data: %(ca)s\n" |
1333 | - " server: %(api_address)s\n" |
1334 | - " name: %(name)s\n" |
1335 | - "contexts:\n" |
1336 | - "- context:\n" |
1337 | - " cluster: %(name)s\n" |
1338 | - " user: admin\n" |
1339 | - " name: default\n" |
1340 | - "current-context: default\n" |
1341 | - "kind: Config\n" |
1342 | - "preferences: {}\n" |
1343 | - "users:\n" |
1344 | - "- name: admin\n" |
1345 | - " user:\n" |
1346 | - " client-certificate-data: %(cert)s\n" |
1347 | - " client-key-data: %(key)s\n" |
1348 | - % {'name': cluster.name, |
1349 | - 'api_address': cluster.api_address, |
1350 | - 'key': base64.b64encode(certs['key']), |
1351 | - 'cert': base64.b64encode(certs['cert']), |
1352 | - 'ca': base64.b64encode(certs['ca'])}) |
1353 | + if not use_keystone: |
1354 | + cfg = ("apiVersion: v1\n" |
1355 | + "clusters:\n" |
1356 | + "- cluster:\n" |
1357 | + " certificate-authority-data: %(ca)s\n" |
1358 | + " server: %(api_address)s\n" |
1359 | + " name: %(name)s\n" |
1360 | + "contexts:\n" |
1361 | + "- context:\n" |
1362 | + " cluster: %(name)s\n" |
1363 | + " user: admin\n" |
1364 | + " name: default\n" |
1365 | + "current-context: default\n" |
1366 | + "kind: Config\n" |
1367 | + "preferences: {}\n" |
1368 | + "users:\n" |
1369 | + "- name: admin\n" |
1370 | + " user:\n" |
1371 | + " client-certificate-data: %(cert)s\n" |
1372 | + " client-key-data: %(key)s\n" |
1373 | + % {'name': cluster.name, |
1374 | + 'api_address': cluster.api_address, |
1375 | + 'key': base64.encode_as_text(certs['key']), |
1376 | + 'cert': base64.encode_as_text(certs['cert']), |
1377 | + 'ca': base64.encode_as_text(certs['ca'])}) |
1378 | + else: |
1379 | + cfg = ("apiVersion: v1\n" |
1380 | + "clusters:\n" |
1381 | + "- cluster:\n" |
1382 | + " certificate-authority-data: %(ca)s\n" |
1383 | + " server: %(api_address)s\n" |
1384 | + " name: %(name)s\n" |
1385 | + "contexts:\n" |
1386 | + "- context:\n" |
1387 | + " cluster: %(name)s\n" |
1388 | + " user: openstackuser\n" |
1389 | + " name: openstackuser@kubernetes\n" |
1390 | + "current-context: openstackuser@kubernetes\n" |
1391 | + "kind: Config\n" |
1392 | + "preferences: {}\n" |
1393 | + "users:\n" |
1394 | + "- name: openstackuser\n" |
1395 | + " user:\n" |
1396 | + " exec:\n" |
1397 | + " command: /bin/bash\n" |
1398 | + " apiVersion: client.authentication.k8s.io/v1alpha1\n" |
1399 | + " args:\n" |
1400 | + " - -c\n" |
1401 | + " - >\n" |
1402 | + " if [ -z ${OS_TOKEN} ]; then\n" |
1403 | + " echo 'Error: Missing OpenStack credential from environment variable $OS_TOKEN' > /dev/stderr\n" # noqa |
1404 | + " exit 1\n" |
1405 | + " else\n" |
1406 | + " echo '{ \"apiVersion\": \"client.authentication.k8s.io/v1alpha1\", \"kind\": \"ExecCredential\", \"status\": { \"token\": \"'\"${OS_TOKEN}\"'\"}}'\n" # noqa |
1407 | + " fi\n" |
1408 | + % {'name': cluster.name, |
1409 | + 'api_address': cluster.api_address, |
1410 | + 'ca': base64.encode_as_text(certs['ca'])}) |
1411 | |
1412 | if os.path.exists(cfg_file) and not force: |
1413 | raise exc.CommandError("File %s exists, aborting." % cfg_file) |
1414 | diff --git a/magnumclient/exceptions.py b/magnumclient/exceptions.py |
1415 | index d069f85..8afd80a 100644 |
1416 | --- a/magnumclient/exceptions.py |
1417 | +++ b/magnumclient/exceptions.py |
1418 | @@ -18,15 +18,15 @@ from magnumclient.common.apiclient.exceptions import * # noqa |
1419 | |
1420 | # NOTE(akurilin): This alias is left here since v.0.1.3 to support backwards |
1421 | # compatibility. |
1422 | -InvalidEndpoint = EndpointException |
1423 | -CommunicationError = ConnectionRefused |
1424 | -HTTPBadRequest = BadRequest |
1425 | -HTTPInternalServerError = InternalServerError |
1426 | -HTTPNotFound = NotFound |
1427 | -HTTPServiceUnavailable = ServiceUnavailable |
1428 | +InvalidEndpoint = exceptions.EndpointException |
1429 | +CommunicationError = exceptions.ConnectionRefused |
1430 | +HTTPBadRequest = exceptions.BadRequest |
1431 | +HTTPInternalServerError = exceptions.InternalServerError |
1432 | +HTTPNotFound = exceptions.NotFound |
1433 | +HTTPServiceUnavailable = exceptions.ServiceUnavailable |
1434 | |
1435 | |
1436 | -class AmbiguousAuthSystem(ClientException): |
1437 | +class AmbiguousAuthSystem(exceptions.ClientException): |
1438 | """Could not obtain token and endpoint using provided credentials.""" |
1439 | pass |
1440 | |
1441 | @@ -35,7 +35,7 @@ class AmbiguousAuthSystem(ClientException): |
1442 | AmbigiousAuthSystem = AmbiguousAuthSystem |
1443 | |
1444 | |
1445 | -class InvalidAttribute(ClientException): |
1446 | +class InvalidAttribute(exceptions.ClientException): |
1447 | pass |
1448 | |
1449 | |
1450 | diff --git a/magnumclient/osc/plugin.py b/magnumclient/osc/plugin.py |
1451 | index dde56fd..49309c2 100644 |
1452 | --- a/magnumclient/osc/plugin.py |
1453 | +++ b/magnumclient/osc/plugin.py |
1454 | @@ -17,7 +17,8 @@ from osc_lib import utils |
1455 | |
1456 | LOG = logging.getLogger(__name__) |
1457 | |
1458 | -DEFAULT_API_VERSION = '1' |
1459 | +DEFAULT_MAJOR_API_VERSION = '1' |
1460 | +DEFAULT_MAGNUM_API_VERSION = 'latest' |
1461 | API_VERSION_OPTION = 'os_container_infra_api_version' |
1462 | API_NAME = 'container_infra' |
1463 | API_VERSIONS = { |
1464 | @@ -37,7 +38,8 @@ def make_client(instance): |
1465 | region_name=instance._region_name, |
1466 | interface=instance._interface, |
1467 | insecure=instance._insecure, |
1468 | - ca_cert=instance._cacert) |
1469 | + ca_cert=instance._cacert, |
1470 | + api_version=DEFAULT_MAGNUM_API_VERSION) |
1471 | return client |
1472 | |
1473 | |
1474 | @@ -49,8 +51,8 @@ def build_option_parser(parser): |
1475 | metavar='<container-infra-api-version>', |
1476 | default=utils.env( |
1477 | 'OS_CONTAINER_INFRA_API_VERSION', |
1478 | - default=DEFAULT_API_VERSION), |
1479 | + default=DEFAULT_MAJOR_API_VERSION), |
1480 | help='Container-Infra API version, default=' + |
1481 | - DEFAULT_API_VERSION + |
1482 | + DEFAULT_MAJOR_API_VERSION + |
1483 | ' (Env: OS_CONTAINER_INFRA_API_VERSION)') |
1484 | return parser |
1485 | diff --git a/magnumclient/osc/v1/cluster_templates.py b/magnumclient/osc/v1/cluster_templates.py |
1486 | index d898af9..852ee33 100644 |
1487 | --- a/magnumclient/osc/v1/cluster_templates.py |
1488 | +++ b/magnumclient/osc/v1/cluster_templates.py |
1489 | @@ -51,7 +51,8 @@ CLUSTER_TEMPLATE_ATTRIBUTES = [ |
1490 | 'coe', |
1491 | 'flavor_id', |
1492 | 'master_lb_enabled', |
1493 | - 'dns_nameserver' |
1494 | + 'dns_nameserver', |
1495 | + 'hidden' |
1496 | ] |
1497 | |
1498 | |
1499 | @@ -221,6 +222,17 @@ class CreateClusterTemplate(command.ShowOne): |
1500 | action='append_const', |
1501 | const=False, |
1502 | help=_('Disables floating ip creation on the new Cluster')) |
1503 | + parser.add_argument( |
1504 | + '--hidden', |
1505 | + dest='hidden', |
1506 | + action='store_true', |
1507 | + default=False, |
1508 | + help=_('Indicates the cluster template should be hidden.')) |
1509 | + parser.add_argument( |
1510 | + '--visible', |
1511 | + dest='hidden', |
1512 | + action='store_false', |
1513 | + help=_('Indicates the cluster template should be visible.')) |
1514 | |
1515 | return parser |
1516 | |
1517 | @@ -252,6 +264,12 @@ class CreateClusterTemplate(command.ShowOne): |
1518 | 'server_type': parsed_args.server_type, |
1519 | 'master_lb_enabled': parsed_args.master_lb_enabled, |
1520 | } |
1521 | + |
1522 | + # NOTE (brtknr): Only supply hidden arg if it is True |
1523 | + # for backward compatibility |
1524 | + if parsed_args.hidden: |
1525 | + args['hidden'] = parsed_args.hidden |
1526 | + |
1527 | if len(parsed_args.floating_ip_enabled) > 1: |
1528 | raise InvalidAttribute('--floating-ip-enabled and ' |
1529 | '--floating-ip-disabled are ' |
1530 | @@ -336,6 +354,8 @@ class ListTemplateCluster(command.Lister): |
1531 | |
1532 | mag_client = self.app.client_manager.container_infra |
1533 | columns = ['uuid', 'name'] |
1534 | + if parsed_args.fields: |
1535 | + columns += parsed_args.fields.split(',') |
1536 | cts = mag_client.cluster_templates.list(limit=parsed_args.limit, |
1537 | sort_key=parsed_args.sort_key, |
1538 | sort_dir=parsed_args.sort_dir) |
1539 | diff --git a/magnumclient/osc/v1/clusters.py b/magnumclient/osc/v1/clusters.py |
1540 | index ac1419a..3ab06e9 100644 |
1541 | --- a/magnumclient/osc/v1/clusters.py |
1542 | +++ b/magnumclient/osc/v1/clusters.py |
1543 | @@ -24,6 +24,7 @@ from osc_lib import utils |
1544 | |
1545 | CLUSTER_ATTRIBUTES = [ |
1546 | 'status', |
1547 | + 'health_status', |
1548 | 'cluster_template_id', |
1549 | 'node_addresses', |
1550 | 'uuid', |
1551 | @@ -33,6 +34,9 @@ CLUSTER_ATTRIBUTES = [ |
1552 | 'updated_at', |
1553 | 'coe_version', |
1554 | 'labels', |
1555 | + 'labels_overridden', |
1556 | + 'labels_skipped', |
1557 | + 'labels_added', |
1558 | 'faults', |
1559 | 'keypair', |
1560 | 'api_address', |
1561 | @@ -45,6 +49,8 @@ CLUSTER_ATTRIBUTES = [ |
1562 | 'name', |
1563 | 'master_flavor_id', |
1564 | 'flavor_id', |
1565 | + 'health_status_reason', |
1566 | + 'project_id', |
1567 | ] |
1568 | |
1569 | |
1570 | @@ -113,6 +119,38 @@ class CreateCluster(command.Command): |
1571 | metavar='<flavor>', |
1572 | help=_('The nova flavor name or UUID to use when launching the ' |
1573 | 'Cluster.')) |
1574 | + parser.add_argument( |
1575 | + '--fixed-network', |
1576 | + dest='fixed_network', |
1577 | + metavar='<fixed-network>', |
1578 | + help=_('The private Neutron network name to connect to this ' |
1579 | + 'Cluster template.')) |
1580 | + parser.add_argument( |
1581 | + '--fixed-subnet', |
1582 | + dest='fixed_subnet', |
1583 | + metavar='<fixed-subnet>', |
1584 | + help=_('The private Neutron subnet name to connect to Cluster.')) |
1585 | + parser.add_argument( |
1586 | + '--floating-ip-enabled', |
1587 | + dest='floating_ip_enabled', |
1588 | + default=[], |
1589 | + action='append_const', |
1590 | + const=True, |
1591 | + help=_('Indicates whether created Clusters should have a ' |
1592 | + 'floating ip.')) |
1593 | + parser.add_argument( |
1594 | + '--floating-ip-disabled', |
1595 | + dest='floating_ip_enabled', |
1596 | + action='append_const', |
1597 | + const=False, |
1598 | + help=_('Disables floating ip creation on the new Cluster')) |
1599 | + parser.add_argument( |
1600 | + '--merge-labels', |
1601 | + dest='merge_labels', |
1602 | + action='store_true', |
1603 | + default=False, |
1604 | + help=_('The labels provided will be merged with the labels ' |
1605 | + 'configured in the specified cluster template.')) |
1606 | |
1607 | return parser |
1608 | |
1609 | @@ -130,6 +168,15 @@ class CreateCluster(command.Command): |
1610 | 'node_count': parsed_args.node_count, |
1611 | } |
1612 | |
1613 | + if len(parsed_args.floating_ip_enabled) > 1: |
1614 | + raise exceptions.InvalidAttribute( |
1615 | + '--floating-ip-enabled and ' |
1616 | + '--floating-ip-disabled are ' |
1617 | + 'mutually exclusive and ' |
1618 | + 'should be specified only once.') |
1619 | + elif len(parsed_args.floating_ip_enabled) == 1: |
1620 | + args['floating_ip_enabled'] = parsed_args.floating_ip_enabled[0] |
1621 | + |
1622 | if parsed_args.labels is not None: |
1623 | args['labels'] = magnum_utils.handle_labels(parsed_args.labels) |
1624 | |
1625 | @@ -142,6 +189,17 @@ class CreateCluster(command.Command): |
1626 | if parsed_args.flavor is not None: |
1627 | args['flavor_id'] = parsed_args.flavor |
1628 | |
1629 | + if parsed_args.fixed_network is not None: |
1630 | + args["fixed_network"] = parsed_args.fixed_network |
1631 | + |
1632 | + if parsed_args.fixed_subnet is not None: |
1633 | + args["fixed_subnet"] = parsed_args.fixed_subnet |
1634 | + |
1635 | + if parsed_args.merge_labels: |
1636 | + # We are only sending this if it's True. This |
1637 | + # way we avoid breaking older APIs. |
1638 | + args["merge_labels"] = parsed_args.merge_labels |
1639 | + |
1640 | cluster = mag_client.clusters.create(**args) |
1641 | print("Request to create cluster %s accepted" |
1642 | % cluster.uuid) |
1643 | @@ -197,7 +255,8 @@ class ListCluster(command.Lister): |
1644 | |
1645 | mag_client = self.app.client_manager.container_infra |
1646 | columns = [ |
1647 | - 'uuid', 'name', 'keypair', 'node_count', 'master_count', 'status'] |
1648 | + 'uuid', 'name', 'keypair', 'node_count', 'master_count', 'status', |
1649 | + 'health_status'] |
1650 | clusters = mag_client.clusters.list(limit=parsed_args.limit, |
1651 | sort_key=parsed_args.sort_key, |
1652 | sort_dir=parsed_args.sort_dir) |
1653 | @@ -305,6 +364,18 @@ class ConfigCluster(command.Command): |
1654 | dest='output_certs', |
1655 | default=False, |
1656 | help=_('Output certificates in separate files.')) |
1657 | + parser.add_argument( |
1658 | + '--use-certificate', |
1659 | + action='store_true', |
1660 | + dest='use_certificate', |
1661 | + default=True, |
1662 | + help=_('Use certificate in config files.')) |
1663 | + parser.add_argument( |
1664 | + '--use-keystone', |
1665 | + action='store_true', |
1666 | + dest='use_keystone', |
1667 | + default=False, |
1668 | + help=_('Use Keystone token in config files.')) |
1669 | |
1670 | return parser |
1671 | |
1672 | @@ -315,16 +386,21 @@ class ConfigCluster(command.Command): |
1673 | the corresponding COE configured to access the cluster. |
1674 | |
1675 | """ |
1676 | + if parsed_args.use_keystone: |
1677 | + parsed_args.use_certificate = False |
1678 | + if not parsed_args.use_certificate: |
1679 | + parsed_args.use_keystone = True |
1680 | + |
1681 | self.log.debug("take_action(%s)", parsed_args) |
1682 | |
1683 | mag_client = self.app.client_manager.container_infra |
1684 | |
1685 | parsed_args.dir = os.path.abspath(parsed_args.dir) |
1686 | cluster = mag_client.clusters.get(parsed_args.cluster) |
1687 | - if cluster.status not in ('CREATE_COMPLETE', 'UPDATE_COMPLETE', |
1688 | - 'ROLLBACK_COMPLETE'): |
1689 | - raise exceptions.CommandError("cluster in status %s" % |
1690 | - cluster.status) |
1691 | + if cluster.api_address is None: |
1692 | + self.log.warning("WARNING: The cluster's api_address is" |
1693 | + " not known yet.") |
1694 | + |
1695 | cluster_template = mag_client.cluster_templates.get( |
1696 | cluster.cluster_template_id) |
1697 | opts = { |
1698 | @@ -346,8 +422,92 @@ class ConfigCluster(command.Command): |
1699 | with open(fname, "w") as f: |
1700 | f.write(tls[k]) |
1701 | |
1702 | - print(magnum_utils.config_cluster(cluster, |
1703 | - cluster_template, |
1704 | - parsed_args.dir, |
1705 | - force=parsed_args.force, |
1706 | - certs=tls)) |
1707 | + print(magnum_utils.config_cluster( |
1708 | + cluster, cluster_template, parsed_args.dir, |
1709 | + force=parsed_args.force, certs=tls, |
1710 | + use_keystone=parsed_args.use_keystone)) |
1711 | + |
1712 | + |
1713 | +class ResizeCluster(command.Command): |
1714 | + _description = _("Resize a Cluster") |
1715 | + |
1716 | + def get_parser(self, prog_name): |
1717 | + parser = super(ResizeCluster, self).get_parser(prog_name) |
1718 | + parser.add_argument( |
1719 | + 'cluster', |
1720 | + metavar='<cluster>', |
1721 | + help=_('The name or UUID of cluster to update')) |
1722 | + |
1723 | + parser.add_argument( |
1724 | + 'node_count', |
1725 | + type=int, |
1726 | + help=_("Desired node count of the cluser.")) |
1727 | + |
1728 | + parser.add_argument( |
1729 | + '--nodes-to-remove', |
1730 | + metavar='<Server UUID>', |
1731 | + action='append', |
1732 | + help=_("Server ID of the nodes to be removed. Repeat to add" |
1733 | + "more server ID")) |
1734 | + |
1735 | + parser.add_argument( |
1736 | + '--nodegroup', |
1737 | + metavar='<nodegroup>', |
1738 | + help=_('The name or UUID of the nodegroup of current cluster.')) |
1739 | + |
1740 | + return parser |
1741 | + |
1742 | + def take_action(self, parsed_args): |
1743 | + self.log.debug("take_action(%s)", parsed_args) |
1744 | + |
1745 | + mag_client = self.app.client_manager.container_infra |
1746 | + cluster = mag_client.clusters.get(parsed_args.cluster) |
1747 | + |
1748 | + mag_client.clusters.resize(cluster.uuid, |
1749 | + parsed_args.node_count, |
1750 | + parsed_args.nodes_to_remove, |
1751 | + parsed_args.nodegroup) |
1752 | + print("Request to resize cluster %s has been accepted." % |
1753 | + parsed_args.cluster) |
1754 | + |
1755 | + |
1756 | +class UpgradeCluster(command.Command): |
1757 | + _description = _("Upgrade a Cluster") |
1758 | + |
1759 | + def get_parser(self, prog_name): |
1760 | + parser = super(UpgradeCluster, self).get_parser(prog_name) |
1761 | + parser.add_argument( |
1762 | + 'cluster', |
1763 | + metavar='<cluster>', |
1764 | + help=_('The name or UUID of cluster to update')) |
1765 | + |
1766 | + parser.add_argument( |
1767 | + 'cluster_template', |
1768 | + help=_("The new cluster template ID will be upgraded to.")) |
1769 | + |
1770 | + parser.add_argument( |
1771 | + '--max-batch-size', |
1772 | + metavar='<max_batch_size>', |
1773 | + type=int, |
1774 | + default=1, |
1775 | + help=_("The max batch size for upgrading each time.")) |
1776 | + |
1777 | + parser.add_argument( |
1778 | + '--nodegroup', |
1779 | + metavar='<nodegroup>', |
1780 | + help=_('The name or UUID of the nodegroup of current cluster.')) |
1781 | + |
1782 | + return parser |
1783 | + |
1784 | + def take_action(self, parsed_args): |
1785 | + self.log.debug("take_action(%s)", parsed_args) |
1786 | + |
1787 | + mag_client = self.app.client_manager.container_infra |
1788 | + cluster = mag_client.clusters.get(parsed_args.cluster) |
1789 | + |
1790 | + mag_client.clusters.upgrade(cluster.uuid, |
1791 | + parsed_args.cluster_template, |
1792 | + parsed_args.max_batch_size, |
1793 | + parsed_args.nodegroup) |
1794 | + print("Request to upgrade cluster %s has been accepted." % |
1795 | + parsed_args.cluster) |
1796 | diff --git a/magnumclient/osc/v1/nodegroups.py b/magnumclient/osc/v1/nodegroups.py |
1797 | new file mode 100644 |
1798 | index 0000000..afb5870 |
1799 | --- /dev/null |
1800 | +++ b/magnumclient/osc/v1/nodegroups.py |
1801 | @@ -0,0 +1,301 @@ |
1802 | +# Copyright (c) 2018 European Organization for Nuclear Research. |
1803 | +# All Rights Reserved. |
1804 | +# |
1805 | +# Licensed under the Apache License, Version 2.0 (the "License"); you may |
1806 | +# not use this file except in compliance with the License. You may obtain |
1807 | +# a copy of the License at |
1808 | +# |
1809 | +# http://www.apache.org/licenses/LICENSE-2.0 |
1810 | +# |
1811 | +# Unless required by applicable law or agreed to in writing, software |
1812 | +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
1813 | +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
1814 | +# License for the specific language governing permissions and limitations |
1815 | +# under the License. |
1816 | + |
1817 | +from magnumclient.common import utils as magnum_utils |
1818 | +from magnumclient.i18n import _ |
1819 | + |
1820 | +from osc_lib.command import command |
1821 | +from osc_lib import utils |
1822 | + |
1823 | + |
1824 | +NODEGROUP_ATTRIBUTES = [ |
1825 | + 'uuid', |
1826 | + 'name', |
1827 | + 'cluster_id', |
1828 | + 'project_id', |
1829 | + 'docker_volume_size', |
1830 | + 'labels', |
1831 | + 'labels_overridden', |
1832 | + 'labels_skipped', |
1833 | + 'labels_added', |
1834 | + 'flavor_id', |
1835 | + 'image_id', |
1836 | + 'node_addresses', |
1837 | + 'node_count', |
1838 | + 'role', |
1839 | + 'max_node_count', |
1840 | + 'min_node_count', |
1841 | + 'is_default', |
1842 | + 'stack_id', |
1843 | + 'status', |
1844 | + 'status_reason', |
1845 | +] |
1846 | + |
1847 | + |
1848 | +class CreateNodeGroup(command.Command): |
1849 | + _description = _("Create a nodegroup") |
1850 | + |
1851 | + def get_parser(self, prog_name): |
1852 | + parser = super(CreateNodeGroup, self).get_parser(prog_name) |
1853 | + # NOTE: All arguments are positional and, if not provided |
1854 | + # with a default, required. |
1855 | + parser.add_argument('--docker-volume-size', |
1856 | + dest='docker_volume_size', |
1857 | + type=int, |
1858 | + metavar='<docker-volume-size>', |
1859 | + help=('The size in GB for the docker volume to ' |
1860 | + 'use.')) |
1861 | + parser.add_argument('--labels', |
1862 | + metavar='<KEY1=VALUE1,KEY2=VALUE2;KEY3=VALUE3...>', |
1863 | + action='append', |
1864 | + help=_('Arbitrary labels in the form of key=value' |
1865 | + 'pairs to associate with a nodegroup. ' |
1866 | + 'May be used multiple times.')) |
1867 | + parser.add_argument('cluster', |
1868 | + metavar='<cluster>', |
1869 | + help='Name of the nodegroup to create.') |
1870 | + parser.add_argument('name', |
1871 | + metavar='<name>', |
1872 | + help='Name of the nodegroup to create.') |
1873 | + parser.add_argument('--node-count', |
1874 | + dest='node_count', |
1875 | + type=int, |
1876 | + default=1, |
1877 | + metavar='<node-count>', |
1878 | + help='The nodegroup node count.') |
1879 | + parser.add_argument('--min-nodes', |
1880 | + dest='min_node_count', |
1881 | + type=int, |
1882 | + default=1, |
1883 | + metavar='<min-nodes>', |
1884 | + help='The nodegroup minimum node count.') |
1885 | + parser.add_argument('--max-nodes', |
1886 | + dest='max_node_count', |
1887 | + type=int, |
1888 | + default=None, |
1889 | + metavar='<max-nodes>', |
1890 | + help='The nodegroup maximum node count.') |
1891 | + parser.add_argument('--role', |
1892 | + dest='role', |
1893 | + type=str, |
1894 | + default='worker', |
1895 | + metavar='<role>', |
1896 | + help=('The role of the nodegroup')) |
1897 | + parser.add_argument( |
1898 | + '--image', |
1899 | + metavar='<image>', |
1900 | + help=_('The name or UUID of the base image to customize for the ' |
1901 | + 'NodeGroup.')) |
1902 | + parser.add_argument( |
1903 | + '--flavor', |
1904 | + metavar='<flavor>', |
1905 | + help=_('The nova flavor name or UUID to use when launching the ' |
1906 | + 'nodes in this NodeGroup.')) |
1907 | + parser.add_argument( |
1908 | + '--merge-labels', |
1909 | + dest='merge_labels', |
1910 | + action='store_true', |
1911 | + default=False, |
1912 | + help=_('The labels provided will be merged with the labels ' |
1913 | + 'configured in the specified cluster.')) |
1914 | + |
1915 | + return parser |
1916 | + |
1917 | + def take_action(self, parsed_args): |
1918 | + self.log.debug("take_action(%s)", parsed_args) |
1919 | + |
1920 | + mag_client = self.app.client_manager.container_infra |
1921 | + args = { |
1922 | + 'name': parsed_args.name, |
1923 | + 'node_count': parsed_args.node_count, |
1924 | + 'max_node_count': parsed_args.max_node_count, |
1925 | + 'min_node_count': parsed_args.min_node_count, |
1926 | + 'role': parsed_args.role, |
1927 | + } |
1928 | + |
1929 | + if parsed_args.labels is not None: |
1930 | + args['labels'] = magnum_utils.handle_labels(parsed_args.labels) |
1931 | + |
1932 | + if parsed_args.docker_volume_size is not None: |
1933 | + args['docker_volume_size'] = parsed_args.docker_volume_size |
1934 | + |
1935 | + if parsed_args.flavor is not None: |
1936 | + args['flavor_id'] = parsed_args.flavor |
1937 | + |
1938 | + if parsed_args.image is not None: |
1939 | + args['image_id'] = parsed_args.image |
1940 | + |
1941 | + if parsed_args.merge_labels: |
1942 | + # We are only sending this if it's True. This |
1943 | + # way we avoid breaking older APIs. |
1944 | + args["merge_labels"] = parsed_args.merge_labels |
1945 | + |
1946 | + cluster_id = parsed_args.cluster |
1947 | + nodegroup = mag_client.nodegroups.create(cluster_id, **args) |
1948 | + print("Request to create nodegroup %s accepted" |
1949 | + % nodegroup.uuid) |
1950 | + |
1951 | + |
1952 | +class DeleteNodeGroup(command.Command): |
1953 | + _description = _("Delete a nodegroup") |
1954 | + |
1955 | + def get_parser(self, prog_name): |
1956 | + parser = super(DeleteNodeGroup, self).get_parser(prog_name) |
1957 | + parser.add_argument( |
1958 | + 'cluster', |
1959 | + metavar='<cluster>', |
1960 | + help=_('ID or name of the cluster where the nodegroup(s) ' |
1961 | + 'belong(s).')) |
1962 | + parser.add_argument( |
1963 | + 'nodegroup', |
1964 | + nargs='+', |
1965 | + metavar='<nodegroup>', |
1966 | + help='ID or name of the nodegroup(s) to delete.') |
1967 | + |
1968 | + return parser |
1969 | + |
1970 | + def take_action(self, parsed_args): |
1971 | + self.log.debug("take_action(%s)", parsed_args) |
1972 | + |
1973 | + mag_client = self.app.client_manager.container_infra |
1974 | + cluster_id = parsed_args.cluster |
1975 | + for ng in parsed_args.nodegroup: |
1976 | + mag_client.nodegroups.delete(cluster_id, ng) |
1977 | + print("Request to delete nodegroup %s has been accepted." % ng) |
1978 | + |
1979 | + |
1980 | +class ListNodeGroup(command.Lister): |
1981 | + _description = _("List nodegroups") |
1982 | + |
1983 | + def get_parser(self, prog_name): |
1984 | + parser = super(ListNodeGroup, self).get_parser(prog_name) |
1985 | + |
1986 | + parser.add_argument( |
1987 | + 'cluster', |
1988 | + metavar='<cluster>', |
1989 | + help=_('ID or name of the cluster where the nodegroup belongs.')) |
1990 | + parser.add_argument( |
1991 | + '--limit', |
1992 | + metavar='<limit>', |
1993 | + type=int, |
1994 | + help=_('Maximum number of nodegroups to return')) |
1995 | + parser.add_argument( |
1996 | + '--sort-key', |
1997 | + metavar='<sort-key>', |
1998 | + help=_('Column to sort results by')) |
1999 | + parser.add_argument( |
2000 | + '--sort-dir', |
2001 | + metavar='<sort-dir>', |
2002 | + choices=['desc', 'asc'], |
2003 | + help=_('Direction to sort. "asc" or "desc".')) |
2004 | + parser.add_argument( |
2005 | + '--role', |
2006 | + metavar='<role>', |
2007 | + help=_('List the nodegroups in the cluster with this role')) |
2008 | + |
2009 | + return parser |
2010 | + |
2011 | + def take_action(self, parsed_args): |
2012 | + self.log.debug("take_action(%s)", parsed_args) |
2013 | + |
2014 | + mag_client = self.app.client_manager.container_infra |
2015 | + columns = ['uuid', 'name', 'flavor_id', 'image_id', 'node_count', |
2016 | + 'status', 'role'] |
2017 | + cluster_id = parsed_args.cluster |
2018 | + nodegroups = mag_client.nodegroups.list(cluster_id, |
2019 | + limit=parsed_args.limit, |
2020 | + sort_key=parsed_args.sort_key, |
2021 | + sort_dir=parsed_args.sort_dir, |
2022 | + role=parsed_args.role) |
2023 | + return ( |
2024 | + columns, |
2025 | + (utils.get_item_properties(n, columns) for n in nodegroups) |
2026 | + ) |
2027 | + |
2028 | + |
2029 | +class ShowNodeGroup(command.ShowOne): |
2030 | + _description = _("Show a nodegroup") |
2031 | + |
2032 | + def get_parser(self, prog_name): |
2033 | + parser = super(ShowNodeGroup, self).get_parser(prog_name) |
2034 | + parser.add_argument( |
2035 | + 'cluster', |
2036 | + metavar='<cluster>', |
2037 | + help=_('ID or name of the cluster where the nodegroup belongs.')) |
2038 | + parser.add_argument( |
2039 | + 'nodegroup', |
2040 | + metavar='<nodegroup>', |
2041 | + help=_('ID or name of the nodegroup to show.') |
2042 | + ) |
2043 | + return parser |
2044 | + |
2045 | + def take_action(self, parsed_args): |
2046 | + self.log.debug("take_action(%s)", parsed_args) |
2047 | + |
2048 | + columns = NODEGROUP_ATTRIBUTES |
2049 | + |
2050 | + mag_client = self.app.client_manager.container_infra |
2051 | + cluster_id = parsed_args.cluster |
2052 | + nodegroup = mag_client.nodegroups.get(cluster_id, |
2053 | + parsed_args.nodegroup) |
2054 | + |
2055 | + return (columns, utils.get_item_properties(nodegroup, columns)) |
2056 | + |
2057 | + |
2058 | +class UpdateNodeGroup(command.Command): |
2059 | + _description = _("Update a Nodegroup") |
2060 | + |
2061 | + def get_parser(self, prog_name): |
2062 | + parser = super(UpdateNodeGroup, self).get_parser(prog_name) |
2063 | + parser.add_argument( |
2064 | + 'cluster', |
2065 | + metavar='<cluster>', |
2066 | + help=_('ID or name of the cluster where the nodegroup belongs.')) |
2067 | + parser.add_argument( |
2068 | + 'nodegroup', |
2069 | + metavar='<nodegroup>', |
2070 | + help=_('The name or UUID of cluster to update')) |
2071 | + |
2072 | + parser.add_argument( |
2073 | + 'op', |
2074 | + metavar='<op>', |
2075 | + choices=['add', 'replace', 'remove'], |
2076 | + help=_("Operations: one of 'add', 'replace' or 'remove'")) |
2077 | + |
2078 | + parser.add_argument( |
2079 | + 'attributes', |
2080 | + metavar='<path=value>', |
2081 | + nargs='+', |
2082 | + action='append', |
2083 | + default=[], |
2084 | + help=_( |
2085 | + "Attributes to add/replace or remove (only PATH is necessary " |
2086 | + "on remove)")) |
2087 | + |
2088 | + return parser |
2089 | + |
2090 | + def take_action(self, parsed_args): |
2091 | + self.log.debug("take_action(%s)", parsed_args) |
2092 | + |
2093 | + mag_client = self.app.client_manager.container_infra |
2094 | + |
2095 | + patch = magnum_utils.args_array_to_patch(parsed_args.op, |
2096 | + parsed_args.attributes[0]) |
2097 | + |
2098 | + cluster_id = parsed_args.cluster |
2099 | + mag_client.nodegroups.update(cluster_id, parsed_args.nodegroup, |
2100 | + patch) |
2101 | + print("Request to update nodegroup %s has been accepted." % |
2102 | + parsed_args.nodegroup) |
2103 | diff --git a/magnumclient/shell.py b/magnumclient/shell.py |
2104 | index 259f1ad..9da9255 100644 |
2105 | --- a/magnumclient/shell.py |
2106 | +++ b/magnumclient/shell.py |
2107 | @@ -33,6 +33,13 @@ from oslo_utils import importutils |
2108 | from oslo_utils import strutils |
2109 | import six |
2110 | |
2111 | +from magnumclient.common import cliutils |
2112 | +from magnumclient import exceptions as exc |
2113 | +from magnumclient.i18n import _ |
2114 | +from magnumclient.v1 import client as client_v1 |
2115 | +from magnumclient.v1 import shell as shell_v1 |
2116 | +from magnumclient import version |
2117 | + |
2118 | profiler = importutils.try_import("osprofiler.profiler") |
2119 | |
2120 | HAS_KEYRING = False |
2121 | @@ -51,12 +58,6 @@ try: |
2122 | except ImportError: |
2123 | pass |
2124 | |
2125 | -from magnumclient.common import cliutils |
2126 | -from magnumclient import exceptions as exc |
2127 | -from magnumclient.i18n import _ |
2128 | -from magnumclient.v1 import client as client_v1 |
2129 | -from magnumclient.v1 import shell as shell_v1 |
2130 | -from magnumclient import version |
2131 | |
2132 | LATEST_API_VERSION = ('1', 'latest') |
2133 | DEFAULT_INTERFACE = 'public' |
2134 | diff --git a/magnumclient/tests/osc/unit/osc_fakes.py b/magnumclient/tests/osc/unit/osc_fakes.py |
2135 | index 2df0686..b9e8086 100644 |
2136 | --- a/magnumclient/tests/osc/unit/osc_fakes.py |
2137 | +++ b/magnumclient/tests/osc/unit/osc_fakes.py |
2138 | @@ -13,13 +13,12 @@ |
2139 | # under the License. |
2140 | # |
2141 | |
2142 | -import json |
2143 | import mock |
2144 | +from oslo_serialization import jsonutils |
2145 | import sys |
2146 | |
2147 | from keystoneauth1 import fixture |
2148 | import requests |
2149 | -import six |
2150 | |
2151 | AUTH_TOKEN = "foobar" |
2152 | AUTH_URL = "http://0.0.0.0" |
2153 | @@ -239,9 +238,7 @@ class FakeResponse(requests.Response): |
2154 | self.status_code = status_code |
2155 | |
2156 | self.headers.update(headers) |
2157 | - self._content = json.dumps(data) |
2158 | - if not isinstance(self._content, six.binary_type): |
2159 | - self._content = self._content.encode() |
2160 | + self._content = jsonutils.dump_as_bytes(data) |
2161 | |
2162 | |
2163 | class FakeModel(dict): |
2164 | diff --git a/magnumclient/tests/osc/unit/v1/fakes.py b/magnumclient/tests/osc/unit/v1/fakes.py |
2165 | index df11d41..4181010 100644 |
2166 | --- a/magnumclient/tests/osc/unit/v1/fakes.py |
2167 | +++ b/magnumclient/tests/osc/unit/v1/fakes.py |
2168 | @@ -62,14 +62,38 @@ class FakeQuotasModelManager(object): |
2169 | pass |
2170 | |
2171 | |
2172 | +class FakeNodeGroupManager(object): |
2173 | + def list(self, cluster_id, limit=None, marker=None, sort_key=None, |
2174 | + sort_dir=None, detail=False): |
2175 | + pass |
2176 | + |
2177 | + def get(self, cluster_id, id): |
2178 | + pass |
2179 | + |
2180 | + def create(self, cluster_id, **kwargs): |
2181 | + pass |
2182 | + |
2183 | + def delete(self, cluster_id, id): |
2184 | + pass |
2185 | + |
2186 | + def update(self, cluster_id, id, patch): |
2187 | + pass |
2188 | + |
2189 | + |
2190 | +class FakeCertificatesModelManager(FakeBaseModelManager): |
2191 | + def get(self, cluster_uuid): |
2192 | + pass |
2193 | + |
2194 | + |
2195 | class MagnumFakeContainerInfra(object): |
2196 | def __init__(self): |
2197 | self.cluster_templates = FakeBaseModelManager() |
2198 | self.clusters = FakeBaseModelManager() |
2199 | self.mservices = FakeBaseModelManager() |
2200 | - self.certificates = FakeBaseModelManager() |
2201 | + self.certificates = FakeCertificatesModelManager() |
2202 | self.stats = FakeStatsModelManager() |
2203 | self.quotas = FakeQuotasModelManager() |
2204 | + self.nodegroups = FakeNodeGroupManager() |
2205 | |
2206 | |
2207 | class MagnumFakeClientManager(osc_fakes.FakeClientManager): |
2208 | @@ -160,7 +184,8 @@ class FakeClusterTemplate(object): |
2209 | 'coe': 'kubernetes', |
2210 | 'flavor_id': 'm1.medium', |
2211 | 'master_lb_enabled': False, |
2212 | - 'dns_nameserver': '8.8.8.8' |
2213 | + 'dns_nameserver': '8.8.8.8', |
2214 | + 'hidden': False |
2215 | } |
2216 | |
2217 | # Overwrite default attributes. |
2218 | @@ -205,12 +230,16 @@ class FakeCluster(object): |
2219 | # set default attributes. |
2220 | cluster_info = { |
2221 | 'status': 'CREATE_IN_PROGRESS', |
2222 | + 'health_status': 'HEALTHY', |
2223 | 'cluster_template_id': 'fake-ct', |
2224 | 'node_addresses': [], |
2225 | 'uuid': '3a369884-b6ba-484f-a206-919b4b718aff', |
2226 | 'stack_id': 'c4554582-77bd-4734-8f1a-72c3c40e5fb4', |
2227 | 'status_reason': None, |
2228 | 'labels': {}, |
2229 | + 'labels_overridden': {}, |
2230 | + 'labels_added': {}, |
2231 | + 'labels_skipped': {}, |
2232 | 'created_at': '2017-03-16T18:40:39+00:00', |
2233 | 'updated_at': '2017-03-16T18:40:45+00:00', |
2234 | 'coe_version': None, |
2235 | @@ -227,6 +256,7 @@ class FakeCluster(object): |
2236 | 'master_flavor_id': None, |
2237 | 'flavor_id': 'm1.medium', |
2238 | 'project_id': None, |
2239 | + 'health_status_reason': {'api': 'ok'} |
2240 | } |
2241 | |
2242 | # Overwrite default attributes. |
2243 | @@ -237,6 +267,11 @@ class FakeCluster(object): |
2244 | return cluster |
2245 | |
2246 | |
2247 | +class FakeCert(object): |
2248 | + def __init__(self, pem): |
2249 | + self.pem = pem |
2250 | + |
2251 | + |
2252 | class FakeQuota(object): |
2253 | """Fake one or more Quota""" |
2254 | |
2255 | @@ -266,3 +301,52 @@ class FakeQuota(object): |
2256 | quota = osc_fakes.FakeResource(info=copy.deepcopy(quota_info), |
2257 | loaded=True) |
2258 | return quota |
2259 | + |
2260 | + |
2261 | +class FakeNodeGroup(object): |
2262 | + """Fake one or more NodeGroup.""" |
2263 | + |
2264 | + @staticmethod |
2265 | + def create_one_nodegroup(attrs=None): |
2266 | + """Create a fake NodeGroup. |
2267 | + |
2268 | + :param Dictionary attrs: |
2269 | + A dictionary with all attributes |
2270 | + :return: |
2271 | + A FakeResource object, with flavor_id, image_id, and so on |
2272 | + """ |
2273 | + |
2274 | + attrs = attrs or {} |
2275 | + |
2276 | + # set default attributes. |
2277 | + nodegroup_info = { |
2278 | + 'created_at': '2017-03-16T18:40:39+00:00', |
2279 | + 'updated_at': '2017-03-16T18:40:45+00:00', |
2280 | + 'uuid': '3a369884-b6ba-484f-a206-919b4b718aff', |
2281 | + 'cluster_id': 'fake-cluster', |
2282 | + 'docker_volume_size': None, |
2283 | + 'node_addresses': [], |
2284 | + 'labels': {}, |
2285 | + 'labels_overridden': {}, |
2286 | + 'labels_added': {}, |
2287 | + 'labels_skipped': {}, |
2288 | + 'node_count': 1, |
2289 | + 'name': 'fake-nodegroup', |
2290 | + 'flavor_id': 'm1.medium', |
2291 | + 'image_id': 'fedora-latest', |
2292 | + 'project_id': None, |
2293 | + 'role': 'worker', |
2294 | + 'max_node_count': 10, |
2295 | + 'min_node_count': 1, |
2296 | + 'is_default': False, |
2297 | + 'stack_id': '3a369884-b6ba-484f-fake-stackb718aff', |
2298 | + 'status': 'CREATE_COMPLETE', |
2299 | + 'status_reason': 'None' |
2300 | + } |
2301 | + |
2302 | + # Overwrite default attributes. |
2303 | + nodegroup_info.update(attrs) |
2304 | + |
2305 | + nodegroup = osc_fakes.FakeResource(info=copy.deepcopy(nodegroup_info), |
2306 | + loaded=True) |
2307 | + return nodegroup |
2308 | diff --git a/magnumclient/tests/osc/unit/v1/test_cluster_templates.py b/magnumclient/tests/osc/unit/v1/test_cluster_templates.py |
2309 | index 5321687..b5c1c35 100644 |
2310 | --- a/magnumclient/tests/osc/unit/v1/test_cluster_templates.py |
2311 | +++ b/magnumclient/tests/osc/unit/v1/test_cluster_templates.py |
2312 | @@ -48,7 +48,7 @@ class TestClusterTemplate(magnum_fakes.TestMagnumClientOSCV1): |
2313 | 'registry_enabled': False, |
2314 | 'server_type': 'vm', |
2315 | 'tls_disabled': False, |
2316 | - 'volume_driver': None |
2317 | + 'volume_driver': None, |
2318 | } |
2319 | |
2320 | def setUp(self): |
2321 | @@ -271,22 +271,24 @@ class TestClusterTemplateList(TestClusterTemplate): |
2322 | '--limit', '1', |
2323 | '--sort-key', 'key', |
2324 | '--sort-dir', 'asc', |
2325 | - '--fields', 'fields' |
2326 | + '--fields', 'field1,field2' |
2327 | ] |
2328 | verifylist = [ |
2329 | ('limit', 1), |
2330 | ('sort_key', 'key'), |
2331 | ('sort_dir', 'asc'), |
2332 | - ('fields', 'fields'), |
2333 | + ('fields', 'field1,field2'), |
2334 | ] |
2335 | + verifycolumns = self.columns + ['field1', 'field2'] |
2336 | parsed_args = self.check_parser(self.cmd, arglist, verifylist) |
2337 | |
2338 | - self.cmd.take_action(parsed_args) |
2339 | + columns, data = self.cmd.take_action(parsed_args) |
2340 | self.cluster_templates_mock.list.assert_called_with( |
2341 | limit=1, |
2342 | sort_dir='asc', |
2343 | sort_key='key', |
2344 | ) |
2345 | + self.assertEqual(verifycolumns, columns) |
2346 | |
2347 | def test_cluster_template_list_bad_sort_dir_fail(self): |
2348 | arglist = [ |
2349 | diff --git a/magnumclient/tests/osc/unit/v1/test_clusters.py b/magnumclient/tests/osc/unit/v1/test_clusters.py |
2350 | index 4783c13..2530796 100644 |
2351 | --- a/magnumclient/tests/osc/unit/v1/test_clusters.py |
2352 | +++ b/magnumclient/tests/osc/unit/v1/test_clusters.py |
2353 | @@ -37,6 +37,8 @@ class TestCluster(magnum_fakes.TestMagnumClientOSCV1): |
2354 | super(TestCluster, self).setUp() |
2355 | |
2356 | self.clusters_mock = self.app.client_manager.container_infra.clusters |
2357 | + self.certificates_mock = \ |
2358 | + self.app.client_manager.container_infra.certificates |
2359 | |
2360 | |
2361 | class TestClusterCreate(TestCluster): |
2362 | @@ -181,7 +183,8 @@ class TestClusterList(TestCluster): |
2363 | 'keypair', |
2364 | 'node_count', |
2365 | 'master_count', |
2366 | - 'status' |
2367 | + 'status', |
2368 | + 'health_status' |
2369 | ] |
2370 | |
2371 | datalist = ( |
2372 | @@ -191,7 +194,8 @@ class TestClusterList(TestCluster): |
2373 | _cluster.keypair, |
2374 | _cluster.node_count, |
2375 | _cluster.master_count, |
2376 | - _cluster.status |
2377 | + _cluster.status, |
2378 | + _cluster.health_status, |
2379 | ), |
2380 | ) |
2381 | |
2382 | @@ -360,10 +364,15 @@ class TestClusterConfig(TestCluster): |
2383 | self.clusters_mock.get = mock.Mock() |
2384 | self.clusters_mock.get.return_value = self._cluster |
2385 | |
2386 | + cert = magnum_fakes.FakeCert(pem='foo bar') |
2387 | + self.certificates_mock.create = mock.Mock() |
2388 | + self.certificates_mock.create.return_value = cert |
2389 | + self.certificates_mock.get = mock.Mock() |
2390 | + self.certificates_mock.get.return_value = cert |
2391 | + |
2392 | # Fake the cluster_template |
2393 | attr = dict() |
2394 | attr['name'] = 'fake-ct' |
2395 | - attr['tls_disabled'] = True |
2396 | self._cluster_template = \ |
2397 | magnum_fakes.FakeClusterTemplate.create_one_cluster_template(attr) |
2398 | |
2399 | @@ -459,14 +468,65 @@ export KUBECONFIG={}/config |
2400 | |
2401 | self.clusters_mock.get.assert_called_with('fake-cluster') |
2402 | |
2403 | - def test_cluster_config_with_in_progress_status(self): |
2404 | - self._cluster.status = 'CREATE_IN_PROGRESS' |
2405 | |
2406 | - arglist = ['fake-cluster-1'] |
2407 | +class TestClusterResize(TestCluster): |
2408 | + |
2409 | + def setUp(self): |
2410 | + super(TestClusterResize, self).setUp() |
2411 | + self.cluster = mock.Mock() |
2412 | + self.cluster.uuid = "UUID1" |
2413 | + self.clusters_mock.resize = mock.Mock() |
2414 | + self.clusters_mock.resize.return_value = None |
2415 | + |
2416 | + self.clusters_mock.get = mock.Mock() |
2417 | + self.clusters_mock.get.return_value = self.cluster |
2418 | + |
2419 | + # Get the command object to test |
2420 | + self.cmd = osc_clusters.ResizeCluster(self.app, None) |
2421 | + |
2422 | + def test_cluster_resize_pass(self): |
2423 | + arglist = ['foo', '2'] |
2424 | verifylist = [ |
2425 | - ('cluster', 'fake-cluster-1') |
2426 | + ('cluster', 'foo'), |
2427 | + ('node_count', 2), |
2428 | + ('nodes_to_remove', None), |
2429 | + ('nodegroup', None) |
2430 | ] |
2431 | + parsed_args = self.check_parser(self.cmd, arglist, verifylist) |
2432 | + |
2433 | + self.cmd.take_action(parsed_args) |
2434 | + self.clusters_mock.resize.assert_called_with( |
2435 | + "UUID1", 2, None, None |
2436 | + ) |
2437 | + |
2438 | + |
2439 | +class TestClusterUpgrade(TestCluster): |
2440 | |
2441 | + def setUp(self): |
2442 | + super(TestClusterUpgrade, self).setUp() |
2443 | + self.cluster = mock.Mock() |
2444 | + self.cluster.uuid = "UUID1" |
2445 | + self.clusters_mock.upgrade = mock.Mock() |
2446 | + self.clusters_mock.upgrade.return_value = None |
2447 | + |
2448 | + self.clusters_mock.get = mock.Mock() |
2449 | + self.clusters_mock.get.return_value = self.cluster |
2450 | + |
2451 | + # Get the command object to test |
2452 | + self.cmd = osc_clusters.UpgradeCluster(self.app, None) |
2453 | + |
2454 | + def test_cluster_upgrade_pass(self): |
2455 | + cluster_template_id = 'TEMPLATE_ID' |
2456 | + arglist = ['foo', cluster_template_id] |
2457 | + verifylist = [ |
2458 | + ('cluster', 'foo'), |
2459 | + ('cluster_template', cluster_template_id), |
2460 | + ('max_batch_size', 1), |
2461 | + ('nodegroup', None) |
2462 | + ] |
2463 | parsed_args = self.check_parser(self.cmd, arglist, verifylist) |
2464 | - self.assertRaises(exceptions.CommandError, |
2465 | - self.cmd.take_action, parsed_args) |
2466 | + |
2467 | + self.cmd.take_action(parsed_args) |
2468 | + self.clusters_mock.upgrade.assert_called_with( |
2469 | + "UUID1", cluster_template_id, 1, None |
2470 | + ) |
2471 | diff --git a/magnumclient/tests/osc/unit/v1/test_nodegroups.py b/magnumclient/tests/osc/unit/v1/test_nodegroups.py |
2472 | new file mode 100644 |
2473 | index 0000000..06f1b55 |
2474 | --- /dev/null |
2475 | +++ b/magnumclient/tests/osc/unit/v1/test_nodegroups.py |
2476 | @@ -0,0 +1,333 @@ |
2477 | +# Copyright (c) 2018 European Organization for Nuclear Research. |
2478 | +# All Rights Reserved. |
2479 | +# |
2480 | +# Licensed under the Apache License, Version 2.0 (the "License"); you may |
2481 | +# not use this file except in compliance with the License. You may obtain |
2482 | +# a copy of the License at |
2483 | +# |
2484 | +# http://www.apache.org/licenses/LICENSE-2.0 |
2485 | +# |
2486 | +# Unless required by applicable law or agreed to in writing, software |
2487 | +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
2488 | +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
2489 | +# License for the specific language governing permissions and limitations |
2490 | +# under the License. |
2491 | + |
2492 | +import copy |
2493 | +import mock |
2494 | +from mock import call |
2495 | + |
2496 | +from magnumclient.osc.v1 import nodegroups as osc_nodegroups |
2497 | +from magnumclient.tests.osc.unit.v1 import fakes as magnum_fakes |
2498 | + |
2499 | + |
2500 | +class TestNodeGroup(magnum_fakes.TestMagnumClientOSCV1): |
2501 | + |
2502 | + def setUp(self): |
2503 | + super(TestNodeGroup, self).setUp() |
2504 | + self.ng_mock = self.app.client_manager.container_infra.nodegroups |
2505 | + |
2506 | + |
2507 | +class TestNodeGroupCreate(TestNodeGroup): |
2508 | + |
2509 | + def setUp(self): |
2510 | + super(TestNodeGroupCreate, self).setUp() |
2511 | + self.nodegroup = magnum_fakes.FakeNodeGroup.create_one_nodegroup() |
2512 | + |
2513 | + self.ng_mock.create = mock.Mock() |
2514 | + self.ng_mock.create.return_value = self.nodegroup |
2515 | + |
2516 | + self.ng_mock.get = mock.Mock() |
2517 | + self.ng_mock.get.return_value = copy.deepcopy(self.nodegroup) |
2518 | + |
2519 | + self.ng_mock.update = mock.Mock() |
2520 | + self.ng_mock.update.return_value = self.nodegroup |
2521 | + |
2522 | + self._default_args = { |
2523 | + 'name': 'fake-nodegroup', |
2524 | + 'node_count': 1, |
2525 | + 'role': 'worker', |
2526 | + 'min_node_count': 1, |
2527 | + 'max_node_count': None, |
2528 | + } |
2529 | + |
2530 | + # Get the command object to test |
2531 | + self.cmd = osc_nodegroups.CreateNodeGroup(self.app, None) |
2532 | + |
2533 | + self.data = tuple(map(lambda x: getattr(self.nodegroup, x), |
2534 | + osc_nodegroups.NODEGROUP_ATTRIBUTES)) |
2535 | + |
2536 | + def test_nodegroup_create_required_args_pass(self): |
2537 | + """Verifies required arguments.""" |
2538 | + |
2539 | + arglist = [ |
2540 | + self.nodegroup.cluster_id, |
2541 | + self.nodegroup.name |
2542 | + ] |
2543 | + verifylist = [ |
2544 | + ('cluster', self.nodegroup.cluster_id), |
2545 | + ('name', self.nodegroup.name) |
2546 | + ] |
2547 | + parsed_args = self.check_parser(self.cmd, arglist, verifylist) |
2548 | + self.cmd.take_action(parsed_args) |
2549 | + self.ng_mock.create.assert_called_with(self.nodegroup.cluster_id, |
2550 | + **self._default_args) |
2551 | + |
2552 | + def test_nodegroup_create_missing_required_arg(self): |
2553 | + """Verifies missing required arguments.""" |
2554 | + |
2555 | + arglist = [ |
2556 | + self.nodegroup.name |
2557 | + ] |
2558 | + verifylist = [ |
2559 | + ('name', self.nodegroup.name) |
2560 | + ] |
2561 | + self.assertRaises(magnum_fakes.MagnumParseException, |
2562 | + self.check_parser, self.cmd, arglist, verifylist) |
2563 | + |
2564 | + def test_nodegroup_create_with_labels(self): |
2565 | + """Verifies labels are properly parsed when given as argument.""" |
2566 | + |
2567 | + expected_args = self._default_args |
2568 | + expected_args['labels'] = { |
2569 | + 'arg1': 'value1', 'arg2': 'value2' |
2570 | + } |
2571 | + |
2572 | + arglist = [ |
2573 | + '--labels', 'arg1=value1', |
2574 | + '--labels', 'arg2=value2', |
2575 | + self.nodegroup.cluster_id, |
2576 | + self.nodegroup.name |
2577 | + ] |
2578 | + verifylist = [ |
2579 | + ('labels', ['arg1=value1', 'arg2=value2']), |
2580 | + ('name', self.nodegroup.name), |
2581 | + ('cluster', self.nodegroup.cluster_id) |
2582 | + ] |
2583 | + parsed_args = self.check_parser(self.cmd, arglist, verifylist) |
2584 | + self.cmd.take_action(parsed_args) |
2585 | + self.ng_mock.create.assert_called_with(self.nodegroup.cluster_id, |
2586 | + **expected_args) |
2587 | + |
2588 | + |
2589 | +class TestNodeGroupDelete(TestNodeGroup): |
2590 | + |
2591 | + def setUp(self): |
2592 | + super(TestNodeGroupDelete, self).setUp() |
2593 | + |
2594 | + self.ng_mock.delete = mock.Mock() |
2595 | + self.ng_mock.delete.return_value = None |
2596 | + |
2597 | + # Get the command object to test |
2598 | + self.cmd = osc_nodegroups.DeleteNodeGroup(self.app, None) |
2599 | + |
2600 | + def test_nodegroup_delete_one(self): |
2601 | + arglist = ['foo', 'fake-nodegroup'] |
2602 | + verifylist = [ |
2603 | + ('cluster', 'foo'), |
2604 | + ('nodegroup', ['fake-nodegroup']) |
2605 | + ] |
2606 | + |
2607 | + parsed_args = self.check_parser(self.cmd, arglist, verifylist) |
2608 | + |
2609 | + self.cmd.take_action(parsed_args) |
2610 | + self.ng_mock.delete.assert_called_with('foo', 'fake-nodegroup') |
2611 | + |
2612 | + def test_nodegroup_delete_multiple(self): |
2613 | + arglist = ['foo', 'fake-nodegroup1', 'fake-nodegroup2'] |
2614 | + verifylist = [ |
2615 | + ('cluster', 'foo'), |
2616 | + ('nodegroup', ['fake-nodegroup1', 'fake-nodegroup2']) |
2617 | + ] |
2618 | + |
2619 | + parsed_args = self.check_parser(self.cmd, arglist, verifylist) |
2620 | + |
2621 | + self.cmd.take_action(parsed_args) |
2622 | + self.ng_mock.delete.assert_has_calls( |
2623 | + [call('foo', 'fake-nodegroup1'), call('foo', 'fake-nodegroup2')] |
2624 | + ) |
2625 | + |
2626 | + def test_nodegroup_delete_no_args(self): |
2627 | + arglist = [] |
2628 | + verifylist = [ |
2629 | + ('cluster', ''), |
2630 | + ('nodegroup', []) |
2631 | + ] |
2632 | + |
2633 | + self.assertRaises(magnum_fakes.MagnumParseException, |
2634 | + self.check_parser, self.cmd, arglist, verifylist) |
2635 | + |
2636 | + |
2637 | +class TestNodeGroupUpdate(TestNodeGroup): |
2638 | + |
2639 | + def setUp(self): |
2640 | + super(TestNodeGroupUpdate, self).setUp() |
2641 | + |
2642 | + self.ng_mock.update = mock.Mock() |
2643 | + self.ng_mock.update.return_value = None |
2644 | + |
2645 | + # Get the command object to test |
2646 | + self.cmd = osc_nodegroups.UpdateNodeGroup(self.app, None) |
2647 | + |
2648 | + def test_nodegroup_update_pass(self): |
2649 | + arglist = ['foo', 'ng1', 'remove', 'bar'] |
2650 | + verifylist = [ |
2651 | + ('cluster', 'foo'), |
2652 | + ('nodegroup', 'ng1'), |
2653 | + ('op', 'remove'), |
2654 | + ('attributes', [['bar']]) |
2655 | + ] |
2656 | + parsed_args = self.check_parser(self.cmd, arglist, verifylist) |
2657 | + |
2658 | + self.cmd.take_action(parsed_args) |
2659 | + self.ng_mock.update.assert_called_with( |
2660 | + 'foo', 'ng1', |
2661 | + [{'op': 'remove', 'path': '/bar'}] |
2662 | + ) |
2663 | + |
2664 | + def test_nodegroup_update_bad_op(self): |
2665 | + arglist = ['cluster', 'ng1', 'foo', 'bar'] |
2666 | + verifylist = [ |
2667 | + ('cluster', 'cluster'), |
2668 | + ('nodegroup', 'ng1'), |
2669 | + ('op', 'foo'), |
2670 | + ('attributes', ['bar']) |
2671 | + ] |
2672 | + |
2673 | + self.assertRaises(magnum_fakes.MagnumParseException, |
2674 | + self.check_parser, self.cmd, arglist, verifylist) |
2675 | + |
2676 | + |
2677 | +class TestNodeGroupShow(TestNodeGroup): |
2678 | + |
2679 | + def setUp(self): |
2680 | + super(TestNodeGroupShow, self).setUp() |
2681 | + |
2682 | + self.nodegroup = magnum_fakes.FakeNodeGroup.create_one_nodegroup() |
2683 | + self.ng_mock.get = mock.Mock() |
2684 | + self.ng_mock.get.return_value = self.nodegroup |
2685 | + |
2686 | + self.data = tuple(map(lambda x: getattr(self.nodegroup, x), |
2687 | + osc_nodegroups.NODEGROUP_ATTRIBUTES)) |
2688 | + |
2689 | + # Get the command object to test |
2690 | + self.cmd = osc_nodegroups.ShowNodeGroup(self.app, None) |
2691 | + |
2692 | + def test_nodegroup_show_pass(self): |
2693 | + arglist = ['fake-cluster', 'fake-nodegroup'] |
2694 | + verifylist = [ |
2695 | + ('cluster', 'fake-cluster'), |
2696 | + ('nodegroup', 'fake-nodegroup') |
2697 | + ] |
2698 | + |
2699 | + parsed_args = self.check_parser(self.cmd, arglist, verifylist) |
2700 | + |
2701 | + columns, data = self.cmd.take_action(parsed_args) |
2702 | + self.ng_mock.get.assert_called_with( |
2703 | + 'fake-cluster', 'fake-nodegroup') |
2704 | + self.assertEqual(osc_nodegroups.NODEGROUP_ATTRIBUTES, columns) |
2705 | + self.assertEqual(self.data, data) |
2706 | + |
2707 | + def test_nodegroup_show_no_nodegroup_fail(self): |
2708 | + arglist = ['fake-cluster'] |
2709 | + verifylist = [ |
2710 | + ('cluster', 'fake-cluster'), |
2711 | + ('nodegroup', '') |
2712 | + ] |
2713 | + |
2714 | + self.assertRaises(magnum_fakes.MagnumParseException, |
2715 | + self.check_parser, self.cmd, arglist, verifylist) |
2716 | + |
2717 | + def test_nodegroup_show_no_args(self): |
2718 | + arglist = [] |
2719 | + verifylist = [ |
2720 | + ('cluster', ''), |
2721 | + ('nodegroup', '') |
2722 | + ] |
2723 | + |
2724 | + self.assertRaises(magnum_fakes.MagnumParseException, |
2725 | + self.check_parser, self.cmd, arglist, verifylist) |
2726 | + |
2727 | + |
2728 | +class TestNodeGroupList(TestNodeGroup): |
2729 | + |
2730 | + nodegroup = magnum_fakes.FakeNodeGroup.create_one_nodegroup() |
2731 | + |
2732 | + columns = ['uuid', 'name', 'flavor_id', 'image_id', 'node_count', |
2733 | + 'status', 'role'] |
2734 | + |
2735 | + datalist = ( |
2736 | + ( |
2737 | + nodegroup.uuid, |
2738 | + nodegroup.name, |
2739 | + nodegroup.flavor_id, |
2740 | + nodegroup.image_id, |
2741 | + nodegroup.node_count, |
2742 | + nodegroup.status, |
2743 | + nodegroup.role, |
2744 | + ), |
2745 | + ) |
2746 | + |
2747 | + def setUp(self): |
2748 | + super(TestNodeGroupList, self).setUp() |
2749 | + self.ng_mock.list = mock.Mock() |
2750 | + self.ng_mock.list.return_value = [self.nodegroup] |
2751 | + |
2752 | + # Get the command object to test |
2753 | + self.cmd = osc_nodegroups.ListNodeGroup(self.app, None) |
2754 | + |
2755 | + def test_nodegroup_list_no_options(self): |
2756 | + arglist = [] |
2757 | + verifylist = [ |
2758 | + ('cluster', ''), |
2759 | + ('limit', None), |
2760 | + ('sort_key', None), |
2761 | + ('sort_dir', None), |
2762 | + ] |
2763 | + self.assertRaises(magnum_fakes.MagnumParseException, |
2764 | + self.check_parser, self.cmd, arglist, verifylist) |
2765 | + |
2766 | + def test_nodegroup_list_ok(self): |
2767 | + arglist = ['fake-cluster'] |
2768 | + verifylist = [ |
2769 | + ('cluster', 'fake-cluster'), |
2770 | + ('limit', None), |
2771 | + ('sort_key', None), |
2772 | + ('sort_dir', None), |
2773 | + ] |
2774 | + parsed_args = self.check_parser(self.cmd, arglist, verifylist) |
2775 | + |
2776 | + columns, data = self.cmd.take_action(parsed_args) |
2777 | + self.ng_mock.list.assert_called_with( |
2778 | + 'fake-cluster', |
2779 | + limit=None, |
2780 | + sort_dir=None, |
2781 | + sort_key=None, |
2782 | + role=None, |
2783 | + ) |
2784 | + self.assertEqual(self.columns, columns) |
2785 | + self.assertEqual(self.datalist, tuple(data)) |
2786 | + |
2787 | + def test_nodegroup_list_options(self): |
2788 | + arglist = [ |
2789 | + 'fake-cluster', |
2790 | + '--limit', '1', |
2791 | + '--sort-key', 'key', |
2792 | + '--sort-dir', 'asc' |
2793 | + ] |
2794 | + verifylist = [ |
2795 | + ('cluster', 'fake-cluster'), |
2796 | + ('limit', 1), |
2797 | + ('sort_key', 'key'), |
2798 | + ('sort_dir', 'asc') |
2799 | + ] |
2800 | + parsed_args = self.check_parser(self.cmd, arglist, verifylist) |
2801 | + |
2802 | + self.cmd.take_action(parsed_args) |
2803 | + self.ng_mock.list.assert_called_with( |
2804 | + 'fake-cluster', |
2805 | + limit=1, |
2806 | + sort_dir='asc', |
2807 | + sort_key='key', |
2808 | + role=None |
2809 | + ) |
2810 | diff --git a/magnumclient/tests/test_httpclient.py b/magnumclient/tests/test_httpclient.py |
2811 | index 205ff14..f045c9c 100644 |
2812 | --- a/magnumclient/tests/test_httpclient.py |
2813 | +++ b/magnumclient/tests/test_httpclient.py |
2814 | @@ -13,9 +13,8 @@ |
2815 | # License for the specific language governing permissions and limitations |
2816 | # under the License. |
2817 | |
2818 | -import json |
2819 | - |
2820 | import mock |
2821 | +from oslo_serialization import jsonutils |
2822 | import six |
2823 | import socket |
2824 | |
2825 | @@ -37,7 +36,7 @@ def _get_error_body(faultstring=None, debuginfo=None, err_type=NORMAL_ERROR): |
2826 | 'faultstring': faultstring, |
2827 | 'debuginfo': debuginfo |
2828 | } |
2829 | - raw_error_body = json.dumps(error_body) |
2830 | + raw_error_body = jsonutils.dumps(error_body) |
2831 | body = {'error_message': raw_error_body} |
2832 | elif err_type == ERROR_DICT: |
2833 | body = {'error': {'title': faultstring, 'message': debuginfo}} |
2834 | @@ -47,7 +46,7 @@ def _get_error_body(faultstring=None, debuginfo=None, err_type=NORMAL_ERROR): |
2835 | elif err_type == ERROR_LIST_WITH_DESC: |
2836 | main_body = {'title': faultstring, 'description': debuginfo} |
2837 | body = {'errors': [main_body]} |
2838 | - raw_body = json.dumps(body) |
2839 | + raw_body = jsonutils.dumps(body) |
2840 | return raw_body |
2841 | |
2842 | |
2843 | @@ -347,7 +346,7 @@ class HttpClientTest(utils.BaseTestCase): |
2844 | resp, body = client.json_request('GET', '/v1/resources') |
2845 | |
2846 | self.assertEqual(resp, fake_resp) |
2847 | - self.assertEqual(json.dumps(body), err) |
2848 | + self.assertEqual(jsonutils.dumps(body), err) |
2849 | |
2850 | def test_raw_request(self): |
2851 | fake_resp = utils.FakeResponse( |
2852 | diff --git a/magnumclient/tests/test_utils.py b/magnumclient/tests/test_utils.py |
2853 | index 93a96fe..831fea4 100644 |
2854 | --- a/magnumclient/tests/test_utils.py |
2855 | +++ b/magnumclient/tests/test_utils.py |
2856 | @@ -17,7 +17,7 @@ |
2857 | |
2858 | import collections |
2859 | import mock |
2860 | -from oslo_serialization import jsonutils as json |
2861 | +from oslo_serialization import jsonutils |
2862 | import six |
2863 | import six.moves.builtins as __builtin__ |
2864 | import tempfile |
2865 | @@ -123,7 +123,7 @@ class FormatLabelsTest(test_utils.BaseTestCase): |
2866 | self.assertEqual({}, utils.format_labels(None)) |
2867 | |
2868 | def test_format_labels(self): |
2869 | - l = utils.format_labels([ |
2870 | + la = utils.format_labels([ |
2871 | 'K1=V1,K2=V2,' |
2872 | 'K3=V3,K4=V4,' |
2873 | 'K5=V5']) |
2874 | @@ -132,10 +132,10 @@ class FormatLabelsTest(test_utils.BaseTestCase): |
2875 | 'K3': 'V3', |
2876 | 'K4': 'V4', |
2877 | 'K5': 'V5' |
2878 | - }, l) |
2879 | + }, la) |
2880 | |
2881 | def test_format_labels_semicolon(self): |
2882 | - l = utils.format_labels([ |
2883 | + la = utils.format_labels([ |
2884 | 'K1=V1;K2=V2;' |
2885 | 'K3=V3;K4=V4;' |
2886 | 'K5=V5']) |
2887 | @@ -144,10 +144,10 @@ class FormatLabelsTest(test_utils.BaseTestCase): |
2888 | 'K3': 'V3', |
2889 | 'K4': 'V4', |
2890 | 'K5': 'V5' |
2891 | - }, l) |
2892 | + }, la) |
2893 | |
2894 | def test_format_labels_mix_commas_semicolon(self): |
2895 | - l = utils.format_labels([ |
2896 | + la = utils.format_labels([ |
2897 | 'K1=V1,K2=V2,' |
2898 | 'K3=V3;K4=V4,' |
2899 | 'K5=V5']) |
2900 | @@ -156,10 +156,10 @@ class FormatLabelsTest(test_utils.BaseTestCase): |
2901 | 'K3': 'V3', |
2902 | 'K4': 'V4', |
2903 | 'K5': 'V5' |
2904 | - }, l) |
2905 | + }, la) |
2906 | |
2907 | def test_format_labels_split(self): |
2908 | - l = utils.format_labels([ |
2909 | + la = utils.format_labels([ |
2910 | 'K1=V1,' |
2911 | 'K2=V22222222222222222222222222222' |
2912 | '222222222222222222222222222,' |
2913 | @@ -167,10 +167,10 @@ class FormatLabelsTest(test_utils.BaseTestCase): |
2914 | self.assertEqual({'K1': 'V1', |
2915 | 'K2': 'V22222222222222222222222222222' |
2916 | '222222222222222222222222222', |
2917 | - 'K3': '3.3.3.3'}, l) |
2918 | + 'K3': '3.3.3.3'}, la) |
2919 | |
2920 | def test_format_labels_multiple(self): |
2921 | - l = utils.format_labels([ |
2922 | + la = utils.format_labels([ |
2923 | 'K1=V1', |
2924 | 'K2=V22222222222222222222222222222' |
2925 | '222222222222222222222222222', |
2926 | @@ -178,35 +178,35 @@ class FormatLabelsTest(test_utils.BaseTestCase): |
2927 | self.assertEqual({'K1': 'V1', |
2928 | 'K2': 'V22222222222222222222222222222' |
2929 | '222222222222222222222222222', |
2930 | - 'K3': '3.3.3.3'}, l) |
2931 | + 'K3': '3.3.3.3'}, la) |
2932 | |
2933 | def test_format_labels_multiple_colon_values(self): |
2934 | - l = utils.format_labels([ |
2935 | + la = utils.format_labels([ |
2936 | 'K1=V1', |
2937 | 'K2=V2,V22,V222,V2222', |
2938 | 'K3=3.3.3.3']) |
2939 | self.assertEqual({'K1': 'V1', |
2940 | 'K2': 'V2,V22,V222,V2222', |
2941 | - 'K3': '3.3.3.3'}, l) |
2942 | + 'K3': '3.3.3.3'}, la) |
2943 | |
2944 | def test_format_labels_parse_comma_false(self): |
2945 | - l = utils.format_labels( |
2946 | + la = utils.format_labels( |
2947 | ['K1=V1,K2=2.2.2.2,K=V'], |
2948 | parse_comma=False) |
2949 | - self.assertEqual({'K1': 'V1,K2=2.2.2.2,K=V'}, l) |
2950 | + self.assertEqual({'K1': 'V1,K2=2.2.2.2,K=V'}, la) |
2951 | |
2952 | def test_format_labels_multiple_values_per_labels(self): |
2953 | - l = utils.format_labels([ |
2954 | + la = utils.format_labels([ |
2955 | 'K1=V1', |
2956 | 'K1=V2']) |
2957 | - self.assertEqual({'K1': 'V1,V2'}, l) |
2958 | + self.assertEqual({'K1': 'V1,V2'}, la) |
2959 | |
2960 | def test_format_label_special_label(self): |
2961 | labels = ['K1=V1,K22.2.2.2'] |
2962 | - l = utils.format_labels( |
2963 | + la = utils.format_labels( |
2964 | labels, |
2965 | parse_comma=True) |
2966 | - self.assertEqual({'K1': 'V1,K22.2.2.2'}, l) |
2967 | + self.assertEqual({'K1': 'V1,K22.2.2.2'}, la) |
2968 | |
2969 | def test_format_multiple_bad_label(self): |
2970 | labels = ['K1=V1', 'K22.2.2.2'] |
2971 | @@ -261,7 +261,7 @@ class HandleJsonFromFileTest(test_utils.BaseTestCase): |
2972 | f.flush() |
2973 | steps = utils.handle_json_from_file(f.name) |
2974 | |
2975 | - self.assertEqual(json.loads(contents), steps) |
2976 | + self.assertEqual(jsonutils.loads(contents), steps) |
2977 | |
2978 | @mock.patch.object(__builtin__, 'open', autospec=True) |
2979 | def test_handle_json_from_file_open_fail(self, mock_open): |
2980 | diff --git a/magnumclient/tests/utils.py b/magnumclient/tests/utils.py |
2981 | index c155ae0..1562671 100644 |
2982 | --- a/magnumclient/tests/utils.py |
2983 | +++ b/magnumclient/tests/utils.py |
2984 | @@ -15,8 +15,8 @@ |
2985 | |
2986 | import copy |
2987 | import datetime |
2988 | -import json as jsonlib |
2989 | import os |
2990 | +from oslo_serialization import jsonutils |
2991 | import sys |
2992 | |
2993 | import fixtures |
2994 | @@ -95,7 +95,7 @@ class FakeResponse(object): |
2995 | self.reason = reason |
2996 | |
2997 | def __getitem__(self, key): |
2998 | - if key is 'location': |
2999 | + if key == 'location': |
3000 | return 'fake_url' |
3001 | else: |
3002 | return None |
3003 | @@ -182,7 +182,7 @@ class FakeSessionResponse(object): |
3004 | |
3005 | def json(self): |
3006 | if self.content is not None: |
3007 | - return jsonlib.loads(self.content) |
3008 | + return jsonutils.loads(self.content) |
3009 | else: |
3010 | return {} |
3011 | |
3012 | diff --git a/magnumclient/tests/v1/shell_test_base.py b/magnumclient/tests/v1/shell_test_base.py |
3013 | index 89f6195..b165298 100644 |
3014 | --- a/magnumclient/tests/v1/shell_test_base.py |
3015 | +++ b/magnumclient/tests/v1/shell_test_base.py |
3016 | @@ -28,56 +28,56 @@ FAKE_ENV = {'OS_USERNAME': 'username', |
3017 | |
3018 | class TestCommandLineArgument(utils.TestCase): |
3019 | _unrecognized_arg_error = [ |
3020 | - '.*?^usage: ', |
3021 | - '.*?^error: unrecognized arguments:', |
3022 | - ".*?^Try 'magnum help ' for more information.", |
3023 | + r'.*?^usage: ', |
3024 | + r'.*?^error: unrecognized arguments:', |
3025 | + r".*?^Try 'magnum help ' for more information.", |
3026 | ] |
3027 | |
3028 | _mandatory_group_arg_error = [ |
3029 | - '.*?^usage: ', |
3030 | - '.*?^error: one of the arguments', |
3031 | - ".*?^Try 'magnum help ", |
3032 | + r'.*?^usage: ', |
3033 | + r'.*?^error: one of the arguments', |
3034 | + r".*?^Try 'magnum help ", |
3035 | ] |
3036 | |
3037 | _too_many_group_arg_error = [ |
3038 | - '.*?^usage: ', |
3039 | - '.*?^error: (argument \-\-[a-z\-]*: not allowed with argument )', |
3040 | - ".*?^Try 'magnum help ", |
3041 | + r'.*?^usage: ', |
3042 | + r'.*?^error: (argument \-\-[a-z\-]*: not allowed with argument )', |
3043 | + r".*?^Try 'magnum help ", |
3044 | ] |
3045 | |
3046 | _mandatory_arg_error = [ |
3047 | - '.*?^usage: ', |
3048 | - '.*?^error: (the following arguments|argument)', |
3049 | - ".*?^Try 'magnum help ", |
3050 | - ] |
3051 | + r'.*?^usage: ', |
3052 | + r'.*?^error: (the following arguments|argument)', |
3053 | + r".*?^Try 'magnum help ", |
3054 | + ] |
3055 | |
3056 | _duplicate_arg_error = [ |
3057 | - '.*?^usage: ', |
3058 | - '.*?^error: (Duplicate "<.*>" arguments:)', |
3059 | - ".*?^Try 'magnum help ", |
3060 | - ] |
3061 | + r'.*?^usage: ', |
3062 | + r'.*?^error: (Duplicate "<.*>" arguments:)', |
3063 | + r".*?^Try 'magnum help ", |
3064 | + ] |
3065 | |
3066 | _deprecated_warning = [ |
3067 | - '.*(WARNING: The \-\-[a-z\-]* parameter is deprecated)+', |
3068 | - ('.*(Use the [\<\-a-z\-\>]* (positional )*parameter to avoid seeing ' |
3069 | + r'.*(WARNING: The \-\-[a-z\-]* parameter is deprecated)+', |
3070 | + (r'.*(Use the [\<\-a-z\-\>]* (positional )*parameter to avoid seeing ' |
3071 | 'this message)+') |
3072 | ] |
3073 | |
3074 | _few_argument_error = [ |
3075 | - '.*?^usage: magnum ', |
3076 | - '.*?^error: (the following arguments|too few arguments)', |
3077 | - ".*?^Try 'magnum help ", |
3078 | - ] |
3079 | + r'.*?^usage: magnum ', |
3080 | + r'.*?^error: (the following arguments|too few arguments)', |
3081 | + r".*?^Try 'magnum help ", |
3082 | + ] |
3083 | |
3084 | _invalid_value_error = [ |
3085 | - '.*?^usage: ', |
3086 | - '.*?^error: argument .*: invalid .* value:', |
3087 | - ".*?^Try 'magnum help ", |
3088 | - ] |
3089 | + r'.*?^usage: ', |
3090 | + r'.*?^error: argument .*: invalid .* value:', |
3091 | + r".*?^Try 'magnum help ", |
3092 | + ] |
3093 | |
3094 | _bay_status_error = [ |
3095 | - '.*?^Bay status for', |
3096 | - ] |
3097 | + r'.*?^Bay status for', |
3098 | + ] |
3099 | |
3100 | def setUp(self): |
3101 | super(TestCommandLineArgument, self).setUp() |
3102 | diff --git a/magnumclient/tests/v1/test_bays_shell.py b/magnumclient/tests/v1/test_bays_shell.py |
3103 | index e9a3a47..60f512f 100644 |
3104 | --- a/magnumclient/tests/v1/test_bays_shell.py |
3105 | +++ b/magnumclient/tests/v1/test_bays_shell.py |
3106 | @@ -329,15 +329,6 @@ class ShellTest(shell_test_base.TestCommandLineArgument): |
3107 | self._test_arg_success('bay-config --dir /tmp --force xxx') |
3108 | mock_bay.assert_called_with('xxx') |
3109 | |
3110 | - @mock.patch('magnumclient.v1.baymodels.BayModelManager.get') |
3111 | - @mock.patch('magnumclient.v1.bays.BayManager.get') |
3112 | - def test_bay_config_failure_wrong_status(self, mock_bay, mock_baymodel): |
3113 | - mock_bay.return_value = FakeBay(status='CREATE_IN_PROGRESS') |
3114 | - self.assertRaises(exceptions.CommandError, |
3115 | - self._test_arg_failure, |
3116 | - 'bay-config xxx', |
3117 | - ['.*?^Bay in status: ']) |
3118 | - |
3119 | @mock.patch('magnumclient.v1.bays.BayManager.get') |
3120 | def test_bay_config_failure_no_arg(self, mock_bay): |
3121 | self._test_arg_failure('bay-config', self._few_argument_error) |
3122 | diff --git a/magnumclient/tests/v1/test_clusters.py b/magnumclient/tests/v1/test_clusters.py |
3123 | index dc1a100..ee47fc0 100644 |
3124 | --- a/magnumclient/tests/v1/test_clusters.py |
3125 | +++ b/magnumclient/tests/v1/test_clusters.py |
3126 | @@ -54,6 +54,14 @@ UPDATED_CLUSTER = copy.deepcopy(CLUSTER1) |
3127 | NEW_NAME = 'newcluster' |
3128 | UPDATED_CLUSTER['name'] = NEW_NAME |
3129 | |
3130 | +RESIZED_CLUSTER = copy.deepcopy(CLUSTER1) |
3131 | +RESIZED_NODE_COUNT = 5 |
3132 | +UPDATED_CLUSTER['node_count'] = RESIZED_NODE_COUNT |
3133 | + |
3134 | +UPGRADED_CLUSTER = copy.deepcopy(CLUSTER1) |
3135 | +UPGRADED_TO_TEMPLATE = "eabbc463-0d3f-49dc-8519-cb6b59507bd6" |
3136 | +UPGRADED_CLUSTER['cluster_template_id'] = UPGRADED_TO_TEMPLATE |
3137 | + |
3138 | fake_responses = { |
3139 | '/v1/clusters': |
3140 | { |
3141 | @@ -145,6 +153,20 @@ fake_responses = { |
3142 | {'clusters': [CLUSTER2, CLUSTER1]}, |
3143 | ), |
3144 | }, |
3145 | + '/v1/clusters/%s/actions/resize' % CLUSTER1['uuid']: |
3146 | + { |
3147 | + 'POST': ( |
3148 | + {}, |
3149 | + UPDATED_CLUSTER |
3150 | + ), |
3151 | + }, |
3152 | + '/v1/clusters/%s/actions/upgrade' % CLUSTER1['uuid']: |
3153 | + { |
3154 | + 'POST': ( |
3155 | + {}, |
3156 | + UPGRADED_CLUSTER |
3157 | + ), |
3158 | + } |
3159 | } |
3160 | |
3161 | |
3162 | @@ -355,3 +377,24 @@ class ClusterManagerTest(testtools.TestCase): |
3163 | ] |
3164 | self.assertEqual(expect, self.api.calls) |
3165 | self.assertEqual(NEW_NAME, cluster.name) |
3166 | + |
3167 | + def test_cluster_resize(self): |
3168 | + body = {'node_count': RESIZED_NODE_COUNT} |
3169 | + cluster = self.mgr.resize(CLUSTER1["uuid"], **body) |
3170 | + expect = [ |
3171 | + ('POST', '/v1/clusters/%s/actions/resize' % CLUSTER1['uuid'], |
3172 | + {}, body), |
3173 | + ] |
3174 | + self.assertEqual(expect, self.api.calls) |
3175 | + self.assertEqual(RESIZED_NODE_COUNT, cluster.node_count) |
3176 | + |
3177 | + def test_cluster_upgrade(self): |
3178 | + body = {'cluster_template': UPGRADED_TO_TEMPLATE, |
3179 | + 'max_batch_size': 1} |
3180 | + cluster = self.mgr.upgrade(CLUSTER1["uuid"], **body) |
3181 | + expect = [ |
3182 | + ('POST', '/v1/clusters/%s/actions/upgrade' % CLUSTER1['uuid'], |
3183 | + {}, body), |
3184 | + ] |
3185 | + self.assertEqual(expect, self.api.calls) |
3186 | + self.assertEqual(UPGRADED_TO_TEMPLATE, cluster.cluster_template_id) |
3187 | diff --git a/magnumclient/tests/v1/test_clusters_shell.py b/magnumclient/tests/v1/test_clusters_shell.py |
3188 | index 244132c..43d81d1 100644 |
3189 | --- a/magnumclient/tests/v1/test_clusters_shell.py |
3190 | +++ b/magnumclient/tests/v1/test_clusters_shell.py |
3191 | @@ -447,17 +447,6 @@ class ShellTest(shell_test_base.TestCommandLineArgument): |
3192 | self._test_arg_success('cluster-config --dir /tmp --force xxx') |
3193 | mock_cluster.assert_called_with('xxx') |
3194 | |
3195 | - @mock.patch('magnumclient.v1.cluster_templates.ClusterTemplateManager.get') |
3196 | - @mock.patch('magnumclient.v1.clusters.ClusterManager.get') |
3197 | - def test_cluster_config_failure_wrong_status(self, |
3198 | - mock_cluster, |
3199 | - mock_clustertemplate): |
3200 | - mock_cluster.return_value = FakeCluster(status='CREATE_IN_PROGRESS') |
3201 | - self.assertRaises(exceptions.CommandError, |
3202 | - self._test_arg_failure, |
3203 | - 'cluster-config xxx', |
3204 | - ['.*?^Cluster in status: ']) |
3205 | - |
3206 | @mock.patch('magnumclient.v1.clusters.ClusterManager.get') |
3207 | def test_cluster_config_failure_no_arg(self, mock_cluster): |
3208 | self._test_arg_failure('cluster-config', self._few_argument_error) |
3209 | diff --git a/magnumclient/tests/v1/test_clustertemplates.py b/magnumclient/tests/v1/test_clustertemplates.py |
3210 | index 0471b1a..2beb78e 100644 |
3211 | --- a/magnumclient/tests/v1/test_clustertemplates.py |
3212 | +++ b/magnumclient/tests/v1/test_clustertemplates.py |
3213 | @@ -46,7 +46,8 @@ CLUSTERTEMPLATE1 = { |
3214 | 'public': False, |
3215 | 'registry_enabled': False, |
3216 | 'master_lb_enabled': True, |
3217 | - 'floating_ip_enabled': True |
3218 | + 'floating_ip_enabled': True, |
3219 | + 'hidden': False |
3220 | } |
3221 | |
3222 | CLUSTERTEMPLATE2 = { |
3223 | @@ -309,6 +310,8 @@ class ClusterTemplateManagerTest(testtools.TestCase): |
3224 | cluster_template.master_lb_enabled) |
3225 | self.assertEqual(CLUSTERTEMPLATE1['floating_ip_enabled'], |
3226 | cluster_template.floating_ip_enabled) |
3227 | + self.assertEqual(CLUSTERTEMPLATE1['hidden'], |
3228 | + cluster_template.hidden) |
3229 | |
3230 | def test_clustertemplate_show_by_name(self): |
3231 | cluster_template = self.mgr.get(CLUSTERTEMPLATE1['name']) |
3232 | @@ -355,6 +358,8 @@ class ClusterTemplateManagerTest(testtools.TestCase): |
3233 | cluster_template.master_lb_enabled) |
3234 | self.assertEqual(CLUSTERTEMPLATE1['floating_ip_enabled'], |
3235 | cluster_template.floating_ip_enabled) |
3236 | + self.assertEqual(CLUSTERTEMPLATE1['hidden'], |
3237 | + cluster_template.hidden) |
3238 | |
3239 | def test_clustertemplate_create(self): |
3240 | cluster_template = self.mgr.create(**CREATE_CLUSTERTEMPLATE) |
3241 | diff --git a/magnumclient/tests/v1/test_clustertemplates_shell.py b/magnumclient/tests/v1/test_clustertemplates_shell.py |
3242 | index 67bce87..ca17a4a 100644 |
3243 | --- a/magnumclient/tests/v1/test_clustertemplates_shell.py |
3244 | +++ b/magnumclient/tests/v1/test_clustertemplates_shell.py |
3245 | @@ -32,6 +32,7 @@ class FakeClusterTemplate(ClusterTemplate): |
3246 | self.coe = kwargs.get('coe', 'x') |
3247 | self.public = kwargs.get('public', False) |
3248 | self.name = kwargs.get('name', 'x') |
3249 | + self.hidden = kwargs.get('hidden', False) |
3250 | |
3251 | |
3252 | class ShellTest(shell_test_base.TestCommandLineArgument): |
3253 | @@ -58,7 +59,7 @@ class ShellTest(shell_test_base.TestCommandLineArgument): |
3254 | tls_disabled=False, public=False, |
3255 | master_lb_enabled=False, server_type='vm', |
3256 | registry_enabled=False, |
3257 | - insecure_registry=None): |
3258 | + insecure_registry=None, hidden=False): |
3259 | |
3260 | expected_args = {} |
3261 | expected_args['image_id'] = image_id |
3262 | @@ -85,6 +86,7 @@ class ShellTest(shell_test_base.TestCommandLineArgument): |
3263 | expected_args['server_type'] = server_type |
3264 | expected_args['registry_enabled'] = registry_enabled |
3265 | expected_args['insecure_registry'] = insecure_registry |
3266 | + expected_args['hidden'] = hidden |
3267 | |
3268 | return expected_args |
3269 | |
3270 | diff --git a/magnumclient/tests/v1/test_nodegroups.py b/magnumclient/tests/v1/test_nodegroups.py |
3271 | new file mode 100644 |
3272 | index 0000000..40cbcf6 |
3273 | --- /dev/null |
3274 | +++ b/magnumclient/tests/v1/test_nodegroups.py |
3275 | @@ -0,0 +1,333 @@ |
3276 | +# Copyright (c) 2018 European Organization for Nuclear Research. |
3277 | +# All Rights Reserved. |
3278 | +# |
3279 | +# Licensed under the Apache License, Version 2.0 (the "License"); you may |
3280 | +# not use this file except in compliance with the License. You may obtain |
3281 | +# a copy of the License at |
3282 | +# |
3283 | +# http://www.apache.org/licenses/LICENSE-2.0 |
3284 | +# |
3285 | +# Unless required by applicable law or agreed to in writing, software |
3286 | +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
3287 | +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
3288 | +# License for the specific language governing permissions and limitations |
3289 | +# under the License. |
3290 | + |
3291 | +import copy |
3292 | + |
3293 | +import testtools |
3294 | +from testtools import matchers |
3295 | + |
3296 | +from magnumclient import exceptions |
3297 | +from magnumclient.tests import utils |
3298 | +from magnumclient.v1 import nodegroups |
3299 | + |
3300 | + |
3301 | +NODEGROUP1 = { |
3302 | + 'id': 123, |
3303 | + 'uuid': '66666666-7777-8888-9999-000000000001', |
3304 | + 'cluster_id': '66666666-7777-8888-9999-000000000000', |
3305 | + 'name': 'test-worker', |
3306 | + 'node_addresses': ['172.17.2.3'], |
3307 | + 'node_count': 2, |
3308 | + 'project_id': 'fake_project', |
3309 | + 'labels': {}, |
3310 | + 'flavor_id': 'fake_flavor_1', |
3311 | + 'image_id': 'fake_image', |
3312 | + 'is_default': True, |
3313 | + 'role': 'worker', |
3314 | + 'max_node_count': 10, |
3315 | + 'min_node_count': 1 |
3316 | +} |
3317 | +NODEGROUP2 = { |
3318 | + 'id': 124, |
3319 | + 'uuid': '66666666-7777-8888-9999-000000000002', |
3320 | + 'cluster_id': '66666666-7777-8888-9999-000000000000', |
3321 | + 'name': 'test-master', |
3322 | + 'node_addresses': ['172.17.2.4'], |
3323 | + 'node_count': 2, |
3324 | + 'project_id': 'fake_project', |
3325 | + 'labels': {}, |
3326 | + 'flavor_id': 'fake_flavor_1', |
3327 | + 'image_id': 'fake_image', |
3328 | + 'is_default': True, |
3329 | + 'role': 'master', |
3330 | + 'max_node_count': 10, |
3331 | + 'min_node_count': 1 |
3332 | +} |
3333 | + |
3334 | +CREATE_NODEGROUP = copy.deepcopy(NODEGROUP1) |
3335 | +del CREATE_NODEGROUP['id'] |
3336 | +del CREATE_NODEGROUP['uuid'] |
3337 | +del CREATE_NODEGROUP['node_addresses'] |
3338 | +del CREATE_NODEGROUP['is_default'] |
3339 | +del CREATE_NODEGROUP['cluster_id'] |
3340 | + |
3341 | +UPDATED_NODEGROUP = copy.deepcopy(NODEGROUP1) |
3342 | +NEW_NODE_COUNT = 9 |
3343 | +UPDATED_NODEGROUP['node_count'] = NEW_NODE_COUNT |
3344 | + |
3345 | + |
3346 | +fake_responses = { |
3347 | + '/v1/clusters/test/nodegroups/': |
3348 | + { |
3349 | + 'GET': ( |
3350 | + {}, |
3351 | + {'nodegroups': [NODEGROUP1, NODEGROUP2]}, |
3352 | + ), |
3353 | + 'POST': ( |
3354 | + {}, |
3355 | + CREATE_NODEGROUP, |
3356 | + ), |
3357 | + }, |
3358 | + '/v1/clusters/test/nodegroups/%s' % NODEGROUP1['id']: |
3359 | + { |
3360 | + 'GET': ( |
3361 | + {}, |
3362 | + NODEGROUP1 |
3363 | + ), |
3364 | + 'DELETE': ( |
3365 | + {}, |
3366 | + None, |
3367 | + ), |
3368 | + 'PATCH': ( |
3369 | + {}, |
3370 | + UPDATED_NODEGROUP, |
3371 | + ), |
3372 | + }, |
3373 | + '/v1/clusters/test/nodegroups/%s/?rollback=True' % NODEGROUP1['id']: |
3374 | + { |
3375 | + 'PATCH': ( |
3376 | + {}, |
3377 | + UPDATED_NODEGROUP, |
3378 | + ), |
3379 | + }, |
3380 | + '/v1/clusters/test/nodegroups/%s' % NODEGROUP1['name']: |
3381 | + { |
3382 | + 'GET': ( |
3383 | + {}, |
3384 | + NODEGROUP1 |
3385 | + ), |
3386 | + 'DELETE': ( |
3387 | + {}, |
3388 | + None, |
3389 | + ), |
3390 | + 'PATCH': ( |
3391 | + {}, |
3392 | + UPDATED_NODEGROUP, |
3393 | + ), |
3394 | + }, |
3395 | + '/v1/clusters/test/nodegroups/?limit=2': |
3396 | + { |
3397 | + 'GET': ( |
3398 | + {}, |
3399 | + {'nodegroups': [NODEGROUP1, NODEGROUP2]}, |
3400 | + ), |
3401 | + }, |
3402 | + '/v1/clusters/test/nodegroups/?marker=%s' % NODEGROUP2['uuid']: |
3403 | + { |
3404 | + 'GET': ( |
3405 | + {}, |
3406 | + {'nodegroups': [NODEGROUP1, NODEGROUP2]}, |
3407 | + ), |
3408 | + }, |
3409 | + '/v1/clusters/test/nodegroups/?limit=2&marker=%s' % NODEGROUP2['uuid']: |
3410 | + { |
3411 | + 'GET': ( |
3412 | + {}, |
3413 | + {'nodegroups': [NODEGROUP1, NODEGROUP2]}, |
3414 | + ), |
3415 | + }, |
3416 | + '/v1/clusters/test/nodegroups/?sort_dir=asc': |
3417 | + { |
3418 | + 'GET': ( |
3419 | + {}, |
3420 | + {'nodegroups': [NODEGROUP1, NODEGROUP2]}, |
3421 | + ), |
3422 | + }, |
3423 | + '/v1/clusters/test/nodegroups/?sort_key=uuid': |
3424 | + { |
3425 | + 'GET': ( |
3426 | + {}, |
3427 | + {'nodegroups': [NODEGROUP1, NODEGROUP2]}, |
3428 | + ), |
3429 | + }, |
3430 | + '/v1/clusters/test/nodegroups/?sort_key=uuid&sort_dir=desc': |
3431 | + { |
3432 | + 'GET': ( |
3433 | + {}, |
3434 | + {'nodegroups': [NODEGROUP2, NODEGROUP1]}, |
3435 | + ), |
3436 | + }, |
3437 | +} |
3438 | + |
3439 | + |
3440 | +class NodeGroupManagerTest(testtools.TestCase): |
3441 | + |
3442 | + def setUp(self): |
3443 | + super(NodeGroupManagerTest, self).setUp() |
3444 | + self.api = utils.FakeAPI(fake_responses) |
3445 | + self.mgr = nodegroups.NodeGroupManager(self.api) |
3446 | + self.cluster_id = 'test' |
3447 | + self.base_path = '/v1/clusters/test/nodegroups/' |
3448 | + |
3449 | + def test_nodegroup_list(self): |
3450 | + clusters = self.mgr.list(self.cluster_id) |
3451 | + expect = [ |
3452 | + ('GET', self.base_path, {}, None), |
3453 | + ] |
3454 | + self.assertEqual(expect, self.api.calls) |
3455 | + self.assertThat(clusters, matchers.HasLength(2)) |
3456 | + |
3457 | + def _test_nodegroup_list_with_filters(self, cluster_id, limit=None, |
3458 | + marker=None, sort_key=None, |
3459 | + sort_dir=None, detail=False, |
3460 | + expect=[]): |
3461 | + nodegroup_filter = self.mgr.list(cluster_id, |
3462 | + limit=limit, |
3463 | + marker=marker, |
3464 | + sort_key=sort_key, |
3465 | + sort_dir=sort_dir, |
3466 | + detail=detail) |
3467 | + self.assertEqual(expect, self.api.calls) |
3468 | + self.assertThat(nodegroup_filter, matchers.HasLength(2)) |
3469 | + |
3470 | + def test_nodegroup_list_with_limit(self): |
3471 | + expect = [ |
3472 | + ('GET', self.base_path + '?limit=2', {}, None), |
3473 | + ] |
3474 | + self._test_nodegroup_list_with_filters( |
3475 | + self.cluster_id, |
3476 | + limit=2, |
3477 | + expect=expect) |
3478 | + |
3479 | + def test_nodegroup_list_with_marker(self): |
3480 | + filter_ = '?marker=%s' % NODEGROUP2['uuid'] |
3481 | + expect = [ |
3482 | + ('GET', self.base_path + filter_, {}, None), |
3483 | + ] |
3484 | + self._test_nodegroup_list_with_filters( |
3485 | + self.cluster_id, |
3486 | + marker=NODEGROUP2['uuid'], |
3487 | + expect=expect) |
3488 | + |
3489 | + def test_nodegroup_list_with_marker_limit(self): |
3490 | + filter_ = '?limit=2&marker=%s' % NODEGROUP2['uuid'] |
3491 | + expect = [ |
3492 | + ('GET', self.base_path + filter_, {}, None), |
3493 | + ] |
3494 | + self._test_nodegroup_list_with_filters( |
3495 | + self.cluster_id, |
3496 | + limit=2, marker=NODEGROUP2['uuid'], |
3497 | + expect=expect) |
3498 | + |
3499 | + def test_nodegroup_list_with_sort_dir(self): |
3500 | + expect = [ |
3501 | + ('GET', '/v1/clusters/test/nodegroups/?sort_dir=asc', {}, None), |
3502 | + ] |
3503 | + self._test_nodegroup_list_with_filters( |
3504 | + self.cluster_id, |
3505 | + sort_dir='asc', |
3506 | + expect=expect) |
3507 | + |
3508 | + def test_nodegroup_list_with_sort_key(self): |
3509 | + expect = [ |
3510 | + ('GET', '/v1/clusters/test/nodegroups/?sort_key=uuid', {}, None), |
3511 | + ] |
3512 | + self._test_nodegroup_list_with_filters( |
3513 | + self.cluster_id, |
3514 | + sort_key='uuid', |
3515 | + expect=expect) |
3516 | + |
3517 | + def test_nodegroup_list_with_sort_key_dir(self): |
3518 | + expect = [ |
3519 | + ('GET', self.base_path + '?sort_key=uuid&sort_dir=desc', {}, None), |
3520 | + ] |
3521 | + self._test_nodegroup_list_with_filters( |
3522 | + self.cluster_id, |
3523 | + sort_key='uuid', sort_dir='desc', |
3524 | + expect=expect) |
3525 | + |
3526 | + def test_nodegroup_show_by_name(self): |
3527 | + nodegroup = self.mgr.get(self.cluster_id, NODEGROUP1['name']) |
3528 | + expect = [ |
3529 | + ('GET', self.base_path + '%s' % NODEGROUP1['name'], {}, None) |
3530 | + ] |
3531 | + self.assertEqual(expect, self.api.calls) |
3532 | + self.assertEqual(NODEGROUP1['name'], nodegroup.name) |
3533 | + |
3534 | + def test_nodegroup_show_by_id(self): |
3535 | + nodegroup = self.mgr.get(self.cluster_id, NODEGROUP1['id']) |
3536 | + expect = [ |
3537 | + ('GET', self.base_path + '%s' % NODEGROUP1['id'], {}, None) |
3538 | + ] |
3539 | + self.assertEqual(expect, self.api.calls) |
3540 | + self.assertEqual(NODEGROUP1['name'], nodegroup.name) |
3541 | + |
3542 | + def test_nodegroup_delete_by_id(self): |
3543 | + nodegroup = self.mgr.delete(self.cluster_id, NODEGROUP1['id']) |
3544 | + expect = [ |
3545 | + ('DELETE', self.base_path + '%s' % NODEGROUP1['id'], {}, None), |
3546 | + ] |
3547 | + self.assertEqual(expect, self.api.calls) |
3548 | + self.assertIsNone(nodegroup) |
3549 | + |
3550 | + def test_nodegroup_delete_by_name(self): |
3551 | + nodegroup = self.mgr.delete(self.cluster_id, NODEGROUP1['name']) |
3552 | + expect = [ |
3553 | + ('DELETE', self.base_path + '%s' % NODEGROUP1['name'], {}, None), |
3554 | + ] |
3555 | + self.assertEqual(expect, self.api.calls) |
3556 | + self.assertIsNone(nodegroup) |
3557 | + |
3558 | + def test_nodegroup_update(self): |
3559 | + patch = {'op': 'replace', |
3560 | + 'value': NEW_NODE_COUNT, |
3561 | + 'path': '/node_count'} |
3562 | + nodegroup = self.mgr.update(self.cluster_id, id=NODEGROUP1['id'], |
3563 | + patch=patch) |
3564 | + expect = [ |
3565 | + ('PATCH', self.base_path + '%s' % NODEGROUP1['id'], {}, patch), |
3566 | + ] |
3567 | + self.assertEqual(expect, self.api.calls) |
3568 | + self.assertEqual(NEW_NODE_COUNT, nodegroup.node_count) |
3569 | + |
3570 | + def test_nodegroup_create(self): |
3571 | + nodegroup = self.mgr.create(self.cluster_id, **CREATE_NODEGROUP) |
3572 | + expect = [ |
3573 | + ('POST', self.base_path, {}, CREATE_NODEGROUP), |
3574 | + ] |
3575 | + self.assertEqual(expect, self.api.calls) |
3576 | + self.assertTrue(nodegroup) |
3577 | + |
3578 | + def test_nodegroup_create_with_docker_volume_size(self): |
3579 | + ng_with_volume_size = dict() |
3580 | + ng_with_volume_size.update(CREATE_NODEGROUP) |
3581 | + ng_with_volume_size['docker_volume_size'] = 20 |
3582 | + nodegroup = self.mgr.create(self.cluster_id, **ng_with_volume_size) |
3583 | + expect = [ |
3584 | + ('POST', self.base_path, {}, ng_with_volume_size), |
3585 | + ] |
3586 | + self.assertEqual(expect, self.api.calls) |
3587 | + self.assertTrue(nodegroup) |
3588 | + |
3589 | + def test_nodegroup_create_with_labels(self): |
3590 | + ng_with_labels = dict() |
3591 | + ng_with_labels.update(CREATE_NODEGROUP) |
3592 | + ng_with_labels['labels'] = "key=val" |
3593 | + nodegroup = self.mgr.create(self.cluster_id, **ng_with_labels) |
3594 | + expect = [ |
3595 | + ('POST', self.base_path, {}, ng_with_labels), |
3596 | + ] |
3597 | + self.assertEqual(expect, self.api.calls) |
3598 | + self.assertTrue(nodegroup) |
3599 | + |
3600 | + def test_nodegroup_create_fail(self): |
3601 | + CREATE_NODEGROUP_FAIL = copy.deepcopy(CREATE_NODEGROUP) |
3602 | + CREATE_NODEGROUP_FAIL["wrong_key"] = "wrong" |
3603 | + self.assertRaisesRegex(exceptions.InvalidAttribute, |
3604 | + ("Key must be in %s" % |
3605 | + ','.join(nodegroups.CREATION_ATTRIBUTES)), |
3606 | + self.mgr.create, self.cluster_id, |
3607 | + **CREATE_NODEGROUP_FAIL) |
3608 | + self.assertEqual([], self.api.calls) |
3609 | diff --git a/magnumclient/v1/basemodels.py b/magnumclient/v1/basemodels.py |
3610 | index 0334b89..6ba0be9 100644 |
3611 | --- a/magnumclient/v1/basemodels.py |
3612 | +++ b/magnumclient/v1/basemodels.py |
3613 | @@ -22,7 +22,7 @@ CREATION_ATTRIBUTES = ['name', 'image_id', 'flavor_id', 'master_flavor_id', |
3614 | 'no_proxy', 'network_driver', 'tls_disabled', 'public', |
3615 | 'registry_enabled', 'volume_driver', 'server_type', |
3616 | 'docker_storage_driver', 'master_lb_enabled', |
3617 | - 'floating_ip_enabled'] |
3618 | + 'floating_ip_enabled', 'hidden'] |
3619 | |
3620 | OUTPUT_ATTRIBUTES = CREATION_ATTRIBUTES + ['apiserver_port', 'created_at', |
3621 | 'insecure_registry', 'links', |
3622 | diff --git a/magnumclient/v1/bays_shell.py b/magnumclient/v1/bays_shell.py |
3623 | index 689e84f..d2c865f 100644 |
3624 | --- a/magnumclient/v1/bays_shell.py |
3625 | +++ b/magnumclient/v1/bays_shell.py |
3626 | @@ -228,8 +228,8 @@ def do_bay_config(cs, args): |
3627 | """ |
3628 | args.dir = os.path.abspath(args.dir) |
3629 | bay = cs.bays.get(args.bay) |
3630 | - if bay.status not in ('CREATE_COMPLETE', 'UPDATE_COMPLETE'): |
3631 | - raise exceptions.CommandError("Bay in status %s" % bay.status) |
3632 | + if (hasattr(bay, 'api_address') and bay.api_address is None): |
3633 | + print("WARNING: The bay's api_address is not known yet.") |
3634 | baymodel = cs.baymodels.get(bay.baymodel_id) |
3635 | opts = { |
3636 | 'cluster_uuid': bay.uuid, |
3637 | diff --git a/magnumclient/v1/client.py b/magnumclient/v1/client.py |
3638 | index 8a8c72e..cb98cf9 100644 |
3639 | --- a/magnumclient/v1/client.py |
3640 | +++ b/magnumclient/v1/client.py |
3641 | @@ -25,6 +25,7 @@ from magnumclient.v1 import certificates |
3642 | from magnumclient.v1 import cluster_templates |
3643 | from magnumclient.v1 import clusters |
3644 | from magnumclient.v1 import mservices |
3645 | +from magnumclient.v1 import nodegroups |
3646 | from magnumclient.v1 import quotas |
3647 | from magnumclient.v1 import stats |
3648 | |
3649 | @@ -215,3 +216,4 @@ class Client(object): |
3650 | profiler.init(profile) |
3651 | self.stats = stats.StatsManager(self.http_client) |
3652 | self.quotas = quotas.QuotasManager(self.http_client) |
3653 | + self.nodegroups = nodegroups.NodeGroupManager(self.http_client) |
3654 | diff --git a/magnumclient/v1/cluster_templates_shell.py b/magnumclient/v1/cluster_templates_shell.py |
3655 | index 32a1aa5..11f8d12 100644 |
3656 | --- a/magnumclient/v1/cluster_templates_shell.py |
3657 | +++ b/magnumclient/v1/cluster_templates_shell.py |
3658 | @@ -187,6 +187,13 @@ def _show_cluster_template(cluster_template): |
3659 | @utils.arg('--insecure-registry', |
3660 | metavar='<insecure-registry>', |
3661 | help='url of docker registry') |
3662 | +@utils.arg('--hidden', |
3663 | + action='store_true', default=False, |
3664 | + help=_('Make cluster template hidden.')) |
3665 | +@utils.arg('--visible', |
3666 | + dest='hidden', |
3667 | + action='store_false', |
3668 | + help=_('Make cluster template visible.')) |
3669 | @utils.deprecated(utils.MAGNUM_CLIENT_DEPRECATION_WARNING) |
3670 | def do_cluster_template_create(cs, args): |
3671 | """Create a cluster template.""" |
3672 | @@ -219,6 +226,7 @@ def do_cluster_template_create(cs, args): |
3673 | opts['server_type'] = args.server_type |
3674 | opts['master_lb_enabled'] = args.master_lb_enabled |
3675 | opts['insecure_registry'] = args.insecure_registry |
3676 | + opts['hidden'] = args.hidden |
3677 | |
3678 | if len(args.floating_ip_enabled) > 1: |
3679 | raise InvalidAttribute('--floating-ip-enabled and ' |
3680 | diff --git a/magnumclient/v1/clusters.py b/magnumclient/v1/clusters.py |
3681 | index cdb599a..6aabc4b 100644 |
3682 | --- a/magnumclient/v1/clusters.py |
3683 | +++ b/magnumclient/v1/clusters.py |
3684 | @@ -23,6 +23,10 @@ CREATION_ATTRIBUTES.append('docker_volume_size') |
3685 | CREATION_ATTRIBUTES.append('labels') |
3686 | CREATION_ATTRIBUTES.append('master_flavor_id') |
3687 | CREATION_ATTRIBUTES.append('flavor_id') |
3688 | +CREATION_ATTRIBUTES.append('fixed_network') |
3689 | +CREATION_ATTRIBUTES.append('fixed_subnet') |
3690 | +CREATION_ATTRIBUTES.append('floating_ip_enabled') |
3691 | +CREATION_ATTRIBUTES.append('merge_labels') |
3692 | |
3693 | |
3694 | class Cluster(baseunit.BaseTemplate): |
3695 | @@ -32,3 +36,33 @@ class Cluster(baseunit.BaseTemplate): |
3696 | class ClusterManager(baseunit.BaseTemplateManager): |
3697 | resource_class = Cluster |
3698 | template_name = 'clusters' |
3699 | + |
3700 | + def resize(self, cluster_uuid, node_count, |
3701 | + nodes_to_remove=[], nodegroup=None): |
3702 | + url = self._path(cluster_uuid) + "/actions/resize" |
3703 | + |
3704 | + post_body = {"node_count": node_count} |
3705 | + if nodes_to_remove: |
3706 | + post_body.update({"nodes_to_remove": nodes_to_remove}) |
3707 | + if nodegroup: |
3708 | + post_body.update({"nodegroup": nodegroup}) |
3709 | + |
3710 | + resp, resp_body = self.api.json_request("POST", url, body=post_body) |
3711 | + |
3712 | + if resp_body: |
3713 | + return self.resource_class(self, resp_body) |
3714 | + |
3715 | + def upgrade(self, cluster_uuid, cluster_template, |
3716 | + max_batch_size=1, nodegroup=None): |
3717 | + url = self._path(cluster_uuid) + "/actions/upgrade" |
3718 | + |
3719 | + post_body = {"cluster_template": cluster_template} |
3720 | + if max_batch_size: |
3721 | + post_body.update({"max_batch_size": max_batch_size}) |
3722 | + if nodegroup: |
3723 | + post_body.update({"nodegroup": nodegroup}) |
3724 | + |
3725 | + resp, resp_body = self.api.json_request("POST", url, body=post_body) |
3726 | + |
3727 | + if resp_body: |
3728 | + return self.resource_class(self, resp_body) |
3729 | diff --git a/magnumclient/v1/clusters_shell.py b/magnumclient/v1/clusters_shell.py |
3730 | index 81e77e7..e46b3f9 100644 |
3731 | --- a/magnumclient/v1/clusters_shell.py |
3732 | +++ b/magnumclient/v1/clusters_shell.py |
3733 | @@ -262,9 +262,8 @@ def do_cluster_config(cs, args): |
3734 | """ |
3735 | args.dir = os.path.abspath(args.dir) |
3736 | cluster = cs.clusters.get(args.cluster) |
3737 | - if cluster.status not in ('CREATE_COMPLETE', 'UPDATE_COMPLETE', |
3738 | - 'ROLLBACK_COMPLETE'): |
3739 | - raise exceptions.CommandError("cluster in status %s" % cluster.status) |
3740 | + if (hasattr(cluster, 'api_address') and cluster.api_address is None): |
3741 | + print("WARNING: The cluster's api_address is not known yet.") |
3742 | cluster_template = cs.cluster_templates.get(cluster.cluster_template_id) |
3743 | opts = { |
3744 | 'cluster_uuid': cluster.uuid, |
3745 | diff --git a/magnumclient/v1/nodegroups.py b/magnumclient/v1/nodegroups.py |
3746 | new file mode 100644 |
3747 | index 0000000..111d8fb |
3748 | --- /dev/null |
3749 | +++ b/magnumclient/v1/nodegroups.py |
3750 | @@ -0,0 +1,84 @@ |
3751 | +# Copyright (c) 2018 European Organization for Nuclear Research. |
3752 | +# All Rights Reserved. |
3753 | +# |
3754 | +# Licensed under the Apache License, Version 2.0 (the "License"); you may |
3755 | +# not use this file except in compliance with the License. You may obtain |
3756 | +# a copy of the License at |
3757 | +# |
3758 | +# http://www.apache.org/licenses/LICENSE-2.0 |
3759 | +# |
3760 | +# Unless required by applicable law or agreed to in writing, software |
3761 | +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
3762 | +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
3763 | +# License for the specific language governing permissions and limitations |
3764 | +# under the License. |
3765 | + |
3766 | +from magnumclient.common import utils |
3767 | +from magnumclient import exceptions |
3768 | +from magnumclient.v1 import baseunit |
3769 | + |
3770 | + |
3771 | +CREATION_ATTRIBUTES = ['docker_volume_size', 'labels', 'flavor_id', 'image_id', |
3772 | + 'project_id', 'node_count', 'name', 'role', |
3773 | + 'min_node_count', 'max_node_count', 'merge_labels'] |
3774 | + |
3775 | + |
3776 | +class NodeGroup(baseunit.BaseTemplate): |
3777 | + template_name = "NodeGroups" |
3778 | + |
3779 | + |
3780 | +class NodeGroupManager(baseunit.BaseTemplateManager): |
3781 | + resource_class = NodeGroup |
3782 | + template_name = 'nodegroups' |
3783 | + api_name = 'nodegroups' |
3784 | + |
3785 | + @classmethod |
3786 | + def _path(cls, cluster_id, id=None): |
3787 | + path = '/v1/clusters/%s/%s/' % (cluster_id, cls.template_name) |
3788 | + if id: |
3789 | + path += str(id) |
3790 | + return path |
3791 | + |
3792 | + def list(self, cluster_id, limit=None, marker=None, sort_key=None, |
3793 | + sort_dir=None, role=None, detail=False): |
3794 | + if limit is not None: |
3795 | + limit = int(limit) |
3796 | + |
3797 | + filters = utils.common_filters(marker, limit, sort_key, sort_dir) |
3798 | + path = '' |
3799 | + if role: |
3800 | + filters.append('role=%s' % role) |
3801 | + if detail: |
3802 | + path += 'detail' |
3803 | + if filters: |
3804 | + path += '?' + '&'.join(filters) |
3805 | + |
3806 | + if limit is None: |
3807 | + return self._list(self._path(cluster_id, id=path), |
3808 | + self.__class__.api_name) |
3809 | + else: |
3810 | + return self._list_pagination(self._path(cluster_id, id=path), |
3811 | + self.__class__.api_name, |
3812 | + limit=limit) |
3813 | + |
3814 | + def get(self, cluster_id, id): |
3815 | + try: |
3816 | + return self._list(self._path(cluster_id, id=id))[0] |
3817 | + except IndexError: |
3818 | + return None |
3819 | + |
3820 | + def create(self, cluster_id, **kwargs): |
3821 | + new = {} |
3822 | + for (key, value) in kwargs.items(): |
3823 | + if key in CREATION_ATTRIBUTES: |
3824 | + new[key] = value |
3825 | + else: |
3826 | + raise exceptions.InvalidAttribute( |
3827 | + "Key must be in %s" % ",".join(CREATION_ATTRIBUTES)) |
3828 | + return self._create(self._path(cluster_id), new) |
3829 | + |
3830 | + def delete(self, cluster_id, id): |
3831 | + return self._delete(self._path(cluster_id, id=id)) |
3832 | + |
3833 | + def update(self, cluster_id, id, patch): |
3834 | + return self._update(self._path(cluster_id, id=id), patch) |
3835 | diff --git a/python_magnumclient.egg-info/PKG-INFO b/python_magnumclient.egg-info/PKG-INFO |
3836 | new file mode 100644 |
3837 | index 0000000..8045ab2 |
3838 | --- /dev/null |
3839 | +++ b/python_magnumclient.egg-info/PKG-INFO |
3840 | @@ -0,0 +1,61 @@ |
3841 | +Metadata-Version: 1.1 |
3842 | +Name: python-magnumclient |
3843 | +Version: 3.0.1 |
3844 | +Summary: Client library for Magnum API |
3845 | +Home-page: https://docs.openstack.org/python-magnumclient/latest/ |
3846 | +Author: OpenStack |
3847 | +Author-email: openstack-discuss@lists.openstack.org |
3848 | +License: UNKNOWN |
3849 | +Description: ======================== |
3850 | + Team and repository tags |
3851 | + ======================== |
3852 | + |
3853 | + .. image:: https://governance.openstack.org/tc/badges/python-magnumclient.svg |
3854 | + :target: https://governance.openstack.org/tc/reference/tags/index.html |
3855 | + |
3856 | + .. Change things from this point on |
3857 | + |
3858 | + Python bindings to the Magnum API |
3859 | + ================================= |
3860 | + |
3861 | + .. image:: https://img.shields.io/pypi/v/python-magnumclient.svg |
3862 | + :target: https://pypi.org/project/python-magnumclient/ |
3863 | + :alt: Latest Version |
3864 | + |
3865 | + .. image:: https://img.shields.io/pypi/dm/python-magnumclient.svg |
3866 | + :target: https://pypi.org/project/python-magnumclient/ |
3867 | + :alt: Downloads |
3868 | + |
3869 | + This is a client library for Magnum built on the Magnum API. It |
3870 | + provides a Python API (the ``magnumclient`` module) and a command-line |
3871 | + tool (``magnum``). |
3872 | + |
3873 | + Development takes place via the usual OpenStack processes as outlined |
3874 | + in the `developer guide |
3875 | + <https://docs.openstack.org/infra/manual/developers.html>`_. |
3876 | + |
3877 | + * License: Apache License, Version 2.0 |
3878 | + * `PyPi`_ - package installation |
3879 | + * `Online Documentation`_ |
3880 | + * `Launchpad project`_ - release management |
3881 | + * `Bugs`_ - issue tracking |
3882 | + * `Source`_ |
3883 | + |
3884 | + .. _PyPi: https://pypi.org/project/python-magnumclient |
3885 | + .. _Online Documentation: https://docs.openstack.org/python-magnumclient/latest/ |
3886 | + .. _Launchpad project: https://launchpad.net/python-magnumclient |
3887 | + .. _Bugs: https://bugs.launchpad.net/python-magnumclient |
3888 | + .. _Source: https://opendev.org/openstack/python-magnumclient |
3889 | + |
3890 | + |
3891 | +Platform: UNKNOWN |
3892 | +Classifier: Environment :: OpenStack |
3893 | +Classifier: Intended Audience :: Information Technology |
3894 | +Classifier: Intended Audience :: System Administrators |
3895 | +Classifier: License :: OSI Approved :: Apache Software License |
3896 | +Classifier: Operating System :: POSIX :: Linux |
3897 | +Classifier: Programming Language :: Python |
3898 | +Classifier: Programming Language :: Python :: 2 |
3899 | +Classifier: Programming Language :: Python :: 3 |
3900 | +Classifier: Programming Language :: Python :: 3.6 |
3901 | +Classifier: Programming Language :: Python :: 3.7 |
3902 | diff --git a/python_magnumclient.egg-info/SOURCES.txt b/python_magnumclient.egg-info/SOURCES.txt |
3903 | new file mode 100644 |
3904 | index 0000000..c63c7ee |
3905 | --- /dev/null |
3906 | +++ b/python_magnumclient.egg-info/SOURCES.txt |
3907 | @@ -0,0 +1,128 @@ |
3908 | +.coveragerc |
3909 | +.mailmap |
3910 | +.stestr.conf |
3911 | +.zuul.yaml |
3912 | +AUTHORS |
3913 | +CONTRIBUTING.rst |
3914 | +ChangeLog |
3915 | +LICENSE |
3916 | +README.rst |
3917 | +babel.cfg |
3918 | +lower-constraints.txt |
3919 | +requirements.txt |
3920 | +setup.cfg |
3921 | +setup.py |
3922 | +test-requirements.txt |
3923 | +tox.ini |
3924 | +doc/requirements.txt |
3925 | +doc/source/conf.py |
3926 | +doc/source/contributing.rst |
3927 | +doc/source/index.rst |
3928 | +doc/source/installation.rst |
3929 | +doc/source/readme.rst |
3930 | +doc/source/usage.rst |
3931 | +magnumclient/__init__.py |
3932 | +magnumclient/client.py |
3933 | +magnumclient/exceptions.py |
3934 | +magnumclient/i18n.py |
3935 | +magnumclient/shell.py |
3936 | +magnumclient/version.py |
3937 | +magnumclient/common/__init__.py |
3938 | +magnumclient/common/base.py |
3939 | +magnumclient/common/cliutils.py |
3940 | +magnumclient/common/httpclient.py |
3941 | +magnumclient/common/utils.py |
3942 | +magnumclient/common/apiclient/__init__.py |
3943 | +magnumclient/common/apiclient/base.py |
3944 | +magnumclient/common/apiclient/exceptions.py |
3945 | +magnumclient/osc/__init__.py |
3946 | +magnumclient/osc/plugin.py |
3947 | +magnumclient/osc/v1/__init__.py |
3948 | +magnumclient/osc/v1/certificates.py |
3949 | +magnumclient/osc/v1/cluster_templates.py |
3950 | +magnumclient/osc/v1/clusters.py |
3951 | +magnumclient/osc/v1/mservices.py |
3952 | +magnumclient/osc/v1/nodegroups.py |
3953 | +magnumclient/osc/v1/quotas.py |
3954 | +magnumclient/osc/v1/stats.py |
3955 | +magnumclient/tests/__init__.py |
3956 | +magnumclient/tests/base.py |
3957 | +magnumclient/tests/test_client.py |
3958 | +magnumclient/tests/test_httpclient.py |
3959 | +magnumclient/tests/test_magnumclient.py |
3960 | +magnumclient/tests/test_shell.py |
3961 | +magnumclient/tests/test_utils.py |
3962 | +magnumclient/tests/utils.py |
3963 | +magnumclient/tests/osc/__init__.py |
3964 | +magnumclient/tests/osc/unit/__init__.py |
3965 | +magnumclient/tests/osc/unit/osc_fakes.py |
3966 | +magnumclient/tests/osc/unit/osc_utils.py |
3967 | +magnumclient/tests/osc/unit/v1/__init__.py |
3968 | +magnumclient/tests/osc/unit/v1/fakes.py |
3969 | +magnumclient/tests/osc/unit/v1/test_certificates.py |
3970 | +magnumclient/tests/osc/unit/v1/test_cluster_templates.py |
3971 | +magnumclient/tests/osc/unit/v1/test_clusters.py |
3972 | +magnumclient/tests/osc/unit/v1/test_mservices.py |
3973 | +magnumclient/tests/osc/unit/v1/test_nodegroups.py |
3974 | +magnumclient/tests/osc/unit/v1/test_quotas.py |
3975 | +magnumclient/tests/osc/unit/v1/test_stats.py |
3976 | +magnumclient/tests/test_csr/test.csr |
3977 | +magnumclient/tests/v1/__init__.py |
3978 | +magnumclient/tests/v1/shell_test_base.py |
3979 | +magnumclient/tests/v1/test_baymodels.py |
3980 | +magnumclient/tests/v1/test_baymodels_shell.py |
3981 | +magnumclient/tests/v1/test_bays.py |
3982 | +magnumclient/tests/v1/test_bays_shell.py |
3983 | +magnumclient/tests/v1/test_certificates.py |
3984 | +magnumclient/tests/v1/test_certificates_shell.py |
3985 | +magnumclient/tests/v1/test_client.py |
3986 | +magnumclient/tests/v1/test_clusters.py |
3987 | +magnumclient/tests/v1/test_clusters_shell.py |
3988 | +magnumclient/tests/v1/test_clustertemplates.py |
3989 | +magnumclient/tests/v1/test_clustertemplates_shell.py |
3990 | +magnumclient/tests/v1/test_mservices.py |
3991 | +magnumclient/tests/v1/test_mservices_shell.py |
3992 | +magnumclient/tests/v1/test_nodegroups.py |
3993 | +magnumclient/tests/v1/test_quotas.py |
3994 | +magnumclient/tests/v1/test_quotas_shell.py |
3995 | +magnumclient/tests/v1/test_stats.py |
3996 | +magnumclient/tests/v1/test_stats_shell.py |
3997 | +magnumclient/v1/__init__.py |
3998 | +magnumclient/v1/basemodels.py |
3999 | +magnumclient/v1/baseunit.py |
4000 | +magnumclient/v1/baymodels.py |
4001 | +magnumclient/v1/baymodels_shell.py |
4002 | +magnumclient/v1/bays.py |
4003 | +magnumclient/v1/bays_shell.py |
4004 | +magnumclient/v1/certificates.py |
4005 | +magnumclient/v1/certificates_shell.py |
4006 | +magnumclient/v1/client.py |
4007 | +magnumclient/v1/cluster_templates.py |
4008 | +magnumclient/v1/cluster_templates_shell.py |
4009 | +magnumclient/v1/clusters.py |
4010 | +magnumclient/v1/clusters_shell.py |
4011 | +magnumclient/v1/mservices.py |
4012 | +magnumclient/v1/mservices_shell.py |
4013 | +magnumclient/v1/nodegroups.py |
4014 | +magnumclient/v1/quotas.py |
4015 | +magnumclient/v1/quotas_shell.py |
4016 | +magnumclient/v1/shell.py |
4017 | +magnumclient/v1/stats.py |
4018 | +magnumclient/v1/stats_shell.py |
4019 | +python_magnumclient.egg-info/PKG-INFO |
4020 | +python_magnumclient.egg-info/SOURCES.txt |
4021 | +python_magnumclient.egg-info/dependency_links.txt |
4022 | +python_magnumclient.egg-info/entry_points.txt |
4023 | +python_magnumclient.egg-info/not-zip-safe |
4024 | +python_magnumclient.egg-info/pbr.json |
4025 | +python_magnumclient.egg-info/requires.txt |
4026 | +python_magnumclient.egg-info/top_level.txt |
4027 | +releasenotes/notes/partial_osc_implementation_for_certificate-4597c20b59c152e1.yaml |
4028 | +releasenotes/notes/partial_osc_implementation_for_quotas-33f44c0496d721f8.yaml |
4029 | +releasenotes/source/conf.py |
4030 | +releasenotes/source/index.rst |
4031 | +releasenotes/source/rocky.rst |
4032 | +releasenotes/source/stein.rst |
4033 | +releasenotes/source/train.rst |
4034 | +releasenotes/source/unreleased.rst |
4035 | +tools/magnum.bash_completion |
4036 | \ No newline at end of file |
4037 | diff --git a/python_magnumclient.egg-info/dependency_links.txt b/python_magnumclient.egg-info/dependency_links.txt |
4038 | new file mode 100644 |
4039 | index 0000000..8b13789 |
4040 | --- /dev/null |
4041 | +++ b/python_magnumclient.egg-info/dependency_links.txt |
4042 | @@ -0,0 +1 @@ |
4043 | + |
4044 | diff --git a/python_magnumclient.egg-info/entry_points.txt b/python_magnumclient.egg-info/entry_points.txt |
4045 | new file mode 100644 |
4046 | index 0000000..ebade23 |
4047 | --- /dev/null |
4048 | +++ b/python_magnumclient.egg-info/entry_points.txt |
4049 | @@ -0,0 +1,36 @@ |
4050 | +[console_scripts] |
4051 | +magnum = magnumclient.shell:main |
4052 | + |
4053 | +[openstack.cli.extension] |
4054 | +container_infra = magnumclient.osc.plugin |
4055 | + |
4056 | +[openstack.container_infra.v1] |
4057 | +coe_ca_rotate = magnumclient.osc.v1.certificates:RotateCa |
4058 | +coe_ca_show = magnumclient.osc.v1.certificates:ShowCa |
4059 | +coe_ca_sign = magnumclient.osc.v1.certificates:SignCa |
4060 | +coe_cluster_config = magnumclient.osc.v1.clusters:ConfigCluster |
4061 | +coe_cluster_create = magnumclient.osc.v1.clusters:CreateCluster |
4062 | +coe_cluster_delete = magnumclient.osc.v1.clusters:DeleteCluster |
4063 | +coe_cluster_list = magnumclient.osc.v1.clusters:ListCluster |
4064 | +coe_cluster_resize = magnumclient.osc.v1.clusters:ResizeCluster |
4065 | +coe_cluster_show = magnumclient.osc.v1.clusters:ShowCluster |
4066 | +coe_cluster_template_create = magnumclient.osc.v1.cluster_templates:CreateClusterTemplate |
4067 | +coe_cluster_template_delete = magnumclient.osc.v1.cluster_templates:DeleteClusterTemplate |
4068 | +coe_cluster_template_list = magnumclient.osc.v1.cluster_templates:ListTemplateCluster |
4069 | +coe_cluster_template_show = magnumclient.osc.v1.cluster_templates:ShowClusterTemplate |
4070 | +coe_cluster_template_update = magnumclient.osc.v1.cluster_templates:UpdateClusterTemplate |
4071 | +coe_cluster_update = magnumclient.osc.v1.clusters:UpdateCluster |
4072 | +coe_cluster_upgrade = magnumclient.osc.v1.clusters:UpgradeCluster |
4073 | +coe_nodegroup_create = magnumclient.osc.v1.nodegroups:CreateNodeGroup |
4074 | +coe_nodegroup_delete = magnumclient.osc.v1.nodegroups:DeleteNodeGroup |
4075 | +coe_nodegroup_list = magnumclient.osc.v1.nodegroups:ListNodeGroup |
4076 | +coe_nodegroup_show = magnumclient.osc.v1.nodegroups:ShowNodeGroup |
4077 | +coe_nodegroup_update = magnumclient.osc.v1.nodegroups:UpdateNodeGroup |
4078 | +coe_quotas_create = magnumclient.osc.v1.quotas:CreateQuotas |
4079 | +coe_quotas_delete = magnumclient.osc.v1.quotas:DeleteQuotas |
4080 | +coe_quotas_list = magnumclient.osc.v1.quotas:ListQuotas |
4081 | +coe_quotas_show = magnumclient.osc.v1.quotas:ShowQuotas |
4082 | +coe_quotas_update = magnumclient.osc.v1.quotas:UpdateQuotas |
4083 | +coe_service_list = magnumclient.osc.v1.mservices:ListService |
4084 | +coe_stats_list = magnumclient.osc.v1.stats:ListStats |
4085 | + |
4086 | diff --git a/python_magnumclient.egg-info/not-zip-safe b/python_magnumclient.egg-info/not-zip-safe |
4087 | new file mode 100644 |
4088 | index 0000000..8b13789 |
4089 | --- /dev/null |
4090 | +++ b/python_magnumclient.egg-info/not-zip-safe |
4091 | @@ -0,0 +1 @@ |
4092 | + |
4093 | diff --git a/python_magnumclient.egg-info/pbr.json b/python_magnumclient.egg-info/pbr.json |
4094 | new file mode 100644 |
4095 | index 0000000..b268641 |
4096 | --- /dev/null |
4097 | +++ b/python_magnumclient.egg-info/pbr.json |
4098 | @@ -0,0 +1 @@ |
4099 | +{"git_version": "6d1a386", "is_release": true} |
4100 | \ No newline at end of file |
4101 | diff --git a/python_magnumclient.egg-info/requires.txt b/python_magnumclient.egg-info/requires.txt |
4102 | new file mode 100644 |
4103 | index 0000000..1a7483a |
4104 | --- /dev/null |
4105 | +++ b/python_magnumclient.egg-info/requires.txt |
4106 | @@ -0,0 +1,15 @@ |
4107 | +Babel!=2.4.0,>=2.3.4 |
4108 | +PrettyTable<0.8,>=0.7.2 |
4109 | +cryptography>=2.1 |
4110 | +decorator>=3.4.0 |
4111 | +keystoneauth1>=3.4.0 |
4112 | +os-client-config>=1.28.0 |
4113 | +osc-lib>=1.8.0 |
4114 | +oslo.i18n>=3.15.3 |
4115 | +oslo.log>=3.36.0 |
4116 | +oslo.serialization!=2.19.1,>=2.18.0 |
4117 | +oslo.utils>=3.33.0 |
4118 | +pbr!=2.1.0,>=2.0.0 |
4119 | +requests>=2.14.2 |
4120 | +six>=1.10.0 |
4121 | +stevedore>=1.20.0 |
4122 | diff --git a/python_magnumclient.egg-info/top_level.txt b/python_magnumclient.egg-info/top_level.txt |
4123 | new file mode 100644 |
4124 | index 0000000..66cb45a |
4125 | --- /dev/null |
4126 | +++ b/python_magnumclient.egg-info/top_level.txt |
4127 | @@ -0,0 +1 @@ |
4128 | +magnumclient |
4129 | diff --git a/releasenotes/source/index.rst b/releasenotes/source/index.rst |
4130 | index 416280b..11d549e 100644 |
4131 | --- a/releasenotes/source/index.rst |
4132 | +++ b/releasenotes/source/index.rst |
4133 | @@ -6,6 +6,8 @@ |
4134 | :maxdepth: 1 |
4135 | |
4136 | unreleased |
4137 | + train |
4138 | + stein |
4139 | rocky |
4140 | |
4141 | OpenStack Releases |
4142 | diff --git a/releasenotes/source/stein.rst b/releasenotes/source/stein.rst |
4143 | new file mode 100644 |
4144 | index 0000000..efaceb6 |
4145 | --- /dev/null |
4146 | +++ b/releasenotes/source/stein.rst |
4147 | @@ -0,0 +1,6 @@ |
4148 | +=================================== |
4149 | + Stein Series Release Notes |
4150 | +=================================== |
4151 | + |
4152 | +.. release-notes:: |
4153 | + :branch: stable/stein |
4154 | diff --git a/releasenotes/source/train.rst b/releasenotes/source/train.rst |
4155 | new file mode 100644 |
4156 | index 0000000..5839003 |
4157 | --- /dev/null |
4158 | +++ b/releasenotes/source/train.rst |
4159 | @@ -0,0 +1,6 @@ |
4160 | +========================== |
4161 | +Train Series Release Notes |
4162 | +========================== |
4163 | + |
4164 | +.. release-notes:: |
4165 | + :branch: stable/train |
4166 | diff --git a/setup.cfg b/setup.cfg |
4167 | index 4db9c44..05d064e 100644 |
4168 | --- a/setup.cfg |
4169 | +++ b/setup.cfg |
4170 | @@ -1,59 +1,64 @@ |
4171 | [metadata] |
4172 | name = python-magnumclient |
4173 | summary = Client library for Magnum API |
4174 | -description-file = |
4175 | - README.rst |
4176 | +description-file = |
4177 | + README.rst |
4178 | author = OpenStack |
4179 | -author-email = openstack-dev@lists.openstack.org |
4180 | +author-email = openstack-discuss@lists.openstack.org |
4181 | home-page = https://docs.openstack.org/python-magnumclient/latest/ |
4182 | -classifier = |
4183 | - Environment :: OpenStack |
4184 | - Intended Audience :: Information Technology |
4185 | - Intended Audience :: System Administrators |
4186 | - License :: OSI Approved :: Apache Software License |
4187 | - Operating System :: POSIX :: Linux |
4188 | - Programming Language :: Python |
4189 | - Programming Language :: Python :: 2 |
4190 | - Programming Language :: Python :: 2.7 |
4191 | - Programming Language :: Python :: 3 |
4192 | - Programming Language :: Python :: 3.5 |
4193 | +classifier = |
4194 | + Environment :: OpenStack |
4195 | + Intended Audience :: Information Technology |
4196 | + Intended Audience :: System Administrators |
4197 | + License :: OSI Approved :: Apache Software License |
4198 | + Operating System :: POSIX :: Linux |
4199 | + Programming Language :: Python |
4200 | + Programming Language :: Python :: 2 |
4201 | + Programming Language :: Python :: 3 |
4202 | + Programming Language :: Python :: 3.6 |
4203 | + Programming Language :: Python :: 3.7 |
4204 | |
4205 | [files] |
4206 | -packages = |
4207 | - magnumclient |
4208 | +packages = |
4209 | + magnumclient |
4210 | |
4211 | [entry_points] |
4212 | -console_scripts = |
4213 | - magnum = magnumclient.shell:main |
4214 | - |
4215 | -openstack.cli.extension = |
4216 | - container_infra = magnumclient.osc.plugin |
4217 | - |
4218 | -openstack.container_infra.v1 = |
4219 | - coe_cluster_template_create = magnumclient.osc.v1.cluster_templates:CreateClusterTemplate |
4220 | - coe_cluster_template_delete = magnumclient.osc.v1.cluster_templates:DeleteClusterTemplate |
4221 | - coe_cluster_template_list = magnumclient.osc.v1.cluster_templates:ListTemplateCluster |
4222 | - coe_cluster_template_show = magnumclient.osc.v1.cluster_templates:ShowClusterTemplate |
4223 | - coe_cluster_template_update = magnumclient.osc.v1.cluster_templates:UpdateClusterTemplate |
4224 | - |
4225 | - coe_cluster_create = magnumclient.osc.v1.clusters:CreateCluster |
4226 | - coe_cluster_list = magnumclient.osc.v1.clusters:ListCluster |
4227 | - coe_cluster_delete = magnumclient.osc.v1.clusters:DeleteCluster |
4228 | - coe_cluster_show = magnumclient.osc.v1.clusters:ShowCluster |
4229 | - coe_cluster_update = magnumclient.osc.v1.clusters:UpdateCluster |
4230 | - coe_cluster_config = magnumclient.osc.v1.clusters:ConfigCluster |
4231 | - coe_ca_rotate = magnumclient.osc.v1.certificates:RotateCa |
4232 | - coe_ca_show = magnumclient.osc.v1.certificates:ShowCa |
4233 | - coe_ca_sign = magnumclient.osc.v1.certificates:SignCa |
4234 | - coe_stats_list = magnumclient.osc.v1.stats:ListStats |
4235 | - coe_quotas_create = magnumclient.osc.v1.quotas:CreateQuotas |
4236 | - coe_quotas_delete = magnumclient.osc.v1.quotas:DeleteQuotas |
4237 | - coe_quotas_update = magnumclient.osc.v1.quotas:UpdateQuotas |
4238 | - coe_quotas_show = magnumclient.osc.v1.quotas:ShowQuotas |
4239 | - coe_quotas_list = magnumclient.osc.v1.quotas:ListQuotas |
4240 | - |
4241 | - coe_service_list = magnumclient.osc.v1.mservices:ListService |
4242 | - |
4243 | +console_scripts = |
4244 | + magnum = magnumclient.shell:main |
4245 | +openstack.cli.extension = |
4246 | + container_infra = magnumclient.osc.plugin |
4247 | +openstack.container_infra.v1 = |
4248 | + coe_cluster_template_create = magnumclient.osc.v1.cluster_templates:CreateClusterTemplate |
4249 | + coe_cluster_template_delete = magnumclient.osc.v1.cluster_templates:DeleteClusterTemplate |
4250 | + coe_cluster_template_list = magnumclient.osc.v1.cluster_templates:ListTemplateCluster |
4251 | + coe_cluster_template_show = magnumclient.osc.v1.cluster_templates:ShowClusterTemplate |
4252 | + coe_cluster_template_update = magnumclient.osc.v1.cluster_templates:UpdateClusterTemplate |
4253 | + |
4254 | + coe_cluster_create = magnumclient.osc.v1.clusters:CreateCluster |
4255 | + coe_cluster_list = magnumclient.osc.v1.clusters:ListCluster |
4256 | + coe_cluster_delete = magnumclient.osc.v1.clusters:DeleteCluster |
4257 | + coe_cluster_show = magnumclient.osc.v1.clusters:ShowCluster |
4258 | + coe_cluster_update = magnumclient.osc.v1.clusters:UpdateCluster |
4259 | + coe_cluster_config = magnumclient.osc.v1.clusters:ConfigCluster |
4260 | + coe_cluster_resize = magnumclient.osc.v1.clusters:ResizeCluster |
4261 | + coe_cluster_upgrade = magnumclient.osc.v1.clusters:UpgradeCluster |
4262 | + coe_ca_rotate = magnumclient.osc.v1.certificates:RotateCa |
4263 | + coe_ca_show = magnumclient.osc.v1.certificates:ShowCa |
4264 | + coe_ca_sign = magnumclient.osc.v1.certificates:SignCa |
4265 | + coe_stats_list = magnumclient.osc.v1.stats:ListStats |
4266 | + coe_quotas_create = magnumclient.osc.v1.quotas:CreateQuotas |
4267 | + coe_quotas_delete = magnumclient.osc.v1.quotas:DeleteQuotas |
4268 | + coe_quotas_update = magnumclient.osc.v1.quotas:UpdateQuotas |
4269 | + coe_quotas_show = magnumclient.osc.v1.quotas:ShowQuotas |
4270 | + coe_quotas_list = magnumclient.osc.v1.quotas:ListQuotas |
4271 | + |
4272 | + coe_service_list = magnumclient.osc.v1.mservices:ListService |
4273 | + |
4274 | + coe_nodegroup_list = magnumclient.osc.v1.nodegroups:ListNodeGroup |
4275 | + coe_nodegroup_show = magnumclient.osc.v1.nodegroups:ShowNodeGroup |
4276 | + coe_nodegroup_create = magnumclient.osc.v1.nodegroups:CreateNodeGroup |
4277 | + coe_nodegroup_delete = magnumclient.osc.v1.nodegroups:DeleteNodeGroup |
4278 | + coe_nodegroup_update = magnumclient.osc.v1.nodegroups:UpdateNodeGroup |
4279 | |
4280 | [compile_catalog] |
4281 | directory = magnumclient/locale |
4282 | @@ -71,3 +76,8 @@ output_file = magnumclient/locale/magnumclient.pot |
4283 | |
4284 | [wheel] |
4285 | universal = 1 |
4286 | + |
4287 | +[egg_info] |
4288 | +tag_build = |
4289 | +tag_date = 0 |
4290 | + |
4291 | diff --git a/test-requirements.txt b/test-requirements.txt |
4292 | index f625855..fd61dfa 100644 |
4293 | --- a/test-requirements.txt |
4294 | +++ b/test-requirements.txt |
4295 | @@ -1,8 +1,8 @@ |
4296 | # The order of packages is significant, because pip processes them in the order |
4297 | # of appearance. Changing the order has an impact on the overall integration |
4298 | # process, which may cause wedges in the gate later. |
4299 | -hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0 |
4300 | -bandit>=1.1.0 # Apache-2.0 |
4301 | +hacking>=2.0,<2.1 # Apache-2.0 |
4302 | +bandit!=1.6.0,>=1.1.0 # Apache-2.0 |
4303 | coverage!=4.4,>=4.0 # Apache-2.0 |
4304 | fixtures>=3.0.0 # Apache-2.0/BSD |
4305 | python-openstackclient>=3.12.0 # Apache-2.0 |
4306 | diff --git a/tools/cover.sh b/tools/cover.sh |
4307 | deleted file mode 100755 |
4308 | index 74b25d9..0000000 |
4309 | --- a/tools/cover.sh |
4310 | +++ /dev/null |
4311 | @@ -1,79 +0,0 @@ |
4312 | -#!/bin/bash |
4313 | -# |
4314 | -# Licensed under the Apache License, Version 2.0 (the "License"); you may |
4315 | -# not use this file except in compliance with the License. You may obtain |
4316 | -# a copy of the License at |
4317 | -# |
4318 | -# http://www.apache.org/licenses/LICENSE-2.0 |
4319 | -# |
4320 | -# Unless required by applicable law or agreed to in writing, software |
4321 | -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
4322 | -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
4323 | -# License for the specific language governing permissions and limitations |
4324 | -# under the License. |
4325 | - |
4326 | -ALLOWED_EXTRA_MISSING=0 |
4327 | - |
4328 | -show_diff () { |
4329 | - head -1 $1 |
4330 | - diff -U 0 $1 $2 | sed 1,2d |
4331 | -} |
4332 | - |
4333 | -if ! git diff --exit-code || ! git diff --cached --exit-code |
4334 | -then |
4335 | - echo "There are uncommitted changes!" |
4336 | - echo "Please clean git working directory and try again" |
4337 | - exit 1 |
4338 | -fi |
4339 | - |
4340 | -# Checkout master and save coverage report |
4341 | -git checkout HEAD^ |
4342 | - |
4343 | -baseline_report=$(mktemp -t magnumclient_coverageXXXXXXX) |
4344 | -find . -type f -name "*.pyc" -delete |
4345 | -stestr run "$*" |
4346 | -coverage combine |
4347 | -coverage report --fail-under=80 --skip-covered |
4348 | -coverage html -d cover |
4349 | -coverage xml -o cover/coverage.xml |
4350 | -coverage report > $baseline_report |
4351 | -mv cover cover-master |
4352 | -cat $baseline_report |
4353 | -baseline_missing=$(awk 'END { print $3 }' $baseline_report) |
4354 | - |
4355 | -# Checkout back and save coverage report |
4356 | -git checkout - |
4357 | - |
4358 | -current_report=$(mktemp -t magnumclient_coverageXXXXXXX) |
4359 | -find . -type f -name "*.pyc" -delete |
4360 | -stestr run "$*" |
4361 | -coverage combine |
4362 | -coverage report --fail-under=80 --skip-covered |
4363 | -coverage html -d cover |
4364 | -coverage xml -o cover/coverage.xml |
4365 | -coverage report > $current_report |
4366 | -current_missing=$(awk 'END { print $3 }' $current_report) |
4367 | - |
4368 | -# Show coverage details |
4369 | -allowed_missing=$((baseline_missing+ALLOWED_EXTRA_MISSING)) |
4370 | - |
4371 | -echo "Allowed to introduce missing lines : ${ALLOWED_EXTRA_MISSING}" |
4372 | -echo "Missing lines in master : ${baseline_missing}" |
4373 | -echo "Missing lines in proposed change : ${current_missing}" |
4374 | - |
4375 | -if [ $allowed_missing -ge $current_missing ]; then |
4376 | - if [ $baseline_missing -lt $current_missing ]; then |
4377 | - show_diff $baseline_report $current_report |
4378 | - echo "We believe you can test your code with 100% coverage!" |
4379 | - else |
4380 | - echo "Thank you! You are awesome! Keep writing unit tests! :)" |
4381 | - fi |
4382 | - exit_code=0 |
4383 | -else |
4384 | - show_diff $baseline_report $current_report |
4385 | - echo "Please write more unit tests, we must maintain our test coverage :( " |
4386 | - exit_code=1 |
4387 | -fi |
4388 | - |
4389 | -rm $baseline_report $current_report |
4390 | -exit $exit_code |
4391 | diff --git a/tox.ini b/tox.ini |
4392 | index 391d0f4..004dc2d 100644 |
4393 | --- a/tox.ini |
4394 | +++ b/tox.ini |
4395 | @@ -1,6 +1,6 @@ |
4396 | [tox] |
4397 | -minversion = 1.6 |
4398 | -envlist = py35,py27,pypy,pep8 |
4399 | +minversion = 2.0 |
4400 | +envlist = py37,pypy,pep8 |
4401 | skipsdist = True |
4402 | |
4403 | [testenv] |
4404 | @@ -11,7 +11,7 @@ setenv = |
4405 | VIRTUAL_ENV={envdir} |
4406 | PYTHONWARNINGS=default::DeprecationWarning |
4407 | deps = |
4408 | - -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} |
4409 | + -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/ussuri} |
4410 | -r{toxinidir}/requirements.txt |
4411 | -r{toxinidir}/test-requirements.txt |
4412 | commands = |
4413 | @@ -21,14 +21,14 @@ commands = |
4414 | [testenv:bandit] |
4415 | basepython = python3 |
4416 | deps = |
4417 | - -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} |
4418 | + -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/ussuri} |
4419 | -r{toxinidir}/test-requirements.txt |
4420 | commands = bandit -r magnumclient -x tests -n5 -ll |
4421 | |
4422 | [testenv:pypy] |
4423 | basepython = python3 |
4424 | deps = |
4425 | - -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} |
4426 | + -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/ussuri} |
4427 | setuptools<3.2 |
4428 | -r{toxinidir}/requirements.txt |
4429 | -r{toxinidir}/test-requirements.txt |
4430 | @@ -37,14 +37,6 @@ deps = |
4431 | basepython = python3 |
4432 | commands = oslo_debug_helper -t magnumclient/tests {posargs} |
4433 | |
4434 | -[testenv:debug-py27] |
4435 | -basepython = python2.7 |
4436 | -commands = oslo_debug_helper -t magnumclient/tests {posargs} |
4437 | - |
4438 | -[testenv:debug-py35] |
4439 | -basepython = python3.5 |
4440 | -commands = oslo_debug_helper -t magnumclient/tests {posargs} |
4441 | - |
4442 | [testenv:pep8] |
4443 | basepython = python3 |
4444 | commands = |
4445 | @@ -64,13 +56,20 @@ commands = {posargs} |
4446 | |
4447 | [testenv:cover] |
4448 | basepython = python3 |
4449 | -commands = {toxinidir}/tools/cover.sh {posargs} |
4450 | +setenv = |
4451 | + PYTHON=coverage run --source magnumclient --parallel-mode |
4452 | +commands = |
4453 | + stestr run {posargs} |
4454 | + coverage combine |
4455 | + coverage html -d cover |
4456 | + coverage xml -o cover/coverage.xml |
4457 | + coverage report |
4458 | |
4459 | [flake8] |
4460 | # E123, E125 skipped as they are invalid PEP-8. |
4461 | |
4462 | show-source = True |
4463 | -ignore = E123,E125 |
4464 | +ignore = E123,E125,W503,W504 |
4465 | builtins = _ |
4466 | exclude=.venv,.git,.tox,dist,doc,,*lib/python*,*egg,build |
4467 | |
4468 | @@ -89,4 +88,4 @@ basepython = python3 |
4469 | deps = -r{toxinidir}/doc/requirements.txt |
4470 | commands = |
4471 | rm -rf releasenotes/build |
4472 | - sphinx-build -a -E -W -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html |
4473 | \ No newline at end of file |
4474 | + sphinx-build -a -E -W -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html |