Server IP : 85.214.239.14 / Your IP : 3.16.135.146 Web Server : Apache/2.4.62 (Debian) System : Linux h2886529.stratoserver.net 4.9.0 #1 SMP Tue Jan 9 19:45:01 MSK 2024 x86_64 User : www-data ( 33) PHP Version : 7.4.18 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare, MySQL : OFF | cURL : OFF | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : OFF Directory : /usr/lib/python3/dist-packages/ansible_collections/cisco/meraki/plugins/modules/ |
Upload File : |
#!/usr/bin/python # -*- coding: utf-8 -*- # Copyright: (c) 2020, Kevin Breit (@kbreit) <kevin.breit@kevinbreit.net> # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function __metaclass__ = type ANSIBLE_METADATA = { 'metadata_version': '1.1', 'status': ['preview'], 'supported_by': 'community' } DOCUMENTATION = r''' --- module: meraki_ms_stack short_description: Modify switch stacking configuration in Meraki. version_added: "1.3.0" description: - Allows for modification of Meraki MS switch stacks. notes: - Not all actions are idempotent. Specifically, creating a new stack will error if any switch is already in a stack. options: state: description: - Create or modify an organization. choices: ['present', 'query', 'absent'] default: present type: str net_name: description: - Name of network which MX firewall is in. type: str net_id: description: - ID of network which MX firewall is in. type: str stack_id: description: - ID of stack which is to be modified or deleted. type: str serials: description: - List of switch serial numbers which should be included or removed from a stack. type: list elements: str name: description: - Name of stack. type: str author: - Kevin Breit (@kbreit) extends_documentation_fragment: cisco.meraki.meraki ''' EXAMPLES = r''' - name: Create new stack meraki_switch_stack: auth_key: abc123 state: present org_name: YourOrg net_name: YourNet name: Test stack serials: - "ABCD-1231-4579" - "ASDF-4321-0987" - name: Add switch to stack meraki_switch_stack: auth_key: abc123 state: present org_name: YourOrg net_name: YourNet stack_id: ABC12340987 serials: - "ABCD-1231-4579" - name: Remove switch from stack meraki_switch_stack: auth_key: abc123 state: absent org_name: YourOrg net_name: YourNet stack_id: ABC12340987 serials: - "ABCD-1231-4579" - name: Query one stack meraki_switch_stack: auth_key: abc123 state: query org_name: YourOrg net_name: YourNet stack_id: ABC12340987 ''' RETURN = r''' data: description: VPN settings. returned: success type: complex contains: id: description: ID of switch stack. returned: always type: str sample: 7636 name: description: Descriptive name of switch stack. returned: always type: str sample: MyStack serials: description: List of serial numbers in switch stack. returned: always type: list sample: - "QBZY-XWVU-TSRQ" - "QBAB-CDEF-GHIJ" ''' from ansible.module_utils.basic import AnsibleModule, json from ansible_collections.cisco.meraki.plugins.module_utils.network.meraki.meraki import MerakiModule, meraki_argument_spec from copy import deepcopy def get_stacks(meraki, net_id): path = meraki.construct_path('get_all', net_id=net_id) return meraki.request(path, method='GET') def get_stack(stack_id, stacks): for stack in stacks: if stack_id == stack['id']: return stack return None def get_stack_id(meraki, net_id): stacks = get_stacks(meraki, net_id) for stack in stacks: if stack['name'] == meraki.params['name']: return stack['id'] def does_stack_exist(meraki, stacks): for stack in stacks: have = set(meraki.params['serials']) want = set(stack['serials']) if have == want: return stack return False def main(): # define the available arguments/parameters that a user can pass to # the module argument_spec = meraki_argument_spec() argument_spec.update(state=dict(type='str', choices=['present', 'query', 'absent'], default='present'), net_name=dict(type='str'), net_id=dict(type='str'), stack_id=dict(type='str'), serials=dict(type='list', elements='str', default=None), name=dict(type='str'), ) # 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=argument_spec, supports_check_mode=True, ) meraki = MerakiModule(module, function='switch_stack') meraki.params['follow_redirects'] = 'all' query_urls = {'switch_stack': '/networks/{net_id}/switch/stacks'} query_url = {'switch_stack': '/networks/{net_id}/switch/stacks/{stack_id}'} add_urls = {'switch_stack': '/networks/{net_id}/switch/stacks/{stack_id}/add'} remove_urls = {'switch_stack': '/networks/{net_id}/switch/stacks/{stack_id}/remove'} create_urls = {'switch_stack': '/networks/{net_id}/switch/stacks'} delete_urls = {'switch_stack': '/networks/{net_id}/switch/stacks/{stack_id}'} meraki.url_catalog['get_all'].update(query_urls) meraki.url_catalog['get_one'].update(query_url) meraki.url_catalog['add'] = add_urls meraki.url_catalog['remove'] = remove_urls meraki.url_catalog['create'] = create_urls meraki.url_catalog['delete'] = delete_urls payload = None # manipulate or modify the state as needed (this is going to be the # part where your module will do what it needs to do) org_id = meraki.params['org_id'] if org_id is None: orgs = meraki.get_orgs() for org in orgs: if org['name'] == meraki.params['org_name']: org_id = org['id'] net_id = meraki.params['net_id'] if net_id is None: net_id = meraki.get_net_id(net_name=meraki.params['net_name'], data=meraki.get_nets(org_id=org_id)) # assign and lookup stack_id stack_id = meraki.params['stack_id'] if stack_id is None and meraki.params['name'] is not None: stack_id = get_stack_id(meraki, net_id) path = meraki.construct_path('get_all', net_id=net_id) stacks = meraki.request(path, method='GET') if meraki.params['state'] == 'query': if stack_id is None: meraki.result['data'] = stacks else: meraki.result['data'] = get_stack(stack_id, stacks) elif meraki.params['state'] == 'present': if meraki.params['stack_id'] is None: payload = {'serials': meraki.params['serials'], 'name': meraki.params['name'], } path = meraki.construct_path('create', net_id=net_id) response = meraki.request(path, method='POST', payload=json.dumps(payload)) if meraki.status == 201: meraki.result['data'] = response meraki.result['changed'] = True else: payload = {'serial': meraki.params['serials'][0]} original = get_stack(stack_id, stacks) comparable = deepcopy(original) comparable.update(payload) if meraki.params['serials'][0] not in comparable['serials']: comparable['serials'].append(meraki.params['serials'][0]) # meraki.fail_json(msg=comparable) if meraki.is_update_required(original, comparable, optional_ignore=['serial']): path = meraki.construct_path('add', net_id=net_id, custom={'stack_id': stack_id}) response = meraki.request(path, method='POST', payload=json.dumps(payload)) if meraki.status == 200: meraki.result['data'] = response meraki.result['changed'] = True else: meraki.result['data'] = original elif meraki.params['state'] == 'absent': if meraki.params['serials'] is None: path = meraki.construct_path('delete', net_id=net_id, custom={'stack_id': stack_id}) response = meraki.request(path, method='DELETE') meraki.result['data'] = {} meraki.result['changed'] = True else: for serial in meraki.params['serials']: payload = {'serial': serial} original = get_stack(stack_id, stacks) comparable = deepcopy(original) comparable.update(payload) if serial in comparable['serials']: comparable['serials'].remove(serial) if meraki.is_update_required(original, comparable, optional_ignore=['serial']): path = meraki.construct_path('remove', net_id=net_id, custom={'stack_id': stack_id}) response = meraki.request(path, method='POST', payload=json.dumps(payload)) if meraki.status == 200: meraki.result['data'] = response meraki.result['changed'] = True else: meraki.result['data'] = original # in the event of a successful module execution, you will want to # simple AnsibleModule.exit_json(), passing the key/value results meraki.exit_json(**meraki.result) if __name__ == '__main__': main()