This commit is contained in:
Pavol Ipoth 2016-04-15 21:11:46 +02:00
commit 2be58bf100
32 changed files with 2012 additions and 141 deletions

View file

@ -79,7 +79,7 @@ except ImportError:
def main(): def main():
if not HAS_BOTO: if not HAS_BOTO3:
module.fail_json(msg='boto required for this module') module.fail_json(msg='boto required for this module')
``` ```

View file

@ -22,7 +22,9 @@ description:
- Create or delete AWS SQS queues. - Create or delete AWS SQS queues.
- Update attributes on existing queues. - Update attributes on existing queues.
version_added: "2.0" version_added: "2.0"
author: Alan Loi (@loia) author:
- Alan Loi (@loia)
- Fernando Jose Pando (@nand0p)
requirements: requirements:
- "boto >= 2.33.0" - "boto >= 2.33.0"
options: options:
@ -61,6 +63,12 @@ options:
- The receive message wait time in seconds. - The receive message wait time in seconds.
required: false required: false
default: null default: null
policy:
description:
- The json dict policy to attach to queue
required: false
default: null
version_added: "2.1"
extends_documentation_fragment: extends_documentation_fragment:
- aws - aws
- ec2 - ec2
@ -76,6 +84,7 @@ EXAMPLES = '''
maximum_message_size: 1024 maximum_message_size: 1024
delivery_delay: 30 delivery_delay: 30
receive_message_wait_time: 20 receive_message_wait_time: 20
policy: "{{ json_dict }}"
# Delete SQS queue # Delete SQS queue
- sqs_queue: - sqs_queue:
@ -102,6 +111,7 @@ def create_or_update_sqs_queue(connection, module):
maximum_message_size=module.params.get('maximum_message_size'), maximum_message_size=module.params.get('maximum_message_size'),
delivery_delay=module.params.get('delivery_delay'), delivery_delay=module.params.get('delivery_delay'),
receive_message_wait_time=module.params.get('receive_message_wait_time'), receive_message_wait_time=module.params.get('receive_message_wait_time'),
policy=module.params.get('policy'),
) )
result = dict( result = dict(
@ -136,7 +146,8 @@ def update_sqs_queue(queue,
message_retention_period=None, message_retention_period=None,
maximum_message_size=None, maximum_message_size=None,
delivery_delay=None, delivery_delay=None,
receive_message_wait_time=None): receive_message_wait_time=None,
policy=None):
changed = False changed = False
changed = set_queue_attribute(queue, 'VisibilityTimeout', default_visibility_timeout, changed = set_queue_attribute(queue, 'VisibilityTimeout', default_visibility_timeout,
@ -149,6 +160,8 @@ def update_sqs_queue(queue,
check_mode=check_mode) or changed check_mode=check_mode) or changed
changed = set_queue_attribute(queue, 'ReceiveMessageWaitTimeSeconds', receive_message_wait_time, changed = set_queue_attribute(queue, 'ReceiveMessageWaitTimeSeconds', receive_message_wait_time,
check_mode=check_mode) or changed check_mode=check_mode) or changed
changed = set_queue_attribute(queue, 'Policy', policy,
check_mode=check_mode) or changed
return changed return changed
@ -156,7 +169,17 @@ def set_queue_attribute(queue, attribute, value, check_mode=False):
if not value: if not value:
return False return False
try:
existing_value = queue.get_attributes(attributes=attribute)[attribute] existing_value = queue.get_attributes(attributes=attribute)[attribute]
except:
existing_value = ''
# convert dict attributes to JSON strings (sort keys for comparing)
if attribute is 'Policy':
value = json.dumps(value, sort_keys=True)
if existing_value:
existing_value = json.dumps(json.loads(existing_value), sort_keys=True)
if str(value) != existing_value: if str(value) != existing_value:
if not check_mode: if not check_mode:
queue.set_attribute(attribute, value) queue.set_attribute(attribute, value)
@ -200,6 +223,7 @@ def main():
maximum_message_size=dict(type='int'), maximum_message_size=dict(type='int'),
delivery_delay=dict(type='int'), delivery_delay=dict(type='int'),
receive_message_wait_time=dict(type='int'), receive_message_wait_time=dict(type='int'),
policy=dict(type='dict', required=False),
)) ))
module = AnsibleModule( module = AnsibleModule(

View file

@ -234,6 +234,7 @@ class AnsibleCloudStackFirewall(AnsibleCloudStack):
'icmptype': 'icmp_type', 'icmptype': 'icmp_type',
} }
self.firewall_rule = None self.firewall_rule = None
self.network = None
def get_firewall_rule(self): def get_firewall_rule(self):
@ -309,10 +310,11 @@ class AnsibleCloudStackFirewall(AnsibleCloudStack):
return cidr == rule['cidrlist'] return cidr == rule['cidrlist']
def get_network(self, key=None, network=None): def get_network(self, key=None):
if not network: if self.network:
network = self.module.params.get('network') return self._get_by_key(key, self.network)
network = self.module.params.get('network')
if not network: if not network:
return None return None
@ -328,6 +330,7 @@ class AnsibleCloudStackFirewall(AnsibleCloudStack):
for n in networks['network']: for n in networks['network']:
if network in [ n['displaytext'], n['name'], n['id'] ]: if network in [ n['displaytext'], n['name'], n['id'] ]:
self.network = n
return self._get_by_key(key, n) return self._get_by_key(key, n)
break break
self.module.fail_json(msg="Network '%s' not found" % network) self.module.fail_json(msg="Network '%s' not found" % network)
@ -392,8 +395,8 @@ class AnsibleCloudStackFirewall(AnsibleCloudStack):
super(AnsibleCloudStackFirewall, self).get_result(firewall_rule) super(AnsibleCloudStackFirewall, self).get_result(firewall_rule)
if firewall_rule: if firewall_rule:
self.result['type'] = self.module.params.get('type') self.result['type'] = self.module.params.get('type')
if 'networkid' in firewall_rule: if self.result['type'] == 'egress':
self.result['network'] = self.get_network(key='displaytext', network=firewall_rule['networkid']) self.result['network'] = self.get_network(key='displaytext')
return self.result return self.result

View file

@ -87,6 +87,15 @@ options:
- Mutually exclusive with C(template) option. - Mutually exclusive with C(template) option.
required: false required: false
default: null default: null
template_filter:
description:
- Name of the filter used to search for the template or iso.
- Used for params C(iso) or C(template) on C(state=present).
required: false
default: 'executable'
choices: [ 'featured', 'self', 'selfexecutable', 'sharedexecutable', 'executable', 'community' ]
aliases: [ 'iso_filter' ]
version_added: '2.1'
hypervisor: hypervisor:
description: description:
- Name the hypervisor to be used for creating the new instance. - Name the hypervisor to be used for creating the new instance.
@ -450,7 +459,7 @@ class AnsibleCloudStackInstance(AnsibleCloudStack):
if self.template: if self.template:
return self._get_by_key(key, self.template) return self._get_by_key(key, self.template)
args['templatefilter'] = 'executable' args['templatefilter'] = self.module.params.get('template_filter')
templates = self.cs.listTemplates(**args) templates = self.cs.listTemplates(**args)
if templates: if templates:
for t in templates['template']: for t in templates['template']:
@ -462,7 +471,7 @@ class AnsibleCloudStackInstance(AnsibleCloudStack):
elif iso: elif iso:
if self.iso: if self.iso:
return self._get_by_key(key, self.iso) return self._get_by_key(key, self.iso)
args['isofilter'] = 'executable' args['isofilter'] = self.module.params.get('template_filter')
isos = self.cs.listIsos(**args) isos = self.cs.listIsos(**args)
if isos: if isos:
for i in isos['iso']: for i in isos['iso']:
@ -913,6 +922,7 @@ def main():
memory = dict(default=None, type='int'), memory = dict(default=None, type='int'),
template = dict(default=None), template = dict(default=None),
iso = dict(default=None), iso = dict(default=None),
template_filter = dict(default="executable", aliases=['iso_filter'], choices=['featured', 'self', 'selfexecutable', 'sharedexecutable', 'executable', 'community']),
networks = dict(type='list', aliases=[ 'network' ], default=None), networks = dict(type='list', aliases=[ 'network' ], default=None),
ip_to_networks = dict(type='list', aliases=['ip_to_network'], default=None), ip_to_networks = dict(type='list', aliases=['ip_to_network'], default=None),
ip_address = dict(defaul=None), ip_address = dict(defaul=None),

View file

@ -89,8 +89,8 @@ options:
default: false default: false
cross_zones: cross_zones:
description: description:
- Whether the template should be syned across zones. - Whether the template should be syned or removed across zones.
- Only used if C(state) is present. - Only used if C(state) is present or absent.
required: false required: false
default: false default: false
project: project:
@ -168,7 +168,7 @@ options:
display_text: display_text:
description: description:
- Display text of the template. - Display text of the template.
required: true required: false
default: null default: null
state: state:
description: description:
@ -220,6 +220,7 @@ EXAMPLES = '''
- local_action: - local_action:
module: cs_template module: cs_template
name: systemvm-4.2 name: systemvm-4.2
cross_zones: yes
state: absent state: absent
''' '''
@ -469,6 +470,12 @@ class AnsibleCloudStackTemplate(AnsibleCloudStack):
def register_template(self): def register_template(self):
required_params = [
'format',
'url',
'hypervisor',
]
self.module.fail_on_missing_params(required_params=required_params)
template = self.get_template() template = self.get_template()
if not template: if not template:
self.result['changed'] = True self.result['changed'] = True
@ -536,9 +543,6 @@ class AnsibleCloudStackTemplate(AnsibleCloudStack):
args['mode'] = self.module.params.get('mode') args['mode'] = self.module.params.get('mode')
args['zoneid'] = self.get_zone(key='id') args['zoneid'] = self.get_zone(key='id')
if not args['url']:
self.module.fail_json(msg="Missing required arguments: url")
self.result['changed'] = True self.result['changed'] = True
if not self.module.check_mode: if not self.module.check_mode:
@ -560,6 +564,8 @@ class AnsibleCloudStackTemplate(AnsibleCloudStack):
args = {} args = {}
args['id'] = template['id'] args['id'] = template['id']
if not self.module.params.get('cross_zones'):
args['zoneid'] = self.get_zone(key='id') args['zoneid'] = self.get_zone(key='id')
if not self.module.check_mode: if not self.module.check_mode:
@ -610,16 +616,12 @@ def main():
poll_async = dict(type='bool', default=True), poll_async = dict(type='bool', default=True),
)) ))
required_together = cs_required_together()
required_together.extend([
['format', 'url', 'hypervisor'],
])
module = AnsibleModule( module = AnsibleModule(
argument_spec=argument_spec, argument_spec=argument_spec,
required_together=required_together, required_together=cs_required_together(),
mutually_exclusive = ( mutually_exclusive = (
['url', 'vm'], ['url', 'vm'],
['zone', 'cross_zones'],
), ),
supports_check_mode=True supports_check_mode=True
) )

