Retire cue
Cue has been retired in mid 2016 as official project and did not continue developement, it's time to retire it completely. Remove everything, update README. Depends-On: https://review.openstack.org/551202 Change-Id: I4092bb5feac88235eae52895a57ce3d01f347638
This commit is contained in:
parent
bb1f4adca0
commit
64dbf807ae
@ -1,7 +0,0 @@
|
|||||||
[run]
|
|
||||||
branch = True
|
|
||||||
source = cueclient
|
|
||||||
omit = cueclient/tests/*
|
|
||||||
|
|
||||||
[report]
|
|
||||||
ignore_errors = True
|
|
26
.gitignore
vendored
26
.gitignore
vendored
@ -1,26 +0,0 @@
|
|||||||
*.pyc
|
|
||||||
*.dat
|
|
||||||
TAGS
|
|
||||||
*.egg
|
|
||||||
*.egg-info
|
|
||||||
build
|
|
||||||
.coverage
|
|
||||||
.tox
|
|
||||||
cover
|
|
||||||
venv
|
|
||||||
.venv
|
|
||||||
*.sublime-workspace
|
|
||||||
*.sqlite
|
|
||||||
var/*
|
|
||||||
etc/*.conf
|
|
||||||
etc/*.ini
|
|
||||||
AUTHORS
|
|
||||||
ChangeLog
|
|
||||||
doc/source/api/*
|
|
||||||
doc/build/*
|
|
||||||
dist
|
|
||||||
cueclient/versioninfo
|
|
||||||
.testrepository
|
|
||||||
.idea/
|
|
||||||
*.DS_Store
|
|
||||||
.coverage.*
|
|
@ -1,4 +0,0 @@
|
|||||||
[gerrit]
|
|
||||||
host=review.openstack.org
|
|
||||||
port=29418
|
|
||||||
project=openstack/python-cueclient.git
|
|
@ -1,4 +0,0 @@
|
|||||||
[DEFAULT]
|
|
||||||
test_command=OS_STDOUT_CAPTURE=1 OS_STDERR_CAPTURE=1 ${PYTHON:-python} -m subunit.run discover -t ./ ${TESTS_DIR:-./cueclient/tests/} $LISTOPT $IDOPTION
|
|
||||||
test_id_option=--load-list $IDFILE
|
|
||||||
test_list_option=--list
|
|
176
LICENSE
176
LICENSE
@ -1,176 +0,0 @@
|
|||||||
|
|
||||||
Apache License
|
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
|
||||||
the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
|
||||||
other entities that control, are controlled by, or are under common
|
|
||||||
control with that entity. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
|
||||||
exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
|
||||||
including but not limited to software source code, documentation
|
|
||||||
source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
|
||||||
transformation or translation of a Source form, including but
|
|
||||||
not limited to compiled object code, generated documentation,
|
|
||||||
and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
|
||||||
Object form, made available under the License, as indicated by a
|
|
||||||
copyright notice that is included in or attached to the work
|
|
||||||
(an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
|
||||||
form, that is based on (or derived from) the Work and for which the
|
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
|
||||||
modifications, and in Source or Object form, provided that You
|
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
|
||||||
Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
|
||||||
stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
|
||||||
that You distribute, all copyright, patent, trademark, and
|
|
||||||
attribution notices from the Source form of the Work,
|
|
||||||
excluding those notices that do not pertain to any part of
|
|
||||||
the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
|
||||||
distribution, then any Derivative Works that You distribute must
|
|
||||||
include a readable copy of the attribution notices contained
|
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
|
||||||
may provide additional or different license terms and conditions
|
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
|
||||||
the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
|
||||||
except as required for reasonable and customary use in describing the
|
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
|
||||||
unless required by applicable law (such as deliberate and grossly
|
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
|
||||||
liable to You for damages, including any direct, indirect, special,
|
|
||||||
incidental, or consequential damages of any character arising as a
|
|
||||||
result of this License or out of the use or inability to use the
|
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses), even if such Contributor
|
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
||||||
or other liability obligations and/or rights consistent with this
|
|
||||||
License. However, in accepting such obligations, You may act only
|
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
|
||||||
defend, and hold each Contributor harmless for any liability
|
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
|
||||||
of your accepting any such warranty or additional liability.
|
|
||||||
|
|
14
README.rst
14
README.rst
@ -0,0 +1,14 @@
|
|||||||
|
This project is no longer maintained.
|
||||||
|
|
||||||
|
The contents of this repository are still available in the Git
|
||||||
|
source code management system. To see the contents of this
|
||||||
|
repository before it reached its end of life, please check out the
|
||||||
|
previous commit with "git checkout HEAD^1".
|
||||||
|
|
||||||
|
(Optional:)
|
||||||
|
For an alternative project, please see <alternative project name> at
|
||||||
|
<alternative project URL>.
|
||||||
|
|
||||||
|
For any further questions, please email
|
||||||
|
openstack-dev@lists.openstack.org or join #openstack-dev on
|
||||||
|
Freenode.
|
@ -1,120 +0,0 @@
|
|||||||
# Copyright 2012 Managed I.T.
|
|
||||||
#
|
|
||||||
# Author: Kiall Mac Innes <kiall@managedit.ie>
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
||||||
# not use this file except in compliance with the License. You may obtain
|
|
||||||
# a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
# License for the specific language governing permissions and limitations
|
|
||||||
# under the License.
|
|
||||||
import abc
|
|
||||||
import json
|
|
||||||
|
|
||||||
import six
|
|
||||||
from six.moves.urllib.parse import urlencode
|
|
||||||
|
|
||||||
|
|
||||||
@six.add_metaclass(abc.ABCMeta)
|
|
||||||
class Controller(object):
|
|
||||||
|
|
||||||
def __init__(self, client):
|
|
||||||
self.client = client
|
|
||||||
|
|
||||||
def build_url(self, url, marker=None, limit=None, params=None):
|
|
||||||
params = params or {}
|
|
||||||
|
|
||||||
if marker is not None:
|
|
||||||
params['marker'] = marker
|
|
||||||
if limit is not None:
|
|
||||||
params['limit'] = limit
|
|
||||||
|
|
||||||
q = urlencode(params) if params else ''
|
|
||||||
return '%(url)s%(params)s' % {
|
|
||||||
'url': url,
|
|
||||||
'params': '?%s' % q
|
|
||||||
}
|
|
||||||
|
|
||||||
def _serialize(self, kwargs):
|
|
||||||
if 'data' in kwargs:
|
|
||||||
kwargs['data'] = json.dumps(kwargs['data'])
|
|
||||||
|
|
||||||
def _post(self, url, response_key=None, **kwargs):
|
|
||||||
self._serialize(kwargs)
|
|
||||||
|
|
||||||
resp = self.client.session.post(url, **kwargs)
|
|
||||||
data = resp.json()
|
|
||||||
|
|
||||||
if response_key in data:
|
|
||||||
return data[response_key]
|
|
||||||
return data
|
|
||||||
|
|
||||||
def _get(self, url, response_key=None):
|
|
||||||
resp = self.client.session.get(url)
|
|
||||||
data = resp.json()
|
|
||||||
|
|
||||||
if response_key in data:
|
|
||||||
return data[response_key]
|
|
||||||
return data
|
|
||||||
|
|
||||||
def _patch(self, url, response_key=None, **kwargs):
|
|
||||||
self._serialize(kwargs)
|
|
||||||
|
|
||||||
resp = self.client.session.patch(url, **kwargs)
|
|
||||||
data = resp.json()
|
|
||||||
|
|
||||||
if response_key in data:
|
|
||||||
return data[response_key]
|
|
||||||
return data
|
|
||||||
|
|
||||||
def _put(self, url, response_key=None, **kwargs):
|
|
||||||
self._serialize(kwargs)
|
|
||||||
|
|
||||||
resp = self.client.session.put(url, **kwargs)
|
|
||||||
data = resp.json()
|
|
||||||
|
|
||||||
if response_key in data:
|
|
||||||
return data[response_key]
|
|
||||||
return data
|
|
||||||
|
|
||||||
def _delete(self, url):
|
|
||||||
self.client.session.delete(url)
|
|
||||||
|
|
||||||
|
|
||||||
@six.add_metaclass(abc.ABCMeta)
|
|
||||||
class CrudController(Controller):
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def list(self, *args, **kw):
|
|
||||||
"""
|
|
||||||
List a resource
|
|
||||||
"""
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def get(self, *args, **kw):
|
|
||||||
"""
|
|
||||||
Get a resouce
|
|
||||||
"""
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def create(self, *args, **kw):
|
|
||||||
"""
|
|
||||||
Create a resource
|
|
||||||
"""
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def update(self, *args, **kw):
|
|
||||||
"""
|
|
||||||
Update a resource
|
|
||||||
"""
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def delete(self, *args, **kw):
|
|
||||||
"""
|
|
||||||
Delete a resource
|
|
||||||
"""
|
|
@ -1,49 +0,0 @@
|
|||||||
# Copyright 2014 Hewlett-Packard Development Company, L.P.
|
|
||||||
#
|
|
||||||
# Author: Endre Karlson <endre.karlson@hp.com>
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
||||||
# not use this file except in compliance with the License. You may obtain
|
|
||||||
# a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
# License for the specific language governing permissions and limitations
|
|
||||||
# under the License.
|
|
||||||
from cueclient import utils
|
|
||||||
|
|
||||||
from openstackclient.common import utils as oscutils
|
|
||||||
|
|
||||||
|
|
||||||
DEFAULT_MB_API_VERSION = '1'
|
|
||||||
|
|
||||||
API_NAME = 'mb'
|
|
||||||
API_VERSION_OPTION = 'os_mb_api_version'
|
|
||||||
API_VERSIONS = {
|
|
||||||
'1': 'cueclient.v1.client.Client',
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def make_client(instance):
|
|
||||||
cls = oscutils.get_client_class(
|
|
||||||
API_NAME, instance._api_version[API_NAME],
|
|
||||||
API_VERSIONS)
|
|
||||||
return cls(session=instance.session, interface=instance._interface)
|
|
||||||
|
|
||||||
|
|
||||||
def build_option_parser(parser):
|
|
||||||
"""Hook to add global options."""
|
|
||||||
parser.add_argument(
|
|
||||||
'--os-mb-api-version',
|
|
||||||
metavar='<mb-api-version>',
|
|
||||||
default=utils.env(
|
|
||||||
'OS_MB_API_VERSION',
|
|
||||||
default=DEFAULT_MB_API_VERSION),
|
|
||||||
help='MB API version, default=' +
|
|
||||||
DEFAULT_MB_API_VERSION +
|
|
||||||
' (Env: OS_MB_API_VERSION)')
|
|
||||||
|
|
||||||
return parser
|
|
@ -1,68 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-04/schema",
|
|
||||||
"name": "Cluster",
|
|
||||||
"title": "Cluster",
|
|
||||||
"type" : "object",
|
|
||||||
|
|
||||||
"properties": {
|
|
||||||
"id": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Cluster Identifier",
|
|
||||||
"pattern": "^([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}$"
|
|
||||||
},
|
|
||||||
"name": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Cluster name",
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
"network_id": {
|
|
||||||
"type": "array",
|
|
||||||
"description": "Network Identifier",
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
"status": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Cluster status"
|
|
||||||
},
|
|
||||||
"created_at": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Date and time of cluster creation",
|
|
||||||
"format": "date-time"
|
|
||||||
},
|
|
||||||
"updated_at": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Date and time of cluster update",
|
|
||||||
"format": "date-time"
|
|
||||||
},
|
|
||||||
"endpoints": {
|
|
||||||
"type": [
|
|
||||||
"array",
|
|
||||||
"null"
|
|
||||||
],
|
|
||||||
"description": "Cluster endpoints"
|
|
||||||
},
|
|
||||||
"flavor": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Cluster flavor",
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"type": "integer",
|
|
||||||
"description": "Cluster size",
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
"volume_size": {
|
|
||||||
"type": [
|
|
||||||
"integer",
|
|
||||||
"null"
|
|
||||||
],
|
|
||||||
"description": "Cluster volume"
|
|
||||||
},
|
|
||||||
"error_detail": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Cluster error description"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
"additionalProperties": false
|
|
||||||
}
|
|
@ -1,67 +0,0 @@
|
|||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
||||||
# not use this file except in compliance with the License. You may obtain
|
|
||||||
# a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
# License for the specific language governing permissions and limitations
|
|
||||||
# under the License.
|
|
||||||
#
|
|
||||||
|
|
||||||
import argparse
|
|
||||||
|
|
||||||
import mock
|
|
||||||
from oslo_serialization import jsonutils
|
|
||||||
from requests_mock.contrib import fixture as requests_mock_fixture
|
|
||||||
import six
|
|
||||||
import testtools
|
|
||||||
|
|
||||||
from cueclient.tests.fixture_data import V1
|
|
||||||
|
|
||||||
|
|
||||||
class TestCueBase(testtools.TestCase):
|
|
||||||
def setUp(self):
|
|
||||||
super(TestCueBase, self).setUp()
|
|
||||||
self.requests = self.useFixture(requests_mock_fixture.Fixture())
|
|
||||||
fix = V1(self.requests)
|
|
||||||
client_fixture = self.useFixture(fix)
|
|
||||||
cs = client_fixture.client
|
|
||||||
|
|
||||||
# Build up a fake app
|
|
||||||
self.app = mock.Mock()
|
|
||||||
self.app.client_manager = mock.Mock()
|
|
||||||
self.app.client_manager.mb = cs
|
|
||||||
|
|
||||||
def check_parser(self, cmd, args, verify_args):
|
|
||||||
"""Test for parsing arguments"""
|
|
||||||
cmd_parser = cmd.get_parser('check_parser')
|
|
||||||
parsed_args = cmd_parser.parse_args(args)
|
|
||||||
|
|
||||||
for av in verify_args:
|
|
||||||
attr, value = av
|
|
||||||
if attr:
|
|
||||||
self.assertIn(attr, parsed_args)
|
|
||||||
self.assertEqual(getattr(parsed_args, attr), value)
|
|
||||||
return parsed_args
|
|
||||||
|
|
||||||
def execute(self, cmd_class, arglist, verifylist):
|
|
||||||
cmd = cmd_class(self.app, argparse.Namespace())
|
|
||||||
parsed_args = self.check_parser(cmd, arglist, verifylist)
|
|
||||||
data = cmd.take_action(parsed_args)
|
|
||||||
return data
|
|
||||||
|
|
||||||
def assert_called(self, method, path, body=None):
|
|
||||||
self.assertEqual(self.requests.last_request.method, method)
|
|
||||||
self.assertEqual(self.requests.last_request.path_url, path)
|
|
||||||
|
|
||||||
if body:
|
|
||||||
req_data = self.requests.last_request.body
|
|
||||||
if isinstance(req_data, six.binary_type):
|
|
||||||
req_data = req_data.decode('utf-8')
|
|
||||||
if not isinstance(body, six.string_types):
|
|
||||||
# json load if the input body to match against is not a string
|
|
||||||
req_data = jsonutils.loads(req_data)
|
|
||||||
self.assertEqual(body, req_data)
|
|
@ -1,113 +0,0 @@
|
|||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
||||||
# not use this file except in compliance with the License. You may obtain
|
|
||||||
# a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
# License for the specific language governing permissions and limitations
|
|
||||||
# under the License.
|
|
||||||
|
|
||||||
import fixtures
|
|
||||||
from keystoneauth1 import session
|
|
||||||
from six.moves.urllib import parse
|
|
||||||
|
|
||||||
from cueclient.v1 import client
|
|
||||||
|
|
||||||
MESSAGE_BROKER_URL = 'http://message.broker'
|
|
||||||
|
|
||||||
|
|
||||||
class V1(fixtures.Fixture):
|
|
||||||
|
|
||||||
base_url = 'clusters'
|
|
||||||
json_headers = {'Content-Type': 'application/json'}
|
|
||||||
|
|
||||||
def __init__(self, requests):
|
|
||||||
super(V1, self).__init__()
|
|
||||||
self.client = None
|
|
||||||
self.requests = requests
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
super(V1, self).setUp()
|
|
||||||
|
|
||||||
self.cluster_1234 = {
|
|
||||||
"name": "test-cluster",
|
|
||||||
"id": "00000000-0000-0000-0000-000000001234",
|
|
||||||
"size": 1,
|
|
||||||
"network_id": ["05860da0-e2bd-4315-9cfb-7dd6e9963cd9"],
|
|
||||||
"created_at": "2015-01-01T00:00:00+00:00",
|
|
||||||
"endpoints": [],
|
|
||||||
"flavor": "1",
|
|
||||||
"status": "ACTIVE",
|
|
||||||
}
|
|
||||||
|
|
||||||
self.cluster_5678 = {
|
|
||||||
"name": "test-cluster2",
|
|
||||||
"id": "00000000-0000-0000-0000-000000005678",
|
|
||||||
"size": 3,
|
|
||||||
"network_id": ["05567na0-f7aa-6820-7afcd-7dd6e9963cd9"],
|
|
||||||
"created_at": "2015-01-01T00:00:00+00:00",
|
|
||||||
"endpoints": [],
|
|
||||||
"flavor": "1",
|
|
||||||
"status": "BUILDING",
|
|
||||||
}
|
|
||||||
|
|
||||||
self.cluster_error = {
|
|
||||||
"name": "test-cluster3",
|
|
||||||
"id": "00000000-0000-0000-0000-000000008765",
|
|
||||||
"size": 3,
|
|
||||||
"network_id": ["05567na0-f7aa-6820-7afcd-7dd6e9963cd9"],
|
|
||||||
"created_at": "2015-01-01T00:00:00+00:00",
|
|
||||||
"endpoints": [],
|
|
||||||
"flavor": "1",
|
|
||||||
"status": "ERROR",
|
|
||||||
"error_detail": "cluster error detailed message",
|
|
||||||
}
|
|
||||||
|
|
||||||
self.new_cluster = {
|
|
||||||
"name": "new-test-cluster",
|
|
||||||
"id": "00000000-0000-0000-0000-000000009012",
|
|
||||||
"size": 3,
|
|
||||||
"network_id": ["05567na0-f7aa-6820-7afcd-7dd6e9963cd9"],
|
|
||||||
"created_at": "2015-01-01T00:00:00+00:00",
|
|
||||||
"endpoints": [],
|
|
||||||
"flavor": "1",
|
|
||||||
"status": "BUILDING",
|
|
||||||
}
|
|
||||||
|
|
||||||
clusters = [self.cluster_1234, self.cluster_5678, self.cluster_error]
|
|
||||||
|
|
||||||
self.requests.register_uri('GET', self.url(),
|
|
||||||
json=clusters,
|
|
||||||
headers=self.json_headers)
|
|
||||||
|
|
||||||
for cluster in clusters:
|
|
||||||
self.requests.register_uri('GET', self.url(cluster['id']),
|
|
||||||
json=cluster,
|
|
||||||
headers=self.json_headers)
|
|
||||||
|
|
||||||
for cluster in clusters:
|
|
||||||
self.requests.register_uri('DELETE', self.url(cluster['id']),
|
|
||||||
status_code=202)
|
|
||||||
|
|
||||||
self.requests.register_uri('POST', self.url(),
|
|
||||||
json=self.new_cluster,
|
|
||||||
headers=self.json_headers)
|
|
||||||
|
|
||||||
self.client = client.Client(session=session.Session())
|
|
||||||
self.client.session.endpoint_override = MESSAGE_BROKER_URL
|
|
||||||
|
|
||||||
def url(self, *args, **kwargs):
|
|
||||||
url_args = [MESSAGE_BROKER_URL]
|
|
||||||
|
|
||||||
if self.base_url:
|
|
||||||
url_args.append(self.base_url)
|
|
||||||
|
|
||||||
url = '/'.join(str(a).strip('/') for a in tuple(url_args) + args)
|
|
||||||
|
|
||||||
if kwargs:
|
|
||||||
url += '?%s' % parse.urlencode(kwargs, doseq=True)
|
|
||||||
|
|
||||||
return url
|
|
@ -1,318 +0,0 @@
|
|||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
||||||
# not use this file except in compliance with the License. You may obtain
|
|
||||||
# a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
# License for the specific language governing permissions and limitations
|
|
||||||
# under the License.
|
|
||||||
#
|
|
||||||
|
|
||||||
from cueclient.tests import base
|
|
||||||
from cueclient.v1.cli import clusters
|
|
||||||
|
|
||||||
|
|
||||||
class TestListClusters(base.TestCueBase):
|
|
||||||
|
|
||||||
def test_list_clusters(self):
|
|
||||||
"""test cluster list."""
|
|
||||||
arglist = []
|
|
||||||
verifylist = []
|
|
||||||
expected = {'00000000-0000-0000-0000-000000001234':
|
|
||||||
('00000000-0000-0000-0000-000000001234',
|
|
||||||
'test-cluster', 'ACTIVE', 1, []),
|
|
||||||
'00000000-0000-0000-0000-000000005678':
|
|
||||||
('00000000-0000-0000-0000-000000005678',
|
|
||||||
'test-cluster2', 'BUILDING', 3, []),
|
|
||||||
'00000000-0000-0000-0000-000000008765':
|
|
||||||
('00000000-0000-0000-0000-000000008765',
|
|
||||||
'test-cluster3', 'ERROR', 3, [])}
|
|
||||||
|
|
||||||
result = self.execute(clusters.ListClustersCommand, arglist,
|
|
||||||
verifylist)
|
|
||||||
self.assertEqual(['id', 'name', 'status', 'size', 'endpoints'],
|
|
||||||
result[0])
|
|
||||||
self.assert_called('GET', '/clusters')
|
|
||||||
for cluster in result[1]:
|
|
||||||
self.assertEqual(expected[cluster[0]], cluster)
|
|
||||||
|
|
||||||
|
|
||||||
class TestShowCluster(base.TestCueBase):
|
|
||||||
|
|
||||||
def test_show_cluster(self):
|
|
||||||
"""test cluster show."""
|
|
||||||
cluster_id = '00000000-0000-0000-0000-000000001234'
|
|
||||||
arglist = [cluster_id]
|
|
||||||
verifylist = []
|
|
||||||
|
|
||||||
result = self.execute(clusters.ShowClusterCommand, arglist, verifylist)
|
|
||||||
expected = [('created_at', 'endpoints', 'flavor', 'id', 'name',
|
|
||||||
'network_id', 'size', 'status'),
|
|
||||||
(u'2015-01-01T00:00:00+00:00', [], '1',
|
|
||||||
'00000000-0000-0000-0000-000000001234',
|
|
||||||
'test-cluster', [u'05860da0-e2bd-4315-9cfb-7dd6e9963cd9'],
|
|
||||||
1, 'ACTIVE')]
|
|
||||||
self.assert_called('GET', '/clusters/' + cluster_id)
|
|
||||||
self.assertEqual(expected, result)
|
|
||||||
|
|
||||||
def test_show_cluster_error(self):
|
|
||||||
"""test cluster show when in error state."""
|
|
||||||
cluster_id = '00000000-0000-0000-0000-000000008765'
|
|
||||||
arglist = [cluster_id]
|
|
||||||
verifylist = []
|
|
||||||
|
|
||||||
result = self.execute(clusters.ShowClusterCommand, arglist, verifylist)
|
|
||||||
expected = [('created_at', 'endpoints', 'error_detail', 'flavor', 'id',
|
|
||||||
'name', 'network_id', 'size', 'status'),
|
|
||||||
(u'2015-01-01T00:00:00+00:00', [],
|
|
||||||
'cluster error detailed message', '1',
|
|
||||||
'00000000-0000-0000-0000-000000008765',
|
|
||||||
'test-cluster3',
|
|
||||||
[u'05567na0-f7aa-6820-7afcd-7dd6e9963cd9'],
|
|
||||||
3, 'ERROR')]
|
|
||||||
self.assert_called('GET', '/clusters/' + cluster_id)
|
|
||||||
self.assertEqual(expected, result)
|
|
||||||
|
|
||||||
def test_show_cluster_without_id(self):
|
|
||||||
"""test show cluster without specifying cluster id"""
|
|
||||||
|
|
||||||
arglist = []
|
|
||||||
verifylist = []
|
|
||||||
|
|
||||||
self.assertRaises(SystemExit, self.execute,
|
|
||||||
clusters.ShowClusterCommand, arglist, verifylist)
|
|
||||||
|
|
||||||
|
|
||||||
class TestCreateCluster(base.TestCueBase):
|
|
||||||
|
|
||||||
cluster_name = "test_Cluster"
|
|
||||||
cluster_network_id = "9d6708ee-ea48-4e78-bef6-b50b48405091"
|
|
||||||
cluster_flavor = "1"
|
|
||||||
cluster_size = "2"
|
|
||||||
auth = "type=plain,user=rabbitmq,pass=rabbit"
|
|
||||||
|
|
||||||
def test_create_cluster(self):
|
|
||||||
arglist = ["--name", self.cluster_name,
|
|
||||||
"--nic", self.cluster_network_id,
|
|
||||||
"--flavor", self.cluster_flavor,
|
|
||||||
"--size", self.cluster_size]
|
|
||||||
verifylist = [
|
|
||||||
('name', self.cluster_name),
|
|
||||||
('nic', self.cluster_network_id),
|
|
||||||
('flavor', self.cluster_flavor),
|
|
||||||
('size', self.cluster_size)
|
|
||||||
]
|
|
||||||
|
|
||||||
request_body = {'name': self.cluster_name,
|
|
||||||
'network_id': [self.cluster_network_id],
|
|
||||||
'flavor': self.cluster_flavor,
|
|
||||||
'size': self.cluster_size,
|
|
||||||
'volume_size': None,
|
|
||||||
'authentication': {'type': 'plain',
|
|
||||||
'token': {'username': None,
|
|
||||||
'password': None}}}
|
|
||||||
|
|
||||||
self.execute(clusters.CreateClusterCommand, arglist, verifylist)
|
|
||||||
self.assert_called('POST', '/clusters', request_body)
|
|
||||||
|
|
||||||
def test_create_cluster_rabbit_auth(self):
|
|
||||||
arglist = ["--name", self.cluster_name,
|
|
||||||
"--nic", self.cluster_network_id,
|
|
||||||
"--flavor", self.cluster_flavor,
|
|
||||||
"--size", self.cluster_size,
|
|
||||||
"--auth", self.auth,
|
|
||||||
]
|
|
||||||
verifylist = [
|
|
||||||
('name', self.cluster_name),
|
|
||||||
('nic', self.cluster_network_id),
|
|
||||||
('flavor', self.cluster_flavor),
|
|
||||||
('size', self.cluster_size),
|
|
||||||
('auth', self.auth),
|
|
||||||
]
|
|
||||||
|
|
||||||
request_body = {'name': self.cluster_name,
|
|
||||||
'network_id': [self.cluster_network_id],
|
|
||||||
'flavor': self.cluster_flavor,
|
|
||||||
'size': self.cluster_size,
|
|
||||||
'volume_size': None,
|
|
||||||
'authentication': {'type': 'plain',
|
|
||||||
'token': {'username': 'rabbitmq',
|
|
||||||
'password': 'rabbit'}}}
|
|
||||||
|
|
||||||
self.execute(clusters.CreateClusterCommand, arglist, verifylist)
|
|
||||||
self.assert_called('POST', '/clusters', request_body)
|
|
||||||
|
|
||||||
def test_create_cluster_rabbit_auth_type_missing(self):
|
|
||||||
|
|
||||||
arglist = ["--name", self.cluster_name,
|
|
||||||
"--nic", self.cluster_network_id,
|
|
||||||
"--flavor", self.cluster_flavor,
|
|
||||||
"--size", self.cluster_size,
|
|
||||||
"--auth", "user=rabbitmq,pass=rabbit",
|
|
||||||
]
|
|
||||||
verifylist = [
|
|
||||||
('name', self.cluster_name),
|
|
||||||
('nic', self.cluster_network_id),
|
|
||||||
('flavor', self.cluster_flavor),
|
|
||||||
('size', self.cluster_size),
|
|
||||||
('auth', "user=rabbitmq,pass=rabbit"),
|
|
||||||
]
|
|
||||||
|
|
||||||
request_body = {'name': self.cluster_name,
|
|
||||||
'network_id': [self.cluster_network_id],
|
|
||||||
'flavor': self.cluster_flavor,
|
|
||||||
'size': self.cluster_size,
|
|
||||||
'volume_size': None,
|
|
||||||
'authentication': {'type': 'plain',
|
|
||||||
'token': {'username': 'rabbitmq',
|
|
||||||
'password': 'rabbit'}}}
|
|
||||||
|
|
||||||
self.execute(clusters.CreateClusterCommand, arglist, verifylist)
|
|
||||||
self.assert_called('POST', '/clusters', request_body)
|
|
||||||
|
|
||||||
def test_create_cluster_rabbit_auth_type_empty(self):
|
|
||||||
|
|
||||||
arglist = ["--name", self.cluster_name,
|
|
||||||
"--nic", self.cluster_network_id,
|
|
||||||
"--flavor", self.cluster_flavor,
|
|
||||||
"--size", self.cluster_size,
|
|
||||||
"--auth", "type=,user=rabbitmq,pass=rabbit",
|
|
||||||
]
|
|
||||||
verifylist = [
|
|
||||||
('name', self.cluster_name),
|
|
||||||
('nic', self.cluster_network_id),
|
|
||||||
('flavor', self.cluster_flavor),
|
|
||||||
('size', self.cluster_size),
|
|
||||||
('auth', "type=,user=rabbitmq,pass=rabbit"),
|
|
||||||
]
|
|
||||||
|
|
||||||
request_body = {'name': self.cluster_name,
|
|
||||||
'network_id': [self.cluster_network_id],
|
|
||||||
'flavor': self.cluster_flavor,
|
|
||||||
'size': self.cluster_size,
|
|
||||||
'volume_size': None,
|
|
||||||
'authentication': {'type': 'plain',
|
|
||||||
'token': {'username': 'rabbitmq',
|
|
||||||
'password': 'rabbit'}}}
|
|
||||||
|
|
||||||
self.execute(clusters.CreateClusterCommand, arglist, verifylist)
|
|
||||||
self.assert_called('POST', '/clusters', request_body)
|
|
||||||
|
|
||||||
def test_create_cluster_rabbit_auth_user_missing(self):
|
|
||||||
|
|
||||||
arglist = ["--name", self.cluster_name,
|
|
||||||
"--nic", self.cluster_network_id,
|
|
||||||
"--flavor", self.cluster_flavor,
|
|
||||||
"--size", self.cluster_size,
|
|
||||||
"--auth", "type=plain,pass=rabbit",
|
|
||||||
]
|
|
||||||
verifylist = [
|
|
||||||
('name', self.cluster_name),
|
|
||||||
('nic', self.cluster_network_id),
|
|
||||||
('flavor', self.cluster_flavor),
|
|
||||||
('size', self.cluster_size),
|
|
||||||
('auth', "type=plain,pass=rabbit"),
|
|
||||||
]
|
|
||||||
|
|
||||||
request_body = {'name': self.cluster_name,
|
|
||||||
'network_id': [self.cluster_network_id],
|
|
||||||
'flavor': self.cluster_flavor,
|
|
||||||
'size': self.cluster_size,
|
|
||||||
'volume_size': None,
|
|
||||||
'authentication': {'type': 'plain',
|
|
||||||
'token': {'username': None,
|
|
||||||
'password': 'rabbit'}}}
|
|
||||||
|
|
||||||
self.execute(clusters.CreateClusterCommand, arglist, verifylist)
|
|
||||||
self.assert_called('POST', '/clusters', request_body)
|
|
||||||
|
|
||||||
def test_create_cluster_rabbit_auth_password_missing(self):
|
|
||||||
|
|
||||||
arglist = ["--name", self.cluster_name,
|
|
||||||
"--nic", self.cluster_network_id,
|
|
||||||
"--flavor", self.cluster_flavor,
|
|
||||||
"--size", self.cluster_size,
|
|
||||||
"--auth", "type=plain,user=rabbitmq",
|
|
||||||
]
|
|
||||||
verifylist = [
|
|
||||||
('name', self.cluster_name),
|
|
||||||
('nic', self.cluster_network_id),
|
|
||||||
('flavor', self.cluster_flavor),
|
|
||||||
('size', self.cluster_size),
|
|
||||||
('auth', "type=plain,user=rabbitmq"),
|
|
||||||
]
|
|
||||||
|
|
||||||
request_body = {'name': self.cluster_name,
|
|
||||||
'network_id': [self.cluster_network_id],
|
|
||||||
'flavor': self.cluster_flavor,
|
|
||||||
'size': self.cluster_size,
|
|
||||||
'volume_size': None,
|
|
||||||
'authentication': {'type': 'plain',
|
|
||||||
'token': {'username': 'rabbitmq',
|
|
||||||
'password': None}}}
|
|
||||||
|
|
||||||
self.execute(clusters.CreateClusterCommand, arglist, verifylist)
|
|
||||||
self.assert_called('POST', '/clusters', request_body)
|
|
||||||
|
|
||||||
def test_create_cluster_without_name(self):
|
|
||||||
"""test create cluster without 'name' argument."""
|
|
||||||
|
|
||||||
arglist = ["--nic", self.cluster_network_id,
|
|
||||||
"--flavor", self.cluster_flavor,
|
|
||||||
"--size", self.cluster_size]
|
|
||||||
verifylist = []
|
|
||||||
self.assertRaises(SystemExit, self.execute,
|
|
||||||
clusters.CreateClusterCommand, arglist, verifylist)
|
|
||||||
|
|
||||||
def test_create_cluster_without_nic(self):
|
|
||||||
"""test create cluster without 'network_id' argument."""
|
|
||||||
|
|
||||||
arglist = ["--name", self.cluster_name,
|
|
||||||
"--flavor", self.cluster_flavor,
|
|
||||||
"--size", self.cluster_size]
|
|
||||||
verifylist = []
|
|
||||||
self.assertRaises(SystemExit, self.execute,
|
|
||||||
clusters.CreateClusterCommand, arglist, verifylist)
|
|
||||||
|
|
||||||
def test_create_cluster_without_flavor(self):
|
|
||||||
"""test create cluster without 'flavor' argument."""
|
|
||||||
|
|
||||||
arglist = ["--name", self.cluster_name,
|
|
||||||
"--nic", self.cluster_network_id,
|
|
||||||
"--size", self.cluster_size]
|
|
||||||
verifylist = []
|
|
||||||
self.assertRaises(SystemExit, self.execute,
|
|
||||||
clusters.CreateClusterCommand, arglist, verifylist)
|
|
||||||
|
|
||||||
def test_create_cluster_without_size(self):
|
|
||||||
"""test create cluster without 'size' argument."""
|
|
||||||
|
|
||||||
arglist = ["--name", self.cluster_name,
|
|
||||||
"--nic", self.cluster_network_id,
|
|
||||||
"--flavor", self.cluster_flavor]
|
|
||||||
verifylist = []
|
|
||||||
self.assertRaises(SystemExit, self.execute,
|
|
||||||
clusters.CreateClusterCommand, arglist, verifylist)
|
|
||||||
|
|
||||||
|
|
||||||
class TestDeleteCluster(base.TestCueBase):
|
|
||||||
|
|
||||||
def test_delete_cluster_without_id(self):
|
|
||||||
"""test delete cluster without giving cluster id"""
|
|
||||||
arglist = []
|
|
||||||
verifylist = []
|
|
||||||
self.assertRaises(SystemExit, self.execute,
|
|
||||||
clusters.DeleteClusterCommand, arglist, verifylist)
|
|
||||||
|
|
||||||
def test_delete_cluster(self):
|
|
||||||
"""test delete cluster"""
|
|
||||||
cluster_id = '00000000-0000-0000-0000-000000001234'
|
|
||||||
arglist = [cluster_id]
|
|
||||||
verifylist = []
|
|
||||||
result = self.execute(clusters.DeleteClusterCommand, arglist,
|
|
||||||
verifylist)
|
|
||||||
self.assert_called('DELETE', '/clusters/' + cluster_id)
|
|
||||||
self.assertIsNone(result)
|
|
@ -1,88 +0,0 @@
|
|||||||
# Copyright 2015 Hewlett-Packard Development Company, L.P.
|
|
||||||
# Copyright 2012-2013 OpenStack Foundation
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
||||||
# not use this file except in compliance with the License. You may obtain
|
|
||||||
# a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
# License for the specific language governing permissions and limitations
|
|
||||||
# under the License.
|
|
||||||
#
|
|
||||||
import json
|
|
||||||
import os
|
|
||||||
|
|
||||||
import pkg_resources
|
|
||||||
|
|
||||||
|
|
||||||
def env(*vars, **kwargs):
|
|
||||||
"""Search for the first defined of possibly many env vars
|
|
||||||
|
|
||||||
Returns the first environment variable defined in vars, or
|
|
||||||
returns the default defined in kwargs.
|
|
||||||
|
|
||||||
"""
|
|
||||||
for v in vars:
|
|
||||||
value = os.environ.get(v)
|
|
||||||
if value:
|
|
||||||
return value
|
|
||||||
return kwargs.get('default', '')
|
|
||||||
|
|
||||||
|
|
||||||
def get_item_properties(item, fields, mixed_case_fields=[], formatters={}):
|
|
||||||
"""Return a tuple containing the item properties.
|
|
||||||
|
|
||||||
:param item: a single dict resource
|
|
||||||
:param fields: tuple of strings with the desired field names
|
|
||||||
:param mixed_case_fields: tuple of field names to preserve case
|
|
||||||
:param formatters: dictionary mapping field names to callables
|
|
||||||
to format the values
|
|
||||||
"""
|
|
||||||
row = []
|
|
||||||
for field in fields:
|
|
||||||
if field in mixed_case_fields:
|
|
||||||
field_name = field.replace(' ', '_')
|
|
||||||
else:
|
|
||||||
field_name = field.lower().replace(' ', '_')
|
|
||||||
data = item[field_name] if field_name in item else ''
|
|
||||||
if field in formatters:
|
|
||||||
row.append(formatters[field](data))
|
|
||||||
else:
|
|
||||||
row.append(data)
|
|
||||||
return tuple(row)
|
|
||||||
|
|
||||||
|
|
||||||
def resource_filename(*args, **kwargs):
|
|
||||||
"""Return specified resource as a string"""
|
|
||||||
if len(args) == 0:
|
|
||||||
raise ValueError()
|
|
||||||
|
|
||||||
package = kwargs.pop('package', None)
|
|
||||||
|
|
||||||
if not package:
|
|
||||||
package = 'cueclient'
|
|
||||||
|
|
||||||
resource_path = os.path.join('resources', *args)
|
|
||||||
|
|
||||||
if not pkg_resources.resource_exists(package, resource_path):
|
|
||||||
# TODO(ap): add exceptions
|
|
||||||
# raise exceptions.ResourceNotFound('Could not find the requested '
|
|
||||||
# 'resource: %s' % resource_path)
|
|
||||||
pass
|
|
||||||
|
|
||||||
return pkg_resources.resource_filename(package, resource_path)
|
|
||||||
|
|
||||||
|
|
||||||
def load_schema(version, name, package=None):
|
|
||||||
"""Load json schema from resources"""
|
|
||||||
schema_filename = resource_filename('schemas', version, '%s.json' % name,
|
|
||||||
package=package)
|
|
||||||
|
|
||||||
with open(schema_filename) as schema_file:
|
|
||||||
schema_json = json.load(schema_file)
|
|
||||||
|
|
||||||
return schema_json
|
|
@ -1,171 +0,0 @@
|
|||||||
# Copyright 2014 Hewlett-Packard Development Company, L.P.
|
|
||||||
#
|
|
||||||
# Author: Endre Karlson <endre.karlson@hp.com>
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
||||||
# not use this file except in compliance with the License. You may obtain
|
|
||||||
# a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
# License for the specific language governing permissions and limitations
|
|
||||||
# under the License.
|
|
||||||
|
|
||||||
import logging
|
|
||||||
|
|
||||||
from cliff import command
|
|
||||||
from cliff import lister
|
|
||||||
from cliff import show
|
|
||||||
import six
|
|
||||||
|
|
||||||
from cueclient import utils
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class ListClustersCommand(lister.Lister):
|
|
||||||
"""List Clusters"""
|
|
||||||
|
|
||||||
columns = ['id', 'name', 'status', 'size', 'endpoints']
|
|
||||||
|
|
||||||
def get_parser(self, prog_name):
|
|
||||||
parser = super(ListClustersCommand, self).get_parser(prog_name)
|
|
||||||
|
|
||||||
return parser
|
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
|
||||||
client = self.app.client_manager.mb
|
|
||||||
|
|
||||||
data = client.clusters.list()
|
|
||||||
|
|
||||||
cols = self.columns
|
|
||||||
return cols, (utils.get_item_properties(s, cols) for s in data)
|
|
||||||
|
|
||||||
|
|
||||||
class ShowClusterCommand(show.ShowOne):
|
|
||||||
"""Show Cluster"""
|
|
||||||
def get_parser(self, prog_name):
|
|
||||||
parser = super(ShowClusterCommand, self).get_parser(prog_name)
|
|
||||||
|
|
||||||
parser.add_argument('id', help="Cluster ID")
|
|
||||||
|
|
||||||
return parser
|
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
|
||||||
client = self.app.client_manager.mb
|
|
||||||
|
|
||||||
data = client.clusters.get(parsed_args.id)
|
|
||||||
|
|
||||||
return zip(*sorted(six.iteritems(data)))
|
|
||||||
|
|
||||||
|
|
||||||
class CreateClusterCommand(show.ShowOne):
|
|
||||||
"""Create Cluster"""
|
|
||||||
|
|
||||||
def get_parser(self, prog_name):
|
|
||||||
parser = super(CreateClusterCommand, self).get_parser(prog_name)
|
|
||||||
|
|
||||||
parser.add_argument('--name', help="Cluster Name", required=True)
|
|
||||||
parser.add_argument('--nic', help="Network to place nodes on",
|
|
||||||
required=True)
|
|
||||||
parser.add_argument('--flavor', help="Flavor to use.", required=True)
|
|
||||||
parser.add_argument('--size', help="Number of nodes", required=True)
|
|
||||||
|
|
||||||
parser.add_argument('--volume_size', help="Volume size")
|
|
||||||
parser.add_argument('--auth',
|
|
||||||
metavar="<type=type,user=user,pass=pass>",
|
|
||||||
help="broker authentication,"
|
|
||||||
"type=type,user=user,pass=pass")
|
|
||||||
|
|
||||||
return parser
|
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
|
||||||
client = self.app.client_manager.mb
|
|
||||||
|
|
||||||
auth_type = username = password = None
|
|
||||||
if parsed_args.auth:
|
|
||||||
for kv_str in parsed_args.auth.split(","):
|
|
||||||
k, v = kv_str.split("=")
|
|
||||||
if 'type' == k:
|
|
||||||
auth_type = v
|
|
||||||
elif 'user' == k:
|
|
||||||
username = v
|
|
||||||
elif 'pass' == k:
|
|
||||||
password = v
|
|
||||||
if not auth_type:
|
|
||||||
auth_type = 'plain'
|
|
||||||
data = client.clusters.create(
|
|
||||||
name=parsed_args.name,
|
|
||||||
nic=parsed_args.nic,
|
|
||||||
flavor=parsed_args.flavor,
|
|
||||||
size=parsed_args.size,
|
|
||||||
volume_size=parsed_args.volume_size,
|
|
||||||
auth_type=auth_type,
|
|
||||||
username=username,
|
|
||||||
password=password)
|
|
||||||
|
|
||||||
return zip(*sorted(six.iteritems(data)))
|
|
||||||
|
|
||||||
|
|
||||||
class SetClusterCommand(command.Command):
|
|
||||||
"""Set Cluster"""
|
|
||||||
|
|
||||||
def get_parser(self, prog_name):
|
|
||||||
parser = super(SetClusterCommand, self).get_parser(prog_name)
|
|
||||||
|
|
||||||
parser.add_argument('id', help="Cluster ID")
|
|
||||||
parser.add_argument('--name', help="Cluster Name")
|
|
||||||
parser.add_argument('--email', help="Cluster Email")
|
|
||||||
parser.add_argument('--ttl', type=int, help="Time To Live (Seconds)")
|
|
||||||
description_group = parser.add_mutually_exclusive_group()
|
|
||||||
description_group.add_argument('--description', help="Description")
|
|
||||||
description_group.add_argument('--no-description', action='store_true')
|
|
||||||
|
|
||||||
parser.add_argument('--masters', help="Cluster Masters", nargs='+')
|
|
||||||
|
|
||||||
return parser
|
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
|
||||||
client = self.app.client_manager.mb
|
|
||||||
|
|
||||||
data = {}
|
|
||||||
|
|
||||||
# TODO(kiall): API needs updating.. this get is silly
|
|
||||||
if parsed_args.name:
|
|
||||||
data['name'] = parsed_args.name
|
|
||||||
|
|
||||||
if parsed_args.email:
|
|
||||||
data['email'] = parsed_args.email
|
|
||||||
|
|
||||||
if parsed_args.ttl:
|
|
||||||
data['ttl'] = parsed_args.ttl
|
|
||||||
|
|
||||||
if parsed_args.no_description:
|
|
||||||
data['description'] = None
|
|
||||||
elif parsed_args.description:
|
|
||||||
data['description'] = parsed_args.description
|
|
||||||
|
|
||||||
if parsed_args.masters:
|
|
||||||
data['masters'] = parsed_args.masters
|
|
||||||
|
|
||||||
updated = client.clusters.update(parsed_args.id, data)
|
|
||||||
return zip(*sorted(six.iteritems(updated)))
|
|
||||||
|
|
||||||
|
|
||||||
class DeleteClusterCommand(command.Command):
|
|
||||||
"""Delete Cluster"""
|
|
||||||
|
|
||||||
def get_parser(self, prog_name):
|
|
||||||
parser = super(DeleteClusterCommand, self).get_parser(prog_name)
|
|
||||||
|
|
||||||
parser.add_argument('id', help="Cluster ID")
|
|
||||||
|
|
||||||
return parser
|
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
|
||||||
client = self.app.client_manager.mb
|
|
||||||
client.clusters.delete(parsed_args.id)
|
|
||||||
LOG.info('Cluster %s was deleted', parsed_args.id)
|
|
@ -1,39 +0,0 @@
|
|||||||
# Copyright 2014 Hewlett-Packard Development Company, L.P.
|
|
||||||
#
|
|
||||||
# Author: Endre Karlson <endre.karlson@hp.com>
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
||||||
# not use this file except in compliance with the License. You may obtain
|
|
||||||
# a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
# License for the specific language governing permissions and limitations
|
|
||||||
# under the License.
|
|
||||||
from keystoneauth1 import adapter
|
|
||||||
|
|
||||||
from cueclient.v1.clusters import ClusterController
|
|
||||||
from cueclient import version
|
|
||||||
|
|
||||||
|
|
||||||
class Client(object):
|
|
||||||
def __init__(self, region_name=None, endpoint_type='publicURL',
|
|
||||||
extensions=None, service_type='message-broker',
|
|
||||||
service_name=None, http_log_debug=False, session=None,
|
|
||||||
auth=None, interface=None):
|
|
||||||
|
|
||||||
if interface is None:
|
|
||||||
interface = endpoint_type.rstrip('URL')
|
|
||||||
self.session = adapter.Adapter(
|
|
||||||
session,
|
|
||||||
auth=auth,
|
|
||||||
region_name=region_name,
|
|
||||||
service_type=service_type,
|
|
||||||
interface=interface,
|
|
||||||
user_agent='python-cueclient-%s' % version.version_info,
|
|
||||||
version=('1'))
|
|
||||||
|
|
||||||
self.clusters = ClusterController(self)
|
|
@ -1,70 +0,0 @@
|
|||||||
# Copyright 2014 Hewlett-Packard Development Company, L.P.
|
|
||||||
#
|
|
||||||
# Author: Endre Karlson <endre.karlson@hp.com>
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
||||||
# not use this file except in compliance with the License. You may obtain
|
|
||||||
# a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
# License for the specific language governing permissions and limitations
|
|
||||||
# under the License.
|
|
||||||
from cueclient import controller
|
|
||||||
from cueclient import utils
|
|
||||||
from cueclient import warlock
|
|
||||||
|
|
||||||
Cluster = warlock.model_factory(utils.load_schema('v1', 'cluster'))
|
|
||||||
|
|
||||||
|
|
||||||
class ClusterController(controller.Controller):
|
|
||||||
"""Cluster Controller to manages operations."""
|
|
||||||
def create(self, name, nic, flavor, size, volume_size, auth_type, username,
|
|
||||||
password):
|
|
||||||
"""Create Cluster"""
|
|
||||||
auth = {'type': auth_type,
|
|
||||||
'token': {'username': username,
|
|
||||||
'password': password}}
|
|
||||||
|
|
||||||
data = {
|
|
||||||
"network_id": nic.split(","),
|
|
||||||
"name": name,
|
|
||||||
"flavor": flavor,
|
|
||||||
"size": size,
|
|
||||||
"volume_size": volume_size,
|
|
||||||
"authentication": auth,
|
|
||||||
}
|
|
||||||
url = self.build_url("/clusters")
|
|
||||||
|
|
||||||
return Cluster(self._post(url, json=data))
|
|
||||||
|
|
||||||
def list(self, marker=None, limit=None, params=None):
|
|
||||||
"""List Clusters"""
|
|
||||||
url = self.build_url("/clusters", marker, limit, params)
|
|
||||||
|
|
||||||
response = self._get(url, "clusters")
|
|
||||||
return [Cluster(i) for i in response]
|
|
||||||
|
|
||||||
def get(self, cluster_id):
|
|
||||||
"""Show Cluster"""
|
|
||||||
url = self.build_url("/clusters/%s" % cluster_id)
|
|
||||||
|
|
||||||
return Cluster(self._get(url))
|
|
||||||
|
|
||||||
def update(self, cluster_id, values):
|
|
||||||
data = {
|
|
||||||
"cluster": values
|
|
||||||
}
|
|
||||||
|
|
||||||
url = self.build_url("/clusters/%s" % cluster_id)
|
|
||||||
|
|
||||||
return self._patch(url, data=data)
|
|
||||||
|
|
||||||
def delete(self, cluster_id):
|
|
||||||
"""Delete Cluster"""
|
|
||||||
url = self.build_url("/clusters/%s" % cluster_id)
|
|
||||||
|
|
||||||
return self._delete(url)
|
|
@ -1,18 +0,0 @@
|
|||||||
# Copyright 2014 Hewlett-Packard Development Company, L.P.
|
|
||||||
#
|
|
||||||
# Author: Endre Karlson <endre.karlson@hp.com>
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
||||||
# not use this file except in compliance with the License. You may obtain
|
|
||||||
# a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
# License for the specific language governing permissions and limitations
|
|
||||||
# under the License.
|
|
||||||
import pbr.version
|
|
||||||
|
|
||||||
version_info = pbr.version.VersionInfo('python-cueclient')
|
|
@ -1,134 +0,0 @@
|
|||||||
# Copyright 2012 Brian Waldon
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
||||||
# not use this file except in compliance with the License. You may obtain
|
|
||||||
# a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
# License for the specific language governing permissions and limitations
|
|
||||||
# under the License.
|
|
||||||
#
|
|
||||||
# Code copied from Warlock, as warlock depends on jsonschema==0.2
|
|
||||||
# Hopefully we can upstream the changes ASAP.
|
|
||||||
#
|
|
||||||
|
|
||||||
import copy
|
|
||||||
import logging
|
|
||||||
|
|
||||||
import jsonschema
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class InvalidOperation(RuntimeError):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class ValidationError(ValueError):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def model_factory(schema):
|
|
||||||
"""Generate a model class based on the provided JSON Schema
|
|
||||||
|
|
||||||
:param schema: dict representing valid JSON schema
|
|
||||||
"""
|
|
||||||
schema = copy.deepcopy(schema)
|
|
||||||
|
|
||||||
def validator(obj):
|
|
||||||
"""Apply a JSON schema to an object"""
|
|
||||||
try:
|
|
||||||
jsonschema.validate(obj, schema, cls=jsonschema.Draft3Validator)
|
|
||||||
except jsonschema.ValidationError as e:
|
|
||||||
raise ValidationError(str(e))
|
|
||||||
|
|
||||||
class Model(dict):
|
|
||||||
"""Self-validating model for arbitrary objects"""
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
d = dict(*args, **kwargs)
|
|
||||||
|
|
||||||
# we overload setattr so set this manually
|
|
||||||
self.__dict__['validator'] = validator
|
|
||||||
try:
|
|
||||||
self.validator(d)
|
|
||||||
except ValidationError as e:
|
|
||||||
raise ValueError('Validation Error: %s' % str(e))
|
|
||||||
else:
|
|
||||||
dict.__init__(self, d)
|
|
||||||
|
|
||||||
self.__dict__['changes'] = {}
|
|
||||||
|
|
||||||
def __getattr__(self, key):
|
|
||||||
try:
|
|
||||||
return self.__getitem__(key)
|
|
||||||
except KeyError:
|
|
||||||
raise AttributeError(key)
|
|
||||||
|
|
||||||
def __setitem__(self, key, value):
|
|
||||||
mutation = dict(self.items())
|
|
||||||
mutation[key] = value
|
|
||||||
try:
|
|
||||||
self.validator(mutation)
|
|
||||||
except ValidationError as e:
|
|
||||||
raise InvalidOperation(str(e))
|
|
||||||
|
|
||||||
dict.__setitem__(self, key, value)
|
|
||||||
|
|
||||||
self.__dict__['changes'][key] = value
|
|
||||||
|
|
||||||
def __setattr__(self, key, value):
|
|
||||||
self.__setitem__(key, value)
|
|
||||||
|
|
||||||
def clear(self):
|
|
||||||
raise InvalidOperation()
|
|
||||||
|
|
||||||
def pop(self, key, default=None):
|
|
||||||
raise InvalidOperation()
|
|
||||||
|
|
||||||
def popitem(self):
|
|
||||||
raise InvalidOperation()
|
|
||||||
|
|
||||||
def __delitem__(self, key):
|
|
||||||
raise InvalidOperation()
|
|
||||||
|
|
||||||
# NOTE(termie): This is kind of the opposite of what copy usually does
|
|
||||||
def copy(self):
|
|
||||||
return copy.deepcopy(dict(self))
|
|
||||||
|
|
||||||
def update(self, other):
|
|
||||||
# NOTE(kiall): It seems update() doesn't update the
|
|
||||||
# self.__dict__['changes'] dict correctly.
|
|
||||||
mutation = dict(self.items())
|
|
||||||
mutation.update(other)
|
|
||||||
try:
|
|
||||||
self.validator(mutation)
|
|
||||||
except ValidationError as e:
|
|
||||||
raise InvalidOperation(str(e))
|
|
||||||
dict.update(self, other)
|
|
||||||
|
|
||||||
def iteritems(self):
|
|
||||||
return copy.deepcopy(dict(self)).iteritems()
|
|
||||||
|
|
||||||
def items(self):
|
|
||||||
return copy.deepcopy(dict(self)).items()
|
|
||||||
|
|
||||||
def itervalues(self):
|
|
||||||
return copy.deepcopy(dict(self)).itervalues()
|
|
||||||
|
|
||||||
def keys(self):
|
|
||||||
return copy.deepcopy(dict(self)).keys()
|
|
||||||
|
|
||||||
def values(self):
|
|
||||||
return copy.deepcopy(dict(self)).values()
|
|
||||||
|
|
||||||
@property
|
|
||||||
def changes(self):
|
|
||||||
return copy.deepcopy(self.__dict__['changes'])
|
|
||||||
|
|
||||||
Model.__name__ = str(schema['title'])
|
|
||||||
return Model
|
|
@ -1,125 +0,0 @@
|
|||||||
=====================
|
|
||||||
Cue Command Line Tool
|
|
||||||
=====================
|
|
||||||
|
|
||||||
The python-cueclient can be used as a command line tool for accessing Cue API.
|
|
||||||
|
|
||||||
Credentials
|
|
||||||
-----------
|
|
||||||
|
|
||||||
As with any OpenStack utility, :program:`python-cueclient` requires certain information to
|
|
||||||
talk to the REST API, username, password, auth url (from where the other required
|
|
||||||
endpoints are retrieved once you are authenticated).
|
|
||||||
|
|
||||||
To provide your access credentials (username, password, tenant name or project_name)
|
|
||||||
you can pass them on the command line with the ``--os-username``, ``--os-password``, ``--os-tenant-name`` or ``--os-project-name``
|
|
||||||
params, but it's easier to just set them as environment variables::
|
|
||||||
|
|
||||||
export OS_USERNAME=<your_username>
|
|
||||||
export OS_PASSWORD=<your_password>
|
|
||||||
export OS_PROJECT_NAME=<project_name>
|
|
||||||
|
|
||||||
You will also need to define the authentication url with ``--os-auth-url``
|
|
||||||
or set is as an environment variable as well::
|
|
||||||
|
|
||||||
export OS_AUTH_URL=<url_to_openstack_identity>
|
|
||||||
|
|
||||||
Since Keystone can return multiple regions in the Service Catalog, you
|
|
||||||
can specify the one you want with ``--os-region-name`` (or
|
|
||||||
``export OS_REGION_NAME``). It defaults to the first in the list returned.
|
|
||||||
|
|
||||||
Using the command line tool
|
|
||||||
---------------------------
|
|
||||||
|
|
||||||
With enough details now in environment, you can use the cue client to create,list,show or delete cluster(s).
|
|
||||||
|
|
||||||
The Openstack Client can be called interactively by simply typing:
|
|
||||||
|
|
||||||
.. code-block:: shell-session
|
|
||||||
|
|
||||||
openstack
|
|
||||||
|
|
||||||
Cluster Create
|
|
||||||
--------------
|
|
||||||
|
|
||||||
Required fields for 'create' : name, network id , flavor and size.
|
|
||||||
|
|
||||||
.. code-block:: shell-session
|
|
||||||
|
|
||||||
(openstack) message-broker cluster create --name cluster_04 --nic 3dd26c0b-03f2-4d2e-ae87-c02d7f33c788 --flavor 2 --size 3 --auth type=plain,user=rabbitmq,pass=rabbit
|
|
||||||
+-------------+--------------------------------------+
|
|
||||||
| Field | Value |
|
|
||||||
+-------------+--------------------------------------+
|
|
||||||
| created_at | 2015-02-17T18:25:28+00:00 |
|
|
||||||
| endpoints | [] |
|
|
||||||
| flavor | 2 |
|
|
||||||
| id | 06d3c0e4-4972-4ca9-91c1-373b1c74e8e1 |
|
|
||||||
| name | cluster_04 |
|
|
||||||
| network_id | 3dd26c0b-03f2-4d2e-ae87-c02d7f33c788 |
|
|
||||||
| size | 3 |
|
|
||||||
| status | BUILDING |
|
|
||||||
| updated_at | 2015-02-17T18:25:28+00:00 |
|
|
||||||
| volume_size | None |
|
|
||||||
+-------------+--------------------------------------+
|
|
||||||
|
|
||||||
Cluster Show
|
|
||||||
------------
|
|
||||||
|
|
||||||
Required field for 'show' : cluster-id
|
|
||||||
|
|
||||||
.. code-block:: shell-session
|
|
||||||
|
|
||||||
|
|
||||||
(openstack) message-broker cluster show 06d3c0e4-4972-4ca9-91c1-373b1c74e8e1
|
|
||||||
+-------------+--------------------------------------+
|
|
||||||
| Field | Value |
|
|
||||||
+-------------+--------------------------------------+
|
|
||||||
| created_at | 2015-02-17T18:25:28+00:00 |
|
|
||||||
| endpoints | [] |
|
|
||||||
| flavor | 2 |
|
|
||||||
| id | 06d3c0e4-4972-4ca9-91c1-373b1c74e8e1 |
|
|
||||||
| name | cluster_04 |
|
|
||||||
| network_id | 3dd26c0b-03f2-4d2e-ae87-c02d7f33c788 |
|
|
||||||
| size | 3 |
|
|
||||||
| status | BUILDING |
|
|
||||||
| updated_at | 2015-02-17T18:25:28+00:00 |
|
|
||||||
| volume_size | None |
|
|
||||||
+-------------+--------------------------------------+
|
|
||||||
|
|
||||||
Cluster Delete
|
|
||||||
--------------
|
|
||||||
|
|
||||||
Required field for 'delete' : cluster-id
|
|
||||||
|
|
||||||
.. code-block:: shell-session
|
|
||||||
|
|
||||||
(openstack) message-broker cluster delete 06d3c0e4-4972-4ca9-91c1-373b1c74e8e1
|
|
||||||
|
|
||||||
Cluster List
|
|
||||||
------------
|
|
||||||
|
|
||||||
.. code-block:: shell-session
|
|
||||||
|
|
||||||
(openstack) message-broker cluster list
|
|
||||||
+--------------------------------------+-------------+----------+--------+------+
|
|
||||||
| id | name | status | flavor | size |
|
|
||||||
+--------------------------------------+-------------+----------+--------+------+
|
|
||||||
| 06d3c0e4-4972-4ca9-91c1-373b1c74e8e1 | cluster_04 | DELETING | 2 | 3 |
|
|
||||||
| 09fa2dc2-7ebb-423f-9726-f45b53f0df99 | cluster_02 | DELETING | 1 | 3 |
|
|
||||||
| 2d6a5359-2c45-44bb-baa9-3ccd2a48c217 | cluster_03 | BUILDING | 2 | 2 |
|
|
||||||
+--------------------------------------+-------------+----------+--------+------+
|
|
||||||
|
|
||||||
Subcommands
|
|
||||||
-----------
|
|
||||||
|
|
||||||
Here are the full list of subcommands:
|
|
||||||
|
|
||||||
================================== ======================================================
|
|
||||||
subcommand Notes
|
|
||||||
================================== ======================================================
|
|
||||||
message-broker cluster create Create Cluster
|
|
||||||
message-broker cluster delete Delete Cluster
|
|
||||||
message-broker cluster show Show Cluster
|
|
||||||
message-broker cluster list List Clusters
|
|
||||||
================================== ======================================================
|
|
||||||
|
|
@ -1,260 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
#
|
|
||||||
# python-cueclient documentation build configuration file, created by
|
|
||||||
# sphinx-quickstart on Wed Feb 11 14:55:41 2015.
|
|
||||||
#
|
|
||||||
# This file is execfile()d with the current directory set to its
|
|
||||||
# containing dir.
|
|
||||||
#
|
|
||||||
# Note that not all possible configuration values are present in this
|
|
||||||
# autogenerated file.
|
|
||||||
#
|
|
||||||
# All configuration values have a default; values that are commented out
|
|
||||||
# serve to show the default.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
|
|
||||||
# If extensions (or modules to document with autodoc) are in another directory,
|
|
||||||
# add these directories to sys.path here. If the directory is relative to the
|
|
||||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
|
||||||
#sys.path.insert(0, os.path.abspath('.'))
|
|
||||||
|
|
||||||
# -- General configuration ------------------------------------------------
|
|
||||||
|
|
||||||
# If your documentation needs a minimal Sphinx version, state it here.
|
|
||||||
#needs_sphinx = '1.0'
|
|
||||||
|
|
||||||
# Add any Sphinx extension module names here, as strings. They can be
|
|
||||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
|
||||||
# ones.
|
|
||||||
extensions = [
|
|
||||||
'sphinx.ext.autodoc',
|
|
||||||
]
|
|
||||||
|
|
||||||
# Add any paths that contain templates here, relative to this directory.
|
|
||||||
templates_path = ['_templates']
|
|
||||||
|
|
||||||
# The suffix of source filenames.
|
|
||||||
source_suffix = '.rst'
|
|
||||||
|
|
||||||
# The encoding of source files.
|
|
||||||
#source_encoding = 'utf-8-sig'
|
|
||||||
|
|
||||||
# The master toctree document.
|
|
||||||
master_doc = 'index'
|
|
||||||
|
|
||||||
# General information about the project.
|
|
||||||
project = u'python-cueclient'
|
|
||||||
copyright = u'2015, Openstack Cue Team'
|
|
||||||
|
|
||||||
# The version info for the project you're documenting, acts as replacement for
|
|
||||||
# |version| and |release|, also used in various other places throughout the
|
|
||||||
# built documents.
|
|
||||||
#
|
|
||||||
# The short X.Y version.
|
|
||||||
version = '0.0.1'
|
|
||||||
# The full version, including alpha/beta/rc tags.
|
|
||||||
release = '0.0.1'
|
|
||||||
|
|
||||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
|
||||||
# for a list of supported languages.
|
|
||||||
#language = None
|
|
||||||
|
|
||||||
# There are two options for replacing |today|: either, you set today to some
|
|
||||||
# non-false value, then it is used:
|
|
||||||
#today = ''
|
|
||||||
# Else, today_fmt is used as the format for a strftime call.
|
|
||||||
#today_fmt = '%B %d, %Y'
|
|
||||||
|
|
||||||
# List of patterns, relative to source directory, that match files and
|
|
||||||
# directories to ignore when looking for source files.
|
|
||||||
exclude_patterns = []
|
|
||||||
|
|
||||||
# The reST default role (used for this markup: `text`) to use for all
|
|
||||||
# documents.
|
|
||||||
#default_role = None
|
|
||||||
|
|
||||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
|
||||||
#add_function_parentheses = True
|
|
||||||
|
|
||||||
# If true, the current module name will be prepended to all description
|
|
||||||
# unit titles (such as .. function::).
|
|
||||||
#add_module_names = True
|
|
||||||
|
|
||||||
# If true, sectionauthor and moduleauthor directives will be shown in the
|
|
||||||
# output. They are ignored by default.
|
|
||||||
#show_authors = False
|
|
||||||
|
|
||||||
# The name of the Pygments (syntax highlighting) style to use.
|
|
||||||
pygments_style = 'sphinx'
|
|
||||||
|
|
||||||
# A list of ignored prefixes for module index sorting.
|
|
||||||
#modindex_common_prefix = []
|
|
||||||
|
|
||||||
# If true, keep warnings as "system message" paragraphs in the built documents.
|
|
||||||
#keep_warnings = False
|
|
||||||
|
|
||||||
|
|
||||||
# -- Options for HTML output ----------------------------------------------
|
|
||||||
|
|
||||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
|
||||||
# a list of builtin themes.
|
|
||||||
html_theme = 'default'
|
|
||||||
|
|
||||||
# Theme options are theme-specific and customize the look and feel of a theme
|
|
||||||
# further. For a list of options available for each theme, see the
|
|
||||||
# documentation.
|
|
||||||
#html_theme_options = {}
|
|
||||||
|
|
||||||
# Add any paths that contain custom themes here, relative to this directory.
|
|
||||||
#html_theme_path = []
|
|
||||||
|
|
||||||
# The name for this set of Sphinx documents. If None, it defaults to
|
|
||||||
# "<project> v<release> documentation".
|
|
||||||
#html_title = None
|
|
||||||
|
|
||||||
# A shorter title for the navigation bar. Default is the same as html_title.
|
|
||||||
#html_short_title = None
|
|
||||||
|
|
||||||
# The name of an image file (relative to this directory) to place at the top
|
|
||||||
# of the sidebar.
|
|
||||||
#html_logo = None
|
|
||||||
|
|
||||||
# The name of an image file (within the static path) to use as favicon of the
|
|
||||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
|
||||||
# pixels large.
|
|
||||||
#html_favicon = None
|
|
||||||
|
|
||||||
# Add any paths that contain custom static files (such as style sheets) here,
|
|
||||||
# relative to this directory. They are copied after the builtin static files,
|
|
||||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
|
||||||
html_static_path = ['_static']
|
|
||||||
|
|
||||||
# Add any extra paths that contain custom files (such as robots.txt or
|
|
||||||
# .htaccess) here, relative to this directory. These files are copied
|
|
||||||
# directly to the root of the documentation.
|
|
||||||
#html_extra_path = []
|
|
||||||
|
|
||||||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
|
||||||
# using the given strftime format.
|
|
||||||
#html_last_updated_fmt = '%b %d, %Y'
|
|
||||||
|
|
||||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
|
||||||
# typographically correct entities.
|
|
||||||
#html_use_smartypants = True
|
|
||||||
|
|
||||||
# Custom sidebar templates, maps document names to template names.
|
|
||||||
#html_sidebars = {}
|
|
||||||
|
|
||||||
# Additional templates that should be rendered to pages, maps page names to
|
|
||||||
# template names.
|
|
||||||
#html_additional_pages = {}
|
|
||||||
|
|
||||||
# If false, no module index is generated.
|
|
||||||
#html_domain_indices = True
|
|
||||||
|
|
||||||
# If false, no index is generated.
|
|
||||||
#html_use_index = True
|
|
||||||
|
|
||||||
# If true, the index is split into individual pages for each letter.
|
|
||||||
#html_split_index = False
|
|
||||||
|
|
||||||
# If true, links to the reST sources are added to the pages.
|
|
||||||
#html_show_sourcelink = True
|
|
||||||
|
|
||||||
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
|
||||||
#html_show_sphinx = True
|
|
||||||
|
|
||||||
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
|
||||||
#html_show_copyright = True
|
|
||||||
|
|
||||||
# If true, an OpenSearch description file will be output, and all pages will
|
|
||||||
# contain a <link> tag referring to it. The value of this option must be the
|
|
||||||
# base URL from which the finished HTML is served.
|
|
||||||
#html_use_opensearch = ''
|
|
||||||
|
|
||||||
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
|
||||||
#html_file_suffix = None
|
|
||||||
|
|
||||||
# Output file base name for HTML help builder.
|
|
||||||
htmlhelp_basename = 'python-cueclientdoc'
|
|
||||||
|
|
||||||
|
|
||||||
# -- Options for LaTeX output ---------------------------------------------
|
|
||||||
|
|
||||||
latex_elements = {
|
|
||||||
# The paper size ('letterpaper' or 'a4paper').
|
|
||||||
#'papersize': 'letterpaper',
|
|
||||||
|
|
||||||
# The font size ('10pt', '11pt' or '12pt').
|
|
||||||
#'pointsize': '10pt',
|
|
||||||
|
|
||||||
# Additional stuff for the LaTeX preamble.
|
|
||||||
#'preamble': '',
|
|
||||||
}
|
|
||||||
|
|
||||||
# Grouping the document tree into LaTeX files. List of tuples
|
|
||||||
# (source start file, target name, title,
|
|
||||||
# author, documentclass [howto, manual, or own class]).
|
|
||||||
latex_documents = [
|
|
||||||
('index', 'python-cueclient.tex', u'python-cueclient Documentation',
|
|
||||||
u'Openstack Cue Team', 'manual'),
|
|
||||||
]
|
|
||||||
|
|
||||||
# The name of an image file (relative to this directory) to place at the top of
|
|
||||||
# the title page.
|
|
||||||
#latex_logo = None
|
|
||||||
|
|
||||||
# For "manual" documents, if this is true, then toplevel headings are parts,
|
|
||||||
# not chapters.
|
|
||||||
#latex_use_parts = False
|
|
||||||
|
|
||||||
# If true, show page references after internal links.
|
|
||||||
#latex_show_pagerefs = False
|
|
||||||
|
|
||||||
# If true, show URL addresses after external links.
|
|
||||||
#latex_show_urls = False
|
|
||||||
|
|
||||||
# Documents to append as an appendix to all manuals.
|
|
||||||
#latex_appendices = []
|
|
||||||
|
|
||||||
# If false, no module index is generated.
|
|
||||||
#latex_domain_indices = True
|
|
||||||
|
|
||||||
|
|
||||||
# -- Options for manual page output ---------------------------------------
|
|
||||||
|
|
||||||
# One entry per manual page. List of tuples
|
|
||||||
# (source start file, name, description, authors, manual section).
|
|
||||||
man_pages = [
|
|
||||||
('index', 'python-cueclient', u'python-cueclient Documentation',
|
|
||||||
[u'Openstack Cue Team'], 1)
|
|
||||||
]
|
|
||||||
|
|
||||||
# If true, show URL addresses after external links.
|
|
||||||
#man_show_urls = False
|
|
||||||
|
|
||||||
|
|
||||||
# -- Options for Texinfo output -------------------------------------------
|
|
||||||
|
|
||||||
# Grouping the document tree into Texinfo files. List of tuples
|
|
||||||
# (source start file, target name, title, author,
|
|
||||||
# dir menu entry, description, category)
|
|
||||||
texinfo_documents = [
|
|
||||||
('index', 'python-cueclient', u'python-cueclient Documentation',
|
|
||||||
u'Openstack Cue Team', 'python-cueclient', 'One line description of project.',
|
|
||||||
'Miscellaneous'),
|
|
||||||
]
|
|
||||||
|
|
||||||
# Documents to append as an appendix to all manuals.
|
|
||||||
#texinfo_appendices = []
|
|
||||||
|
|
||||||
# If false, no module index is generated.
|
|
||||||
#texinfo_domain_indices = True
|
|
||||||
|
|
||||||
# How to display URL addresses: 'footnote', 'no', or 'inline'.
|
|
||||||
#texinfo_show_urls = 'footnote'
|
|
||||||
|
|
||||||
# If true, do not generate a @detailmenu in the "Top" node's menu.
|
|
||||||
#texinfo_no_detailmenu = False
|
|
@ -1,47 +0,0 @@
|
|||||||
Contributing
|
|
||||||
============
|
|
||||||
|
|
||||||
Code is hosted `on GitHub`_.
|
|
||||||
Submit bugs to the Cue Client project on `Launchpad`_.
|
|
||||||
Submit code to the openstack/python-cueclient project using `Gerrit`_.
|
|
||||||
|
|
||||||
Here's a quick summary:
|
|
||||||
|
|
||||||
Install the git-review package to make life easier
|
|
||||||
|
|
||||||
.. code-block:: shell-session
|
|
||||||
|
|
||||||
pip install git-review
|
|
||||||
|
|
||||||
Branch, work, & submit:
|
|
||||||
|
|
||||||
.. code-block:: shell-session
|
|
||||||
|
|
||||||
# cut a new branch, tracking master
|
|
||||||
git checkout --track -b bug/id origin/master
|
|
||||||
# work work work
|
|
||||||
git add stuff
|
|
||||||
git commit
|
|
||||||
# rebase/squash to a single commit before submitting
|
|
||||||
git rebase -i
|
|
||||||
# submit
|
|
||||||
git-review
|
|
||||||
|
|
||||||
Coding Standards
|
|
||||||
----------------
|
|
||||||
Cue Client uses the OpenStack flake8 coding standards guidelines.
|
|
||||||
These are stricter than pep8, and are run by gerrit on every commit.
|
|
||||||
|
|
||||||
You can use tox to check your code locally by running
|
|
||||||
|
|
||||||
.. code-block:: shell-session
|
|
||||||
|
|
||||||
# For just flake8 tests
|
|
||||||
tox -e flake8
|
|
||||||
# For tests + flake8
|
|
||||||
tox
|
|
||||||
|
|
||||||
.. _on GitHub: https://github.com/openstack/python-cueclient
|
|
||||||
.. _Launchpad: https://launchpad.net/python-cueclient
|
|
||||||
.. _Gerrit: http://docs.openstack.org/infra/manual/developers.html#development-workflow
|
|
||||||
|
|
@ -1,73 +0,0 @@
|
|||||||
..
|
|
||||||
Copyright 2014 Hewlett-Packard Development Company, L.P.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
||||||
not use this file except in compliance with the License. You may obtain
|
|
||||||
a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
License for the specific language governing permissions and limitations
|
|
||||||
under the License.
|
|
||||||
|
|
||||||
.. _getting-started:
|
|
||||||
|
|
||||||
===============
|
|
||||||
Getting Started
|
|
||||||
===============
|
|
||||||
|
|
||||||
.. _Development Environment:
|
|
||||||
|
|
||||||
The python-cueclient can be used either as a command line tool or as a binding to access Cue.
|
|
||||||
|
|
||||||
|
|
||||||
Installing Cue Client from source
|
|
||||||
=================================
|
|
||||||
|
|
||||||
.. index::
|
|
||||||
double: install; python-cueclient
|
|
||||||
|
|
||||||
|
|
||||||
1. Clone the CueClient repo from GitHub
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
$ git clone https://github.com/openstack/python-cueclient.git
|
|
||||||
$ cd python-cueclient
|
|
||||||
|
|
||||||
|
|
||||||
2. Setup virtualenv
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
This is an optional step, but will allow CueClient's dependencies
|
|
||||||
to be installed in a contained environment that can be easily deleted
|
|
||||||
if you choose to start over or uninstall Cue.
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
$ virtualenv --no-site-packages .venv
|
|
||||||
$ . .venv/bin/activate
|
|
||||||
|
|
||||||
|
|
||||||
3. Install CueClient and its dependencies
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
$ pip install -r requirements.txt -r test-requirements.txt
|
|
||||||
$ python setup.py develop
|
|
||||||
|
|
||||||
|
|
||||||
Installation to use as Command Line Tool
|
|
||||||
----------------------------------------
|
|
||||||
4. To access the shell for cue client 'python-openstackclient' has to be installed.
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
$ pip install python-openstackclient
|
|
||||||
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
This step can be skipped if you choose to use python-cueclient as only a binding to Cue API.
|
|
@ -1,26 +0,0 @@
|
|||||||
.. python-cueclient documentation master file, created by
|
|
||||||
sphinx-quickstart on Wed Feb 11 14:55:41 2015.
|
|
||||||
You can adapt this file completely to your liking, but it should at least
|
|
||||||
contain the root `toctree` directive.
|
|
||||||
|
|
||||||
Welcome to python-cueclient's documentation!
|
|
||||||
============================================
|
|
||||||
|
|
||||||
Contents:
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:maxdepth: 2
|
|
||||||
|
|
||||||
getting-started
|
|
||||||
command-line
|
|
||||||
python-bindings
|
|
||||||
contributing
|
|
||||||
|
|
||||||
|
|
||||||
Indices and tables
|
|
||||||
==================
|
|
||||||
|
|
||||||
* :ref:`genindex`
|
|
||||||
* :ref:`modindex`
|
|
||||||
* :ref:`search`
|
|
||||||
|
|
@ -1,54 +0,0 @@
|
|||||||
====
|
|
||||||
cue
|
|
||||||
====
|
|
||||||
|
|
||||||
|
|
||||||
SYNOPSIS
|
|
||||||
========
|
|
||||||
|
|
||||||
`message-broker` [options] <command> [command-options]
|
|
||||||
|
|
||||||
`message-broker help`
|
|
||||||
|
|
||||||
`message-broker help` <command>
|
|
||||||
|
|
||||||
|
|
||||||
DESCRIPTION
|
|
||||||
===========
|
|
||||||
|
|
||||||
`message-broker` is a command line client for controlling OpenStack Cue, the message broker provisioning service.
|
|
||||||
|
|
||||||
Before you can issue commands with `message-broker`, you must ensure that your
|
|
||||||
environment contains the necessary variables so that you can prove to the CLI
|
|
||||||
who you are and what credentials you have to issue the commands.
|
|
||||||
|
|
||||||
OPTIONS
|
|
||||||
=======
|
|
||||||
|
|
||||||
To get a list of available commands and options run::
|
|
||||||
|
|
||||||
message-broker help
|
|
||||||
|
|
||||||
To get usage and options of a command run::
|
|
||||||
|
|
||||||
message-broker help <command>
|
|
||||||
|
|
||||||
EXAMPLES
|
|
||||||
========
|
|
||||||
|
|
||||||
Get information about cluster create command::
|
|
||||||
|
|
||||||
help message-broker cluster create
|
|
||||||
|
|
||||||
List available clusters::
|
|
||||||
|
|
||||||
help message-broker cluster list
|
|
||||||
|
|
||||||
View cluster information::
|
|
||||||
|
|
||||||
help message-broker cluster show
|
|
||||||
|
|
||||||
Delete clusters::
|
|
||||||
|
|
||||||
help message-broker cluster delete
|
|
||||||
|
|
@ -1,196 +0,0 @@
|
|||||||
===============
|
|
||||||
Python Bindings
|
|
||||||
===============
|
|
||||||
|
|
||||||
The python-cueclient can be used to interact with the Cue API from any other
|
|
||||||
python program.
|
|
||||||
|
|
||||||
|
|
||||||
Introduction
|
|
||||||
============
|
|
||||||
|
|
||||||
Below is a simple example of how to instantiate and perform basic tasks using
|
|
||||||
the bindings.
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
from keystoneauth1.identity import v3 as keystone_v3_auth
|
|
||||||
from keystoneauth1 import session as keystone_session
|
|
||||||
from cueclient.v1 import client
|
|
||||||
|
|
||||||
auth = keystone_v3_auth.Password(
|
|
||||||
auth_url="http://example.com:5000/v3",
|
|
||||||
username="admin",
|
|
||||||
password="password",
|
|
||||||
project_name="admin",
|
|
||||||
project_domain_name="default",
|
|
||||||
user_domain_name="default"
|
|
||||||
)
|
|
||||||
|
|
||||||
session = keystone_session.Session(auth=auth)
|
|
||||||
|
|
||||||
# Create an instance of the client
|
|
||||||
cue_client = client.Client(session=session)
|
|
||||||
|
|
||||||
# Cluster List - returns list of cluster objects
|
|
||||||
list_response = cue_client.clusters.list()
|
|
||||||
|
|
||||||
# Iterate the list, printing some useful information
|
|
||||||
for cluster in list_response:
|
|
||||||
|
|
||||||
print "Cluster ID: %s \t Name: %s \t NetworkId: %s \t Flavor: %s \t Size: %s" % \
|
|
||||||
(cluster.id, cluster.name, cluster.network_id, cluster.flavor, cluster.size)
|
|
||||||
|
|
||||||
And the output this program might produce:
|
|
||||||
|
|
||||||
.. code-block:: console
|
|
||||||
|
|
||||||
$ python /example.py
|
|
||||||
Cluster ID: 213cdd06-c361-4cca-93b5-7ed651d46936 Name: test_binding2 NetworkId: 33333 Flavor: 1 Size: 2
|
|
||||||
Cluster ID: 24f299fd-0509-4218-bf80-6c0481452480 Name: test_binding4 NetworkId: 44444 Flavor: 1 Size: 2
|
|
||||||
|
|
||||||
|
|
||||||
Authentication
|
|
||||||
==============
|
|
||||||
|
|
||||||
Cue supports Keystone authentication.
|
|
||||||
|
|
||||||
Keystone Authentication
|
|
||||||
-----------------------
|
|
||||||
|
|
||||||
Below is a sample of standard authentication with keystone v3:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
from keystoneauth1.identity import v3 as keystone_v3_auth
|
|
||||||
from keystoneauth1 import session as keystone_session
|
|
||||||
|
|
||||||
auth = keystone_v3_auth.Password(
|
|
||||||
auth_url="http://example.com:5000/v3",
|
|
||||||
username="admin",
|
|
||||||
password="password",
|
|
||||||
project_name="admin",
|
|
||||||
project_domain_name="default",
|
|
||||||
user_domain_name="default"
|
|
||||||
)
|
|
||||||
|
|
||||||
Cue Functions
|
|
||||||
=============
|
|
||||||
|
|
||||||
Cluster List
|
|
||||||
------------
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
from keystoneauth1.identity import v3 as keystone_v3_auth
|
|
||||||
from keystoneauth1 import session as keystone_session
|
|
||||||
from cueclient.v1 import client
|
|
||||||
|
|
||||||
auth = keystone_v3_auth.Password(
|
|
||||||
auth_url="http://example.com:5000/v3",
|
|
||||||
username="admin",
|
|
||||||
password="password",
|
|
||||||
project_name="admin",
|
|
||||||
project_domain_name="default",
|
|
||||||
user_domain_name="default"
|
|
||||||
)
|
|
||||||
|
|
||||||
session = keystone_session.Session(auth=auth)
|
|
||||||
cue_client = client.Client(session=session)
|
|
||||||
|
|
||||||
# Cluster List
|
|
||||||
list_response = cue_client.clusters.list()
|
|
||||||
|
|
||||||
|
|
||||||
Cluster Show
|
|
||||||
------------
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
from keystoneauth1.identity import v3 as keystone_v3_auth
|
|
||||||
from keystoneauth1 import session as keystone_session
|
|
||||||
from cueclient.v1 import client
|
|
||||||
|
|
||||||
auth = keystone_v3_auth.Password(
|
|
||||||
auth_url="http://example.com:5000/v3",
|
|
||||||
username="admin",
|
|
||||||
password="password",
|
|
||||||
project_name="admin",
|
|
||||||
project_domain_name="default",
|
|
||||||
user_domain_name="default"
|
|
||||||
)
|
|
||||||
|
|
||||||
session = keystone_session.Session(auth=auth)
|
|
||||||
cue_client = client.Client(session=session)
|
|
||||||
|
|
||||||
cluster_id = "0a352f9a-8aa8-411e-9d6d-4e6217d70afd"
|
|
||||||
|
|
||||||
# Cluster Show
|
|
||||||
show_response = cue_client.clusters.get(cluster_id)
|
|
||||||
|
|
||||||
|
|
||||||
Cluster Create
|
|
||||||
--------------
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
from keystoneauth1.auth.identity import v3 as keystone_v3_auth
|
|
||||||
from keystoneauth1 import session as keystone_session
|
|
||||||
from cueclient.v1 import client
|
|
||||||
|
|
||||||
auth = keystone_v3_auth.Password(
|
|
||||||
auth_url="http://example.com:5000/v3",
|
|
||||||
username="admin",
|
|
||||||
password="password",
|
|
||||||
project_name="admin",
|
|
||||||
project_domain_name="default",
|
|
||||||
user_domain_name="default"
|
|
||||||
)
|
|
||||||
|
|
||||||
session = keystone_session.Session(auth=auth)
|
|
||||||
cue_client = client.Client(session=session)
|
|
||||||
|
|
||||||
# Cluster create
|
|
||||||
create_response = cue_client.clusters.create(name="test_binding5",
|
|
||||||
nic="55555", flavor="1",size="2",volume_size="0",
|
|
||||||
auth_type="plain", username="rabbitmq",
|
|
||||||
password="password")
|
|
||||||
|
|
||||||
Cluster Delete
|
|
||||||
--------------
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
from keystoneauth1.identity import v3 as keystone_v3_auth
|
|
||||||
from keystoneauth1 import session as keystone_session
|
|
||||||
from cueclient.v1 import client
|
|
||||||
|
|
||||||
auth = keystone_v3_auth.Password(
|
|
||||||
auth_url="http://example.com:5000/v3",
|
|
||||||
username="admin",
|
|
||||||
password="password",
|
|
||||||
project_name="admin",
|
|
||||||
project_domain_name="default",
|
|
||||||
user_domain_name="default"
|
|
||||||
)
|
|
||||||
|
|
||||||
session = keystone_session.Session(auth=auth)
|
|
||||||
cue_client = client.Client(session=session)
|
|
||||||
|
|
||||||
delete_id = "dc86d96f-6b37-4e2d-9805-4542450f427d"
|
|
||||||
|
|
||||||
# Cluster Delete
|
|
||||||
delete_response = cue_client.clusters.delete(delete_id)
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
|||||||
# The order of packages is significant, because pip processes them in the order
|
|
||||||
# of appearance. Changing the order has an impact on the overall integration
|
|
||||||
# process, which may cause wedges in the gate later.
|
|
||||||
cliff!=1.16.0,!=1.17.0,>=1.15.0 # Apache-2.0
|
|
||||||
keystoneauth1>=2.7.0 # Apache-2.0
|
|
||||||
jsonschema!=2.5.0,<3.0.0,>=2.0.0 # MIT
|
|
||||||
pbr>=1.6 # Apache-2.0
|
|
||||||
requests!=2.9.0,>=2.8.1 # Apache-2.0
|
|
||||||
six>=1.9.0 # MIT
|
|
||||||
stevedore>=1.5.0 # Apache-2.0
|
|
65
setup.cfg
65
setup.cfg
@ -1,65 +0,0 @@
|
|||||||
[metadata]
|
|
||||||
name = python-cueclient
|
|
||||||
summary = Message Broker Provisioning Service Cue Client
|
|
||||||
description-file =
|
|
||||||
README.rst
|
|
||||||
license = Apache License, Version 2.0
|
|
||||||
author = OpenStack
|
|
||||||
author-email = openstack-dev@lists.openstack.org
|
|
||||||
home-page = http://www.openstack.org/
|
|
||||||
classifier =
|
|
||||||
Environment :: OpenStack
|
|
||||||
Intended Audience :: Information Technology
|
|
||||||
Intended Audience :: System Administrators
|
|
||||||
License :: OSI Approved :: Apache Software License
|
|
||||||
Operating System :: POSIX :: Linux
|
|
||||||
Programming Language :: Python
|
|
||||||
Programming Language :: Python :: 2
|
|
||||||
Programming Language :: Python :: 2.7
|
|
||||||
|
|
||||||
[global]
|
|
||||||
setup-hooks =
|
|
||||||
pbr.hooks.setup_hook
|
|
||||||
|
|
||||||
[files]
|
|
||||||
packages =
|
|
||||||
cueclient
|
|
||||||
|
|
||||||
[entry_points]
|
|
||||||
openstack.mb.v1 =
|
|
||||||
message-broker_cluster_create = cueclient.v1.cli.clusters:CreateClusterCommand
|
|
||||||
message-broker_cluster_list = cueclient.v1.cli.clusters:ListClustersCommand
|
|
||||||
message-broker_cluster_show = cueclient.v1.cli.clusters:ShowClusterCommand
|
|
||||||
message-broker_cluster_set = cueclient.v1.cli.clusters:SetClusterCommand
|
|
||||||
message-broker_cluster_delete = cueclient.v1.cli.clusters:DeleteClusterCommand
|
|
||||||
|
|
||||||
openstack.cli.extension =
|
|
||||||
mb = cueclient.osc.plugin
|
|
||||||
|
|
||||||
|
|
||||||
[build_sphinx]
|
|
||||||
all_files = 1
|
|
||||||
build-dir = doc/build
|
|
||||||
source-dir = doc/source
|
|
||||||
|
|
||||||
[egg_info]
|
|
||||||
tag_build =
|
|
||||||
tag_date = 0
|
|
||||||
tag_svn_revision = 0
|
|
||||||
|
|
||||||
[compile_catalog]
|
|
||||||
directory = cueclient/locale
|
|
||||||
domain = cueclient
|
|
||||||
|
|
||||||
[update_catalog]
|
|
||||||
domain = cueclient
|
|
||||||
output_dir = cueclient/locale
|
|
||||||
input_file = cueclient/locale/cueclient.pot
|
|
||||||
|
|
||||||
[extract_messages]
|
|
||||||
keywords = _ gettext ngettext l_ lazy_gettext
|
|
||||||
mapping_file = babel.cfg
|
|
||||||
output_file = cueclient/locale/cueclient.pot
|
|
||||||
|
|
||||||
[wheel]
|
|
||||||
universal = 1
|
|
29
setup.py
29
setup.py
@ -1,29 +0,0 @@
|
|||||||
# Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
# you may not use this file except in compliance with the License.
|
|
||||||
# You may obtain a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
# implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT
|
|
||||||
import setuptools
|
|
||||||
|
|
||||||
# In python < 2.7.4, a lazy loading of package `pbr` will break
|
|
||||||
# setuptools if some other modules registered functions in `atexit`.
|
|
||||||
# solution from: http://bugs.python.org/issue15881#msg170215
|
|
||||||
try:
|
|
||||||
import multiprocessing # noqa
|
|
||||||
except ImportError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
setuptools.setup(
|
|
||||||
setup_requires=['pbr>=1.8'],
|
|
||||||
pbr=True)
|
|
@ -1,17 +0,0 @@
|
|||||||
# The order of packages is significant, because pip processes them in the order
|
|
||||||
# of appearance. Changing the order has an impact on the overall integration
|
|
||||||
# process, which may cause wedges in the gate later.
|
|
||||||
# Hacking already pins down pep8, pyflakes and flake8
|
|
||||||
hacking<0.10,>=0.9.2
|
|
||||||
coverage>=3.6 # Apache-2.0
|
|
||||||
discover # BSD
|
|
||||||
fixtures>=1.3.1 # Apache-2.0/BSD
|
|
||||||
mock>=1.2 # BSD
|
|
||||||
oslo.serialization>=1.10.0 # Apache-2.0
|
|
||||||
requests-mock>=0.7.0 # Apache-2.0
|
|
||||||
python-subunit>=0.0.18 # Apache-2.0/BSD
|
|
||||||
testrepository>=0.0.18 # Apache-2.0/BSD
|
|
||||||
|
|
||||||
# Doc requirements
|
|
||||||
sphinx!=1.2.0,!=1.3b1,<1.3,>=1.1.2 # BSD
|
|
||||||
oslosphinx!=3.4.0,>=2.5.0 # Apache-2.0
|
|
45
tox.ini
45
tox.ini
@ -1,45 +0,0 @@
|
|||||||
[tox]
|
|
||||||
envlist = py27,py34,flake8
|
|
||||||
minversion = 1.6
|
|
||||||
|
|
||||||
[testenv]
|
|
||||||
sitepackages = False
|
|
||||||
install_command = pip install {opts} {packages}
|
|
||||||
setenv = VIRTUAL_ENV={envdir}
|
|
||||||
LANG=en_US.UTF-8
|
|
||||||
LANGUAGE=en_US:en
|
|
||||||
LC_ALL=C
|
|
||||||
deps = -r{toxinidir}/requirements.txt
|
|
||||||
-r{toxinidir}/test-requirements.txt
|
|
||||||
whitelist_externals = find
|
|
||||||
commands =
|
|
||||||
find . -type f -name "*.pyc" -delete
|
|
||||||
python setup.py testr --testr-args='{posargs}'
|
|
||||||
|
|
||||||
[testenv:flake8]
|
|
||||||
commands = flake8
|
|
||||||
|
|
||||||
[testenv:pep8]
|
|
||||||
commands = flake8
|
|
||||||
|
|
||||||
[testenv:pyflakes]
|
|
||||||
commands = flake8
|
|
||||||
|
|
||||||
[testenv:cover]
|
|
||||||
commands = python setup.py testr --coverage --testr-args='{posargs}'
|
|
||||||
|
|
||||||
[testenv:venv]
|
|
||||||
commands = {posargs}
|
|
||||||
|
|
||||||
[flake8]
|
|
||||||
# ignored flake8 codes:
|
|
||||||
# H302 import only modules
|
|
||||||
# H402 one line docstring needs punctuation
|
|
||||||
# H404 multi line docstring should start with a summary
|
|
||||||
# H405 multi line docstring summary not separated with an empty line
|
|
||||||
# H904 Wrap long lines in parentheses instead of a backslash
|
|
||||||
# See cueclient for other ignored codes that may apply here
|
|
||||||
|
|
||||||
ignore = H302,H402,H404,H405,H904
|
|
||||||
builtins = _
|
|
||||||
exclude = .venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,build,tools
|
|
Loading…
Reference in New Issue
Block a user