Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rbac #6

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion appd/model/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,15 @@ class JsonObject(object):

FIELDS = {}

# Added the check to below function to avoid Key_errors, where key we are checking for is not returned by the server
# 'if json_dict.has_key(k):'
# For instance, 'user' object has description field, but when we get the list of users; the description field is not
# sent by server. Description field is present, only when getting the info of an individual user.
@classmethod
def _set_fields_from_json_dict(cls, obj, json_dict):
for k, v in list(obj.FIELDS.items()):
obj.__setattr__(k, json_dict[v or k])
if json_dict.has_key(k):
obj.__setattr__(k, json_dict[v or k])

@classmethod
def from_json(cls, json_dict):
Expand Down
59 changes: 59 additions & 0 deletions appd/model/group.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
"""
Model classes for AppDynamics REST API

moduleauthor:: Srikar Achanta <[email protected]>

"""

from . import JsonObject, JsonList


class Group(JsonObject):

FIELDS = {'id': '', 'name': '', 'description': '', 'security_provider_type': '', 'roles': None}

def __init__(self, id='0', name=None, description=None, security_provider_type=None, roles=None):
self.id, self.name, self.description, self.security_provider_type, self.roles = id, name, description, \
security_provider_type, roles


class Groups(JsonList):
"""
Represents a collection of :class:Group objects. Extends :class:UserList, so it supports the
standard array index and :keyword:`for` semantics.
"""

def __init__(self, initial_list=None):
super(Groups, self).__init__(Group, initial_list)

def __getitem__(self, i):
"""
:rtype: Group
"""
return self.data[i]

def by_name(self, name):
"""
Finds a group by name.

:returns: First group with the correct name
:rtype: Group
"""
found = [x for x in self.data if x.name == name]
try:
return found[0]
except IndexError:
raise KeyError(name)

def by_id(self, id):
"""
Finds a group by id.

:returns: First group with the correct id
:rtype: Group
"""
found = [x for x in self.data if x.id == id]
try:
return found[0]
except IndexError:
raise KeyError(id)
59 changes: 59 additions & 0 deletions appd/model/role.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
"""
Model classes for AppDynamics REST API

moduleauthor:: Srikar Achanta <[email protected]>

"""

from . import JsonObject, JsonList


class Role(JsonObject):

FIELDS = {'id': '', 'name': '', 'description': ''}
# FIELDS = {'id': '', 'name': ''}

def __init__(self, id='0', name=None, description=None):
self.id, self.name, self.description = id, name, description


class Roles(JsonList):
"""
kylefurlong marked this conversation as resolved.
Show resolved Hide resolved
Represents a collection of :class:Role objects. Extends :class:UserList, so it supports the
standard array index and :keyword:`for` semantics.
"""

def __init__(self, initial_list=None):
super(Roles, self).__init__(Role, initial_list)

def __getitem__(self, i):
"""
:rtype: Role
"""
return self.data[i]

def by_name(self, name):
"""
Finds a role by name.

:returns: First role with the correct name
:rtype: Role
"""
found = [x for x in self.data if x.name == name]
try:
return found[0]
except IndexError:
raise KeyError(name)

def by_id(self, id):
"""
Finds a role by id.

:returns: First role with the correct id
:rtype: Role
"""
found = [x for x in self.data if x.id == id]
try:
return found[0]
except IndexError:
raise KeyError(id)
61 changes: 61 additions & 0 deletions appd/model/user.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
"""
Model classes for AppDynamics REST API

moduleauthor:: Srikar Achanta <[email protected]>

"""

from . import JsonObject, JsonList


class User(JsonObject):

FIELDS = {'id': '', 'name': '', 'displayName': '', 'email': '', 'security_provider_type': '', 'roles': None,
'groups': None}

def __init__(self, id='0', name=None, displayName=None, email=None, security_provider_type=None, roles=None,
groups=None):
self.id, self.name, self.displayName, self.email, self.security_provider_type, self.roles, self.groups = \
id, name, displayName, email, security_provider_type, roles, groups


class Users(JsonList):
"""
Represents a collection of :class:User objects. Extends :class:UserList, so it supports the
standard array index and :keyword:`for` semantics.
"""

def __init__(self, initial_list=None):
super(Users, self).__init__(User, initial_list)

def __getitem__(self, i):
"""
:rtype: User
"""
return self.data[i]

def by_name(self, name):
"""
Finds a user by name.

:returns: First user with the correct name
:rtype: User
"""
found = [x for x in self.data if x.name == name]
try:
return found[0]
except IndexError:
raise KeyError(name)

def by_id(self, id):
"""
Finds a user by id.

:returns: First user with the correct id
:rtype: User
"""
found = [x for x in self.data if x.id == id]
try:
return found[0]
except IndexError:
raise KeyError(id)
82 changes: 81 additions & 1 deletion appd/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@
from appd.model.event import *
from appd.model.action_suppressions import *
from appd.model.audit_history import *

from appd.model.role import *
from appd.model.group import *
from appd.model.user import *