View file

@ -180,7 +180,7 @@ def main():
state=dict(default='present', choices=['present', 'absent']), state=dict(default='present', choices=['present', 'absent']),
zone=dict(default='us-central1-a'), zone=dict(default='us-central1-a'),
service_account_email=dict(), service_account_email=dict(),
pem_file=dict(), pem_file=dict(type='path'),
project_id=dict(), project_id=dict(),
timeout=dict(type='int', default=180) timeout=dict(type='int', default=180)
) )

View file

@ -188,7 +188,7 @@ def main():
state=dict(default='present', choices=['present', 'absent']), state=dict(default='present', choices=['present', 'absent']),
zone=dict(default='us-central1-a'), zone=dict(default='us-central1-a'),
service_account_email=dict(), service_account_email=dict(),
pem_file=dict(), pem_file=dict(type='path'),
project_id=dict(), project_id=dict(),
) )
) )

View file

@ -424,6 +424,8 @@ lxc_container:
sample: True sample: True
""" """
import re
try: try:
import lxc import lxc
except ImportError: except ImportError:
@ -745,10 +747,13 @@ class LxcContainerManagement(object):
config_change = False config_change = False
for key, value in parsed_options: for key, value in parsed_options:
key = key.strip()
value = value.strip()
new_entry = '%s = %s\n' % (key, value) new_entry = '%s = %s\n' % (key, value)
keyre = re.compile(r'%s(\s+)?=' % key)
for option_line in container_config: for option_line in container_config:
# Look for key in config # Look for key in config
if option_line.startswith(key): if keyre.match(option_line):
_, _value = option_line.split('=', 1) _, _value = option_line.split('=', 1)
config_value = ' '.join(_value.split()) config_value = ' '.join(_value.split())
line_index = container_config.index(option_line) line_index = container_config.index(option_line)
@ -1684,7 +1689,6 @@ def main():
), ),
config=dict( config=dict(
type='path', type='path',
default='/etc/lxc/default.conf'
), ),
vg_name=dict( vg_name=dict(
type='str', type='str',

View file

@ -144,6 +144,48 @@ options:
default: null default: null
required: false required: false
aliases: [] aliases: []
instance_dns:
description:
- define the instance's Primary DNS server
required: false
aliases: [ dns ]
version_added: "2.1"
instance_domain:
description:
- define the instance's Domain
required: false
aliases: [ domain ]
version_added: "2.1"
instance_hostname:
description:
- define the instance's Hostname
required: false
aliases: [ hostname ]
version_added: "2.1"
instance_ip:
description:
- define the instance's IP
required: false
aliases: [ ip ]
version_added: "2.1"
instance_netmask:
description:
- define the instance's Netmask
required: false
aliases: [ netmask ]
version_added: "2.1"
instance_rootpw:
description:
- define the instance's Root password
required: false
aliases: [ rootpw ]
version_added: "2.1"
instance_key:
description:
- define the instance's Authorized key
required: false
aliases: [ key ]
version_added: "2.1"
state: state:
description: description:
- create, terminate or remove instances - create, terminate or remove instances
@ -205,6 +247,19 @@ ovirt:
password: secret password: secret
url: https://ovirt.example.com url: https://ovirt.example.com
# starting an instance with cloud init information
ovirt:
instance_name: testansible
state: started
user: admin@internal
password: secret
url: https://ovirt.example.com
hostname: testansible
domain: ansible.local
ip: 192.168.1.100
netmask: 255.255.255.0
gateway: 192.168.1.1
rootpw: bigsecret
''' '''
@ -273,9 +328,23 @@ def create_vm_template(conn, vmname, image, zone):
# start instance # start instance
def vm_start(conn, vmname): def vm_start(conn, vmname, hostname=None, ip=None, netmask=None, gateway=None,
domain=None, dns=None, rootpw=None, key=None):
vm = conn.vms.get(name=vmname) vm = conn.vms.get(name=vmname)
vm.start() use_cloud_init = False
nics = None
if hostname or ip or netmask or gateway or domain or dns or rootpw or key:
use_cloud_init = True
if ip and netmask and gateway:
ipinfo = params.IP(address=ip, netmask=netmask, gateway=gateway)
nic = params.GuestNicConfiguration(name='eth0', boot_protocol='STATIC', ip=ipinfo, on_boot=True)
nics = params.Nics()
nics = params.GuestNicsConfiguration(nic_configuration=[nic])
initialization=params.Initialization(regenerate_ssh_keys=True, host_name=hostname, domain=domain, user_name='root',
root_password=rootpw, nic_configurations=nics, dns_servers=dns,
authorized_ssh_keys=key)
action = params.Action(use_cloud_init=use_cloud_init, vm=params.VM(initialization=initialization))
vm.start(action=action)
# Stop instance # Stop instance
def vm_stop(conn, vmname): def vm_stop(conn, vmname):
@ -302,7 +371,6 @@ def vm_remove(conn, vmname):
# Get the VMs status # Get the VMs status
def vm_status(conn, vmname): def vm_status(conn, vmname):
status = conn.vms.get(name=vmname).status.state status = conn.vms.get(name=vmname).status.state
print "vm status is : %s" % status
return status return status
@ -311,10 +379,8 @@ def get_vm(conn, vmname):
vm = conn.vms.get(name=vmname) vm = conn.vms.get(name=vmname)
if vm == None: if vm == None:
name = "empty" name = "empty"
print "vmname: %s" % name
else: else:
name = vm.get_name() name = vm.get_name()
print "vmname: %s" % name
return name return name
# ------------------------------------------------------------------- # # ------------------------------------------------------------------- #
@ -333,7 +399,7 @@ def main():
user = dict(required=True), user = dict(required=True),
url = dict(required=True), url = dict(required=True),
instance_name = dict(required=True, aliases=['vmname']), instance_name = dict(required=True, aliases=['vmname']),
password = dict(required=True), password = dict(required=True, no_log=True),
image = dict(), image = dict(),
resource_type = dict(choices=['new', 'template']), resource_type = dict(choices=['new', 'template']),
zone = dict(), zone = dict(),
@ -347,6 +413,14 @@ def main():
disk_int = dict(default='virtio', choices=['virtio', 'ide']), disk_int = dict(default='virtio', choices=['virtio', 'ide']),
instance_os = dict(aliases=['vmos']), instance_os = dict(aliases=['vmos']),
instance_cores = dict(default=1, aliases=['vmcores']), instance_cores = dict(default=1, aliases=['vmcores']),
instance_hostname = dict(aliases=['hostname']),
instance_ip = dict(aliases=['ip']),
instance_netmask = dict(aliases=['netmask']),
instance_gateway = dict(aliases=['gateway']),
instance_domain = dict(aliases=['domain']),
instance_dns = dict(aliases=['dns']),
instance_rootpw = dict(aliases=['rootpw']),
instance_key = dict(aliases=['key']),
sdomain = dict(), sdomain = dict(),
region = dict(), region = dict(),
) )
@ -375,6 +449,14 @@ def main():
vmcores = module.params['instance_cores'] # number of cores vmcores = module.params['instance_cores'] # number of cores
sdomain = module.params['sdomain'] # storage domain to store disk on sdomain = module.params['sdomain'] # storage domain to store disk on
region = module.params['region'] # oVirt Datacenter region = module.params['region'] # oVirt Datacenter
hostname = module.params['instance_hostname']
ip = module.params['instance_ip']
netmask = module.params['instance_netmask']
gateway = module.params['instance_gateway']
domain = module.params['instance_domain']
dns = module.params['instance_dns']
rootpw = module.params['instance_rootpw']
key = module.params['instance_key']
#initialize connection #initialize connection
try: try:
c = conn(url+"/api", user, password) c = conn(url+"/api", user, password)
@ -405,7 +487,8 @@ def main():
if vm_status(c, vmname) == 'up': if vm_status(c, vmname) == 'up':
module.exit_json(changed=False, msg="VM %s is already running" % vmname) module.exit_json(changed=False, msg="VM %s is already running" % vmname)
else: else:
vm_start(c, vmname) #vm_start(c, vmname)
vm_start(c, vmname, hostname, ip, netmask, gateway, domain, dns, rootpw, key)
module.exit_json(changed=True, msg="VM %s started" % vmname) module.exit_json(changed=True, msg="VM %s started" % vmname)
if state == 'shutdown': if state == 'shutdown':

View file

