Merge "Add role inference calls, domains"
diff --git a/_modules/keystonev3/__init__.py b/_modules/keystonev3/__init__.py
index 9581cb1..1f929b2 100644
--- a/_modules/keystonev3/__init__.py
+++ b/_modules/keystonev3/__init__.py
@@ -5,62 +5,117 @@
except ImportError:
REQUIREMENTS_MET = False
+from keystonev3 import lists
from keystonev3 import endpoints
from keystonev3 import roles
from keystonev3 import services
from keystonev3 import projects
from keystonev3 import users
+from keystonev3 import domains
+from keystonev3 import regions
+from keystonev3 import groups
+
+
+domain_list = lists.domain_list
+domain_create = domains.domain_create
+domain_update = domains.domain_update
+domain_get_details = domains.domain_get_details
+domain_delete = domains.domain_delete
endpoint_get_details = endpoints.endpoint_get_details
endpoint_update = endpoints.endpoint_update
endpoint_delete = endpoints.endpoint_delete
-endpoint_list = endpoints.endpoint_list
+endpoint_list = lists.endpoint_list
endpoint_create = endpoints.endpoint_create
-role_assignment_list = roles.role_assignment_list
-role_assignment_check = roles.role_assignment_check
-role_add = roles.role_add
-role_delete = roles.role_delete
+role_assignment_list = lists.role_assignment_list
+role_assign_for_user_on_project = roles.role_assign_for_user_on_project
+role_assign_for_user_on_domain = roles.role_assign_for_user_on_domain
+role_unassign_for_user_on_project = roles.role_unassign_for_user_on_project
+role_unassign_for_user_on_domain = roles.role_unassign_for_user_on_domain
+role_assign_check_for_user_on_project = roles.\
+ role_assign_check_for_user_on_project
+role_assign_check_for_user_on_domain = roles.\
+ role_assign_check_for_user_on_domain
role_get_details = roles.role_get_details
role_update = roles.role_update
-role_delete = roles.role_delete
-role_list = roles.role_list
+role_list = lists.role_list
role_create = roles.role_create
+role_delete = roles.role_delete
+
+role_inference_rule_list = lists.role_inference_rule_list
+role_inference_rule_for_role_list = roles.role_inference_rule_for_role_list
+role_inference_rule_create = roles.role_inference_rule_create
+role_inference_rule_get = roles.role_inference_rule_get
+role_inference_rule_confirm = roles.role_inference_rule_confirm
+role_inference_rule_delete = roles.role_inference_rule_delete
+
service_get_details = services.service_get_details
service_update = services.service_update
service_delete = services.service_delete
-service_list = services.service_list
+service_list = lists.service_list
service_create = services.service_create
project_get_details = projects.project_get_details
project_update = projects.project_update
project_delete = projects.project_delete
-project_list = projects.project_list
+project_list = lists.project_list
project_create = projects.project_create
user_get_details = users.user_get_details
user_update = users.user_update
user_delete = users.user_delete
-user_list = users.user_list
+user_list = lists.user_list
user_create = users.user_create
+region_list = lists.region_list
+region_create = regions.region_create
+region_get_details = regions.region_get_details
+region_update = regions.region_update
+region_delete = regions.region_delete
+
+group_list = lists.group_list
+group_create = groups.group_create
+group_get_details = groups.group_get_details
+group_update = groups.group_update
+group_delete = groups.group_delete
+group_user_list = groups.group_user_list
+group_user_add = groups.group_user_add
+group_user_check = groups.group_user_check
+group_user_remove = groups.group_user_remove
+
+
__all__ = (
+ 'domain_list',
+ 'domain_create',
+ 'domain_get_details',
+ 'domain_update',
+ 'domain_delete',
'endpoint_get_details',
'endpoint_update',
'endpoint_delete',
'endpoint_list',
'endpoint_create',
'role_assignment_list',
- 'role_assignment_check',
- 'role_add',
- 'role_delete',
+ 'role_assign_for_user_on_project',
+ 'role_assign_for_user_on_domain',
+ 'role_assign_check_for_user_on_domain',
+ 'role_assign_check_for_user_on_project',
+ 'role_unassign_for_user_on_domain',
+ 'role_unassign_for_user_on_project',
'role_get_details',
'role_update',
'role_delete',
'role_list',
'role_create',
+ 'role_inference_rule_confirm',
+ 'role_inference_rule_create',
+ 'role_inference_rule_delete',
+ 'role_inference_rule_for_role_list',
+ 'role_inference_rule_get',
+ 'role_inference_rule_list',
'service_get_details',
'service_update',
'service_delete',
@@ -75,7 +130,21 @@
'user_update',
'user_delete',
'user_list',
- 'user_create'
+ 'user_create',
+ 'region_create',
+ 'region_delete',
+ 'region_get_details',
+ 'region_list',
+ 'region_update',
+ 'group_list',
+ 'group_create',
+ 'group_delete',
+ 'group_get_details',
+ 'group_update',
+ 'group_user_add',
+ 'group_user_check',
+ 'group_user_list',
+ 'group_user_remove',
)
diff --git a/_modules/keystonev3/arg_converter.py b/_modules/keystonev3/arg_converter.py
new file mode 100644
index 0000000..2ef40aa
--- /dev/null
+++ b/_modules/keystonev3/arg_converter.py
@@ -0,0 +1,73 @@
+import uuid
+from keystonev3 import common
+from keystonev3 import lists
+
+
+class CheckId(object):
+ def check_id(self, val):
+ try:
+ return str(uuid.UUID(val)).replace('-', '') == val
+ except (TypeError, ValueError, AttributeError):
+ return False
+
+
+class DomainCheckId(CheckId):
+ def check_id(self, val):
+ if val == 'default':
+ return True
+ return super(DomainCheckId, self).check_id(val)
+
+
+resource_lists = {
+ 'project': lists.project_list,
+ 'role': lists.role_list,
+ 'service': lists.service_list,
+ 'user': lists.user_list,
+ 'domain': lists.domain_list,
+ 'group': lists.group_list,
+}
+
+
+response_keys = {
+ 'project': 'projects',
+ 'role': 'roles',
+ 'service': 'services',
+ 'user': 'users',
+ 'domain': 'domains',
+ 'group': 'groups'
+}
+
+
+def get_by_name_or_uuid_multiple(resource_arg_name_pairs):
+ def wrap(func):
+ def wrapped_f(*args, **kwargs):
+ results = []
+ args_start = 0
+ for index, (resource, arg_name) in enumerate(
+ resource_arg_name_pairs):
+ if arg_name in kwargs:
+ ref = kwargs.pop(arg_name, None)
+ else:
+ ref = args[index]
+ args_start += 1
+ cloud_name = kwargs['cloud_name']
+ if resource == 'domain':
+ checker = DomainCheckId()
+ else:
+ checker = CheckId()
+ if checker.check_id(ref):
+ results.append(ref)
+ else:
+ # Then we have name not uuid
+ resp_key = response_keys[resource]
+ resp = resource_lists[resource](
+ name=ref, cloud_name=cloud_name)[resp_key]
+ if len(resp) == 0:
+ raise common.ResourceNotFound(resp_key, ref)
+ elif len(resp) > 1:
+ raise common.MultipleResourcesFound(resp_key, ref)
+ results.append(resp[0]['id'])
+ results.extend(args[args_start:])
+ return func(*results, **kwargs)
+ return wrapped_f
+ return wrap
\ No newline at end of file
diff --git a/_modules/keystonev3/common.py b/_modules/keystonev3/common.py
index 52b7914..93cfe6d 100644
--- a/_modules/keystonev3/common.py
+++ b/_modules/keystonev3/common.py
@@ -1,6 +1,5 @@
import logging
import os_client_config
-import uuid
log = logging.getLogger(__name__)
@@ -96,36 +95,3 @@
return resp
return wrapped_f
return wrap
-
-
-def _check_uuid(val):
- try:
- return str(uuid.UUID(val)).replace('-', '') == val
- except (TypeError, ValueError, AttributeError):
- return False
-
-
-def get_by_name_or_uuid(resource_list, resp_key, arg_name):
- def wrap(func):
- def wrapped_f(*args, **kwargs):
- if arg_name in kwargs:
- ref = kwargs.pop(arg_name, None)
- start_arg = 0
- else:
- start_arg = 1
- ref = args[0]
- cloud_name = kwargs['cloud_name']
- if _check_uuid(ref):
- uuid = ref
- else:
- # Then we have name not uuid
- resp = resource_list(
- name=ref, cloud_name=cloud_name)[resp_key]
- if len(resp) == 0:
- raise ResourceNotFound(resp_key, ref)
- elif len(resp) > 1:
- raise MultipleResourcesFound(resp_key, ref)
- uuid = resp[0]['id']
- return func(uuid, *args[start_arg:], **kwargs)
- return wrapped_f
- return wrap
diff --git a/_modules/keystonev3/domains.py b/_modules/keystonev3/domains.py
new file mode 100644
index 0000000..d594f05
--- /dev/null
+++ b/_modules/keystonev3/domains.py
@@ -0,0 +1,36 @@
+from keystonev3.common import send
+from keystonev3.arg_converter import get_by_name_or_uuid_multiple
+
+
+@send('post')
+def domain_create(name, **kwargs):
+ url = '/domains'
+ json = {
+ 'domain': kwargs,
+ }
+ json['domain']['name'] = name
+ return url, json
+
+
+@get_by_name_or_uuid_multiple([('domain', 'domain_id')])
+@send('get')
+def domain_get_details(domain_id, **kwargs):
+ url = '/domains/{}'.format(domain_id)
+ return url, None
+
+
+@get_by_name_or_uuid_multiple([('domain', 'domain_id')])
+@send('patch')
+def domain_update(domain_id, **kwargs):
+ url = '/domains/{}'.format(domain_id)
+ json = {
+ 'domain': kwargs,
+ }
+ return url, json
+
+
+@get_by_name_or_uuid_multiple([('domain', 'domain_id')])
+@send('delete')
+def domain_delete(domain_id, **kwargs):
+ url = '/domains/{}'.format(domain_id)
+ return url, None
diff --git a/_modules/keystonev3/endpoints.py b/_modules/keystonev3/endpoints.py
index 4230ad3..9f378d5 100644
--- a/_modules/keystonev3/endpoints.py
+++ b/_modules/keystonev3/endpoints.py
@@ -1,5 +1,5 @@
from keystonev3.common import send
-
+from keystonev3.arg_converter import get_by_name_or_uuid_multiple
try:
from urllib.parse import urlencode
except ImportError:
@@ -27,16 +27,16 @@
return url, None
-@send('get')
-def endpoint_list(**kwargs):
- url = '/endpoints?{}'.format(urlencode(kwargs))
- return url, None
-
-
+@get_by_name_or_uuid_multiple([('service', 'service_id')])
@send('post')
-def endpoint_create(**kwargs):
- url = '/endpoints'
+def endpoint_create(service_id, url, interface, **kwargs):
+ api_url = '/endpoints'
json = {
- 'endpoint': kwargs,
+ 'endpoint': {
+ 'service_id': service_id,
+ 'url': url,
+ 'interface': interface,
+ }
}
- return url, json
+ json['endpoint'].update(kwargs)
+ return api_url, json
diff --git a/_modules/keystonev3/groups.py b/_modules/keystonev3/groups.py
new file mode 100644
index 0000000..a8890d5
--- /dev/null
+++ b/_modules/keystonev3/groups.py
@@ -0,0 +1,71 @@
+from keystonev3.common import send
+from keystonev3.arg_converter import get_by_name_or_uuid_multiple
+try:
+ from urllib.parse import urlencode
+except ImportError:
+ from urllib import urlencode
+
+
+@get_by_name_or_uuid_multiple([('domain', 'domain_id')])
+@send('post')
+def group_create(domain_id, name, **kwargs):
+ url = '/groups'
+ json = {
+ 'group':{
+ 'name': name,
+ 'domain_id': domain_id,
+ }
+ }
+ json['group'].update(kwargs)
+ return url, json
+
+
+@get_by_name_or_uuid_multiple([('group', 'group_id')])
+@send('get')
+def group_get_details(group_id, **kwargs):
+ url = '/groups/{}'.format(group_id)
+ return url, None
+
+
+@get_by_name_or_uuid_multiple([('group', 'group_id')])
+@send('patch')
+def group_update(group_id, **kwargs):
+ url = '/groups/{}'.format(group_id)
+ json = {
+ 'group': kwargs,
+ }
+ return url, json
+
+
+@get_by_name_or_uuid_multiple([('group', 'group_id')])
+@send('delete')
+def group_delete(group_id, **kwargs):
+ url = '/groups/{}'.format(group_id)
+ return url, None
+
+@get_by_name_or_uuid_multiple([('group', 'group_id')])
+@send('get')
+def group_user_list(group_id, **kwargs):
+ url = '/groups/{}?{}'.format(group_id, urlencode(kwargs))
+ return url, None
+
+
+@get_by_name_or_uuid_multiple([('group', 'group_id'), ('user', 'user_id')])
+@send('put')
+def group_user_add(group_id, user_id, **kwargs):
+ url = '/groups/{}/users/{}'.format(group_id, user_id)
+ return url, None
+
+
+@get_by_name_or_uuid_multiple([('group', 'group_id'), ('user', 'user_id')])
+@send('head')
+def group_user_check(group_id, user_id, **kwargs):
+ url = '/groups/{}/users/{}'.format(group_id, user_id)
+ return url, None
+
+
+@get_by_name_or_uuid_multiple([('group', 'group_id'), ('user', 'user_id')])
+@send('delete')
+def group_user_remove(group_id, user_id, **kwargs):
+ url = '/groups/{}/users/{}'.format(group_id, user_id)
+ return url, None
diff --git a/_modules/keystonev3/lists.py b/_modules/keystonev3/lists.py
new file mode 100644
index 0000000..f2d8344
--- /dev/null
+++ b/_modules/keystonev3/lists.py
@@ -0,0 +1,66 @@
+from keystonev3.common import send
+
+try:
+ from urllib.parse import urlencode
+except ImportError:
+ from urllib import urlencode
+
+
+@send('get')
+def project_list(**kwargs):
+ url = '/projects?{}'.format(urlencode(kwargs))
+ return url, None
+
+
+@send('get')
+def domain_list(**kwargs):
+ url = '/domains?{}'.format(urlencode(kwargs))
+ return url, None
+
+
+@send('get')
+def endpoint_list(**kwargs):
+ url = '/endpoints?{}'.format(urlencode(kwargs))
+ return url, None
+
+
+@send('get')
+def service_list(**kwargs):
+ url = '/services?{}'.format(urlencode(kwargs))
+ return url, None
+
+
+@send('get')
+def user_list(**kwargs):
+ url = '/users?{}'.format(urlencode(kwargs))
+ return url, None
+
+
+@send('get')
+def role_list(**kwargs):
+ url = '/roles?{}'.format(urlencode(kwargs))
+ return url, None
+
+
+@send('get')
+def role_assignment_list(**kwargs):
+ url = '/role_assignments?{}'.format(urlencode(kwargs))
+ return url, None
+
+
+@send('get')
+def role_inference_rule_list(**kwargs):
+ url = '/role_inferences'
+ return url, None
+
+
+@send('get')
+def region_list(**kwargs):
+ url = '/regions?{}'.format(urlencode(kwargs))
+ return url, None
+
+
+@send('get')
+def group_list(**kwargs):
+ url = '/groups?{}'.format(urlencode(kwargs))
+ return url, None
\ No newline at end of file
diff --git a/_modules/keystonev3/projects.py b/_modules/keystonev3/projects.py
index 26e44fe..643a46d 100644
--- a/_modules/keystonev3/projects.py
+++ b/_modules/keystonev3/projects.py
@@ -1,24 +1,20 @@
-from keystonev3.common import get_by_name_or_uuid, send
+from keystonev3.common import send
+from keystonev3.arg_converter import get_by_name_or_uuid_multiple
+
try:
from urllib.parse import urlencode
except ImportError:
from urllib import urlencode
-@send('get')
-def project_list(**kwargs):
- url = '/projects?{}'.format(urlencode(kwargs))
- return url, None
-
-
-@get_by_name_or_uuid(project_list, 'projects', 'project_id')
+@get_by_name_or_uuid_multiple([('project', 'project_id')])
@send('get')
def project_get_details(project_id, **kwargs):
url = '/projects/{}?{}'.format(project_id, urlencode(kwargs))
return url, None
-@get_by_name_or_uuid(project_list, 'projects', 'project_id')
+@get_by_name_or_uuid_multiple([('project', 'project_id')])
@send('patch')
def project_update(project_id, **kwargs):
url = '/projects/{}'.format(project_id)
@@ -28,17 +24,22 @@
return url, json
-@get_by_name_or_uuid(project_list, 'projects', 'project_id')
+@get_by_name_or_uuid_multiple([('project', 'project_id')])
@send('delete')
def project_delete(project_id, **kwargs):
url = '/projects/{}'.format(project_id)
return url, None
+@get_by_name_or_uuid_multiple([('domain', 'domain_id')])
@send('post')
-def project_create(**kwargs):
+def project_create(domain_id, name,**kwargs):
url = '/projects'
json = {
- 'project': kwargs,
+ 'project': {
+ 'name': name,
+ 'domain_id': domain_id,
+ }
}
+ json['project'].update(kwargs)
return url, json
diff --git a/_modules/keystonev3/regions.py b/_modules/keystonev3/regions.py
new file mode 100644
index 0000000..549e27a
--- /dev/null
+++ b/_modules/keystonev3/regions.py
@@ -0,0 +1,31 @@
+from keystonev3.common import send
+
+
+@send('get')
+def region_get_details(region_id, **kwargs):
+ url = '/regions/{}'.format(region_id)
+ return url, None
+
+
+@send('patch')
+def region_update(region_id, **kwargs):
+ url = '/regions/{}'.format(region_id)
+ json = {
+ 'region': kwargs
+ }
+ return url, json
+
+
+@send('delete')
+def region_delete(region_id, **kwargs):
+ url = '/regions/{}'.format(region_id)
+ return url, None
+
+
+@send('post')
+def region_create(**kwargs):
+ url = '/regions'
+ json = {
+ 'region': kwargs
+ }
+ return url, json
\ No newline at end of file
diff --git a/_modules/keystonev3/roles.py b/_modules/keystonev3/roles.py
index bd85c16..3f6c06a 100644
--- a/_modules/keystonev3/roles.py
+++ b/_modules/keystonev3/roles.py
@@ -1,5 +1,6 @@
-from keystonev3.common import get_by_name_or_uuid, send
-from keystonev3.common import KeystoneException
+from keystonev3.common import send
+from keystonev3.arg_converter import get_by_name_or_uuid_multiple
+
try:
from urllib.parse import urlencode
@@ -7,69 +8,64 @@
from urllib import urlencode
-@send('get')
-def role_list(**kwargs):
- url = '/roles?{}'.format(urlencode(kwargs))
- return url, None
-
-
-@send('get')
-def role_assignment_list(**kwargs):
- url = '/role_assignments?{}'.format(urlencode(kwargs))
- return url, None
-
-
+@get_by_name_or_uuid_multiple([('project', 'project_id'), ('user', 'user_id'),
+ ('role', 'role_id')])
@send('put')
-def role_add(user_id, role_id, project_id=None, domain_id=None, **kwargs):
- if (project_id and domain_id) or (not project_id and not domain_id):
- raise KeystoneException('Role can be assigned either to project '
- 'or domain.')
- if project_id:
- url = '/projects/{}/users/{}/roles/{}'.format(project_id, user_id,
- role_id)
- elif domain_id:
- url = '/domains/{}/users/{}/roles/{}'.format(domain_id, user_id,
- role_id)
+def role_assign_for_user_on_project(project_id, user_id, role_id, **kwargs):
+ url = '/projects/{}/users/{}/roles/{}'.format(project_id, user_id, role_id)
return url, None
+@get_by_name_or_uuid_multiple([('domain', 'domain_id'), ('user', 'user_id'),
+ ('role', 'role_id')])
+@send('put')
+def role_assign_for_user_on_domain(domain_id, user_id, role_id, **kwargs):
+ url = '/domains/{}/users/{}/roles/{}'.format(domain_id, user_id, role_id)
+ return url, None
+
+
+@get_by_name_or_uuid_multiple([('project', 'project_id'), ('user', 'user_id'),
+ ('role', 'role_id')])
@send('delete')
-def role_delete(user_id, role_id, project_id=None, domain_id=None, **kwargs):
- if (project_id and domain_id) or (not project_id and not domain_id):
- raise KeystoneException('Role can be unassigned either from project '
- 'or domain.')
- if project_id:
- url = '/projects/{}/users/{}/roles/{}'.format(project_id, user_id,
- role_id)
- elif domain_id:
- url = '/domains/{}/users/{}/roles/{}'.format(domain_id, user_id,
- role_id)
+def role_unassign_for_user_on_project(project_id, user_id, role_id, **kwargs):
+ url = '/projects/{}/users/{}/roles/{}'.format(project_id, user_id, role_id)
return url, None
+@get_by_name_or_uuid_multiple([('domain', 'domain_id'), ('user', 'user_id'),
+ ('role', 'role_id')])
+@send('delete')
+def role_unassign_for_user_on_domain(domain_id, user_id, role_id, **kwargs):
+ url = '/domains/{}/users/{}/roles/{}'.format(domain_id, user_id, role_id)
+ return url, None
+
+
+@get_by_name_or_uuid_multiple([('project', 'project_id'), ('user', 'user_id'),
+ ('role', 'role_id')])
@send('head')
-def role_assignment_check(user_id, role_id, project_id=None,
- domain_id=None, **kwargs):
- if (project_id and domain_id) or (not project_id and not domain_id):
- raise KeystoneException('Role can be assigned either to project '
- 'or domain.')
- if project_id:
- url = '/projects/{}/users/{}/roles/{}'.format(project_id, user_id,
- role_id)
- elif domain_id:
- url = '/domains/{}/users/{}/roles/{}'.format(domain_id, user_id,
- role_id)
+def role_assign_check_for_user_on_project(project_id, user_id, role_id,
+ **kwargs):
+ url = '/projects/{}/users/{}/roles/{}'.format(project_id, user_id, role_id)
return url, None
-@get_by_name_or_uuid(role_list, 'roles', 'role_id')
+@get_by_name_or_uuid_multiple([('domain', 'domain_id'), ('user', 'user_id'),
+ ('role', 'role_id')])
+@send('head')
+def role_assign_check_for_user_on_domain(domain_id, user_id, role_id,
+ **kwargs):
+ url = '/domains/{}/users/{}/roles/{}'.format(domain_id, user_id, role_id)
+ return url, None
+
+
+@get_by_name_or_uuid_multiple([('role', 'role_id')])
@send('get')
def role_get_details(role_id, **kwargs):
url = '/roles/{}?{}'.format(role_id, urlencode(kwargs))
return url, None
-@get_by_name_or_uuid(role_list, 'roles', 'role_id')
+@get_by_name_or_uuid_multiple([('role', 'role_id')])
@send('patch')
def role_update(role_id, **kwargs):
url = '/roles/{}'.format(role_id)
@@ -79,9 +75,9 @@
return url, json
-@get_by_name_or_uuid(role_list, 'roles', 'role_id')
+@get_by_name_or_uuid_multiple([('role', 'role_id')])
@send('delete')
-def role_remove(role_id, **kwargs):
+def role_delete(role_id, **kwargs):
url = '/roles/{}'.format(role_id)
return url, None
@@ -93,3 +89,42 @@
'role': kwargs,
}
return url, json
+
+
+@get_by_name_or_uuid_multiple([('role', 'prior_role_id')])
+@send('get')
+def role_inference_rule_for_role_list(prior_role_id, **kwargs):
+ url = '/roles/{}/implies'.format(prior_role_id)
+ return url, None
+
+
+@get_by_name_or_uuid_multiple([('role', 'prior_role_id'),
+ ('role', 'implies_role_id')])
+@send('put')
+def role_inference_rule_create(prior_role_id, implies_role_id, **kwargs):
+ url = '/roles/{}/implies/{}'.format(prior_role_id, implies_role_id)
+ return url, None
+
+
+@get_by_name_or_uuid_multiple([('role', 'prior_role_id'),
+ ('role', 'implies_role_id')])
+@send('get')
+def role_inference_rule_get(prior_role_id, implies_role_id, **kwargs):
+ url = '/roles/{}/implies/{}'.format(prior_role_id, implies_role_id)
+ return url, None
+
+
+@get_by_name_or_uuid_multiple([('role', 'prior_role_id'),
+ ('role', 'implies_role_id')])
+@send('head')
+def role_inference_rule_confirm(prior_role_id, implies_role_id, **kwargs):
+ url = '/roles/{}/implies/{}'.format(prior_role_id, implies_role_id)
+ return url, None
+
+
+@get_by_name_or_uuid_multiple([('role', 'prior_role_id'),
+ ('role', 'implies_role_id')])
+@send('delete')
+def role_inference_rule_delete(prior_role_id, implies_role_id, **kwargs):
+ url = '/roles/{}/implies/{}'.format(prior_role_id, implies_role_id)
+ return url, None
diff --git a/_modules/keystonev3/services.py b/_modules/keystonev3/services.py
index f917cbf..546e3a0 100644
--- a/_modules/keystonev3/services.py
+++ b/_modules/keystonev3/services.py
@@ -1,4 +1,5 @@
-from keystonev3.common import get_by_name_or_uuid, send
+from keystonev3.common import send
+from keystonev3.arg_converter import get_by_name_or_uuid_multiple
try:
from urllib.parse import urlencode
@@ -6,20 +7,14 @@
from urllib import urlencode
-@send('get')
-def service_list(**kwargs):
- url = '/services?{}'.format(urlencode(kwargs))
- return url, None
-
-
-@get_by_name_or_uuid(service_list, 'services', 'service_id')
+@get_by_name_or_uuid_multiple([('service', 'service_id')])
@send('get')
def service_get_details(service_id, **kwargs):
url = '/services/{}?{}'.format(service_id, urlencode(kwargs))
return url, None
-@get_by_name_or_uuid(service_list, 'services', 'service_id')
+@get_by_name_or_uuid_multiple([('service', 'service_id')])
@send('patch')
def service_update(service_id, **kwargs):
url = '/services/{}'.format(service_id)
@@ -29,7 +24,7 @@
return url, json
-@get_by_name_or_uuid(service_list, 'services', 'service_id')
+@get_by_name_or_uuid_multiple([('service', 'service_id')])
@send('delete')
def service_delete(service_id, **kwargs):
url = '/services/{}'.format(service_id)
diff --git a/_modules/keystonev3/users.py b/_modules/keystonev3/users.py
index 9582eef..d239922 100644
--- a/_modules/keystonev3/users.py
+++ b/_modules/keystonev3/users.py
@@ -1,24 +1,19 @@
-from keystonev3.common import get_by_name_or_uuid, send
+from keystonev3.common import send
+from keystonev3.arg_converter import get_by_name_or_uuid_multiple
try:
from urllib.parse import urlencode
except ImportError:
from urllib import urlencode
-@send('get')
-def user_list(**kwargs):
- url = '/users?{}'.format(urlencode(kwargs))
- return url, None
-
-
-@get_by_name_or_uuid(user_list, 'users', 'user_id')
+@get_by_name_or_uuid_multiple([('user', 'user_id')])
@send('get')
def user_get_details(user_id, **kwargs):
url = '/users/{}?{}'.format(user_id, urlencode(kwargs))
return url, None
-@get_by_name_or_uuid(user_list, 'users', 'user_id')
+@get_by_name_or_uuid_multiple([('user', 'user_id')])
@send('patch')
def user_update(user_id, **kwargs):
url = '/users/{}'.format(user_id)
@@ -28,7 +23,7 @@
return url, json
-@get_by_name_or_uuid(user_list, 'users', 'user_id')
+@get_by_name_or_uuid_multiple([('user', 'user_id')])
@send('delete')
def user_delete(user_id, **kwargs):
url = '/users/{}'.format(user_id)
diff --git a/_states/keystonev3.py b/_states/keystonev3.py
index 4a63d60..f9012cf 100644
--- a/_states/keystonev3.py
+++ b/_states/keystonev3.py
@@ -62,10 +62,14 @@
return _find_failed(name, 'endpoint')
-def endpoint_absent(name, cloud_name):
+def endpoint_absent(name, service_id, interface, cloud_name):
+ service_id = _keystonev3_call(
+ 'service_get_details', service_id,
+ cloud_name=cloud_name)['service']['id']
+
endpoints = _keystonev3_call(
- 'endpoint_list', name=name, cloud_name=cloud_name
- )['endpoints']
+ 'endpoint_list', name=name, service_id=service_id, interface=interface,
+ cloud_name=cloud_name)['endpoints']
if not endpoints:
return _absent(name, 'endpoint')
elif len(endpoints) == 1:
@@ -133,16 +137,36 @@
return _find_failed(name, 'service')
-def project_present(name, cloud_name, **kwargs):
+def service_absent(name, cloud_name):
+ try:
+ _keystonev3_call(
+ 'service_get_details', name,
+ cloud_name=cloud_name)['service']
+ except Exception as e:
+ if 'ResourceNotFound' in repr(e):
+ return _absent(name, 'service')
+ else:
+ log.error('Failed to get service {}'.format(e))
+ return _find_failed(name, 'service')
+ try:
+ _keystonev3_call('service_delete', name, cloud_name=cloud_name)
+ except Exception:
+ return _delete_failed(name, 'service')
+ return _deleted(name, 'service')
+
+
+
+def project_present(name, domain_id, cloud_name, **kwargs):
projects = _keystonev3_call(
- 'project_list', name=name, cloud_name=cloud_name
+ 'project_list', name=name, domain_id=domain_id, cloud_name=cloud_name
)['projects']
if not projects:
try:
resp = _keystonev3_call(
- 'project_create', name=name, cloud_name=cloud_name, **kwargs
+ 'project_create', domain_id=domain_id, name=name,
+ cloud_name=cloud_name, **kwargs
)
except Exception as e:
log.error('Keystone project create failed with {}'.format(e))
@@ -178,6 +202,24 @@
return _find_failed(name, 'project')
+def project_absent(name, cloud_name):
+ try:
+ _keystonev3_call('project_get_details',
+ project_id=name, cloud_name=cloud_name)
+ except Exception as e:
+ if 'ResourceNotFound' in repr(e):
+ return _absent(name, 'project')
+ else:
+ log.error('Failed to get project {}'.format(e))
+ return _find_failed(name, 'project')
+ try:
+ _keystonev3_call('project_delete', project_id=name,
+ cloud_name=cloud_name)
+ except Exception:
+ return _delete_failed(name, 'project')
+ return _deleted(name, 'project')
+
+
def user_present(name, cloud_name, password_reset=False, **kwargs):
users = _keystonev3_call(
@@ -232,6 +274,23 @@
return _find_failed(name, 'user')
+def user_absent(name, cloud_name):
+ try:
+ _keystonev3_call('user_get_details', user_id=name,
+ cloud_name=cloud_name)
+ except Exception as e:
+ if 'ResourceNotFound' in repr(e):
+ return _absent(name, 'user')
+ else:
+ log.error('Failed to get user {}'.format(e))
+ return _find_failed(name, 'user')
+ try:
+ _keystonev3_call('user_delete', user_id=name, cloud_name=cloud_name)
+ except Exception:
+ return _delete_failed(name, 'user')
+ return _deleted(name, 'user')
+
+
def user_role_assigned(name, role_id, cloud_name, project_id=None,
domain_id=None, role_domain_id=None, **kwargs):
@@ -244,21 +303,30 @@
'project_get_details', project_id,
cloud_name=cloud_name)['project']['id']
-# TODO: Add when domain support is added.
-# if domain_id and not uuidutils.is_uuid_like(domain_id):
-# domain_id = _keystonev3_call(
-# 'domain_get_details', domain_id,
-# cloud_name=cloud_name)['domain']['id']
+ if domain_id:
+ domain_id = _keystonev3_call(
+ 'domain_get_details', domain_id,
+ cloud_name=cloud_name)['domain']['id']
-# if role_domain_id and not uuidutils.is_uuid_like(role_domain_id):
-# role_domain_id = _keystonev3_call(
-# 'domain_get_details', role_domain_id,
-# cloud_name=cloud_name)['domain']['id']
+
+ if (project_id and domain_id) or (not project_id and not domain_id):
+ return {
+ 'name': name,
+ 'changes': {},
+ 'result': False,
+ 'comment': 'Use project_id or domain_id (only one of them)'
+ }
+
+
+ if role_domain_id:
+ role_domain_id = _keystonev3_call(
+ 'domain_get_details', role_domain_id,
+ cloud_name=cloud_name)['domain']['id']
if role_id:
role_id = _keystonev3_call(
- 'role_get_details', role_id, domain_id=role_domain_id,
- cloud_name=cloud_name)['role']['id']
+ 'role_get_details', role_id, domain_id=role_domain_id,
+ cloud_name=cloud_name)['role']['id']
req_kwargs = {'role.id': role_id, 'user.id': user_id,
'cloud_name': cloud_name}
@@ -278,8 +346,10 @@
req_kwargs['project_id'] = project_id
if not role_assignments:
+ method_type = 'project' if project_id else 'domain'
+ method = 'role_assign_for_user_on_{}'.format(method_type)
try:
- resp = _keystonev3_call('role_add', **req_kwargs)
+ resp = _keystonev3_call(method, **req_kwargs)
except Exception as e:
log.error('Keystone user role assignment with {}'.format(e))
return _create_failed(name, 'user_role_assignment')
@@ -289,6 +359,69 @@
return _no_changes(name, 'user_role_assignment')
+def user_role_unassign(name, role_id, cloud_name, project_id=None,
+ domain_id=None, role_domain_id=None):
+ user_id = _keystonev3_call(
+ 'user_get_details', name,
+ cloud_name=cloud_name)['user']['id']
+
+ if project_id:
+ project_id = _keystonev3_call(
+ 'project_get_details', project_id,
+ cloud_name=cloud_name)['project']['id']
+
+ if domain_id:
+ domain_id = _keystonev3_call(
+ 'domain_get_details', domain_id,
+ cloud_name=cloud_name)['domain']['id']
+
+ if (project_id and domain_id) or (not project_id and not domain_id):
+ return {
+ 'name': name,
+ 'changes': {},
+ 'result': False,
+ 'comment': 'Use project_id or domain_id (only one of them)'
+ }
+
+ if role_domain_id:
+ role_domain_id = _keystonev3_call(
+ 'domain_get_details', role_domain_id,
+ cloud_name=cloud_name)['domain']['id']
+
+ if role_id:
+ role_id = _keystonev3_call(
+ 'role_get_details', role_id, domain_id=role_domain_id,
+ cloud_name=cloud_name)['role']['id']
+
+ req_kwargs = {'role.id': role_id, 'user.id': user_id,
+ 'cloud_name': cloud_name}
+ if domain_id:
+ req_kwargs['domain_id'] = domain_id
+ if project_id:
+ req_kwargs['project_id'] = project_id
+
+ role_assignments = _keystonev3_call(
+ 'role_assignment_list', **req_kwargs)['role_assignments']
+
+ req_kwargs = {'cloud_name': cloud_name, 'user_id': user_id,
+ 'role_id': role_id}
+ if domain_id:
+ req_kwargs['domain_id'] = domain_id
+ if project_id:
+ req_kwargs['project_id'] = project_id
+
+ if not role_assignments:
+ return _absent(name, 'user_role_assignment')
+ else:
+ method_type = 'project' if project_id else 'domain'
+ method = 'role_unassign_for_user_on_{}'.format(method_type)
+ try:
+ _keystonev3_call(method, **req_kwargs)
+ except Exception:
+ return _delete_failed(name, 'user_role_assignment')
+ return _deleted(name, 'user_role_assignment')
+
+
def role_present(name, cloud_name, **kwargs):
roles = _keystonev3_call(
@@ -336,6 +469,23 @@
return _find_failed(name, 'role')
+def role_absent(name, cloud_name):
+ try:
+ _keystonev3_call('role_get_details', role_id=name,
+ cloud_name=cloud_name)
+ except Exception as e:
+ if 'ResourceNotFound' in repr(e):
+ return _absent(name, 'role')
+ else:
+ log.error('Failed to get role {}'.format(e))
+ return _find_failed(name, 'role')
+ try:
+ _keystonev3_call('role_delete', role_id=name, cloud_name=cloud_name)
+ except Exception:
+ return _delete_failed(name, 'role')
+ return _deleted(name, 'role')
+
+
def _created(name, resource, resource_definition):
changes_dict = {
'name': name,
diff --git a/keystone/client/resources/v3.sls b/keystone/client/resources/v3.sls
index 015fdcf..ea174b2 100644
--- a/keystone/client/resources/v3.sls
+++ b/keystone/client/resources/v3.sls
@@ -46,7 +46,7 @@
- url: {{ endpoint.url }}
- interface: {{ endpoint.interface }}
- service_id: {{ service_name }}
- - region: {{ endpoint.region }}
+ - region_id: {{ endpoint.region }}
- require:
- keystone_service_{{ service_name }}_{{ service.type }}
@@ -61,16 +61,13 @@
keystonev3.project_present:
- cloud_name: {{ project.get('cloud_name', resources.cloud_name) }}
- name: {{ project_name }}
+ - domain_id: {{ project.get('domain_id', 'default')}}
{%- if project.is_domain is defined %}
- is_domain: {{ project.is_domain }}
{%- endif %}
{%- if project.description is defined %}
- description: {{ project.description }}
{%- endif %}
-{# TODO unkomment when domain support is added. #}
-{# {- if project.domain_id is defined %} #}
-{# - domain_id: {{ project.domain_id }} #}
-{# {%- endif %} #}
{%- if project.enabled is defined %}
- enabled: {{ project.enabled }}
{%- endif %}