Преглед на файлове

Added requirements.yml and galaxy-roles to manage and install third party roles

Till Klocke преди 9 години
родител
ревизия
16dad0839c
променени са 51 файла, в които са добавени 1467 реда и са изтрити 0 реда
  1. 3 0
      galaxy-roles/usermanage/.gitignore
  2. 53 0
      galaxy-roles/usermanage/.kitchen.yml
  3. 22 0
      galaxy-roles/usermanage/.travis.yml
  4. 12 0
      galaxy-roles/usermanage/Gemfile
  5. 79 0
      galaxy-roles/usermanage/README.md
  6. 30 0
      galaxy-roles/usermanage/defaults/main.yml
  7. 157 0
      galaxy-roles/usermanage/library/load_user_files.py
  8. 201 0
      galaxy-roles/usermanage/library/usersdb.py
  9. 1 0
      galaxy-roles/usermanage/meta/.galaxy_install_info
  10. 11 0
      galaxy-roles/usermanage/meta/main.yml
  11. 40 0
      galaxy-roles/usermanage/tasks/debug.yml
  12. 7 0
      galaxy-roles/usermanage/tasks/groups.yml
  13. 15 0
      galaxy-roles/usermanage/tasks/main.yml
  14. 7 0
      galaxy-roles/usermanage/tasks/per_user_group.yml
  15. 23 0
      galaxy-roles/usermanage/tasks/sources.yml
  16. 31 0
      galaxy-roles/usermanage/tasks/users.yml
  17. 4 0
      galaxy-roles/usermanage/templates/debug_users.j2
  18. 22 0
      galaxy-roles/usermanage/test/.kitchen.yml
  19. 2 0
      galaxy-roles/usermanage/test/ansible.cfg
  20. 13 0
      galaxy-roles/usermanage/test/application/advanced.yml
  21. 31 0
      galaxy-roles/usermanage/test/application/advanced_var_server_db.yml
  22. 49 0
      galaxy-roles/usermanage/test/application/advanced_var_user_db.yml
  23. 10 0
      galaxy-roles/usermanage/test/application/group.yml
  24. 17 0
      galaxy-roles/usermanage/test/application/group_var_group_db.yml
  25. 15 0
      galaxy-roles/usermanage/test/application/multi_source_files.yml
  26. 12 0
      galaxy-roles/usermanage/test/application/simple.yml
  27. 36 0
      galaxy-roles/usermanage/test/application/simple_var_user_db.yml
  28. 26 0
      galaxy-roles/usermanage/test/application/source_databag.yml
  29. 13 0
      galaxy-roles/usermanage/test/application/source_files.yml
  30. 14 0
      galaxy-roles/usermanage/test/application/team.yml
  31. 63 0
      galaxy-roles/usermanage/test/application/team_var_db.yml
  32. 19 0
      galaxy-roles/usermanage/test/application/user_source/databag/bbreezer.json
  33. 19 0
      galaxy-roles/usermanage/test/application/user_source/databag/ebacardi.json
  34. 15 0
      galaxy-roles/usermanage/test/application/user_source/databag/fbacardi.json
  35. 16 0
      galaxy-roles/usermanage/test/application/user_source/mutli/databag/bbreezer.json
  36. 15 0
      galaxy-roles/usermanage/test/application/user_source/mutli/databag/strtois.json
  37. 6 0
      galaxy-roles/usermanage/test/application/user_source/mutli/yaml/user1_yaml.yml
  38. 6 0
      galaxy-roles/usermanage/test/application/user_source/yaml&json/user1_yaml.yml
  39. 5 0
      galaxy-roles/usermanage/test/application/user_source/yaml&json/user2_yaml.yml
  40. 10 0
      galaxy-roles/usermanage/test/application/user_source/yaml&json/user3_json.json
  41. 32 0
      galaxy-roles/usermanage/test/integration/advanced/serverspec/test_spec.rb
  42. 24 0
      galaxy-roles/usermanage/test/integration/group/serverspec/test_spec.rb
  43. 19 0
      galaxy-roles/usermanage/test/integration/multi-source-files/serverspec/test_spec.rb
  44. 40 0
      galaxy-roles/usermanage/test/integration/simple/serverspec/test_spec.rb
  45. 35 0
      galaxy-roles/usermanage/test/integration/source-databag/serverspec/test_spec.rb
  46. 21 0
      galaxy-roles/usermanage/test/integration/source-files/serverspec/test_spec.rb
  47. 46 0
      galaxy-roles/usermanage/test/integration/team/serverspec/test_spec.rb
  48. 1 0
      galaxy-roles/usermanage/test/local.ini
  49. 18 0
      galaxy-roles/usermanage/test/run_vagrant_kitchen.sh
  50. 98 0
      galaxy-roles/usermanage/test/travis_run.py
  51. 3 0
      requirements.yml

+ 3 - 0
galaxy-roles/usermanage/.gitignore

@@ -0,0 +1,3 @@
+.kitchen/
+.kitchen.local.yml
+test/ansible_output

+ 53 - 0
galaxy-roles/usermanage/.kitchen.yml

@@ -0,0 +1,53 @@
+---
+driver                 :
+    name               : localhost
+
+provisioner:
+    name               : ansible_push
+    verbose            : "vvvv"
+    ansible_config     : "test/ansible.cfg"
+    idempotency_test   : True
+
+
+platforms:
+    - name                      : travis
+      provisioner               :
+        raw_arguments           : "-c local --ask-sudo-pass"
+        extra_vars              : 
+          xxxxx               : "hxx"
+
+suites:
+  - name            : group
+    provisioner     :
+        playbook    : "test/application/group.yml"
+        extra_vars  : { 'kitchen_connection': 'smart' }
+
+  - name            : simple
+    provisioner     :
+        playbook    : "test/application/simple.yml"
+        extra_vars  : { 'kitchen_connection': 'smart' }
+
+  - name            : advanced
+    provisioner     :
+        playbook    : "test/application/advanced.yml"
+        extra_vars  : { 'kitchen_connection': 'smart' }
+
+  - name            : source-files
+    provisioner     :
+        playbook    : "test/application/source_files.yml"
+        extra_vars  : { 'kitchen_connection': 'smart' }
+
+  - name            : source-databag
+    provisioner     :
+        playbook    : "test/application/source_databag.yml"
+        extra_vars  : { 'kitchen_connection': 'smart' }
+
+  - name            : multi-source-files
+    provisioner     :
+        playbook    : "test/application/multi_source_files.yml"
+        extra_vars  : { 'kitchen_connection': 'smart' }
+
+  - name            : team
+    provisioner     :
+        playbook    : "test/application/team.yml"
+        extra_vars  : { 'kitchen_connection': 'smart' }

+ 22 - 0
galaxy-roles/usermanage/.travis.yml

@@ -0,0 +1,22 @@
+---
+language: python
+python: "2.7"
+
+before_install:
+  # Make sure everything's up to date.
+  - sudo apt-get update -qq
+  - sudo apt-get install -qq python-apt python-pycurl git python-pip ruby ruby-dev bundler build-essential autoconf ruby-dep-selector
+
+install:
+  - sudo pip install ansible
+
+
+script:
+    - cd test
+    - ansible --version
+    - bundle install
+    - bundle exec kitchen test travis
+
+
+after_success:
+    - echo "Success"

+ 12 - 0
galaxy-roles/usermanage/Gemfile

@@ -0,0 +1,12 @@
+source 'https://rubygems.org'
+
+
+group :development do
+  # Use Berkshelf for resolving cookbook dependencies
+  gem 'berkshelf', '~> 3.0'
+
+  gem 'test-kitchen'
+  gem 'kitchen-vagrant'
+  gem 'kitchen-ansiblepush'
+  gem 'kitchen-localhost'
+end

+ 79 - 0
galaxy-roles/usermanage/README.md