@ -0,0 +1,137 @@
#!/usr/bin/python
# Copyright (c) 2016 Hewlett-Packard Enterprise Corporation
#
# This module is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This software is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this software. If not, see <http://www.gnu.org/licenses/>.
try:
import shade
HAS_SHADE = True
except ImportError:
HAS_SHADE = False
DOCUMENTATION = '''
---
module: os_keystone_domain_facts
short_description: Retrieve facts about one or more OpenStack domains
extends_documentation_fragment: openstack
version_added: "2.1"
author: "Ricardo Carrillo Cruz (@rcarrillocruz)"
description:
- Retrieve facts about a one or more OpenStack domains
requirements:
- "python >= 2.6"
- "shade"
options:
name:
description:
- Name or ID of the domain
required: true
filters:
description:
- A dictionary of meta data to use for further filtering. Elements of
this dictionary may be additional dictionaries.
required: false
default: None
'''
EXAMPLES = '''
# Gather facts about previously created domain
- os_keystone_domain_facts:
cloud: awesomecloud
- debug: var=openstack_domains
# Gather facts about a previously created domain by name
- os_keystone_domain_facts:
cloud: awesomecloud
name: demodomain
- debug: var=openstack_domains
# Gather facts about a previously created domain with filter
- os_keystone_domain_facts
cloud: awesomecloud
name: demodomain
filters:
enabled: False
- debug: var=openstack_domains
'''
RETURN = '''
openstack_domains:
description: has all the OpenStack facts about domains
returned: always, but can be null
type: complex
contains:
id:
description: Unique UUID.
returned: success
type: string
name:
description: Name given to the domain.
returned: success
type: string
description:
description: Description of the domain.
returned: success
type: string
enabled:
description: Flag to indicate if the domain is enabled.
returned: success
type: bool
'''
def main():
argument_spec = openstack_full_argument_spec(
name=dict(required=False, default=None),
filters=dict(required=False, type='dict', default=None),
)
module_kwargs = openstack_module_kwargs(
mutually_exclusive=[
['name', 'filters'],
]
)
module = AnsibleModule(argument_spec, **module_kwargs)
if not HAS_SHADE:
module.fail_json(msg='shade is required for this module')
try:
name = module.params['name']
filters = module.params['filters']
opcloud = shade.operator_cloud(**module.params)
if name:
# Let's suppose user is passing domain ID
try:
domains = cloud.get_domain(name)
except:
domains = opcloud.search_domains(filters={'name': name})
else:
domains = opcloud.search_domains(filters)
module.exit_json(changed=False, ansible_facts=dict(
openstack_domains=domains))
except shade.OpenStackCloudException as e:
module.fail_json(msg=str(e))
from ansible.module_utils.basic import *
from ansible.module_utils.openstack import *
if __name__ == '__main__':
main()

View file

@ -0,0 +1,225 @@
#!/usr/bin/python
# Copyright (c) 2016 IBM
#
# This module is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This software is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this software. If not, see <http://www.gnu.org/licenses/>.
try:
import shade
HAS_SHADE = True
except ImportError:
HAS_SHADE = False
DOCUMENTATION = '''
module: os_port_facts
short_description: Retrieve facts about ports within OpenStack.
version_added: "2.1"
author: "David Shrewsbury (@Shrews)"
description:
- Retrieve facts about ports from OpenStack.
notes:
- Facts are placed in the C(openstack_ports) variable.
requirements:
- "python >= 2.6"
- "shade"
options:
port:
description:
- Unique name or ID of a port.
required: false
default: null
filters:
description:
- A dictionary of meta data to use for further filtering. Elements
of this dictionary will be matched against the returned port
dictionaries. Matching is currently limited to strings within
the port dictionary, or strings within nested dictionaries.
required: false
default: null
extends_documentation_fragment: openstack
'''
EXAMPLES = '''
# Gather facts about all ports
- os_port_facts:
cloud: mycloud
# Gather facts about a single port
- os_port_facts:
cloud: mycloud
port: 6140317d-e676-31e1-8a4a-b1913814a471
# Gather facts about all ports that have device_id set to a specific value
# and with a status of ACTIVE.
- os_port_facts:
cloud: mycloud
filters:
device_id: 1038a010-3a37-4a9d-82ea-652f1da36597
status: ACTIVE
'''
RETURN = '''
openstack_ports:
description: List of port dictionaries. A subset of the dictionary keys
listed below may be returned, depending on your cloud provider.
returned: always, but can be null
type: complex
contains:
admin_state_up:
description: The administrative state of the router, which is
up (true) or down (false).
returned: success
type: boolean
sample: true
allowed_address_pairs:
description: A set of zero or more allowed address pairs. An
address pair consists of an IP address and MAC address.
returned: success
type: list
sample: []
"binding:host_id":
description: The UUID of the host where the port is allocated.
returned: success
type: string
sample: "b4bd682d-234a-4091-aa5b-4b025a6a7759"
"binding:profile":
description: A dictionary the enables the application running on
the host to pass and receive VIF port-specific
information to the plug-in.
returned: success
type: dict
sample: {}
"binding:vif_details":
description: A dictionary that enables the application to pass
information about functions that the Networking API
provides.
returned: success
type: dict
sample: {"port_filter": true}
"binding:vif_type":
description: The VIF type for the port.
returned: success
type: dict
sample: "ovs"
"binding:vnic_type":
description: The virtual network interface card (vNIC) type that is
bound to the neutron port.
returned: success
type: string
sample: "normal"
device_id:
description: The UUID of the device that uses this port.
returned: success
type: string
sample: "b4bd682d-234a-4091-aa5b-4b025a6a7759"
device_owner:
description: The UUID of the entity that uses this port.
returned: success
type: string
sample: "network:router_interface"
dns_assignment:
description: DNS assignment information.
returned: success
type: list
dns_name:
description: DNS name
returned: success
type: string
sample: ""
extra_dhcp_opts:
description: A set of zero or more extra DHCP option pairs.
An option pair consists of an option value and name.
returned: success
type: list
sample: []
fixed_ips:
description: The IP addresses for the port. Includes the IP address
and UUID of the subnet.
returned: success
type: list
id:
description: The UUID of the port.
returned: success
type: string
sample: "3ec25c97-7052-4ab8-a8ba-92faf84148de"
ip_address:
description: The IP address.
returned: success
type: string
sample: "127.0.0.1"
mac_address:
description: The MAC address.
returned: success
type: string
sample: "fa:16:30:5f:10:f1"
name:
description: The port name.
returned: success
type: string
sample: "port_name"
network_id:
description: The UUID of the attached network.
returned: success
type: string
sample: "dd1ede4f-3952-4131-aab6-3b8902268c7d"
port_security_enabled:
description: The port security status. The status is enabled (true) or disabled (false).
returned: success
type: boolean
sample: false
security_groups:
description: The UUIDs of any attached security groups.
returned: success
type: list
status:
description: The port status.
returned: success
type: string
sample: "ACTIVE"
tenant_id:
description: The UUID of the tenant who owns the network.
returned: success
type: string
sample: "51fce036d7984ba6af4f6c849f65ef00"
'''
def main():
argument_spec = openstack_full_argument_spec(
port=dict(required=False),
filters=dict(type='dict', required=False),
)
module_kwargs = openstack_module_kwargs()
module = AnsibleModule(argument_spec, **module_kwargs)
if not HAS_SHADE:
module.fail_json(msg='shade is required for this module')
port = module.params.pop('port')
filters = module.params.pop('filters')
try:
cloud = shade.openstack_cloud(**module.params)
ports = cloud.search_ports(port, filters)
module.exit_json(changed=False, ansible_facts=dict(
openstack_ports=ports))
except shade.OpenStackCloudException as e:
module.fail_json(msg=str(e))
from ansible.module_utils.basic import *
from ansible.module_utils.openstack import *
if __name__ == '__main__':
main()

View file

@ -0,0 +1,163 @@
#!/usr/bin/python
# Copyright (c) 2016 Hewlett-Packard Enterprise Corporation
#
# This module is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This software is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this software. If not, see <http://www.gnu.org/licenses/>.
try:
import shade
HAS_SHADE = True
except ImportError:
HAS_SHADE = False
DOCUMENTATION = '''
---
module: os_project_facts
short_description: Retrieve facts about one or more OpenStack projects
extends_documentation_fragment: openstack
version_added: "2.1"
author: "Ricardo Carrillo Cruz (@rcarrillocruz)"
description:
- Retrieve facts about a one or more OpenStack projects
requirements:
- "python >= 2.6"
- "shade"
options:
name:
description:
- Name or ID of the project
required: true
domain:
description:
- Name or ID of the domain containing the project if the cloud supports domains
required: false
default: None
filters:
description:
- A dictionary of meta data to use for further filtering. Elements of
this dictionary may be additional dictionaries.
required: false
default: None
'''
EXAMPLES = '''
# Gather facts about previously created projects
- os_project_facts:
cloud: awesomecloud
- debug: var=openstack_projects
# Gather facts about a previously created project by name
- os_project_facts:
cloud: awesomecloud
name: demoproject
- debug: var=openstack_projects
# Gather facts about a previously created project in a specific domain
- os_project_facts
cloud: awesomecloud
name: demoproject
domain: admindomain
- debug: var=openstack_projects
# Gather facts about a previously created project in a specific domain
with filter
- os_project_facts
cloud: awesomecloud
name: demoproject
domain: admindomain
filters:
enabled: False
- debug: var=openstack_projects
'''
RETURN = '''
openstack_projects:
description: has all the OpenStack facts about projects
returned: always, but can be null
type: complex
contains:
id:
description: Unique UUID.
returned: success
type: string
name:
description: Name given to the project.
returned: success
type: string
description:
description: Description of the project
returned: success
type: string
enabled:
description: Flag to indicate if the project is enabled
returned: success
type: bool
domain_id:
description: Domain ID containing the project (keystone v3 clouds only)
returned: success
type: bool
'''
def main():
argument_spec = openstack_full_argument_spec(
name=dict(required=False, default=None),
domain=dict(required=False, default=None),
filters=dict(required=False, type='dict', default=None),
)
module = AnsibleModule(argument_spec)
if not HAS_SHADE:
module.fail_json(msg='shade is required for this module')
try:
name = module.params['name']
domain = module.params['domain']
filters = module.params['filters']
opcloud = shade.operator_cloud(**module.params)
if domain:
try:
# We assume admin is passing domain id
dom = opcloud.get_domain(domain)['id']
domain = dom
except:
# If we fail, maybe admin is passing a domain name.
# Note that domains have unique names, just like id.
dom = opcloud.search_domains(filters={'name': domain})
if dom:
domain = dom[0]['id']
else:
module.fail_json(msg='Domain name or ID does not exist')
if not filters:
filters = {}
filters['domain_id'] = domain
projects = opcloud.search_projects(name, filters)
module.exit_json(changed=False, ansible_facts=dict(
openstack_projects=projects))
except shade.OpenStackCloudException as e:
module.fail_json(msg=str(e))
from ansible.module_utils.basic import *
from ansible.module_utils.openstack import *
if __name__ == '__main__':
main()

View file

