You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ranger.apache.org by ma...@apache.org on 2020/12/14 18:40:28 UTC

[ranger] branch master updated: RANGER-3114: updated Python client with more samples, and some refactoring

This is an automated email from the ASF dual-hosted git repository.

madhan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ranger.git


The following commit(s) were added to refs/heads/master by this push:
     new fa3e3d6  RANGER-3114: updated Python client with more samples, and some refactoring
fa3e3d6 is described below

commit fa3e3d6e1753eff062d73ba3eca57f71435e8bea
Author: Madhan Neethiraj <ma...@apache.org>
AuthorDate: Fri Dec 11 18:54:48 2020 -0800

    RANGER-3114: updated Python client with more samples, and some refactoring
---
 .gitignore                                         |   7 +
 intg/src/main/python/README.md                     |  91 ++-
 .../python/apache_ranger/client/ranger_client.py   | 618 ++++++++++-----------
 intg/src/main/python/apache_ranger/exceptions.py   |  45 ++
 .../model/grant_revoke_role_request.py             |  34 +-
 .../main/python/apache_ranger/model/ranger_base.py |  51 +-
 .../python/apache_ranger/model/ranger_policy.py    | 198 ++++---
 .../main/python/apache_ranger/model/ranger_role.py |  41 +-
 .../apache_ranger/model/ranger_security_zone.py    |  40 +-
 .../python/apache_ranger/model/ranger_service.py   |  36 +-
 .../apache_ranger/model/ranger_service_def.py      | 295 ++++++----
 intg/src/main/python/apache_ranger/utils.py        |  92 +++
 intg/src/main/python/setup.py                      |  20 +-
 .../sample-client/src/main/python/sample_client.py | 319 ++++++++---
 14 files changed, 1162 insertions(+), 725 deletions(-)

diff --git a/.gitignore b/.gitignore
index e351815..9768b79 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,3 +10,10 @@
 winpkg/target
 .DS_Store
 .idea
+
+#Python
+*.pyc
+**/build
+**/dist
+**/apache_ranger.egg-info
+.python-version
diff --git a/intg/src/main/python/README.md b/intg/src/main/python/README.md
index 4426d10..a70fdac 100644
--- a/intg/src/main/python/README.md
+++ b/intg/src/main/python/README.md
@@ -19,8 +19,7 @@ under the License.
 
 # Apache Ranger - Python client
 
-This is a python library for Apache Ranger. Users can integrate with Apache Ranger using the python client.
-Currently, compatible with Python 3.5+
+Python library for Apache Ranger.
 
 ## Installation
 
@@ -36,33 +35,89 @@ Verify if apache-ranger client is installed:
 
 Package      Version
 ------------ ---------
-apache-ranger 0.0.2
+apache-ranger 0.0.3
 ```
 
 ## Usage
 
-```python init_dev_hive.py```
+```python test_ranger.py```
 ```python
-# init_dev_hive.py
+# test_ranger.py
 
-from apache_ranger.model.ranger_service import RangerService
-from apache_ranger.client.ranger_client import RangerClient
-from apache_ranger.model.ranger_policy  import RangerPolicy, RangerPolicyResource, RangerPolicyItem, RangerPolicyItemAccess
+from apache_ranger.model.ranger_service import *
+from apache_ranger.client.ranger_client import *
+from apache_ranger.model.ranger_policy  import *
 
-service_name = 'dev_hive'
 
-service = RangerService(name=service_name, type='hive')
-service.configs = {'username':'hive', 'password':'hive', 'jdbc.driverClassName': 'org.apache.hive.jdbc.HiveDriver', 'jdbc.url': 'jdfb:hive2://ranger-hadoop:10000', 'hadoop.security.authorization': 'true'}
+## Step 1: create a client to connect to Apache Ranger admin
+ranger_url  = 'http://localhost:6080'
+ranger_auth = ('admin', 'rangerR0cks!')
 
-policy = RangerPolicy(service=service_name, name='test policy')
-policy.resources = {'database': RangerPolicyResource(['test_db']), 'table': RangerPolicyResource(['test_tbl']), 'column': RangerPolicyResource(['*'])}
-policy.policyItems.append(RangerPolicyItem(users=['admin'], accesses=[RangerPolicyItemAccess('create'), RangerPolicyItemAccess('alter'), RangerPolicyItemAccess('drop')], delegateAdmin=True))
-policy.denyPolicyItems.append(RangerPolicyItem(users=['admin'], accesses=[RangerPolicyItemAccess('select')]))
+# For Kerberos authentication
+#
+# from requests_kerberos import HTTPKerberosAuth
+#
+# ranger_auth = HTTPKerberosAuth()
 
+ranger = RangerClient(ranger_url, ranger_auth)
 
