Merge "Remove cyclical dependency"
This commit is contained in:
@@ -57,62 +57,13 @@ class HTTPAuthError(HTTPError):
|
||||
pass
|
||||
|
||||
|
||||
class Client(object):
|
||||
class _HTTPClient(object):
|
||||
|
||||
def __init__(self, session=None, endpoint=None, project_id=None,
|
||||
def __init__(self, session, endpoint=None, project_id=None,
|
||||
verify=True, service_type=_DEFAULT_SERVICE_TYPE,
|
||||
service_name=None, interface=_DEFAULT_SERVICE_INTERFACE,
|
||||
region_name=None):
|
||||
"""
|
||||
Barbican client object used to interact with barbican service.
|
||||
|
||||
:param session: An instance of a keystoneclient Session that
|
||||
can be either authenticated, or not authenticated. When using
|
||||
a non-authenticated Session, you must provide some additional
|
||||
parameters. When no session is provided it will default to a
|
||||
non-authenticated Session.
|
||||
:type session: keystoneclient.session.Session
|
||||
:param str endpoint: Barbican endpoint url. Required when a session is
|
||||
not given, or when using a non-authenticated session.
|
||||
When using an authenticated session, the client will attempt
|
||||
to get an endpoint from the session.
|
||||
:param str project_id: The project ID used for context in Barbican.
|
||||
Required when a session is not given, or when using a
|
||||
non-authenticated session.
|
||||
When using an authenticated session, the project ID will be
|
||||
provided by the authentication mechanism.
|
||||
:param bool verify: When a session is not given, the client will create
|
||||
a non-authenticated session. This parameter is passed to the
|
||||
session that is created. If set to False, it allows
|
||||
barbicanclient to perform "insecure" TLS (https) requests.
|
||||
The server's certificate will not be verified against any
|
||||
certificate authorities.
|
||||
WARNING: This option should be used with extreme caution.
|
||||
:param str service_type: Used as an endpoint filter when using an
|
||||
authenticated keystone session. Defaults to 'key-manager'.
|
||||
:param str service_name: Used as an endpoint filter when using an
|
||||
authenticated keystone session.
|
||||
:param str interface: Used as an endpoint filter when using an
|
||||
authenticated keystone session. Defaults to 'public'.
|
||||
:param str region_name: Used as an endpoint filter when using an
|
||||
authenticated keystone session.
|
||||
"""
|
||||
LOG.debug("Creating Client object")
|
||||
|
||||
self._session = session or ks_session.Session(verify=verify)
|
||||
|
||||
if self._session.auth is None:
|
||||
self._validate_endpoint_and_project_id(endpoint, project_id)
|
||||
|
||||
if endpoint is not None:
|
||||
self._barbican_endpoint = self._get_normalized_endpoint(endpoint)
|
||||
else:
|
||||
self._barbican_endpoint = self._get_normalized_endpoint(
|
||||
self._session.get_endpoint(
|
||||
service_type=service_type, service_name=service_name,
|
||||
interface=interface, region_name=region_name
|
||||
)
|
||||
)
|
||||
self._session = session
|
||||
|
||||
if project_id is None:
|
||||
self._default_headers = dict()
|
||||
@@ -120,25 +71,17 @@ class Client(object):
|
||||
# If provided we'll include the project ID in all requests.
|
||||
self._default_headers = {'X-Project-Id': project_id}
|
||||
|
||||
self._base_url = '{0}/{1}'.format(self._barbican_endpoint,
|
||||
_DEFAULT_API_VERSION)
|
||||
if not endpoint:
|
||||
endpoint = session.get_endpoint(service_type=service_type,
|
||||
service_name=service_name,
|
||||
interface=interface,
|
||||
region_name=region_name)
|
||||
|
||||
self.secrets = secrets.SecretManager(self)
|
||||
self.orders = orders.OrderManager(self)
|
||||
self.containers = containers.ContainerManager(self)
|
||||
|
||||
def _validate_endpoint_and_project_id(self, endpoint, project_id):
|
||||
if endpoint is None:
|
||||
raise ValueError('Barbican endpoint url must be provided when not '
|
||||
'using auth in the Keystone Session.')
|
||||
if project_id is None:
|
||||
raise ValueError('Project ID must be provided when not using auth '
|
||||
'in the Keystone Session')
|
||||
|
||||
def _get_normalized_endpoint(self, endpoint):
|
||||
if endpoint.endswith('/'):
|
||||
endpoint = endpoint[:-1]
|
||||
return endpoint
|
||||
|
||||
self._barbican_endpoint = endpoint
|
||||
self._base_url = '{0}/{1}'.format(endpoint, _DEFAULT_API_VERSION)
|
||||
|
||||
def _get(self, href, params=None):
|
||||
headers = {'Accept': 'application/json'}
|
||||
@@ -216,6 +159,63 @@ class Client(object):
|
||||
return message
|
||||
|
||||
|
||||
class Client(object):
|
||||
|
||||
def __init__(self, session=None, *args, **kwargs):
|
||||
"""
|
||||
Barbican client object used to interact with barbican service.
|
||||
|
||||
:param session: An instance of keystoneclient.session.Session that
|
||||
can be either authenticated, or not authenticated. When using
|
||||
a non-authenticated Session, you must provide some additional
|
||||
parameters. When no session is provided it will default to a
|
||||
non-authenticated Session.
|
||||
:param endpoint: Barbican endpoint url. Required when a session is not
|
||||
given, or when using a non-authentciated session.
|
||||
When using an authenticated session, the client will attempt
|
||||
to get an endpoint from the session.
|
||||
:param project_id: The project ID used for context in Barbican.
|
||||
Required when a session is not given, or when using a
|
||||
non-authenticated session.
|
||||
When using an authenticated session, the project ID will be
|
||||
provided by the authentication mechanism.
|
||||
:param verify: When a session is not given, the client will create
|
||||
a non-authenticated session. This parameter is passed to the
|
||||
session that is created. If set to False, it allows
|
||||
barbicanclient to perform "insecure" TLS (https) requests.
|
||||
The server's certificate will not be verified against any
|
||||
certificate authorities.
|
||||
WARNING: This option should be used with caution.
|
||||
:param service_type: Used as an endpoint filter when using an
|
||||
authenticated keystone session. Defaults to 'key-management'.
|
||||
:param service_name: Used as an endpoint filter when using an
|
||||
authenticated keystone session.
|
||||
:param interface: Used as an endpoint filter when using an
|
||||
authenticated keystone session. Defaults to 'public'.
|
||||
:param region_name: Used as an endpoint filter when using an
|
||||
authenticated keystone session.
|
||||
"""
|
||||
LOG.debug("Creating Client object")
|
||||
|
||||
if not session:
|
||||
session = ks_session.Session(verify=kwargs.pop('verify', True))
|
||||
|
||||
if session.auth is None:
|
||||
if kwargs.get('endpoint') is None:
|
||||
raise ValueError('Barbican endpoint url must be provided when '
|
||||
'not using auth in the Keystone Session.')
|
||||
|
||||
if kwargs.get('project_id') is None:
|
||||
raise ValueError('Project ID must be provided when not using '
|
||||
'auth in the Keystone Session')
|
||||
|
||||
httpclient = _HTTPClient(session=session, *args, **kwargs)
|
||||
|
||||
self.secrets = secrets.SecretManager(httpclient)
|
||||
self.orders = orders.OrderManager(httpclient)
|
||||
self.containers = containers.ContainerManager(httpclient)
|
||||
|
||||
|
||||
def env(*vars, **kwargs):
|
||||
"""Search for the first defined of possibly many env vars
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ from oslo_utils.timeutils import parse_isotime
|
||||
|
||||
from barbicanclient import base
|
||||
from barbicanclient import formatter
|
||||
from barbicanclient import secrets
|
||||
from barbicanclient import secrets as secret_manager
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
@@ -76,6 +76,7 @@ class Container(ContainerFormatter):
|
||||
container_ref=None, created=None, updated=None, status=None,
|
||||
secret_refs=None):
|
||||
self._api = api
|
||||
self._secret_manager = secret_manager.SecretManager(api)
|
||||
self._name = name
|
||||
self._container_ref = container_ref
|
||||
self._secret_refs = secret_refs
|
||||
@@ -109,7 +110,7 @@ class Container(ContainerFormatter):
|
||||
def _fill_secrets_from_secret_refs(self):
|
||||
if self._secret_refs:
|
||||
self._cached_secrets = dict(
|
||||
(name.lower(), self._api.secrets.get(secret_ref=secret_ref))
|
||||
(name.lower(), self._secret_manager.get(secret_ref=secret_ref))
|
||||
for name, secret_ref in six.iteritems(self._secret_refs)
|
||||
)
|
||||
|
||||
@@ -165,7 +166,7 @@ class Container(ContainerFormatter):
|
||||
|
||||
@_immutable_after_save
|
||||
def add(self, name, secret):
|
||||
if not isinstance(secret, secrets.Secret):
|
||||
if not isinstance(secret, secret_manager.Secret):
|
||||
raise ValueError("Must provide a valid Secret object")
|
||||
if name.lower() in self.secrets:
|
||||
raise KeyError("A secret with this name already exists!")
|
||||
|
||||
@@ -26,8 +26,10 @@ class TestClient(testtools.TestCase):
|
||||
self.responses = self.useFixture(fixture.Fixture())
|
||||
self.endpoint = 'http://localhost:9311'
|
||||
self.project_id = 'project_id'
|
||||
self.client = client.Client(endpoint=self.endpoint,
|
||||
project_id=self.project_id)
|
||||
sess = mock.MagicMock()
|
||||
self.httpclient = client._HTTPClient(session=sess,
|
||||
endpoint=self.endpoint,
|
||||
project_id=self.project_id)
|
||||
|
||||
|
||||
class WhenTestingClientInit(TestClient):
|
||||
@@ -38,23 +40,26 @@ class WhenTestingClientInit(TestClient):
|
||||
return sess
|
||||
|
||||
def test_can_be_used_without_a_session(self):
|
||||
c = client.Client(endpoint=self.endpoint,
|
||||
project_id=self.project_id)
|
||||
c = client._HTTPClient(session=self._get_fake_session(),
|
||||
endpoint=self.endpoint,
|
||||
project_id=self.project_id)
|
||||
self.assertIsNotNone(c._session)
|
||||
|
||||
def test_api_version_is_appended_to_endpoint(self):
|
||||
c = client.Client(endpoint=self.endpoint,
|
||||
project_id=self.project_id)
|
||||
c = client._HTTPClient(session=self._get_fake_session(),
|
||||
endpoint=self.endpoint,
|
||||
project_id=self.project_id)
|
||||
self.assertEqual(c._base_url, 'http://localhost:9311/v1')
|
||||
|
||||
def test_default_headers_are_empty(self):
|
||||
c = client.Client(session=self._get_fake_session())
|
||||
c = client._HTTPClient(self._get_fake_session(), self.endpoint)
|
||||
self.assertIsInstance(c._default_headers, dict)
|
||||
self.assertFalse(bool(c._default_headers))
|
||||
|
||||
def test_project_id_is_added_to_default_headers(self):
|
||||
c = client.Client(endpoint=self.endpoint,
|
||||
project_id=self.project_id)
|
||||
c = client._HTTPClient(session=self._get_fake_session(),
|
||||
endpoint=self.endpoint,
|
||||
project_id=self.project_id)
|
||||
self.assertIn('X-Project-Id', c._default_headers.keys())
|
||||
self.assertEqual(c._default_headers['X-Project-Id'], self.project_id)
|
||||
|
||||
@@ -67,20 +72,26 @@ class WhenTestingClientInit(TestClient):
|
||||
**{"endpoint": self.endpoint})
|
||||
|
||||
def test_client_strips_trailing_slash_from_endpoint(self):
|
||||
c = client.Client(endpoint=self.endpoint + '/',
|
||||
project_id=self.project_id)
|
||||
c = client._HTTPClient(session=self._get_fake_session(),
|
||||
endpoint=self.endpoint + '/',
|
||||
project_id=self.project_id)
|
||||
self.assertEqual(c._barbican_endpoint, self.endpoint)
|
||||
|
||||
def test_base_url_starts_with_endpoint_url(self):
|
||||
c = client.Client(endpoint=self.endpoint, project_id=self.project_id)
|
||||
c = client._HTTPClient(session=self._get_fake_session(),
|
||||
endpoint=self.endpoint,
|
||||
project_id=self.project_id)
|
||||
self.assertTrue(c._base_url.startswith(self.endpoint))
|
||||
|
||||
def test_base_url_ends_with_default_api_version(self):
|
||||
c = client.Client(endpoint=self.endpoint, project_id=self.project_id)
|
||||
c = client._HTTPClient(session=self._get_fake_session(),
|
||||
endpoint=self.endpoint,
|
||||
project_id=self.project_id)
|
||||
self.assertTrue(c._base_url.endswith(client._DEFAULT_API_VERSION))
|
||||
|
||||
def test_gets_endpoint_from_keystone_session(self):
|
||||
c = client.Client(session=self._get_fake_session())
|
||||
c = client._HTTPClient(session=self._get_fake_session(),
|
||||
endpoint=self.endpoint)
|
||||
self.assertEqual(c._barbican_endpoint, self.endpoint)
|
||||
|
||||
|
||||
@@ -106,33 +117,33 @@ class WhenTestingClientPost(TestClientWithSession):
|
||||
def setUp(self):
|
||||
super(WhenTestingClientPost, self).setUp()
|
||||
self.session = self._get_fake_session_with_status_code(201)
|
||||
self.client = client.Client(session=self.session)
|
||||
self.httpclient = client._HTTPClient(self.session, self.endpoint)
|
||||
|
||||
def test_post_normalizes_url_with_traling_slash(self):
|
||||
self.client._post(path='secrets', data={'test_data': 'test'})
|
||||
self.httpclient._post(path='secrets', data={'test_data': 'test'})
|
||||
args, kwargs = self.session.post.call_args
|
||||
url = args[0]
|
||||
self.assertTrue(url.endswith('/'))
|
||||
|
||||
def test_post_includes_content_type_header_of_application_json(self):
|
||||
self.client._post(path='secrets', data={'test_data': 'test'})
|
||||
self.httpclient._post(path='secrets', data={'test_data': 'test'})
|
||||
args, kwargs = self.session.post.call_args
|
||||
headers = kwargs.get('headers')
|
||||
self.assertIn('Content-Type', headers.keys())
|
||||
self.assertEqual(headers['Content-Type'], 'application/json')
|
||||
|
||||
def test_post_includes_default_headers(self):
|
||||
self.client._default_headers = {'Test-Default-Header': 'test'}
|
||||
self.client._post(path='secrets', data={'test_data': 'test'})
|
||||
self.httpclient._default_headers = {'Test-Default-Header': 'test'}
|
||||
self.httpclient._post(path='secrets', data={'test_data': 'test'})
|
||||
args, kwargs = self.session.post.call_args
|
||||
headers = kwargs.get('headers')
|
||||
self.assertIn('Test-Default-Header', headers.keys())
|
||||
|
||||
def test_post_checks_status_code(self):
|
||||
self.client._check_status_code = mock.MagicMock()
|
||||
self.client._post(path='secrets', data={'test_data': 'test'})
|
||||
self.httpclient._check_status_code = mock.MagicMock()
|
||||
self.httpclient._post(path='secrets', data={'test_data': 'test'})
|
||||
resp = self.session.post()
|
||||
self.client._check_status_code.assert_called_with(resp)
|
||||
self.httpclient._check_status_code.assert_called_with(resp)
|
||||
|
||||
|
||||
class WhenTestingClientGet(TestClientWithSession):
|
||||
@@ -140,65 +151,65 @@ class WhenTestingClientGet(TestClientWithSession):
|
||||
def setUp(self):
|
||||
super(WhenTestingClientGet, self).setUp()
|
||||
self.session = self._get_fake_session_with_status_code(200)
|
||||
self.client = client.Client(session=self.session)
|
||||
self.httpclient = client._HTTPClient(self.session, self.endpoint)
|
||||
self.headers = dict()
|
||||
self.href = 'http://test_href'
|
||||
|
||||
def test_get_uses_href_as_is(self):
|
||||
self.client._get(self.href)
|
||||
self.httpclient._get(self.href)
|
||||
args, kwargs = self.session.get.call_args
|
||||
url = args[0]
|
||||
self.assertEqual(url, self.href)
|
||||
|
||||
def test_get_passes_params(self):
|
||||
params = object()
|
||||
self.client._get(self.href, params=params)
|
||||
self.httpclient._get(self.href, params=params)
|
||||
args, kwargs = self.session.get.call_args
|
||||
passed_params = kwargs.get('params')
|
||||
self.assertIs(params, passed_params)
|
||||
|
||||
def test_get_includes_accept_header_of_application_json(self):
|
||||
self.client._get(self.href)
|
||||
self.httpclient._get(self.href)
|
||||
args, kwargs = self.session.get.call_args
|
||||
headers = kwargs.get('headers')
|
||||
self.assertIn('Accept', headers.keys())
|
||||
self.assertEqual(headers['Accept'], 'application/json')
|
||||
|
||||
def test_get_includes_default_headers(self):
|
||||
self.client._default_headers = {'Test-Default-Header': 'test'}
|
||||
self.client._get(self.href)
|
||||
self.httpclient._default_headers = {'Test-Default-Header': 'test'}
|
||||
self.httpclient._get(self.href)
|
||||
args, kwargs = self.session.get.call_args
|
||||
headers = kwargs.get('headers')
|
||||
self.assertIn('Test-Default-Header', headers.keys())
|
||||
|
||||
def test_get_checks_status_code(self):
|
||||
self.client._check_status_code = mock.MagicMock()
|
||||
self.client._get(self.href)
|
||||
self.httpclient._check_status_code = mock.MagicMock()
|
||||
self.httpclient._get(self.href)
|
||||
resp = self.session.get()
|
||||
self.client._check_status_code.assert_called_with(resp)
|
||||
self.httpclient._check_status_code.assert_called_with(resp)
|
||||
|
||||
def test_get_raw_uses_href_as_is(self):
|
||||
self.client._get_raw(self.href, self.headers)
|
||||
self.httpclient._get_raw(self.href, self.headers)
|
||||
args, kwargs = self.session.get.call_args
|
||||
url = args[0]
|
||||
self.assertEqual(url, self.href)
|
||||
|
||||
def test_get_raw_passes_headers(self):
|
||||
self.client._get_raw(self.href, self.headers)
|
||||
self.httpclient._get_raw(self.href, self.headers)
|
||||
args, kwargs = self.session.get.call_args
|
||||
headers = kwargs.get('headers')
|
||||
self.assertIs(headers, self.headers)
|
||||
|
||||
def test_get_raw_includes_default_headers(self):
|
||||
self.client._default_headers = {'Test-Default-Header': 'test'}
|
||||
self.client._get_raw(self.href, self.headers)
|
||||
self.httpclient._default_headers = {'Test-Default-Header': 'test'}
|
||||
self.httpclient._get_raw(self.href, self.headers)
|
||||
self.assertIn('Test-Default-Header', self.headers.keys())
|
||||
|
||||
def test_get_raw_checks_status_code(self):
|
||||
self.client._check_status_code = mock.MagicMock()
|
||||
self.client._get_raw(self.href, self.headers)
|
||||
self.httpclient._check_status_code = mock.MagicMock()
|
||||
self.httpclient._get_raw(self.href, self.headers)
|
||||
resp = self.session.get()
|
||||
self.client._check_status_code.assert_called_with(resp)
|
||||
self.httpclient._check_status_code.assert_called_with(resp)
|
||||
|
||||
|
||||
class WhenTestingClientDelete(TestClientWithSession):
|
||||
@@ -206,34 +217,35 @@ class WhenTestingClientDelete(TestClientWithSession):
|
||||
def setUp(self):
|
||||
super(WhenTestingClientDelete, self).setUp()
|
||||
self.session = self._get_fake_session_with_status_code(200)
|
||||
self.client = client.Client(session=self.session)
|
||||
self.httpclient = client._HTTPClient(session=self.session,
|
||||
endpoint=self.endpoint)
|
||||
self.href = 'http://test_href'
|
||||
|
||||
def test_delete_uses_href_as_is(self):
|
||||
self.client._delete(self.href)
|
||||
self.httpclient._delete(self.href)
|
||||
args, kwargs = self.session.delete.call_args
|
||||
url = args[0]
|
||||
self.assertEqual(url, self.href)
|
||||
|
||||
def test_delete_passes_json(self):
|
||||
json = '{"test": "test"}'
|
||||
self.client._delete(self.href, json=json)
|
||||
self.httpclient._delete(self.href, json=json)
|
||||
args, kwargs = self.session.delete.call_args
|
||||
passed_json = kwargs.get('json')
|
||||
self.assertEqual(passed_json, json)
|
||||
|
||||
def test_delete_includes_default_headers(self):
|
||||
self.client._default_headers = {'Test-Default-Header': 'test'}
|
||||
self.client._delete(self.href)
|
||||
self.httpclient._default_headers = {'Test-Default-Header': 'test'}
|
||||
self.httpclient._delete(self.href)
|
||||
args, kwargs = self.session.delete.call_args
|
||||
headers = kwargs.get('headers')
|
||||
self.assertIn('Test-Default-Header', headers.keys())
|
||||
|
||||
def test_delete_checks_status_code(self):
|
||||
self.client._check_status_code = mock.MagicMock()
|
||||
self.client._delete(self.href)
|
||||
self.httpclient._check_status_code = mock.MagicMock()
|
||||
self.httpclient._delete(self.href)
|
||||
resp = self.session.get()
|
||||
self.client._check_status_code.assert_called_with(resp)
|
||||
self.httpclient._check_status_code.assert_called_with(resp)
|
||||
|
||||
|
||||
class WhenTestingCheckStatusCodes(TestClient):
|
||||
@@ -241,20 +253,21 @@ class WhenTestingCheckStatusCodes(TestClient):
|
||||
def test_raises_http_auth_error_for_401_response(self):
|
||||
resp = mock.MagicMock()
|
||||
resp.status_code = 401
|
||||
self.assertRaises(client.HTTPAuthError, self.client._check_status_code,
|
||||
self.assertRaises(client.HTTPAuthError,
|
||||
self.httpclient._check_status_code,
|
||||
resp)
|
||||
|
||||
def test_raises_http_server_error_for_500_response(self):
|
||||
resp = mock.MagicMock()
|
||||
resp.status_code = 500
|
||||
self.assertRaises(client.HTTPServerError,
|
||||
self.client._check_status_code, resp)
|
||||
self.httpclient._check_status_code, resp)
|
||||
|
||||
def test_raises_http_client_error_for_400_response(self):
|
||||
resp = mock.MagicMock()
|
||||
resp.status_code = 400
|
||||
self.assertRaises(client.HTTPClientError,
|
||||
self.client._check_status_code, resp)
|
||||
self.httpclient._check_status_code, resp)
|
||||
|
||||
|
||||
class WhenTestingGetErrorMessage(TestClient):
|
||||
@@ -262,14 +275,14 @@ class WhenTestingGetErrorMessage(TestClient):
|
||||
def test_gets_error_message_from_title_in_json(self):
|
||||
resp = mock.MagicMock()
|
||||
resp.json.return_value = {'title': 'test_text'}
|
||||
msg = self.client._get_error_message(resp)
|
||||
msg = self.httpclient._get_error_message(resp)
|
||||
self.assertEqual(msg, 'test_text')
|
||||
|
||||
def test_gets_error_message_from_content_when_no_json(self):
|
||||
resp = mock.MagicMock()
|
||||
resp.json.side_effect = ValueError()
|
||||
resp.content = content = 'content'
|
||||
msg = self.client._get_error_message(resp)
|
||||
msg = self.httpclient._get_error_message(resp)
|
||||
self.assertEqual(msg, content)
|
||||
|
||||
|
||||
|
||||
@@ -28,7 +28,8 @@ class ContainerData(object):
|
||||
self.type = 'generic'
|
||||
self.secret = mock.Mock(spec=secrets.Secret)
|
||||
self.secret.__bases__ = (secrets.Secret,)
|
||||
self.secret.secret_ref = 'http://a/b/1'
|
||||
self.secret.secret_ref = ('http://barbican/v1/secrets/'
|
||||
'a73b62e4-eee2-4169-9a14-b8bb4da71d87')
|
||||
self.secret.name = 'thing1'
|
||||
self.generic_secret_refs = {self.secret.name: self.secret.secret_ref}
|
||||
self.generic_secret_refs_json = [{'name': self.secret.name,
|
||||
@@ -92,9 +93,6 @@ class WhenTestingContainers(test_client.BaseEntityResource):
|
||||
self._setUp('containers')
|
||||
|
||||
self.container = ContainerData()
|
||||
self.client.secrets = mock.MagicMock()
|
||||
self.client.secrets.get.return_value = self.container.secret
|
||||
self.client.secrets._api = self.client
|
||||
self.manager = self.client.containers
|
||||
|
||||
self.consumers_post_resource = self.entity_href + '/consumers/'
|
||||
|
||||
Reference in New Issue
Block a user