@ -0,0 +1,172 @@
#!/usr/bin/python
# Copyright (c) 2016 Hewlett-Packard Enterprise Corporation
#
# This module is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This software is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this software. If not, see <http://www.gnu.org/licenses/>.
try:
import shade
HAS_SHADE = True
except ImportError:
HAS_SHADE = False
DOCUMENTATION = '''
---
module: os_user_facts
short_description: Retrieve facts about one or more OpenStack users
extends_documentation_fragment: openstack
version_added: "2.1"
author: "Ricardo Carrillo Cruz (@rcarrillocruz)"
description:
- Retrieve facts about a one or more OpenStack users
requirements:
- "python >= 2.6"
- "shade"
options:
name:
description:
- Name or ID of the user
required: true
domain:
description:
- Name or ID of the domain containing the user if the cloud supports domains
required: false
default: None
filters:
description:
- A dictionary of meta data to use for further filtering. Elements of
this dictionary may be additional dictionaries.
required: false
default: None
'''
EXAMPLES = '''
# Gather facts about previously created users
- os_user_facts:
cloud: awesomecloud
- debug: var=openstack_users
# Gather facts about a previously created user by name
- os_user_facts:
cloud: awesomecloud
name: demouser
- debug: var=openstack_users
# Gather facts about a previously created user in a specific domain
- os_user_facts
cloud: awesomecloud
name: demouser
domain: admindomain
- debug: var=openstack_users
# Gather facts about a previously created user in a specific domain
with filter
- os_user_facts
cloud: awesomecloud
name: demouser
domain: admindomain
filters:
enabled: False
- debug: var=openstack_users
'''
RETURN = '''
openstack_users:
description: has all the OpenStack facts about users
returned: always, but can be null
type: complex
contains:
id:
description: Unique UUID.
returned: success
type: string
name:
description: Name given to the user.
returned: success
type: string
enabled:
description: Flag to indicate if the user is enabled
returned: success
type: bool
domain_id:
description: Domain ID containing the user
returned: success
type: string
default_project_id:
description: Default project ID of the user
returned: success
type: string
email:
description: Email of the user
returned: success
type: string
username:
description: Username of the user
returned: success
type: string
'''
def main():
argument_spec = openstack_full_argument_spec(
name=dict(required=False, default=None),
domain=dict(required=False, default=None),
filters=dict(required=False, type='dict', default=None),
)
module = AnsibleModule(argument_spec)
if not HAS_SHADE:
module.fail_json(msg='shade is required for this module')
try:
name = module.params['name']
domain = module.params['domain']
filters = module.params['filters']
opcloud = shade.operator_cloud(**module.params)
if domain:
try:
# We assume admin is passing domain id
dom = opcloud.get_domain(domain)['id']
domain = dom
except:
# If we fail, maybe admin is passing a domain name.
# Note that domains have unique names, just like id.
dom = opcloud.search_domains(filters={'name': domain})
if dom:
domain = dom[0]['id']
else:
module.fail_json(msg='Domain name or ID does not exist')
if not filters:
filters = {}
filters['domain_id'] = domain
users = opcloud.search_users(name,
filters)
module.exit_json(changed=False, ansible_facts=dict(
openstack_users=users))
except shade.OpenStackCloudException as e:
module.fail_json(msg=str(e))
from ansible.module_utils.basic import *
from ansible.module_utils.openstack import *
if __name__ == '__main__':
main()

View file

