blob: fed74152f8b4c60569291348f0aa5f02ac461160 [file] [log] [blame]
Oleg Iurchenko5b1e5322017-10-20 00:29:20 +03001# -*- coding: utf-8 -*-
2'''
3Management of Keystone users
4============================
5
6:depends: - keystoneclient Python module
7:configuration: See :py:mod:`salt.modules.keystone` for setup instructions.
8
9.. code-block:: yaml
10
11 Keystone tenants:
12 keystoneng.tenant_present:
13 - names:
14 - admin
15 - demo
16 - service
17
18 Keystone roles:
19 keystoneng.role_present:
20 - names:
21 - admin
22 - Member
23
24 admin:
25 keystoneng.user_present:
26 - password: R00T_4CC3SS
27 - email: admin@domain.com
28 - roles:
29 admin: # tenants
30 - admin # roles
31 service:
32 - admin
33 - Member
34 - require:
35 - keystone: Keystone tenants
36 - keystone: Keystone roles
37
38 nova:
39 keystoneng.user_present:
40 - password: '$up3rn0v4'
41 - email: nova@domain.com
42 - tenant: service
43 - roles:
44 service:
45 - admin
46 - require:
47 - keystone: Keystone tenants
48 - keystone: Keystone roles
49
50 demo:
51 keystoneng.user_present:
52 - password: 'd3m0n$trati0n'
53 - email: demo@domain.com
54 - tenant: demo
55 - roles:
56 demo:
57 - Member
58 - require:
59 - keystone: Keystone tenants
60 - keystone: Keystone roles
61
62 nova service:
63 keystoneng.service_present:
64 - name: nova
65 - service_type: compute
66 - description: OpenStack Compute Service
67
68'''
69
Oleg Iurchenkofd0f5f32018-02-07 15:44:08 +020070# Import 3rd-party libs
71from salt.ext import six
Oleg Iurchenko5b1e5322017-10-20 00:29:20 +030072
73def __virtual__():
74 '''
75 Only load if the keystone module is in __salt__
76 '''
77 return 'keystoneng' if 'keystoneng.auth' in __salt__ else False
78
79
80_OS_IDENTITY_API_VERSION = 2
81_TENANT_ID = 'tenant_id'
82
83
84def _api_version(profile=None, **connection_args):
85 '''
86 Sets global variables _OS_IDENTITY_API_VERSION and _TENANT_ID
87 depending on API version.
88 '''
89 global _TENANT_ID
90 global _OS_IDENTITY_API_VERSION
91 try:
92 if float(__salt__['keystoneng.api_version'](profile=profile, **connection_args)) >= 3:
93 _TENANT_ID = 'project_id'
94 _OS_IDENTITY_API_VERSION = 3
95 except KeyError:
96 pass
97
98
99def user_present(name,
100 password,
101 email,
102 tenant=None,
103 enabled=True,
104 roles=None,
105 profile=None,
106 password_reset=True,
107 project=None,
Oleksandr Shyshkoa0b79e22019-02-27 15:02:30 +0000108 options=None,
Oleg Iurchenko5b1e5322017-10-20 00:29:20 +0300109 **connection_args):
110 '''
111 Ensure that the keystone user is present with the specified properties.
112
113 name
114 The name of the user to manage
115
116 password
117 The password to use for this user.
118
119 .. note::
120
121 If the user already exists and a different password was set for
122 the user than the one specified here, the password for the user
123 will be updated. Please set the ``password_reset`` option to
124 ``False`` if this is not the desired behavior.
125
126 password_reset
127 Whether or not to reset password after initial set. Defaults to
128 ``True``.
129
130 email
131 The email address for this user
132
133 tenant
134 The tenant (name) for this user
135
136 project
137 The project (name) for this user (overrides tenant in api v3)
138
139 enabled
140 Availability state for this user
141
Oleksandr Shyshkoa0b79e22019-02-27 15:02:30 +0000142 options
143 Dictionary of extra user options.
144
Oleg Iurchenko5b1e5322017-10-20 00:29:20 +0300145 roles
146 The roles the user should have under given tenants.
147 Passed as a dictionary mapping tenant names to a list
148 of roles in this tenant, i.e.::
149
150 roles:
151 admin: # tenant
152 - admin # role
153 service:
154 - admin
155 - Member
156 '''
157 ret = {'name': name,
158 'changes': {},
159 'result': True,
160 'comment': 'User "{0}" will be updated'.format(name)}
161
162 _api_version(profile=profile, **connection_args)
163
164 if project and not tenant:
165 tenant = project
166
167 # Validate tenant if set
168 if tenant is not None:
169 tenantdata = __salt__['keystoneng.tenant_get'](name=tenant,
170 profile=profile,
171 **connection_args)
172 if 'Error' in tenantdata:
173 ret['result'] = False
174 ret['comment'] = 'Tenant / project "{0}" does not exist'.format(tenant)
175 return ret
176 tenant_id = tenantdata[tenant]['id']
177 else:
178 tenant_id = None
179
180 # Check if user is already present
181 user = __salt__['keystoneng.user_get'](name=name, profile=profile,
182 **connection_args)
183 if 'Error' not in user:
184
185 change_email = False
186 change_enabled = False
187 change_tenant = False
188 change_password = False
Oleksandr Shyshkoa0b79e22019-02-27 15:02:30 +0000189 change_options = False
Oleg Iurchenko5b1e5322017-10-20 00:29:20 +0300190
191 if user[name].get('email', None) != email:
192 change_email = True
193
194 if user[name].get('enabled', None) != enabled:
195 change_enabled = True
196
197 if tenant and (_TENANT_ID not in user[name] or
198 user[name].get(_TENANT_ID, None) != tenant_id):
199 change_tenant = True
200
201 if (password_reset is True and
202 not __salt__['keystoneng.user_verify_password'](name=name,
203 password=password,
204 profile=profile,
205 **connection_args)):
206 change_password = True
207
Oleksandr Shyshkoa0b79e22019-02-27 15:02:30 +0000208 if options:
209 options_to_update = {option: options[option] for option in options
Vasyl Saienkoaeb4e082019-04-27 09:37:17 +0300210 if (option not in user[name].get('options', {}))
Oleksandr Shyshkoa0b79e22019-02-27 15:02:30 +0000211 or (options[option] != user[name]['options'][option])}
212
213 if len(options_to_update):
214 change_options = True
215
216 if __opts__.get('test') and (change_email or change_enabled or change_tenant or change_password or change_options):
Oleg Iurchenko5b1e5322017-10-20 00:29:20 +0300217 ret['result'] = None
218 ret['comment'] = 'User "{0}" will be updated'.format(name)
219 if change_email is True:
220 ret['changes']['Email'] = 'Will be updated'
221 if change_enabled is True:
222 ret['changes']['Enabled'] = 'Will be True'
223 if change_tenant is True:
224 ret['changes']['Tenant'] = 'Will be added to "{0}" tenant'.format(tenant)
225 if change_password is True:
226 ret['changes']['Password'] = 'Will be updated'
Oleksandr Shyshkoa0b79e22019-02-27 15:02:30 +0000227 if change_options is True:
228 ret['changes']['Options'] = 'Will be updated'
Oleg Iurchenko5b1e5322017-10-20 00:29:20 +0300229 return ret
230
231 ret['comment'] = 'User "{0}" is already present'.format(name)
232
233 if change_email:
234 __salt__['keystoneng.user_update'](name=name, email=email, profile=profile, **connection_args)
235 ret['comment'] = 'User "{0}" has been updated'.format(name)
236 ret['changes']['Email'] = 'Updated'
237
238 if change_enabled:
239 __salt__['keystoneng.user_update'](name=name, enabled=enabled, profile=profile, **connection_args)
240 ret['comment'] = 'User "{0}" has been updated'.format(name)
241 ret['changes']['Enabled'] = 'Now {0}'.format(enabled)
242
243 if change_tenant:
244 __salt__['keystoneng.user_update'](name=name, tenant=tenant, profile=profile, **connection_args)
245 ret['comment'] = 'User "{0}" has been updated'.format(name)
246 ret['changes']['Tenant'] = 'Added to "{0}" tenant'.format(tenant)
247
248 if change_password:
249 __salt__['keystoneng.user_password_update'](name=name, password=password, profile=profile,
250 **connection_args)
251 ret['comment'] = 'User "{0}" has been updated'.format(name)
252 ret['changes']['Password'] = 'Updated'
253
Oleksandr Shyshkoa0b79e22019-02-27 15:02:30 +0000254 if change_options:
255 __salt__['keystoneng.user_update'](name=name, options=options_to_update, profile=profile, **connection_args)
256 ret['comment'] = 'Options has been updated'
257 ret['changes']['Options'] = options_to_update
258
Oleg Iurchenko5b1e5322017-10-20 00:29:20 +0300259 if roles:
260 for tenant in roles:
261 args = dict({'user_name': name, 'tenant_name':
262 tenant, 'profile': profile}, **connection_args)
263 tenant_roles = __salt__['keystoneng.user_role_list'](**args)
264 for role in roles[tenant]:
265 if role not in tenant_roles:
266 if __opts__.get('test'):
267 ret['result'] = None
268 ret['comment'] = 'User roles "{0}" will been updated'.format(name)
269 return ret
270 addargs = dict({'user': name, 'role': role,
271 'tenant': tenant,
272 'profile': profile},
273 **connection_args)
274 newrole = __salt__['keystoneng.user_role_add'](**addargs)
275 if 'roles' in ret['changes']:
276 ret['changes']['roles'].append(newrole)
277 else:
278 ret['changes']['roles'] = [newrole]
279 roles_to_remove = list(set(tenant_roles) - set(roles[tenant]))
280 for role in roles_to_remove:
281 if __opts__.get('test'):
282 ret['result'] = None
283 ret['comment'] = 'User roles "{0}" will been updated'.format(name)
284 return ret
285 addargs = dict({'user': name, 'role': role,
286 'tenant': tenant,
287 'profile': profile},
288 **connection_args)
289 oldrole = __salt__['keystoneng.user_role_remove'](**addargs)
290 if 'roles' in ret['changes']:
291 ret['changes']['roles'].append(oldrole)
292 else:
293 ret['changes']['roles'] = [oldrole]
294 else:
295 # Create that user!
296 if __opts__.get('test'):
297 ret['result'] = None
298 ret['comment'] = 'Keystone user "{0}" will be added'.format(name)
299 ret['changes']['User'] = 'Will be created'
300 return ret
301 __salt__['keystoneng.user_create'](name=name,
302 password=password,
303 email=email,
304 tenant_id=tenant_id,
305 enabled=enabled,
Oleksandr Shyshkoa0b79e22019-02-27 15:02:30 +0000306 options=options,
Oleg Iurchenko5b1e5322017-10-20 00:29:20 +0300307 profile=profile,
308 **connection_args)
309 if roles:
310 for tenant in roles:
311 for role in roles[tenant]:
312 __salt__['keystoneng.user_role_add'](user=name,
313 role=role,
314 tenant=tenant,
315 profile=profile,
316 **connection_args)
317 ret['comment'] = 'Keystone user {0} has been added'.format(name)
318 ret['changes']['User'] = 'Created'
319
320 return ret
321
322
323def user_absent(name, profile=None, **connection_args):
324 '''
325 Ensure that the keystone user is absent.
326
327 name
328 The name of the user that should not exist
329 '''
330 ret = {'name': name,
331 'changes': {},
332 'result': True,
333 'comment': 'User "{0}" is already absent'.format(name)}
334
335 # Check if user is present
336 user = __salt__['keystoneng.user_get'](name=name, profile=profile,
337 **connection_args)
338 if 'Error' not in user:
339 if __opts__.get('test'):
340 ret['result'] = None
341 ret['comment'] = 'User "{0}" will be deleted'.format(name)
342 return ret
343 # Delete that user!
344 __salt__['keystoneng.user_delete'](name=name, profile=profile,
345 **connection_args)
346 ret['comment'] = 'User "{0}" has been deleted'.format(name)
347 ret['changes']['User'] = 'Deleted'
348
349 return ret
350
351
352def tenant_present(name, description=None, enabled=True, profile=None,
353 **connection_args):
354 '''
355 Ensures that the keystone tenant exists
356
357 name
358 The name of the tenant to manage
359
360 description
361 The description to use for this tenant
362
363 enabled
364 Availability state for this tenant
365 '''
366 ret = {'name': name,
367 'changes': {},
368 'result': True,
369 'comment': 'Tenant / project "{0}" already exists'.format(name)}
370
371 _api_version(profile=profile, **connection_args)
372
373 # Check if tenant is already present
374 tenant = __salt__['keystoneng.tenant_get'](name=name,
375 profile=profile,
376 **connection_args)
377
378 if 'Error' not in tenant:
379 if tenant[name].get('description', None) != description:
380 if __opts__.get('test'):
381 ret['result'] = None
382 ret['comment'] = 'Tenant / project "{0}" will be updated'.format(name)
383 ret['changes']['Description'] = 'Will be updated'
384 return ret
385 __salt__['keystoneng.tenant_update'](name=name,
386 description=description,
387 enabled=enabled,
388 profile=profile,
389 **connection_args)
390 ret['comment'] = 'Tenant / project "{0}" has been updated'.format(name)
391 ret['changes']['Description'] = 'Updated'
392 if tenant[name].get('enabled', None) != enabled:
393 if __opts__.get('test'):
394 ret['result'] = None
395 ret['comment'] = 'Tenant / project "{0}" will be updated'.format(name)
396 ret['changes']['Enabled'] = 'Will be {0}'.format(enabled)
397 return ret
398 __salt__['keystoneng.tenant_update'](name=name,
399 description=description,
400 enabled=enabled,
401 profile=profile,
402 **connection_args)
403 ret['comment'] = 'Tenant / project "{0}" has been updated'.format(name)
404 ret['changes']['Enabled'] = 'Now {0}'.format(enabled)
405 else:
406 if __opts__.get('test'):
407 ret['result'] = None
408 ret['comment'] = 'Tenant / project "{0}" will be added'.format(name)
409 ret['changes']['Tenant'] = 'Will be created'
410 return ret
411 # Create tenant
412 if _OS_IDENTITY_API_VERSION > 2:
413 created = __salt__['keystoneng.project_create'](name=name, domain='default', description=description,
414 enabled=enabled, profile=profile, **connection_args)
415 else:
416 created = __salt__['keystoneng.tenant_create'](name=name, description=description, enabled=enabled,
417 profile=profile, **connection_args)
Oleg Iurchenkofd0f5f32018-02-07 15:44:08 +0200418 # If tenant has been created succesfully 'created' is:
419 # {u'test_tenant3': {'enabled': True, 'NAME_ATTR': 'name', 'HUMAN_ID': False, 'name': u'test_tenant3', 'id': u'0a5f319f8a794bfc9045746069c76fd8'}}
420 # If tenant is not created:
421 # {'Error': 'Unable to resolve tenant id'}
422 if 'Error' in created and isinstance(created['Error'], six.string_types):
423 ret['result'] = False
424 ret['comment'] = 'Cannot create tenant / project "{0}"'.format(name)
425 else:
426 ret['changes']['Tenant'] = 'Created'
427 ret['result'] = True
428 ret['comment'] = 'Tenant / project "{0}" has been added'.format(name)
Oleg Iurchenko5b1e5322017-10-20 00:29:20 +0300429 return ret
430
431
432def tenant_absent(name, profile=None, **connection_args):
433 '''
434 Ensure that the keystone tenant is absent.
435
436 name
437 The name of the tenant that should not exist
438 '''
439 ret = {'name': name,
440 'changes': {},
441 'result': True,
442 'comment': 'Tenant / project "{0}" is already absent'.format(name)}
443
444 # Check if tenant is present
445 tenant = __salt__['keystoneng.tenant_get'](name=name,
446 profile=profile,
447 **connection_args)
448 if 'Error' not in tenant:
449 if __opts__.get('test'):
450 ret['result'] = None
451 ret['comment'] = 'Tenant / project "{0}" will be deleted'.format(name)
452 return ret
453 # Delete tenant
454 __salt__['keystoneng.tenant_delete'](name=name, profile=profile,
455 **connection_args)
456 ret['comment'] = 'Tenant / project "{0}" has been deleted'.format(name)
457 ret['changes']['Tenant/Project'] = 'Deleted'
458
459 return ret
460
461
462def project_present(name, description=None, enabled=True, profile=None,
463 **connection_args):
464 '''
465 Ensures that the keystone project exists
466 Alias for tenant_present from V2 API to fulfill
467 V3 API naming convention.
468
469 .. versionadded:: 2016.11.0
470
471 name
472 The name of the project to manage
473
474 description
475 The description to use for this project
476
477 enabled
478 Availability state for this project
479
480 .. code-block:: yaml
481
482 nova:
483 keystoneng.project_present:
484 - enabled: True
485 - description: 'Nova Compute Service'
486
487 '''
488
489 return tenant_present(name, description=description, enabled=enabled, profile=profile,
490 **connection_args)
491
492
493def project_absent(name, profile=None, **connection_args):
494 '''
495 Ensure that the keystone project is absent.
496 Alias for tenant_absent from V2 API to fulfill
497 V3 API naming convention.
498
499 .. versionadded:: 2016.11.0
500
501 name
502 The name of the project that should not exist
503
504 .. code-block:: yaml
505
506 delete_nova:
507 keystoneng.project_absent:
508 - name: nova
509 '''
510
511 return tenant_absent(name, profile=profile, **connection_args)
512
513
514def role_present(name, profile=None, **connection_args):
515 ''''
516 Ensures that the keystone role exists
517
518 name
519 The name of the role that should be present
520 '''
521 ret = {'name': name,
522 'changes': {},
523 'result': True,
524 'comment': 'Role "{0}" already exists'.format(name)}
525
526 # Check if role is already present
527 role = __salt__['keystoneng.role_get'](name=name, profile=profile,
528 **connection_args)
529
530 if 'Error' not in role:
531 return ret
532 else:
533 if __opts__.get('test'):
534 ret['result'] = None
535 ret['comment'] = 'Role "{0}" will be added'.format(name)
536 return ret
537 # Create role
538 __salt__['keystoneng.role_create'](name, profile=profile,
539 **connection_args)
540 ret['comment'] = 'Role "{0}" has been added'.format(name)
541 ret['changes']['Role'] = 'Created'
542 return ret
543
544
545def role_absent(name, profile=None, **connection_args):
546 '''
547 Ensure that the keystone role is absent.
548
549 name
550 The name of the role that should not exist
551 '''
552 ret = {'name': name,
553 'changes': {},
554 'result': True,
555 'comment': 'Role "{0}" is already absent'.format(name)}
556
557 # Check if role is present
558 role = __salt__['keystoneng.role_get'](name=name, profile=profile,
559 **connection_args)
560 if 'Error' not in role:
561 if __opts__.get('test'):
562 ret['result'] = None
563 ret['comment'] = 'Role "{0}" will be deleted'.format(name)
564 return ret
565 # Delete role
566 __salt__['keystoneng.role_delete'](name=name, profile=profile,
567 **connection_args)
568 ret['comment'] = 'Role "{0}" has been deleted'.format(name)
569 ret['changes']['Role'] = 'Deleted'
570
571 return ret
572
573
574def service_present(name, service_type, description=None,
575 profile=None, **connection_args):
576 '''
577 Ensure service present in Keystone catalog
578
579 name
580 The name of the service
581
582 service_type
583 The type of Openstack Service
584
585 description (optional)
586 Description of the service
587 '''
588 ret = {'name': name,
589 'changes': {},
590 'result': True,
591 'comment': 'Service "{0}" already exists'.format(name)}
592
593 # Check if service is already present
594 role = __salt__['keystoneng.service_get'](name=name,
595 profile=profile,
596 **connection_args)
597
598 if 'Error' not in role:
599 return ret
600 else:
601 if __opts__.get('test'):
602 ret['result'] = None
603 ret['comment'] = 'Service "{0}" will be added'.format(name)
604 return ret
605 # Create service
606 __salt__['keystoneng.service_create'](name, service_type,
607 description,
608 profile=profile,
609 **connection_args)
610 ret['comment'] = 'Service "{0}" has been added'.format(name)
611 ret['changes']['Service'] = 'Created'
612
613 return ret
614
615
616def service_absent(name, profile=None, **connection_args):
617 '''
618 Ensure that the service doesn't exist in Keystone catalog
619
620 name
621 The name of the service that should not exist
622 '''
623 ret = {'name': name,
624 'changes': {},
625 'result': True,
626 'comment': 'Service "{0}" is already absent'.format(name)}
627
628 # Check if service is present
629 role = __salt__['keystoneng.service_get'](name=name,
630 profile=profile,
631 **connection_args)
632 if 'Error' not in role:
633 if __opts__.get('test'):
634 ret['result'] = None
635 ret['comment'] = 'Service "{0}" will be deleted'.format(name)
636 return ret
637 # Delete service
638 __salt__['keystoneng.service_delete'](name=name,
639 profile=profile,
640 **connection_args)
641 ret['comment'] = 'Service "{0}" has been deleted'.format(name)
642 ret['changes']['Service'] = 'Deleted'
643
644 return ret
645
646
647def endpoint_present(name,
648 publicurl=None,
649 internalurl=None,
650 adminurl=None,
651 region=None,
652 profile=None,
653 url=None,
654 interface=None, **connection_args):
655 '''
656 Ensure the specified endpoints exists for service
657
658 name
659 The Service name
660
661 publicurl
662 The public url of service endpoint (for V2 API)
663
664 internalurl
665 The internal url of service endpoint (for V2 API)
666
667 adminurl
668 The admin url of the service endpoint (for V2 API)
669
670 region
671 The region of the endpoint
672
673 url
674 The endpoint URL (for V3 API)
675
676 interface
677 The interface type, which describes the visibility
678 of the endpoint. (for V3 API)
679
680 '''
681 ret = {'name': name,
682 'changes': {},
683 'result': True,
684 'comment': ''}
685 endpoint = __salt__['keystoneng.endpoint_get'](name, region,
686 profile=profile,
687 interface=interface,
688 **connection_args)
689
690 def _changes(desc):
691 return ret.get('comment', '') + desc + '\n'
692
693 def _create_endpoint():
694 if _OS_IDENTITY_API_VERSION > 2:
695 ret['changes'] = __salt__['keystoneng.endpoint_create'](
696 name,
697 region=region,
698 url=url,
699 interface=interface,
700 profile=profile,
701 **connection_args)
702 else:
703 ret['changes'] = __salt__['keystoneng.endpoint_create'](
704 name,
705 region=region,
706 publicurl=publicurl,
707 adminurl=adminurl,
708 internalurl=internalurl,
709 profile=profile,
710 **connection_args)
711
712 if endpoint and 'Error' not in endpoint and endpoint.get('region') == region:
713
714 if _OS_IDENTITY_API_VERSION > 2:
715
716 change_url = False
717 change_interface = False
718
719 if endpoint.get('url', None) != url:
720 ret['comment'] = _changes('URL changes from "{0}" to "{1}"'.format(endpoint.get('url', None), url))
721 change_url = True
722
723 if endpoint.get('interface', None) != interface:
724 ret['comment'] = _changes('Interface changes from "{0}" to "{1}"'.format(endpoint.get('interface', None), interface))
725 change_interface = True
726
727 if __opts__.get('test') and (change_url or change_interface):
728 ret['result'] = None
729 ret['changes']['Endpoint'] = 'Will be updated'
730 ret['comment'] += 'Endpoint for service "{0}" will be updated'.format(name)
731 return ret
732
733 if change_url:
734 ret['changes']['url'] = url
735
736 if change_interface:
737 ret['changes']['interface'] = interface
738
739 else:
740 change_publicurl = False
741 change_adminurl = False
742 change_internalurl = False
743
744 if endpoint.get('publicurl', None) != publicurl:
745 change_publicurl = True
746
747 ret['comment'] = _changes('Public URL changes from "{0}" to "{1}"'.format(
748 endpoint.get('publicurl', None), publicurl)
749 )
750
751 if endpoint.get('adminurl', None) != adminurl:
752 change_adminurl = True
753 ret['comment'] = _changes('Admin URL changes from "{0}" to "{1}"'.format(
754 endpoint.get('adminurl', None), adminurl)
755 )
756
757 if endpoint.get('internalurl', None) != internalurl:
758 change_internalurl = True
759 ret['comment'] = _changes(
760 'Internal URL changes from "{0}" to "{1}"'.format(
761 endpoint.get('internalurl', None),
762 internalurl
763 )
764 )
765
766 if __opts__.get('test') and (change_publicurl or change_adminurl or change_internalurl):
767 ret['result'] = None
768 ret['comment'] += 'Endpoint for service "{0}" will be updated'.format(name)
769 ret['changes']['Endpoint'] = 'Will be updated'
770 return ret
771
772 if change_publicurl:
773 ret['changes']['publicurl'] = publicurl
774
775 if change_adminurl:
776 ret['changes']['adminurl'] = adminurl
777
778 if change_internalurl:
779 ret['changes']['internalurl'] = internalurl
780
781 if ret['comment']: # changed
782 __salt__['keystoneng.endpoint_delete'](name, region, profile=profile, interface=interface, **connection_args)
783 _create_endpoint()
784 ret['comment'] += 'Endpoint for service "{0}" has been updated'.format(name)
785
786 else:
787 # Add new endpoint
788 if __opts__.get('test'):
789 ret['result'] = None
790 ret['changes']['Endpoint'] = 'Will be created'
791 ret['comment'] = 'Endpoint for service "{0}" will be added'.format(name)
792 return ret
793 _create_endpoint()
794 ret['comment'] = 'Endpoint for service "{0}" has been added'.format(name)
795
796 if ret['comment'] == '': # => no changes
797 ret['comment'] = 'Endpoint for service "{0}" already exists'.format(name)
798 return ret
799
800
801def endpoint_absent(name, region=None, profile=None, interface=None, **connection_args):
802 '''
803 Ensure that the endpoint for a service doesn't exist in Keystone catalog
804
805 name
806 The name of the service whose endpoints should not exist
807
808 region (optional)
809 The region of the endpoint. Defaults to ``RegionOne``.
810
811 interface
812 The interface type, which describes the visibility
813 of the endpoint. (for V3 API)
814 '''
815 ret = {'name': name,
816 'changes': {},
817 'result': True,
818 'comment': 'Endpoint for service "{0}"{1} is already absent'.format(name,
819 ', interface "{0}",'.format(interface) if interface is not None else '')}
820
821 # Check if service is present
822 endpoint = __salt__['keystoneng.endpoint_get'](name, region,
823 profile=profile,
824 interface=interface,
825 **connection_args)
Oleksandr Shyshkoc0a50e42018-12-19 19:20:40 +0200826 if endpoint and 'Error' in endpoint:
Oleg Iurchenko5b1e5322017-10-20 00:29:20 +0300827 return ret
828 else:
829 if __opts__.get('test'):
830 ret['result'] = None
831 ret['comment'] = 'Endpoint for service "{0}" will be deleted'.format(name)
832 return ret
833 # Delete service
834 __salt__['keystoneng.endpoint_delete'](name, region,
835 profile=profile,
836 interface=interface,
837 **connection_args)
838 ret['comment'] = 'Endpoint for service "{0}"{1} has been deleted'.format(name,
839 ', interface "{0}",'.format(interface) if interface is not None else '')
840 ret['changes']['endpoint'] = 'Deleted'
841 return ret