-ranger_client   = RangerClient('http://localhost:6080', 'admin', 'rangerR0cks!')
-created_service = ranger_client.create_service(service)
-created_policy  = ranger_client.create_policy(policy)
+# to disable SSL certificate validation (not recommended for production use!)
+#
+# ranger.session.verify = False
+
+
+## Step 2: Let's create a service
+service         = RangerService()
+service.name    = 'test_hive'
+service.type    = 'hive'
+service.configs = {'username':'hive', 'password':'hive', 'jdbc.driverClassName': 'org.apache.hive.jdbc.HiveDriver', 'jdbc.url': 'jdbc:hive2://ranger-hadoop:10000', 'hadoop.security.authorization': 'true'}
+
+print('Creating service: name=' + service.name)
+
+created_service = ranger.create_service(service)
+
+print('    created service: name=' + created_service.name + ', id=' + str(created_service.id))
+
+
+## Step 3: Let's create a policy
+policy           = RangerPolicy()
+policy.service   = service.name
+policy.name      = 'test policy'
+policy.resources = { 'database': RangerPolicyResource({ 'values': ['test_db'] }),
+                     'table':    RangerPolicyResource({ 'values': ['test_tbl'] }),
+                     'column':   RangerPolicyResource({ 'values': ['*'] }) }
+
+allowItem1          = RangerPolicyItem()
+allowItem1.users    = [ 'admin' ]
+allowItem1.accesses = [ RangerPolicyItemAccess({ 'type': 'create' }),
+                        RangerPolicyItemAccess({ 'type': 'alter' }) ]
+
+denyItem1          = RangerPolicyItem()
+denyItem1.users    = [ 'admin' ]
+denyItem1.accesses = [ RangerPolicyItemAccess({ 'type': 'drop' }) ]
+
+policy.policyItems     = [ allowItem1 ]
+policy.denyPolicyItems = [ denyItem1 ]
+
+print('Creating policy: name=' + policy.name)
+
+created_policy = ranger.create_policy(policy)
+
+print('    created policy: name=' + created_policy.name + ', id=' + str(created_policy.id))
+
+
+## Step 4: Delete policy and service created above
+print('Deleting policy: id=' + str(created_policy.id))
+
+ranger.delete_policy_by_id(created_policy.id)
+
+print('    deleted policy: id=' + str(created_policy.id))
+
+print('Deleting service: id=' + str(created_service.id))
+
+ranger.delete_service_by_id(created_service.id)
+
+print('    deleted service: id=' + str(created_service.id))
 
 ```
 For more examples, checkout `sample-client` python  project in [ranger-examples](https://github.com/apache/ranger/blob/master/ranger-examples/sample-client/src/main/python/sample_client.py) module.
diff --git a/intg/src/main/python/apache_ranger/client/ranger_client.py b/intg/src/main/python/apache_ranger/client/ranger_client.py
index c95d0d9..67b21c2 100644
--- a/intg/src/main/python/apache_ranger/client/ranger_client.py
+++ b/intg/src/main/python/apache_ranger/client/ranger_client.py
@@ -17,475 +17,425 @@
 # limitations under the License.
 
 
-import enum
 import json
 import logging
-import requests
+import os
 
-from http     import HTTPStatus
 from requests import Session, Response
 
+from apache_ranger.exceptions                 import RangerServiceException
+from apache_ranger.model.ranger_base          import RangerBase
 from apache_ranger.model.ranger_role          import RangerRole
 from apache_ranger.model.ranger_policy        import RangerPolicy
 from apache_ranger.model.ranger_service       import RangerService
 from apache_ranger.model.ranger_service_def   import RangerServiceDef
 from apache_ranger.model.ranger_security_zone import RangerSecurityZone
+from apache_ranger.utils                      import *
 
 
-APPLICATION_JSON = 'application/json'
 
-requests.packages.urllib3.disable_warnings()
-
-log = logging.getLogger(__name__)
-
-class Message:
-    def __init__(self, name=None, rbKey=None, message=None, objectId=None, fieldName=None):
-        self.name      = name
-        self.rbKey     = rbKey
-        self.message   = message
-        self.objectId  = objectId
-        self.fieldName = fieldName
-
-    def __repr__(self):
-        return json.dumps(self, default=lambda x: x.__dict__, sort_keys=True, indent=4)
-
-
-class RESTResponse:
-    def __init__(self, httpStatusCode=None, statusCode=None, msgDesc=None, messageList=None):
-        self.httpStatusCode = httpStatusCode
-        self.statusCode     = statusCode
-        self.msgDesc        = msgDesc
-        self.messageList    = messageList if messageList is not None else []
-
-    def __repr__(self):
-        return json.dumps(self, default=lambda x: x.__dict__, sort_keys=True, indent=4)
-
-
-class HttpMethod(enum.Enum):
-    GET    = "GET"
-    PUT    = "PUT"
-    POST   = "POST"
-    DELETE = "DELETE"
-
-
-class API:
-    def __init__(self, path, method, expected_status, consumes=APPLICATION_JSON, produces=APPLICATION_JSON):
-        self.path            = path
-        self.method          = method
-        self.expected_status = expected_status
-        self.consumes        = consumes
-        self.produces        = produces
-
-    def call(self, session, baseUrl, params, request):
-        session.headers['Accept']       = self.consumes
-        session.headers['Content-type'] = self.produces
-
-        if log.isEnabledFor(logging.DEBUG):
-            log.debug('==> call({},{},{})'.format(self, params, request))
-            log.debug('------------------------------------------------------')
-            log.debug('Call         : {} {}'.format(self.method, self.path))
-            log.debug('Content-type : {}'.format(self.consumes))
-            log.debug('Accept       : {}'.format(self.produces))
-
-            if request is not None:
-                log.debug("Request      : {}".format(request))
-
-        path = baseUrl + self.path
-
-        if self.method == HttpMethod.GET:
-            client_response = session.get(path)
-        elif self.method == HttpMethod.POST:
-            client_response = session.post(path, data=request.__repr__())
-        elif self.method == HttpMethod.PUT:
-            client_response = session.put(path, data=request.__repr__())
-        elif self.method == HttpMethod.DELETE:
-            client_response = session.delete(path, params=params)
-        else:
-            raise Exception('Unsupported HTTP Method {}'.format(self.method))
-
-        if client_response.status_code == self.expected_status:
-            if client_response.content:
-                if log.isEnabledFor(logging.DEBUG):
-                    log.debug('Response: {}'.format(client_response.text))
-            else:
-                return None
-        elif client_response.status_code == HTTPStatus.SERVICE_UNAVAILABLE:
-            log.error('Ranger Admin unavailable. HTTP Status: {}'.format(HTTPStatus.SERVICE_UNAVAILABLE))
-            log.error("client_response=: {}" + str(client_response))
-            return None
-        else:
-            raise Exception(client_response.text)
-
-        __json = json.loads(str(json.dumps(client_response.json())))
-
-        if log.isEnabledFor(logging.DEBUG):
-            log.debug('<== call({},{},{}), result = {}'.format(self, params, request, client_response))
-
-        return __json
-
-    def apply_url_params(self, params):
-        try:
-            return API(self.path.format(**params), self.method, self.expected_status, self.consumes, self.produces)
-        except (KeyError, TypeError) as e:
-            log.error('Arguments not formatted properly' + str(e))
-            raise e
+LOG = logging.getLogger(__name__)
 
 
 class RangerClient:
-    # Query Params
-    PARAM_ID                            = "id"
-    PARAM_NAME                          = "name"
-    PARAM_DAYS                          = "days"
-    PARAM_EXEC_USER                     = "execUser"
-    PARAM_POLICY_NAME                   = "policyname"
-    PARAM_SERVICE_NAME                  = "serviceName"
-    PARAM_RELOAD_SERVICE_POLICIES_CACHE = "reloadServicePoliciesCache"
-
-    # URIs
-    URI_BASE = "/service/public/v2/api"
-
-    URI_SERVICEDEF         = URI_BASE + "/servicedef"
-    URI_SERVICEDEF_BY_ID   = URI_SERVICEDEF + "/{id}"
-    URI_SERVICEDEF_BY_NAME = URI_SERVICEDEF + "/name/{name}"
-
-    URI_SERVICE             = URI_BASE + "/service"
-    URI_SERVICE_BY_ID       = URI_SERVICE + "/{id}"
-    URI_SERVICE_BY_NAME     = URI_SERVICE + "/name/{name}"
-    URI_POLICIES_IN_SERVICE = URI_SERVICE + "/{serviceName}/policy"
-
-    URI_POLICY         = URI_BASE + "/policy"
-    URI_APPLY_POLICY   = URI_POLICY + "/apply"
-    URI_POLICY_BY_ID   = URI_POLICY + "/{id}"
-    URI_POLICY_BY_NAME = URI_SERVICE + "/{serviceName}/policy/{policyname}"
-
-    URI_ROLE         = URI_BASE + "/roles"
-    URI_ROLE_NAMES   = URI_ROLE + "/names"
-    URI_ROLE_BY_ID   = URI_ROLE + "/{id}"
-    URI_ROLE_BY_NAME = URI_ROLE + "/name/{name}"
-    URI_USER_ROLES   = URI_ROLE + "/user/{name}"
-    URI_GRANT_ROLE   = URI_ROLE + "/grant/{name}"
-    URI_REVOKE_ROLE  = URI_ROLE + "/revoke/{name}"
-
-    URI_ZONE         = URI_BASE + "/zones"
-    URI_ZONE_BY_ID   = URI_ZONE + "/{id}"
-    URI_ZONE_BY_NAME = URI_ZONE + "/name/{name}"
+    def __init__(self, url, auth):
+        self.url          = url
+        self.session      = Session()
+        self.session.auth = auth
 
-    URI_PLUGIN_INFO   = URI_BASE + "/plugins/info"
-    URI_POLICY_DELTAS = URI_BASE + "/server/policydeltas"
+        logging.getLogger("requests").setLevel(logging.WARNING)
 
-    # APIs
-    CREATE_SERVICEDEF         = API(URI_SERVICEDEF, HttpMethod.POST, HTTPStatus.OK)
-    UPDATE_SERVICEDEF_BY_ID   = API(URI_SERVICEDEF_BY_ID, HttpMethod.PUT, HTTPStatus.OK)
-    UPDATE_SERVICEDEF_BY_NAME = API(URI_SERVICEDEF_BY_NAME, HttpMethod.PUT, HTTPStatus.OK)
-    DELETE_SERVICEDEF_BY_ID   = API(URI_SERVICEDEF_BY_ID, HttpMethod.DELETE, HTTPStatus.NO_CONTENT)
-    DELETE_SERVICEDEF_BY_NAME = API(URI_SERVICEDEF_BY_NAME, HttpMethod.DELETE, HTTPStatus.NO_CONTENT)
-    GET_SERVICEDEF_BY_ID      = API(URI_SERVICEDEF_BY_ID, HttpMethod.GET, HTTPStatus.OK)
-    GET_SERVICEDEF_BY_NAME    = API(URI_SERVICEDEF_BY_NAME, HttpMethod.GET, HTTPStatus.OK)
-    FIND_SERVICEDEFS          = API(URI_SERVICEDEF, HttpMethod.GET, HTTPStatus.OK)
-
-    CREATE_SERVICE         = API(URI_SERVICE, HttpMethod.POST, HTTPStatus.OK)
-    UPDATE_SERVICE_BY_ID   = API(URI_SERVICE_BY_ID, HttpMethod.PUT, HTTPStatus.OK)
-    UPDATE_SERVICE_BY_NAME = API(URI_SERVICE_BY_NAME, HttpMethod.PUT, HTTPStatus.OK)
-    DELETE_SERVICE_BY_ID   = API(URI_SERVICE_BY_ID, HttpMethod.DELETE, HTTPStatus.NO_CONTENT)
-    DELETE_SERVICE_BY_NAME = API(URI_SERVICE_BY_NAME, HttpMethod.DELETE, HTTPStatus.NO_CONTENT)
-    GET_SERVICE_BY_ID      = API(URI_SERVICE_BY_ID, HttpMethod.GET, HTTPStatus.OK)
-    GET_SERVICE_BY_NAME    = API(URI_SERVICE_BY_NAME, HttpMethod.GET, HTTPStatus.OK)
-    FIND_SERVICES          = API(URI_SERVICE, HttpMethod.GET, HTTPStatus.OK)
-
-    CREATE_POLICY           = API(URI_POLICY, HttpMethod.POST, HTTPStatus.OK)
-    UPDATE_POLICY_BY_ID     = API(URI_POLICY_BY_ID, HttpMethod.PUT, HTTPStatus.OK)
-    UPDATE_POLICY_BY_NAME   = API(URI_POLICY_BY_NAME, HttpMethod.PUT, HTTPStatus.OK)
-    APPLY_POLICY            = API(URI_APPLY_POLICY, HttpMethod.POST, HTTPStatus.OK)
-    DELETE_POLICY_BY_ID     = API(URI_POLICY_BY_ID, HttpMethod.DELETE, HTTPStatus.NO_CONTENT)
-    DELETE_POLICY_BY_NAME   = API(URI_POLICY, HttpMethod.DELETE, HTTPStatus.NO_CONTENT)
-    GET_POLICY_BY_ID        = API(URI_POLICY_BY_ID, HttpMethod.GET, HTTPStatus.OK)
-    GET_POLICY_BY_NAME      = API(URI_POLICY_BY_NAME, HttpMethod.GET, HTTPStatus.OK)
-    GET_POLICIES_IN_SERVICE = API(URI_POLICIES_IN_SERVICE, HttpMethod.GET, HTTPStatus.OK)
-    FIND_POLICIES           = API(URI_POLICY, HttpMethod.GET, HTTPStatus.OK)
-
-    CREATE_ZONE         = API(URI_ZONE, HttpMethod.POST, HTTPStatus.OK)
-    UPDATE_ZONE_BY_ID   = API(URI_ZONE_BY_ID, HttpMethod.PUT, HTTPStatus.OK)
-    UPDATE_ZONE_BY_NAME = API(URI_ZONE_BY_NAME, HttpMethod.PUT, HTTPStatus.OK)
-    DELETE_ZONE_BY_ID   = API(URI_ZONE_BY_ID, HttpMethod.DELETE, HTTPStatus.NO_CONTENT)
-    DELETE_ZONE_BY_NAME = API(URI_ZONE_BY_NAME, HttpMethod.DELETE, HTTPStatus.NO_CONTENT)
-    GET_ZONE_BY_ID      = API(URI_ZONE_BY_ID, HttpMethod.GET, HTTPStatus.OK)
-    GET_ZONE_BY_NAME    = API(URI_ZONE_BY_NAME, HttpMethod.GET, HTTPStatus.OK)
-    FIND_ZONES          = API(URI_ZONE, HttpMethod.GET, HTTPStatus.OK)
-
-    CREATE_ROLE         = API(URI_ROLE, HttpMethod.POST, HTTPStatus.OK)
-    UPDATE_ROLE_BY_ID   = API(URI_ROLE_BY_ID, HttpMethod.PUT, HTTPStatus.OK)
-    DELETE_ROLE_BY_ID   = API(URI_ROLE_BY_ID, HttpMethod.DELETE, HTTPStatus.NO_CONTENT)
-    DELETE_ROLE_BY_NAME = API(URI_ROLE_BY_NAME, HttpMethod.DELETE, HTTPStatus.NO_CONTENT)
-    GET_ROLE_BY_ID      = API(URI_ROLE_BY_ID, HttpMethod.GET, HTTPStatus.OK)
-    GET_ROLE_BY_NAME    = API(URI_ROLE_BY_NAME, HttpMethod.GET, HTTPStatus.OK)
-    GET_ALL_ROLE_NAMES  = API(URI_ROLE_NAMES, HttpMethod.GET, HTTPStatus.OK)
-    GET_USER_ROLES      = API(URI_USER_ROLES, HttpMethod.GET, HTTPStatus.OK)
-    GRANT_ROLE          = API(URI_GRANT_ROLE, HttpMethod.PUT, HTTPStatus.OK)
-    REVOKE_ROLE         = API(URI_REVOKE_ROLE, HttpMethod.PUT, HTTPStatus.OK)
-    FIND_ROLES          = API(URI_ROLE, HttpMethod.GET, HTTPStatus.OK)
-
-    GET_PLUGIN_INFO      = API(URI_PLUGIN_INFO, HttpMethod.GET, HTTPStatus.OK)
-    DELETE_POLICY_DELTAS = API(URI_POLICY_DELTAS, HttpMethod.DELETE, HTTPStatus.NO_CONTENT)
-
-    def __init__(self, url, username, password):
-        self.__password     = password
-        self.url            = url
-        self.username       = username
-        self.session        = Session()
-        self.session.auth   = (username, password)
-        self.session.verify = False
-
-    def __call_api(self, api, params, request):
-        return api.call(self.session, self.url, params, request)
-
-    def __call_api_with_url_params(self, api, urlParams, params, request):
-        return api.apply_url_params(urlParams).call(self.session, self.url, params, request)
 
     # Service Definition APIs
     def create_service_def(self, serviceDef):
-        ret = self.__call_api(RangerClient.CREATE_SERVICEDEF, {}, serviceDef)
+        resp = self.__call_api(RangerClient.CREATE_SERVICEDEF, request_data=serviceDef)
 
-        return RangerServiceDef(**ret) if ret is not None else None
+        return type_coerce(resp, RangerServiceDef)
 
     def update_service_def_by_id(self, serviceDefId, serviceDef):
-        ret = self.__call_api_with_url_params(RangerClient.UPDATE_SERVICEDEF_BY_ID, { RangerClient.PARAM_ID: serviceDefId }, {}, serviceDef)
+        resp = self.__call_api(RangerClient.UPDATE_SERVICEDEF_BY_ID.format_path({ 'id': serviceDefId }), request_data=serviceDef)
 
-        return RangerServiceDef(**ret) if ret is not None else None
+        return type_coerce(resp, RangerServiceDef)
 
     def update_service_def(self, serviceDefName, serviceDef):
-        ret = self.__call_api_with_url_params(RangerClient.UPDATE_SERVICEDEF_BY_NAME, { RangerClient.PARAM_NAME: serviceDefName }, {}, serviceDef)
+        resp = self.__call_api(RangerClient.UPDATE_SERVICEDEF_BY_NAME.format_path({ 'name': serviceDefName }), request_data=serviceDef)
 
-        return RangerServiceDef(**ret) if ret is not None else None
+        return type_coerce(resp, RangerServiceDef)
 
     def delete_service_def_by_id(self, serviceDefId):
-        self.__call_api_with_url_params(RangerClient.DELETE_SERVICEDEF_BY_ID, { RangerClient.PARAM_ID: serviceDefId }, {}, {})
-
-        return None
+        self.__call_api(RangerClient.DELETE_SERVICEDEF_BY_ID.format_path({ 'id': serviceDefId }))
 
     def delete_service_def(self, serviceDefName):
-        self.__call_api_with_url_params(RangerClient.DELETE_SERVICEDEF_BY_NAME, { RangerClient.PARAM_NAME: serviceDefName }, {}, {})
-
-        return None
+        self.__call_api(RangerClient.DELETE_SERVICEDEF_BY_NAME.format_path({ 'name': serviceDefName }))
 
     def get_service_def_by_id(self, serviceDefId):
-        ret = self.__call_api_with_url_params(RangerClient.GET_SERVICEDEF_BY_ID, { RangerClient.PARAM_ID: serviceDefId }, {}, {})
+        resp = self.__call_api(RangerClient.GET_SERVICEDEF_BY_ID.format_path({ 'id': serviceDefId }))
 
-        return RangerServiceDef(**ret) if ret is not None else None
+        return type_coerce(resp, RangerServiceDef)
 
     def get_service_def(self, serviceDefName):
-        ret = self.__call_api_with_url_params(RangerClient.GET_SERVICEDEF_BY_NAME, { RangerClient.PARAM_NAME: serviceDefName }, {}, {})
+        resp = self.__call_api(RangerClient.GET_SERVICEDEF_BY_NAME.format_path({ 'name': serviceDefName }))
 
-        return RangerServiceDef(**ret) if ret is not None else None
+        return type_coerce(resp, RangerServiceDef)
 
-    def find_service_defs(self, filter):
-        ret = self.__call_api(RangerClient.FIND_SERVICEDEFS, filter, {})
+    def find_service_defs(self, filter={}):
+        resp = self.__call_api(RangerClient.FIND_SERVICEDEFS, filter)
+
+        return type_coerce_list(resp, RangerServiceDef)
 
-        return list(ret) if ret is not None else None
 
     # Service APIs
     def create_service(self, service):
-        ret = self.__call_api(RangerClient.CREATE_SERVICE, {}, service)
+        resp = self.__call_api(RangerClient.CREATE_SERVICE, request_data=service)
+
+        return type_coerce(resp, RangerService)
+
+    def get_service_by_id(self, serviceId):
+        resp = self.__call_api(RangerClient.GET_SERVICE_BY_ID.format_path({ 'id': serviceId }))
+
+        return type_coerce(resp, RangerService)
+
+    def get_service(self, serviceName):
+        resp = self.__call_api(RangerClient.GET_SERVICE_BY_NAME.format_path({ 'name': serviceName }))
 
-        return RangerService(**ret) if ret is not None else None
+        return type_coerce(resp, RangerService)
 
     def update_service_by_id(self, serviceId, service):
-        ret = self.__call_api_with_url_params(RangerClient.UPDATE_SERVICE_BY_ID, { RangerClient.PARAM_ID: serviceId }, {}, service)
+        resp = self.__call_api(RangerClient.UPDATE_SERVICE_BY_ID.format_path({ 'id': serviceId }), request_data=service)
 
-        return RangerService(**ret) if ret is not None else None
+        return type_coerce(resp, RangerService)
 
     def update_service(self, serviceName, service):
-        ret = self.__call_api_with_url_params(RangerClient.UPDATE_SERVICE_BY_NAME, { RangerClient.PARAM_NAME: serviceName }, {}, service)
+        resp = self.__call_api(RangerClient.UPDATE_SERVICE_BY_NAME.format_path({ 'name': serviceName }), request_data=service)
 
-        return RangerService(**ret) if ret is not None else None
+        return type_coerce(resp, RangerService)
 
     def delete_service_by_id(self, serviceId):
-        self.__call_api_with_url_params(RangerClient.DELETE_SERVICE_BY_ID, { RangerClient.PARAM_ID: serviceId }, {}, {})
-
-        return None
+        self.__call_api(RangerClient.DELETE_SERVICE_BY_ID.format_path({ 'id': serviceId }))
 
     def delete_service(self, serviceName):
-        self.__call_api_with_url_params(RangerClient.DELETE_SERVICE_BY_NAME, { RangerClient.PARAM_NAME: serviceName }, {}, {})
+        self.__call_api(RangerClient.DELETE_SERVICE_BY_NAME.format_path({ 'name': serviceName }))
 
-        return None
+    def find_services(self, filter={}):
+        resp = self.__call_api(RangerClient.FIND_SERVICES, filter)
 
-    def get_service_by_id(self, serviceId):
-        ret = self.__call_api_with_url_params(RangerClient.GET_SERVICE_BY_ID, { RangerClient.PARAM_ID: serviceId }, {}, {})
+        return type_coerce_list(resp, RangerService)
 
-        return RangerService(**ret) if ret is not None else None
 
-    def get_service(self, serviceName):
-        ret = self.__call_api_with_url_params(RangerClient.GET_SERVICE_BY_NAME, { RangerClient.PARAM_NAME: serviceName }, {}, {})
+    # Policy APIs
+    def create_policy(self, policy):
+        resp = self.__call_api(RangerClient.CREATE_POLICY, request_data=policy)
 
-        return RangerService(**ret) if ret is not None else None
+        return type_coerce(resp, RangerPolicy)
 
-    def find_services(self, filter):
-        ret = self.__call_api(RangerClient.FIND_SERVICES, filter, {})
+    def get_policy_by_id(self, policyId):
+        resp = self.__call_api(RangerClient.GET_POLICY_BY_ID.format_path({ 'id': policyId }))
 
-        return list(ret) if ret is not None else None
+        return type_coerce(resp, RangerPolicy)
 
-    # Policy APIs
-    def create_policy(self, policy):
-        ret = self.__call_api(RangerClient.CREATE_POLICY, {}, policy)
+    def get_policy(self, serviceName, policyName):
+        resp = self.__call_api(RangerClient.GET_POLICY_BY_NAME.format_path({ 'serviceName': serviceName, 'policyName': policyName}))
 
-        return RangerPolicy(**ret) if ret is not None else None
+        return type_coerce(resp, RangerPolicy)
+
+    def get_policies_in_service(self, serviceName):
+        resp = self.__call_api(RangerClient.GET_POLICIES_IN_SERVICE.format_path({ 'serviceName': serviceName }))
+
+        return type_coerce_list(resp, RangerPolicy)
 
     def update_policy_by_id(self, policyId, policy):
-        ret = self.__call_api_with_url_params(RangerClient.UPDATE_POLICY_BY_ID, { RangerClient.PARAM_ID: policyId }, {}, policy)
+        resp = self.__call_api(RangerClient.UPDATE_POLICY_BY_ID.format_path({ 'id': policyId }), request_data=policy)
 
-        return RangerPolicy(**ret) if ret is not None else None
+        return type_coerce(resp, RangerPolicy)
 
     def update_policy(self, serviceName, policyName, policy):
-        path_params = { RangerClient.PARAM_SERVICE_NAME: serviceName, RangerClient.PARAM_POLICY_NAME: policyName }
-        ret         = self.__call_api_with_url_params(RangerClient.UPDATE_POLICY_BY_NAME, path_params, {}, policy)
+        resp = self.__call_api(RangerClient.UPDATE_POLICY_BY_NAME.format_path({ 'serviceName': serviceName, 'policyName': policyName}), request_data=policy)
 
-        return RangerPolicy(**ret) if ret is not None else None
+        return type_coerce(resp, RangerPolicy)
 
     def apply_policy(self, policy):
-        ret = self.__call_api(RangerClient.APPLY_POLICY, {}, policy)
+        resp = self.__call_api(RangerClient.APPLY_POLICY, request_data=policy)
 
-        return RangerPolicy(**ret) if ret is not None else None
+        return type_coerce(resp, RangerPolicy)
 
     def delete_policy_by_id(self, policyId):
-        self.__call_api_with_url_params(RangerClient.DELETE_POLICY_BY_ID, { RangerClient.PARAM_ID: policyId }, {}, {})
-
-        return None
+        self.__call_api(RangerClient.DELETE_POLICY_BY_ID.format_path({ 'id': policyId }))
 
     def delete_policy(self, serviceName, policyName):
-        query_params = { RangerClient.PARAM_POLICY_NAME: policyName, 'servicename': serviceName }
-
-        self.__call_api(RangerClient.DELETE_POLICY_BY_NAME, query_params, {})
-
-        return None
-
-    def get_policy_by_id(self, policyId):
-        ret = self.__call_api_with_url_params(RangerClient.GET_POLICY_BY_ID, { RangerClient.PARAM_ID: policyId }, {}, {})
-
-        return RangerPolicy(**ret) if ret is not None else None
-
-    def get_policy(self, serviceName, policyName):
-        path_params = {RangerClient.PARAM_SERVICE_NAME: serviceName, RangerClient.PARAM_POLICY_NAME: policyName}
-        ret         = self.__call_api_with_url_params(RangerClient.GET_POLICY_BY_NAME, path_params, {}, {})
-
-        return RangerPolicy(**ret) if ret is not None else None
-
-    def get_policies_in_service(self, serviceName):
-        ret = self.__call_api_with_url_params(RangerClient.GET_POLICIES_IN_SERVICE, { RangerClient.PARAM_SERVICE_NAME: serviceName }, {}, {})
+        self.__call_api(RangerClient.DELETE_POLICY_BY_NAME, { 'servicename': serviceName, 'policyname': policyName })
 
-        return list(ret) if ret is not None else None
+    def find_policies(self, filter={}):
+        resp = self.__call_api(RangerClient.FIND_POLICIES, filter)
 
-    def find_policies(self, filter):
-        ret = self.__call_api(RangerClient.FIND_POLICIES, filter, {})
+        return type_coerce_list(resp, RangerPolicy)
 
-        return list(ret) if ret is not None else None
 
     # SecurityZone APIs
     def create_security_zone(self, securityZone):
-        ret = self.__call_api(RangerClient.CREATE_ZONE, {}, securityZone)
+        resp = self.__call_api(RangerClient.CREATE_ZONE, request_data=securityZone)
 
-        return RangerSecurityZone(**ret) if ret is not None else None
+        return type_coerce(resp, RangerSecurityZone)
 
     def update_security_zone_by_id(self, zoneId, securityZone):
-        ret = self.__call_api_with_url_params(RangerClient.UPDATE_ZONE_BY_ID, { RangerClient.PARAM_ID: zoneId }, {}, securityZone)
+        resp = self.__call_api(RangerClient.UPDATE_ZONE_BY_ID.format_path({ 'id': zoneId }), request_data=securityZone)
 
-        return RangerSecurityZone(**ret) if ret is not None else None
+        return type_coerce(resp, RangerSecurityZone)
 
     def update_security_zone(self, zoneName, securityZone):
-        ret = self.__call_api_with_url_params(RangerClient.UPDATE_ZONE_BY_NAME, { RangerClient.PARAM_NAME: zoneName }, {}, securityZone)
+        resp = self.__call_api(RangerClient.UPDATE_ZONE_BY_NAME.format_path({ 'name': zoneName }), request_data=securityZone)
 
-        return RangerSecurityZone(**ret) if ret is not None else None
+        return type_coerce(resp, RangerSecurityZone)
 
     def delete_security_zone_by_id(self, zoneId):
-        self.__call_api_with_url_params(RangerClient.DELETE_ZONE_BY_ID, { RangerClient.PARAM_ID: zoneId }, {}, {})
-        return None
+        self.__call_api(RangerClient.DELETE_ZONE_BY_ID.format_path({ 'id': zoneId }))
 
     def delete_security_zone(self, zoneName):
-        self.__call_api_with_url_params(RangerClient.DELETE_ZONE_BY_NAME, { RangerClient.PARAM_NAME: zoneName }, {}, {})
-
-        return None
+        self.__call_api(RangerClient.DELETE_ZONE_BY_NAME.format_path({ 'name': zoneName }))
 
     def get_security_zone_by_id(self, zoneId):
-        ret = self.__call_api_with_url_params(RangerClient.GET_ZONE_BY_ID, { RangerClient.PARAM_ID: zoneId }, {}, {})
+        resp = self.__call_api(RangerClient.GET_ZONE_BY_ID.format_path({ 'id': zoneId }))
 
-        return RangerSecurityZone(**ret) if ret is not None else None
+        return type_coerce(resp, RangerSecurityZone)
 
     def get_security_zone(self, zoneName):
-        ret = self.__call_api_with_url_params(RangerClient.GET_ZONE_BY_NAME, { RangerClient.PARAM_NAME: zoneName }, {}, {})
+        resp = self.__call_api(RangerClient.GET_ZONE_BY_NAME.format_path({ 'name': zoneName }))
 
-        return RangerSecurityZone(**ret) if ret is not None else None
+        return type_coerce(resp, RangerSecurityZone)
 
-    def find_security_zones(self, filter):
-        ret = self.__call_api(RangerClient.FIND_ZONES, filter, {})
+    def find_security_zones(self, filter={}):
+        resp = self.__call_api(RangerClient.FIND_ZONES, filter)
+
+        return type_coerce_list(resp, RangerSecurityZone)
 
-        return list(ret) if ret is not None else None
 
     # Role APIs
     def create_role(self, serviceName, role):
-        query_params = {RangerClient.PARAM_SERVICE_NAME, serviceName}
-        ret          = self.__call_api(RangerClient.CREATE_ROLE, query_params, role)
+        resp = self.__call_api(RangerClient.CREATE_ROLE, { 'serviceName': serviceName }, role)
 
-        return RangerRole(**ret) if ret is not None else None
+        return type_coerce(resp, RangerRole)
 
     def update_role(self, roleId, role):
-        ret = self.__call_api_with_url_params(RangerClient.UPDATE_ROLE_BY_ID, { RangerClient.PARAM_ID: roleId }, {}, role)
+        resp = self.__call_api(RangerClient.UPDATE_ROLE_BY_ID.format_path({ 'id': roleId }), request_data=role)
 
-        return RangerRole(**ret) if ret is not None else None
+        return type_coerce(resp, RangerRole)
 
     def delete_role_by_id(self, roleId):
-        self.__call_api_with_url_params(RangerClient.DELETE_ROLE_BY_ID, { RangerClient.PARAM_ID: roleId }, {}, {})
-
-        return None
+        self.__call_api(RangerClient.DELETE_ROLE_BY_ID.format_path({ 'id': roleId }))
 
     def delete_role(self, roleName, execUser, serviceName):
-        query_params = { RangerClient.PARAM_EXEC_USER: execUser, RangerClient.PARAM_SERVICE_NAME: serviceName }
-
-        self.__call_api_with_url_params(RangerClient.DELETE_ROLE_BY_NAME, { RangerClient.PARAM_NAME: roleName }, query_params, {})
-
-        return None
+        self.__call_api(RangerClient.DELETE_ROLE_BY_NAME.format_path({ 'name': roleName }), { 'execUser': execUser, 'serviceName': serviceName })
 
     def get_role_by_id(self, roleId):
-        ret = self.__call_api_with_url_params(RangerClient.GET_ROLE_BY_ID, { RangerClient.PARAM_ID: roleId }, {}, {})
+        resp = self.__call_api(RangerClient.GET_ROLE_BY_ID.format_path({ 'id': roleId }))
 
-        return RangerRole(**ret) if ret is not None else None
+        return type_coerce(resp, RangerRole)
 
     def get_role(self, roleName, execUser, serviceName):
-        query_params = { RangerClient.PARAM_EXEC_USER: execUser, RangerClient.PARAM_SERVICE_NAME: serviceName }
-        ret          = self.__call_api_with_url_params(RangerClient.GET_ROLE_BY_NAME, { RangerClient.PARAM_NAME: roleName }, query_params, {})
+        resp = self.__call_api(RangerClient.GET_ROLE_BY_NAME.format_path({ 'name': roleName }), { 'execUser': execUser, 'serviceName': serviceName })
 
-        return RangerRole(**ret) if ret is not None else None
+        return type_coerce(resp, RangerRole)
 
     def get_all_role_names(self, execUser, serviceName):
-        query_params = { RangerClient.PARAM_EXEC_USER: execUser, RangerClient.PARAM_SERVICE_NAME: serviceName }
-        ret          = self.__call_api_with_url_params(RangerClient.GET_ALL_ROLE_NAMES, { RangerClient.PARAM_NAME: serviceName }, query_params, {})
+        resp = self.__call_api(RangerClient.GET_ALL_ROLE_NAMES.format_path({ 'name': serviceName }), { 'execUser': execUser, 'serviceName': serviceName })
 
-        return list(ret) if ret is not None else None
+        return resp
 
     def get_user_roles(self, user):
-        ret = self.__call_api_with_url_params(RangerClient.GET_USER_ROLES, { RangerClient.PARAM_NAME: user }, {}, {})
+        ret = self.__call_api(RangerClient.GET_USER_ROLES.format_path({ 'name': user }))
 
         return list(ret) if ret is not None else None
 
-    def find_roles(self, filter):
-        ret = self.__call_api(RangerClient.FIND_ROLES, filter, {})
+    def find_roles(self, filter={}):
+        resp = self.__call_api(RangerClient.FIND_ROLES, filter)
 
-        return list(ret) if ret is not None else None
+        return type_coerce_list(resp, RangerRole)
 
     def grant_role(self, serviceName, request):
-        ret = self.__call_api_with_url_params(RangerClient.GRANT_ROLE, { RangerClient.PARAM_NAME: serviceName }, {}, request)
+        resp = self.__call_api(RangerClient.GRANT_ROLE.format_path({ 'name': serviceName }), request_data=request)
 
-        return RESTResponse(**ret) if ret is not None else None
+        return type_coerce(resp, RESTResponse)
 
     def revoke_role(self, serviceName, request):
-        ret = self.__call_api_with_url_params(RangerClient.REVOKE_ROLE, { RangerClient.PARAM_NAME: serviceName }, {}, request)
+        resp = self.__call_api(RangerClient.REVOKE_ROLE.format_path({ 'name': serviceName }), request_data=request)
+
+        return type_coerce(resp, RESTResponse)
 
-        return RESTResponse(**ret) if ret is not None else None
 
     # Admin APIs
     def delete_policy_deltas(self, days, reloadServicePoliciesCache):
-        query_params = {
-            RangerClient.PARAM_DAYS: days,
-            RangerClient.PARAM_RELOAD_SERVICE_POLICIES_CACHE: reloadServicePoliciesCache
-        }
+        self.__call_api(RangerClient.DELETE_POLICY_DELTAS, { 'days': days, 'reloadServicePoliciesCache': reloadServicePoliciesCache})
+
+
+
+    def __call_api(self, api, query_params=None, request_data=None):
+        ret    = None
+        params = { 'headers': { 'Accept': api.consumes, 'Content-type': api.produces } }
+
+        if query_params:
+            params['params'] = query_params
+
+        if request_data:
+            params['data'] = json.dumps(request_data)
+
+        path = os.path.join(self.url, api.path)
+
+        if LOG.isEnabledFor(logging.DEBUG):
+            LOG.debug("------------------------------------------------------")
+            LOG.debug("Call         : %s %s", api.method, path)
+            LOG.debug("Content-type : %s", api.consumes)
+            LOG.debug("Accept       : %s", api.produces)
+
+        response = None
+
+        if api.method == HttpMethod.GET:
+            response = self.session.get(path, **params)
+        elif api.method == HttpMethod.POST:
+            response = self.session.post(path, **params)
+        elif api.method == HttpMethod.PUT:
+            response = self.session.put(path, **params)
+        elif api.method == HttpMethod.DELETE:
+            response = self.session.delete(path, **params)
 
-        self.__call_api(RangerClient.DELETE_POLICY_DELTAS, query_params, {})
+        if LOG.isEnabledFor(logging.DEBUG):
+            LOG.debug("HTTP Status: %s", response.status_code if response else "None")
+
+        if response is None:
+            ret = None
+        elif response.status_code == api.expected_status:
+            try:
+                if response.content:
+                    if LOG.isEnabledFor(logging.DEBUG):
+                        LOG.debug("<== __call_api(%s, %s, %s), result=%s", vars(api), params, request_data, response)
+
+                        LOG.debug(response.json())
+
+                    ret = response.json()
+                else:
+                    ret = None
+            except Exception as e:
+                print(e)
+
+                LOG.exception("Exception occurred while parsing response with msg: %s", e)
+
+                raise RangerServiceException(api, response)
+        elif response.status_code == HTTPStatus.SERVICE_UNAVAILABLE:
+            LOG.error("Ranger admin unavailable. HTTP Status: %s", HTTPStatus.SERVICE_UNAVAILABLE)
+
+            ret = None
+        else:
+            raise RangerServiceException(api, response)
+
+        return ret
+
+
+    # URIs
+    URI_BASE                = "service/public/v2/api"
+
+    URI_SERVICEDEF          = URI_BASE + "/servicedef"
+    URI_SERVICEDEF_BY_ID    = URI_SERVICEDEF + "/{id}"
+    URI_SERVICEDEF_BY_NAME  = URI_SERVICEDEF + "/name/{name}"
+
+    URI_SERVICE             = URI_BASE + "/service"
+    URI_SERVICE_BY_ID       = URI_SERVICE + "/{id}"
+    URI_SERVICE_BY_NAME     = URI_SERVICE + "/name/{name}"
+    URI_POLICIES_IN_SERVICE = URI_SERVICE + "/{serviceName}/policy"
+
+    URI_POLICY              = URI_BASE + "/policy"
+    URI_APPLY_POLICY        = URI_POLICY + "/apply"
+    URI_POLICY_BY_ID        = URI_POLICY + "/{id}"
+    URI_POLICY_BY_NAME      = URI_SERVICE + "/{serviceName}/policy/{policyName}"
+
+    URI_ROLE                = URI_BASE + "/roles"
+    URI_ROLE_NAMES          = URI_ROLE + "/names"
+    URI_ROLE_BY_ID          = URI_ROLE + "/{id}"
+    URI_ROLE_BY_NAME        = URI_ROLE + "/name/{name}"
+    URI_USER_ROLES          = URI_ROLE + "/user/{name}"
+    URI_GRANT_ROLE          = URI_ROLE + "/grant/{name}"
+    URI_REVOKE_ROLE         = URI_ROLE + "/revoke/{name}"
+
+    URI_ZONE                = URI_BASE + "/zones"
+    URI_ZONE_BY_ID          = URI_ZONE + "/{id}"
+    URI_ZONE_BY_NAME        = URI_ZONE + "/name/{name}"
+
+    URI_PLUGIN_INFO         = URI_BASE + "/plugins/info"
+    URI_POLICY_DELTAS       = URI_BASE + "/server/policydeltas"
+
+    # APIs
+    CREATE_SERVICEDEF         = API(URI_SERVICEDEF, HttpMethod.POST, HTTPStatus.OK)
+    UPDATE_SERVICEDEF_BY_ID   = API(URI_SERVICEDEF_BY_ID, HttpMethod.PUT, HTTPStatus.OK)
+    UPDATE_SERVICEDEF_BY_NAME = API(URI_SERVICEDEF_BY_NAME, HttpMethod.PUT, HTTPStatus.OK)
+    DELETE_SERVICEDEF_BY_ID   = API(URI_SERVICEDEF_BY_ID, HttpMethod.DELETE, HTTPStatus.NO_CONTENT)
+    DELETE_SERVICEDEF_BY_NAME = API(URI_SERVICEDEF_BY_NAME, HttpMethod.DELETE, HTTPStatus.NO_CONTENT)
+    GET_SERVICEDEF_BY_ID      = API(URI_SERVICEDEF_BY_ID, HttpMethod.GET, HTTPStatus.OK)
+    GET_SERVICEDEF_BY_NAME    = API(URI_SERVICEDEF_BY_NAME, HttpMethod.GET, HTTPStatus.OK)
+    FIND_SERVICEDEFS          = API(URI_SERVICEDEF, HttpMethod.GET, HTTPStatus.OK)
 
-        return None
+    CREATE_SERVICE            = API(URI_SERVICE, HttpMethod.POST, HTTPStatus.OK)
+    UPDATE_SERVICE_BY_ID      = API(URI_SERVICE_BY_ID, HttpMethod.PUT, HTTPStatus.OK)
+    UPDATE_SERVICE_BY_NAME    = API(URI_SERVICE_BY_NAME, HttpMethod.PUT, HTTPStatus.OK)
+    DELETE_SERVICE_BY_ID      = API(URI_SERVICE_BY_ID, HttpMethod.DELETE, HTTPStatus.NO_CONTENT)
+    DELETE_SERVICE_BY_NAME    = API(URI_SERVICE_BY_NAME, HttpMethod.DELETE, HTTPStatus.NO_CONTENT)
+    GET_SERVICE_BY_ID         = API(URI_SERVICE_BY_ID, HttpMethod.GET, HTTPStatus.OK)
+    GET_SERVICE_BY_NAME       = API(URI_SERVICE_BY_NAME, HttpMethod.GET, HTTPStatus.OK)
+    FIND_SERVICES             = API(URI_SERVICE, HttpMethod.GET, HTTPStatus.OK)
+
+    CREATE_POLICY             = API(URI_POLICY, HttpMethod.POST, HTTPStatus.OK)
+    UPDATE_POLICY_BY_ID       = API(URI_POLICY_BY_ID, HttpMethod.PUT, HTTPStatus.OK)
+    UPDATE_POLICY_BY_NAME     = API(URI_POLICY_BY_NAME, HttpMethod.PUT, HTTPStatus.OK)
+    APPLY_POLICY              = API(URI_APPLY_POLICY, HttpMethod.POST, HTTPStatus.OK)
+    DELETE_POLICY_BY_ID       = API(URI_POLICY_BY_ID, HttpMethod.DELETE, HTTPStatus.NO_CONTENT)
+    DELETE_POLICY_BY_NAME     = API(URI_POLICY, HttpMethod.DELETE, HTTPStatus.NO_CONTENT)
+    GET_POLICY_BY_ID          = API(URI_POLICY_BY_ID, HttpMethod.GET, HTTPStatus.OK)
+    GET_POLICY_BY_NAME        = API(URI_POLICY_BY_NAME, HttpMethod.GET, HTTPStatus.OK)
+    GET_POLICIES_IN_SERVICE   = API(URI_POLICIES_IN_SERVICE, HttpMethod.GET, HTTPStatus.OK)
+    FIND_POLICIES             = API(URI_POLICY, HttpMethod.GET, HTTPStatus.OK)
+
+    CREATE_ZONE               = API(URI_ZONE, HttpMethod.POST, HTTPStatus.OK)
+    UPDATE_ZONE_BY_ID         = API(URI_ZONE_BY_ID, HttpMethod.PUT, HTTPStatus.OK)
+    UPDATE_ZONE_BY_NAME       = API(URI_ZONE_BY_NAME, HttpMethod.PUT, HTTPStatus.OK)
+    DELETE_ZONE_BY_ID         = API(URI_ZONE_BY_ID, HttpMethod.DELETE, HTTPStatus.NO_CONTENT)
+    DELETE_ZONE_BY_NAME       = API(URI_ZONE_BY_NAME, HttpMethod.DELETE, HTTPStatus.NO_CONTENT)
+    GET_ZONE_BY_ID            = API(URI_ZONE_BY_ID, HttpMethod.GET, HTTPStatus.OK)
+    GET_ZONE_BY_NAME          = API(URI_ZONE_BY_NAME, HttpMethod.GET, HTTPStatus.OK)
+    FIND_ZONES                = API(URI_ZONE, HttpMethod.GET, HTTPStatus.OK)
+
+    CREATE_ROLE               = API(URI_ROLE, HttpMethod.POST, HTTPStatus.OK)
+    UPDATE_ROLE_BY_ID         = API(URI_ROLE_BY_ID, HttpMethod.PUT, HTTPStatus.OK)
+    DELETE_ROLE_BY_ID         = API(URI_ROLE_BY_ID, HttpMethod.DELETE, HTTPStatus.NO_CONTENT)
+    DELETE_ROLE_BY_NAME       = API(URI_ROLE_BY_NAME, HttpMethod.DELETE, HTTPStatus.NO_CONTENT)
+    GET_ROLE_BY_ID            = API(URI_ROLE_BY_ID, HttpMethod.GET, HTTPStatus.OK)
+    GET_ROLE_BY_NAME          = API(URI_ROLE_BY_NAME, HttpMethod.GET, HTTPStatus.OK)
+    GET_ALL_ROLE_NAMES        = API(URI_ROLE_NAMES, HttpMethod.GET, HTTPStatus.OK)
+    GET_USER_ROLES            = API(URI_USER_ROLES, HttpMethod.GET, HTTPStatus.OK)
+    GRANT_ROLE                = API(URI_GRANT_ROLE, HttpMethod.PUT, HTTPStatus.OK)
+    REVOKE_ROLE               = API(URI_REVOKE_ROLE, HttpMethod.PUT, HTTPStatus.OK)
+    FIND_ROLES                = API(URI_ROLE, HttpMethod.GET, HTTPStatus.OK)
+
+    GET_PLUGIN_INFO           = API(URI_PLUGIN_INFO, HttpMethod.GET, HTTPStatus.OK)
+    DELETE_POLICY_DELTAS      = API(URI_POLICY_DELTAS, HttpMethod.DELETE, HTTPStatus.NO_CONTENT)
+
+
+class Message(RangerBase):
+    def __init__(self, attrs={}):
+        RangerBase.__init__(self, attrs)
+
+        self.name      = attrs.get('name')
+        self.rbKey     = attrs.get('rbKey')
+        self.message   = attrs.get('message')
+        self.objectId  = attrs.get('objectId')
+        self.fieldName = attrs.get('fieldName')
+
+
+class RESTResponse(RangerBase):
+    def __init__(self, attrs={}):
+        RangerBase.__init__(self, attrs)
+
+        self.httpStatusCode = attrs.get('httpStatusCode')
+        self.statusCode     = attrs.get('statusCode')
+        self.msgDesc        = attrs.get('msgDesc')
+        self.messageList    = non_null(attrs.get('messageList'), [])
+
+    def type_coerce_attrs(self):
+        super(RangerPolicy, self).type_coerce_attrs()
+
+        self.messageList = type_coerce_dict(self.messageList, Message)
diff --git a/intg/src/main/python/apache_ranger/exceptions.py b/intg/src/main/python/apache_ranger/exceptions.py
new file mode 100644
index 0000000..a229947
--- /dev/null
+++ b/intg/src/main/python/apache_ranger/exceptions.py
@@ -0,0 +1,45 @@
+#!/usr/bin/env python
+
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+class RangerServiceException(Exception):
+    """Exception raised for errors in API calls.
+
+    Attributes:
+        api      -- api endpoint which caused the error
+        response -- response from the server
+    """
+
+    def __init__(self, api, response):
+        self.method          = api.method.name
+        self.path            = api.path
+        self.expected_status = api.expected_status
+        self.statusCode      = -1
+        self.msgDesc         = None
+        self.messageList     = None
+
+        print(response)
+
+        if api is not None and response is not None:
+            respJson = response.json()
+
+            self.statusCode  = response.status_code
+            self.msgDesc     = respJson['msgDesc']     if respJson is not None and 'msgDesc'     in respJson else None
+            self.messageList = respJson['messageList'] if respJson is not None and 'messageList' in respJson else None
+
+        Exception.__init__(self, "{} {} failed: expected_status={}, status={}, message={}".format(self.method, self.path, self.expected_status, self.statusCode, self.msgDesc))
diff --git a/intg/src/main/python/apache_ranger/model/grant_revoke_role_request.py b/intg/src/main/python/apache_ranger/model/grant_revoke_role_request.py
index fb0eab2..fcc9078 100644
--- a/intg/src/main/python/apache_ranger/model/grant_revoke_role_request.py
+++ b/intg/src/main/python/apache_ranger/model/grant_revoke_role_request.py
@@ -16,24 +16,24 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import json
+from apache_ranger.model.ranger_base import *
+from apache_ranger.utils             import *
 
 
-class GrantRevokeRoleRequest:
-    def __init__(self, grantor=None, grantorGroups=None, targetRoles=None, users=None, groups=None, roles=None, grantOption=None, clientIPAddress=None, clientType=None, requestData=None, sessionId=None, clusterName=None):
-        self.grantor         = grantor
-        self.grantorGroups   = grantorGroups if grantorGroups is not None else []
-        self.targetRoles     = targetRoles if targetRoles is not None else []
-        self.users           = users if users is not None else []
-        self.groups          = groups if groups is not None else []
-        self.roles           = roles if roles is not None else []
-        self.grantOption     = grantOption if grantOption is not None else False
-        self.clientIPAddress = clientIPAddress
-        self.clientType      = clientType
-        self.requestData     = requestData
-        self.sessionId       = sessionId
-        self.clusterName     = clusterName
+class GrantRevokeRoleRequest(RangerBase):
+    def __init__(self, attrs={}):
+        RangerBase.__init__(self, attrs)
 
-    def __repr__(self):
-        return json.dumps(self, default=lambda x: x.__dict__, sort_keys=True, indent=4)
+        self.grantor         = attrs.get('grantor')
+        self.grantorGroups   = attrs.get('grantorGroups')
+        self.targetRoles     = attrs.get('targetRoles')
+        self.users           = attrs.get('users')
+        self.groups          = attrs.get('groups')
+        self.roles           = attrs.get('roles')
+        self.grantOption     = non_null(attrs.get('grantOption'), False)
+        self.clientIPAddress = attrs.get('clientIPAddress')
+        self.clientType      = attrs.get('clientType')
+        self.requestData     = attrs.get('requestData')
+        self.sessionId       = attrs.get('sessionId')
+        self.clusterName     = attrs.get('clusterName')
 
diff --git a/intg/src/main/python/apache_ranger/model/ranger_base.py b/intg/src/main/python/apache_ranger/model/ranger_base.py
index ae8de74..edabe2c 100644
--- a/intg/src/main/python/apache_ranger/model/ranger_base.py
+++ b/intg/src/main/python/apache_ranger/model/ranger_base.py
@@ -18,17 +18,46 @@
 
 import json
 
+from apache_ranger.utils import *
 
-class RangerBase:
-    def __init__(self, id=None, guid=None, createdBy=None, updatedBy=None, createTime=None, updateTime=None, version=None, isEnabled=None):
-        self.id         = id
-        self.guid       = guid
-        self.isEnabled  = isEnabled if isEnabled is not None else True
-        self.createdBy  = createdBy
-        self.updatedBy  = updatedBy
-        self.createTime = createTime
-        self.updateTime = updateTime
-        self.version    = version
+
+class RangerBase(dict):
+    def __init__(self, attrs):
+        pass
+
+    def __getattr__(self, attr):
+        return self.get(attr)
+
+    def __setattr__(self, key, value):
+        self.__setitem__(key, value)
+
+    def __setitem__(self, key, value):
+        super(RangerBase, self).__setitem__(key, value)
+        self.__dict__.update({key: value})
+
+    def __delattr__(self, item):
+        self.__delitem__(item)
+
+    def __delitem__(self, key):
+        super(RangerBase, self).__delitem__(key)
+        del self.__dict__[key]
 
     def __repr__(self):
-        return json.dumps(self, default=lambda x: x.__dict__, sort_keys=True, indent=4)
+        return json.dumps(self)
+
+    def type_coerce_attrs(self):
+        pass
+
+
+class RangerBaseModelObject(RangerBase):
+    def __init__(self, attrs={}):
+        RangerBase.__init__(self, attrs)
+
+        self.id         = attrs.get('id')
+        self.guid       = attrs.get('guid')
+        self.isEnabled  = non_null(attrs.get('isEnabled'), True)
+        self.createdBy  = attrs.get('createdBy')
+        self.updatedBy  = attrs.get('updatedBy')
+        self.createTime = attrs.get('createTime')
+        self.updateTime = attrs.get('updateTime')
+        self.version    = attrs.get('version')
diff --git a/intg/src/main/python/apache_ranger/model/ranger_policy.py b/intg/src/main/python/apache_ranger/model/ranger_policy.py
index 2136989..1531a84 100644
--- a/intg/src/main/python/apache_ranger/model/ranger_policy.py
+++ b/intg/src/main/python/apache_ranger/model/ranger_policy.py
@@ -16,112 +16,140 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import json
 
-from apache_ranger.model.ranger_base import RangerBase
+from apache_ranger.model.ranger_base import *
+from apache_ranger.utils             import *
 
 
-class RangerPolicyResource:
-    def __init__(self, values=None, isExcludes=None, isRecursive=None):
-        self.values      = values if values is not None else []
-        self.isExcludes  = isExcludes if isExcludes is not None else False
-        self.isRecursive = isRecursive if isRecursive is not None else False
+class RangerPolicy(RangerBaseModelObject):
+    POLICY_TYPE_ACCESS    = 0
+    POLICY_TYPE_DATAMASK  = 1
+    POLICY_TYPE_ROWFILTER = 2
 
-    def __repr__(self):
-        return json.dumps(self, default=lambda x: x.__dict__, sort_keys=True, indent=4)
+    def __init__(self, attrs={}):
+        RangerBaseModelObject.__init__(self, attrs)
 
+        self.service              = attrs.get('service')
+        self.name                 = attrs.get('name')
+        self.policyType           = attrs.get('policyType')
+        self.policyPriority       = attrs.get('policyPriority')
+        self.description          = attrs.get('description')
+        self.resourceSignature    = attrs.get('resourceSignature')
+        self.isAuditEnabled       = attrs.get('isAuditEnabled')
+        self.resources            = attrs.get('resources')
+        self.policyItems          = attrs.get('policyItems')
+        self.denyPolicyItems      = attrs.get('denyPolicyItems')
+        self.allowExceptions      = attrs.get('allowExceptions')
+        self.denyExceptions       = attrs.get('denyExceptions')
+        self.dataMaskPolicyItems  = attrs.get('dataMaskPolicyItems')
+        self.rowFilterPolicyItems = attrs.get('rowFilterPolicyItems')
+        self.serviceType          = attrs.get('serviceType')
+        self.options              = attrs.get('options')
+        self.validitySchedules    = attrs.get('validitySchedules')
+        self.policyLabels         = attrs.get('policyLabels')
+        self.zoneName             = attrs.get('zoneName')
+        self.conditions           = attrs.get('conditions')
+        self.isDenyAllElse        = non_null(attrs.get('isDenyAllElse'), False)
 
-class RangerPolicyItemCondition:
-    def __init__(self, type=None, values=None):
-        self.type   = type
-        self.values = values if values is not None else []
+    def type_coerce_attrs(self):
+        super(RangerPolicy, self).type_coerce_attrs()
 
-    def __repr__(self):
-        return json.dumps(self, default=lambda x: x.__dict__, sort_keys=True, indent=4)
+        self.resources            = type_coerce_dict(self.resources, RangerPolicyResource)
+        self.policyItems          = type_coerce_list(self.policyItems, RangerPolicyItem)
+        self.denyPolicyItems      = type_coerce_list(self.denyPolicyItems, RangerPolicyItem)
+        self.allowExceptions      = type_coerce_list(self.allowExceptions, RangerPolicyItem)
+        self.denyExceptions       = type_coerce_list(self.denyExceptions, RangerPolicyItem)
+        self.dataMaskPolicyItems  = type_coerce_list(self.dataMaskPolicyItems, RangerDataMaskPolicyItem)
+        self.rowFilterPolicyItems = type_coerce_list(self.rowFilterPolicyItems, RangerRowFilterPolicyItem)
+        self.validitySchedules    = type_coerce_list(self.validitySchedules, RangerValiditySchedule)
 
 
-class RangerPolicyItem:
-    def __init__(self, accesses=None, users=None, groups=None, roles=None, conditions=None, delegateAdmin=None):
-        self.accesses      = accesses if accesses is not None else []
-        self.users         = users if users is not None else []
-        self.groups        = groups if groups is not None else []
-        self.roles         = roles if roles is not None else []
-        self.conditions    = conditions if conditions is not None else []
-        self.delegateAdmin = delegateAdmin if delegateAdmin is not None else False
+class RangerPolicyResource(RangerBase):
+    def __init__(self, attrs={}):
+        RangerBase.__init__(self, attrs)
 
-    def __repr__(self):
-        return json.dumps(self, default=lambda x: x.__dict__, sort_keys=True, indent=4)
+        self.values      = attrs.get('values')
+        self.isExcludes  = non_null(attrs.get('isExcludes'), False)
+        self.isRecursive = non_null(attrs.get('isRecursive'), False)
 
 
-class RangerPolicyItemAccess:
-    def __init__(self, type=None, isAllowed=None):
-        self.type      = type
-        self.isAllowed = isAllowed if isAllowed is not None else True
+class RangerPolicyItemCondition(RangerBase):
+    def __init__(self, attrs={}):
+        RangerBase.__init__(self, attrs)
 
-    def __repr__(self):
-        return json.dumps(self, default=lambda x: x.__dict__, sort_keys=True, indent=4)
+        self.type   = attrs.get('type')
+        self.values = attrs.get('values')
 
 
-class RangerPolicyItemDataMaskInfo:
-    def __init__(self, dataMaskType=None, conditionExpr=None, valueExpr=None):
-        self.dataMaskType  = dataMaskType
-        self.conditionExpr = conditionExpr
-        self.valueExpr     = valueExpr
+class RangerPolicyItem(RangerBase):
+    def __init__(self, attrs={}):
+        RangerBase.__init__(self, attrs)
 
-    def __repr__(self):
-        return json.dumps(self, default=lambda x: x.__dict__, sort_keys=True, indent=4)
+        self.accesses      = attrs.get('accesses')
+        self.users         = attrs.get('users')
+        self.groups        = attrs.get('groups')
+        self.roles         = attrs.get('roles')
+        self.conditions    = attrs.get('conditions')
+        self.delegateAdmin = non_null(attrs.get('delegateAdmin'), False)
+
+    def type_coerce_attrs(self):
+        super(RangerPolicyItem, self).type_coerce_attrs()
+
+        self.accesses = type_coerce_list(self.accesses, RangerPolicyItemAccess)
 
 
 class RangerDataMaskPolicyItem(RangerPolicyItem):
-    def __init__(self, dataMaskInfo=None, accesses=None, users=None, groups=None, roles=None, conditions=None, delegateAdmin=None):
-        super().__init__(accesses, users, groups, roles, conditions, delegateAdmin)
+    def __init__(self, attrs={}):
+        RangerPolicyItem.__init__(self, attrs)
+
+        self.dataMaskInfo = attrs.get('dataMaskInfo')
 
-        self.dataMaskInfo = dataMaskInfo if dataMaskInfo is not None else RangerPolicyItemDataMaskInfo()
+    def type_coerce_attrs(self):
+        super(RangerDataMaskPolicyItem, self).type_coerce_attrs()
 
-    def __repr__(self):
-        return json.dumps(self, default=lambda x: x.__dict__, sort_keys=True, indent=4)
+        self.dataMaskInfo = type_coerce(self.dataMaskInfo, RangerPolicyItemDataMaskInfo)
 
 
 class RangerRowFilterPolicyItem(RangerPolicyItem):
-    def __init__(self, rowFilterInfo=None, accesses=None, users=None, groups=None, roles=None, conditions=None, delegateAdmin=None):
-        super().__init__(accesses, users, groups, roles, conditions, delegateAdmin)
-
-        self.rowFilterInfo = rowFilterInfo
-
-    def __repr__(self):
-        return json.dumps(self, default=lambda x: x.__dict__, sort_keys=True, indent=4)
-
-
-class RangerPolicy(RangerBase):
-    def __init__(self, id=None, guid=None, createdBy=None, updatedBy=None, createTime=None, updateTime=None,
-                 service=None, name=None, description=None, isEnabled=True, isAuditEnabled=None, resources=None,
-                 policyItems=None, dataMaskPolicyItems=None, rowFilterPolicyItems=None, serviceType=None, options=None,
-                 policyLabels=None, zoneName=None, isDenyAllElse=None, validitySchedules=None, version=None,
-                 denyPolicyItems=None, denyExceptions=None, allowExceptions=None, resourceSignature=None,
-                 policyType=None, policyPriority=None, conditions=None):
-        super().__init__(id, guid, createdBy, updatedBy, createTime, updateTime, version, isEnabled)
-
-        self.service              = service
-        self.name                 = name
-        self.policyType           = policyType
-        self.policyPriority       = policyPriority if policyPriority is not None else 0
-        self.description          = description
-        self.resourceSignature    = resourceSignature
-        self.isAuditEnabled       = isAuditEnabled if isAuditEnabled is not None else True
-        self.resources            = resources if resources is not None else {}
-        self.policyItems          = policyItems if policyItems is not None else []
-        self.denyPolicyItems      = denyPolicyItems if denyPolicyItems is not None else []
-        self.allowExceptions      = allowExceptions if allowExceptions is not None else []
-        self.denyExceptions       = denyExceptions if denyExceptions is not None else []
-        self.dataMaskPolicyItems  = dataMaskPolicyItems if dataMaskPolicyItems is not None else []
-        self.rowFilterPolicyItems = rowFilterPolicyItems if rowFilterPolicyItems is not None else []
-        self.serviceType          = serviceType
-        self.options              = options if options is not None else {}
-        self.validitySchedules    = validitySchedules if validitySchedules is not None else []
-        self.policyLabels         = policyLabels if policyLabels is not None else []
-        self.zoneName             = zoneName
-        self.conditions           = conditions
-        self.isDenyAllElse        = isDenyAllElse if isDenyAllElse is not None else False
-
-    def __repr__(self):
-        return json.dumps(self, default=lambda x: x.__dict__, sort_keys=True, indent=4)
+    def __init__(self, attrs={}):
+        RangerPolicyItem.__init__(self, attrs)
+
+        self.rowFilterInfo = attrs.get('rowFilterInfo')
+
+    def type_coerce_attrs(self):
+        super(RangerRowFilterPolicyItem, self).type_coerce_attrs()
+
+        self.rowFilterInfo = type_coerce(self.rowFilterInfo, RangerPolicyItemRowFilterInfo)
+
+
+class RangerValiditySchedule(RangerBase):
+    def __init__(self, attrs={}):
+        RangerBase.__init__(self, attrs)
+
+        self.startTime = attrs.get('startTime')
+        self.endTime   = attrs.get('endTime')
+        self.timeZone  = attrs.get('timeZone')
+
+
+class RangerPolicyItemAccess(RangerBase):
+    def __init__(self, attrs={}):
+        RangerBase.__init__(self, attrs)
+
+        self.type      = attrs.get('type')
+        self.isAllowed = non_null(attrs.get('isAllowed'), True)
+
+
+class RangerPolicyItemDataMaskInfo(RangerBase):
+    def __init__(self, attrs={}):
+        RangerBase.__init__(self, attrs)
+
+        self.dataMaskType  = attrs.get('dataMaskType')
+        self.conditionExpr = attrs.get('conditionExpr')
+        self.valueExpr     = attrs.get('valueExpr')
+
+
+class RangerPolicyItemRowFilterInfo(RangerBase):
+    def __init__(self, attrs={}):
+        RangerBase.__init__(self, attrs)
+
+        self.filterExpr = attrs.get('filterExpr')
diff --git a/intg/src/main/python/apache_ranger/model/ranger_role.py b/intg/src/main/python/apache_ranger/model/ranger_role.py
index 1c698ed..c789a76 100644
--- a/intg/src/main/python/apache_ranger/model/ranger_role.py
+++ b/intg/src/main/python/apache_ranger/model/ranger_role.py
@@ -16,33 +16,26 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import json
+from apache_ranger.model.ranger_base import RangerBase, RangerBaseModelObject
+from apache_ranger.utils             import *
 
-from apache_ranger.model.ranger_base import RangerBase
 
+class RoleMember(RangerBase):
+    def __init__(self, attrs={}):
+        RangerBase.__init__(self, attrs)
 
-class RoleMember:
-    def __init__(self, name=None, isAdmin=None):
-        self.name    = name
-        self.isAdmin = isAdmin if isAdmin is not None else False
+        self.name    = attrs.get('name')
+        self.isAdmin = non_null(attrs.get('isAdmin'), False)
 
-    def __repr__(self):
-        return json.dumps(self, default=lambda x: x.__dict__, sort_keys=True, indent=4)
 
+class RangerRole(RangerBaseModelObject):
+    def __init__(self, attrs={}):
+        RangerBaseModelObject.__init__(self, attrs)
 
-class RangerRole(RangerBase):
-    def __init__(self, id=None, guid=None, createdBy=None, updatedBy=None, createTime=None, updateTime=None,
-                 version=None, isEnabled=None, name=None, description=None, options=None, users=None, groups=None,
-                 roles=None, createdByUser=None):
-        super().__init__(id, guid, createdBy, updatedBy, createTime, updateTime, version, isEnabled)
-
-        self.name          = name
-        self.description   = description
-        self.options       = options if options is not None else {}
-        self.users         = users if users is not None else []
-        self.groups        = groups if groups is not None else []
-        self.roles         = roles if roles is not None else []
-        self.createdByUser = createdByUser
-
-    def __repr__(self):
-        return json.dumps(self, default=lambda x: x.__dict__, sort_keys=True, indent=4)
+        self.name          = attrs.get('name')
+        self.description   = attrs.get('description')
+        self.options       = attrs.get('options')
+        self.users         = attrs.get('users')
+        self.groups        = attrs.get('groups')
+        self.roles         = attrs.get('roles')
+        self.createdByUser = attrs.get('createdByUser')
diff --git a/intg/src/main/python/apache_ranger/model/ranger_security_zone.py b/intg/src/main/python/apache_ranger/model/ranger_security_zone.py
index 9ed8208..2ba0915 100644
--- a/intg/src/main/python/apache_ranger/model/ranger_security_zone.py
+++ b/intg/src/main/python/apache_ranger/model/ranger_security_zone.py
@@ -16,33 +16,25 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import json
+from apache_ranger.model.ranger_base import RangerBase, RangerBaseModelObject
 
-from apache_ranger.model.ranger_base import RangerBase
 
+class RangerSecurityZoneService(RangerBase):
+    def __init__(self, attrs={}):
+        RangerBase.__init__(self, attrs)
 
-class RangerSecurityZoneService:
-    def __init__(self, resources=None):
-        self.resources = resources if resources is not None else []
+        self.resources = attrs.get('resources')
 
-    def __repr__(self):
-        return json.dumps(self, default=lambda x: x.__dict__, sort_keys=True, indent=4)
 
+class RangerSecurityZone(RangerBaseModelObject):
+    def __init__(self, attrs={}):
+        RangerBaseModelObject.__init__(self, attrs)
 
-class RangerSecurityZone(RangerBase):
-    def __init__(self, id=None, guid=None, createdBy=None, updatedBy=None, createTime=None, updateTime=None,
-                 version=None, isEnabled=None, name=None, services=None, tagServices=None, adminUsers=None,
-                 adminUserGroups=None, auditUsers=None, auditUserGroups=None, description=None):
-        super().__init__(id, guid, createdBy, updatedBy, createTime, updateTime, version, isEnabled)
-        self.name = name
-        self.services = services if services is not None else {}
-        self.tagServices = tagServices if tagServices is not None else []
-        self.adminUsers = adminUsers if adminUsers is not None else []
-        self.adminUserGroups = adminUserGroups if adminUserGroups is not None else []
-        self.auditUsers = auditUsers if auditUsers is not None else []
-        self.auditUserGroups = auditUserGroups if auditUserGroups is not None else []
-        self.description = description
-        return
-
-    def __repr__(self):
-        return json.dumps(self, default=lambda x: x.__dict__, sort_keys=True, indent=4)
+        self.name            = attrs.get('name')
+        self.services        = attrs.get('services')
+        self.tagServices     = attrs.get('tagServices')
+        self.adminUsers      = attrs.get('adminUsers')
+        self.adminUserGroups = attrs.get('adminUserGroups')
+        self.auditUsers      = attrs.get('auditUsers')
+        self.auditUserGroups = attrs.get('auditUserGroups')
+        self.description     = attrs.get('description')
diff --git a/intg/src/main/python/apache_ranger/model/ranger_service.py b/intg/src/main/python/apache_ranger/model/ranger_service.py
index e07a706..d8ea93b 100644
--- a/intg/src/main/python/apache_ranger/model/ranger_service.py
+++ b/intg/src/main/python/apache_ranger/model/ranger_service.py
@@ -16,28 +16,20 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import json
+from apache_ranger.model.ranger_base import RangerBaseModelObject
 
-from apache_ranger.model.ranger_base import RangerBase
 
+class RangerService(RangerBaseModelObject):
+    def __init__(self, attrs={}):
+        RangerBaseModelObject.__init__(self, attrs)
 
-class RangerService(RangerBase):
-    def __init__(self, id=None, guid=None, createdBy=None, updatedBy=None, createTime=None, updateTime=None,
-                 version=None, isEnabled=None, type=None, name=None, displayName=None, description=None,
-                 tagService=None, configs=None, policyVersion=None, policyUpdateTime=None, tagVersion=None,
-                 tagUpdateTime=None):
-        super().__init__(id, guid, createdBy, updatedBy, createTime, updateTime, version, isEnabled)
-
-        self.type             = type
-        self.name             = name
-        self.displayName      = displayName
-        self.description      = description
-        self.tagService       = tagService
-        self.configs          = configs if configs is not None else {}
-        self.policyVersion    = policyVersion
-        self.policyUpdateTime = policyUpdateTime
-        self.tagVersion       = tagVersion
-        self.tagUpdateTime    = tagUpdateTime
-
-    def __repr__(self):
-        return json.dumps(self, default=lambda x: x.__dict__, sort_keys=True, indent=4)
+        self.type             = attrs.get('type')
+        self.name             = attrs.get('name')
+        self.displayName      = attrs.get('displayName')
+        self.description      = attrs.get('description')
+        self.tagService       = attrs.get('tagService')
+        self.configs          = attrs.get('configs')
+        self.policyVersion    = attrs.get('policyVersion')
+        self.policyUpdateTime = attrs.get('policyUpdateTime')
+        self.tagVersion       = attrs.get('tagVersion')
+        self.tagUpdateTime    = attrs.get('tagUpdateTime')
diff --git a/intg/src/main/python/apache_ranger/model/ranger_service_def.py b/intg/src/main/python/apache_ranger/model/ranger_service_def.py
index ec3845d..b35fe2a 100644
--- a/intg/src/main/python/apache_ranger/model/ranger_service_def.py
+++ b/intg/src/main/python/apache_ranger/model/ranger_service_def.py
@@ -16,121 +16,194 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import json
+from apache_ranger.model.ranger_base import RangerBase, RangerBaseModelObject
+from apache_ranger.utils             import *
+
+
+class RangerServiceDef(RangerBaseModelObject):
+    def __init__(self, attrs={}):
+        RangerBaseModelObject.__init__(self, attrs)
+
+        self.name             = attrs.get('name')
+        self.displayName      = attrs.get('displayName')
+        self.implClass        = attrs.get('implClass')
+        self.label            = attrs.get('label')
+        self.description      = attrs.get('description')
+        self.rbKeyLabel       = attrs.get('rbKeyLabel')
+        self.rbKeyDescription = attrs.get('rbKeyDescription')
+        self.options          = attrs.get('options')
+        self.configs          = attrs.get('configs')
+        self.resources        = attrs.get('resources')
+        self.accessTypes      = attrs.get('accessTypes')
+        self.policyConditions = attrs.get('policyConditions')
+        self.contextEnrichers = attrs.get('contextEnrichers')
+        self.enums            = attrs.get('enums')
+        self.dataMaskDef      = attrs.get('dataMaskDef')
+        self.rowFilterDef     = attrs.get('rowFilterDef')
+
+    def type_coerce_attrs(self):
+        super(RangerServiceDef, self).type_coerce_attrs()
+
+        self.configs          = type_coerce_list(self.configs, RangerResourceDef)
+        self.resources        = type_coerce_list(self.resources, RangerResourceDef)
+        self.accessTypes      = type_coerce_list(self.accessTypes, RangerAccessTypeDef)
+        self.policyConditions = type_coerce_list(self.policyConditions, RangerPolicyConditionDef)
+        self.contextEnrichers = type_coerce_list(self.contextEnrichers, RangerContextEnricherDef)
+        self.enums            = type_coerce_list(self.enums, RangerEnumDef)
+        self.dataMaskDef      = type_coerce(self.dataMaskDef, RangerDataMaskDef)
+        self.rowFilterDef     = type_coerce(self.rowFilterDef, RangerRowFilterDef)
 
-from apache_ranger.model.ranger_base import RangerBase
+
+class RangerServiceConfigDef:
+    def __init__(self, attrs={}):
+        RangerBase.__init__(self, attrs)
+
+        self.itemId                 = attrs.get('itemId')
+        self.name                   = attrs.get('name')
+        self.type                   = attrs.get('type')
+        self.subType                = attrs.get('subType')
+        self.mandatory              = attrs.get('mandatory')
+        self.defaultValue           = attrs.get('defaultValue')
+        self.validationRegEx        = attrs.get('validationRegEx')
+        self.validationMessage      = attrs.get('validationMessage')
+        self.uiHint                 = attrs.get('uiHint')
+        self.label                  = attrs.get('label')
+        self.description            = attrs.get('description')
+        self.rbKeyLabel             = attrs.get('rbKeyLabel')
+        self.rbKeyDescription       = attrs.get('rbKeyDescription')
+        self.rbKeyValidationMessage = attrs.get('rbKeyValidationMessage')
+
+
+class RangerResourceDef(RangerBase):
+    def __init__(self, attrs={}):
+        RangerBase.__init__(self, attrs)
+
+        self.itemId                 = attrs.get('itemId')
+        self.name                   = attrs.get('name')
+        self.type                   = attrs.get('type')
+        self.level                  = non_null(attrs.get('level'), 1)
+        self.parent                 = attrs.get('parent')
+        self.mandatory              = attrs.get('mandatory')
+        self.lookupSupported        = attrs.get('lookupSupported')
+        self.recursiveSupported     = attrs.get('recursiveSupported')
+        self.excludesSupported      = attrs.get('excludesSupported')
+        self.matcher                = attrs.get('matcher')
+        self.matcherOptions         = attrs.get('matcherOptions')
+        self.validationRegEx        = attrs.get('validationRegEx')
+        self.validationMessage      = attrs.get('validationMessage')
+        self.uiHint                 = attrs.get('uiHint')
+        self.label                  = attrs.get('label')
+        self.description            = attrs.get('description')
+        self.rbKeyLabel             = attrs.get('rbKeyLabel')
+        self.rbKeyDescription       = attrs.get('rbKeyDescription')
+        self.rbKeyValidationMessage = attrs.get('rbKeyValidationMessage')
+        self.accessTypeRestrictions = attrs.get('accessTypeRestrictions')
+        self.isValidLeaf            = attrs.get('isValidLeaf')
+
+
+class RangerAccessTypeDef(RangerBase):
+    def __init__(self, attrs={}):
+        RangerBase.__init__(self, attrs)
+
+        self.itemId        = attrs.get('itemId')
+        self.name          = attrs.get('name')
+        self.label         = attrs.get('label')
+        self.rbKeyLabel    = attrs.get('rbKeyLabel')
+        self.impliedGrants = attrs.get('impliedGrants')
+
+
+class RangerPolicyConditionDef(RangerBase):
+    def __init__(self, attrs={}):
+        RangerBase.__init__(self, attrs)
+
+        self.itemId                 = attrs.get('itemId')
+        self.name                   = attrs.get('name')
+        self.evaluator              = attrs.get('evaluator')
+        self.evaluatorOptions       = attrs.get('evaluatorOptions')
+        self.validationRegEx        = attrs.get('validationRegEx')
+        self.validationMessage      = attrs.get('validationMessage')
+        self.uiHint                 = attrs.get('uiHint')
+        self.label                  = attrs.get('label')
+        self.description            = attrs.get('description')
+        self.rbKeyLabel             = attrs.get('rbKeyLabel')
+        self.rbKeyDescription       = attrs.get('rbKeyDescription')
+        self.rbKeyValidationMessage = attrs.get('rbKeyValidationMessage')
+
+
+class RangerContextEnricherDef(RangerBase):
+    def __init__(self, attrs={}):
+        RangerBase.__init__(self, attrs)
+
+        self.itemId         = attrs.get('itemId')
+        self.name           = attrs.get('name')
+        self.enricher       = attrs.get('enricher')
+        self.enricherOptions = attrs.get('enricherOptions')
+
+
+class RangerEnumDef(RangerBase):
+    def __init__(self, attrs={}):
+        RangerBase.__init__(self, attrs)
+
+        self.itemId       = attrs.get('itemId')
+        self.name         = attrs.get('name')
+        self.elements     = attrs.get('elements')
+        self.defaultIndex = attrs.get('defaultIndex')
+
+    def type_coerce_attrs(self):
+        super(RangerEnumDef, self).type_coerce_attrs()
+
+        self.elements = type_coerce_list(self.resources, RangerEnumElementDef)
+
+
+class RangerDataMaskDef(RangerBase):
+    def __init__(self, attrs={}):
+        RangerBase.__init__(self, attrs)
+
+        self.maskTypes   = attrs.get('maskTypes')
+        self.accessTypes = attrs.get('accessTypes')
+        self.resources   = attrs.get('resources')
+
+    def type_coerce_attrs(self):
+        super(RangerDataMaskDef, self).type_coerce_attrs()
+
+        self.maskTypes   = type_coerce_list(self.maskTypes, RangerDataMaskTypeDef)
+        self.accessTypes = type_coerce_list(self.accessTypes, RangerAccessTypeDef)
+        self.resources   = type_coerce_list(self.resources, RangerResourceDef)
+
+
+class RangerRowFilterDef(RangerBase):
+    def __init__(self, attrs={}):
+        RangerBase.__init__(self, attrs)
+
+        self.accessTypes = attrs.get('accessTypes')
+        self.resources   = attrs.get('resources')
+
+    def type_coerce_attrs(self):
+        super(RangerRowFilterDef, self).type_coerce_attrs()
+
+        self.accessTypes = type_coerce_list(self.accessTypes, RangerAccessTypeDef)
+        self.resources   = type_coerce_list(self.accessTypes, RangerResourceDef)
 
 
-class RangerDataMaskDef:
-    def __init__(self, maskTypes=None, accessTypes=None, resources=None):
-        self.maskTypes   = maskTypes if maskTypes is not None else []
-        self.accessTypes = accessTypes if accessTypes is not None else []
-        self.resources   = resources if resources is not None else []
-
-    def __repr__(self):
-        return json.dumps(self, default=lambda x: x.__dict__, sort_keys=True, indent=4)
-
+class RangerEnumElementDef(RangerBase):
+    def __init__(self, attrs={}):
+        RangerBase.__init__(self, attrs)
 
-class RangerRowFilterDef:
-    def __init__(self, accessTypes=None, resources=None):
-        self.accessTypes = accessTypes if accessTypes is not None else []
-        self.resources   = resources if resources is not None else []
+        self.itemId     = attrs.get('itemId')
+        self.name       = attrs.get('name')
+        self.label      = attrs.get('label')
+        self.rbKeyLabel = attrs.get('rbKeyLabel')
 
-    def __repr__(self):
-        return json.dumps(self, default=lambda x: x.__dict__, sort_keys=True, indent=4)
 
+class RangerDataMaskTypeDef(RangerBase):
+    def __init__(self, attrs={}):
+        RangerBase.__init__(self, attrs)
 
-class RangerServiceConfigDef:
-    def __init__(self, itemId=None, name=None, type=None, subType=None, mandatory=None, defaultValue=None,
-                 validationRegEx=None, validationMessage=None, uiHint=None, label=None, description=None,
-                 rbKeyLabel=None, rbKeyDescription=None, rbKeyValidationMessage=None):
-        self.itemId                 = itemId
-        self.name                   = name
-        self.type                   = type
-        self.subType                = subType
-        self.mandatory              = mandatory if mandatory is not None else False
-        self.defaultValue           = defaultValue
-        self.validationRegEx        = validationRegEx
-        self.validationMessage      = validationMessage
-        self.uiHint                 = uiHint
-        self.label                  = label
-        self.description            = description
-        self.rbKeyLabel             = rbKeyLabel
-        self.rbKeyDescription       = rbKeyDescription
-        self.rbKeyValidationMessage = rbKeyValidationMessage
-
-    def __repr__(self):
-        return json.dumps(self, default=lambda x: x.__dict__, sort_keys=True, indent=4)
-
-
-class RangerAccessTypeDef:
-    def __init__(self, itemId=None, name=None, label=None, rbKeyLabel=None, impliedGrants=None):
-        self.itemId        = itemId
-        self.name          = name
-        self.label         = label
-        self.rbKeyLabel    = rbKeyLabel
-        self.impliedGrants = impliedGrants if impliedGrants is not None else []
-
-    def __repr__(self):
-        return json.dumps(self, default=lambda x: x.__dict__, sort_keys=True, indent=4)
-
-
-class RangerResourceDef:
-    def __init__(self, itemId=None, name=None, type=None, level=None, parent=None, mandatory=None, lookupSupported=None,
-                 recursiveSupported=None, excludesSupported=None, matcher=None, matcherOptions=None,
-                 validationRegEx=None, validationMessage=None, uiHint=None, label=None, description=None,
-                 rbKeyLabel=None, rbKeyDescription=None, rbKeyValidationMessage=None, accessTypeRestrictions=None,
-                 isValidLeaf=None):
-        self.itemId                 = itemId
-        self.name                   = name
-        self.type                   = type
-        self.level                  = level if level is not None else 1
-        self.parent                 = parent
-        self.mandatory              = mandatory if mandatory is not None else False
-        self.lookupSupported        = lookupSupported if lookupSupported is not None else False
-        self.recursiveSupported     = recursiveSupported if recursiveSupported is not None else False
-        self.excludesSupported      = excludesSupported if excludesSupported is not None else False
-        self.matcher                = matcher
-        self.matcherOptions         = matcherOptions if matcherOptions is not None else {}
-        self.validationRegEx        = validationRegEx
-        self.validationMessage      = validationMessage
-        self.uiHint                 = uiHint
-        self.label                  = label
-        self.description            = description
-        self.rbKeyLabel             = rbKeyLabel
-        self.rbKeyDescription       = rbKeyDescription
-        self.rbKeyValidationMessage = rbKeyValidationMessage
-        self.accessTypeRestrictions = accessTypeRestrictions if accessTypeRestrictions is not None else []
-        self.isValidLeaf            = isValidLeaf
-
-    def __repr__(self):
-        return json.dumps(self, default=lambda x: x.__dict__, sort_keys=True, indent=4)
-
-
-class RangerServiceDef(RangerBase):
-    def __init__(self, id=None, guid=None, createdBy=None, updatedBy=None, createTime=None, updateTime=None,
-                 version=None, isEnabled=None, name=None, displayName=None, implClass=None, label=None,
-                 description=None, rbKeyLabel=None, rbKeyDescription=None, options=None, configs=None, resources=None,
-                 accessTypes=None, policyConditions=None, contextEnrichers=None, enums=None, dataMaskDef=None,
-                 rowFilterDef=None):
-        super().__init__(id, guid, createdBy, updatedBy, createTime, updateTime, version, isEnabled)
-
-        self.name             = name
-        self.displayName      = displayName
-        self.implClass        = implClass
-        self.label            = label
-        self.description      = description
-        self.rbKeyLabel       = rbKeyLabel
-        self.rbKeyDescription = rbKeyDescription
-        self.options          = options if options is not None else {}
-        self.configs          = configs if configs is not None else []
-        self.resources        = resources if resources is not None else []
-        self.accessTypes      = accessTypes if accessTypes is not None else []
-        self.policyConditions = policyConditions if policyConditions is not None else []
-        self.contextEnrichers = contextEnrichers if contextEnrichers is not None else []
-        self.enums            = enums if enums is not None else []
-        self.dataMaskDef      = dataMaskDef if dataMaskDef is not None else RangerDataMaskDef()
-        self.rowFilterDef     = rowFilterDef if rowFilterDef is not None else RangerRowFilterDef()
-
-    def __repr__(self):
-        return json.dumps(self, default=lambda x: x.__dict__, sort_keys=True, indent=4)
+        self.itemId           = attrs.get('itemId')
+        self.name             = attrs.get('name')
+        self.label            = attrs.get('label')
+        self.description      = attrs.get('description')
+        self.transformer      = attrs.get('transformer')
+        self.dataMaskOptions  = attrs.get('dataMaskOptions')
+        self.rbKeyLabel       = attrs.get('rbKeyLabel')
+        self.rbKeyDescription = attrs.get('rbKeyDescription')
diff --git a/intg/src/main/python/apache_ranger/utils.py b/intg/src/main/python/apache_ranger/utils.py
new file mode 100644
index 0000000..4c7e77f
--- /dev/null
+++ b/intg/src/main/python/apache_ranger/utils.py
@@ -0,0 +1,92 @@
+#!/usr/bin/env python
+
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import enum
+
+APPLICATION_JSON         = 'application/json'
+
+
+def non_null(obj, defValue):
+    return obj if obj is not None else defValue
+
+def type_coerce(obj, objType):
+    if isinstance(obj, objType):
+        ret = obj
+    elif isinstance(obj, dict):
+        ret = objType(obj)
+
+        ret.type_coerce_attrs()
+    else:
+        ret = None
+
+    return ret
+
+def type_coerce_list(obj, objType):
+    if isinstance(obj, list):
+        ret = []
+        for entry in obj:
+            ret.append(type_coerce(entry, objType))
+    else:
+        ret = None
+
+    return ret
+
+def type_coerce_dict(obj, objType):
+    if isinstance(obj, dict):
+        ret = {}
+        for k, v in obj.items():
+            ret[k] = type_coerce(v, objType)
+    else:
+        ret = None
+
+    return ret
+
+def type_coerce_dict_list(obj, objType):
+    if isinstance(obj, dict):
+        ret = {}
+        for k, v in obj.items():
+            ret[k] = type_coerce_list(v, objType)
+    else:
+        ret = None
+
+    return ret
+
+
+class API:
+    def __init__(self, path, method, expected_status, consumes=APPLICATION_JSON, produces=APPLICATION_JSON):
+        self.path            = path
+        self.method          = method
+        self.expected_status = expected_status
+        self.consumes        = consumes
+        self.produces        = produces
+
+    def format_path(self, params):
+        return API(self.path.format(**params), self.method, self.expected_status, self.consumes, self.produces)
+
+
+class HttpMethod(enum.Enum):
+    GET    = "GET"
+    PUT    = "PUT"
+    POST   = "POST"
+    DELETE = "DELETE"
+
+
+class HTTPStatus:
+    OK                  = 200
+    NO_CONTENT          = 204
+    SERVICE_UNAVAILABLE = 503
diff --git a/intg/src/main/python/setup.py b/intg/src/main/python/setup.py
index b073a80..5a97657 100644
--- a/intg/src/main/python/setup.py
+++ b/intg/src/main/python/setup.py
@@ -16,26 +16,34 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import setuptools
+from setuptools import setup, find_packages
 
+# External dependencies
+requirements = ['requests>=2.24']
+
+long_description = ''
 with open("README.md", "r") as fh:
     long_description = fh.read()
 
-setuptools.setup(
+setup(
     name="apache-ranger",
-    version="0.0.2",
+    version="0.0.3",
     author="Apache Ranger",
     author_email="dev@ranger.apache.org",
     description="Apache Ranger Python client",
     long_description=long_description,
     long_description_content_type="text/markdown",
     url="https://github.com/apache/ranger/tree/master/intg/src/main/python",
-    packages=setuptools.find_packages(),
+    license='Apache LICENSE 2.0',
     classifiers=[
-        "Programming Language :: Python :: 3",
+        "Programming Language :: Python :: 2.7",
         "License :: OSI Approved :: Apache Software License",
         "Operating System :: OS Independent",
     ],
+    packages=find_packages(),
+    install_requires=requirements,
+    include_package_data=True,
+    zip_safe=False,
     keywords='ranger client, apache ranger',
-    python_requires='>=3.6',
+    python_requires='>=2.7',
 )
diff --git a/ranger-examples/sample-client/src/main/python/sample_client.py b/ranger-examples/sample-client/src/main/python/sample_client.py
index 1d1c331..9027349 100644
--- a/ranger-examples/sample-client/src/main/python/sample_client.py
+++ b/ranger-examples/sample-client/src/main/python/sample_client.py
@@ -16,131 +16,304 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import argparse
-import logging.config
+import time
 
-from os import path
+from apache_ranger.model.ranger_service import *
+from apache_ranger.client.ranger_client import *
+from apache_ranger.model.ranger_policy  import *
 
-from apache_ranger.model.ranger_service     import RangerService
-from apache_ranger.model.ranger_role        import RangerRole, RoleMember
-from apache_ranger.client.ranger_client     import RangerClient
-from apache_ranger.model.ranger_policy      import RangerPolicy, RangerPolicyResource
-from apache_ranger.model.ranger_service_def import RangerServiceConfigDef, RangerAccessTypeDef, RangerResourceDef, RangerServiceDef
 
-LOG_CONFIG = path.dirname(__file__) + '/../resources/logging.conf'
+## create a client to connect to Apache Ranger admin server
+ranger_url  = 'http://localhost:6080'
+ranger_auth = ('admin', 'rangerR0cks!')
 
-logging.config.fileConfig(LOG_CONFIG, disable_existing_loggers=False)
+# For Kerberos authentication
+#
+# from requests_kerberos import HTTPKerberosAuth
+#
+# ranger_auth = HTTPKerberosAuth()
+
+
+print('Using Ranger at ' + ranger_url);
+
+ranger = RangerClient(ranger_url, ranger_auth)
+
+# to disable SSL certificate validation (not recommended for production use!)
+#
+# ranger.session.verify = False
+
+
+print('Listing service-defs..')
+service_defs = ranger.find_service_defs()
+
+print('    ' + str(len(service_defs)) + ' service-defs found')
+for service_def in service_defs:
+    print('        ' + 'id: ' + str(service_def.id) + ', name: ' + service_def.name)
+
+
+service_name = 'dev_hive-' + str(int(time.time() * 1000))
+
+print('Creating service: name=' + service_name)
+
+service         = RangerService({'name': service_name, 'type': 'hive'})
+service.configs = {'username':'hive', 'password':'hive', 'jdbc.driverClassName': 'org.apache.hive.jdbc.HiveDriver', 'jdbc.url': 'jdbc:hive2://ranger-hadoop:10000', 'hadoop.security.authorization': 'true'}
+
+created_service = ranger.create_service(service)
+
+print('    created service: id: ' + str(created_service.id) + ', name: ' + created_service.name)
+
+service_id = created_service.id
+
+
+print('Retrieving service: id=' + str(service_id))
+
+retrieved_service = ranger.get_service_by_id(service_id)
+
+print('    retrieved service: id: ' + str(retrieved_service.id) + ', name: ' + retrieved_service.name)
+
+
+print('Retrieving service: name=' + service_name)
+
+retrieved_service = ranger.get_service(service_name)
+
+print('    retrieved service: id: ' + str(retrieved_service.id) + ', name: ' + retrieved_service.name)
+
+
+print('Updating service: id=' + str(service_id))
+
+saved_value                 = created_service.displayName
+created_service.displayName = service_name + '-UPDATE1'
+
+updated_service1 = ranger.update_service_by_id(service_id, created_service)
+
+print('    updated service: id: ' + str(updated_service1.id) + ', displayName: ' + saved_value + ', updatedDisplayName: ' + updated_service1.displayName)
+
+
+print('Updating service: name=' + service_name)
+
+saved_value                  = updated_service1.displayName
+updated_service1.displayName = service_name + '-UPDATE2'
+
+updated_service2 = ranger.update_service(service_name, updated_service1)
+
+print('    updated service: id: ' + str(updated_service2.id) + ', displayName: ' + saved_value + ', updatedDisplayName: ' + updated_service2.displayName)
+
+
+print('Listing services..')
+services = ranger.find_services()
+
+print('    ' + str(len(services)) + ' services found')
+for svc in services:
+    print('        ' + 'id: ' + str(svc.id) + ', type: ' + svc.type + ', name: ' + svc.name)
+
+
+print('Deleting service id=' + str(service_id))
+
+ranger.delete_service_by_id(service_id)
+
+print('    deleted service: id: ' + str(service_id) + ', name: ' + updated_service2.name)
+
+
+print('Deleting service: name=' + service.name)
+
+service_to_delete = ranger.create_service(service)
+
+print('    created service: id: ' + str(service_to_delete.id) + ', name: ' + service_to_delete.name)
+
+ranger.delete_service(service_to_delete.name)
+
+print('    deleted service: id: ' + str(service_to_delete.id) + ', name: ' + service_to_delete.name)
+
+
+print('Listing services..')
+services = ranger.find_services()
+
+print('    ' + str(len(services)) + ' services found')
+for svc in services:
+    print('        ' + 'id: ' + str(svc.id) + ', type: ' + svc.type + ', name: ' + svc.name)
+
+
+policy_name = 'test policy'
+
+print('Creating policy: name=' + policy_name)
+
+created_service = ranger.create_service(service)
+
+print('    created service: id: ' + str(created_service.id) + ', name: ' + created_service.name)
+
+service_id   = created_service.id
+service_name = created_service.name
+
+policy             = RangerPolicy()
+policy.service     = service_name
+policy.name        = policy_name
+policy.description = 'test description'
+policy.resources   = { 'database': RangerPolicyResource({ 'values': ['test_db'] }),
+                       'table':    RangerPolicyResource({ 'values': ['test_tbl'] }),
+					   'column':   RangerPolicyResource({ 'values': ['*'] }) }
+
+allowItem1          = RangerPolicyItem()
+allowItem1.users    = [ 'admin' ]
+allowItem1.accesses = [ RangerPolicyItemAccess({ 'type': 'create' }),
+                        RangerPolicyItemAccess({ 'type': 'alter' }),
+                        RangerPolicyItemAccess({ 'type': 'select' }) ]
+
+denyItem1          = RangerPolicyItem()
+denyItem1.users    = [ 'admin' ]
+denyItem1.accesses = [ RangerPolicyItemAccess({ 'type': 'drop' }) ]
+
+policy.policyItems     = [ allowItem1 ]
+policy.denyPolicyItems = [ denyItem1 ]
+
+created_policy = ranger.create_policy(policy)
+
+print('    created policy: id: ' + str(created_policy.id) + ', name: ' + created_policy.name)
+
+policy_id = created_policy.id
+
+
+data_mask_policy_name = 'test masking policy'
+
+print('Creating data-masking policy: name=' + data_mask_policy_name)
+
+data_mask_policy             = RangerPolicy()
+data_mask_policy.service     = service_name
+data_mask_policy.policyType  = RangerPolicy.POLICY_TYPE_DATAMASK
+data_mask_policy.name        = data_mask_policy_name
+data_mask_policy.description = 'test description'
+data_mask_policy.resources   = { 'database': RangerPolicyResource({ 'values': ['test_db'] }),
+                                 'table':    RangerPolicyResource({ 'values': ['test_tbl'] }),
+					             'column':   RangerPolicyResource({ 'values': ['test_col'] }) }
+
+policyItem1              = RangerDataMaskPolicyItem()
+policyItem1.users        = [ 'admin' ]
+policyItem1.accesses     = [ RangerPolicyItemAccess({ 'type': 'select' }) ]
+policyItem1.dataMaskInfo = RangerPolicyItemDataMaskInfo({ 'dataMaskType': 'MASK_SHOW_LAST_4' })
+
+data_mask_policy.dataMaskPolicyItems = [ policyItem1 ]
+
+created_data_mask_policy = ranger.create_policy(data_mask_policy)
+
+print('    created data-masking policy: id: ' + str(created_data_mask_policy.id) + ', name: ' + created_data_mask_policy.name)
+
+
+row_filter_policy_name = 'test row filter policy'
+
+print('Creating row-filtering policy: name=' + row_filter_policy_name)
+
+row_filter_policy             = RangerPolicy()
+row_filter_policy.service     = service_name
+row_filter_policy.policyType  = RangerPolicy.POLICY_TYPE_ROWFILTER
+row_filter_policy.name        = row_filter_policy_name
+row_filter_policy.description = 'test description'
+row_filter_policy.resources   = { 'database': RangerPolicyResource({ 'values': ['test_db'] }),
+                                  'table':    RangerPolicyResource({ 'values': ['test_tbl'] }) }
+
+policyItem1               = RangerRowFilterPolicyItem()
+policyItem1.users         = [ 'admin' ]
+policyItem1.accesses      = [ RangerPolicyItemAccess({ 'type': 'select' }) ]
+policyItem1.rowFilterInfo = RangerPolicyItemRowFilterInfo({ 'filterExpr': 'country_code = "US"' })
+
+row_filter_policy.rowFilterPolicyItems = [ policyItem1 ]
 
-log = logging.getLogger(__name__)
+create_row_filter_policy = ranger.create_policy(row_filter_policy)
 
-if __name__ == "__main__":
-    parser = argparse.ArgumentParser(description='Parameters required for connection to Ranger Admin!')
+print('    created row-filtering policy: id: ' + str(create_row_filter_policy.id) + ', name: ' + create_row_filter_policy.name)
 
-    parser.add_argument('--url', default='http://localhost:6080')
-    parser.add_argument('--username')
-    parser.add_argument('--password')
 
-    args = parser.parse_args()
+print('Retrieving policy: id=' + str(policy_id))
 
-    service_def_name = "sampleServiceDef"
-    service_name     = "sampleService"
-    policy_name      = "samplePolicy"
-    role_name        = "sampleRole"
+retrieved_policy = ranger.get_policy_by_id(policy_id)
 
-    ranger_client = RangerClient(args.url, args.username, args.password)
+print('    retrieved policy: id: ' + str(retrieved_policy.id) + ', name: ' + retrieved_policy.name)
 
 
-    # create a new service definition
-    config       = RangerServiceConfigDef(itemId=1, name='sampleConfig', type='string')
-    access_type  = RangerAccessTypeDef(itemId=1, name='sampleAccess')
-    resource_def = RangerResourceDef(itemId=1, name='root', type='string')
-    service_def  = RangerServiceDef(name=service_def_name, configs=[config], accessTypes=[access_type],
-                                    resources=[resource_def])
+print('Retrieving policy: service_name=' + service_name + ', policy_name=' + data_mask_policy.name)
 
-    created_service_def = ranger_client.create_service_def(service_def)
+retrieved_policy = ranger.get_policy(service_name, data_mask_policy.name)
 
-    log.info('New Service Definition created successfully {}'.format(created_service_def))
+print('    retrieved policy: id: ' + str(retrieved_policy.id) + ', name: ' + retrieved_policy.name)
 
 
-    # create a new service
-    service = RangerService(name=service_name, type=service_def_name)
+print('Retrieving policy: service_name=' + service_name + ', policy_name=' + row_filter_policy.name)
 
-    created_service = ranger_client.create_service(service)
+retrieved_policy = ranger.get_policy(service_name, row_filter_policy.name)
 
-    log.info('New Service created successfully {}'.format(created_service))
+print('    retrieved policy: id: ' + str(retrieved_policy.id) + ', name: ' + retrieved_policy.name)
 
 
-    # create a new policy
-    resource = RangerPolicyResource(['/path/to/sample/resource'], False, False)
-    policy   = RangerPolicy(service=service_name, name=policy_name, resources={'root': resource})
+print('Retrieving policies in service ' + created_policy.service + '..')
 
-    created_policy = ranger_client.create_policy(policy)
+policies = ranger.get_policies_in_service(created_policy.service)
 
-    log.info('New Ranger Policy created successfully {}'.format(created_policy))
+print('    ' + str(len(policies)) + ' policies found')
+for plcy in policies:
+    print('        id: ' + str(plcy.id) + ', service: ' + plcy.service + ', name: ' + plcy.name)
 
 
-    # update an existing policy
-    policy = RangerPolicy(service=service_name, name=policy_name, description='Policy Updated!')
+print('Updating policy: id=' + str(policy_id))
 
-    updated_policy = ranger_client.update_policy(service_name, policy_name, policy)
+saved_value                = created_policy.description
+created_policy.description = 'updated description - #1'
 
-    log.info('Ranger Policy updated successfully {}'.format(updated_policy))
+updated_policy1 = ranger.update_policy_by_id(policy_id, created_policy)
 
+print('    updated policy: id: ' + str(updated_policy1.id) + ', description: ' + saved_value + ', updatedDescription: ' + updated_policy1.description)
 
-    # get a policy by name
-    fetched_policy = ranger_client.get_policy(service_name, policy_name)
 
-    log.info('Policy {} fetched {}'.format(policy_name, fetched_policy))
+print('Updating policy: service_name=' + service_name + ', policy_name=' + policy_name)
 
+saved_value                 = updated_policy1.description
+updated_policy1.description = 'updated description - #2'
 
-    # get all policies
-    all_policies = ranger_client.find_policies({})
+updated_policy2 = ranger.update_policy(service_name, policy_name, updated_policy1)
 
-    for id, policy in enumerate(all_policies):
-        log.info('Policy #{}: {}'.format(id, RangerPolicy(**policy)))
+print('    updated policy: id: ' + str(updated_policy2.id) + ', description: ' + saved_value + ', updatedDescription: ' + updated_policy2.description)
 
 
-    # delete a policy by name
-    ranger_client.delete_policy(service_name, policy_name)
+print('Deleting policy: id=' + str(policy_id))
 
-    log.info('Policy {} successfully deleted'.format(policy_name))
+ranger.delete_policy_by_id(policy_id)
 
+print('    deleted policy: id: ' + str(policy_id) + ', name: ' + updated_policy2.name)
 
-    # create a role in ranger
-    sample_role = RangerRole(name=role_name, description='Sample Role', users=[RoleMember(isAdmin=True)])
 
-    created_role = ranger_client.create_role(service_name, sample_role)
+print('Deleting policy: service_name=' + data_mask_policy.service + ', policy_name=' + data_mask_policy.name)
 
-    log.info('New Role successfully created {}'.format(created_role))
+ranger.delete_policy(data_mask_policy.service, data_mask_policy.name)
 
+print('    deleted policy: id: ' + str(data_mask_policy.id) + ', name: ' + data_mask_policy.name)
 
-    # update a role in ranger
-    sample_role = RangerRole(name=role_name, description='Updated Sample Role!')
 
-    updated_role = ranger_client.update_role(created_role.id, sample_role)
+print('Deleting policy: service_name=' + row_filter_policy.service + ', policy_name=' + row_filter_policy.name)
 
-    log.info('Role {} successfully updated {}'.format(role_name, updated_role))
+ranger.delete_policy(row_filter_policy.service, row_filter_policy.name)
 
+print('    deleted policy: id: ' + str(row_filter_policy.id) + ', name: ' + row_filter_policy.name)
 
-    # get all roles in ranger
-    all_roles = ranger_client.find_roles({})
+ranger.delete_service_by_id(service_id)
 
-    log.info('List of Roles {}'.format(all_roles)) if all_roles is not None else log.info('No roles found!')
 
+print('Listing policies..')
+policies = ranger.find_policies()
 
-    # delete a role in ranger
-    ranger_client.delete_role(role_name, ranger_client.username, service_name)
+print('    ' + str(len(policies)) + ' policies found')
+for policy in policies:
+    print('        id: ' + str(policy.id) + ', service: ' + policy.service + ', name: ' + policy.name)
 
-    log.info('Role {} successfully deleted'.format(role_name))
 
+print('Listing security zones..')
+security_zones = ranger.find_security_zones()
 
-    # delete a service
-    ranger_client.delete_service(service_name)
+print('    ' + str(len(security_zones)) + ' security zones found')
+for security_zone in security_zones:
+    print('        id: ' + str(security_zone.id) + ', name: ' + security_zone.name)
 
-    log.info('Service {} successfully deleted'.format(service_name))
 
+print('Listing roles..')
+roles = ranger.find_roles()
 
-    # delete a service definition
-    ranger_client.delete_service_def(service_def_name)
+print('    ' + str(len(roles)) + ' roles zones found')
+for role in roles:
+    print('        id: ' + str(role.id) + ', name: ' + role.name)
 
-    log.info('Service Definition {} successfully deleted'.format(service_def_name))