@ -25,9 +25,9 @@ short_description: Manage VMware vSphere Datacenters
description: description:
- Manage VMware vSphere Datacenters - Manage VMware vSphere Datacenters
version_added: 2.0 version_added: 2.0
author: "Joseph Callen (@jcpowermac)" author: "Joseph Callen (@jcpowermac), Kamil Szczygiel (@kamsz)"
notes: notes:
- Tested on vSphere 5.5 - Tested on vSphere 6.0
requirements: requirements:
- "python >= 2.6" - "python >= 2.6"
- PyVmomi - PyVmomi
@ -54,7 +54,7 @@ options:
description: description:
- If the datacenter should be present or absent - If the datacenter should be present or absent
choices: ['present', 'absent'] choices: ['present', 'absent']
required: True default: present
extends_documentation_fragment: vmware.documentation extends_documentation_fragment: vmware.documentation
''' '''
@ -64,7 +64,7 @@ EXAMPLES = '''
local_action: > local_action: >
vmware_datacenter vmware_datacenter
hostname="{{ ansible_ssh_host }}" username=root password=vmware hostname="{{ ansible_ssh_host }}" username=root password=vmware
datacenter_name="datacenter" datacenter_name="datacenter" state=present
''' '''
try: try:
@ -74,18 +74,28 @@ except ImportError:
HAS_PYVMOMI = False HAS_PYVMOMI = False
def state_create_datacenter(module): def get_datacenter(context, module):
datacenter_name = module.params['datacenter_name'] try:
content = module.params['content'] datacenter_name = module.params.get('datacenter_name')
changed = True datacenter = find_datacenter_by_name(context, datacenter_name)
datacenter = None return datacenter
except vmodl.RuntimeFault as runtime_fault:
module.fail_json(msg=runtime_fault.msg)
except vmodl.MethodFault as method_fault:
module.fail_json(msg=method_fault.msg)
folder = content.rootFolder
def create_datacenter(context, module):
datacenter_name = module.params.get('datacenter_name')
folder = context.rootFolder
try: try:
datacenter = get_datacenter(context, module)
if not datacenter:
changed = True
if not module.check_mode: if not module.check_mode:
datacenter = folder.CreateDatacenter(name=datacenter_name) folder.CreateDatacenter(name=datacenter_name)
module.exit_json(changed=changed, result=str(datacenter)) module.exit_json(changed=changed)
except vim.fault.DuplicateName: except vim.fault.DuplicateName:
module.fail_json(msg="A datacenter with the name %s already exists" % datacenter_name) module.fail_json(msg="A datacenter with the name %s already exists" % datacenter_name)
except vim.fault.InvalidName: except vim.fault.InvalidName:
@ -99,31 +109,13 @@ def state_create_datacenter(module):
module.fail_json(msg=method_fault.msg) module.fail_json(msg=method_fault.msg)
def check_datacenter_state(module): def destroy_datacenter(context, module):
datacenter_name = module.params['datacenter_name']
try:
content = connect_to_api(module)
datacenter = find_datacenter_by_name(content, datacenter_name)
module.params['content'] = content
if datacenter is None:
return 'absent'
else:
module.params['datacenter'] = datacenter
return 'present'
except vmodl.RuntimeFault as runtime_fault:
module.fail_json(msg=runtime_fault.msg)
except vmodl.MethodFault as method_fault:
module.fail_json(msg=method_fault.msg)
def state_destroy_datacenter(module):
datacenter = module.params['datacenter']
changed = True
result = None result = None
try: try:
datacenter = get_datacenter(context, module)
if datacenter:
changed = True
if not module.check_mode: if not module.check_mode:
task = datacenter.Destroy_Task() task = datacenter.Destroy_Task()
changed, result = wait_for_task(task) changed, result = wait_for_task(task)
@ -136,17 +128,13 @@ def state_destroy_datacenter(module):
module.fail_json(msg=method_fault.msg) module.fail_json(msg=method_fault.msg)
def state_exit_unchanged(module):
module.exit_json(changed=False)
def main(): def main():
argument_spec = vmware_argument_spec() argument_spec = vmware_argument_spec()
argument_spec.update( argument_spec.update(
dict( dict(
datacenter_name=dict(required=True, type='str'), datacenter_name=dict(required=True, type='str'),
state=dict(required=True, choices=['present', 'absent'], type='str'), state=dict(default='present', choices=['present', 'absent'], type='str')
) )
) )
module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True) module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)
@ -154,21 +142,14 @@ def main():
if not HAS_PYVMOMI: if not HAS_PYVMOMI:
module.fail_json(msg='pyvmomi is required for this module') module.fail_json(msg='pyvmomi is required for this module')
datacenter_states = { context = connect_to_api(module)
'absent': { state = module.params.get('state')
'present': state_destroy_datacenter,
'absent': state_exit_unchanged,
},
'present': {
'present': state_exit_unchanged,
'absent': state_create_datacenter,
}
}
desired_state = module.params['state']
current_state = check_datacenter_state(module)
datacenter_states[desired_state][current_state](module) if state == 'present':
create_datacenter(context, module)
if state == 'absent':
destroy_datacenter(context, module)
from ansible.module_utils.basic import * from ansible.module_utils.basic import *
from ansible.module_utils.vmware import * from ansible.module_utils.vmware import *

View file

@ -144,7 +144,9 @@ class RabbitMqUser(object):
def _exec(self, args, run_in_check_mode=False): def _exec(self, args, run_in_check_mode=False):
if not self.module.check_mode or (self.module.check_mode and run_in_check_mode): if not self.module.check_mode or (self.module.check_mode and run_in_check_mode):
cmd = [self._rabbitmqctl, '-q', '-n', self.node] cmd = [self._rabbitmqctl, '-q']
if self.node is not None:
cmd.append(['-n', self.node])
rc, out, err = self.module.run_command(cmd + args, check_rc=True) rc, out, err = self.module.run_command(cmd + args, check_rc=True)
return out.splitlines() return out.splitlines()
return list() return list()
@ -235,7 +237,7 @@ def main():
read_priv=dict(default='^$'), read_priv=dict(default='^$'),
force=dict(default='no', type='bool'), force=dict(default='no', type='bool'),
state=dict(default='present', choices=['present', 'absent']), state=dict(default='present', choices=['present', 'absent']),
node=dict(default='rabbit') node=dict(default=None)
) )
module = AnsibleModule( module = AnsibleModule(
argument_spec=arg_spec, argument_spec=arg_spec,

View file

@ -169,7 +169,7 @@ def main():
module = AnsibleModule( module = AnsibleModule(
argument_spec=dict( argument_spec=dict(
token=dict(required=True), token=dict(required=True, no_log=True),
room=dict(required=True), room=dict(required=True),
msg=dict(required=True), msg=dict(required=True),
msg_from=dict(default="Ansible", aliases=['from']), msg_from=dict(default="Ansible", aliases=['from']),

View file

@ -108,7 +108,7 @@ else:
def main(): def main():
module = AnsibleModule( module = AnsibleModule(
argument_spec = dict( argument_spec = dict(
api_key = dict(type='str', required=True), api_key = dict(type='str', required=True, no_log=True),
channel = dict(type='str', default=None), channel = dict(type='str', default=None),
device = dict(type='str', default=None), device = dict(type='str', default=None),
push_type = dict(type='str', default="note", choices=['note', 'link']), push_type = dict(type='str', default="note", choices=['note', 'link']),

View file

@ -95,9 +95,9 @@ def main():
module = AnsibleModule( module = AnsibleModule(
argument_spec=dict( argument_spec=dict(
msg=dict(required=True), msg=dict(required=True),
app_token=dict(required=True), app_token=dict(required=True, no_log=True),
user_key=dict(required=True), user_key=dict(required=True, no_log=True),
pri=dict(required=False, default=0), pri=dict(required=False, default='0', choices=['-2','-1','0','1','2']),
), ),
) )

View file

@ -202,7 +202,6 @@ def main():
installed = _is_package_installed(module, name, locallib, cpanm, version) installed = _is_package_installed(module, name, locallib, cpanm, version)
if not installed: if not installed:
out_cpanm = err_cpanm = ''
cmd = _build_cmd_line(name, from_path, notest, locallib, mirror, mirror_only, installdeps, cpanm, use_sudo) cmd = _build_cmd_line(name, from_path, notest, locallib, mirror, mirror_only, installdeps, cpanm, use_sudo)
rc_cpanm, out_cpanm, err_cpanm = module.run_command(cmd, check_rc=False) rc_cpanm, out_cpanm, err_cpanm = module.run_command(cmd, check_rc=False)
@ -210,7 +209,7 @@ def main():
if rc_cpanm != 0: if rc_cpanm != 0:
module.fail_json(msg=err_cpanm, cmd=cmd) module.fail_json(msg=err_cpanm, cmd=cmd)
if err_cpanm and 'is up to date' not in err_cpanm: if (err_cpanm.find('is up to date') == -1 and out_cpanm.find('is up to date') == -1):
changed = True changed = True
module.exit_json(changed=changed, binary=cpanm, name=name) module.exit_json(changed=changed, binary=cpanm, name=name)

View file

@ -323,7 +323,7 @@ def main():
enablerepo=dict(type='list', default=[]), enablerepo=dict(type='list', default=[]),
disablerepo=dict(type='list', default=[]), disablerepo=dict(type='list', default=[]),
list=dict(), list=dict(),
conf_file=dict(default=None), conf_file=dict(default=None, type='path'),
disable_gpg_check=dict(default=False, type='bool'), disable_gpg_check=dict(default=False, type='bool'),
), ),
required_one_of=[['name', 'list']], required_one_of=[['name', 'list']],

3
packaging/os/homebrew.py Normal file → Executable file
View file

@ -813,6 +813,9 @@ def main():
), ),
supports_check_mode=True, supports_check_mode=True,
) )
module.run_command_environ_update = dict(LANG='C', LC_ALL='C', LC_MESSAGES='C', LC_CTYPE='C')
p = module.params p = module.params
if p['name']: if p['name']:

3
packaging/os/homebrew_cask.py Normal file → Executable file
View file

@ -481,6 +481,9 @@ def main():
), ),
supports_check_mode=True, supports_check_mode=True,
) )
module.run_command_environ_update = dict(LANG='C', LC_ALL='C', LC_MESSAGES='C', LC_CTYPE='C')
p = module.params p = module.params
if p['name']: if p['name']:

View file

@ -3,6 +3,7 @@
# Copyright (c) 2013 Shaun Zinck <shaun.zinck at gmail.com> # Copyright (c) 2013 Shaun Zinck <shaun.zinck at gmail.com>
# Copyright (c) 2015 Lawrence Leonard Gilbert <larry@L2G.to> # Copyright (c) 2015 Lawrence Leonard Gilbert <larry@L2G.to>
# Copyright (c) 2016 Jasper Lievisse Adriaanse <j at jasper.la>
# #
# Written by Shaun Zinck # Written by Shaun Zinck
# Based on pacman module written by Afterburn <http://github.com/afterburn> # Based on pacman module written by Afterburn <http://github.com/afterburn>
@ -33,6 +34,7 @@ version_added: "1.0"
author: author:
- "Larry Gilbert (L2G)" - "Larry Gilbert (L2G)"
- "Shaun Zinck (@szinck)" - "Shaun Zinck (@szinck)"
- "Jasper Lievisse Adriaanse (@jasperla)"
notes: notes:
- "Known bug with pkgin < 0.8.0: if a package is removed and another - "Known bug with pkgin < 0.8.0: if a package is removed and another
package depends on it, the other package will be silently removed as package depends on it, the other package will be silently removed as
@ -57,6 +59,34 @@ options:
default: no default: no
choices: [ "yes", "no" ] choices: [ "yes", "no" ]
version_added: "2.1" version_added: "2.1"
upgrade:
description:
- Upgrade main packages to their newer versions
required: false
default: no
choices: [ "yes", "no" ]
version_added: "2.1"
full_upgrade:
description:
- Upgrade all packages to their newer versions
required: false
default: no
choices: [ "yes", "no" ]
version_added: "2.1"
clean:
description:
- Clean packages cache
required: false
default: no
choices: [ "yes", "no" ]
version_added: "2.1"
force:
description:
- Force package reinstall
required: false
default: no
choices: [ "yes", "no" ]
version_added: "2.1"
''' '''
EXAMPLES = ''' EXAMPLES = '''
@ -74,12 +104,24 @@ EXAMPLES = '''
# Update repositories as a separate step # Update repositories as a separate step
- pkgin: update_cache=yes - pkgin: update_cache=yes
# Upgrade main packages (equivalent to C(pkgin upgrade))
- pkgin: upgrade=yes
# Upgrade all packages (equivalent to C(pkgin full-upgrade))
- pkgin: full_upgrade=yes
# Force-upgrade all packages (equivalent to C(pkgin -F full-upgrade))
- pkgin: full_upgrade=yes force=yes
# clean packages cache (equivalent to C(pkgin clean))
- pkgin: clean=yes
''' '''
import re import re
def query_package(module, pkgin_path, name): def query_package(module, name):
"""Search for the package by name. """Search for the package by name.
Possible return values: Possible return values:
@ -89,7 +131,7 @@ def query_package(module, pkgin_path, name):
""" """
# test whether '-p' (parsable) flag is supported. # test whether '-p' (parsable) flag is supported.
rc, out, err = module.run_command("%s -p -v" % pkgin_path) rc, out, err = module.run_command("%s -p -v" % PKGIN_PATH)
if rc == 0: if rc == 0:
pflag = '-p' pflag = '-p'
@ -100,7 +142,7 @@ def query_package(module, pkgin_path, name):
# Use "pkgin search" to find the package. The regular expression will # Use "pkgin search" to find the package. The regular expression will
# only match on the complete name. # only match on the complete name.
rc, out, err = module.run_command("%s %s search \"^%s$\"" % (pkgin_path, pflag, name)) rc, out, err = module.run_command("%s %s search \"^%s$\"" % (PKGIN_PATH, pflag, name))
# rc will not be 0 unless the search was a success # rc will not be 0 unless the search was a success
if rc == 0: if rc == 0:
@ -122,7 +164,7 @@ def query_package(module, pkgin_path, name):
# Search for package, stripping version # Search for package, stripping version
# (results in sth like 'gcc47-libs' or 'emacs24-nox11') # (results in sth like 'gcc47-libs' or 'emacs24-nox11')
pkg_search_obj = re.search(r'^([a-zA-Z]+[0-9]*[\-]*\w*)-[0-9]', pkgname_with_version, re.M) pkg_search_obj = re.search(r'^(.*?)\-[0-9][0-9.]*(nb[0-9]+)*', pkgname_with_version, re.M)
# Do not proceed unless we have a match # Do not proceed unless we have a match
if not pkg_search_obj: if not pkg_search_obj:
@ -162,37 +204,43 @@ def format_action_message(module, action, count):
return message + "s" return message + "s"
def format_pkgin_command(module, pkgin_path, command, package=None): def format_pkgin_command(module, command, package=None):
# Not all commands take a package argument, so cover this up by passing # Not all commands take a package argument, so cover this up by passing
# an empty string. Some commands (e.g. 'update') will ignore extra # an empty string. Some commands (e.g. 'update') will ignore extra
# arguments, however this behaviour cannot be relied on for others. # arguments, however this behaviour cannot be relied on for others.
if package is None: if package is None:
package = "" package = ""
vars = { "pkgin": pkgin_path, if module.params["force"]:
force = "-F"
else:
force = ""
vars = { "pkgin": PKGIN_PATH,
"command": command, "command": command,
"package": package } "package": package,
"force": force}
if module.check_mode: if module.check_mode:
return "%(pkgin)s -n %(command)s %(package)s" % vars return "%(pkgin)s -n %(command)s %(package)s" % vars
else: else:
return "%(pkgin)s -y %(command)s %(package)s" % vars return "%(pkgin)s -y %(force)s %(command)s %(package)s" % vars
def remove_packages(module, pkgin_path, packages): def remove_packages(module, packages):
remove_c = 0 remove_c = 0
# Using a for loop incase of error, we can report the package that failed # Using a for loop incase of error, we can report the package that failed
for package in packages: for package in packages:
# Query the package first, to see if we even need to remove # Query the package first, to see if we even need to remove
if not query_package(module, pkgin_path, package): if not query_package(module, package):
continue continue
rc, out, err = module.run_command( rc, out, err = module.run_command(
format_pkgin_command(module, pkgin_path, "remove", package)) format_pkgin_command(module, "remove", package))
if not module.check_mode and query_package(module, pkgin_path, package): if not module.check_mode and query_package(module, package):
module.fail_json(msg="failed to remove %s: %s" % (package, out)) module.fail_json(msg="failed to remove %s: %s" % (package, out))
remove_c += 1 remove_c += 1
@ -203,18 +251,18 @@ def remove_packages(module, pkgin_path, packages):
module.exit_json(changed=False, msg="package(s) already absent") module.exit_json(changed=False, msg="package(s) already absent")
def install_packages(module, pkgin_path, packages): def install_packages(module, packages):
install_c = 0 install_c = 0
for package in packages: for package in packages:
if query_package(module, pkgin_path, package): if query_package(module, package):
continue continue
rc, out, err = module.run_command( rc, out, err = module.run_command(
format_pkgin_command(module, pkgin_path, "install", package)) format_pkgin_command(module, "install", package))
if not module.check_mode and not query_package(module, pkgin_path, package): if not module.check_mode and not query_package(module, package):
module.fail_json(msg="failed to install %s: %s" % (package, out)) module.fail_json(msg="failed to install %s: %s" % (package, out))
install_c += 1 install_c += 1
@ -224,41 +272,97 @@ def install_packages(module, pkgin_path, packages):
module.exit_json(changed=False, msg="package(s) already present") module.exit_json(changed=False, msg="package(s) already present")
def update_package_db(module, pkgin_path): def update_package_db(module):
rc, out, err = module.run_command( rc, out, err = module.run_command(
format_pkgin_command(module, pkgin_path, "update")) format_pkgin_command(module, "update"))
if rc == 0: if rc == 0:
return True if re.search('database for.*is up-to-date\n$', out):
return False, "datebase is up-to-date"
else:
return True, "updated repository database"
else: else:
module.fail_json(msg="could not update package db") module.fail_json(msg="could not update package db")
def do_upgrade_packages(module, full=False):
if full:
cmd = "full-upgrade"
else:
cmd = "upgrade"
rc, out, err = module.run_command(
format_pkgin_command(module, cmd))
if rc == 0:
if re.search('^nothing to do.\n$', out):
module.exit_json(changed=False, msg="nothing left to upgrade")
else:
module.fail_json(msg="could not %s packages" % cmd)
def upgrade_packages(module):
do_upgrade_packages(module)
def full_upgrade_packages(module):
do_upgrade_packages(module, True)
def clean_cache(module):
rc, out, err = module.run_command(
format_pkgin_command(module, "clean"))
if rc == 0:
# There's no indication if 'clean' actually removed anything,
# so assume it did.
module.exit_json(changed=True, msg="cleaned caches")
else:
module.fail_json(msg="could not clean package cache")
def main(): def main():
module = AnsibleModule( module = AnsibleModule(
argument_spec = dict( argument_spec = dict(
state = dict(default="present", choices=["present","absent"]), state = dict(default="present", choices=["present","absent"]),
name = dict(aliases=["pkg"], type='list'), name = dict(aliases=["pkg"], type='list'),
update_cache = dict(default='no', type='bool')), update_cache = dict(default='no', type='bool'),
required_one_of = [['name', 'update_cache']], upgrade = dict(default='no', type='bool'),
full_upgrade = dict(default='no', type='bool'),
clean = dict(default='no', type='bool'),
force = dict(default='no', type='bool')),
required_one_of = [['name', 'update_cache', 'upgrade', 'full_upgrade', 'clean']],
supports_check_mode = True) supports_check_mode = True)
pkgin_path = module.get_bin_path('pkgin', True, ['/opt/local/bin']) global PKGIN_PATH
PKGIN_PATH = module.get_bin_path('pkgin', True, ['/opt/local/bin'])
module.run_command_environ_update = dict(LANG='C', LC_ALL='C', LC_MESSAGES='C', LC_CTYPE='C')
p = module.params p = module.params
if p["update_cache"]:
c, msg = update_package_db(module)
if not (p['name'] or p["upgrade"] or p["full_upgrade"]):
module.exit_json(changed=c, msg=msg)
if p["upgrade"]:
upgrade_packages(module)
if not p['name']:
module.exit_json(changed=True, msg='upgraded packages')
if p["full_upgrade"]:
full_upgrade_packages(module)
if not p['name']:
module.exit_json(changed=True, msg='upgraded all packages')
if p["clean"]:
clean_cache(module)
if not p['name']:
module.exit_json(changed=True, msg='cleaned caches')
pkgs = p["name"] pkgs = p["name"]
if p["update_cache"]:
update_package_db(module, pkgin_path)
if not p['name']:
module.exit_json(changed=True, msg='updated repository database')
if p["state"] == "present": if p["state"] == "present":
install_packages(module, pkgin_path, pkgs) install_packages(module, pkgs)
elif p["state"] == "absent": elif p["state"] == "absent":
remove_packages(module, pkgin_path, pkgs) remove_packages(module, pkgs)
# import module snippets # import module snippets
from ansible.module_utils.basic import * from ansible.module_utils.basic import *

