Implemented jenkins user enforcing by script API from client side
diff --git a/_modules/jenkins_common.py b/_modules/jenkins_common.py
index fcb8984..e4ae5d8 100644
--- a/_modules/jenkins_common.py
+++ b/_modules/jenkins_common.py
@@ -47,8 +47,8 @@
     """
     Helper method for rendering groovy script with props
 
-    :param name: groovy script tempalte
-    :param scope: groovy script properties
+    :param script: groovy script template
+    :param props: groovy script properties
     :returns: generated groovy script
     """
     return script.format(**props)
@@ -77,7 +77,7 @@
         return None
     else:
         raise Exception("Cannot obtain Jenkins API crumb. Status code: %s. Text: %s" %
-                        tokenReq.status_code, tokenReq.text)
+                        (tokenReq.status_code, tokenReq.text))
 
 
 
diff --git a/_states/jenkins_users.py b/_states/jenkins_users.py
new file mode 100644
index 0000000..29a2f64
--- /dev/null
+++ b/_states/jenkins_users.py
@@ -0,0 +1,59 @@
+import logging
+logger = logging.getLogger(__name__)
+
+create_admin_groovy = u"""\
+import jenkins.model.*
+import hudson.security.*
+def instance = Jenkins.getInstance()
+def hudsonRealm = new HudsonPrivateSecurityRealm(false)
+def result=hudsonRealm.createAccount("{username}","{password}")
+instance.setSecurityRealm(hudsonRealm)
+def strategy = new hudson.security.FullControlOnceLoggedInAuthorizationStrategy()
+strategy.setAllowAnonymousRead(false)
+instance.setAuthorizationStrategy(strategy)
+instance.save()
+print(result)
+"""  #noqa
+
+
+create_user_groovy = u"""\
+def result=jenkins.model.Jenkins.instance.securityRealm.createAccount("{username}", "{password}")
+print(result)
+"""  # noqa
+
+
+def present(name, username, password, admin=False):
+    """
+    Main jenkins users state method
+
+    :param username: user name
+    :param password: user password
+    :param admin:  is admin user flag (username will be always admin)
+    :returns: salt-specified state dict
+    """
+    test = __opts__['test']  # noqa
+    ret = {
+        'name': username,
+        'changes': {},
+        'result': False,
+        'comment': '',
+    }
+
+    result = False
+    if test:
+        status = 'CREATED'
+        ret['changes'][username] = status
+        ret['comment'] = 'User %s %s' % (username, status.lower())
+    else:
+        call_result = __salt__['jenkins_common.call_groovy_script'](create_admin_groovy if admin else create_user_groovy, {"username": username, "password":password})
+        if call_result["code"] == 200 and call_result["msg"].count(username) == 1:
+            status = "CREATED" if not admin else "ADMIN CREATED"
+            ret['changes'][username] = status
+            ret['comment'] = 'User %s %s' % (username, status.lower())
+            result = True
+        else:
+            status = 'FAILED'
+            logger.error("Jenkins user API call failure: %s", call_result["msg"])
+            ret['comment'] = 'Jenkins user API call failure: %s' % (call_result["msg"])
+    ret['result'] = None if test else result
+    return ret
diff --git a/jenkins/client/init.sls b/jenkins/client/init.sls
index c89954a..a31d0a1 100644
--- a/jenkins/client/init.sls
+++ b/jenkins/client/init.sls
@@ -5,6 +5,8 @@
   - jenkins.client.source
   - jenkins.client.job
   - jenkins.client.credential
+  - jenkins.client.user
+  
 jenkins_client_install:
   pkg.installed:
   - names: {{ client.pkgs }}
diff --git a/jenkins/client/user.sls b/jenkins/client/user.sls
new file mode 100644
index 0000000..ca8b377
--- /dev/null
+++ b/jenkins/client/user.sls
@@ -0,0 +1,9 @@
+{% from "jenkins/map.jinja" import client with context %}
+
+{% for name, user in client.get('user',{}).iteritems() %}
+user_{{ name }}:
+  jenkins_user.present:
+  - username: {{ name }}
+  - password: {{ user.password }}
+  - admin: {{ user.get('admin', False) }}
+{% endfor %}
\ No newline at end of file