Compare commits

..

52 Commits
0.0.3 ... 0.1.0

Author SHA1 Message Date
Jenkins
e689b3233e Merge "Add a description field for resource plan" 2016-10-06 13:07:28 +00:00
Jenkins
1f422f4c5c Merge "Add trigger update client" 2016-10-06 13:07:19 +00:00
Jenkins
fda6cdfb7b Merge "Remove copy of incubated Oslo code" 2016-10-06 12:57:15 +00:00
OpenStack Proposal Bot
448bb4468f Updated from global requirements
Change-Id: Ic3a9ecca756ec01c986f0028b5bf49dfbb11ca48
2016-09-30 20:05:43 +00:00
ChangBo Guo(gcb)
ce263ecc9e Remove copy of incubated Oslo code
The Oslo team has moved all previously incubated code from the
openstack/oslo-incubator repository into separate library repositories
and released those libraries to the Python Package Index. Many of our
big tent project teams are still using the old, unsupported, incubated
versions of the code. The Oslo team has been working to remove that
incubated code from projects, and the time has come to finish that work.

As one of community-wide goals in Ocata, please see:
https://github.com/openstack/governance/blob/master/goals/ocata/remove-incubated-oslo-code.rst

Note: This commit also fix pep8 violations.

Change-Id: Ic2d8079b85ebd302a27785772462378f13d593d0
2016-09-29 15:33:58 +00:00
Jenkins
d2d3a475e2 Merge "Update homepage with developer documentation page" 2016-09-29 11:05:51 +00:00
yizhihui
e0a2b0edcd Fix restore-create failed with "no attribute 'username'"
Change-Id: I5fa824a82d199fef6620318ccb93f156c69652bd
2016-09-29 12:29:05 +08:00
Tony Xu
6113f97d2f Update homepage with developer documentation page
Change-Id: I4d833e796da4ee02485e197c7ec5603f229e188f
2016-09-27 00:37:45 +08:00
Jenkins
b7ceed787e Merge "Add restore user and password to restore-create" 2016-09-25 08:53:32 +00:00
chenying
f18cf64f9d Add a description field for resource plan
Change-Id: I2191a557b2777a9c7e92b1c9bc0fb153cb7ec2af
2016-09-22 20:19:46 +08:00
Jenkins
c0bddb93d5 Merge "Shell: restore & plan CLI parameters" 2016-09-22 10:53:10 +00:00
OpenStack Proposal Bot
25beeb0819 Updated from global requirements
Change-Id: Ie1ac3466dfc6d820fdae4b0b596281a42aac6a47
2016-09-21 06:48:20 +00:00
zhangshuai
4c6a252b76 Add trigger update client
To keep consistency with api doc, add trigger update client,
and fix plan update client.

Change-Id: Ie2e6e01bde0d3c8a947685874dcb2d82a6a49e12
2016-09-21 11:21:00 +08:00
Yuval Brik
7c3ab24bf1 Add restore user and password to restore-create
Add restore_user and restore_password to restore-create command.
Will be sent in restore body as 'restore_auth'

Change-Id: Iac54ad345c4a43427b0353fde6ca9e159300d522
2016-09-15 16:40:39 +03:00
Yuval Brik
b304d5978d Shell: restore & plan CLI parameters
Current restore and plan parameter are passed in the key=value form,
which doesn't fix the requirement of key=value pairs for each
resource (i.e dictionary).
Change the restore and plan parameters to be passed in one of the
following formats:
1. JSON using the --parameter-json '{"OS::Cinder::Volume": { ... } }'
2. Multiple --parameter option for each resource:
   --parameter resource_type=OS::Cinder::Volume,resource_id=<uuid>,k=v

Change-Id: I416dc1f00060a5c994984ddfc04c30d1a04c803c
2016-09-15 16:35:41 +03:00
Jenkins
bfc9c63952 Merge "Updated from global requirements" 2016-09-05 09:30:20 +00:00
Yuval Brik
0fc2893234 Rename package python-karborclient
Rename package name to be python-karborclient following the project
and repository rename.

Change-Id: I7171e6ef12bc8de7fc6038534dac86a44094ad51
2016-09-04 12:17:33 +03:00
OpenStack Proposal Bot
51e14a5231 Updated from global requirements
Change-Id: I66bcdb9509ff266baf01129f56814836ab975eb6
2016-09-03 02:01:34 +00:00
Jenkins
d8da515092 Merge "Fix package to be 'karborclient'" 2016-08-29 07:54:52 +00:00
Yuval Brik
271998a5e8 Fix package to be 'karborclient'
Package name will be 'python-smaugclient' for pypi, and
'karborclient' for python

Change-Id: I62290f48e2cc5d4b7f837abaaf44d6b21251f57e
2016-08-28 15:02:50 +03:00
zhangshuai
ef4f89da06 fix .coveragerc
Replace karbor as karborclient in .coveragerc,

Change-Id: I1761237c252707411f5e7b4548ce7d5e89d57079
2016-08-26 17:50:37 +08:00
Yuval Brik
6b3ba9f4af Change package name back to smaugclient
Change the package name to smaugclient to allow a sane release

Change-Id: I39843f7c7c46b4fe16f9cb03cfff1647265f83f0
2016-08-23 15:29:33 +03:00
chenying
44f20e3019 Change Smaug to Karbor
There was a decision in the community to change the project name.

Change-Id: I552759662151f424d752ced8f1df2e6664f434e4
2016-08-18 22:59:45 +08:00
OpenStack Proposal Bot
321b6f640a Updated from global requirements
Change-Id: Idc45cd53c60b5f391f2547d56e7e12ca2094dcce
2016-08-09 10:31:15 +00:00
Jenkins
86b59bd334 Merge "Remove discover from test-requirements" 2016-08-09 08:13:04 +00:00
Swapnil Kulkarni (coolsvap)
c25f584fa0 Remove discover from test-requirements
It's only needed for python < 2.7 which is not supported

Change-Id: Ib26c5f2fa5c540cfa1cf3cb6b05a106bb864af64
2016-07-22 04:12:45 +00:00
chenying
2879e0df18 Fix the parameter field not being successfully passed with plan create command
Change-Id: Ie17be4f8db459e66ab0d4e755282a62c471d38ce
Closes-Bug:#1597689
2016-07-21 17:59:14 +08:00
Jenkins
811a4f0ad0 Merge "Fix checkpoint delete error because of provider api update" 2016-07-21 09:25:27 +00:00
Jenkins
9e8380d8d5 Merge "Add __ne__ built-in function" 2016-07-21 09:08:45 +00:00
Jenkins
6d10a66474 Merge "Remove unused LOG" 2016-07-21 09:08:12 +00:00
chenying
6f30c77f41 Fix checkpoint delete error because of provider api update
Change-Id: I455134bc5bdfbfa113ffa303ed86f144903b6504
Closes-Bug:#1597670
2016-07-21 09:02:37 +00:00
zhangshuai
368eaf9aed fix scheduledoperation show and delete
Change-Id: Ie7e3e9b0010d4b42018deafe649a8ed652528830
Closes-Bug:#1603277
2016-07-15 10:13:15 +08:00
zhangshuai
ea3e6e775a fix scheduledoperation list, object has no attribute 'type'
Change-Id: Icb7380cc84684298e5480ddc8a9e0bb0f8160ac5
Closes-Bugs:#1603069
2016-07-14 20:28:19 +08:00
Daiki Kato
4599b87f1c Fixed argment in trigger-create and scheduledoperation-create
Colon was replaced with a semi-colon.

Change-Id: Ia48815a059ae3cb0bd0aab4a787159a733e309e9
2016-07-14 20:26:42 +08:00
liangjingtao
a0a38d5e68 Remove unused LOG
This is to remove unused LOG to keep code clean.

Change-Id: I037a1db59a7297bdcf64fa576652819daf4c6e48
2016-07-09 11:28:27 +08:00
yuyafei
7b16de4908 Add __ne__ built-in function
In Python 3 __ne__ by default delegates to __eq__ and inverts the
result, but in Python 2 they urge you to define __ne__ when you
define __eq__ for it to work properly [1].There are no implied
relationships among the comparison operators. The truth of x==y
does not imply that x!=y is false. Accordingly, when defining
__eq__(), one should also define __ne__() so that the operators
will behave as expected.
[1]https://docs.python.org/2/reference/datamodel.html#object.__ne__

Change-Id: Iae22095146e64081f362601665284b43d0056f48
Closes-Bug: #1586268
2016-07-05 15:38:37 +08:00
OpenStack Proposal Bot
9292e6fb2e Updated from global requirements
Change-Id: I55ba6361c75d6d3622f529624c8fe778d55cd231
2016-06-30 18:49:57 +00:00
Jenkins
25971fd867 Merge "Return actual object, not raw, when creating" 2016-06-28 09:27:19 +00:00
Yuval Brik
0644b6e175 Return actual object, not raw, when creating
When creating objects (checkpoint, plan, restore, scheduled operation,
trigger, etc) return the actual object, and not a raw dictionary.
Because a raw dictionary was returned on create and an actual object was
returned on get, this lead to the following confusion:

  checkpoint = smaug_client.checkpoint.create(...)
  checkpoint_id = checkpoint['id']
  checkpoint = smaug_client.checkpoint.get(...)
  checkpoint_id = checkpoint.id

Change-Id: I30c8eb4468d8fba830a64f336dd6cfa7793f0b48
2016-06-22 10:49:06 +03:00
OpenStack Proposal Bot
20139d066f Updated from global requirements
Change-Id: I78e0fa4c64e4a0916f25a7016c564d2d41861483
2016-06-21 18:05:49 +00:00
Jenkins
4225036154 Merge "The parameters of plan could be an empty dict without being configured" 2016-06-20 14:22:33 +00:00
chenying
db20090283 The parameters of plan could be an empty dict without being configured
Change-Id: Ife1796048a5830df707627aa7fcceae499699bff
2016-06-20 15:41:16 +08:00
OpenStack Proposal Bot
537ce1ed60 Updated from global requirements
Change-Id: I955acc77803e5f42f7f8d4d3a9af262df3e1c493
2016-06-01 13:54:35 +00:00
chenying
18ae2eb061 Fix creating scheduled_operations error
Change-Id: I5f150a6065424adbce12e2dc08a3e1cc784ef410
Closes-Bug:#1577607
2016-05-03 14:54:07 +08:00
Jenkins
34a9e75754 Merge "Add a field parameters to resource plans" 2016-04-22 09:05:20 +00:00
Jenkins
fb37a4ad52 Merge "Remove the project_id in the url of smaugclient resource" 2016-04-22 09:02:39 +00:00
Jenkins
17342e3d01 Merge "Add show protectables instance endpoint" 2016-04-21 09:26:01 +00:00
chenying
66c6ff898c Add a field parameters to resource plans
Change-Id: I89fa8861535c32262f5c538b80000116bfab488c
Closes-Bug:#1571993
2016-04-19 19:55:45 +08:00
chenying
a1f6310356 Remove the project_id in the url of smaugclient resource
The publicURL of smaug endpoint contains the api version
and project_id. So the project_id in the url of smaugclient
resource can be removed.

Change-Id: I972e584d637781fdca4fbd03d5e3cfa81b2d76cc
Closes-Bug: #1570365
2016-04-14 23:36:22 +08:00
Jenkins
77df0bfe89 Merge "Fix missing a resource class Instances" 2016-04-10 06:45:13 +00:00
chenying
a54697d7bc Add show protectables instance endpoint
Change-Id: I635b1993ef40d4c29e260d28ff11714493bc37a8
Closes-Bug: #1567264
2016-04-07 17:39:45 +08:00
chenying
b8cbc418e4 Fix missing a resource class Instances
Change-Id: I9d45035c0c684bf0e645f36c3aa623b7a079fd30
Closes-Bug: #1564323
2016-03-31 17:45:11 +08:00
56 changed files with 559 additions and 466 deletions

View File