View file

@ -0,0 +1,215 @@
#!/usr/bin/python
# (c) 2015, Werner Dijkerman (ikben@werner-dijkerman.nl)
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
DOCUMENTATION = '''
---
module: gitlab_group
short_description: Creates/updates/deletes Gitlab Groups
description:
- When the group does not exists in Gitlab, it will be created.
- When the group does exists and state=absent, the group will be deleted.
version_added: "2.1"
author: "Werner Dijkerman (@dj-wasabi)"
requirements:
- pyapi-gitlab python module
options:
server_url:
description:
- Url of Gitlab server, with protocol (http or https).
required: true
validate_certs:
description:
- When using https if SSL certificate needs to be verified.
required: false
default: true
aliases:
- verify_ssl
login_user:
description:
- Gitlab user name.
required: false
default: null
login_password:
description:
- Gitlab password for login_user
required: false
default: null
login_token:
description:
- Gitlab token for logging in.
required: false
default: null
name:
description:
- Name of the group you want to create.
required: true
path:
description:
- The path of the group you want to create, this will be server_url/group_path
- If not supplied, the group_name will be used.
required: false
default: null
state:
description:
- create or delete group.
- Possible values are present and absent.
required: false
default: "present"
choices: ["present", "absent"]
'''
EXAMPLES = '''
- name: "Delete Gitlab Group"
local_action: gitlab_group
server_url="http://gitlab.dj-wasabi.local"
validate_certs=false
login_token="WnUzDsxjy8230-Dy_k"
name=my_first_group
state=absent
- name: "Create Gitlab Group"
local_action: gitlab_group
server_url="https://gitlab.dj-wasabi.local"
validate_certs=true
login_user=dj-wasabi
login_password="MySecretPassword"
name=my_first_group
path=my_first_group
state=present
'''
RETURN = '''# '''
try:
import gitlab
HAS_GITLAB_PACKAGE = True
except:
HAS_GITLAB_PACKAGE = False
class GitLabGroup(object):
def __init__(self, module, git):
self._module = module
self._gitlab = git
def createGroup(self, group_name, group_path):
if self._module.check_mode:
self._module.exit_json(changed=True)
return self._gitlab.creategroup(group_name, group_path)
def deleteGroup(self, group_name):
is_group_empty = True
group_id = self.idGroup(group_name)
for project in self._gitlab.getall(self._gitlab.getprojects):
owner = project['namespace']['name']
if owner == group_name:
is_group_empty = False
if is_group_empty:
if self._module.check_mode:
self._module.exit_json(changed=True)
return self._gitlab.deletegroup(group_id)
else:
self._module.fail_json(msg="There are still projects in this group. These needs to be moved or deleted before this group can be removed.")
def existsGroup(self, group_name):
for group in self._gitlab.getall(self._gitlab.getgroups):
if group['name'] == group_name:
return True
return False
def idGroup(self, group_name):
for group in self._gitlab.getall(self._gitlab.getgroups):
if group['name'] == group_name:
return group['id']
def main():
module = AnsibleModule(
argument_spec=dict(
server_url=dict(required=True),
validate_certs=dict(required=False, default=True, type=bool, aliases=['verify_ssl']),
login_user=dict(required=False, no_log=True),
login_password=dict(required=False, no_log=True),
login_token=dict(required=False, no_log=True),
name=dict(required=True),
path=dict(required=False),
state=dict(default="present", choices=["present", "absent"]),
),
supports_check_mode=True
)
if not HAS_GITLAB_PACKAGE:
module.fail_json(msg="Missing requried gitlab module (check docs or install with: pip install pyapi-gitlab")
server_url = module.params['server_url']
verify_ssl = module.params['validate_certs']
login_user = module.params['login_user']
login_password = module.params['login_password']
login_token = module.params['login_token']
group_name = module.params['name']
group_path = module.params['path']
state = module.params['state']
# We need both login_user and login_password or login_token, otherwise we fail.
if login_user is not None and login_password is not None:
use_credentials = True
elif login_token is not None:
use_credentials = False
else:
module.fail_json(msg="No login credentials are given. Use login_user with login_password, or login_token")
# Set group_path to group_name if it is empty.
if group_path is None:
group_path = group_name.replace(" ", "_")
# Lets make an connection to the Gitlab server_url, with either login_user and login_password
# or with login_token
try:
if use_credentials:
git = gitlab.Gitlab(host=server_url)
git.login(user=login_user, password=login_password)
else:
git = gitlab.Gitlab(server_url, token=login_token, verify_ssl=verify_ssl)
except Exception, e:
module.fail_json(msg="Failed to connect to Gitlab server: %s " % e)
# Validate if group exists and take action based on "state"
group = GitLabGroup(module, git)
group_name = group_name.lower()
group_exists = group.existsGroup(group_name)
if group_exists and state == "absent":
group.deleteGroup(group_name)
module.exit_json(changed=True, result="Successfully deleted group %s" % group_name)
else:
if state == "absent":
module.exit_json(changed=False, result="Group deleted or does not exists")
else:
if group_exists:
module.exit_json(changed=False)
else:
if group.createGroup(group_name, group_path):
module.exit_json(changed=True, result="Successfully created or updated the group %s" % group_name)
from ansible.module_utils.basic import *
if __name__ == '__main__':
main()

View file

