blob: bf8d68429bb956a7519bec475f7c1bbb1eac2870 [file] [log] [blame]
David K. Bainbridge6e23ac82016-12-07 12:55:41 -08001#!/usr/bin/python
2
3DOCUMENTATION = '''
4---
5module: maas_zone
6short_description: Manage MAAS Clusters Interfaces
7options:
8 maas:
9 description:
10 - URL of MAAS server
11 default: http://localhost/MAAS/api/1.0/
12 key:
13 description:
14 - MAAS API key
15 required: yes
16 name:
17 description:
18 - name of the zone
19 required: yes
20 description:
21 description:
22 - description text of zone
23 required: no
24 state:
25 description:
26 - possible states for this zone
27 choices: ['present', 'absent', 'query']
28 default: present
29
30requirements: [ipaddress, requests_oauthlib, maasclient]
31author: David Bainbridge
32'''
33
34EXAMPLES = '''
35examples:
36 maas_zone:
37 maas: http://my.maas.server.com/MAAS/api/1.0/
38 key: 'xBvr9dx5k7S52myufC:fqBXV7hJgXegNZDw9c:K8hsmL47XjAppfQy2pDVW7G49p6PELgp'
39 name: MyZone
40 description: This is my zone
41 state: present
42
43 maas_zone:
44 maas: http://my.maas.server.com/MAAS/api/1.0/
45 key: 'xBvr9dx5k7S52myufC:fqBXV7hJgXegNZDw9c:K8hsmL47XjAppfQy2pDVW7G49p6PELgp'
46 name: MyDeadZone
47 description: This was my zone
48 state: absent
49'''
50
51import sys
52import json
53import ipaddress
54import requests
55from maasclient.auth import MaasAuth
56from maasclient import MaasClient
57
58# For some reason the maasclient doesn't provide a put method. So
59# we will add it here
60def put(client, url, params=None):
61 return requests.put(url=client.auth.api_url + url,
62 auth=client._oauth(), data=params)
63
64# Attempt to interpret the given value as a JSON object, if that fails
65# just return it as a string
66def string_or_object(val):
67 try:
68 return json.loads(val)
69 except:
70 return val
71
72# Return a copy of the given dictionary with any `null` valued entries
73# removed
74def remove_null(d_in):
75 d = d_in.copy()
76 to_remove = []
77 for k in d.keys():
78 if d[k] == None:
79 to_remove.append(k)
80 for k in to_remove:
81 del d[k]
82 return d
83
84# Deterine if two dictionaries are different
85def different(have, want):
86 have_keys = have.keys()
87 for key in want.keys():
88 if (key in have_keys and want[key] != have[key]) or key not in have_keys:
89 return True
90 return False
91
92# Get an zone from MAAS using its name, if not found return None
93def get_zone(maas, name):
94 res = maas.get('/zones/%s/' % name)
95 if res.ok:
96 return json.loads(res.text)
97 return None
98
99# Create an zone based on the value given
100def create_zone(maas, zone):
101 merged = zone.copy()
102 # merged['op'] = 'new'
103 res = maas.post('/zones/', merged)
104 if res.ok:
105 return { 'error': False, 'status': get_zone(maas, merged['name']) }
106 return { 'error': True, 'status': string_or_object(res.text) }
107
108# Delete an zone based on the name
109def delete_zone(maas, name):
110 res = maas.delete('/zones/%s/' % name)
111 if res.ok:
112 return { 'error': False }
113 return { 'error': True, 'status': string_or_object(res.text) }
114
115def update_zone(maas, have, want):
116 merged = have.copy()
117 merged.update(want)
118 res = put(maas, '/zones/%s/' % merged['name'], merged)
119 if res.ok:
120 return { 'error': False, 'status': get_zone(maas, merged['name']) }
121 return { 'error': True, 'status': string_or_object(res.text) }
122
123def main():
124 module = AnsibleModule(
125 argument_spec = dict(
126 maas=dict(default='http://localhost/MAAS/api/1.0/'),
127 key=dict(required=True),
128 name=dict(required=True),
129 description=dict(required=False),
130 state=dict(default='present', choices=['present', 'absent', 'query'])
131 ),
132 supports_check_mode = False
133 )
134
135 maas = module.params['maas']
136 key = module.params['key']
137 state = module.params['state']
138
139 # Construct a sparsely populate desired state
140 desired = remove_null({
141 'name': module.params['name'],
142 'description': module.params['description'],
143 })
144
145 # Authenticate into MAAS
146 auth = MaasAuth(maas, key)
147 maas = MaasClient(auth)
148
149 # Attempt to get the zone from MAAS
150 zone = get_zone(maas, desired['name'])
151
152 # Actions if the zone does not currently exist
153 if not zone:
154 if state == 'query':
155 # If this is a query, returne it is not found
156 module.exit_json(changed=False, found=False)
157 elif state == 'present':
158 # If this should be present, then attempt to create it
159 res = create_zone(maas, desired)
160 if res['error']:
161 module.fail_json(msg=res['status'])
162 else:
163 module.exit_json(changed=True, zone=res['status'])
164 else:
165 # If this should be absent, then we are done and in the desired state
166 module.exit_json(changed=False)
167
168 # Done with zones does not exists actions
169 return
170
171 # Actions if the zone does exist
172 if state == 'query':
173 # If this is a query, return the zone
174 module.exit_json(changed=False, found=True, zone=zone)
175 return
176 elif state == 'present':
177 # If we want this to exists check to see if this is different and
178 # needs updated
179 if different(zone, desired):
180 res = update_zone(maas, zone, desired)
181 if res['error']:
182 module.fail_json(msg=res['status'])
183 else:
184 module.exit_json(changed=True, zone=res['status'])
185 else:
186 # No differences, to nothing to change
187 module.exit_json(changed=False, zone=zone)
188 else:
189 # If we don't want this zone, then delete it
190 res = delete_zone(maas, zone['name'])
191 if res['error']:
192 module.fail_json(msg=res['status'])
193 else:
194 module.exit_json(changed=True, zone=zone)
195
196# this is magic, see lib/ansible/module_common.py
197#<<INCLUDE_ANSIBLE_MODULE_COMMON>>
198if __name__ == '__main__':
199 main()