class AppDynamicsClient(object):
"""
Expand Down Expand Up @@ -732,6 +734,84 @@ def get_nodes(self, app_id=None, tier_id=None):
path = ('/tiers/%s/nodes' % tier_id) if tier_id else '/nodes'
return self._app_request(Nodes, path, app_id)

# RBAC requests

def _rbac_v1_request_set(self, cls, path, params=None, method='GET', query=True, use_json=True):
obj = self.request('/controller/api/rbac/v1' + path, params, method=method, query=query, use_json=use_json)
for key in obj:
kylefurlong marked this conversation as resolved.
Show resolved Hide resolved
if obj[key] is not None:
value = obj[key]
return cls.from_json(value)

def _rbac_v1_request(self, cls, path, params=None, method='GET', query=True, use_json=True):
return cls.from_json(
self.request('/controller/api/rbac/v1' + path, params, method=method, query=query, use_json=use_json))

def get_roles(self):
"""
Retrieves the list of roles in the Controller.

:return: A :class:`Roles <appd.model.Roles>` object, representing a collection of roles.
:rtype: appd.model.Roles
"""

path = '/roles'
return self._rbac_v1_request_set(Roles, path)

def get_role(self, role_id):
"""
Retrieves details about a single role.

:param role_id: ID or name of the role to retrieve.
:return: A single Role object.
:rtype: appd.model.Role
"""
return self._rbac_v1_request(Role, '/roles/%s' % role_id)

def get_groups(self):
"""
Retrieves the list of groups in the application.

:return: A :class:`Groups <appd.model.Groups>` object, representing a collection of Groups.
:rtype: appd.model.Groups
"""

path = '/groups'
return self._rbac_v1_request_set(Groups, path)

def get_group(self, group_id):
"""
Retrieves details about a single group.

:param group_id: ID or name of the group to retrieve.
:return: A single Group object.
:rtype: appd.model.Group
"""
return self._rbac_v1_request(Group, '/groups/%s' % group_id)

def get_users(self):
"""
Retrieves the list of users in the Controller.

:return: A :class:`Users <appd.model.Roles>` object, representing a collection of users.
:rtype: appd.model.Users
"""

path = '/users'
return self._rbac_v1_request_set(Users, path)

def get_user(self, user_id):
"""
Retrieves details about a single user.

:param user_id: ID or name of the user to retrieve.
:return: A single User object.
:rtype: appd.model.User
"""
return self._rbac_v1_request(User, '/users/%s' % user_id)

# rbac requests end

def get_node(self, node_id, app_id=None):
"""
Retrieves details about a single node.
Expand Down
50 changes: 32 additions & 18 deletions test/test_create_event.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,38 @@
__author__ = 'Kyle Furlong'
__copyright__ = 'Copyright (c) 2013-2017 AppDynamics Inc.'


args = parse_argv()
c = AppDynamicsClient(args.url, args.username, args.password, args.account, args.verbose)

resp = c.create_event(app_id=16,
summary='Event 1',
comment='This is an event created by the Python SDK',
severity='INFO',
eventtype='APPLICATION_CONFIG_CHANGE')
print(resp)

resp = c.create_event(app_id=16,
summary='Custom Event 1',
comment='This is an event created by the Python SDK',
severity='INFO',
eventtype='CUSTOM',
customeventtype='MYCUSTOMEVENT',
node="python-node-1",
tier="python",
bt="/admin")
print(resp)
apps = c.get_applications()

if len(apps) > 0:
tiers = c.get_tiers(apps[0].id)
if len(tiers) > 0:
bts = c.get_bt_list(apps[0].id)

if len(bts) > 0:
resp = c.create_event(app_id=apps[0].id,
summary='Custom Event 1',
comment='This is an event created by the Python SDK',
severity='INFO',
eventtype='CUSTOM',
customeventtype='MYCUSTOMEVENT',
# node=nodes[0].name,
tier=bts[0].tier_name,
bt=bts[0].name)
print(resp)
else:
print('BT, not found!')
else:
print('Tier, not found!')

resp = c.create_event(apps[0].id,
summary='Event 1',
comment='This is an event created by the Python SDK',
severity='INFO',
eventtype='APPLICATION_CONFIG_CHANGE')
print(resp)

else:
print('Application, not found!')
29 changes: 25 additions & 4 deletions test/test_create_user.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,34 @@
from appd.cmdline import parse_argv
from appd.request import AppDynamicsClient

import random
import string

__author__ = 'Kyle Furlong'
__copyright__ = 'Copyright (c) 2013-2017 AppDynamics Inc.'


args = parse_argv()
c = AppDynamicsClient(args.url, args.username, args.password, args.account, args.verbose)

resp = c.create_user('Ash', 'AsherBasher', '[email protected]',
user_password='asher', user_roles='Administrator,Universal Agent User')
print(resp)
apps = c.get_applications()


def get_random_string(length):
letters = string.ascii_lowercase
result_str = ''.join(random.choice(letters) for i in range(length))
return result_str


if len(apps) > 0:

first_name = get_random_string(5)
second_name = get_random_string(5)
email = first_name + '.' + second_name + '@email.com'

resp = c.create_user(first_name, second_name, email,
user_password='johndoe', user_roles='Administrator,Universal Agent User')
print(resp)
else:
print('Application, not found!')


Loading