@ -0,0 +1,397 @@
#!/usr/bin/python
# (c) 2015, Werner Dijkerman (ikben@werner-dijkerman.nl)
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
DOCUMENTATION = '''
---
module: gitlab_project
short_description: Creates/updates/deletes Gitlab Projects
description:
- When the project does not exists in Gitlab, it will be created.
- When the project does exists and state=absent, the project will be deleted.
- When changes are made to the project, the project will be updated.
version_added: "2.1"
author: "Werner Dijkerman (@dj-wasabi)"
requirements:
- pyapi-gitlab python module
options:
server_url:
description:
- Url of Gitlab server, with protocol (http or https).
required: true
validate_certs:
description:
- When using https if SSL certificate needs to be verified.
required: false
default: true
aliases:
- verify_ssl
login_user:
description:
- Gitlab user name.
required: false
default: null
login_password:
description:
- Gitlab password for login_user
required: false
default: null
login_token:
description:
- Gitlab token for logging in.
required: false
default: null
group:
description:
- The name of the group of which this projects belongs to.
- When not provided, project will belong to user which is configured in 'login_user' or 'login_token'
- When provided with username, project will be created for this user. 'login_user' or 'login_token' needs admin rights.
required: false
default: null
name:
description:
- The name of the project
required: true
path:
description:
- The path of the project you want to create, this will be server_url/<group>/path
- If not supplied, name will be used.
required: false
default: null
description:
description:
- An description for the project.
required: false
default: null
issues_enabled:
description:
- Whether you want to create issues or not.
- Possible values are true and false.
required: false
default: true
merge_requests_enabled:
description:
- If merge requests can be made or not.
- Possible values are true and false.
required: false
default: true
wiki_enabled:
description:
- If an wiki for this project should be available or not.
- Possible values are true and false.
required: false
default: true
snippets_enabled:
description:
- If creating snippets should be available or not.
- Possible values are true and false.
required: false
default: true
public:
description:
- If the project is public available or not.
- Setting this to true is same as setting visibility_level to 20.
- Possible values are true and false.
required: false
default: false
visibility_level:
description:
- Private. visibility_level is 0. Project access must be granted explicitly for each user.
- Internal. visibility_level is 10. The project can be cloned by any logged in user.
- Public. visibility_level is 20. The project can be cloned without any authentication.
- Possible values are 0, 10 and 20.
required: false
default: 0
import_url:
description:
- Git repository which will me imported into gitlab.
- Gitlab server needs read access to this git repository.
required: false
default: false
state:
description:
- create or delete project.
- Possible values are present and absent.
required: false
default: "present"
choices: ["present", "absent"]
'''
EXAMPLES = '''
- name: "Delete Gitlab Project"
local_action: gitlab_project
server_url="http://gitlab.dj-wasabi.local"
validate_certs=false
login_token="WnUzDsxjy8230-Dy_k"
name=my_first_project
state=absent
- name: "Create Gitlab Project in group Ansible"
local_action: gitlab_project
server_url="https://gitlab.dj-wasabi.local"
validate_certs=true
login_user=dj-wasabi
login_password="MySecretPassword"
name=my_first_project
group=ansible
issues_enabled=false
wiki_enabled=true
snippets_enabled=true
import_url="http://git.example.com/example/lab.git"
state=present
'''
RETURN = '''# '''
try:
import gitlab
HAS_GITLAB_PACKAGE = True
except:
HAS_GITLAB_PACKAGE = False
class GitLabProject(object):
def __init__(self, module, git):
self._module = module
self._gitlab = git
def createOrUpdateProject(self, project_exists, group_name, import_url, arguments):
is_user = False
group_id = self.getGroupId(group_name)
if not group_id:
group_id = self.getUserId(group_name)
is_user = True
if project_exists:
# Edit project
return self.updateProject(group_name, arguments)
else:
# Create project
if self._module.check_mode:
self._module.exit_json(changed=True)
return self.createProject(is_user, group_id, import_url, arguments)
def createProject(self, is_user, user_id, import_url, arguments):
if is_user:
return self._gitlab.createprojectuser(user_id=user_id, import_url=import_url, **arguments)
else:
group_id = user_id
return self._gitlab.createproject(namespace_id=group_id, import_url=import_url, **arguments)
def deleteProject(self, group_name, project_name):
if self.existsGroup(group_name):
project_owner = group_name
else:
project_owner = self._gitlab.currentuser()['username']
search_results = self._gitlab.searchproject(search=project_name)
for result in search_results:
owner = result['namespace']['name']
if owner == project_owner:
return self._gitlab.deleteproject(result['id'])
def existsProject(self, group_name, project_name):
if self.existsGroup(group_name):
project_owner = group_name
else:
project_owner = self._gitlab.currentuser()['username']
search_results = self._gitlab.searchproject(search=project_name)
for result in search_results:
owner = result['namespace']['name']
if owner == project_owner:
return True
return False
def existsGroup(self, group_name):
if group_name is not None:
# Find the group, if group not exists we try for user
for group in self._gitlab.getall(self._gitlab.getgroups):
if group['name'] == group_name:
return True
user_name = group_name
user_data = self._gitlab.getusers(search=user_name)
for data in user_data:
if 'id' in user_data:
return True
return False
def getGroupId(self, group_name):
if group_name is not None:
# Find the group, if group not exists we try for user
for group in self._gitlab.getall(self._gitlab.getgroups):
if group['name'] == group_name:
return group['id']
def getProjectId(self, group_name, project_name):
if self.existsGroup(group_name):
project_owner = group_name
else:
project_owner = self._gitlab.currentuser()['username']
search_results = self._gitlab.searchproject(search=project_name)
for result in search_results:
owner = result['namespace']['name']
if owner == project_owner:
return result['id']
def getUserId(self, user_name):
user_data = self._gitlab.getusers(search=user_name)
for data in user_data:
if 'id' in data:
return data['id']
return self._gitlab.currentuser()['id']
def to_bool(self, value):
if value:
return 1
else:
return 0
def updateProject(self, group_name, arguments):
project_changed = False
project_name = arguments['name']
project_id = self.getProjectId(group_name, project_name)
project_data = self._gitlab.getproject(project_id=project_id)
for arg_key, arg_value in arguments.items():
project_data_value = project_data[arg_key]
if isinstance(project_data_value, bool) or project_data_value is None:
to_bool = self.to_bool(project_data_value)
if to_bool != arg_value:
project_changed = True
continue
else:
if project_data_value != arg_value:
project_changed = True
if project_changed:
if self._module.check_mode:
self._module.exit_json(changed=True)
return self._gitlab.editproject(project_id=project_id, **arguments)
else:
return False
def main():
module = AnsibleModule(
argument_spec=dict(
server_url=dict(required=True),
validate_certs=dict(required=False, default=True, type=bool, aliases=['verify_ssl']),
login_user=dict(required=False, no_log=True),
login_password=dict(required=False, no_log=True),
login_token=dict(required=False, no_log=True),
group=dict(required=False),
name=dict(required=True),
path=dict(required=False),
description=dict(required=False),
issues_enabled=dict(default=True, type=bool),
merge_requests_enabled=dict(default=True, type=bool),
wiki_enabled=dict(default=True, type=bool),
snippets_enabled=dict(default=True, type=bool),
public=dict(default=False, type=bool),
visibility_level=dict(default="0", choices=["0", "10", "20"]),
import_url=dict(required=False),
state=dict(default="present", choices=["present", 'absent']),
),
supports_check_mode=True
)
if not HAS_GITLAB_PACKAGE:
module.fail_json(msg="Missing required gitlab module (check docs or install with: pip install pyapi-gitlab")
server_url = module.params['server_url']
verify_ssl = module.params['validate_certs']
login_user = module.params['login_user']
login_password = module.params['login_password']
login_token = module.params['login_token']
group_name = module.params['group']
project_name = module.params['name']
project_path = module.params['path']
description = module.params['description']
issues_enabled = module.params['issues_enabled']
merge_requests_enabled = module.params['merge_requests_enabled']
wiki_enabled = module.params['wiki_enabled']
snippets_enabled = module.params['snippets_enabled']
public = module.params['public']
visibility_level = module.params['visibility_level']
import_url = module.params['import_url']
state = module.params['state']
# We need both login_user and login_password or login_token, otherwise we fail.
if login_user is not None and login_password is not None:
use_credentials = True
elif login_token is not None:
use_credentials = False
else:
module.fail_json(msg="No login credentials are given. Use login_user with login_password, or login_token")
# Set project_path to project_name if it is empty.
if project_path is None:
project_path = project_name.replace(" ", "_")
# Gitlab API makes no difference between upper and lower cases, so we lower them.
project_name = project_name.lower()
project_path = project_path.lower()
if group_name is not None:
group_name = group_name.lower()
# Lets make an connection to the Gitlab server_url, with either login_user and login_password
# or with login_token
try:
if use_credentials:
git = gitlab.Gitlab(host=server_url)
git.login(user=login_user, password=login_password)
else:
git = gitlab.Gitlab(server_url, token=login_token, verify_ssl=verify_ssl)
except Exception, e:
module.fail_json(msg="Failed to connect to Gitlab server: %s " % e)
# Validate if project exists and take action based on "state"
project = GitLabProject(module, git)
project_exists = project.existsProject(group_name, project_name)
# Creating the project dict
arguments = {"name": project_name,
"path": project_path,
"description": description,
"issues_enabled": project.to_bool(issues_enabled),
"merge_requests_enabled": project.to_bool(merge_requests_enabled),
"wiki_enabled": project.to_bool(wiki_enabled),
"snippets_enabled": project.to_bool(snippets_enabled),
"public": project.to_bool(public),
"visibility_level": int(visibility_level)}
if project_exists and state == "absent":
project.deleteProject(group_name, project_name)
module.exit_json(changed=True, result="Successfully deleted project %s" % project_name)
else:
if state == "absent":
module.exit_json(changed=False, result="Project deleted or does not exists")
else:
if project.createOrUpdateProject(project_exists, group_name, import_url, arguments):
module.exit_json(changed=True, result="Successfully created or updated the project %s" % project_name)
else:
module.exit_json(changed=False)
from ansible.module_utils.basic import *
if __name__ == '__main__':
main()

View file

