-
Notifications
You must be signed in to change notification settings - Fork 23
/
Copy pathkoji_host.py
257 lines (230 loc) · 8.76 KB
/
koji_host.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
#!/usr/bin/python
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils import common_koji
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'status': ['preview'],
'supported_by': 'community'
}
DOCUMENTATION = '''
---
module: koji_host
short_description: Create and manage Koji build hosts
description:
- This module can add new hosts and manage existing hosts.
- 'Koji only supports adding new hosts, not deleting them. Once they are
defined, you can enable or disable the hosts with "state: enabled" or
"state: disabled".'
options:
name:
description:
- The name of the Koji builder.
- 'Example: "builder1.example.com".'
required: true
arches:
description:
- The list of arches this host supports.
- 'Example: [x86_64]'
required: true
channels:
description:
- The list of channels this host should belong to.
- If you specify a completely new channel here, Ansible will create the
channel on the hub. For example, when you set up OSBS with Koji, you
must add a builder host to a new "container" channel. You can simply
specify "container" in the list here, and Ansible will create the new
"container" channel when it adds your host to that channel.
- 'Example: [default, createrepo]'
required: false
state:
description:
- Whether to set this host as "enabled" or "disabled". If unset, this
defaults to "enabled".
krb_principal:
description:
- Set a single non-default krb principal for this host. If unset, Koji
will use the standard krb principal scheme for builder accounts.
- Mutually exclusive with I(krb_principals).
krb_principals:
description:
- Set a list of non-default krb principals for this host. If unset,
Koji will use the standard krb principal scheme for builder accounts.
Your Koji Hub must be v1.19 or later to use this option.
- Mutually exclusive with I(krb_principal).
capacity:
description:
- Total task weight for this host. This is a float value. If unset,
Koji will use the standard capacity for a host (2.0).
- 'Example: 10.0'
description:
description:
- Human-readable description for this host.
comment:
description:
- Human-readable comment explaining the current state of the host. You
may write a description here explaining how this host was set up, or
why this host is currently offline.
requirements:
- "python >= 2.7"
- "koji"
'''
EXAMPLES = '''
- name: create a koji host
hosts: localhost
tasks:
- name: Add new builder1 host
koji_host:
name: builder1.example.com
arches: [x86_64]
state: enabled
channels:
- createrepo
- default
- name: Add new builder host for OSBS
koji_host:
name: containerbuild1.example.com
arches: [x86_64]
state: enabled
channels:
# This will automatically create the "container" channel
# if it does not already exist:
- container
'''
def ensure_channels(session, host_id, host_name, check_mode, desired_channels):
"""
Ensure that given host belongs to given channels (and only them).
:param session: Koji client session
:param int host_id: Koji host ID
:param str host_name: Koji host name
:param bool check_mode: don't make any changes
:param list desired_channels: channels that the host should belong to
"""
result = {'changed': False, 'stdout_lines': []}
common_koji.ensure_logged_in(session)
current_channels = session.listChannels(host_id)
current_channels = [channel['name'] for channel in current_channels]
for channel in current_channels:
if channel not in desired_channels:
if not check_mode:
session.removeHostFromChannel(host_name, channel)
result['stdout_lines'].append('removed host from channel %s' % channel)
result['changed'] = True
for channel in desired_channels:
if channel not in current_channels:
if not check_mode:
session.addHostToChannel(host_name, channel, create=True)
result['stdout_lines'].append('added host to channel %s' % channel)
result['changed'] = True
return result
def ensure_host(session, name, check_mode, state, arches, krb_principals,
channels, **kwargs):
"""
Ensure that this host is configured in Koji.
:param session: Koji client session
:param str name: Koji builder host name
:param bool check_mode: don't make any changes
:param str state: "enabled" or "disabled"
:param list arches: list of arches for this builder.
:param list krb_principals: custom kerberos principals, or None
:param list chanels: list of channels this host should belong to.
:param **kwargs: Pass remaining kwargs directly into Koji's editHost RPC.
"""
result = {'changed': False, 'stdout_lines': []}
host = session.getHost(name)
if not host:
result['changed'] = True
result['stdout_lines'].append('created host')
if check_mode:
return result
common_koji.ensure_logged_in(session)
krb_principal = krb_principals[0] if krb_principals else None
id_ = session.addHost(name, arches, krb_principal)
host = session.getHost(id_)
if state == 'enabled':
if not host['enabled']:
result['changed'] = True
result['stdout_lines'].append('enabled host')
if not check_mode:
common_koji.ensure_logged_in(session)
session.enableHost(name)
elif state == 'disabled':
if host['enabled']:
result['changed'] = True
result['stdout_lines'].append('disabled host')
if not check_mode:
common_koji.ensure_logged_in(session)
session.disableHost(name)
edits = {}
if ' '.join(arches) != host['arches']:
edits['arches'] = ' '.join(arches)
for key, value in kwargs.items():
if value is None:
continue # Ansible did not set this parameter.
if key in host and kwargs[key] != host[key]:
edits[key] = value
if edits:
result['changed'] = True
for edit in edits.keys():
result['stdout_lines'].append('edited host %s' % edit)
if not check_mode:
common_koji.ensure_logged_in(session)
session.editHost(name, **edits)
# Ensure host is member of desired channels.
if channels not in (None, ''):
channels_result = ensure_channels(session, host['id'],
name, check_mode, channels)
if channels_result['changed']:
result['changed'] = True
result['stdout_lines'].extend(channels_result['stdout_lines'])
if krb_principals is not None:
user = session.getUser(host['user_id'])
changes = common_koji.ensure_krb_principals(
session, user, check_mode, krb_principals)
if changes:
result['changed'] = True
result['stdout_lines'].extend(changes)
return result
def run_module():
module_args = dict(
koji=dict(),
name=dict(required=True),
arches=dict(type='list', required=True),
channels=dict(type='list'),
krb_principal=dict(),
krb_principals=dict(type='list', elements='str'),
capacity=dict(type='float'),
description=dict(),
comment=dict(),
state=dict(choices=['enabled', 'disabled'], default='enabled'),
)
module = AnsibleModule(
argument_spec=module_args,
mutually_exclusive=[('krb_principal', 'krb_principals')],
supports_check_mode=True
)
if not common_koji.HAS_KOJI:
module.fail_json(msg='koji is required for this module')
check_mode = module.check_mode
params = module.params
profile = params['koji']
name = params['name']
state = params['state']
if params['krb_principals'] is not None:
krb_principals = params['krb_principals']
elif params['krb_principal'] is not None:
krb_principals = [params['krb_principal']]
else:
krb_principals = None
session = common_koji.get_session(profile)
result = ensure_host(session, name, check_mode, state,
arches=params['arches'],
channels=params['channels'],
krb_principals=krb_principals,
capacity=params['capacity'],
description=params['description'],
comment=params['comment'])
module.exit_json(**result)
def main():
run_module()
if __name__ == '__main__':
main()