blob: 66629c3bc67d7e5949ff4fbe79f871a12d7fce2b [file] [log] [blame]
David K. Bainbridge6e23ac82016-12-07 12:55:41 -08001#!/usr/bin/python
2
Jonathan Hart93956f52017-08-22 13:12:42 -07003# Copyright 2017-present Open Networking Foundation
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
David K. Bainbridge6e23ac82016-12-07 12:55:41 -080017DOCUMENTATION = '''
18---
19module: maas_user
20short_description: Manage MAAS Clusters Interfaces
21options:
22 maas:
23 description:
24 - URL of MAAS server
25 default: http://localhost/MAAS/api/1.0/
26 key:
27 description:
28 - MAAS API key
29 required: yes
30 name:
31 description:
32 - name of the user
33 required: yes
34 email:
35 description:
36 - email address of the user
37 required: no
38 password:
39 description:
40 - password for the user
41 required: no
42 is_superuser:
43 description:
44 - does the user have priviledges
45 default: no
46 state:
47 description:
48 - possible states for this user
49 choices: ['present', 'absent', 'query']
50 default: present
51
52requirements: [ipaddress, requests_oauthlib, maasclient]
53author: David Bainbridge
54'''
55
56EXAMPLES = '''
57examples:
58 maas_user:
59 maas: http://my.maas.server.com/MAAS/api/1.0/
60 key: 'xBvr9dx5k7S52myufC:fqBXV7hJgXegNZDw9c:K8hsmL47XjAppfQy2pDVW7G49p6PELgp'
61 name: MyUser
62 email: user@company.com
63 password: donttell
64 is_superuser: no
65 state: present
66
67 maas_user:
68 maas: http://my.maas.server.com/MAAS/api/1.0/
69 key: 'xBvr9dx5k7S52myufC:fqBXV7hJgXegNZDw9c:K8hsmL47XjAppfQy2pDVW7G49p6PELgp'
70 name: MyDeadUser
71 state: absent
72'''
73
74import sys
75import json
76import ipaddress
77import requests
78from maasclient.auth import MaasAuth
79from maasclient import MaasClient
80
81# For some reason the maasclient doesn't provide a put method. So
82# we will add it here
83def put(client, url, params=None):
84 return requests.put(url=client.auth.api_url + url,
85 auth=client._oauth(), data=params)
86
87# Attempt to interpret the given value as a JSON object, if that fails
88# just return it as a string
89def string_or_object(val):
90 try:
91 return json.loads(val)
92 except:
93 return val
94
95# Return a copy of the given dictionary with any `null` valued entries
96# removed
97def remove_null(d_in):
98 d = d_in.copy()
99 to_remove = []
100 for k in d.keys():
101 if d[k] == None:
102 to_remove.append(k)
103 for k in to_remove:
104 del d[k]
105 return d
106
107# Deterine if two dictionaries are different
108def different(have, want):
109 have_keys = have.keys()
110 for key in want.keys():
111 if (key in have_keys and want[key] != have[key]) or key not in have_keys:
112 return True
113 return False
114
115# Get an user from MAAS using its name, if not found return None
116def get_user(maas, name):
117 res = maas.get('/users/%s/' % name)
118 if res.ok:
119 return json.loads(res.text)
120 return None
121
122# Create an user based on the value given
123def create_user(maas, user):
124 merged = user.copy()
125 # merged['op'] = 'new'
126 res = maas.post('/users/', merged)
127 if res.ok:
128 return { 'error': False, 'status': get_user(maas, merged['username']) }
129 return { 'error': True, 'status': string_or_object(res.text) }
130
131# Delete an user based on the name
132def delete_user(maas, name):
133 res = maas.delete('/users/%s/' % name)
134 if res.ok:
135 return { 'error': False }
136 return { 'error': True, 'status': string_or_object(res.text) }
137
138def main():
139 module = AnsibleModule(
140 argument_spec = dict(
141 maas=dict(default='http://localhost/MAAS/api/1.0/'),
142 key=dict(required=True),
143 name=dict(required=True),
144 email=dict(required=False),
145 password=dict(required=False),
146 is_superuser=dict(default=False, type='bool'),
147 state=dict(default='present', choices=['present', 'absent', 'query'])
148 ),
149 supports_check_mode = False
150 )
151
152 maas = module.params['maas']
153 key = module.params['key']
154 state = module.params['state']
155
156 # Construct a sparsely populate desired state
157 desired = remove_null({
158 'username': module.params['name'],
159 'email': module.params['email'],
160 'password': module.params['password'],
161 'is_superuser': 0 if not module.params['is_superuser'] else 1
162 })
163
164 # Authenticate into MAAS
165 auth = MaasAuth(maas, key)
166 maas = MaasClient(auth)
167
168 # Attempt to get the user from MAAS
169 user = get_user(maas, desired['username'])
170
171 # Actions if the user does not currently exist
172 if not user:
173 if state == 'query':
174 # If this is a query, returne it is not found
175 module.exit_json(changed=False, found=False)
176 elif state == 'present':
177 # If this should be present, then attempt to create it
178 res = create_user(maas, desired)
179 if res['error']:
180 module.fail_json(msg=res['status'])
181 else:
182 module.exit_json(changed=True, user=res['status'])
183 else:
184 # If this should be absent, then we are done and in the desired state
185 module.exit_json(changed=False)
186
187 # Done with users does not exists actions
188 return
189
190 # Actions if the user does exist
191 if state == 'query':
192 # If this is a query, return the user
193 module.exit_json(changed=False, found=True, user=user)
194 elif state == 'present':
195 # If we want this to exists check to see if this is different and
196 # needs updated
197 if different(user, desired):
198 module.fail_json(msg='Specified user, "%s", exists and MAAS does not allow the user to be modified programatically'
199 % user['username'])
200 else:
201 # No differences, to nothing to change
202 module.exit_json(changed=False, user=user)
203 else:
204 # If we don't want this user, then delete it
205 res = delete_user(maas, user['username'])
206 if res['error']:
207 module.fail_json(msg=res['status'])
208 else:
209 module.exit_json(changed=True, user=user)
210
211# this is magic, see lib/ansible/module_common.py
212#<<INCLUDE_ANSIBLE_MODULE_COMMON>>
213if __name__ == '__main__':
214 main()