Bring in domains state

Change-Id: I0d8009bb2b295c807f83a290f35a1d962c832624
diff --git a/_states/keystonev3.py b/_states/keystonev3.py
index f9012cf..55d14e9 100644
--- a/_states/keystonev3.py
+++ b/_states/keystonev3.py
@@ -486,6 +486,65 @@
     return _deleted(name, 'role')
 
 
+def domain_present(name, cloud_name, **kwargs):
+
+    domains = _keystonev3_call(
+        'domain_list', name=name, cloud_name=cloud_name)['domains']
+
+    if not domains:
+        try:
+            resp = _keystonev3_call(
+                'domain_create', name=name, cloud_name=cloud_name, **kwargs
+            )
+        except Exception as e:
+            log.error('Keystone domain create failed with {}'.format(e))
+            return _create_failed(name, 'domain')
+        return _created(name, 'domain', resp)
+    elif len(domains) == 1:
+        exact_domain = domains[0]
+        domain_id = exact_domain['id']
+        changable = ('tags', 'enabled', 'description')
+        to_update = {}
+
+        for key in kwargs:
+            if (key in changable and (key not in exact_domain or
+                                      kwargs[key] != exact_domain[key])):
+                to_update[key] = kwargs[key]
+
+        if to_update:
+            try:
+                resp = _keystonev3_call(
+                    'domain_update', domain_id=domain_id,
+                    cloud_name=cloud_name, **to_update
+                )
+            except Exception as e:
+                log.error('Keystone domain update failed with {}'.format(e))
+                return _update_failed(name, 'domain')
+            return _updated(name, 'domain', resp)
+        else:
+            return _no_changes(name, 'domain')
+    else:
+        return _find_failed(name, 'domain')
+
+
+def domain_absent(name, cloud_name):
+    try:
+        _keystonev3_call('domain_get_details',
+                         domain_id=name, cloud_name=cloud_name)
+    except Exception as e:
+        if 'ResourceNotFound' in repr(e):
+            return _absent(name, 'domain')
+        else:
+            log.error('Failed to get a domain {}'.format(e))
+            return _find_failed(name, 'domain')
+    try:
+        _keystonev3_call('domain_delete', domain_id=name,
+                         cloud_name=cloud_name)
+    except Exception:
+        return _delete_failed(name, 'domain')
+    return _deleted(name, 'domain')
+
+
 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 ea174b2..b91ad6d 100644
--- a/keystone/client/resources/v3.sls
+++ b/keystone/client/resources/v3.sls
@@ -55,7 +55,20 @@
 
 {% for domain_name, domain  in resources.get('domains', {}).iteritems() %}
 
-{#- TODO: Add domain support #}
+keystone_domain_{{ domain_name }}:
+  keystonev3.domain_present:
+    - cloud_name: {{ domain.get('cloud_name', resources.cloud_name) }}
+    - name: {{ domain_name }}
+    {%- if domain.description is defined %}
+    - description: {{ domain.description }}
+    {%- endif %}
+    {%- if domain.enabled is defined %}
+    - enabled: {{ domain.enabled }}
+    {%- endif %}
+    {%- if domain.tags is defined %}
+    - tags: {{ domain.tags }}
+    {%- endif %}
+
     {%- for project_name, project in domain.get('projects', {}).iteritems() %}
 keystone_project_{{ project_name }}:
   keystonev3.project_present: