1
+ #!/usr/bin/python
2
+ # -*- coding: utf-8 -*-
3
+
4
+ ANSIBLE_METADATA = {
5
+ 'metadata_version' : '0.1' ,
6
+ 'status' : ['preview' ],
7
+ 'supported_by' : 'lae'
8
+ }
9
+
10
+ DOCUMENTATION = '''
11
+ ---
12
+ module: proxmox_role
13
+ short_description: Manages the Access Control List in Proxmox
14
+ options:
15
+ name:
16
+ required: true
17
+ description:
18
+ - name of the role.
19
+ privileges:
20
+ required: true
21
+ type: list
22
+ description:
23
+ - Specifies a list of PVE privileges for the given role.
24
+ state:
25
+ required: false
26
+ default: "present"
27
+ choices: [ "present", "absent" ]
28
+ description:
29
+ - Specifies whether this role should exist or not.
30
+ author:
31
+ - Thoralf Rickert-Wendt (@trickert76)
32
+ '''
33
+
34
+ EXAMPLES = '''
35
+ - name: Create a role for monitoring with given privileges
36
+ proxmox_role:
37
+ name: "monitoring"
38
+ privileges: [ "Sys.Modify", "Sys.Audit", "Datastore.Audit", "VM.Monitor", "VM.Audit" ]
39
+ '''
40
+
41
+ RETURN = '''
42
+ '''
43
+
44
+ from ansible .module_utils .basic import AnsibleModule
45
+ from ansible .module_utils ._text import to_text
46
+ from ansible .module_utils .pvesh import ProxmoxShellError
47
+ import ansible .module_utils .pvesh as pvesh
48
+
49
+ class ProxmoxRole (object ):
50
+ def __init__ (self , module ):
51
+ self .module = module
52
+ self .name = module .params ['name' ]
53
+ self .privileges = module .params ['privileges' ]
54
+ self .state = module .params ['state' ]
55
+
56
+ try :
57
+ self .existing_roles = pvesh .get ("access/roles" )
58
+ except ProxmoxShellError as e :
59
+ self .module .fail_json (msg = e .message , status_code = e .status_code )
60
+
61
+ self .parse_roles ()
62
+
63
+ def parse_roles (self ):
64
+ self .roles = []
65
+ for existing_role in self .existing_roles :
66
+ self .roles .append (existing_role .get ('roleid' ))
67
+
68
+ def lookup (self ):
69
+ self .roles = []
70
+ for existing_role in self .existing_roles :
71
+ if existing_role .get ('roleid' ) == self .name :
72
+ args = {}
73
+ args ['roleid' ] = existing_role .get ('roleid' )
74
+ args ['privs' ] = ',' .join (sorted (existing_role .get ('privs' ).split (',' )))
75
+ return args
76
+
77
+ return None
78
+
79
+ def exists (self ):
80
+ if self .name not in self .roles :
81
+ return False
82
+
83
+ return True
84
+
85
+ def prepare_role_args (self , appendKey = True ):
86
+ args = {}
87
+ if appendKey :
88
+ args ['roleid' ] = self .name
89
+ args ['privs' ] = ',' .join (sorted (self .privileges ))
90
+
91
+ return args
92
+
93
+ def remove_role (self ):
94
+ try :
95
+ pvesh .delete ("access/roles/{}" .format (self .name ))
96
+ return (True , None )
97
+ except ProxmoxShellError as e :
98
+ return (False , e .message )
99
+
100
+ def create_role (self ):
101
+ new_role = self .prepare_role_args ()
102
+
103
+ try :
104
+ pvesh .create ("access/roles" , ** new_role )
105
+ return (True , None )
106
+ except ProxmoxShellError as e :
107
+ return (False , e .message )
108
+
109
+ def modify_role (self ):
110
+ existing_role = self .lookup ()
111
+ modified_role = self .prepare_role_args (appendKey = False )
112
+ updated_fields = []
113
+ error = None
114
+
115
+ for key in modified_role :
116
+ if key not in existing_role :
117
+ updated_fields .append (key )
118
+ else :
119
+ new_value = modified_role .get (key )
120
+ old_value = existing_role .get (key )
121
+ if isinstance (old_value , list ):
122
+ old_value = ',' .join (sorted (old_value ))
123
+ if isinstance (new_value , list ):
124
+ new_value = ',' .join (sorted (new_value ))
125
+
126
+ if new_value != old_value :
127
+ updated_fields .append (key )
128
+
129
+ if self .module .check_mode :
130
+ self .module .exit_json (changed = bool (updated_fields ), expected_changes = updated_fields )
131
+
132
+ if not updated_fields :
133
+ # No changes necessary
134
+ return (updated_fields , error )
135
+
136
+ try :
137
+ pvesh .set ("access/roles/{}" .format (self .name ), ** modified_role )
138
+ except ProxmoxShellError as e :
139
+ error = e .message
140
+
141
+ return (updated_fields , error )
142
+
143
+ def main ():
144
+ # Refer to https://pve.proxmox.com/pve-docs/api-viewer/index.html
145
+ module = AnsibleModule (
146
+ argument_spec = dict (
147
+ name = dict (type = 'str' , required = True ),
148
+ privileges = dict (type = 'list' , required = True ),
149
+ state = dict (default = 'present' , choices = ['present' , 'absent' ], type = 'str' )
150
+ ),
151
+ supports_check_mode = True
152
+ )
153
+
154
+ role = ProxmoxRole (module )
155
+
156
+ changed = False
157
+ error = None
158
+ result = {}
159
+ result ['name' ] = role .name
160
+ result ['state' ] = role .state
161
+ result ['changed' ] = False
162
+
163
+ if role .state == 'absent' :
164
+ if role .exists ():
165
+ if module .check_mode :
166
+ module .exit_json (changed = True )
167
+
168
+ (changed , error ) = role .remove_role ()
169
+ elif role .state == 'present' :
170
+ if not role .exists ():
171
+ if module .check_mode :
172
+ module .exit_json (changed = True )
173
+
174
+ (changed , error ) = role .create_role ()
175
+ else :
176
+ (updated_fields , error ) = role .modify_role ()
177
+
178
+ if updated_fields :
179
+ changed = True
180
+ result ['updated_fields' ] = updated_fields
181
+
182
+ if error is not None :
183
+ module .fail_json (name = role .name , msg = error )
184
+
185
+ result ['changed' ] = changed
186
+ module .exit_json (** result )
187
+
188
+ if __name__ == '__main__' :
189
+ main ()
0 commit comments