Skip to content

Instantly share code, notes, and snippets.

@rabin-io
Created January 2, 2020 21:19
Show Gist options
  • Save rabin-io/d470f81a47f92fca1180d1d451a23863 to your computer and use it in GitHub Desktop.
Save rabin-io/d470f81a47f92fca1180d1d451a23863 to your computer and use it in GitHub Desktop.
WIP: Ansible tc Module (Utilizes tcconfig on the client machine)
#!/usr/bin/python
# Copyright: (c) 2018, Terry Jones <terry.jones@example.org>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
# from lib.ansible.modules.system.iptables import push_arguments
ANSIBLE_METADATA = {
'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'
}
DOCUMENTATION = '''
---
module: my_test
short_description: This is my test module
version_added: "2.4"
description:
- "This is my longer description explaining my test module"
options:
name:
description:
- This is the message to send to the test module
required: true
new:
description:
- Control to demo if the result of this module is changed or not
required: false
extends_documentation_fragment:
- azure
author:
- Your Name (@yourhandle)
'''
EXAMPLES = '''
# Pass in a message
- name: Test with a message
my_test:
name: hello world
# pass in a message and have changed true
- name: Test with a message and changed output
my_test:
name: hello world
new: true
# fail the module
- name: Test failure of the module
my_test:
name: fail me
'''
RETURN = '''
original_message:
description: The original name param that was passed in
type: str
returned: always
message:
description: The output message that the test module generates
type: str
returned: always
'''
from ansible.module_utils.basic import AnsibleModule
from pprint import pprint
def append_param(rule, param, flag, is_list=False):
if is_list:
for item in param:
append_param(rule, item, flag, False)
else:
if param is not None:
rule.extend([flag, param])
def construct_rule(params):
rule = []
append_param(rule, params['rate'], '--rate', False)
append_param(rule, params['loss'], '--loss', False)
append_param(rule, params['delay'], '--delay', False)
append_param(rule, params['delay_distro'], '--delay-distro', False)
append_param(rule, params['duplicate'], '--duplicate', False)
append_param(rule, params['corrupt'], '--corrupt', False)
append_param(rule, params['reordering'], '--reordering', False)
append_param(rule, params['shaping_algo'], '--shaping-algo', False)
append_param(rule, params['direction'], '--direction', False)
append_param(rule, params['src_network'], '--src-network', False)
append_param(rule, params['dst_network'], '--dst-network', False)
rule.append('--' + params['method'])
rule.append(params['device'])
return rule
def push_arguments(tcset_path, params):
cmd = [tcset_path]
cmd.extend(construct_rule(params))
return cmd
def run_tcset(tcset_path, module, params):
cmd = push_arguments(tcset_path, params)
rc = module.run_command(cmd, check_rc=True)
return [rc[0], ' '.join(cmd)]
def run_module():
# define available arguments/parameters a user can pass to the module
module_args = dict(
device=dict(type='str', required=True),
rate=dict(type='str', required=False, default=None),
delay=dict(type='str', required=False, default=None),
delay_distro=dict(type='str', required=False, default=None),
loss=dict(type='str', required=False, default=None),
duplicate=dict(type='str', required=False, default=None),
corrupt=dict(type='str', required=False, default=None),
reordering=dict(type='str', required=False, default=None),
shaping_algo=dict(type='str', chooice=['htb', 'tbf'], required=False, default='htb'),
direction=dict(type='str', chooice=['outgoing', 'incoming'], required=False, default='outgoing'),
method=dict(type='str', chooice=['change', 'overwrite', 'add'], required=False, default='overwrite'),
src_network=dict(type='str', required=False, default=None),
dst_network=dict(type='str', required=False, default=None),
tcset_path=dict(type='str', required=False, default='/usr/bin/tcset'),
)
# seed the result dict in the object
# we primarily care about changed and state
# change is if this module effectively modified the target
# state will include any data that you want your module to pass back
# for consumption, for example, in a subsequent task
result = dict(
changed=False,
original_message='',
message='',
command='',
)
# the AnsibleModule object will be our abstraction working with Ansible
# this includes instantiation, a couple of common attr would be the
# args/params passed to the execution, as well as if the module
# supports check mode
module = AnsibleModule(
argument_spec=module_args,
supports_check_mode=True
)
# args = dict(
# changed=False,
# failed=False,
# loss=module.params['loss'],
# delay=module.params['delay'],
# device=module.params['device'],
# rate=module.params['rate'],
# delay_distro=module.params['delay_distro'],
# duplicate=module.params['duplicate'],
# corrupt=module.params['corrupt'],
# reordering=module.params['reordering'],
# shaping_algo=module.params['shaping_algo'],
# direction=module.params['direction'],
# tcset_path=module.params['tcset_path'],
# )
# if the user is working with this module in only check mode we do not
# want to make any changes to the environment, just return the current
# state with no modifications
if module.check_mode:
module.exit_json(**result)
# manipulate or modify the state as needed (this is going to be the
# part where your module will do what it needs to do)
status = run_tcset(module.params['tcset_path'], module, module.params)
result['rc'] = status[0]
result['command'] = status[1]
# use whatever logic you need to determine whether or not this module
# made any modifications to your target
# if module.params['new']:
# result['changed'] = True
# during the execution of the module, if there is an exception or a
# conditional state that effectively causes a failure, run
# AnsibleModule.fail_json() to pass in the message and the result
# if module.params['name'] == 'fail me':
# module.fail_json(msg='You requested this to fail', **result)
# in the event of a successful module execution, you will want to
# simple AnsibleModule.exit_json(), passing the key/value results
module.exit_json(**result)
def main():
run_module()
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment