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