@@ -1,7 +1,7 @@
[run]
branch = True
source = smaugclient
omit = smaugclient/tests/*,smaug/openstack/*
source = karborclient
omit = karborclient/tests/*,karborclient/openstack/*
[report]
ignore_errors = True

View File

@@ -1,4 +1,4 @@
[gerrit]
host=review.openstack.org
port=29418
project=openstack/python-smaugclient.git
project=openstack/python-karborclient.git

View File

@@ -14,4 +14,4 @@ Pull requests submitted through GitHub will be ignored.
Bugs should be filed on Launchpad, not GitHub:
https://launchpad.net/python-smaugclient
https://launchpad.net/python-karborclient

View File

@@ -1,16 +1,16 @@
Smaug
Karbor
======
.. image:: https://img.shields.io/pypi/v/python-smaugclient.svg
:target: https://pypi.python.org/pypi/python-smaugclient/
.. image:: https://img.shields.io/pypi/v/python-karborclient.svg
:target: https://pypi.python.org/pypi/python-karborclient/
:alt: Latest Version
.. image:: https://img.shields.io/pypi/dm/python-smaugclient.svg
:target: https://pypi.python.org/pypi/python-smaugclient/
.. image:: https://img.shields.io/pypi/dm/python-karborclient.svg
:target: https://pypi.python.org/pypi/python-karborclient/
:alt: Downloads
Smaug Mission Statement
Karbor Mission Statement
* Formalize Application Data Protection in OpenStack (APIs, Services, Plugins, …)
* Be able to protect Any Resource in OpenStack(as well as their dependencies)
@@ -25,37 +25,37 @@ Smaug Mission Statement
* `Specs`_
* `How to Contribute`_
.. _PyPi: https://pypi.python.org/pypi/python-smaugclient
.. _Launchpad project: https://launchpad.net/python-smaugclient
.. _Blueprints: https://blueprints.launchpad.net/python-smaugclient
.. _Bugs: https://bugs.launchpad.net/python-smaugclient
.. _Source: https://git.openstack.org/cgit/openstack/python-smaugclient
.. _PyPi: https://pypi.python.org/pypi/python-karborclient
.. _Launchpad project: https://launchpad.net/python-karborclient
.. _Blueprints: https://blueprints.launchpad.net/python-karborclient
.. _Bugs: https://bugs.launchpad.net/python-karborclient
.. _Source: https://git.openstack.org/cgit/openstack/python-karborclient
.. _How to Contribute: http://docs.openstack.org/infra/manual/developers.html
Python Smaugclient
Python Karborclient
-------------------
python-smaugclient is a client library for Smaug built on the Smaug API.
It provides a Python API (the ``smaugclient`` module) and a command-line tool
(``smaug``).
python-karborclient is a client library for karbor built on the karbor API.
It provides a Python API (the ``karborclient`` module) and a command-line tool
(``karbor``).
Project Resources
-----------------
Project status, bugs, and blueprints are tracked on Launchpad:
* Client bug tracker
* https://launchpad.net/python-smaugclient
* https://launchpad.net/python-karborclient
* Smaug bug tracker
* https://launchpad.net/smaug
* Karbor bug tracker
* https://launchpad.net/karbor
Developer documentation can be found here:
http://docs.openstack.org/developer/smaug
http://docs.openstack.org/developer/karbor
Additional resources are linked from the project wiki page:
https://wiki.openstack.org/wiki/Smaug
https://wiki.openstack.org/wiki/karbor
License
-------

View File

@@ -37,7 +37,7 @@ source_suffix = '.rst'
master_doc = 'index'
# General information about the project.
project = u'python-smaugclient'
project = u'python-karborclient'
copyright = u'2013, OpenStack Foundation'
# If true, '()' will be appended to :func: etc. cross-reference text.

View File

@@ -1,4 +1,4 @@
Welcome to smaugclient's documentation!
Welcome to karborclient's documentation!
========================================================
Contents:

View File

@@ -4,9 +4,9 @@ Installation
At the command line::
$ pip install python-smaugclient
$ pip install python-karborclient
Or, if you have virtualenvwrapper installed::
$ mkvirtualenv python-smaugclient
$ pip install python-smaugclient
$ mkvirtualenv python-karborclient
$ pip install python-karborclient

View File

@@ -2,6 +2,6 @@
Usage
========
To use smaugclient in a project::
To use karborclient in a project::
import smaugclient
import karborclient

View File

@@ -16,4 +16,4 @@ import pbr.version
__version__ = pbr.version.VersionInfo(
'python-smaugclient').version_string()
'python-karborclient').version_string()

View File

@@ -9,7 +9,7 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from smaugclient.common import utils
from karborclient.common import utils
def Client(version, *args, **kwargs):

View File

@@ -24,7 +24,7 @@ import os
import six
from stevedore import extension
from smaugclient.openstack.common.apiclient import exceptions
from karborclient.common.apiclient import exceptions
_discovered_plugins = {}
@@ -41,7 +41,7 @@ def discover_auth_systems():
def add_plugin(ext):
_discovered_plugins[ext.name] = ext.plugin
ep_namespace = "smaugclient.openstack.common.apiclient.auth"
ep_namespace = "karborclient.common.apiclient.auth"
mgr = extension.ExtensionManager(ep_namespace)
mgr.map(add_plugin)
@@ -143,8 +143,7 @@ class BaseAuthPlugin(object):
@classmethod
def add_opts(cls, parser):
"""Populate the parser with the options for this plugin.
"""
"""Populate the parser with the options for this plugin."""
for opt in cls.opt_names:
# use `BaseAuthPlugin.common_opt_names` since it is never
# changed in child classes
@@ -153,8 +152,7 @@ class BaseAuthPlugin(object):
@classmethod
def add_common_opts(cls, parser):
"""Add options that are common for several plugins.
"""
"""Add options that are common for several plugins."""
for opt in cls.common_opt_names:
cls._parser_add_opt(parser, opt)
@@ -191,8 +189,7 @@ class BaseAuthPlugin(object):
@abc.abstractmethod
def _do_authenticate(self, http_client):
"""Protected method for authentication.
"""
"""Protected method for authentication."""
def sufficient_options(self):
"""Check if all required options are present.

View File

@@ -31,8 +31,8 @@ from oslo_utils import uuidutils
import six
from six.moves.urllib import parse
from smaugclient.i18n import _
from smaugclient.openstack.common.apiclient import exceptions
from karborclient.common.apiclient import exceptions
from karborclient.i18n import _
def getid(obj):
@@ -462,8 +462,7 @@ class Resource(object):
@property
def human_id(self):
"""Human-readable ID which can be used for bash completion.
"""
"""Human-readable ID which can be used for bash completion."""
if self.HUMAN_ID:
name = getattr(self, self.NAME_ATTR, None)
if name is not None:
@@ -481,7 +480,7 @@ class Resource(object):
def __getattr__(self, k):
if k not in self.__dict__:
#NOTE(bcwaldon): disallow lazy-loading if already loaded once
# NOTE(bcwaldon): disallow lazy-loading if already loaded once
if not self.is_loaded():
self.get()
return self.__getattr__(k)
@@ -513,6 +512,9 @@ class Resource(object):
return False
return self._info == other._info
def __ne__(self, other):
return not self.__eq__(other)
def is_loaded(self):
return self._loaded

View File

@@ -36,9 +36,8 @@ from oslo_log import log as logging
from oslo_utils import importutils
import requests
from smaugclient.i18n import _
from smaugclient.openstack.common.apiclient import exceptions
from karborclient.i18n import _
from karborclient.openstack.common.apiclient import exceptions
_logger = logging.getLogger(__name__)
@@ -63,7 +62,7 @@ class HTTPClient(object):
into terminal and send the same request with curl.
"""
user_agent = "smaugclient.openstack.common.apiclient"
user_agent = "karborclient.common.apiclient"
def __init__(self,
auth_plugin,
@@ -272,7 +271,7 @@ class HTTPClient(object):
>>> def test_clients():
... from keystoneclient.auth import keystone
... from openstack.common.apiclient import client
... from karborclient.common.apiclient import client
... auth = keystone.KeystoneAuthPlugin(
... username="user", password="pass", tenant_name="tenant",
... auth_url="http://auth:5000/v2.0")
@@ -358,8 +357,7 @@ class BaseClient(object):
"Must be one of: %(version_map)s") % {
'api_name': api_name,
'version': version,
'version_map': ', '.join(version_map.keys())
}
'version_map': ', '.join(version_map.keys())}
raise exceptions.UnsupportedVersion(msg)
return importutils.import_class(client_path)

View File

@@ -24,12 +24,11 @@ import sys
import six
from smaugclient.i18n import _
from karborclient.i18n import _
class ClientException(Exception):
"""The base exception class for all exceptions this library raises.
"""
"""The base exception class for all exceptions this library raises."""
pass
@@ -107,8 +106,7 @@ class AmbiguousEndpoints(EndpointException):
class HttpError(ClientException):
"""The base exception class for all HTTP exceptions.
"""
"""The base exception class for all HTTP exceptions."""
http_status = 0
message = _("HTTP Error")
@@ -426,7 +424,7 @@ def from_response(response, method, url):
"""
req_id = response.headers.get("x-openstack-request-id")
#NOTE(hdd) true for older versions of nova and cinder
# NOTE(hdd) true for older versions of nova and cinder
if not req_id:
req_id = response.headers.get("x-compute-request-id")
kwargs = {

View File

@@ -30,7 +30,7 @@ import requests
import six
from six.moves.urllib import parse
from smaugclient.openstack.common.apiclient import client
from karborclient.common.apiclient import client
def assert_has_keys(dct, required=None, optional=None):
@@ -48,8 +48,7 @@ def assert_has_keys(dct, required=None, optional=None):
class TestResponse(requests.Response):
"""Wrap requests.Response and provide a convenient initialization.
"""
"""Wrap requests.Response and provide a convenient initialization."""
def __init__(self, data):
super(TestResponse, self).__init__()
@@ -77,19 +76,21 @@ class TestResponse(requests.Response):
self.headers == other.headers and
self._content == other._content)
def __ne__(self, other):
return not self.__eq__(other)
class FakeHTTPClient(client.HTTPClient):
def __init__(self, *args, **kwargs):
self.callstack = []
self.fixtures = kwargs.pop("fixtures", None) or {}
if not args and not "auth_plugin" in kwargs:
if not args and "auth_plugin" not in kwargs:
args = (None, )
super(FakeHTTPClient, self).__init__(*args, **kwargs)
def assert_called(self, method, url, body=None, pos=-1):
"""Assert than an API method was just called.
"""
"""Assert than an API method was just called."""
expected = (method, url)
called = self.callstack[pos][0:2]
assert self.callstack, \
@@ -104,8 +105,7 @@ class FakeHTTPClient(client.HTTPClient):
(self.callstack[pos][3], body))
def assert_called_anytime(self, method, url, body=None):
"""Assert than an API method was called anytime in the test.
"""
"""Assert than an API method was called anytime in the test."""
expected = (method, url)
assert self.callstack, \

View File

@@ -20,8 +20,9 @@ import copy
import six
from six.moves.urllib import parse
from smaugclient.common import http
from smaugclient.openstack.common.apiclient import exceptions
from karborclient.common.apiclient import exceptions
from karborclient.common import http
SORT_DIR_VALUES = ('asc', 'desc')
SORT_KEY_VALUES = ('id', 'status', 'name', 'created_at')
@@ -160,10 +161,9 @@ class Manager(object):
if detailed:
detail = "/detail"
return ("/v1/%(project_id)s/%(resource_type)s%(detail)s"
return ("/%(resource_type)s%(detail)s"
"%(query_string)s" %
{"project_id": self.project_id,
"resource_type": resource_type, "detail": detail,
{"resource_type": resource_type, "detail": detail,
"query_string": query_string})
def _format_sort_param(self, sort):
@@ -331,6 +331,9 @@ class Resource(object):
return False
return self._info == other._info
def __ne__(self, other):
return not self.__eq__(other)
def is_loaded(self):
return self._loaded

View File

@@ -26,10 +26,10 @@ import requests
import six
from six.moves import urllib
from smaugclient.openstack.common.apiclient import exceptions as exc
from karborclient.common.apiclient import exceptions as exc
LOG = logging.getLogger(__name__)
USER_AGENT = 'python-smaugclient'
USER_AGENT = 'python-karborclient'
CHUNKSIZE = 1024 * 64 # 64kB
@@ -299,7 +299,7 @@ class HTTPClient(object):
class SessionClient(keystone_adapter.Adapter):
"""Smaug specific keystoneclient Adapter.
"""karbor specific keystoneclient Adapter.
"""
@@ -386,7 +386,7 @@ def _construct_http_client(*args, **kwargs):
'service_type': service_type,
'region_name': region_name,
'service_name': service_name,
'user_agent': 'python-smaugclient',
'user_agent': 'python-karborclient',
}
parameters.update(kwargs)
return SessionClient(**parameters)

View File

@@ -18,15 +18,12 @@ import sys
import six
import uuid
from oslo_log import log as logging
from oslo_utils import encodeutils
from oslo_utils import importutils
import prettytable
from smaugclient.openstack.common.apiclient import exceptions
LOG = logging.getLogger(__name__)
from karborclient.common.apiclient import exceptions
# Decorator for cli-args
@@ -53,7 +50,7 @@ def env(*vars, **kwargs):
def import_versioned_module(version, submodule=None):
module = 'smaugclient.v%s' % version
module = 'karborclient.v%s' % version
if submodule:
module = '.'.join((module, submodule))
return importutils.import_module(module)

View File

@@ -18,7 +18,7 @@ See http://docs.openstack.org/developer/oslo.i18n/usage.html
import oslo_i18n
_translators = oslo_i18n.TranslatorFactory(domain='smaugclient')
_translators = oslo_i18n.TranslatorFactory(domain='karborclient')
# The primary translation function using the well-known name "_"
_ = _translators.primary

View File

@@ -11,7 +11,7 @@
# under the License.
"""
Command-line interface to the Smaug Project.
Command-line interface to the karbor Project.
"""
from __future__ import print_function
@@ -31,15 +31,16 @@ from oslo_utils import encodeutils
import six
import six.moves.urllib.parse as urlparse
import smaugclient
from smaugclient import client as smaug_client
from smaugclient.common import utils
from smaugclient.openstack.common.apiclient import exceptions as exc
import karborclient
from karborclient import client as karbor_client
from karborclient.common.apiclient import exceptions as exc
from karborclient.common import utils
logger = logging.getLogger(__name__)
class SmaugShell(object):
class KarborShell(object):
def _append_global_identity_args(self, parser):
# Register the CLI arguments that have moved to the session object.
@@ -50,9 +51,9 @@ class SmaugShell(object):
def get_base_parser(self):
parser = argparse.ArgumentParser(
prog='smaug',
prog='karbor',
description=__doc__.strip(),
epilog='See "smaug help COMMAND" '
epilog='See "karbor help COMMAND" '
'for help on a specific command.',
add_help=False,
formatter_class=HelpFormatter,
@@ -65,13 +66,13 @@ class SmaugShell(object):
parser.add_argument('--version',
action='version',
version=smaugclient.__version__,
version=karborclient.__version__,
help="Show program's version number and exit.")
parser.add_argument('-d', '--debug',
default=bool(utils.env('SMAUGCLIENT_DEBUG')),
default=bool(utils.env('KARBORCLIENT_DEBUG')),
action='store_true',
help='Defaults to env[SMAUGCLIENT_DEBUG].')
help='Defaults to env[KARBORCLIENT_DEBUG].')
parser.add_argument('-v', '--verbose',
default=False, action="store_true",
@@ -117,14 +118,14 @@ class SmaugShell(object):
action='store_true',
help="Do not contact keystone for a token. "
"Defaults to env[OS_NO_CLIENT_AUTH].")
parser.add_argument('--smaug-url',
default=utils.env('SMAUG_URL'),
help='Defaults to env[SMAUG_URL].')
parser.add_argument('--karbor-url',
default=utils.env('KARBOR_URL'),
help='Defaults to env[KARBOR_URL].')
parser.add_argument('--smaug-api-version',
parser.add_argument('--karbor-api-version',
default=utils.env(
'SMAUG_API_VERSION', default='1'),
help='Defaults to env[SMAUG_API_VERSION] '
'KARBOR_API_VERSION', default='1'),
help='Defaults to env[KARBOR_API_VERSION] '
'or 1.')
parser.add_argument('--os-service-type',
@@ -136,9 +137,9 @@ class SmaugShell(object):
help='Defaults to env[OS_ENDPOINT_TYPE].')
parser.add_argument('--include-password',
default=bool(utils.env('SMAUG_INCLUDE_PASSWORD')),
default=bool(utils.env('KARBOR_INCLUDE_PASSWORD')),
action='store_true',
help='Send os-username and os-password to smaug.')
help='Send os-username and os-password to karbor.')
self._append_global_identity_args(parser)
@@ -289,7 +290,7 @@ class SmaugShell(object):
self._setup_logging(options.debug)
# build available subcommands based on version
api_version = options.smaug_api_version
api_version = options.karbor_api_version
subcommand_parser = self.get_subcommand_parser(api_version)
self.parser = subcommand_parser
@@ -320,11 +321,11 @@ class SmaugShell(object):
" env[OS_AUTH_TOKEN]")
if args.os_no_client_auth:
if not args.smaug_url:
if not args.karbor_url:
raise exc.CommandError(
"If you specify --os-no-client-auth"
" you must also specify a Smaug API URL"
" via either --smaug-url or env[SMAUG_URL]")
" you must also specify a Karbor API URL"
" via either --karbor-url or env[KARBOR_URL]")
else:
# Tenant name or ID is needed to make keystoneclient retrieve a
@@ -343,10 +344,10 @@ class SmaugShell(object):
" either --os-auth-url or via"
" env[OS_AUTH_URL]")
endpoint = args.smaug_url
endpoint = args.karbor_url
if args.os_no_client_auth:
# Authenticate through smaug, don't use session
# Authenticate through karbor, don't use session
kwargs = {
'username': args.os_username,
'password': args.os_password,
@@ -380,13 +381,12 @@ class SmaugShell(object):
project_domain_name=args.os_project_domain_name)
endpoint_type = args.os_endpoint_type or 'publicURL'
service_type = args.os_service_type or 'application-catalog'
service_type = args.os_service_type or 'data-protect'
if not endpoint:
endpoint = keystone_auth.get_endpoint(
keystone_session,
service_type=service_type,
region_name=args.os_region_name)
endpoint = keystone_auth.get_endpoint(
keystone_session,
service_type=service_type,
region_name=args.os_region_name)
kwargs = {
'session': keystone_session,
@@ -399,7 +399,7 @@ class SmaugShell(object):
if args.api_timeout:
kwargs['timeout'] = args.api_timeout
client = smaug_client.Client(api_version, endpoint, **kwargs)
client = karbor_client.Client(api_version, endpoint, **kwargs)
args.func(client, args)
@@ -441,10 +441,10 @@ class HelpFormatter(argparse.HelpFormatter):
def main(args=sys.argv[1:]):
try:
SmaugShell().main(args)
KarborShell().main(args)
except KeyboardInterrupt:
print('... terminating smaug client', file=sys.stderr)
print('... terminating karbor client', file=sys.stderr)
sys.exit(1)
except Exception as e:
if '--debug' in args or '-d' in args:

View File

@@ -55,6 +55,9 @@ class TestResponse(requests.Response):
def __eq__(self, other):
return self.__dict__ == other.__dict__
def __ne__(self, other):
return not self.__eq__(other)
@property
def text(self):
return self._text

View File

@@ -16,12 +16,12 @@ import socket
import mock
import testtools
from smaugclient.common import http
from smaugclient.openstack.common.apiclient import exceptions as exc
from smaugclient.tests.unit import fakes
from karborclient.common.apiclient import exceptions as exc
from karborclient.common import http
from karborclient.tests.unit import fakes
@mock.patch('smaugclient.common.http.requests.request')
@mock.patch('karborclient.common.http.requests.request')
class HttpClientTest(testtools.TestCase):
# Patch os.environ to avoid required auth info.
@@ -29,7 +29,7 @@ class HttpClientTest(testtools.TestCase):
super(HttpClientTest, self).setUp()
def test_http_raw_request(self, mock_request):
headers = {'User-Agent': 'python-smaugclient'}
headers = {'User-Agent': 'python-karborclient'}
mock_request.return_value = \
fakes.FakeHTTPResponse(
200, 'OK',
@@ -71,15 +71,15 @@ class HttpClientTest(testtools.TestCase):
mock_request.assert_has_calls([
mock.call('GET', 'http://example.com:8082',
allow_redirects=False,
headers={'User-Agent': 'python-smaugclient'}),
headers={'User-Agent': 'python-karborclient'}),
mock.call('GET', 'http://example.com:8082',
allow_redirects=False,
headers={'User-Agent': 'python-smaugclient',
headers={'User-Agent': 'python-karborclient',
'X-Auth-Key': 'pass',
'X-Auth-User': 'user'}),
mock.call('GET', 'http://example.com:8082',
allow_redirects=False,
headers={'User-Agent': 'python-smaugclient',
headers={'User-Agent': 'python-karborclient',
'X-Auth-Token': 'abcd1234'})
])
@@ -101,7 +101,7 @@ class HttpClientTest(testtools.TestCase):
'GET', 'http://example.com:8082',
allow_redirects=False,
headers={'X-Region-Name': 'RegionOne',
'User-Agent': 'python-smaugclient'})
'User-Agent': 'python-karborclient'})
def test_http_json_request(self, mock_request):
# Record a 200
@@ -119,7 +119,7 @@ class HttpClientTest(testtools.TestCase):
'GET', 'http://example.com:8082',
allow_redirects=False,
headers={'Content-Type': 'application/json',
'User-Agent': 'python-smaugclient'})
'User-Agent': 'python-karborclient'})
def test_http_json_request_argument_passed_to_requests(self, mock_request):
"""Check that we have sent the proper arguments to requests."""
@@ -147,7 +147,7 @@ class HttpClientTest(testtools.TestCase):
data='"text"',
headers={'Content-Type': 'application/json',
'X-Auth-Url': 'http://AUTH_URL',
'User-Agent': 'python-smaugclient'})
'User-Agent': 'python-karborclient'})
def test_http_json_request_w_req_body(self, mock_request):
# Record a 200
@@ -166,7 +166,7 @@ class HttpClientTest(testtools.TestCase):
data='"test-body"',
allow_redirects=False,
headers={'Content-Type': 'application/json',
'User-Agent': 'python-smaugclient'})
'User-Agent': 'python-karborclient'})
def test_http_json_request_non_json_resp_cont_type(self, mock_request):
# Record a 200
@@ -184,7 +184,7 @@ class HttpClientTest(testtools.TestCase):
'GET', 'http://example.com:8082', data='"test-data"',
allow_redirects=False,
headers={'Content-Type': 'application/json',
'User-Agent': 'python-smaugclient'})
'User-Agent': 'python-karborclient'})
def test_http_json_request_invalid_json(self, mock_request):
# Record a 200
@@ -202,7 +202,7 @@ class HttpClientTest(testtools.TestCase):
'GET', 'http://example.com:8082',
allow_redirects=False,
headers={'Content-Type': 'application/json',
'User-Agent': 'python-smaugclient'})
'User-Agent': 'python-karborclient'})
def test_http_manual_redirect_delete(self, mock_request):
mock_request.side_effect = [
@@ -223,11 +223,11 @@ class HttpClientTest(testtools.TestCase):
mock.call('DELETE', 'http://example.com:8082/foo',
allow_redirects=False,
headers={'Content-Type': 'application/json',
'User-Agent': 'python-smaugclient'}),
'User-Agent': 'python-karborclient'}),
mock.call('DELETE', 'http://example.com:8082/foo/bar',
allow_redirects=False,
headers={'Content-Type': 'application/json',
'User-Agent': 'python-smaugclient'})
'User-Agent': 'python-karborclient'})
])
def test_http_manual_redirect_post(self, mock_request):
@@ -249,11 +249,11 @@ class HttpClientTest(testtools.TestCase):
mock.call('POST', 'http://example.com:8082/foo',
allow_redirects=False,
headers={'Content-Type': 'application/json',
'User-Agent': 'python-smaugclient'}),
'User-Agent': 'python-karborclient'}),
mock.call('POST', 'http://example.com:8082/foo/bar',
allow_redirects=False,
headers={'Content-Type': 'application/json',
'User-Agent': 'python-smaugclient'})
'User-Agent': 'python-karborclient'})
])
def test_http_manual_redirect_put(self, mock_request):
@@ -275,11 +275,11 @@ class HttpClientTest(testtools.TestCase):
mock.call('PUT', 'http://example.com:8082/foo',
allow_redirects=False,
headers={'Content-Type': 'application/json',
'User-Agent': 'python-smaugclient'}),
'User-Agent': 'python-karborclient'}),
mock.call('PUT', 'http://example.com:8082/foo/bar',
allow_redirects=False,
headers={'Content-Type': 'application/json',
'User-Agent': 'python-smaugclient'})
'User-Agent': 'python-karborclient'})
])
def test_http_manual_redirect_prohibited(self, mock_request):
@@ -295,7 +295,7 @@ class HttpClientTest(testtools.TestCase):
'DELETE', 'http://example.com:8082/foo',
allow_redirects=False,
headers={'Content-Type': 'application/json',
'User-Agent': 'python-smaugclient'})
'User-Agent': 'python-karborclient'})
def test_http_manual_redirect_error_without_location(self, mock_request):
mock_request.return_value = \
@@ -310,7 +310,7 @@ class HttpClientTest(testtools.TestCase):
'DELETE', 'http://example.com:8082/foo',
allow_redirects=False,
headers={'Content-Type': 'application/json',
'User-Agent': 'python-smaugclient'})
'User-Agent': 'python-karborclient'})
def test_http_json_request_redirect(self, mock_request):
# Record the 302
@@ -333,11 +333,11 @@ class HttpClientTest(testtools.TestCase):
mock.call('GET', 'http://example.com:8082',
allow_redirects=False,
headers={'Content-Type': 'application/json',
'User-Agent': 'python-smaugclient'}),
'User-Agent': 'python-karborclient'}),
mock.call('GET', 'http://example.com:8082',
allow_redirects=False,
headers={'Content-Type': 'application/json',
'User-Agent': 'python-smaugclient'})
'User-Agent': 'python-karborclient'})
])
def test_http_404_json_request(self, mock_request):
@@ -356,7 +356,7 @@ class HttpClientTest(testtools.TestCase):
'GET', 'http://example.com:8082',
allow_redirects=False,
headers={'Content-Type': 'application/json',
'User-Agent': 'python-smaugclient'})
'User-Agent': 'python-karborclient'})
def test_http_300_json_request(self, mock_request):
mock_request.return_value = \
@@ -374,10 +374,10 @@ class HttpClientTest(testtools.TestCase):
'GET', 'http://example.com:8082',
allow_redirects=False,
headers={'Content-Type': 'application/json',
'User-Agent': 'python-smaugclient'})
'User-Agent': 'python-karborclient'})
def test_fake_json_request(self, mock_request):
headers = {'User-Agent': 'python-smaugclient'}
headers = {'User-Agent': 'python-karborclient'}
mock_request.side_effect = [socket.gaierror]
client = http.HTTPClient('fake://example.com:8082')
@@ -388,7 +388,7 @@ class HttpClientTest(testtools.TestCase):
headers=headers)
def test_http_request_socket_error(self, mock_request):
headers = {'User-Agent': 'python-smaugclient'}
headers = {'User-Agent': 'python-karborclient'}
mock_request.side_effect = [socket.gaierror]
client = http.HTTPClient('http://example.com:8082')
@@ -399,7 +399,7 @@ class HttpClientTest(testtools.TestCase):
headers=headers)
def test_http_request_socket_timeout(self, mock_request):
headers = {'User-Agent': 'python-smaugclient'}
headers = {'User-Agent': 'python-karborclient'}
mock_request.side_effect = [socket.timeout]
client = http.HTTPClient('http://example.com:8082')
@@ -424,7 +424,7 @@ class HttpClientTest(testtools.TestCase):
'GET', 'http://example.com:8082',
allow_redirects=False,
headers={'Content-Type': 'application/json',
'User-Agent': 'python-smaugclient'},
'User-Agent': 'python-karborclient'},
timeout=float(123))
def test_get_system_ca_file(self, mock_request):
@@ -445,7 +445,7 @@ class HttpClientTest(testtools.TestCase):
client = http.HTTPClient('https://foo', cacert="NOWHERE")
self.assertEqual("NOWHERE", client.verify_cert)
with mock.patch('smaugclient.common.http.get_system_ca_file') as gsf:
with mock.patch('karborclient.common.http.get_system_ca_file') as gsf:
gsf.return_value = "SOMEWHERE"
client = http.HTTPClient('https://foo')
self.assertEqual("SOMEWHERE", client.verify_cert)

View File

@@ -11,13 +11,13 @@
# under the License.
"""
Tests for `smaugclient` module.
Tests for `karborclient` module.
"""
from smaugclient.tests.unit import base
from karborclient.tests.unit import base
class TestSmaugclient(base.TestCaseShell):
class TestKarborclient(base.TestCaseShell):
def test_something(self):
pass

View File

@@ -23,9 +23,9 @@ from oslo_log import log
import six
from testtools import matchers
from smaugclient.openstack.common.apiclient import exceptions
import smaugclient.shell
from smaugclient.tests.unit import base
from karborclient.common.apiclient import exceptions
import karborclient.shell
from karborclient.tests.unit import base
FAKE_ENV = {'OS_USERNAME': 'username',
@@ -51,7 +51,7 @@ def _create_ver_list(versions):
class TestArgs(object):
package_version = ''
smaug_repo_url = 'http://127.0.0.1'
karbor_repo_url = 'http://127.0.0.1'
exists_action = ''
is_public = False
categories = []
@@ -78,7 +78,7 @@ class ShellCommandTest(ShellTest):
def get_auth_endpoint(bound_self, args):
return ('test', {})
self.useFixture(fixtures.MonkeyPatch(
'smaugclient.shell.SmaugShell._get_endpoint_and_kwargs',
'karborclient.shell.KarborShell._get_endpoint_and_kwargs',
get_auth_endpoint))
self.client = mock.MagicMock()
@@ -99,7 +99,7 @@ class ShellCommandTest(ShellTest):
try:
sys.stdout = six.StringIO()
sys.stderr = six.StringIO()
_shell = smaugclient.shell.SmaugShell()
_shell = karborclient.shell.KarborShell()
_shell.main(argstr.split())
except SystemExit:
exc_type, exc_value, exc_traceback = sys.exc_info()
@@ -133,9 +133,9 @@ class ShellCommandTest(ShellTest):
def test_help(self):
required = [
'.*?^usage: smaug',
'.*?^usage: karbor',
'.*?^\s+plan-create\s+Create a plan.',
'.*?^See "smaug help COMMAND" for help on a specific command',
'.*?^See "karbor help COMMAND" for help on a specific command',
]
stdout, stderr = self.shell('help')
for r in required:
@@ -144,7 +144,7 @@ class ShellCommandTest(ShellTest):
def test_help_on_subcommand(self):
required = [
'.*?^usage: smaug plan-create',
'.*?^usage: karbor plan-create',
'.*?^Create a plan.',
]
stdout, stderr = self.shell('help plan-create')
@@ -154,9 +154,9 @@ class ShellCommandTest(ShellTest):
def test_help_no_options(self):
required = [
'.*?^usage: smaug',
'.*?^usage: karbor',
'.*?^\s+plan-create\s+Create a plan',
'.*?^See "smaug help COMMAND" for help on a specific command',
'.*?^See "karbor help COMMAND" for help on a specific command',
]
stdout, stderr = self.shell('')
for r in required:

View File

@@ -15,10 +15,10 @@ try:
except ImportError:
import urllib.parse as urlparse
from smaugclient.common import http as base_client
from smaugclient.tests.unit import base
from smaugclient.tests.unit import fakes
from smaugclient.v1 import client
from karborclient.common import http as base_client
from karborclient.tests.unit import base
from karborclient.tests.unit import fakes
from karborclient.v1 import client
REQUEST_ID = 'req-test-request-id'

View File

@@ -12,8 +12,8 @@
import mock
from smaugclient.tests.unit import base
from smaugclient.tests.unit.v1 import fakes
from karborclient.tests.unit import base
from karborclient.tests.unit.v1 import fakes
cs = fakes.FakeClient()
mock_request_return = ({}, {'checkpoint': {}})
@@ -24,75 +24,69 @@ FAKE_PLAN_ID = "3330f8b1-975d-4621-a872-fa9afb43cb6c"
class CheckpointsTest(base.TestCaseShell):
@mock.patch('smaugclient.common.http.HTTPClient.json_request')
@mock.patch('karborclient.common.http.HTTPClient.json_request')
def test_list_checkpoints(self, mock_request):
mock_request.return_value = mock_request_return
cs.checkpoints.list(provider_id=FAKE_PROVIDER_ID)
mock_request.assert_called_with(
'GET',
'/v1/{project_id}/providers/{provider_id}/checkpoints'.format(
project_id=fakes.PROJECT_ID,
'/providers/{provider_id}/checkpoints'.format(
provider_id=FAKE_PROVIDER_ID), headers={})
@mock.patch('smaugclient.common.http.HTTPClient.json_request')
@mock.patch('karborclient.common.http.HTTPClient.json_request')
def test_get_checkpoint(self, mock_request):
mock_request.return_value = mock_request_return
cs.checkpoints.get(FAKE_PROVIDER_ID, '1')
mock_request.assert_called_with(
'GET',
'/v1/{project_id}/providers/{provider_id}/checkpoints/1'.format(
project_id=fakes.PROJECT_ID,
'/providers/{provider_id}/checkpoints/1'.format(
provider_id=FAKE_PROVIDER_ID), headers={})
@mock.patch('smaugclient.common.http.HTTPClient.raw_request')
@mock.patch('karborclient.common.http.HTTPClient.raw_request')
def test_delete_checkpoint(self, mock_request):
mock_request.return_value = mock_request_return
cs.checkpoints.delete(FAKE_PROVIDER_ID, '1')
mock_request.assert_called_with(
'DELETE',
'/v1/{project_id}/providers/{provider_id}/checkpoints/1'.format(
project_id=fakes.PROJECT_ID,
'/providers/{provider_id}/checkpoints/1'.format(
provider_id=FAKE_PROVIDER_ID), headers={})
@mock.patch('smaugclient.common.http.HTTPClient.json_request')
@mock.patch('karborclient.common.http.HTTPClient.json_request')
def test_list_checkpoints_with_marker_limit(self, mock_request):
mock_request.return_value = mock_request_return
cs.checkpoints.list(provider_id=FAKE_PROVIDER_ID,
marker=1234, limit=2)
mock_request.assert_called_with(
'GET',
'/v1/{project_id}/providers/{provider_id}/'
'/providers/{provider_id}/'
'checkpoints?limit=2&marker=1234'.format(
provider_id=FAKE_PROVIDER_ID,
project_id=fakes.PROJECT_ID), headers={})
provider_id=FAKE_PROVIDER_ID), headers={})
@mock.patch('smaugclient.common.http.HTTPClient.json_request')
@mock.patch('karborclient.common.http.HTTPClient.json_request')
def test_list_checkpoints_with_sort_key_dir(self, mock_request):
mock_request.return_value = mock_request_return
cs.checkpoints.list(provider_id=FAKE_PROVIDER_ID,
sort_key='id', sort_dir='asc')
mock_request.assert_called_with(
'GET',
'/v1/{project_id}/providers/{provider_id}/'
'/providers/{provider_id}/'
'checkpoints?sort_dir=asc&sort_key=id'.format(
provider_id=FAKE_PROVIDER_ID,
project_id=fakes.PROJECT_ID), headers={})
provider_id=FAKE_PROVIDER_ID), headers={})
def test_list_checkpoints_with_invalid_sort_key(self):
self.assertRaises(ValueError,
cs.checkpoints.list, FAKE_PROVIDER_ID,
sort_key='invalid', sort_dir='asc')
@mock.patch('smaugclient.common.http.HTTPClient.json_request')
@mock.patch('karborclient.common.http.HTTPClient.json_request')
def test_create_checkpoint(self, mock_request):
mock_request.return_value = mock_request_return
cs.checkpoints.create(FAKE_PROVIDER_ID, FAKE_PLAN_ID)
mock_request.assert_called_with(
'POST',
'/v1/{project_id}/providers/{provider_id}/'
'/providers/{provider_id}/'
'checkpoints'.format(
provider_id=FAKE_PROVIDER_ID,
project_id=fakes.PROJECT_ID),
provider_id=FAKE_PROVIDER_ID),
data={
'checkpoint': {'plan_id': FAKE_PLAN_ID}},
headers={})

View File

@@ -12,8 +12,8 @@
import mock
from smaugclient.tests.unit import base
from smaugclient.tests.unit.v1 import fakes
from karborclient.tests.unit import base
from karborclient.tests.unit.v1 import fakes
cs = fakes.FakeClient()
mock_request_return = ({}, {'plan': {'name': 'fake_name'}})
@@ -21,75 +21,77 @@ mock_request_return = ({}, {'plan': {'name': 'fake_name'}})
class PlansTest(base.TestCaseShell):
@mock.patch('smaugclient.common.http.HTTPClient.json_request')
@mock.patch('karborclient.common.http.HTTPClient.json_request')
def test_list_plans_with_marker_limit(self, mock_request):
mock_request.return_value = mock_request_return
cs.plans.list(marker=1234, limit=2)
mock_request.assert_called_with(
'GET',
'/v1/{project_id}/plans?limit=2&marker=1234'.format(
'/plans?limit=2&marker=1234'.format(
project_id=fakes.PROJECT_ID), headers={})
@mock.patch('smaugclient.common.http.HTTPClient.json_request')
@mock.patch('karborclient.common.http.HTTPClient.json_request')
def test_list_plans_with_sort_key_dir(self, mock_request):
mock_request.return_value = mock_request_return
cs.plans.list(sort_key='id', sort_dir='asc')
mock_request.assert_called_with(
'GET',
'/v1/{project_id}/plans?'
'/plans?'
'sort_dir=asc&sort_key=id'.format(
project_id=fakes.PROJECT_ID), headers={})
@mock.patch('smaugclient.common.http.HTTPClient.json_request')
@mock.patch('karborclient.common.http.HTTPClient.json_request')
def test_list_plans_with_invalid_sort_key(self, mock_request):
self.assertRaises(ValueError,
cs.plans.list, sort_key='invalid', sort_dir='asc')
@mock.patch('smaugclient.common.http.HTTPClient.json_request')
@mock.patch('karborclient.common.http.HTTPClient.json_request')
def test_create_plan(self, mock_request):
mock_request.return_value = mock_request_return
cs.plans.create('Plan name', 'provider_id', '')
cs.plans.create('Plan name', 'provider_id', '', "", '')
mock_request.assert_called_with(
'POST',
'/v1/efc6a88b-9096-4bb6-8634-cda182a6e12a/plans',
'/plans',
data={
'plan': {'provider_id': 'provider_id',
'name': 'Plan name',
'resources': ''}},
'resources': '',
'parameters': '',
'description': ''}},
headers={})
@mock.patch('smaugclient.common.http.HTTPClient.raw_request')
@mock.patch('karborclient.common.http.HTTPClient.raw_request')
def test_delete_plan(self, mock_request):
mock_request.return_value = mock_request_return
cs.plans.delete('1')
mock_request.assert_called_with(
'DELETE',
'/v1/efc6a88b-9096-4bb6-8634-cda182a6e12a/plans/1',
'/plans/1',
headers={})
@mock.patch('smaugclient.common.http.HTTPClient.json_request')
@mock.patch('karborclient.common.http.HTTPClient.json_request')
def test_create_update(self, mock_request):
mock_request.return_value = mock_request_return
cs.plans.update('1', {'name': 'Test name.'})
mock_request.assert_called_with(
'PUT',
'/v1/efc6a88b-9096-4bb6-8634-cda182a6e12a/plans/1',
'/plans/1',
data={'plan': {'name': 'Test name.'}}, headers={})
@mock.patch('smaugclient.common.http.HTTPClient.json_request')
@mock.patch('karborclient.common.http.HTTPClient.json_request')
def test_show_plan(self, mock_request):
mock_request.return_value = mock_request_return
cs.plans.get('1')
mock_request.assert_called_with(
'GET',
'/v1/efc6a88b-9096-4bb6-8634-cda182a6e12a/plans/1',
'/plans/1',
headers={})
@mock.patch('smaugclient.common.http.HTTPClient.json_request')
@mock.patch('karborclient.common.http.HTTPClient.json_request')
def test_show_plan_with_headers(self, mock_request):
mock_request.return_value = mock_request_return
cs.plans.get('1', session_id='fake_session_id')
mock_request.assert_called_with(
'GET',
'/v1/efc6a88b-9096-4bb6-8634-cda182a6e12a/plans/1',
'/plans/1',
headers={'X-Configuration-Session': 'fake_session_id'})

View File

@@ -12,64 +12,70 @@
import mock
from smaugclient.tests.unit import base
from smaugclient.tests.unit.v1 import fakes
from karborclient.tests.unit import base
from karborclient.tests.unit.v1 import fakes
cs = fakes.FakeClient()
mock_request_return = ({}, {'protectable_type': {}})
mock_instances_request_return = ({}, {'instances': {}})
mock_instance_request_return = ({}, {'instance': {}})
class ProtectablesTest(base.TestCaseShell):
@mock.patch('smaugclient.common.http.HTTPClient.json_request')
@mock.patch('karborclient.common.http.HTTPClient.json_request')
def test_list_protectables(self, mock_request):
mock_request.return_value = mock_request_return
cs.protectables.list()
mock_request.assert_called_with(
'GET',
'/v1/{project_id}/protectables'.format(
project_id=fakes.PROJECT_ID), headers={})
'/protectables', headers={})
@mock.patch('smaugclient.common.http.HTTPClient.json_request')
@mock.patch('karborclient.common.http.HTTPClient.json_request')
def test_get_protectables(self, mock_request):
mock_request.return_value = mock_request_return
cs.protectables.get('OS::Cinder::Volume')
mock_request.assert_called_with(
'GET',
'/v1/{project_id}/protectables/OS::Cinder::Volume'.format(
project_id=fakes.PROJECT_ID), headers={})
'/protectables/OS::Cinder::Volume', headers={})
@mock.patch('smaugclient.common.http.HTTPClient.json_request')
@mock.patch('karborclient.common.http.HTTPClient.json_request')
def test_get_protectables_instance(self, mock_request):
mock_request.return_value = mock_instance_request_return
cs.protectables.get_instance('OS::Cinder::Volume', '1')
mock_request.assert_called_with(
'GET',
'/protectables/OS::Cinder::Volume/'
'instances/1', headers={})
@mock.patch('karborclient.common.http.HTTPClient.json_request')
def test_list_protectables_instances(self, mock_request):
mock_request.return_value = mock_instances_request_return
cs.protectables.list_instances('OS::Cinder::Volume')
mock_request.assert_called_with(
'GET',
'/v1/{project_id}/protectables/OS::Cinder::Volume/'
'instances'.format(project_id=fakes.PROJECT_ID), headers={})
'/protectables/OS::Cinder::Volume/'
'instances', headers={})
@mock.patch('smaugclient.common.http.HTTPClient.json_request')
@mock.patch('karborclient.common.http.HTTPClient.json_request')
def test_list_protectables_instances_with_marker_limit(self, mock_request):
mock_request.return_value = mock_instances_request_return
cs.protectables.list_instances('OS::Cinder::Volume',
marker=1234, limit=2)
mock_request.assert_called_with(
'GET',
'/v1/{project_id}/protectables/OS::Cinder::Volume/'
'instances?limit=2&marker=1234'.format(
project_id=fakes.PROJECT_ID), headers={})
'/protectables/OS::Cinder::Volume/'
'instances?limit=2&marker=1234', headers={})
@mock.patch('smaugclient.common.http.HTTPClient.json_request')
@mock.patch('karborclient.common.http.HTTPClient.json_request')
def test_list_protectables_instances_with_sort_key_dir(self, mock_request):
mock_request.return_value = mock_instances_request_return
cs.protectables.list_instances('OS::Cinder::Volume',
sort_key='id', sort_dir='asc')
mock_request.assert_called_with(
'GET',
'/v1/{project_id}/protectables/OS::Cinder::Volume/'
'instances?sort_dir=asc&sort_key=id'.format(
project_id=fakes.PROJECT_ID), headers={})
'/protectables/OS::Cinder::Volume/'
'instances?sort_dir=asc&sort_key=id', headers={})
def test_list_protectables_instances_with_invalid_sort_key(self):
self.assertRaises(ValueError,

View File

@@ -12,8 +12,8 @@
import mock
from smaugclient.tests.unit import base
from smaugclient.tests.unit.v1 import fakes
from karborclient.tests.unit import base
from karborclient.tests.unit.v1 import fakes
cs = fakes.FakeClient()
mock_request_return = ({}, {'provider': {}})
@@ -21,43 +21,39 @@ mock_request_return = ({}, {'provider': {}})
class ProvidersTest(base.TestCaseShell):
@mock.patch('smaugclient.common.http.HTTPClient.json_request')
@mock.patch('karborclient.common.http.HTTPClient.json_request')
def test_get_providers(self, mock_request):
mock_request.return_value = mock_request_return
cs.providers.get('2220f8b1-975d-4621-a872-fa9afb43cb6c')
mock_request.assert_called_with(
'GET',
'/v1/{project_id}/providers/'
'2220f8b1-975d-4621-a872-fa9afb43cb6c'.format(
project_id=fakes.PROJECT_ID), headers={})
'/providers/'
'2220f8b1-975d-4621-a872-fa9afb43cb6c', headers={})
@mock.patch('smaugclient.common.http.HTTPClient.json_request')
@mock.patch('karborclient.common.http.HTTPClient.json_request')
def test_list_providers(self, mock_request):
mock_request.return_value = mock_request_return
cs.providers.list()
mock_request.assert_called_with(
'GET',
'/v1/{project_id}/providers'.format(
project_id=fakes.PROJECT_ID), headers={})
'/providers', headers={})
@mock.patch('smaugclient.common.http.HTTPClient.json_request')
@mock.patch('karborclient.common.http.HTTPClient.json_request')
def test_list_providers_with_marker_limit(self, mock_request):
mock_request.return_value = mock_request_return
cs.providers.list(marker=1234, limit=2)
mock_request.assert_called_with(
'GET',
'/v1/{project_id}/providers?limit=2&marker=1234'.format(
project_id=fakes.PROJECT_ID), headers={})
'/providers?limit=2&marker=1234', headers={})
@mock.patch('smaugclient.common.http.HTTPClient.json_request')
@mock.patch('karborclient.common.http.HTTPClient.json_request')
def test_list_providers_with_sort_key_dir(self, mock_request):
mock_request.return_value = mock_request_return
cs.providers.list(sort_key='id', sort_dir='asc')
mock_request.assert_called_with(
'GET',
'/v1/{project_id}/providers?'
'sort_dir=asc&sort_key=id'.format(
project_id=fakes.PROJECT_ID), headers={})
'/providers?'
'sort_dir=asc&sort_key=id', headers={})
def test_list_providers_with_invalid_sort_key(self):
self.assertRaises(ValueError,

View File

@@ -12,8 +12,8 @@
import mock
from smaugclient.tests.unit import base
from smaugclient.tests.unit.v1 import fakes
from karborclient.tests.unit import base
from karborclient.tests.unit.v1 import fakes
cs = fakes.FakeClient()
mock_request_return = ({}, {'restore': {}})
@@ -21,63 +21,65 @@ mock_request_return = ({}, {'restore': {}})
class RestoresTest(base.TestCaseShell):
@mock.patch('smaugclient.common.http.HTTPClient.json_request')
@mock.patch('karborclient.common.http.HTTPClient.json_request')
def test_list_restores_with_marker_limit(self, mock_request):
mock_request.return_value = mock_request_return
cs.restores.list(marker=1234, limit=2)
mock_request.assert_called_with(
'GET',
'/v1/{project_id}/restores?limit=2&marker=1234'.format(
project_id=fakes.PROJECT_ID), headers={})
'/restores?limit=2&marker=1234', headers={})
@mock.patch('smaugclient.common.http.HTTPClient.json_request')
@mock.patch('karborclient.common.http.HTTPClient.json_request')
def test_list_restores_with_sort_key_dir(self, mock_request):
mock_request.return_value = mock_request_return
cs.restores.list(sort_key='id', sort_dir='asc')
mock_request.assert_called_with(
'GET',
'/v1/{project_id}/restores?'
'sort_dir=asc&sort_key=id'.format(
project_id=fakes.PROJECT_ID), headers={})
'/restores?'
'sort_dir=asc&sort_key=id', headers={})
@mock.patch('smaugclient.common.http.HTTPClient.json_request')
@mock.patch('karborclient.common.http.HTTPClient.json_request')
def test_list_plans_with_invalid_sort_key(self, mock_request):
self.assertRaises(ValueError,
cs.restores.list, sort_key='invalid', sort_dir='asc')
@mock.patch('smaugclient.common.http.HTTPClient.json_request')
@mock.patch('karborclient.common.http.HTTPClient.json_request')
def test_create_restore(self, mock_request):
mock_request.return_value = mock_request_return
cs.restores.create('586cc6ce-e286-40bd-b2b5-dd32694d9944',
'2220f8b1-975d-4621-a872-fa9afb43cb6c',
'192.168.1.2:35357/v2.0',
'{"username": "admin"}')
'{}',
'{"type": "password", "username": "admin", '
'"password": "test"}')
mock_request.assert_called_with(
'POST',
'/v1/efc6a88b-9096-4bb6-8634-cda182a6e12a/restores',
'/restores',
data={
'restore':
{
'checkpoint_id': '2220f8b1-975d-4621-a872-fa9afb43cb6c',
'parameters': '{"username": "admin"}',
'parameters': '{}',
'provider_id': '586cc6ce-e286-40bd-b2b5-dd32694d9944',
'restore_target': '192.168.1.2:35357/v2.0'
'restore_target': '192.168.1.2:35357/v2.0',
'restore_auth': '{"type": "password", "username": '
'"admin", "password": "test"}'
}}, headers={})
@mock.patch('smaugclient.common.http.HTTPClient.json_request')
@mock.patch('karborclient.common.http.HTTPClient.json_request')
def test_show_restore(self, mock_request):
mock_request.return_value = mock_request_return
cs.restores.get('1')
mock_request.assert_called_with(
'GET',
'/v1/efc6a88b-9096-4bb6-8634-cda182a6e12a/restores/1',
'/restores/1',
headers={})
@mock.patch('smaugclient.common.http.HTTPClient.json_request')
@mock.patch('karborclient.common.http.HTTPClient.json_request')
def test_show_restore_with_headers(self, mock_request):
mock_request.return_value = mock_request_return
cs.restores.get('1', session_id='fake_session_id')
mock_request.assert_called_with(
'GET',
'/v1/efc6a88b-9096-4bb6-8634-cda182a6e12a/restores/1',
'/restores/1',
headers={'X-Configuration-Session': 'fake_session_id'})

View File

@@ -12,8 +12,8 @@
import mock
from smaugclient.tests.unit import base
from smaugclient.tests.unit.v1 import fakes
from karborclient.tests.unit import base
from karborclient.tests.unit.v1 import fakes
cs = fakes.FakeClient()
mock_request_return = ({}, {'scheduled_operation': {'name': 'fake_name'}})
@@ -21,33 +21,31 @@ mock_request_return = ({}, {'scheduled_operation': {'name': 'fake_name'}})
class ScheduledOperationsTest(base.TestCaseShell):
@mock.patch('smaugclient.common.http.HTTPClient.json_request')
@mock.patch('karborclient.common.http.HTTPClient.json_request')
def test_list_scheduled_operations_with_marker_limit(self, mock_request):
mock_request.return_value = mock_request_return
cs.scheduled_operations.list(marker=1234, limit=2)
mock_request.assert_called_with(
'GET',
'/v1/{project_id}/scheduled_operations?limit=2&marker=1234'.format(
project_id=fakes.PROJECT_ID), headers={})
'/scheduled_operations?limit=2&marker=1234', headers={})
@mock.patch('smaugclient.common.http.HTTPClient.json_request')
@mock.patch('karborclient.common.http.HTTPClient.json_request')
def test_list__scheduled_operations_with_sort_key_dir(self, mock_request):
mock_request.return_value = mock_request_return
cs.scheduled_operations.list(sort_key='id', sort_dir='asc')
mock_request.assert_called_with(
'GET',
'/v1/{project_id}/scheduled_operations?'
'sort_dir=asc&sort_key=id'.format(
project_id=fakes.PROJECT_ID), headers={})
'/scheduled_operations?'
'sort_dir=asc&sort_key=id', headers={})
@mock.patch('smaugclient.common.http.HTTPClient.json_request')
@mock.patch('karborclient.common.http.HTTPClient.json_request')
def test_list_scheduled_operations_with_invalid_sort_key(self,
mock_request):
self.assertRaises(ValueError,
cs.scheduled_operations.list, sort_key='invalid',
sort_dir='asc')
@mock.patch('smaugclient.common.http.HTTPClient.json_request')
@mock.patch('karborclient.common.http.HTTPClient.json_request')
def test_create_scheduled_operation(self, mock_request):
mock_request.return_value = mock_request_return
cs.scheduled_operations.create(
@@ -56,7 +54,7 @@ class ScheduledOperationsTest(base.TestCaseShell):
'operation_definition')
mock_request.assert_called_with(
'POST',
'/v1/efc6a88b-9096-4bb6-8634-cda182a6e12a/scheduled_operations',
'/scheduled_operations',
data={
'scheduled_operation': {
'name': 'name',
@@ -65,29 +63,29 @@ class ScheduledOperationsTest(base.TestCaseShell):
'operation_definition': 'operation_definition'}},
headers={})
@mock.patch('smaugclient.common.http.HTTPClient.raw_request')
@mock.patch('karborclient.common.http.HTTPClient.raw_request')
def test_delete_scheduled_operation(self, mock_request):
mock_request.return_value = mock_request_return
cs.scheduled_operations.delete('1')
mock_request.assert_called_with(
'DELETE',
'/v1/efc6a88b-9096-4bb6-8634-cda182a6e12a/scheduled_operations/1',
'/scheduled_operations/1',
headers={})
@mock.patch('smaugclient.common.http.HTTPClient.json_request')
@mock.patch('karborclient.common.http.HTTPClient.json_request')
def test_show_scheduled_operation(self, mock_request):
mock_request.return_value = mock_request_return
cs.scheduled_operations.get('1')
mock_request.assert_called_with(
'GET',
'/v1/efc6a88b-9096-4bb6-8634-cda182a6e12a/scheduled_operations/1',
'/scheduled_operations/1',
headers={})
@mock.patch('smaugclient.common.http.HTTPClient.json_request')
@mock.patch('karborclient.common.http.HTTPClient.json_request')
def test_show_scheduled_operation_with_headers(self, mock_request):
mock_request.return_value = mock_request_return
cs.scheduled_operations.get('1', session_id='fake_session_id')
mock_request.assert_called_with(
'GET',
'/v1/efc6a88b-9096-4bb6-8634-cda182a6e12a/scheduled_operations/1',
'/scheduled_operations/1',
headers={'X-Configuration-Session': 'fake_session_id'})

View File

@@ -12,8 +12,8 @@
import mock
from smaugclient.tests.unit import base
from smaugclient.tests.unit.v1 import fakes
from karborclient.tests.unit import base
from karborclient.tests.unit.v1 import fakes
cs = fakes.FakeClient()
mock_request_return = ({}, {'trigger_info': {'name': 'fake_name'}})
@@ -21,66 +21,79 @@ mock_request_return = ({}, {'trigger_info': {'name': 'fake_name'}})
class TriggersTest(base.TestCaseShell):
@mock.patch('smaugclient.common.http.HTTPClient.json_request')
@mock.patch('karborclient.common.http.HTTPClient.json_request')
def test_list_triggers_with_marker_limit(self, mock_request):
mock_request.return_value = mock_request_return
cs.triggers.list(marker=1234, limit=2)
mock_request.assert_called_with(
'GET',
'/v1/{project_id}/triggers?limit=2&marker=1234'.format(
project_id=fakes.PROJECT_ID), headers={})
'/triggers?limit=2&marker=1234', headers={})
@mock.patch('smaugclient.common.http.HTTPClient.json_request')
@mock.patch('karborclient.common.http.HTTPClient.json_request')
def test_list_triggers_with_sort_key_dir(self, mock_request):
mock_request.return_value = mock_request_return
cs.triggers.list(sort_key='id', sort_dir='asc')
mock_request.assert_called_with(
'GET',
'/v1/{project_id}/triggers?'
'sort_dir=asc&sort_key=id'.format(
project_id=fakes.PROJECT_ID), headers={})
'/triggers?'
'sort_dir=asc&sort_key=id', headers={})
@mock.patch('smaugclient.common.http.HTTPClient.json_request')
@mock.patch('karborclient.common.http.HTTPClient.json_request')
def test_list_triggers_with_invalid_sort_key(self, mock_request):
self.assertRaises(ValueError,
cs.triggers.list, sort_key='invalid', sort_dir='asc')
@mock.patch('smaugclient.common.http.HTTPClient.json_request')
@mock.patch('karborclient.common.http.HTTPClient.json_request')
def test_create_trigger(self, mock_request):
mock_request.return_value = mock_request_return
cs.triggers.create('name', 'time', 'properties')
mock_request.assert_called_with(
'POST',
'/v1/efc6a88b-9096-4bb6-8634-cda182a6e12a/triggers',
'/triggers',
data={
'trigger_info': {'name': 'name',
'type': 'time',
'properties': 'properties'}},
headers={})
@mock.patch('smaugclient.common.http.HTTPClient.raw_request')
@mock.patch('karborclient.common.http.HTTPClient.raw_request')
def test_delete_trigger(self, mock_request):
mock_request.return_value = mock_request_return
cs.triggers.delete('1')
mock_request.assert_called_with(
'DELETE',
'/v1/efc6a88b-9096-4bb6-8634-cda182a6e12a/triggers/1',
'/triggers/1',
headers={})
@mock.patch('smaugclient.common.http.HTTPClient.json_request')
def test_show_plan(self, mock_request):
@mock.patch('karborclient.common.http.HTTPClient.json_request')
def test_show_trigger(self, mock_request):
mock_request.return_value = mock_request_return
cs.triggers.get('1')
mock_request.assert_called_with(
'GET',
'/v1/efc6a88b-9096-4bb6-8634-cda182a6e12a/triggers/1',
'/triggers/1',
headers={})
@mock.patch('smaugclient.common.http.HTTPClient.json_request')
@mock.patch('karborclient.common.http.HTTPClient.json_request')
def test_show_trigger_with_headers(self, mock_request):
mock_request.return_value = mock_request_return
cs.triggers.get('1', session_id='fake_session_id')
mock_request.assert_called_with(
'GET',
'/v1/efc6a88b-9096-4bb6-8634-cda182a6e12a/triggers/1',
'/triggers/1',
headers={'X-Configuration-Session': 'fake_session_id'})
@mock.patch('karborclient.common.http.HTTPClient.json_request')
def test_update_trigger(self, mock_request):
mock_request.return_value = mock_request_return
trigger_id = '123'
data = {"name": "My Trigger",
"properties": {"pattern": "0 10 * * *", "format": "crontab"}}
body = {"trigger_info": data}
cs.triggers.update(trigger_id, data)
mock_request.assert_called_with(
'PUT',
'/triggers/123',
data=body,
headers={}
)

View File

@@ -12,7 +12,7 @@
from six.moves.urllib import parse
from smaugclient.common import base
from karborclient.common import base
class Checkpoint(base.Resource):
@@ -28,15 +28,13 @@ class CheckpointManager(base.ManagerWithFind):
def create(self, provider_id, plan_id):
body = {'checkpoint': {'plan_id': plan_id}}
url = "/v1/{project_id}/providers/{provider_id}/" \
"checkpoints" .format(project_id=self.project_id,
provider_id=provider_id)
return self._create(url, body, 'checkpoint', return_raw=True)
url = "/providers/{provider_id}/" \
"checkpoints" .format(provider_id=provider_id)
return self._create(url, body, 'checkpoint')
def delete(self, provider_id, checkpoint_id):
path = '/v1/{project_id}/providers/{provider_id}/checkpoints/' \
'{checkpoint_id}'.format(project_id=self.project_id,
provider_id=provider_id,
path = '/providers/{provider_id}/checkpoints/' \
'{checkpoint_id}'.format(provider_id=provider_id,
checkpoint_id=checkpoint_id)
return self._delete(path)
@@ -45,9 +43,8 @@ class CheckpointManager(base.ManagerWithFind):
headers = {'X-Configuration-Session': session_id}
else:
headers = {}
url = '/v1/{project_id}/providers/{provider_id}/checkpoints/' \
'{checkpoint_id}'.format(project_id=self.project_id,
provider_id=provider_id,
url = '/providers/{provider_id}/checkpoints/' \
'{checkpoint_id}'.format(provider_id=provider_id,
checkpoint_id=checkpoint_id)
return self._get(url, response_key="checkpoint", headers=headers)
@@ -111,8 +108,7 @@ class CheckpointManager(base.ManagerWithFind):
params = sorted(query_params.items(), key=lambda x: x[0])
query_string = "?%s" % parse.urlencode(params)
return ("/v1/%(project_id)s/providers/%(provider_id)s"
return ("/providers/%(provider_id)s"
"/checkpoints%(query_string)s" %
{"project_id": self.project_id,
"provider_id": provider_id,
{"provider_id": provider_id,
"query_string": query_string})

View File

@@ -12,18 +12,18 @@
# License for the specific language governing permissions and limitations
# under the License.
from smaugclient.common import http
from smaugclient.v1 import checkpoints
from smaugclient.v1 import plans
from smaugclient.v1 import protectables
from smaugclient.v1 import providers
from smaugclient.v1 import restores
from smaugclient.v1 import scheduled_operations
from smaugclient.v1 import triggers
from karborclient.common import http
from karborclient.v1 import checkpoints
from karborclient.v1 import plans
from karborclient.v1 import protectables
from karborclient.v1 import providers
from karborclient.v1 import restores
from karborclient.v1 import scheduled_operations
from karborclient.v1 import triggers
class Client(object):
"""Client for the Smaug v1 API.
"""Client for the karbor v1 API.
:param string endpoint: A user-supplied endpoint URL for the service.
:param string token: Token for authentication.
@@ -32,7 +32,7 @@ class Client(object):
"""
def __init__(self, *args, **kwargs):
"""Initialize a new client for the Smaug v1 API."""
"""Initialize a new client for the karbor v1 API."""
self.http_client = http._construct_http_client(*args, **kwargs)
self.plans = plans.PlanManager(self.http_client)
self.restores = restores.RestoreManager(self.http_client)

View File

@@ -10,7 +10,7 @@
# License for the specific language governing permissions and limitations
# under the License.
from smaugclient.common import base
from karborclient.common import base
class Plan(base.Resource):
@@ -24,27 +24,27 @@ class Plan(base.Resource):
class PlanManager(base.ManagerWithFind):
resource_class = Plan
def create(self, name, provider_id, resources):
def create(self, name, provider_id, resources, parameters,
description=None):
body = {'plan': {'name': name,
'description': description,
'provider_id': provider_id,
'resources': resources,
'parameters': parameters
}}
url = "/v1/{project_id}/plans" .format(
project_id=self.project_id)
return self._create(url, body, 'plan', return_raw=True)
url = "/plans"
return self._create(url, body, 'plan')
def update(self, plan_id, data):
body = {"plan": data}
return self._update('/v1/{project_id}/plans/{plan_id}'
.format(project_id=self.project_id,
plan_id=plan_id),
return self._update('/plans/{plan_id}'
.format(plan_id=plan_id),
body, "plan")
def delete(self, plan_id):
path = '/v1/{project_id}/plans/{plan_id}'.format(
project_id=self.project_id,
path = '/plans/{plan_id}'.format(
plan_id=plan_id)
return self._delete(path)
@@ -53,8 +53,7 @@ class PlanManager(base.ManagerWithFind):
headers = {'X-Configuration-Session': session_id}
else:
headers = {}
url = "/v1/{project_id}/plans/{plan_id}".format(
project_id=self.project_id,
url = "/plans/{plan_id}".format(
plan_id=plan_id)
return self._get(url, response_key="plan", headers=headers)

View File

@@ -12,7 +12,7 @@
from six.moves.urllib import parse
from smaugclient.common import base
from karborclient.common import base
class Protectable(base.Resource):
@@ -23,6 +23,14 @@ class Protectable(base.Resource):
return self.manager.data(self, **kwargs)
class Instances(base.Resource):
def __repr__(self):
return "<Instances %s>" % self._info
def data(self, **kwargs):
return self.manager.data(self, **kwargs)
class ProtectableManager(base.ManagerWithFind):
resource_class = Protectable
@@ -31,14 +39,12 @@ class ProtectableManager(base.ManagerWithFind):
headers = {'X-Configuration-Session': session_id}
else:
headers = {}
url = "/v1/{project_id}/protectables/{protectable_type}".format(
project_id=self.project_id,
url = "/protectables/{protectable_type}".format(
protectable_type=protectable_type)
return self._get(url, response_key="protectable_type", headers=headers)
def list(self):
url = "/v1/{project_id}/protectables".format(
project_id=self.project_id)
url = "/protectables"
protectables = self._list(url, 'protectable_type', return_raw=True)
protectables_list = []
@@ -61,7 +67,7 @@ class ProtectableManager(base.ManagerWithFind):
:param sort_dir: Sort direction, should be 'desc' or 'asc'; deprecated
in kilo
:param sort: Sort information
:rtype: list of :class:`Protectable`
:rtype: list of :class:`Instances`
"""
url = self._build_instances_list_url(
@@ -69,7 +75,17 @@ class ProtectableManager(base.ManagerWithFind):
search_opts=search_opts, marker=marker,
limit=limit, sort_key=sort_key,
sort_dir=sort_dir, sort=sort)
return self._list(url, 'instances')
return self._list(url, response_key='instances', obj_class=Instances)
def get_instance(self, type, id, session_id=None):
if session_id:
headers = {'X-Configuration-Session': session_id}
else:
headers = {}
url = "/protectables/{protectable_type}/" \
"instances/{protectable_id}".format(protectable_type=type,
protectable_id=id)
return self._get(url, response_key="instance", headers=headers)
def _build_instances_list_url(self, protectable_type,
search_opts=None, marker=None, limit=None,
@@ -108,8 +124,7 @@ class ProtectableManager(base.ManagerWithFind):
params = sorted(query_params.items(), key=lambda x: x[0])
query_string = "?%s" % parse.urlencode(params)
return ("/v1/%(project_id)s/protectables/%(protectable_type)s"
return ("/protectables/%(protectable_type)s"
"/instances%(query_string)s" %
{"project_id": self.project_id,
"protectable_type": protectable_type,
{"protectable_type": protectable_type,
"query_string": query_string})

View File

@@ -10,7 +10,7 @@
# License for the specific language governing permissions and limitations
# under the License.
from smaugclient.common import base
from karborclient.common import base
class Provider(base.Resource):
@@ -29,8 +29,7 @@ class ProviderManager(base.ManagerWithFind):
headers = {'X-Configuration-Session': session_id}
else:
headers = {}
url = "/v1/{project_id}/providers/{provider_id}".format(
project_id=self.project_id,
url = "/providers/{provider_id}".format(
provider_id=provider_id)
return self._get(url, response_key="provider", headers=headers)

View File

@@ -10,7 +10,7 @@
# License for the specific language governing permissions and limitations
# under the License.
from smaugclient.common import base
from karborclient.common import base
class Restore(base.Resource):
@@ -24,20 +24,22 @@ class Restore(base.Resource):
class RestoreManager(base.ManagerWithFind):
resource_class = Restore
def create(self, provider_id, checkpoint_id, restore_target, parameters):
body = {'restore': {'provider_id': provider_id,
'checkpoint_id': checkpoint_id,
'restore_target': restore_target,
'parameters': parameters,
}
}
url = "/v1/{project_id}/restores" .format(
project_id=self.project_id)
return self._create(url, body, 'restore', return_raw=True)
def create(self, provider_id, checkpoint_id, restore_target, parameters,
restore_auth):
body = {
'restore': {
'provider_id': provider_id,
'checkpoint_id': checkpoint_id,
'restore_target': restore_target,
'restore_auth': restore_auth,
'parameters': parameters,
}
}
url = "/restores"
return self._create(url, body, 'restore')
def delete(self, restore_id):
path = '/v1/{project_id}/restores/{restore_id}'.format(
project_id=self.project_id,
path = '/restores/{restore_id}'.format(
restore_id=restore_id)
return self._delete(path)
@@ -46,8 +48,7 @@ class RestoreManager(base.ManagerWithFind):
headers = {'X-Configuration-Session': session_id}
else:
headers = {}
url = "/v1/{project_id}/restores/{restore_id}".format(
project_id=self.project_id,
url = "/restores/{restore_id}".format(
restore_id=restore_id)
return self._get(url, response_key="restore", headers=headers)

View File

@@ -10,7 +10,7 @@
# License for the specific language governing permissions and limitations
# under the License.
from smaugclient.common import base
from karborclient.common import base
class ScheduledOperation(base.Resource):
@@ -31,14 +31,12 @@ class ScheduledOperationManager(base.ManagerWithFind):
'operation_definition':
operation_definition,
}}
url = "/v1/{project_id}/scheduled_operations" .format(
project_id=self.project_id)
return self._create(url, body, 'scheduled_operation', return_raw=True)
url = "/scheduled_operations"
return self._create(url, body, 'scheduled_operation')
def delete(self, scheduled_operation_id):
path = '/v1/{project_id}/scheduled_operations/{scheduled_operation_id}'.\
format(project_id=self.project_id,
scheduled_operation_id=scheduled_operation_id)
path = '/scheduled_operations/{scheduled_operation_id}'.\
format(scheduled_operation_id=scheduled_operation_id)
return self._delete(path)
def get(self, scheduled_operation_id, session_id=None):
@@ -46,9 +44,8 @@ class ScheduledOperationManager(base.ManagerWithFind):
headers = {'X-Configuration-Session': session_id}
else:
headers = {}
url = "/v1/{project_id}/scheduled_operations/{scheduled_operation_id}".\
format(project_id=self.project_id,
scheduled_operation_id=scheduled_operation_id)
url = "/scheduled_operations/{scheduled_operation_id}".\
format(scheduled_operation_id=scheduled_operation_id)
return self._get(url, response_key="scheduled_operation",
headers=headers)

View File

@@ -11,13 +11,14 @@
# under the License.
import argparse
import os
from oslo_serialization import jsonutils
from oslo_utils import uuidutils
from smaugclient.common import base
from smaugclient.common import utils
from smaugclient.openstack.common.apiclient import exceptions
from karborclient.common.apiclient import exceptions
from karborclient.common import base
from karborclient.common import utils
@utils.arg('--all-tenants',
@@ -93,7 +94,7 @@ def do_plan_list(cs, args):
limit=args.limit, sort_key=args.sort_key,
sort_dir=args.sort_dir, sort=args.sort)
key_list = ['Id', 'Name', 'Provider id', 'Status']
key_list = ['Id', 'Name', 'Description', 'Provider id', 'Status']
if args.sort_key or args.sort_dir or args.sort:
sortby_index = None
@@ -110,14 +111,34 @@ def do_plan_list(cs, args):
metavar='<provider_id>',
help='ID of provider.')
@utils.arg('resources',
metavar='<id=type,id=type>',
metavar='<id=type=name,id=type=name>',
help='Resource in list must be a dict when creating'
' a plan.The keys of resource are id and type.')
@utils.arg('--parameters-json',
type=str,
dest='parameters_json',
metavar='<parameters>',
default=None,
help='Plan parameters in json format.')
@utils.arg('--parameters',
action='append',
metavar='resource_type=<type>[,resource_id=<id>,key=val,...]',
default=[],
help='Plan parameters, may be specified multiple times. '
'resource_type: type of resource to apply parameters. '
'resource_id: limit the parameters to a specific resource. '
'Other keys and values: according to provider\'s protect schema.'
)
@utils.arg('--description',
metavar='<description>',
help='The description of a plan.')
def do_plan_create(cs, args):
"""Create a plan."""
plan_resources = _extract_resources(args)
plan = cs.plans.create(args.name, args.provider_id, plan_resources)
utils.print_dict(plan)
plan_parameters = _extract_parameters(args)
plan = cs.plans.create(args.name, args.provider_id, plan_resources,
plan_parameters, description=args.description)
utils.print_dict(plan.to_dict())
@utils.arg('plan',
@@ -153,7 +174,7 @@ def do_plan_delete(cs, args):
help="Id of plan to update.")
@utils.arg("--name", metavar="<name>",
help="A name to which the plan will be renamed.")
@utils.arg("--resources", metavar="<id=type,id=type>",
@utils.arg("--resources", metavar="<id=type=name,id=type=name>",
help="Resources to which the plan will be updated.")
@utils.arg("--status", metavar="<suspended|started>",
help="status to which the plan will be updated.")
@@ -181,14 +202,16 @@ def _extract_resources(args):
for data in args.resources.split(','):
resource = {}
if '=' in data:
(resource_id, resource_type) = data.split('=', 1)
(resource_id, resource_type, resource_name) = data.split('=', 2)
else:
raise exceptions.CommandError(
"Unable to parse parameter resources.")
resource["id"] = resource_id
resource["type"] = resource_type
resource["name"] = resource_name
resources.append(resource)
return resources
@@ -201,12 +224,29 @@ def _extract_resources(args):
@utils.arg('restore_target',
metavar='<restore_target>',
help='Restore target.')
@utils.arg('--parameters',
@utils.arg('restore_username',
metavar='<restore_username>',
default="",
help='Username to restore target.')
@utils.arg('restore_password',
metavar='<restore_password>',
default="",
help='Password to restore target.')
@utils.arg('--parameters-json',
type=str,
nargs='*',
metavar='<key=value>',
dest='parameters_json',
metavar='<parameters>',
default=None,
help='The parameters of a restore target.')
help='Restore parameters in json format.')
@utils.arg('--parameters',
action='append',
metavar='resource_type=<type>[,resource_id=<id>,key=val,...]',
default=[],
help='Restore parameters, may be specified multiple times. '
'resource_type: type of resource to apply parameters. '
'resource_id: limit the parameters to a specific resource. '
'Other keys and values: according to provider\'s restore schema.'
)
def do_restore_create(cs, args):
"""Create a restore."""
if not uuidutils.is_uuid_like(args.provider_id):
@@ -217,27 +257,56 @@ def do_restore_create(cs, args):
raise exceptions.CommandError(
"Invalid checkpoint id provided.")
if args.parameters is not None:
restore_parameters = _extract_parameters(args)
else:
raise exceptions.CommandError(
"checkpoint_id must be provided.")
restore_parameters = _extract_parameters(args)
restore_auth = {
'type': 'password',
'username': args.restore_username,
'password': args.restore_password,
}
restore = cs.restores.create(args.provider_id, args.checkpoint_id,
args.restore_target, restore_parameters)
utils.print_dict(restore)
args.restore_target, restore_parameters,
restore_auth)
utils.print_dict(restore.to_dict())
def _extract_parameters(args):
parameters = {}
for data in args.parameters:
# unset doesn't require a val, so we have the if/else
if '=' in data:
(key, value) = data.split('=', 1)
else:
key = data
value = None
if all((args.parameters, args.parameters_json)):
raise exceptions.CommandError(
"Must provide parameters or parameters-json, not both")
if not any((args.parameters, args.parameters_json)):
return {}
if args.parameters_json:
return jsonutils.loads(args.parameters_json)
parameters = {}
for resource_params in args.parameters:
resource_type = None
resource_id = None
parameter = {}
for param_kv in resource_params.split(','):
try:
key, value = param_kv.split('=')
except Exception:
raise exceptions.CommandError(
'parameters must be in the form: key1=val1,key2=val2,...'
)
if key == "resource_type":
resource_type = value
if key == "resource_id":
if not uuidutils.is_uuid_like(value):
raise exceptions.CommandError('resource_id must be a uuid')
resource_id = value
parameters[key] = value
if resource_type is None:
raise exceptions.CommandError(
'Must specify resource_type for parameters'
)
if resource_id is None:
resource_key = resource_type
else:
resource_key = "%s#%s" % (resource_type, resource_id)
parameters[resource_key] = parameter
parameters[key] = value
return parameters
@@ -348,6 +417,19 @@ def do_protectable_show(cs, args):
utils.print_dict(protectable.to_dict())
@utils.arg('protectable_id',
metavar='<protectable_id>',
help='Protectable instance id.')
@utils.arg('protectable_type',
metavar='<protectable_type>',
help='Protectable type.')
def do_protectable_show_instance(cs, args):
"""Shows instance details."""
instance = cs.protectables.get_instance(args.protectable_type,
args.protectable_id)
utils.print_dict(instance.to_dict())
@utils.arg('protectable_type',
metavar='<protectable_type>',
help='Type of protectable.')
@@ -486,7 +568,7 @@ def do_provider_list(cs, args):
def do_checkpoint_create(cs, args):
"""Create a checkpoint."""
checkpoint = cs.checkpoints.create(args.provider_id, args.plan_id)
utils.print_dict(checkpoint)
utils.print_dict(checkpoint.to_dict())
@utils.arg('provider_id',
@@ -579,7 +661,7 @@ def do_checkpoint_delete(cs, args):
try:
checkpoint = cs.checkpoints.get(args.provider_id,
checkpoint_id)
cs.checkpoints.delete(checkpoint.provider_id, checkpoint.id)
cs.checkpoints.delete(args.provider_id, checkpoint.id)
except exceptions.NotFound:
failure_count += 1
print("Failed to delete '{0}'; checkpoint not found".
@@ -684,13 +766,13 @@ def do_trigger_list(cs, args):
metavar='<type>',
help='Type of trigger.')
@utils.arg('properties',
metavar='<key=value;key=value>',
metavar='<key=value:key=value>',
help='Properties of trigger.')
def do_trigger_create(cs, args):
"""Create a trigger."""
trigger_properties = _extract_properties(args)
trigger = cs.triggers.create(args.name, args.type, trigger_properties)
utils.print_dict(trigger)
utils.print_dict(trigger.to_dict())
def _extract_properties(args):
@@ -706,6 +788,22 @@ def _extract_properties(args):
return properties
@utils.arg("trigger_id", metavar="<TRIGGER ID>",
help="Id of trigger to update.")
@utils.arg("--name", metavar="<name>",
help="A new name to which the trigger will be renamed.")
@utils.arg("--properties", metavar="<key=value:key=value>",
help="Properties of trigger which will be updated.")
def do_trigger_update(cs, args):
"""Update a trigger."""
trigger_info = {}
trigger_properties = _extract_properties(args)
trigger_info['name'] = args.name
trigger_info['properties'] = trigger_properties
trigger = cs.triggers.update(args.trigger_id, trigger_info)
utils.print_dict(trigger.to_dict())
@utils.arg('trigger',
metavar='<trigger>',
help='ID of trigger.')
@@ -800,7 +898,7 @@ def do_scheduledoperation_list(cs, args):
'all_tenants': all_tenants,
'project_id': args.tenant,
'name': args.name,
'operation_type': args.type,
'operation_type': args.operation_type,
'trigger_id': args.trigger_id,
}
@@ -834,16 +932,16 @@ def do_scheduledoperation_list(cs, args):
metavar='<trigger_id>',
help='Trigger id of scheduled operation.')
@utils.arg('operation_definition',
metavar='<key=value;key=value>',
metavar='<key=value:key=value>',
help='Operation definition of scheduled operation.')
def do_scheduledoperation_create(cs, args):
"""Create a scheduled operation."""
operation_definition = _extract_operation_definition(args)
scheduledoperation = cs.scheduledoperations.create(args.name,
args.operation_type,
args.trigger_id,
operation_definition)
utils.print_dict(scheduledoperation)
scheduledoperation = cs.scheduled_operations.create(args.name,
args.operation_type,
args.trigger_id,
operation_definition)
utils.print_dict(scheduledoperation.to_dict())
def _extract_operation_definition(args):
@@ -864,7 +962,7 @@ def _extract_operation_definition(args):
help='ID of scheduled operation.')
def do_scheduledoperation_show(cs, args):
"""Shows scheduledoperation details."""
scheduledoperation = cs.scheduledoperations.get(args.scheduledoperation)
scheduledoperation = cs.scheduled_operations.get(args.scheduledoperation)
utils.print_dict(scheduledoperation.to_dict())
@@ -877,9 +975,9 @@ def do_scheduledoperation_delete(cs, args):
failure_count = 0
for scheduledoperation_id in args.scheduledoperation:
try:
scheduledoperation = utils.find_resource(cs.scheduledoperations,
scheduledoperation = utils.find_resource(cs.scheduled_operations,
scheduledoperation_id)
cs.scheduledoperations.delete(scheduledoperation.id)
cs.scheduled_operations.delete(scheduledoperation.id)
except exceptions.NotFound:
failure_count += 1
print("Failed to delete '{0}'; scheduledoperation not found".

View File

@@ -10,7 +10,7 @@
# License for the specific language governing permissions and limitations
# under the License.
from smaugclient.common import base
from karborclient.common import base
class Trigger(base.Resource):
@@ -29,13 +29,11 @@ class TriggerManager(base.ManagerWithFind):
'type': type,
'properties': properties,
}}
url = "/v1/{project_id}/triggers" .format(
project_id=self.project_id)
return self._create(url, body, 'trigger_info', return_raw=True)
url = "/triggers"
return self._create(url, body, 'trigger_info')
def delete(self, trigger_id):
path = '/v1/{project_id}/triggers/{trigger_id}'.format(
project_id=self.project_id,
path = '/triggers/{trigger_id}'.format(
trigger_id=trigger_id)
return self._delete(path)
@@ -44,11 +42,18 @@ class TriggerManager(base.ManagerWithFind):
headers = {'X-Configuration-Session': session_id}
else:
headers = {}
url = "/v1/{project_id}/triggers/{trigger_id}".format(
project_id=self.project_id,
url = "/triggers/{trigger_id}".format(
trigger_id=trigger_id)
return self._get(url, response_key="trigger_info", headers=headers)
def update(self, trigger_id, data):
body = {"trigger_info": data}
return self._update('/triggers/{trigger_id}'
.format(trigger_id=trigger_id),
body, "trigger_info")
def list(self, detailed=False, search_opts=None, marker=None, limit=None,
sort_key=None, sort_dir=None, sort=None):
"""Lists all triggers."""

View File

@@ -13,4 +13,4 @@
from pbr import version
version_info = version.VersionInfo('python-smaugclient')
version_info = version.VersionInfo('python-karborclient')

View File

@@ -1,8 +0,0 @@
[DEFAULT]
# The list of modules to copy from openstack-common
module=apiclient.exceptions
module=apiclient
# The base module to hold the copy of openstack.common
base=smaugclient

View File

@@ -2,12 +2,12 @@
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
pbr>=1.6 # Apache-2.0
PrettyTable<0.8,>=0.7 # BSD
python-keystoneclient!=1.8.0,!=2.1.0,>=1.6.0 # Apache-2.0
requests!=2.9.0,>=2.8.1 # Apache-2.0
PrettyTable<0.8,>=0.7.1 # BSD
python-keystoneclient!=2.1.0,>=2.0.0 # Apache-2.0
requests>=2.10.0 # Apache-2.0
simplejson>=2.2.0 # MIT
Babel>=1.3 # BSD
Babel>=2.3.4 # BSD
six>=1.9.0 # MIT
oslo.utils>=3.5.0 # Apache-2.0
oslo.log>=1.14.0 # Apache-2.0
oslo.utils>=3.16.0 # Apache-2.0
oslo.log>=3.11.0 # Apache-2.0
oslo.i18n>=2.1.0 # Apache-2.0

View File

@@ -1,11 +1,11 @@
[metadata]
name = python-smaugclient
summary = Python client library for Smaug API
name = python-karborclient
summary = Python client library for Karbor API
description-file =
README.rst
author = OpenStack
author-email = openstack-dev@lists.openstack.org
home-page = http://www.openstack.org/
home-page = http://docs.openstack.org/developer/karbor/
classifier =
Environment :: OpenStack
Intended Audience :: Information Technology
@@ -25,11 +25,11 @@ setup-hooks =
[files]
packages =
smaugclient
karborclient
[entry_points]
console_scripts =
smaug = smaugclient.shell:main
karbor = karborclient.shell:main
[build_sphinx]
source-dir = doc/source

View File

@@ -1,17 +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 six
six.add_move(six.MovedModule('mox', 'mox', 'mox3.mox'))

View File

@@ -5,10 +5,9 @@
hacking<0.11,>=0.10.2 # Apache-2.0
coverage>=3.6 # Apache-2.0
discover # BSD
python-subunit>=0.0.18 # Apache-2.0/BSD
sphinx!=1.2.0,!=1.3b1,<1.3,>=1.1.2 # BSD
oslosphinx!=3.4.0,>=2.5.0 # Apache-2.0
sphinx!=1.3b1,<1.4,>=1.2.1 # BSD
oslosphinx>=4.7.0 # Apache-2.0
oslotest>=1.10.0 # Apache-2.0
testrepository>=0.0.18 # Apache-2.0/BSD
testscenarios>=0.4 # Apache-2.0/BSD

View File

@@ -20,7 +20,7 @@ commands = {posargs}
[testenv:functional]
setenv =
OS_TEST_PATH = ./smaugclient/tests/functional
OS_TEST_PATH = ./karborclient/tests/functional
passenv = OS_*
[testenv:cover]
commands = python setup.py test --coverage --testr-args='{posargs}'
@@ -37,4 +37,4 @@ commands = oslo_debug_helper {posargs}
show-source = True
ignore = E123,E125
builtins = _
exclude=.venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,tools
exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,tools