@ -0,0 +1,348 @@
#!/usr/bin/python
# (c) 2015, Werner Dijkerman (ikben@werner-dijkerman.nl)
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
DOCUMENTATION = '''
---
module: gitlab_user
short_description: Creates/updates/deletes Gitlab Users
description:
- When the user does not exists in Gitlab, it will be created.
- When the user does exists and state=absent, the user will be deleted.
- When changes are made to user, the user will be updated.
version_added: "2.1"
author: "Werner Dijkerman (@dj-wasabi)"
requirements:
- pyapi-gitlab python module
options:
server_url:
description:
- Url of Gitlab server, with protocol (http or https).
required: true
validate_certs:
description:
- When using https if SSL certificate needs to be verified.
required: false
default: true
aliases:
- verify_ssl
login_user:
description:
- Gitlab user name.
required: false
default: null
login_password:
description:
- Gitlab password for login_user
required: false
default: null
login_token:
description:
- Gitlab token for logging in.
required: false
default: null
name:
description:
- Name of the user you want to create
required: true
username:
description:
- The username of the user.
required: true
password:
description:
- The password of the user.
required: true
email:
description:
- The email that belongs to the user.
required: true
sshkey_name:
description:
- The name of the sshkey
required: false
default: null
sshkey_file:
description:
- The ssh key itself.
required: false
default: null
group:
description:
- Add user as an member to this group.
required: false
default: null
access_level:
description:
- The access level to the group. One of the following can be used.
- guest
- reporter
- developer
- master
- owner
required: false
default: null
state:
description:
- create or delete group.
- Possible values are present and absent.
required: false
default: present
choices: ["present", "absent"]
'''
EXAMPLES = '''
- name: "Delete Gitlab User"
local_action: gitlab_user
server_url="http://gitlab.dj-wasabi.local"
validate_certs=false
login_token="WnUzDsxjy8230-Dy_k"
username=myusername
state=absent
- name: "Create Gitlab User"
local_action: gitlab_user
server_url="https://gitlab.dj-wasabi.local"
validate_certs=true
login_user=dj-wasabi
login_password="MySecretPassword"
name=My Name
username=myusername
password=mysecretpassword
email=me@home.com
sshkey_name=MySSH
sshkey_file=ssh-rsa AAAAB3NzaC1yc...
state=present
'''
RETURN = '''# '''
try:
import gitlab
HAS_GITLAB_PACKAGE = True
except:
HAS_GITLAB_PACKAGE = False
class GitLabUser(object):
def __init__(self, module, git):
self._module = module
self._gitlab = git
def addToGroup(self, group_id, user_id, access_level):
if access_level == "guest":
level = 10
elif access_level == "reporter":
level = 20
elif access_level == "developer":
level = 30
elif access_level == "master":
level = 40
elif access_level == "owner":
level = 50
return self._gitlab.addgroupmember(group_id, user_id, level)
def createOrUpdateUser(self, user_name, user_username, user_password, user_email, user_sshkey_name, user_sshkey_file, group_name, access_level):
group_id = ''
arguments = {"name": user_name,
"username": user_username,
"email": user_email}
if group_name is not None:
if self.existsGroup(group_name):
group_id = self.getGroupId(group_name)
if self.existsUser(user_username):
self.updateUser(group_id, user_sshkey_name, user_sshkey_file, access_level, arguments)
else:
if self._module.check_mode:
self._module.exit_json(changed=True)
self.createUser(group_id, user_password, user_sshkey_name, user_sshkey_file, access_level, arguments)
def createUser(self, group_id, user_password, user_sshkey_name, user_sshkey_file, access_level, arguments):
user_changed = False
# Create the user
user_username = arguments['username']
user_name = arguments['name']
user_email = arguments['email']
if self._gitlab.createuser(password=user_password, **arguments):
user_id = self.getUserId(user_username)
if self._gitlab.addsshkeyuser(user_id=user_id, title=user_sshkey_name, key=user_sshkey_file):
user_changed = True
# Add the user to the group if group_id is not empty
if group_id != '':
if self.addToGroup(group_id, user_id, access_level):
user_changed = True
user_changed = True
# Exit with change to true or false
if user_changed:
self._module.exit_json(changed=True, result="Created the user")
else:
self._module.exit_json(changed=False)
def deleteUser(self, user_username):
user_id = self.getUserId(user_username)
if self._gitlab.deleteuser(user_id):
self._module.exit_json(changed=True, result="Successfully deleted user %s" % user_username)
else:
self._module.exit_json(changed=False, result="User %s already deleted or something went wrong" % user_username)
def existsGroup(self, group_name):
for group in self._gitlab.getall(self._gitlab.getgroups):
if group['name'] == group_name:
return True
return False
def existsUser(self, username):
found_user = self._gitlab.getusers(search=username)
for user in found_user:
if user['id'] != '':
return True
return False
def getGroupId(self, group_name):
for group in self._gitlab.getall(self._gitlab.getgroups):
if group['name'] == group_name:
return group['id']
def getUserId(self, username):
found_user = self._gitlab.getusers(search=username)
for user in found_user:
if user['id'] != '':
return user['id']
def updateUser(self, group_id, user_sshkey_name, user_sshkey_file, access_level, arguments):
user_changed = False
user_username = arguments['username']
user_id = self.getUserId(user_username)
user_data = self._gitlab.getuser(user_id=user_id)
# Lets check if we need to update the user
for arg_key, arg_value in arguments.items():
if user_data[arg_key] != arg_value:
user_changed = True
if user_changed:
if self._module.check_mode:
self._module.exit_json(changed=True)
self._gitlab.edituser(user_id=user_id, **arguments)
user_changed = True
if self._module.check_mode or self._gitlab.addsshkeyuser(user_id=user_id, title=user_sshkey_name, key=user_sshkey_file):
user_changed = True
if group_id != '':
if self._module.check_mode or self.addToGroup(group_id, user_id, access_level):
user_changed = True
if user_changed:
self._module.exit_json(changed=True, result="The user %s is updated" % user_username)
else:
self._module.exit_json(changed=False, result="The user %s is already up2date" % user_username)
def main():
global user_id
module = AnsibleModule(
argument_spec=dict(
server_url=dict(required=True),
validate_certs=dict(required=False, default=True, type=bool, aliases=['verify_ssl']),
login_user=dict(required=False, no_log=True),
login_password=dict(required=False, no_log=True),
login_token=dict(required=False, no_log=True),
name=dict(required=True),
username=dict(required=True),
password=dict(required=True),
email=dict(required=True),
sshkey_name=dict(required=False),
sshkey_file=dict(required=False),
group=dict(required=False),
access_level=dict(required=False, choices=["guest", "reporter", "developer", "master", "owner"]),
state=dict(default="present", choices=["present", "absent"]),
),
supports_check_mode=True
)
if not HAS_GITLAB_PACKAGE:
module.fail_json(msg="Missing required gitlab module (check docs or install with: pip install pyapi-gitlab")
server_url = module.params['server_url']
verify_ssl = module.params['validate_certs']
login_user = module.params['login_user']
login_password = module.params['login_password']
login_token = module.params['login_token']
user_name = module.params['name']
user_username = module.params['username']
user_password = module.params['password']
user_email = module.params['email']
user_sshkey_name = module.params['sshkey_name']
user_sshkey_file = module.params['sshkey_file']
group_name = module.params['group']
access_level = module.params['access_level']
state = module.params['state']
# We need both login_user and login_password or login_token, otherwise we fail.
if login_user is not None and login_password is not None:
use_credentials = True
elif login_token is not None:
use_credentials = False
else:
module.fail_json(msg="No login credentials are given. Use login_user with login_password, or login_token")
# Check if vars are none
if user_sshkey_file is not None and user_sshkey_name is not None:
use_sshkey = True
else:
use_sshkey = False
if group_name is not None and access_level is not None:
add_to_group = True
group_name = group_name.lower()
else:
add_to_group = False
user_username = user_username.lower()
# Lets make an connection to the Gitlab server_url, with either login_user and login_password
# or with login_token
try:
if use_credentials:
git = gitlab.Gitlab(host=server_url)
git.login(user=login_user, password=login_password)
else:
git = gitlab.Gitlab(server_url, token=login_token, verify_ssl=verify_ssl)
except Exception, e:
module.fail_json(msg="Failed to connect to Gitlab server: %s " % e)
# Validate if group exists and take action based on "state"
user = GitLabUser(module, git)
# Check if user exists, if not exists and state = absent, we exit nicely.
if not user.existsUser(user_username) and state == "absent":
module.exit_json(changed=False, result="User already deleted or does not exists")
else:
# User exists,
if state == "absent":
user.deleteUser(user_username)
else:
user.createOrUpdateUser(user_name, user_username, user_password, user_email, user_sshkey_name, user_sshkey_file, group_name, access_level)
from ansible.module_utils.basic import *
if __name__ == '__main__':
main()

0
system/cronvar.py Executable file → Normal file
View file

0
system/crypttab.py Executable file → Normal file
View file

View file

@ -328,14 +328,6 @@ def main():
timeout = module.params['timeout'] timeout = module.params['timeout']
interface = module.params['interface'] interface = module.params['interface']
## Check for firewalld running
try:
if fw.connected == False:
module.fail_json(msg='firewalld service must be running')
except AttributeError:
module.fail_json(msg="firewalld connection can't be established,\
version likely too old. Requires firewalld >= 2.0.11")
modification_count = 0 modification_count = 0
if service != None: if service != None:
modification_count += 1 modification_count += 1

2
system/svc.py Normal file → Executable file
View file

@ -249,6 +249,8 @@ def main():
supports_check_mode=True, supports_check_mode=True,
) )
module.run_command_environ_update = dict(LANG='C', LC_ALL='C', LC_MESSAGES='C', LC_CTYPE='C')
state = module.params['state'] state = module.params['state']
enabled = module.params['enabled'] enabled = module.params['enabled']
downed = module.params['downed'] downed = module.params['downed']

View file

@ -212,6 +212,7 @@ $action=Get-Attr $params "action" "";
$misArg = '' $misArg = ''
# Check the arguments # Check the arguments
if ($enable -ne $null) { if ($enable -ne $null) {
$enable=ConvertTo-Bool $enable;
if ($enable -eq $true) { if ($enable -eq $true) {
$fwsettings.Add("Enabled", "yes"); $fwsettings.Add("Enabled", "yes");
} elseif ($enable -eq $false) { } elseif ($enable -eq $false) {

View file

@ -114,10 +114,11 @@ EXAMPLES = '''
action: win_firewall_rule action: win_firewall_rule
args: args:
name: smtp name: smtp
enabled: yes enable: yes
state: present state: present
localport: 25 localport: 25
action: allow action: allow
direction: In
protocol: TCP protocol: TCP
''' '''