mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Add execution module for BambooHR
This commit is contained in:
parent
f1f90a2ec6
commit
fa7e46e30d
1 changed files with 290 additions and 0 deletions
290
salt/modules/bamboohr.py
Normal file
290
salt/modules/bamboohr.py
Normal file
|
@ -0,0 +1,290 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
Support for BambooHR
|
||||
|
||||
Requires a ``subdomain`` and an ``apikey`` in ``/etc/salt/minion``:
|
||||
|
||||
.. code-block: yaml
|
||||
|
||||
bamboohr:
|
||||
apikey: 012345678901234567890
|
||||
subdomain: mycompany
|
||||
'''
|
||||
|
||||
# Import python libs
|
||||
from __future__ import absolute_import, print_function
|
||||
import yaml
|
||||
import logging
|
||||
|
||||
# Import salt libs
|
||||
import salt.utils.http
|
||||
import salt.ext.six as six
|
||||
from salt._compat import ElementTree as ET
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def __virtual__():
|
||||
'''
|
||||
Only load the module if apache is installed
|
||||
'''
|
||||
if _apikey():
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def _apikey():
|
||||
'''
|
||||
Get the API key
|
||||
'''
|
||||
return __opts__.get('bamboohr', {}).get('apikey', None)
|
||||
|
||||
|
||||
def list_employees(order_by='id'):
|
||||
'''
|
||||
Show all employees for this company.
|
||||
|
||||
CLI Example:
|
||||
|
||||
salt myminion bamboohr.list_employees
|
||||
|
||||
By default, the return data will be keyed by ID. However, it can be ordered
|
||||
by any other field. Keep in mind that if the field that is chosen contains
|
||||
duplicate values (i.e., location is used, for a company which only has one
|
||||
location), then each duplicate value will be overwritten by the previous.
|
||||
Therefore, it is advisable to only sort by fields that are guaranteed to be
|
||||
unique.
|
||||
|
||||
CLI Examples:
|
||||
|
||||
salt myminion bamboohr.list_employees order_by=id
|
||||
salt myminion bamboohr.list_employees order_by=displayName
|
||||
salt myminion bamboohr.list_employees order_by=workEmail
|
||||
'''
|
||||
ret = {}
|
||||
status, result = _query(action='employees', command='directory')
|
||||
root = ET.fromstring(result)
|
||||
directory = root.getchildren()
|
||||
for cat in directory:
|
||||
if cat.tag != 'employees':
|
||||
continue
|
||||
for item in cat:
|
||||
emp_id = item.items()[0][1]
|
||||
emp_ret = {'id': emp_id}
|
||||
for details in item.getchildren():
|
||||
emp_ret[details.items()[0][1]] = details.text
|
||||
ret[emp_ret[order_by]] = emp_ret
|
||||
return ret
|
||||
|
||||
|
||||
def show_employee(emp_id, fields=None):
|
||||
'''
|
||||
Show all employees for this company.
|
||||
|
||||
CLI Example:
|
||||
|
||||
salt myminion bamboohr.show_employee 1138
|
||||
|
||||
By default, the fields normally returned from bamboohr.list_employees are
|
||||
returned. These fields are:
|
||||
|
||||
- canUploadPhoto
|
||||
- department
|
||||
- displayName
|
||||
- firstName
|
||||
- id
|
||||
- jobTitle
|
||||
- lastName
|
||||
- location
|
||||
- mobilePhone
|
||||
- nickname
|
||||
- photoUploaded
|
||||
- photoUrl
|
||||
- workEmail
|
||||
- workPhone
|
||||
- workPhoneExtension
|
||||
|
||||
If needed, a different set of fields may be specified, separated by commas:
|
||||
|
||||
CLI Example:
|
||||
|
||||
salt myminion bamboohr.show_employee 1138 displayName,dateOfBirth
|
||||
|
||||
A list of available fields can be found at
|
||||
http://www.bamboohr.com/api/documentation/employees.php
|
||||
'''
|
||||
ret = {}
|
||||
if fields is None:
|
||||
fields = ','.join((
|
||||
'canUploadPhoto',
|
||||
'department',
|
||||
'displayName',
|
||||
'firstName',
|
||||
'id',
|
||||
'jobTitle',
|
||||
'lastName',
|
||||
'location',
|
||||
'mobilePhone',
|
||||
'nickname',
|
||||
'photoUploaded',
|
||||
'photoUrl',
|
||||
'workEmail',
|
||||
'workPhone',
|
||||
'workPhoneExtension',
|
||||
))
|
||||
|
||||
status, result = _query(
|
||||
action='employees',
|
||||
command=emp_id,
|
||||
args={'fields': fields}
|
||||
)
|
||||
|
||||
root = ET.fromstring(result)
|
||||
items = root.getchildren()
|
||||
|
||||
ret = {'id': emp_id}
|
||||
for item in items:
|
||||
ret[item.items()[0][1]] = item.text
|
||||
return ret
|
||||
|
||||
|
||||
def update_employee(emp_id, key=None, value=None, items=None):
|
||||
'''
|
||||
Update one or more items for this employee. Specifying an empty value will
|
||||
clear it for that employee.
|
||||
|
||||
CLI Examples:
|
||||
|
||||
salt myminion bamboohr.update_employee 1138 nickname Curly
|
||||
salt myminion bamboohr.update_employee 1138 nickname ''
|
||||
salt myminion bamboohr.update_employee 1138 items='{"nickname": "Curly"}
|
||||
salt myminion bamboohr.update_employee 1138 items='{"nickname": ""}
|
||||
'''
|
||||
if items is None:
|
||||
if key is None or value is None:
|
||||
return {'Error': 'At least one key/value pair is required'}
|
||||
items = {key: value}
|
||||
elif isinstance(items, six.string_types):
|
||||
items = yaml.safe_load(items)
|
||||
|
||||
xml_items = ''
|
||||
for pair in items.keys():
|
||||
xml_items += '<field id="{0}">{1}</field>'.format(pair, items[pair])
|
||||
xml_items = '<employee>{0}</employee>'.format(xml_items)
|
||||
|
||||
status, result = _query(
|
||||
action='employees',
|
||||
command=emp_id,
|
||||
data=xml_items,
|
||||
method='POST',
|
||||
)
|
||||
|
||||
return show_employee(emp_id, ','.join(items.keys()))
|
||||
|
||||
|
||||
def list_users(order_by='id'):
|
||||
'''
|
||||
Show all users for this company.
|
||||
|
||||
CLI Example:
|
||||
|
||||
salt myminion bamboohr.list_users
|
||||
|
||||
By default, the return data will be keyed by ID. However, it can be ordered
|
||||
by any other field. Keep in mind that if the field that is chosen contains
|
||||
duplicate values (i.e., location is used, for a company which only has one
|
||||
location), then each duplicate value will be overwritten by the previous.
|
||||
Therefore, it is advisable to only sort by fields that are guaranteed to be
|
||||
unique.
|
||||
|
||||
CLI Examples:
|
||||
|
||||
salt myminion bamboohr.list_users order_by=id
|
||||
salt myminion bamboohr.list_users order_by=email
|
||||
'''
|
||||
ret = {}
|
||||
status, result = _query(action='meta', command='users')
|
||||
root = ET.fromstring(result)
|
||||
users = root.getchildren()
|
||||
for user in users:
|
||||
user_id = None
|
||||
user_ret = {}
|
||||
for item in user.items():
|
||||
user_ret[item[0]] = item[1]
|
||||
if item[0] == 'id':
|
||||
user_id = item[1]
|
||||
for item in user.getchildren():
|
||||
user_ret[item.tag] = item.text
|
||||
ret[user_ret[order_by]] = user_ret
|
||||
return ret
|
||||
|
||||
|
||||
def list_meta_fields():
|
||||
'''
|
||||
Show all meta data fields for this company.
|
||||
|
||||
CLI Example:
|
||||
|
||||
salt myminion bamboohr.list_meta_fields
|
||||
'''
|
||||
ret = {}
|
||||
status, result = _query(action='meta', command='fields')
|
||||
root = ET.fromstring(result)
|
||||
fields = root.getchildren()
|
||||
for field in fields:
|
||||
field_id = None
|
||||
field_ret = {'name': field.text}
|
||||
for item in field.items():
|
||||
field_ret[item[0]] = item[1]
|
||||
if item[0] == 'id':
|
||||
field_id = item[1]
|
||||
ret[field_id] = field_ret
|
||||
return ret
|
||||
|
||||
|
||||
def _query(action=None,
|
||||
command=None,
|
||||
args=None,
|
||||
method='GET',
|
||||
data=None):
|
||||
'''
|
||||
Make a web call to BambooHR
|
||||
|
||||
The password can be any random text, so we chose Salty text.
|
||||
'''
|
||||
subdomain = __opts__.get('bamboohr', {}).get('subdomain', None)
|
||||
path = 'https://api.bamboohr.com/api/gateway.php/{0}/v1/'.format(
|
||||
subdomain
|
||||
)
|
||||
|
||||
if action:
|
||||
path += action
|
||||
|
||||
if command:
|
||||
path += '/{0}'.format(command)
|
||||
|
||||
log.debug('BambooHR URL: {0}'.format(path))
|
||||
|
||||
if not isinstance(args, dict):
|
||||
args = {}
|
||||
|
||||
return_content = None
|
||||
result = salt.utils.http.query(
|
||||
path,
|
||||
method,
|
||||
username=_apikey(),
|
||||
password='saltypork',
|
||||
params=args,
|
||||
data=data,
|
||||
decode=False,
|
||||
text=True,
|
||||
status=True,
|
||||
opts=__opts__,
|
||||
)
|
||||
log.debug(
|
||||
'BambooHR Response Status Code: {0}'.format(
|
||||
result['status']
|
||||
)
|
||||
)
|
||||
|
||||
return [result['status'], result['text']]
|
Loading…
Add table
Reference in a new issue