@@ -0,0 +1,79 @@
+ansible-usermanage
+===
+
+[![Build Status](https://travis-ci.org/ahelal/ansible-usermanage.svg?branch=master)](https://travis-ci.org/ahelal/ansible-usermanage)
+
+## What
+
+This playbook was developed to manage users, groups, teams and SSH keys in multi node environment.
+It supports two modes *simple and advanced mode*
+
+
+## How
+### Simple Mode
+
+You define your user in a variable *usermanage_usersdb*. You can define that differnetly per host our group.
+
+```yaml
+usermanage_usersdb: 
+  daniels: 
+    comment: "Jack daniels"
+    state: "present"
+    keys: 
+      - key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDLql1khoXEH/pThpLSDwJNBIEHkjrBggjEvRCqCFYvE1Neavc6iuLSzjLdnj74LNrPEjY+xcjAcPmgwxo8+WKpLL7Iy8e9IGH3lwB05x9jfnw2H1ZRnZZxF+wV/ei/vfCmRyt2cqv+DLomg18RDTnyTk2pvSEvL0xkRn5QRbzxqbnB+9xmItTjdtq/ZDYRgFYn2ZPfokFyyr3KpwpK0gNcpFhCF94CvExKpu6SFPTv+ERnFvHEN9d8SlzwkyCP4yqrfOjFuVUuZf2FtAkDx0d4cXo0i7VUM/hOthUNFpmljZLhkxafPxwp50Q/xRe7MvDQMrEPGPZ/pubOwzqVmMWH"
+      - key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCxAqbTlltSFlRY+gQyAx3j0W+WDnahZYbECAXiwNqAHG7PP8GSEDVkfZTkJdlu9PoB/B3nW2R/Q3//IxUfzRsUnjUzl0WXbhz331n5bHtgJlg82MGqwbNjN0yMR/GB4pQKeExYOLKi/7jI/wkOAJ4X9Bv9skEK/mHAWWPrBf/5C5qWUOxVC1+he3iaU+LSbiL6uiNs8S49fiGno8tBkBFgth+9gqdCLRAFVe2dzJJK1nSQTffHCs12pJs2S3yBD9KkUQJO51tByP4qO3549iwLo8hQnqtFULMpL+NN5Muk1bFZ2jW+0Sri1bhVS58llZCuoENZsLf/+xejbfwJAk4h"
+        key_options: no-port-forwarding
+  gin: 
+    comment: "Gordons Gin"
+    keys: 
+      - key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCcoo+eU8+k7QYpKbZwOQwiMpeklQcmEyLTsJr0RLTeqsHkIh8rFWyMZURDZ5pgEGo3iXZD+dqM28agy2Pw68/V0wht/9n0PjmUVZgkWIas162w3vZrJENDi8wAo4ojQJf0lZf63K8AxoB12fF+QdR7jfTLrz2bCxv9XaHKm7nYGtRO0f8ETgvwpIS2jN0mPAD7qnCFvLtbaxd/UzsQS5M8Au42+9zdn78Atm7gtKY9uR5U1Jwrop8KipXf0wAtMo39Xc9P8hGbYGA1jkbcG2x1LI7G9L+PddxeZjpkW2Uv559YJDRjBJfJAfp6K4HGV5uXITSMVDY9KBYvepolrlul"
+    shell: /bin/zsh
+    uid: 2300
+  vodaka: 
+    comment: "Savvy Vodka"
+    state: "absent"
+    keys: 
+      - key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC2Pq3M7AgeBjmNII6HGsKd2uaXFIfaljpNg1Rf6y3iGP84wC82bMfZTSIhnzJ4qwHj7Bzn8oiMmqtyeGcmEwLXm5f7mk3lj9NmxUEfbuWsPoSX4VHIney0F2cjrYRAHua8vZ50OrqYvRaBNttx+pCsub/Kw/t91PQvz7s5ML12DfhlfbE5f/g+ZrKHBxsn6Vw0VqN1Cx5cecaN+9NbdwTV25/RVsXC6v9TQlIqWR+znt4ZVxUSCTAbGc51tmauoleZee2XBkAO7xmJ7zPQEndhErq/zm0euZGx1xGIjQ7dVBK8t1ah2UdBS4pSHgjhDulo0hr4gIubQ0FSV+8cWCNN"
+```
+
+Basically **usermanage_usersdb** is a dictionary of users each user will accept all options defined in [user ansible module](http://docs.ansible.com/user_module.html)
+
+A special argument **keys** which is a list of keys that will be created for that user, each key can accept all options defined in [authorized key module](http://docs.ansible.com/authorized_key_module.html)
+
+### Group Management
+To manage groups you can define **usermanage_groupsdb** as a **list**. You must define atleast the *name* of group and optional state,gid and system.
+
+```yaml
+usermanage_groupsdb  :
+      - name         : "group1"
+        state        : "present"
+        gid          : "5000"
+        system       : "true"
+
+      - name         : "group2"
+        state        : "present"
+        gid          : "5001"
+        system       : "false"
+
+      - name         : "group3"
+
+      - name         : "group4"
+        state        : "absent"
+```
+
+Some *nix system does not support creating the primary group for each user with the same name. If you want to enable that functionality for systems that does not support it. just enable that flag.
+```yaml
+usermanage_create_per_user_group            : true 
+```
+
+### Users DB Sources
+** TODO **
+
+### Advanced mode
+ToDo document
+
+### teams
+ToDo document
+
+### Private Key
+ToDo document

+ 30 - 0
galaxy-roles/usermanage/defaults/main.yml

@@ -0,0 +1,30 @@
+---
+# You should override those variables, Have a look at readme.md for examples
+#usermanage_usersdb                          :
+#usermanage_users_publickey                  :
+#usermanage_servers                          :
+#usermanage_teamsdb                          :
+#usermanage_groupsdb                         :
+###
+usermanage_user_source_files                :       # if you want to include a yaml&json/json file or chef databag
+usermanage_user_source_databag              : false # Is this user_source opscode chef user databag
+usermanage_default_home_dir_prefix          : "/home" ## TODO: not working yet
+
+usermanage_create_per_user_group            : false   # Create a group for every user and make that their primary group (Ubuntu does not need that)
+usermanage_default_group                    : false  # If your not creating a per user group and want default primary group. set the group name here i.e. "ops" or "dev"
+
+## WARNING Debug will deploy a text file on target server and dumps variable file
+## /tmp/debugUser.{{inventory_hostname}}-{{item.account}}
+## if you want to use debug use the limit to one server than delete the tempfile
+## for more info look at the debug users task in the role
+usermanage_debug                            : false
+usermanage_debug_level                      : 2  # support 1 or 2 for now
+usermanage_debug_dir                        : /tmp/usermanage_debug/
+# var_dir
+usermanage_source_facts                     : "user_files"
+
+# Temp solution to with_items and when condition issue
+default_temp_solution                       :
+                                               - user: "x"
+
+usermanage_priv_key_suffix                  : ".ssh/id_rsa"

+ 157 - 0
galaxy-roles/usermanage/library/load_user_files.py

@@ -0,0 +1,157 @@
+#!/usr/bin/python
+
+
+class LoadVarDir(object):
+    def __init__(self, module):
+        self.module = module
+        self.path = self.module.params["path"]
+        self.fact = self.module.params["fact"]
+        self.data_bag = self.module.params["databag"]
+        # Chef => Ansible mapping
+        self.mapping = {"comment": "comment",
+                        "force": "force",
+                        "gid": "group",
+                        "groups": "groups",
+                        "home": "home",
+                        "manage_home": "move_home",
+                        "non_unique": "non_unique",
+                        "password": "password",
+                        "shell": "shell",
+                        "action": "state",
+                        "system": "system",
+                        "uid": "uid",
+                        "ssh_keys":  "keys"
+                        }
+        self.file_data = {}
+
+    def parse_yaml(self, data, path_hint=None):
+        ''' convert a yaml string to a data structure.  Also supports JSON, ssssssh!!!'''
+
+        stripped_data = data.lstrip()
+        loaded = None
+        if stripped_data.startswith("{") or stripped_data.startswith("["):
+            # since the line starts with { or [ we can infer this is a JSON document.
+            try:
+                loaded = json.loads(data)
+            except ValueError, ve:
+                if path_hint:
+                    self.module.fail_json(msg=path_hint + ": " + str(ve))
+                else:
+                    self.module.fail_json(msg=str(ve))
+        else:
+            # else this is pretty sure to be a YAML document
+            loaded = yaml.load(data, Loader=Loader)
+        return loaded
+
+    def parse_yaml_from_file(self, path, vault_password=None):
+        ''' convert a yaml file to a data structure '''
+        data = None
+        try:
+            data = open(path).read()
+        except IOError:
+            self.module.fail_json(msg="file could not read: %s" % path)
+
+        try:
+            return self.parse_yaml(data, path_hint=path)
+        except yaml.YAMLError, exc:
+            self.module.fail_json(msg="Syntax error in yaml file '%s'" % path)
+
+    def main(self):
+        self._check_variable()
+        result = {"changed": False, "msg": "Hi", self.fact: self.file_data}
+        self.module.exit_json(**result)
+
+    def _read_from_file(self, file_path, databag):
+        data = self.parse_yaml_from_file(file_path, vault_password="")
+        if data and type(data) != dict:
+            self.module.fail_json(msg="%s must be stored as a dictionary/hash".format(file_path))
+        elif data is None:
+            data = {}
+
+        if databag:
+            data = self.convert_chef_user_data_bag(data)
+        return data
+
+    def convert_chef_user_data_bag(self, data):
+        print "data=", data
+        if len(data) == 0:
+            return data
+        else:
+            new_data = {}
+            user_name = data.pop("id")  # Should fail if no id
+            # Loop and only pick item in our map and translate it to ansible ignore the rest
+            for mapping_key in self.mapping:
+                data_bag_item_value = data.pop(mapping_key, None)
+                if data_bag_item_value:
+                    ansible_key = self.mapping.get(mapping_key)
+                    new_data.update({ansible_key: data_bag_item_value})
+            # Check for an action
+            chef_action = new_data.get("state", False)
+            if chef_action:
+                if chef_action == "create":
+                    new_data["state"] = "present"
+                elif chef_action == "remove":
+                    new_data["state"] = "absent"
+            chef_groups = new_data.get("groups", False)
+            primary_group = new_data.get("group", False)
+            if primary_group in chef_groups:
+                # Databag issue for smart-os Issue
+                chef_groups = [group_item for group_item in chef_groups if group_item != primary_group]
+            new_data["groups"] = ",".join(chef_groups)
+            return {user_name: new_data}
+
+    def _check_variable(self):
+        for path_item in self.path:
+
+            try:
+                path = path_item.get("path")
+                path = os.path.expanduser(path)
+                databag = path_item.get("databag", self.data_bag)
+                #print "all={} type={} path={} databag={}".format(path_item, type(path_item), path, databag)
+            except Exception as E:
+                self.module.fail_json(msg="Path is a list but is malformed could not get 'path' got '{}'. Error '{}'".
+                                      format(path_item, E))
+            self._follow_path(path, databag)
+
+    def _follow_path(self, path, databag):
+        if os.path.exists(path):
+            if os.path.isdir(path):
+                for root, dirs, files in os.walk(path, topdown=False):
+                    for filename in files:
+                        self.file_data.update(self._read_from_file(path + "/" + filename, databag))
+            else:
+                self.file_data.update(self._read_from_file(path, databag))
+        else:
+            self.module.fail_json(msg="Failed to find path '{}'.".format(path))
+
+
+def main():
+    module = AnsibleModule(
+        argument_spec=dict(
+            name=dict(default=None, aliases=["path"], required=True, type='list'),
+            fact=dict(default="var_dir", required=False),
+            databag=dict(default=False, type='bool')
+        ),
+        supports_check_mode=False
+    )
+    if not ansible_client_found:
+        module.fail_json(msg="Ansible is not installed or ansible python library is not in path. Can't import 'ansible.utils '")
+    LoadVarDir(module).main()
+
+
+# import module snippets
+from ansible.module_utils.basic import *
+
+
+try:
+    import yaml
+except ImportError:
+    ansible_client_found = False
+else:
+    ansible_client_found = True
+    try:
+        from yaml import CSafeLoader as Loader
+    except ImportError:
+        from yaml import SafeLoader as Loader
+
+main()

+ 201 - 0
galaxy-roles/usermanage/library/usersdb.py

@@ -0,0 +1,201 @@
+#!/usr/bin/python
+
+
+class UsersDB(object):
+    def __init__(self, module):
+        self.module = module
+        self.users_db = self.module.params["usersdb"]
+        self.source_user_db = self.module.params["source_userdb"]
+        # If we have to userdb and source db lets merge them if not
+        if self.users_db and self.source_user_db:
+            self.users_db.update(self.source_user_db)
+        if self.source_user_db and not self.users_db:
+            self.users_db = self.source_user_db
+        if not self.users_db and not self.source_user_db:
+            self.module.fail_json(msg="Missing argument. You must defined either 'usersdb' or 'source_userdb'.")
+
+        self.teams_db = self.module.params["teamsdb"]
+        self.servers_db = self.module.params["serversdb"]
+        # Databases
+        self.lookup_key_db = {}  # used for quick lookup
+        self.expanded_users_db = []  # Used in simple mode
+        self.expanded_users_key_db = []  # Used in simple mode
+        self.expanded_server_db = []  # Used in advanced mode for merged User + server
+        self.expanded_server_key_db = []  # Used in advanced mode
+
+    def _concat_keys(self, user_name, user_keys=None, server_keys=None, user_status=False):
+        # Concat keys (if possible) and update username to keys
+        new_user_keys = []
+        if user_keys and server_keys:
+            for user_key in user_keys:
+                new_user_key = dict(user_key, **server_keys)
+                new_user_key.pop("name", None)
+                new_user_key.pop("user", None)
+                if user_status:
+                    new_user_key.update({"state": "absent"})
+                new_user_keys.append(new_user_key)
+        elif server_keys:
+            # server key is dic
+            server_keys.pop("name", None)
+            new_user_keys = [server_keys]
+        elif user_keys:
+            for user_key in user_keys:
+                new_user_key = user_key
+                new_user_key.pop("user", None)
+                new_user_key.pop("name", None)
+                if user_status:
+                    new_user_key.update({"state": "absent"})
+                new_user_keys.append(new_user_key)
+        else:
+            # TODO: Should work without keys
+            # self.module.fail_json(msg="user '{}' list has no keys defined.".format(user_name))
+            pass
+        return new_user_keys
+
+    def _merge_key(self, user_keys, sever_keys, user_name, user_status=False):
+        # Rules ( no real merge happens )
+        # 1- Default use the user key
+        # 2- if server has defined keys then use those instead no merge here
+        if sever_keys:
+            merged_keys = []
+            for server_key in sever_keys:
+                if "user" in server_key:
+                    user = server_key.pop("user", False)
+                    account_key = self.lookup_key_db.get(user)
+                    user_definition = self.users_db.get(user, {})
+                    if user_definition.get("state", "present") in ("absent", "delete", "deleted", "remove", "removed"):
+                        user_status = "absent"
+                    merged_keys += self._concat_keys(user_name, account_key, server_key, user_status=user_status)
+                elif "team" in server_key:
+                    self.module.fail_json(msg="Team key is not yet implemented")
+                elif "key" in server_key:
+                    merged_keys += self._concat_keys(user_name, server_keys=server_key, user_status=user_status)
+                else:
+                    # TODO: Should work without keys
+                    # self.module.fail_json(msg="user '{}' list has no keys defined.".format(user_name))
+                    pass
+            return merged_keys
+        else:
+            return self._concat_keys(user_name, user_keys=user_keys, user_status=user_status)
+
+    def _merge_user(self, user_name, user_server):
+        user_definition = self.users_db.get(user_name, False)
+
+        if not user_definition:
+            self.module.fail_json(msg="'%s' user has no definition" % user_name)
+
+        if user_definition.get("state", "present") in ("absent", "delete", "deleted", "remove", "removed"):
+            user_status = "absent"
+        else:
+            user_status = False
+
+        # Merge User and Server ( Server has precedence in this case )
+        merged_user = dict(user_definition.items() + user_server.items())
+
+        if user_status:
+            merged_user.update({"state": "absent"})
+        user_server = merged_user
+        user_db_key = self.lookup_key_db.get(user_name, None)
+        user_server_keys = self._merge_key(user_db_key, user_server.get("keys", None), user_name, user_status)
+        # In case of team user dict will not be defined so lets just define anyway
+        user_server.update({"user": user_name})
+
+        # Populate DBs
+        user_server.pop("keys", None)  # Get rid of keys
+        user_server.pop("team", None)  # Get rid of team if exists
+        self.expanded_server_db.append(user_server)
+        if len(user_server_keys) > 0:
+            self.expanded_server_key_db.append({"user": user_name, "keys": user_server_keys})
+
+    def expand_servers(self):
+        # Advanced mode Merges users and servers data
+        # Expand server will overwrite same attributes defined in user db except for state = "absent"
+        for user_server in self.servers_db:
+            team_name = user_server.get("team", False)
+            user_name = user_server.get("user", False) or user_server.get("name", False)
+
+            if user_name:
+                self._merge_user(user_name, user_server)
+            elif team_name:
+                team_definition = self.teams_db.get(team_name, False)
+                if not team_definition:
+                    self.module.fail_json(msg="'%s' team has no definition" % team_name)
+                for user_in_team in team_definition:
+                    self._merge_user(user_in_team, user_server)
+            else:
+                self.module.fail_json(msg="Your server definition has no user or team. Please check your data type. "
+                                          "for '{}'".format(user_server))
+
+    def expand_keys(self, keys, user):
+        # if len(keys) == 0:
+        #     # TODO: Should work without keys
+        #     self.module.fail_json(msg="user '{}' has no keys defined.".format(user))
+
+        user_keys = []
+        # If key is not a list than its a raw key string
+        if not isinstance(keys, list):
+            user_keys.append({"key": keys})
+        else:
+            for key in keys:
+                # Basic syntax check
+                if isinstance(key, basestring) and "ssh-" in key:
+                    user_keys.append({"key": key})
+                elif "key" not in key and "name" not in key:
+                    # TODO: Should work without keys
+                    # self.module.fail_json(msg="user '{}' list has no keys defined.".format(key.keys()))
+                    pass
+                else:
+                    # All is okay just add the dict
+                    user_keys.append(key)
+        return user_keys
+
+    def expand_users(self):
+        # Get User database which is a dic and create expendaded_user_db and key_db
+        # Put keys in right dictionary format
+        for username, user_options in self.users_db.iteritems():
+            # 1- Convert dic to list (servers_db style)
+            user = {"name": username}  # create the account name
+            user.update(user_options)  # update all other option
+            # 2- Compile key
+            unformatted_keys = user_options.get("keys", [])
+            keys = self.expand_keys(unformatted_keys, user)
+            # 3- remove keys from userdb if exists
+            user.pop("keys", None)
+            # 4- Populate DBs
+            self.expanded_users_db.append(user)  # Populate new list user db
+            self.expanded_users_key_db.append({"user": username, "keys": keys})
+            if len(keys) > 0:
+                self.lookup_key_db.update({username: keys})  # Populate dict key db
+
+    def main(self):
+        self.expand_users()
+
+        if self.servers_db and len(self.servers_db) > 0:
+            # Advanced mode we have to do merges and stuff :D
+            self.expand_servers()
+            result = {"changed": False, "msg": "",
+                      "users_db": self.expanded_server_db,
+                      "key_db": self.expanded_server_key_db}
+        else:
+            # Simple mode no servers db
+            result = {"changed": False, "msg": "",
+                      "users_db": self.expanded_users_db,
+                      "key_db": self.expanded_users_key_db}
+        self.module.exit_json(**result)
+
+
+def main():
+    module = AnsibleModule(
+        argument_spec=dict(
+            usersdb=dict(default=None, required=False, type="dict"),
+            source_userdb=dict(default=None, required=False, type="dict"),
+            teamsdb=dict(default=None, required=False),  # Should be dict but would break if value is false/none
+            serversdb=dict(default=None, required=False),
+        ),
+        supports_check_mode=False
+    )
+    UsersDB(module).main()
+
+# import module snippets
+from ansible.module_utils.basic import *
+main()

+ 1 - 0
galaxy-roles/usermanage/meta/.galaxy_install_info

@@ -0,0 +1 @@
+{install_date: 'Sat Jul 25 11:16:15 2015', version: master}

+ 11 - 0
galaxy-roles/usermanage/meta/main.yml

@@ -0,0 +1,11 @@
+---
+galaxy_info:
+  author: Adham Helal
+  description: "Manage your Linux user and ssh key account. Accross your infrastructure"
+  min_ansible_version: 1.4
+  platforms:
+  - name: Ubuntu
+    versions:
+    - precise
+  categories:
+  - system

+ 40 - 0
galaxy-roles/usermanage/tasks/debug.yml

@@ -0,0 +1,40 @@
+---
+
+- name: debug | Display compiled user
+  debug:
+    var=cuser.users_db
+  sudo: no
+  when: usermanage_debug_level >= 2
+
+- name: debug | Display compiled keys
+  debug:
+    var=cuser.key_db
+  sudo: no
+  when: usermanage_debug_level >= 2
+
+- name: debug | Display lookup_key_db keys
+  debug:
+    var=cuser.lookup_key_db
+  sudo: no
+  when: usermanage_debug_level >= 3 and cuser.lookup_key_db is defined
+
+- name: debug | Debug directory create
+  file:
+    path={{ usermanage_debug_dir }}
+    state="directory"
+    mode=0700
+    owner=root
+  when: usermanage_debug_level >= 1
+
+- name: debug | Debug Users /tmp/debugUser.{{inventory_hostname}}-{{item.account}}
+  template:
+     src=debug_users.j2
+     dest="{{ usermanage_debug_dir }}/{{ inventory_hostname }}-{{ item.user | default(item.name) }}"
+  with_items: cuser.users_db
+  when: usermanage_debug_level >= 1
+
+- name: debug | Debug usermanage_groupsdb
+  debug:
+    var=usermanage_groupsdb
+  sudo: no
+  when: usermanage_debug_level >= 3 and usermanage_groupsdb is defined

+ 7 - 0
galaxy-roles/usermanage/tasks/groups.yml

@@ -0,0 +1,7 @@
+---
+
+- name: groups | Create groups
+  group:
+  args: "{{ item }}"
+  with_items: usermanage_groupsdb | default(default_temp_solution)
+  when: usermanage_groupsdb

+ 15 - 0
galaxy-roles/usermanage/tasks/main.yml

@@ -0,0 +1,15 @@
+---
+
+- include: sources.yml
+
+- include: debug.yml
+  when: usermanage_debug
+
+- include: per_user_group.yml
+  when: usermanage_create_per_user_group and cuser.users_db is defined
+
+- include: groups.yml
+  when: usermanage_groupsdb is defined and usermanage_groupsdb is not none
+
+- include: users.yml
+

+ 7 - 0
galaxy-roles/usermanage/tasks/per_user_group.yml

@@ -0,0 +1,7 @@
+---
+
+- name: groups | Create per user group
+  group:
+    name="{{ item.name  | default(item.user) }}"
+    state="{{ item.state | default("present") }}"
+  with_items: cuser.users_db

+ 23 - 0
galaxy-roles/usermanage/tasks/sources.yml

@@ -0,0 +1,23 @@
+---
+
+- name: sources | Load users db from a path
+  load_user_files:
+  args:
+    path: "{{ usermanage_user_source_files }}"
+    fact: "{{ usermanage_source_facts }}"
+    databag: "{{ usermanage_user_source_databag }}"
+  register: loaded_users_db
+  connection: local
+  sudo: no
+  when: usermanage_user_source_files is defined and usermanage_user_source_files is not none
+
+- name: sources | Compile effective users
+  usersdb:
+    usersdb: "{{ usermanage_usersdb | default(omit) }}"
+    serversdb: "{{ usermanage_servers | default(omit) }}"
+    teamsdb: "{{ usermanage_teamsdb | default(omit) }}"
+    source_userdb: "{{ loaded_users_db[usermanage_source_facts] | default(omit) }}"
+  register: cuser
+  connection: local
+  sudo: no
+  when: usermanage_usersdb is defined or loaded_users_db[usermanage_source_facts] is defined

+ 31 - 0
galaxy-roles/usermanage/tasks/users.yml

@@ -0,0 +1,31 @@
+---
+- name: users | Create users
+  user:
+    force=yes
+    append=True
+  args: "{{ item }}"
+  with_items: cuser.users_db | default([])
+  when: cuser.users_db is defined
+
+- name: users | Manage public key for users
+  authorized_key:
+     user="{{ item.0.user | default(item.0.name) }}"
+     manage_dir="yes"
+  args: "{{ item.1 }}"
+  with_subelements:
+      - cuser.key_db | default([])
+      - keys
+  register: keyrc
+  failed_when: "'failed' in keyrc and 'getpwnam' not in keyrc.msg"
+  when: cuser.key_db is defined
+
+- name: users | Manage private key for users
+  copy:
+     content="{{ item.privkey }}"
+     dest="{{ item.home | default(usermanage_default_home_dir_prefix + "/" + item.user ) }}/{{ usermanage_priv_key_suffix}}"
+     mode=0600
+     owner="{{ item.user }}"
+  with_items: usermanage_users_privkey
+  when: usermanage_users_privkey is defined
+#  no_log: True
+

+ 4 - 0
galaxy-roles/usermanage/templates/debug_users.j2

@@ -0,0 +1,4 @@
+inventory_hostname= {{inventory_hostname}}
+------------------------------------------
+
+{{ item | to_nice_yaml }}

+ 22 - 0
galaxy-roles/usermanage/test/.kitchen.yml

@@ -0,0 +1,22 @@
+---
+
+# this file is used to simulate travis 
+driver:
+  name: vagrant
+
+provisioner:
+  name: shell
+  script: run_vagrant_kitchen.sh
+
+platforms:
+    - name: ubuntu-14.04
+      driver:
+        box: ubuntu/trusty64
+        synced_folders:
+         - [ '/Users/helal/Documents/Projects/ansible-usermanage/' , '/mnt/shared/ansible-usermanage/' ]
+
+suites:
+  - name: default
+
+
+#     - ["<% File.expand_path('../',File.expand_path('../', Dir.pwd))%>", "<%= '/mnt/shared/' +  File.basename(File.expand_path('../', Dir.pwd)) %>/"]

+ 2 - 0
galaxy-roles/usermanage/test/ansible.cfg

@@ -0,0 +1,2 @@
+[defaults]
+roles_path=../:../../:/spec/

+ 13 - 0
galaxy-roles/usermanage/test/application/advanced.yml

@@ -0,0 +1,13 @@
+---
+- name         : Advanced Mode (1)
+  hosts        : all
+  gather_facts : no
+  sudo         : True
+  connection   : "{{ kitchen_connection | default('local') }}"
+  vars         :
+                 usermanage_debug : true
+  vars_files   :
+                 - "advanced_var_user_db.yml"
+                 - "advanced_var_server_db.yml"
+  roles        :
+                 - "ansible-usermanage"

+ 31 - 0
galaxy-roles/usermanage/test/application/advanced_var_server_db.yml

@@ -0,0 +1,31 @@
+---
+
+usermanage_servers:
+      #Simplest form (create testuser and push the testuser key defined in the userdb)
+      - user        : "label"
+        groups      : "sudo"
+        uid         : 4000
+
+      - user        : "ops"
+        groups      : "adm"
+        state       : "present"
+        keys        :
+             - user        : 'daniels'
+               state       : 'present'
+               key_options : 'no-port-forwarding'
+             - user        : 'stewart'
+               state       : 'present'
+
+      - user        : "dev"
+        groups      : 'ops,lp'
+        state       : 'present'
+        shell       : '/bin/false'
+        keys        :
+             - user        : 'vodka'
+               state       : 'present'
+               key_options : 'no-port-forwarding'
+             - user        : 'raki'  # should be not there
+               state       : 'present'
+      - user        : tool
+        groups      : 'ops,lp'
+        state       : 'present'

+ 49 - 0
galaxy-roles/usermanage/test/application/advanced_var_user_db.yml

@@ -0,0 +1,49 @@
+---
+usermanage_usersdb:
+  daniels:
+    comment: "Jack daniels"
+    keys:
+      - key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDLql1khoXEH/pThpLSDwJNBIEHkjrBggjEvRCqCFYvE1Neavc6iuLSzjLdnj74LNrPEjY+xcjAcPmgwxo8+WKpLL7Iy8e9IGH3lwB05x9jfnw2H1ZRnZZxF+wV/ei/vfCmRyt2cqv+DLomg18RDTnyTk2pvSEvL0xkRn5QRbzxqbnB+9xmItTjdtq/ZDYRgFYn2ZPfokFyyr3KpwpK0gNcpFhCF94CvExKpu6SFPTv+ERnFvHEN9d8SlzwkyCP4yqrfOjFuVUuZf2FtAkDx0d4cXo0i7VUM/hOthUNFpmljZLhkxafPxwp50Q/xRe7MvDQMrEPGPZ/pubOwzqVmMWH daniels1"
+      - key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCxAqbTlltSFlRY+gQyAx3j0W+WDnahZYbECAXiwNqAHG7PP8GSEDVkfZTkJdlu9PoB/B3nW2R/Q3//IxUfzRsUnjUzl0WXbhz331n5bHtgJlg82MGqwbNjN0yMR/GB4pQKeExYOLKi/7jI/wkOAJ4X9Bv9skEK/mHAWWPrBf/5C5qWUOxVC1+he3iaU+LSbiL6uiNs8S49fiGno8tBkBFgth+9gqdCLRAFVe2dzJJK1nSQTffHCs12pJs2S3yBD9KkUQJO51tByP4qO3549iwLo8hQnqtFULMpL+NN5Muk1bFZ2jW+0Sri1bhVS58llZCuoENZsLf/+xejbfwJAk4h daniels2"
+        key_options: no-port-forwarding
+  gin:
+    comment: "Gordons Gin"
+    keys:
+      - key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCcoo+eU8+k7QYpKbZwOQwiMpeklQcmEyLTsJr0RLTeqsHkIh8rFWyMZURDZ5pgEGo3iXZD+dqM28agy2Pw68/V0wht/9n0PjmUVZgkWIas162w3vZrJENDi8wAo4ojQJf0lZf63K8AxoB12fF+QdR7jfTLrz2bCxv9XaHKm7nYGtRO0f8ETgvwpIS2jN0mPAD7qnCFvLtbaxd/UzsQS5M8Au42+9zdn78Atm7gtKY9uR5U1Jwrop8KipXf0wAtMo39Xc9P8hGbYGA1jkbcG2x1LI7G9L+PddxeZjpkW2Uv559YJDRjBJfJAfp6K4HGV5uXITSMVDY9KBYvepolrlul gin1"
+    shell: /bin/false
+  rum:
+    comment: "Pirates Grog Rum"
+    keys:
+      - key: "ssh-rsa AAAAB3NzaC2EAA1ycAADAAAQABABAQCootXD63hexEQnbCmKGC7DjFSWxkqJ2neaC5S6POEdgwo7jQ60JWy0VCm5JS5d2ZNDQh+vi1wZ2cTr6n9X9bAkYhQ/eACmzYBjf8I8AXcqaigAOjRMLADU2qQfZmnRGyOLaGDI/EH52yBjeZHbgQdJOGrB07qgAu2facA2bd6kvI8eLwCx5yjqA+mInYEewRYrr5tUduGFdPhmyoKSGpaEeWWkLhafTj9eGRMSB3unBcMtux+LxXH4TfWgVBmWNVbr2Mcv+M6tYxix/iKniBLBUH/AfM/dTHlk38y2mjemUMUc/HBW+HmH3NXMwOks8po6Iohh8JNhywUlLKN9MvB7 rum1"
+        state: absent
+  stewart:
+    comment: "Daniel Stewart"
+    home: /opt/stewart
+    keys:
+      - key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDhiDPE4S4K6AGJFRSIB5xVoIlKtgjVUVHK1WhT0hD/I3nZ3AFszqDXUz4eREDlPSfMsvNCuAd1Mxwg2vx1Udbzf0M5OH1DDgYyVeJXXB5/B2rpX7vm0A1Hxx17mMHg9OrCNKNn8B83g6IqAGM6P3VKHqnRQ9kLpPcki65gMx06R2dQ1Dh5kks2yOjyx7Mjut0rL9Ig/b9ysMMC1YjMupC8vb31Dhy8pVi1F/RT/7M6PwM4Kjh3fdzgqvQRxDrmky8kbXJj+TXU6pIM1mZtZyENddUCA0rDNtpi6yIaAR9aJkcPXxPpblkWjYAO++sukz88BKWt0Z+nLx9JUhwXtoW7 stewart1"
+  vodka:
+    comment: "Savvy Vodka"
+    keys:
+      - key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC2Pq3M7AgeBjmNII6HGsKd2uaXFIfaljpNg1Rf6y3iGP84wC82bMfZTSIhnzJ4qwHj7Bzn8oiMmqtyeGcmEwLXm5f7mk3lj9NmxUEfbuWsPoSX4VHIney0F2cjrYRAHua8vZ50OrqYvRaBNttx+pCsub/Kw/t91PQvz7s5ML12DfhlfbE5f/g+ZrKHBxsn6Vw0VqN1Cx5cecaN+9NbdwTV25/RVsXC6v9TQlIqWR+znt4ZVxUSCTAbGc51tmauoleZee2XBkAO7xmJ7zPQEndhErq/zm0euZGx1xGIjQ7dVBK8t1ah2UdBS4pSHgjhDulo0hr4gIubQ0FSV+8cWCNN vodka1"
+    uid: 2300
+  raki:
+    state: "absent"
+    comment: "Yeni Raki"
+    keys:
+      - key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCvy3wrbh9hwSP0WrwXSFW4AujinW+xiDQn7RLJ8UcVZ+Yf4EmV6GTvjjJjIegIKjnH2xiRDjZ1qaSZzxW7/uyVxPrjhGAE8iPQAGcLEEcpg4IwlFpd3+7NgCKLdVHozH6z+h3G95otKQZLmKq9lzkfVyhDzTjU2qsnSQPitDrPY/tngN1gnZHQm2CUh4gamtOfxtPKlOqQ/t0iXJU48QfyN33XWr8M5/2FWP9jDyvxEjpCRW2Qu2+8uQONPOHMtkLW70G2+KVN90fkOXMnDotm+aY1OluUcXgrBakEctHNIWoKSUbcdOw1JkLY3Ojl11lIdXn267A1t70FaEXG8cIf raki1"
+    uid: 2400
+  label:
+    comment: "Black Label"
+    keys:
+      - key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDbakoTSJHYJ88J3//celPFG1kAXv0WvH0o1WkJmrjZe1nWvpHArSv9MmELh3QOu2L3f87Yx8p0kzz0wTQowQisrspFSI6lvIJ+2aapx4J+4O+9IRR+XRcw6giD4OGfTH3af8lgAmVvrcfP41NH4l/jl2Fs+BjeCudTTFemy6L8wlHZPOdsHFs/71aAAcUqpLmrBECHzHBo+LzNZ2ZKy7s+V6RNR5TmWUdupQGsuE6C5yY2AZQ3cFxOmhPJsEVzQSZneCMfNQI3qfAYvXRQNXxQjCaXBJH7S+cCnf8kIrr+Ntfu5A54iyuAZ3SWVCLvym29ZTN0RH8fCvH9zqC5F0r/ label1"
+  ops:
+    comment: "Operations"
+    state: "present"
+    keys:
+      - key: "ssh-rsa ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC6b7thDSxav6nzor9k7h1joWT5dQOOBHgvmk82xcR/fRtr5uOGm5YrbRSt5ftiC8+2IdyyAWhy5ur4BIaf4LkKW+Z3db6uN6dkNxE/v+yYH5M2Nsk6LPJ9GyY8Wl15TYHFWyexGXg9n/cSmuzjM2PjAk89DlbQJnbh4iqqCl1D3Taq2CHEqQhJLwL9mgmIeZvlfuHxPxpDLuS5otOqNbBmkbmcpznkBfeyHF7wpauZgl060WxVsVxCtjcczawjBqA1JODImbgBivVw85aGI9PRqdPj25JYeoQWf02jhpNlIt2fULIyUGHNT76oKh7AkRjUwEv1iYX+PzTRtxov6CGr ops1"
+  dev:
+    state: "present"
+    keys:
+      - key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC+CDl3fAHWGS++kVXsWIGkh9yAaO9Nv4XbVX0CsCzIxRd85HS/uOCp5SUtjvTzVjOJu+GKfoNuYwMyGKAJprITVU/lPl9czMySz70BqxDn3yhELWC9GRq+EuZEWasV6xbEeSaUTA0S6614ciBoXSYC7WGYJhnUv59b+yHnQBT7ZDN6MYSWBA9UDFZWE90BxzzjYzJpxY80KOqmfXrMEMbjK31L8dCLHmVKGIYsOJkswLPN7kkxeZxxIpBwo3D9SUYels7sOzXb/G83hxj6NfTVkzcut9GsiQxAPt92RsoMbLqDv6QcwABo4MdOw7wDieoP8I5ftqq76q+GTangM7Sj dev1"
+  tool:
+    state: "present"

+ 10 - 0
galaxy-roles/usermanage/test/application/group.yml

@@ -0,0 +1,10 @@
+---
+- name         : Group (1)
+  hosts        : all
+  gather_facts : no
+  sudo         : True
+  connection   : "{{ kitchen_connection | default('local') }}"
+  vars_files   :
+                 - "group_var_group_db.yml"
+  roles        :
+                 - "ansible-usermanage"

+ 17 - 0
galaxy-roles/usermanage/test/application/group_var_group_db.yml

@@ -0,0 +1,17 @@
+---
+
+usermanage_groupsdb  :
+      - name         : "group1"
+        state        : "present"
+        gid          : "5000"
+        system       : "true"
+
+      - name         : "group2"
+        state        : "present"
+        gid          : "5001"
+        system       : "false"
+
+      - name         : "group3"
+
+      - name         : "group4"
+        state        : "absent"

+ 15 - 0
galaxy-roles/usermanage/test/application/multi_source_files.yml

@@ -0,0 +1,15 @@
+---
+- name         : Multi Sources files
+  hosts        : all
+  gather_facts : no
+  sudo         : True
+  connection   : "{{ kitchen_connection | default('local') }}"
+  vars_files   :
+                 - "group_var_group_db.yml"
+  vars         :
+                 usermanage_user_source_files:
+                    - path: "./user_source/mutli/yaml/"
+                    - path: "./user_source/mutli/databag"
+                      databag: true
+  roles        :
+                 - "ansible-usermanage"

+ 12 - 0
galaxy-roles/usermanage/test/application/simple.yml

@@ -0,0 +1,12 @@
+---
+- name         : Simple Mode (1)
+  hosts        : all
+  gather_facts : no
+  sudo         : True
+  connection   : "{{ kitchen_connection | default('local') }}"
+  vars         :
+                 usermanage_debug : true
+  vars_files   :
+                 - "simple_var_user_db.yml"
+  roles        :
+                 - "ansible-usermanage"

+ 36 - 0
galaxy-roles/usermanage/test/application/simple_var_user_db.yml

@@ -0,0 +1,36 @@
+--- 
+usermanage_usersdb: 
+  daniels: 
+    comment: "Jack daniels"
+    keys: 
+      - key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDLql1khoXEH/pThpLSDwJNBIEHkjrBggjEvRCqCFYvE1Neavc6iuLSzjLdnj74LNrPEjY+xcjAcPmgwxo8+WKpLL7Iy8e9IGH3lwB05x9jfnw2H1ZRnZZxF+wV/ei/vfCmRyt2cqv+DLomg18RDTnyTk2pvSEvL0xkRn5QRbzxqbnB+9xmItTjdtq/ZDYRgFYn2ZPfokFyyr3KpwpK0gNcpFhCF94CvExKpu6SFPTv+ERnFvHEN9d8SlzwkyCP4yqrfOjFuVUuZf2FtAkDx0d4cXo0i7VUM/hOthUNFpmljZLhkxafPxwp50Q/xRe7MvDQMrEPGPZ/pubOwzqVmMWH"
+      - key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCxAqbTlltSFlRY+gQyAx3j0W+WDnahZYbECAXiwNqAHG7PP8GSEDVkfZTkJdlu9PoB/B3nW2R/Q3//IxUfzRsUnjUzl0WXbhz331n5bHtgJlg82MGqwbNjN0yMR/GB4pQKeExYOLKi/7jI/wkOAJ4X9Bv9skEK/mHAWWPrBf/5C5qWUOxVC1+he3iaU+LSbiL6uiNs8S49fiGno8tBkBFgth+9gqdCLRAFVe2dzJJK1nSQTffHCs12pJs2S3yBD9KkUQJO51tByP4qO3549iwLo8hQnqtFULMpL+NN5Muk1bFZ2jW+0Sri1bhVS58llZCuoENZsLf/+xejbfwJAk4h"
+        key_options: no-port-forwarding
+  gin: 
+    comment: "Gordons Gin"
+    keys: 
+      - key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCcoo+eU8+k7QYpKbZwOQwiMpeklQcmEyLTsJr0RLTeqsHkIh8rFWyMZURDZ5pgEGo3iXZD+dqM28agy2Pw68/V0wht/9n0PjmUVZgkWIas162w3vZrJENDi8wAo4ojQJf0lZf63K8AxoB12fF+QdR7jfTLrz2bCxv9XaHKm7nYGtRO0f8ETgvwpIS2jN0mPAD7qnCFvLtbaxd/UzsQS5M8Au42+9zdn78Atm7gtKY9uR5U1Jwrop8KipXf0wAtMo39Xc9P8hGbYGA1jkbcG2x1LI7G9L+PddxeZjpkW2Uv559YJDRjBJfJAfp6K4HGV5uXITSMVDY9KBYvepolrlul"
+    shell: /bin/false
+  rum: 
+    comment: "Pirates Grog Rum"
+    keys: 
+      - key: "ssh-rsa AAAAB3NzaC2EAA1ycAADAAAQABABAQCootXD63hexEQnbCmKGC7DjFSWxkqJ2neaC5S6POEdgwo7jQ60JWy0VCm5JS5d2ZNDQh+vi1wZ2cTr6n9X9bAkYhQ/eACmzYBjf8I8AXcqaigAOjRMLADU2qQfZmnRGyOLaGDI/EH52yBjeZHbgQdJOGrB07qgAu2facA2bd6kvI8eLwCx5yjqA+mInYEewRYrr5tUduGFdPhmyoKSGpaEeWWkLhafTj9eGRMSB3unBcMtux+LxXH4TfWgVBmWNVbr2Mcv+M6tYxix/iKniBLBUH/AfM/dTHlk38y2mjemUMUc/HBW+HmH3NXMwOks8po6Iohh8JNhywUlLKN9MvB7"
+        state: absent
+  stewart: 
+    comment: "Daniel Stewart"
+    home: /opt/stewart
+    keys: 
+      - key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDhiDPE4S4K6AGJFRSIB5xVoIlKtgjVUVHK1WhT0hD/I3nZ3AFszqDXUz4eREDlPSfMsvNCuAd1Mxwg2vx1Udbzf0M5OH1DDgYyVeJXXB5/B2rpX7vm0A1Hxx17mMHg9OrCNKNn8B83g6IqAGM6P3VKHqnRQ9kLpPcki65gMx06R2dQ1Dh5kks2yOjyx7Mjut0rL9Ig/b9ysMMC1YjMupC8vb31Dhy8pVi1F/RT/7M6PwM4Kjh3fdzgqvQRxDrmky8kbXJj+TXU6pIM1mZtZyENddUCA0rDNtpi6yIaAR9aJkcPXxPpblkWjYAO++sukz88BKWt0Z+nLx9JUhwXtoW7"
+  vodaka: 
+    comment: "Savvy Vodka"
+    keys: 
+      - key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC2Pq3M7AgeBjmNII6HGsKd2uaXFIfaljpNg1Rf6y3iGP84wC82bMfZTSIhnzJ4qwHj7Bzn8oiMmqtyeGcmEwLXm5f7mk3lj9NmxUEfbuWsPoSX4VHIney0F2cjrYRAHua8vZ50OrqYvRaBNttx+pCsub/Kw/t91PQvz7s5ML12DfhlfbE5f/g+ZrKHBxsn6Vw0VqN1Cx5cecaN+9NbdwTV25/RVsXC6v9TQlIqWR+znt4ZVxUSCTAbGc51tmauoleZee2XBkAO7xmJ7zPQEndhErq/zm0euZGx1xGIjQ7dVBK8t1ah2UdBS4pSHgjhDulo0hr4gIubQ0FSV+8cWCNN"
+    uid: 2300
+  raki:
+    state: "absent"
+    comment: "Yeni Raki"
+    keys:
+      - key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCvy3wrbh9hwSP0WrwXSFW4AujinW+xiDQn7RLJ8UcVZ+Yf4EmV6GTvjjJjIegIKjnH2xiRDjZ1qaSZzxW7/uyVxPrjhGAE8iPQAGcLEEcpg4IwlFpd3+7NgCKLdVHozH6z+h3G95otKQZLmKq9lzkfVyhDzTjU2qsnSQPitDrPY/tngN1gnZHQm2CUh4gamtOfxtPKlOqQ/t0iXJU48QfyN33XWr8M5/2FWP9jDyvxEjpCRW2Qu2+8uQONPOHMtkLW70G2+KVN90fkOXMnDotm+aY1OluUcXgrBakEctHNIWoKSUbcdOw1JkLY3Ojl11lIdXn267A1t70FaEXG8cIf"
+    uid: 2400
+  brad:
+    comment: "Brad"

+ 26 - 0
galaxy-roles/usermanage/test/application/source_databag.yml

@@ -0,0 +1,26 @@
+---
+- name         : Sources databag
+  hosts        : all
+  gather_facts : no
+  sudo         : True
+  connection   : "{{ kitchen_connection | default('local') }}"
+  vars_files   :
+                 - "group_var_group_db.yml"
+  vars         :
+                 usermanage_user_source_files   :
+                                                  - path: "./user_source/databag/"
+                                                    databag: true
+
+                 usermanage_debug               : true
+                 usermanage_usersdb:
+                  daniels:
+                     state : "absent"
+                     keys:
+                       - key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDLql1khoXEH/pThpLSDwJNBIEHkjrBggjEvRCqCFYvE1Neavc6iuLSzjLdnj74LNrPEjY+xcjAcPmgwxo8+WKpLL7Iy8e9IGH3lwB05x9jfnw2H1ZRnZZxF+wV/ei/vfCmRyt2cqv+DLomg18RDTnyTk2pvSEvL0xkRn5QRbzxqbnB+9xmItTjdtq/ZDYRgFYn2ZPfokFyyr3KpwpK0gNcpFhCF94CvExKpu6SFPTv+ERnFvHEN9d8SlzwkyCP4yqrfOjFuVUuZf2FtAkDx0d4cXo0i7VUM/hOthUNFpmljZLhkxafPxwp50Q/xRe7MvDQMrEPGPZ/pubOwzqVmMWH"
+
+                  whisky:
+                     state : "present"
+                     keys:
+                       - key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDLql1khoXEH/pThpLSDwJNBIEHkjrBggjEvRCqCFYvE1Neavc6iuLSzjLdnj74LNrPEjY+xcjAcPmgwxo8+WKpLL7Iy8e9IGH3lwB05x9jfnw2H1ZRnZZxF+wV/ei/vfCmRyt2cqv+DLomg18RDTnyTk2pvSEvL0xkRn5QRbzxqbnB+9xmItTjdtq/ZDYRgFYn2ZPfokFyyr3KpwpK0gNcpFhCF94CvExKpu6SFPTv+ERnFvHEN9d8SlzwkyCP4yqrfOjFuVUuZf2FtAkDx0d4cXo0i7VUM/hOthUNFpmljZLhkxafPxwp50Q/xRe7MvDQMrEPGPZ/pubOwzqVmxxx"
+  roles        :
+                 - "ansible-usermanage"

+ 13 - 0
galaxy-roles/usermanage/test/application/source_files.yml

@@ -0,0 +1,13 @@
+---
+- name         : Sources files
+  hosts        : all
+  gather_facts : no
+  sudo         : True
+  connection   : "{{ kitchen_connection | default('local') }}"
+  vars         :
+                 usermanage_user_source_files:
+                                               - path: "./user_source/yaml&json/"
+                                                 databag: false
+
+  roles        :
+                 - "ansible-usermanage"

+ 14 - 0
galaxy-roles/usermanage/test/application/team.yml

@@ -0,0 +1,14 @@
+---
+- name         : Team (1)
+  hosts        : all
+  gather_facts : no
+  sudo         : True
+  connection   : "{{ kitchen_connection | default('local') }}"
+  vars:
+                usermanage_debug : true
+                usermanage_debug_level: 3
+  vars_files   :
+                 - "team_var_db.yml"
+                 - "group_var_group_db.yml"                 
+  roles        :
+                 - "ansible-usermanage"

+ 63 - 0
galaxy-roles/usermanage/test/application/team_var_db.yml

@@ -0,0 +1,63 @@
+---
+usermanage_usersdb:
+  daniels:
+    comment: "Jack daniels team"
+    keys:
+      - key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDLql1khoXEH/pThpLSDwJNBIEHkjrBggjEvRCqCFYvE1Neavc6iuLSzjLdnj74LNrPEjY+xcjAcPmgwxo8+WKpLL7Iy8e9IGH3lwB05x9jfnw2H1ZRnZZxF+wV/ei/vfCmRyt2cqv+DLomg18RDTnyTk2pvSEvL0xkRn5QRbzxqbnB+9xmItTjdtq/ZDYRgFYn2ZPfokFyyr3KpwpK0gNcpFhCF94CvExKpu6SFPTv+ERnFvHEN9d8SlzwkyCP4yqrfOjFuVUuZf2FtAkDx0d4cXo0i7VUM/hOthUNFpmljZLhkxafPxwp50Q/xRe7MvDQMrEPGPZ/pubOwzqVmMWH"
+      - key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCxAqbTlltSFlRY+gQyAx3j0W+WDnahZYbECAXiwNqAHG7PP8GSEDVkfZTkJdlu9PoB/B3nW2R/Q3//IxUfzRsUnjUzl0WXbhz331n5bHtgJlg82MGqwbNjN0yMR/GB4pQKeExYOLKi/7jI/wkOAJ4X9Bv9skEK/mHAWWPrBf/5C5qWUOxVC1+he3iaU+LSbiL6uiNs8S49fiGno8tBkBFgth+9gqdCLRAFVe2dzJJK1nSQTffHCs12pJs2S3yBD9KkUQJO51tByP4qO3549iwLo8hQnqtFULMpL+NN5Muk1bFZ2jW+0Sri1bhVS58llZCuoENZsLf/+xejbfwJAk4h"
+        key_options: no-port-forwarding
+  vodka:
+    comment: "Savvy Vodka team"
+    keys:
+      - key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC2Pq3M7AgeBjmNII6HGsKd2uaXFIfaljpNg1Rf6y3iGP84wC82bMfZTSIhnzJ4qwHj7Bzn8oiMmqtyeGcmEwLXm5f7mk3lj9NmxUEfbuWsPoSX4VHIney0F2cjrYRAHua8vZ50OrqYvRaBNttx+pCsub/Kw/t91PQvz7s5ML12DfhlfbE5f/g+ZrKHBxsn6Vw0VqN1Cx5cecaN+9NbdwTV25/RVsXC6v9TQlIqWR+znt4ZVxUSCTAbGc51tmauoleZee2XBkAO7xmJ7zPQEndhErq/zm0euZGx1xGIjQ7dVBK8t1ah2UdBS4pSHgjhDulo0hr4gIubQ0FSV+8cWCNN"
+    uid: 3300
+  pepsi:
+    comment: "Pepsi Cola"
+    uid: 3400
+    shell: /bin/false
+    keys:
+      - key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCcoo+eU8+k7QYpKbZwOQwiMpeklQcmEyLTsJr0RLTeqsHkIh8rFWyMZURDZ5pgEGo3iXZD+dqM28agy2Pw68/V0wht/9n0PjmUVZgkWIas162w3vZrJENDi8wAo4ojQJf0lZf63K8AxoB12fF+QdR7jfTLrz2bCxv9XaHKm7nYGtRO0f8ETgvwpIS2jN0mPAD7qnCFvLtbaxd/UzsQS5M8Au42+9zdn78Atm7gtKY9uR5U1Jwrop8KipXf0wAtMo39Xc9P8hGbYGA1jkbcG2x1LI7G9L+PddxeZjpkW2Uv559YJDRjBJfJAfp6K4HGV5uXITSMVDY9KBYvepolrlul"
+  coca:
+    comment: "Coca Cola"
+    keys:
+      - key: "ssh-rsa AAAAB3NzaC2EAA1ycAADAAAQABABAQCootXD63hexEQnbCmKGC7DjFSWxkqJ2neaC5S6POEdgwo7jQ60JWy0VCm5JS5d2ZNDQh+vi1wZ2cTr6n9X9bAkYhQ/eACmzYBjf8I8AXcqaigAOjRMLADU2qQfZmnRGyOLaGDI/EH52yBjeZHbgQdJOGrB07qgAu2facA2bd6kvI8eLwCx5yjqA+mInYEewRYrr5tUduGFdPhmyoKSGpaEeWWkLhafTj9eGRMSB3unBcMtux+LxXH4TfWgVBmWNVbr2Mcv+M6tYxix/iKniBLBUH/AfM/dTHlk38y2mjemUMUc/HBW+HmH3NXMwOks8po6Iohh8JNhywUlLKN9MvB7"
+        state: present
+  stewart:
+    comment: "Daniel Stewart team"
+    state: "absent"
+    keys:
+      - key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDhiDPE4S4K6AGJFRSIB5xVoIlKtgjVUVHK1WhT0hD/I3nZ3AFszqDXUz4eREDlPSfMsvNCuAd1Mxwg2vx1Udbzf0M5OH1DDgYyVeJXXB5/B2rpX7vm0A1Hxx17mMHg9OrCNKNn8B83g6IqAGM6P3VKHqnRQ9kLpPcki65gMx06R2dQ1Dh5kks2yOjyx7Mjut0rL9Ig/b9ysMMC1YjMupC8vb31Dhy8pVi1F/RT/7M6PwM4Kjh3fdzgqvQRxDrmky8kbXJj+TXU6pIM1mZtZyENddUCA0rDNtpi6yIaAR9aJkcPXxPpblkWjYAO++sukz88BKWt0Z+nLx9JUhwXtoW7"
+
+  raki:
+    comment: "Yeni Raki team"
+    uid: 3400
+    keys:
+      - key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCvy3wrbh9hwSP0WrwXSFW4AujinW+xiDQn7RLJ8UcVZ+Yf4EmV6GTvjjJjIegIKjnH2xiRDjZ1qaSZzxW7/uyVxPrjhGAE8iPQAGcLEEcpg4IwlFpd3+7NgCKLdVHozH6z+h3G95otKQZLmKq9lzkfVyhDzTjU2qsnSQPitDrPY/tngN1gnZHQm2CUh4gamtOfxtPKlOqQ/t0iXJU48QfyN33XWr8M5/2FWP9jDyvxEjpCRW2Qu2+8uQONPOHMtkLW70G2+KVN90fkOXMnDotm+aY1OluUcXgrBakEctHNIWoKSUbcdOw1JkLY3Ojl11lIdXn267A1t70FaEXG8cIf"
+
+  label:
+    comment: "Black Label team"
+    keys:
+      - key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDbakoTSJHYJ88J3//celPFG1kAXv0WvH0o1WkJmrjZe1nWvpHArSv9MmELh3QOu2L3f87Yx8p0kzz0wTQowQisrspFSI6lvIJ+2aapx4J+4O+9IRR+XRcw6giD4OGfTH3af8lgAmVvrcfP41NH4l/jl2Fs+BjeCudTTFemy6L8wlHZPOdsHFs/71aAAcUqpLmrBECHzHBo+LzNZ2ZKy7s+V6RNR5TmWUdupQGsuE6C5yY2AZQ3cFxOmhPJsEVzQSZneCMfNQI3qfAYvXRQNXxQjCaXBJH7S+cCnf8kIrr+Ntfu5A54iyuAZ3SWVCLvym29ZTN0RH8fCvH9zqC5F0r/ label1"
+
+usermanage_teamsdb:
+      team1:
+              - daniels
+              - vodka
+      team2:
+              - pepsi
+              - coca
+              - stewart
+      team3:
+              - raki
+
+usermanage_servers:
+      - team        : "team1"
+        groups      : "group1,group2"
+
+      - team        : "team2"
+
+      - team        : "team3"
+        state       : 'absent'
+
+      - user        : "label"
+        state       : 'absent'

+ 19 - 0
galaxy-roles/usermanage/test/application/user_source/databag/bbreezer.json

@@ -0,0 +1,19 @@
+{
+  "id": "bbreezer",
+  "action": "create",
+  "ssh_keys": [
+    "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCun7TGUhQ1JoWkdtroI4ufEnf/cPWn5mIitu8+eTtMK/yS71CuEhf8f6IkKMuSd5L9PHiIAYd0o87pJ952sUsDdLpk7NPhxVod7ADa7uC+FnFrJ0tgyUlPpe0XC77H1T9abpQ2fAOsC5F+fuWQSBxJyczS6tOIz7b25SUBSTA5ObM4bP0LEE2CJ4uegNpmPn73LAhYgRU43VCH4+w7QmNUHdhkcuVIVNiK2Kt7o3KXP8OjbrdQLCdG2aCMEITrTljHPazhbAgkMnEKLY28fWJpJTIzRCSdEXhdsJMS/nzszPCXvJiol6xOvbcYooYg9c9auMQJUn7EpR062VmlPXuP bbreezer1"
+  ],
+  "groups": [
+    "group2",
+    "group1",
+    "group3"
+  ],
+  "shell": "\/bin\/bash",
+  "system": true,
+  "vpn_password": "asdasdasdad",
+  "openid": "bbreezer.myopenid.com",
+  "comment": "Bacardi Breezer"
+}
+
+

+ 19 - 0
galaxy-roles/usermanage/test/application/user_source/databag/ebacardi.json

@@ -0,0 +1,19 @@
+{
+  "id": "ebacardi",
+  "action": "create",
+  "ssh_keys": [
+    "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDIg6ennnJMC9Ogw55LdVZnpfiaaQLDrAQoWPeFWOld8CCql5JDARY8N+/Zr+SxxHQBb4KqXZidE73u8srEtXcS1YTlDMLK2+KIKPb8TJl4ksChBUv3XM95VDGT0AVUy4yW8v3PTKVlSA9b8yUBOcMQfDd1wtGsyL/Hjq9m0Jev+fXUV7vsVJXtV6OQOEwH8ag6NtdgQ34FdDqCUHK+vNtzrr6zXrgUj38NeAdNlb/WlaSFUlnCiRoohTk/9m3+bcne3Q84o5AzxYvB1d7azpVQFrBQABRR/hyTr07nSdBm5x4RUY35rGT4YTSrslvY+605nZon6beoK81jmcJdi9S1 ebacardi"
+  ],
+  "groups": [
+    "group1",
+    "group2"
+  ],
+  "shell": "\/bin\/sh",
+  "vpn_password": "aoidasoidoiuasdoiasdasd",
+  "openid": "ebacardi.myopenid.com",
+  "comment": "Emilio Bacardi"
+}
+
+
+
+

+ 15 - 0
galaxy-roles/usermanage/test/application/user_source/databag/fbacardi.json

@@ -0,0 +1,15 @@
+{
+  "id": "fbacardi",
+  "action": "remove",
+  "ssh_keys": [
+    "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCnGPR+PYOR6JRpNyr2qAQBV4FPvVin+pbPZ4Mk6ZhiShOXqulrTUVsBQaqtIu2cmyBvxAZyrGh8cwhqT047pGWB1CTaAJ1ZeKISyWeirPoqq6Lc9zQubxAeHCCtCt4z6fbOZ3amxmrseoaGoV3NlyiYlN8YJl1mUOijqoKYJPpt2s8KqKPufUzJc2UCHLUtFJVa+rBgZ2DKLtmdfNpA8ZGeuZ/lvsptJndekf+oup2ia/SWqC27pdrWHEygfbs0HL6tKTwgc0sjNurEgCrgNT95yf2cOqcbDrLgHwf8rQcYA21Kf5I3fQElvhZpQ9BqHif7hTE3FovlILZGbO1Eq6f fbacardi"
+  ],
+  "groups": [
+    "group1"
+  ],
+  "shell": "\/bin\/false",
+  "vpn_password": "wadasdasdasdasdadasd",
+  "openid": "fbacardi.myopenid.com",
+  "comment": "Facundo Bacardi"
+}
+

+ 16 - 0
galaxy-roles/usermanage/test/application/user_source/mutli/databag/bbreezer.json

@@ -0,0 +1,16 @@
+{
+  "id": "bbreezer",
+  "action": "remove",
+  "ssh_keys": [
+    "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCun7TGUhQ1JoWkdtroI4ufEnf/cPWn5mIitu8+eTtMK/yS71CuEhf8f6IkKMuSd5L9PHiIAYd0o87pJ952sUsDdLpk7NPhxVod7ADa7uC+FnFrJ0tgyUlPpe0XC77H1T9abpQ2fAOsC5F+fuWQSBxJyczS6tOIz7b25SUBSTA5ObM4bP0LEE2CJ4uegNpmPn73LAhYgRU43VCH4+w7QmNUHdhkcuVIVNiK2Kt7o3KXP8OjbrdQLCdG2aCMEITrTljHPazhbAgkMnEKLY28fWJpJTIzRCSdEXhdsJMS/nzszPCXvJiol6xOvbcYooYg9c9auMQJUn7EpR062VmlPXuP bbreezer1"
+  ],
+  "groups": [
+    "group2",
+    "group1",
+    "group3"
+  ],
+  "shell": "\/bin\/bash",
+  "system": true
+}
+
+

+ 15 - 0
galaxy-roles/usermanage/test/application/user_source/mutli/databag/strtois.json

@@ -0,0 +1,15 @@
+{
+  "id": "sartois",
+  "action": "create",
+  "ssh_keys": [
+    "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCun7TGUhQ1JoWkdtroI4ufEnf/cPWn5mIitu8+eTtMK/yS71CuEhf8f6IkKMuSd5L9PHiIAYd0o87pJ952sUsDdLpk7NPhxVod7ADa7uC+FnFrJ0tgyUlPpe0XC77H1T9abpQ2fAOsC5F+fuWQSBxJyczS6tOIz7b25SUBSTA5ObM4bP0LEE2CJ4uegNpmPn73LAhYgRU43VCH4+w7QmNUHdhkcuVIVNiK2Kt7o3KXP8OjbrdQLCdG2aCMEITrTljHPazhbAgkMnEKLY28fWJpJTIzRCSdEXhdsJMS/nzszPCXvJiol6xOvbcYooYg9c9auMQJUn7EpR062VmlPXuP bbreezer1"
+  ],
+  "groups": [
+    "group2",
+    "group1",
+    "group3"
+  ],
+  "shell": "\/bin\/bash",
+  "system": true,
+  "comment": "Stella Artois"
+}

+ 6 - 0
galaxy-roles/usermanage/test/application/user_source/mutli/yaml/user1_yaml.yml

@@ -0,0 +1,6 @@
+user1_yaml:
+    comment: "User 1 yaml"
+    keys:
+      - key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDfIG0Zqxtj+OGordHLn82CWzRXA3++D5BdevRx7kCJE50gRhuUbc2lImBbLE+1JRlzwpg+a1AWbM1MTiHJyLbw7e4+KxfUaPxclktvrCD3xqN/Pn0ncgCcZNFrXfeP4RbHN143qzy8ri0Vn4o/3OYK9KZGkfIT+ix8TpD6804LLjrgmgFcEDxJILFNeVL187vfoGdhh/Wed4JMZSWjiXMjA9WHzFkYDWW6HhlmmjNrXQvaQTWpmDAABvP918N7LLf8KuhTcXfyWrVOCpc0jNZKOtzvScixOi2licUkJ/xlGYbirr8cmV9gS+5UzUdzMstZeiKNXkU7imcInsSk5BFv yaml1"
+    shell: /bin/true
+    state: "absent"

+ 6 - 0
galaxy-roles/usermanage/test/application/user_source/yaml&json/user1_yaml.yml

@@ -0,0 +1,6 @@
+---
+user1_yaml:
+    comment: "User 1 yaml"
+    keys:
+      - key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDfIG0Zqxtj+OGordHLn82CWzRXA3++D5BdevRx7kCJE50gRhuUbc2lImBbLE+1JRlzwpg+a1AWbM1MTiHJyLbw7e4+KxfUaPxclktvrCD3xqN/Pn0ncgCcZNFrXfeP4RbHN143qzy8ri0Vn4o/3OYK9KZGkfIT+ix8TpD6804LLjrgmgFcEDxJILFNeVL187vfoGdhh/Wed4JMZSWjiXMjA9WHzFkYDWW6HhlmmjNrXQvaQTWpmDAABvP918N7LLf8KuhTcXfyWrVOCpc0jNZKOtzvScixOi2licUkJ/xlGYbirr8cmV9gS+5UzUdzMstZeiKNXkU7imcInsSk5BFv yaml1"
+    shell: /bin/true

+ 5 - 0
galaxy-roles/usermanage/test/application/user_source/yaml&json/user2_yaml.yml

@@ -0,0 +1,5 @@
+---
+user2_yaml:
+    comment: "User 2 yaml"
+    keys:
+      - key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDXfwZI7qSBnqEwlxWFBQt9YpdhR7bHYbtcRuy77EmAu1VPZmfn+pIDLUXn5sTOZQxzXN32GohJOlC8vW63WMnROVRlI3yVjspcmxEcHeATsFEKfg2JDdH2m88fiG2JaVFBnV9N/obfGZiWCRxmjodttyETw/nvTzAQTczvalO0lm0bkfgkiGffFREucQikf+ZRbgRQmIZxNX2dYMN5nNIcRXjv+2z//N30J22Lzmo0JXRmByBIkCG+QVrvc3UudJ2prkebDp60CoTiPgA9nnpLxYbBbX4QU/q/sYTwb/wMv8g+4AENEJ8RWPIcpLXt65vTUcpbPTuEM8egfSDtlwph yaml2"

+ 10 - 0
galaxy-roles/usermanage/test/application/user_source/yaml&json/user3_json.json

@@ -0,0 +1,10 @@
+{
+  "user3_json": {
+    "comment": "User 3 json",
+    "keys": [
+      {
+        "key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDY3q7JKLPiPawSUK6NIJWKMl1EV9ORJkqrMIQsxanYQyElWw3Y+aj9Kbtl37hbQIYtHVb2y43e26MjlY8XfpHGRtKxtR6t+oIgxVNV3paT31OkJSiLgNS8yn7+JbyeTSu7UN2XdPZgSIF8yCWmNFvwRkW+TsRwCobXJqDwzhSx/BphLqR9ADV+nCyfhG3T/BgJ8XWsio60cOTl/Qy9aIcyDOdsu/HJtB7hIAfxbSMksocMnssJYds3wMQnNYwGVEbHVzJk8priR8GsGBgT8Bh83JmB+gDBXEfT4hRfJ0eC4ekwLAH/bg9IZhfOOQJMQHdk16HL32XNM3TPQiy9845D user3_json"
+      }
+    ]
+  }
+}

+ 32 - 0
galaxy-roles/usermanage/test/integration/advanced/serverspec/test_spec.rb

@@ -0,0 +1,32 @@
+require 'serverspec'
+
+# Required by serverspec
+set :backend, :exec
+
+describe user('label') do
+  it { should exist }
+  it { should belong_to_group 'sudo' }
+  it { should have_uid 4000 }  
+  it { should have_authorized_key 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDbakoTSJHYJ88J3//celPFG1kAXv0WvH0o1WkJmrjZe1nWvpHArSv9MmELh3QOu2L3f87Yx8p0kzz0wTQowQisrspFSI6lvIJ+2aapx4J+4O+9IRR+XRcw6giD4OGfTH3af8lgAmVvrcfP41NH4l/jl2Fs+BjeCudTTFemy6L8wlHZPOdsHFs/71aAAcUqpLmrBECHzHBo+LzNZ2ZKy7s+V6RNR5TmWUdupQGsuE6C5yY2AZQ3cFxOmhPJsEVzQSZneCMfNQI3qfAYvXRQNXxQjCaXBJH7S+cCnf8kIrr+Ntfu5A54iyuAZ3SWVCLvym29ZTN0RH8fCvH9zqC5F0r/ label1' }
+end
+
+describe user('ops') do
+  it { should exist }
+  it { should belong_to_group 'ops' }
+  it { should have_authorized_key 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDLql1khoXEH/pThpLSDwJNBIEHkjrBggjEvRCqCFYvE1Neavc6iuLSzjLdnj74LNrPEjY+xcjAcPmgwxo8+WKpLL7Iy8e9IGH3lwB05x9jfnw2H1ZRnZZxF+wV/ei/vfCmRyt2cqv+DLomg18RDTnyTk2pvSEvL0xkRn5QRbzxqbnB+9xmItTjdtq/ZDYRgFYn2ZPfokFyyr3KpwpK0gNcpFhCF94CvExKpu6SFPTv+ERnFvHEN9d8SlzwkyCP4yqrfOjFuVUuZf2FtAkDx0d4cXo0i7VUM/hOthUNFpmljZLhkxafPxwp50Q/xRe7MvDQMrEPGPZ/pubOwzqVmMWH daniels1' }
+  #TODO: should check  key_options : 'no-port-forwarding'  
+  it { should have_authorized_key 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCxAqbTlltSFlRY+gQyAx3j0W+WDnahZYbECAXiwNqAHG7PP8GSEDVkfZTkJdlu9PoB/B3nW2R/Q3//IxUfzRsUnjUzl0WXbhz331n5bHtgJlg82MGqwbNjN0yMR/GB4pQKeExYOLKi/7jI/wkOAJ4X9Bv9skEK/mHAWWPrBf/5C5qWUOxVC1+he3iaU+LSbiL6uiNs8S49fiGno8tBkBFgth+9gqdCLRAFVe2dzJJK1nSQTffHCs12pJs2S3yBD9KkUQJO51tByP4qO3549iwLo8hQnqtFULMpL+NN5Muk1bFZ2jW+0Sri1bhVS58llZCuoENZsLf/+xejbfwJAk4h daniels2' }
+  #TODO: should check  key_options : 'no-port-forwarding'  
+  it { should have_authorized_key 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDhiDPE4S4K6AGJFRSIB5xVoIlKtgjVUVHK1WhT0hD/I3nZ3AFszqDXUz4eREDlPSfMsvNCuAd1Mxwg2vx1Udbzf0M5OH1DDgYyVeJXXB5/B2rpX7vm0A1Hxx17mMHg9OrCNKNn8B83g6IqAGM6P3VKHqnRQ9kLpPcki65gMx06R2dQ1Dh5kks2yOjyx7Mjut0rL9Ig/b9ysMMC1YjMupC8vb31Dhy8pVi1F/RT/7M6PwM4Kjh3fdzgqvQRxDrmky8kbXJj+TXU6pIM1mZtZyENddUCA0rDNtpi6yIaAR9aJkcPXxPpblkWjYAO++sukz88BKWt0Z+nLx9JUhwXtoW7 stewart1' }
+end
+
+describe user('dev') do
+  it { should exist }
+  it { should belong_to_group 'ops' }  
+  it { should belong_to_group 'lp' }    
+  it { have_login_shell '/bin/false' }
+  it { should have_authorized_key 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC2Pq3M7AgeBjmNII6HGsKd2uaXFIfaljpNg1Rf6y3iGP84wC82bMfZTSIhnzJ4qwHj7Bzn8oiMmqtyeGcmEwLXm5f7mk3lj9NmxUEfbuWsPoSX4VHIney0F2cjrYRAHua8vZ50OrqYvRaBNttx+pCsub/Kw/t91PQvz7s5ML12DfhlfbE5f/g+ZrKHBxsn6Vw0VqN1Cx5cecaN+9NbdwTV25/RVsXC6v9TQlIqWR+znt4ZVxUSCTAbGc51tmauoleZee2XBkAO7xmJ7zPQEndhErq/zm0euZGx1xGIjQ7dVBK8t1ah2UdBS4pSHgjhDulo0hr4gIubQ0FSV+8cWCNN vodka1' }  
+  #key_options : 'no-port-forwarding'
+  it { should_not have_authorized_key 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCvy3wrbh9hwSP0WrwXSFW4AujinW+xiDQn7RLJ8UcVZ+Yf4EmV6GTvjjJjIegIKjnH2xiRDjZ1qaSZzxW7/uyVxPrjhGAE8iPQAGcLEEcpg4IwlFpd3+7NgCKLdVHozH6z+h3G95otKQZLmKq9lzkfVyhDzTjU2qsnSQPitDrPY/tngN1gnZHQm2CUh4gamtOfxtPKlOqQ/t0iXJU48QfyN33XWr8M5/2FWP9jDyvxEjpCRW2Qu2+8uQONPOHMtkLW70G2+KVN90fkOXMnDotm+aY1OluUcXgrBakEctHNIWoKSUbcdOw1JkLY3Ojl11lIdXn267A1t70FaEXG8cIf raki1' }  
+end
+

+ 24 - 0
galaxy-roles/usermanage/test/integration/group/serverspec/test_spec.rb

@@ -0,0 +1,24 @@
+require 'serverspec'
+
+# Required by serverspec
+set :backend, :exec
+
+
+describe group('group1') do
+  it { should exist }
+  it { should have_gid 5000 }
+end
+
+describe group('group2') do
+  it { should exist }
+  it { should have_gid 5001 }
+end
+
+describe group('group3') do
+  it { should exist }
+  it { should have_gid 5002 }
+end
+
+describe group('group4') do
+  it { should_not exist }
+end

+ 19 - 0
galaxy-roles/usermanage/test/integration/multi-source-files/serverspec/test_spec.rb

@@ -0,0 +1,19 @@
+require 'serverspec'
+
+# Required by serverspec
+set :backend, :exec
+
+describe user('bbreezer') do
+  it { should_not exist }
+end
+
+
+describe user('sartois') do
+  it { should exist }
+  it { should belong_to_group 'group2' }
+  it { should belong_to_group 'group1' }
+  it { should belong_to_group 'group3' }
+  it { have_login_shell 'bin/bash' }
+  it { should have_authorized_key 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCun7TGUhQ1JoWkdtroI4ufEnf/cPWn5mIitu8+eTtMK/yS71CuEhf8f6IkKMuSd5L9PHiIAYd0o87pJ952sUsDdLpk7NPhxVod7ADa7uC+FnFrJ0tgyUlPpe0XC77H1T9abpQ2fAOsC5F+fuWQSBxJyczS6tOIz7b25SUBSTA5ObM4bP0LEE2CJ4uegNpmPn73LAhYgRU43VCH4+w7QmNUHdhkcuVIVNiK2Kt7o3KXP8OjbrdQLCdG2aCMEITrTljHPazhbAgkMnEKLY28fWJpJTIzRCSdEXhdsJMS/nzszPCXvJiol6xOvbcYooYg9c9auMQJUn7EpR062VmlPXuP bbreezer1' }
+  #system  : true
+end

+ 40 - 0
galaxy-roles/usermanage/test/integration/simple/serverspec/test_spec.rb

@@ -0,0 +1,40 @@
+require 'serverspec'
+
+# Required by serverspec
+set :backend, :exec
+
+describe user('daniels') do
+  it { should exist }
+  it { should have_authorized_key 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDLql1khoXEH/pThpLSDwJNBIEHkjrBggjEvRCqCFYvE1Neavc6iuLSzjLdnj74LNrPEjY+xcjAcPmgwxo8+WKpLL7Iy8e9IGH3lwB05x9jfnw2H1ZRnZZxF+wV/ei/vfCmRyt2cqv+DLomg18RDTnyTk2pvSEvL0xkRn5QRbzxqbnB+9xmItTjdtq/ZDYRgFYn2ZPfokFyyr3KpwpK0gNcpFhCF94CvExKpu6SFPTv+ERnFvHEN9d8SlzwkyCP4yqrfOjFuVUuZf2FtAkDx0d4cXo0i7VUM/hOthUNFpmljZLhkxafPxwp50Q/xRe7MvDQMrEPGPZ/pubOwzqVmMWH' }
+  it { should have_authorized_key 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCxAqbTlltSFlRY+gQyAx3j0W+WDnahZYbECAXiwNqAHG7PP8GSEDVkfZTkJdlu9PoB/B3nW2R/Q3//IxUfzRsUnjUzl0WXbhz331n5bHtgJlg82MGqwbNjN0yMR/GB4pQKeExYOLKi/7jI/wkOAJ4X9Bv9skEK/mHAWWPrBf/5C5qWUOxVC1+he3iaU+LSbiL6uiNs8S49fiGno8tBkBFgth+9gqdCLRAFVe2dzJJK1nSQTffHCs12pJs2S3yBD9KkUQJO51tByP4qO3549iwLo8hQnqtFULMpL+NN5Muk1bFZ2jW+0Sri1bhVS58llZCuoENZsLf/+xejbfwJAk4h' }  
+#TODO: second key should have #key_options: no-port-forwarding
+end
+
+describe user('gin') do
+  it { should exist }
+  it { have_login_shell '/bin/false' }
+  it { should have_authorized_key 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCcoo+eU8+k7QYpKbZwOQwiMpeklQcmEyLTsJr0RLTeqsHkIh8rFWyMZURDZ5pgEGo3iXZD+dqM28agy2Pw68/V0wht/9n0PjmUVZgkWIas162w3vZrJENDi8wAo4ojQJf0lZf63K8AxoB12fF+QdR7jfTLrz2bCxv9XaHKm7nYGtRO0f8ETgvwpIS2jN0mPAD7qnCFvLtbaxd/UzsQS5M8Au42+9zdn78Atm7gtKY9uR5U1Jwrop8KipXf0wAtMo39Xc9P8hGbYGA1jkbcG2x1LI7G9L+PddxeZjpkW2Uv559YJDRjBJfJAfp6K4HGV5uXITSMVDY9KBYvepolrlul' }  
+end
+
+describe user('rum') do
+  it { should exist }
+  it { should_not have_authorized_key 'ssh-rsa AAAAB3NzaC2EAA1ycAADAAAQABABAQCootXD63hexEQnbCmKGC7DjFSWxkqJ2neaC5S6POEdgwo7jQ60JWy0VCm5JS5d2ZNDQh+vi1wZ2cTr6n9X9bAkYhQ/eACmzYBjf8I8AXcqaigAOjRMLADU2qQfZmnRGyOLaGDI/EH52yBjeZHbgQdJOGrB07qgAu2facA2bd6kvI8eLwCx5yjqA+mInYEewRYrr5tUduGFdPhmyoKSGpaEeWWkLhafTj9eGRMSB3unBcMtux+LxXH4TfWgVBmWNVbr2Mcv+M6tYxix/iKniBLBUH/AfM/dTHlk38y2mjemUMUc/HBW+HmH3NXMwOks8po6Iohh8JNhywUlLKN9MvB7' }  
+end
+
+describe user('stewart') do
+  it { should exist }
+  it { should have_home_directory '/opt/stewart' }
+  it { should have_authorized_key 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDhiDPE4S4K6AGJFRSIB5xVoIlKtgjVUVHK1WhT0hD/I3nZ3AFszqDXUz4eREDlPSfMsvNCuAd1Mxwg2vx1Udbzf0M5OH1DDgYyVeJXXB5/B2rpX7vm0A1Hxx17mMHg9OrCNKNn8B83g6IqAGM6P3VKHqnRQ9kLpPcki65gMx06R2dQ1Dh5kks2yOjyx7Mjut0rL9Ig/b9ysMMC1YjMupC8vb31Dhy8pVi1F/RT/7M6PwM4Kjh3fdzgqvQRxDrmky8kbXJj+TXU6pIM1mZtZyENddUCA0rDNtpi6yIaAR9aJkcPXxPpblkWjYAO++sukz88BKWt0Z+nLx9JUhwXtoW7' }  
+end
+
+describe user('vodaka') do
+  it { should exist }
+  it { should have_uid 2300 }
+  it { should have_authorized_key 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC2Pq3M7AgeBjmNII6HGsKd2uaXFIfaljpNg1Rf6y3iGP84wC82bMfZTSIhnzJ4qwHj7Bzn8oiMmqtyeGcmEwLXm5f7mk3lj9NmxUEfbuWsPoSX4VHIney0F2cjrYRAHua8vZ50OrqYvRaBNttx+pCsub/Kw/t91PQvz7s5ML12DfhlfbE5f/g+ZrKHBxsn6Vw0VqN1Cx5cecaN+9NbdwTV25/RVsXC6v9TQlIqWR+znt4ZVxUSCTAbGc51tmauoleZee2XBkAO7xmJ7zPQEndhErq/zm0euZGx1xGIjQ7dVBK8t1ah2UdBS4pSHgjhDulo0hr4gIubQ0FSV+8cWCNN' }    
+end
+
+describe user('raki') do
+  it { should_not exist }
+end
+
+

+ 35 - 0
galaxy-roles/usermanage/test/integration/source-databag/serverspec/test_spec.rb

@@ -0,0 +1,35 @@
+require 'serverspec'
+
+# Required by serverspec
+set :backend, :exec
+
+describe user('bbreezer') do
+  it { should exist }
+  it { should belong_to_group 'group2' }
+  it { should belong_to_group 'group1' }
+  it { should belong_to_group 'group3' }
+  it { have_login_shell 'bin/bash' }
+  it { should have_authorized_key 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCun7TGUhQ1JoWkdtroI4ufEnf/cPWn5mIitu8+eTtMK/yS71CuEhf8f6IkKMuSd5L9PHiIAYd0o87pJ952sUsDdLpk7NPhxVod7ADa7uC+FnFrJ0tgyUlPpe0XC77H1T9abpQ2fAOsC5F+fuWQSBxJyczS6tOIz7b25SUBSTA5ObM4bP0LEE2CJ4uegNpmPn73LAhYgRU43VCH4+w7QmNUHdhkcuVIVNiK2Kt7o3KXP8OjbrdQLCdG2aCMEITrTljHPazhbAgkMnEKLY28fWJpJTIzRCSdEXhdsJMS/nzszPCXvJiol6xOvbcYooYg9c9auMQJUn7EpR062VmlPXuP bbreezer1' }
+  #system  : true
+end
+
+describe user('ebacardi') do
+  it { should exist }
+  it { should belong_to_group 'group2' }
+  it { should belong_to_group 'group1' }
+  it { have_login_shell 'bin/sh' }
+  it { should have_authorized_key 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDIg6ennnJMC9Ogw55LdVZnpfiaaQLDrAQoWPeFWOld8CCql5JDARY8N+/Zr+SxxHQBb4KqXZidE73u8srEtXcS1YTlDMLK2+KIKPb8TJl4ksChBUv3XM95VDGT0AVUy4yW8v3PTKVlSA9b8yUBOcMQfDd1wtGsyL/Hjq9m0Jev+fXUV7vsVJXtV6OQOEwH8ag6NtdgQ34FdDqCUHK+vNtzrr6zXrgUj38NeAdNlb/WlaSFUlnCiRoohTk/9m3+bcne3Q84o5AzxYvB1d7azpVQFrBQABRR/hyTr07nSdBm5x4RUY35rGT4YTSrslvY+605nZon6beoK81jmcJdi9S1 ebacardi' }
+end
+
+describe user('fbacardi') do
+  it { should_not exist }
+end
+
+describe user('daniels') do
+  it { should_not exist }
+end
+
+describe user('whisky') do
+  it { should exist }
+  it { should have_authorized_key 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDLql1khoXEH/pThpLSDwJNBIEHkjrBggjEvRCqCFYvE1Neavc6iuLSzjLdnj74LNrPEjY+xcjAcPmgwxo8+WKpLL7Iy8e9IGH3lwB05x9jfnw2H1ZRnZZxF+wV/ei/vfCmRyt2cqv+DLomg18RDTnyTk2pvSEvL0xkRn5QRbzxqbnB+9xmItTjdtq/ZDYRgFYn2ZPfokFyyr3KpwpK0gNcpFhCF94CvExKpu6SFPTv+ERnFvHEN9d8SlzwkyCP4yqrfOjFuVUuZf2FtAkDx0d4cXo0i7VUM/hOthUNFpmljZLhkxafPxwp50Q/xRe7MvDQMrEPGPZ/pubOwzqVmxxx' }
+end

+ 21 - 0
galaxy-roles/usermanage/test/integration/source-files/serverspec/test_spec.rb

@@ -0,0 +1,21 @@
+require 'serverspec'
+
+# Required by serverspec
+set :backend, :exec
+
+describe user('user1_yaml') do
+  it { should exist }
+  it { have_login_shell '/bin/true' }
+  it { should have_authorized_key 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDfIG0Zqxtj+OGordHLn82CWzRXA3++D5BdevRx7kCJE50gRhuUbc2lImBbLE+1JRlzwpg+a1AWbM1MTiHJyLbw7e4+KxfUaPxclktvrCD3xqN/Pn0ncgCcZNFrXfeP4RbHN143qzy8ri0Vn4o/3OYK9KZGkfIT+ix8TpD6804LLjrgmgFcEDxJILFNeVL187vfoGdhh/Wed4JMZSWjiXMjA9WHzFkYDWW6HhlmmjNrXQvaQTWpmDAABvP918N7LLf8KuhTcXfyWrVOCpc0jNZKOtzvScixOi2licUkJ/xlGYbirr8cmV9gS+5UzUdzMstZeiKNXkU7imcInsSk5BFv yaml1' }
+end
+
+describe user('user2_yaml') do
+  it { should exist }
+  it { should have_authorized_key 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDXfwZI7qSBnqEwlxWFBQt9YpdhR7bHYbtcRuy77EmAu1VPZmfn+pIDLUXn5sTOZQxzXN32GohJOlC8vW63WMnROVRlI3yVjspcmxEcHeATsFEKfg2JDdH2m88fiG2JaVFBnV9N/obfGZiWCRxmjodttyETw/nvTzAQTczvalO0lm0bkfgkiGffFREucQikf+ZRbgRQmIZxNX2dYMN5nNIcRXjv+2z//N30J22Lzmo0JXRmByBIkCG+QVrvc3UudJ2prkebDp60CoTiPgA9nnpLxYbBbX4QU/q/sYTwb/wMv8g+4AENEJ8RWPIcpLXt65vTUcpbPTuEM8egfSDtlwph yaml2' }
+end
+
+describe user('user3_json') do
+  it { should exist }
+  it { should have_authorized_key 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDY3q7JKLPiPawSUK6NIJWKMl1EV9ORJkqrMIQsxanYQyElWw3Y+aj9Kbtl37hbQIYtHVb2y43e26MjlY8XfpHGRtKxtR6t+oIgxVNV3paT31OkJSiLgNS8yn7+JbyeTSu7UN2XdPZgSIF8yCWmNFvwRkW+TsRwCobXJqDwzhSx/BphLqR9ADV+nCyfhG3T/BgJ8XWsio60cOTl/Qy9aIcyDOdsu/HJtB7hIAfxbSMksocMnssJYds3wMQnNYwGVEbHVzJk8priR8GsGBgT8Bh83JmB+gDBXEfT4hRfJ0eC4ekwLAH/bg9IZhfOOQJMQHdk16HL32XNM3TPQiy9845D user3_json' }
+end
+

+ 46 - 0
galaxy-roles/usermanage/test/integration/team/serverspec/test_spec.rb

@@ -0,0 +1,46 @@
+require 'serverspec'
+
+# Required by serverspec
+set :backend, :exec
+
+describe user('daniels') do
+  it { should exist }
+  it { should belong_to_group 'group2' }
+  it { should belong_to_group 'group1' }  
+  it { should have_authorized_key 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDLql1khoXEH/pThpLSDwJNBIEHkjrBggjEvRCqCFYvE1Neavc6iuLSzjLdnj74LNrPEjY+xcjAcPmgwxo8+WKpLL7Iy8e9IGH3lwB05x9jfnw2H1ZRnZZxF+wV/ei/vfCmRyt2cqv+DLomg18RDTnyTk2pvSEvL0xkRn5QRbzxqbnB+9xmItTjdtq/ZDYRgFYn2ZPfokFyyr3KpwpK0gNcpFhCF94CvExKpu6SFPTv+ERnFvHEN9d8SlzwkyCP4yqrfOjFuVUuZf2FtAkDx0d4cXo0i7VUM/hOthUNFpmljZLhkxafPxwp50Q/xRe7MvDQMrEPGPZ/pubOwzqVmMWH' }
+
+  it { should have_authorized_key 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCxAqbTlltSFlRY+gQyAx3j0W+WDnahZYbECAXiwNqAHG7PP8GSEDVkfZTkJdlu9PoB/B3nW2R/Q3//IxUfzRsUnjUzl0WXbhz331n5bHtgJlg82MGqwbNjN0yMR/GB4pQKeExYOLKi/7jI/wkOAJ4X9Bv9skEK/mHAWWPrBf/5C5qWUOxVC1+he3iaU+LSbiL6uiNs8S49fiGno8tBkBFgth+9gqdCLRAFVe2dzJJK1nSQTffHCs12pJs2S3yBD9KkUQJO51tByP4qO3549iwLo8hQnqtFULMpL+NN5Muk1bFZ2jW+0Sri1bhVS58llZCuoENZsLf/+xejbfwJAk4h' }  
+  #key_options : 'no-port-forwarding'
+end
+
+describe user('vodka') do
+  it { should exist }
+  it { should have_uid 3300 }  
+  it { should belong_to_group 'group2' }
+  it { should belong_to_group 'group1' }  
+  it { should have_authorized_key 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC2Pq3M7AgeBjmNII6HGsKd2uaXFIfaljpNg1Rf6y3iGP84wC82bMfZTSIhnzJ4qwHj7Bzn8oiMmqtyeGcmEwLXm5f7mk3lj9NmxUEfbuWsPoSX4VHIney0F2cjrYRAHua8vZ50OrqYvRaBNttx+pCsub/Kw/t91PQvz7s5ML12DfhlfbE5f/g+ZrKHBxsn6Vw0VqN1Cx5cecaN+9NbdwTV25/RVsXC6v9TQlIqWR+znt4ZVxUSCTAbGc51tmauoleZee2XBkAO7xmJ7zPQEndhErq/zm0euZGx1xGIjQ7dVBK8t1ah2UdBS4pSHgjhDulo0hr4gIubQ0FSV+8cWCNN' }
+end
+
+describe user('pepsi') do
+  it { should exist }
+  it { should have_uid 3400 }  
+  it { have_login_shell '/bin/false' }
+  it { should have_authorized_key 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCcoo+eU8+k7QYpKbZwOQwiMpeklQcmEyLTsJr0RLTeqsHkIh8rFWyMZURDZ5pgEGo3iXZD+dqM28agy2Pw68/V0wht/9n0PjmUVZgkWIas162w3vZrJENDi8wAo4ojQJf0lZf63K8AxoB12fF+QdR7jfTLrz2bCxv9XaHKm7nYGtRO0f8ETgvwpIS2jN0mPAD7qnCFvLtbaxd/UzsQS5M8Au42+9zdn78Atm7gtKY9uR5U1Jwrop8KipXf0wAtMo39Xc9P8hGbYGA1jkbcG2x1LI7G9L+PddxeZjpkW2Uv559YJDRjBJfJAfp6K4HGV5uXITSMVDY9KBYvepolrlul' }
+end
+
+describe user('coca') do
+  it { should exist }
+  it { should have_authorized_key 'ssh-rsa AAAAB3NzaC2EAA1ycAADAAAQABABAQCootXD63hexEQnbCmKGC7DjFSWxkqJ2neaC5S6POEdgwo7jQ60JWy0VCm5JS5d2ZNDQh+vi1wZ2cTr6n9X9bAkYhQ/eACmzYBjf8I8AXcqaigAOjRMLADU2qQfZmnRGyOLaGDI/EH52yBjeZHbgQdJOGrB07qgAu2facA2bd6kvI8eLwCx5yjqA+mInYEewRYrr5tUduGFdPhmyoKSGpaEeWWkLhafTj9eGRMSB3unBcMtux+LxXH4TfWgVBmWNVbr2Mcv+M6tYxix/iKniBLBUH/AfM/dTHlk38y2mjemUMUc/HBW+HmH3NXMwOks8po6Iohh8JNhywUlLKN9MvB7' }
+end
+
+describe user('stewart') do
+  it { should_not exist }
+end	
+
+describe user('raki') do
+  it { should_not exist }
+end	
+
+describe user('label') do
+  it { should_not exist }
+end	

+ 1 - 0
galaxy-roles/usermanage/test/local.ini

@@ -0,0 +1 @@
+localhost ansible_connection='local'

+ 18 - 0
galaxy-roles/usermanage/test/run_vagrant_kitchen.sh

@@ -0,0 +1,18 @@
+#!/usr/bin/env bash
+set -e
+echo "**** Box setup ***"
+
+echo "* mkdir /kitchen"
+mkdir -p /kitchen
+
+#echo "* cp -ar /mnt/shared /kitchen"
+#cp -r /mnt/shared/. /kitchen
+echo "* ln -sf /mnt/shared /kitchen"
+ln -sf /mnt/shared/* /kitchen/
+
+echo "* cd /kitchen"
+cd /kitchen/*
+
+echo "* python test/travis_run.py"
+python test/travis_run.py
+

+ 98 - 0
galaxy-roles/usermanage/test/travis_run.py

@@ -0,0 +1,98 @@
+#!/usr/bin/env python
+# https://github.com/ahelal/travis-in-box
+
+import yaml
+import subprocess
+import sys
+import os.path
+
+
+class TravisExec(object):
+    def __init__(self, filename="travis.yml"):
+        self.fail = False
+        stream = open(filename, 'r')
+        yaml_file = yaml.load(stream)
+        # language
+        self.language = yaml_file.get("language", None)
+
+        # Section
+        self.section_before_install = yaml_file.get("before_install", None)
+        self.section_install = yaml_file.get("install", None)
+        self.section_before_script = yaml_file.get("before_script", None)
+        self.section_script = yaml_file.get("script", None)
+
+        #self.section_after_script = yaml_file.get("after_script", None)
+        self.section_after_failure = yaml_file.get("after_failure", None)
+        self.section_after_success = yaml_file.get("after_success", None)
+
+    def _setup(self):
+        if self.language == "python":
+            print "********** Setup Python  **********"
+            print ""
+            # Since we are not using container we have to install various lang our self
+            # So this is probably not the best way to do it
+            self._execute_command(["sudo apt-get install python-setuptools python-pip -y"])
+        else:
+            print "Errors unsupported language {}".format(self.language)
+            exit(1)
+
+    def life_cycle(self):
+        # See http://docs.travis-ci.com/user/build-configuration/
+
+            # 1. setup language
+            self._setup()
+            # 4. Run before_install commands
+            self.run_command("before_install", self.section_before_install, self.section_after_failure)
+            # 5. Run install commands
+            self.run_command("install", self.section_install, self.section_after_failure)
+            # 6. Run before_script commands
+            self.run_command("before_script", self.section_before_script, self.section_after_failure)
+            # 7. Run test script commands
+            self.run_command("script", self.section_script, self.section_after_failure)
+            # 8 . if we reach this point we made it run after_success
+            self.run_command("after_success", self.section_after_success, None)
+
+    @staticmethod
+    def _execute_command(command):
+        new_command = ["echo '> " + item.rstrip('\n') + "' && { " + item.rstrip('\n') + " ; }" for item in command]
+        new_command = " && ".join(new_command)
+
+        p = subprocess.Popen(new_command, shell=True, stderr=subprocess.PIPE)
+        while True:
+            out = p.stderr.read(1)
+            if out == '' and p.poll() is not None:
+                break
+            if out != '':
+                sys.stdout.write(out)
+                sys.stdout.flush()
+        print ""
+        return p.returncode
+
+    def run_command(self, section_name=None, command=None, execute_on_failure=None):
+        if command:
+            print ""
+            print "********** Running '{}' **********".format(section_name)
+            return_code = self._execute_command(command)
+            if return_code != 0:
+                print ""
+                print "********** Failed in '{}' **********".format(section_name)
+                if execute_on_failure:
+                    print ""
+                    print "********** Running after_failure  **********".format(section_name)
+                    self._execute_command(execute_on_failure)
+                    exit(1)
+
+filename = None
+if len(sys.argv) == 1:
+    filename = ".travis.yml"
+elif len(sys.argv) == 2:
+    filename = sys.argv[1]
+else:
+    print "Invalid number of arguments"
+    exit(1)
+
+if os.path.exists(filename):
+    TravisExec(filename).life_cycle()
+else:
+    print "Could not file travis file '{}'".format(filename)
+    exit(1)

+ 3 - 0
requirements.yml

@@ -0,0 +1,3 @@
+- src: https://github.com/ahelal/ansible-usermanage
+  version: master
+  name: usermanage