├── .gitignore ├── README.md ├── __init__.py ├── ansible_cloudstack_utils.py ├── cloudstack-routers.py ├── cloudstack.ini.origin ├── cloudstack.py ├── cs_account.py ├── cs_affinitygroup.py ├── cs_cluster.py ├── cs_configuration.py ├── cs_domain.py ├── cs_facts.py ├── cs_firewall.py ├── cs_instance.py ├── cs_instance_facts.py ├── cs_instancegroup.py ├── cs_ip_address.py ├── cs_iso.py ├── cs_loadbalancer_rule.py ├── cs_loadbalancer_rule_member.py ├── cs_network.py ├── cs_nic.py ├── cs_pod.py ├── cs_portforward.py ├── cs_project.py ├── cs_resourcelimit.py ├── cs_router.py ├── cs_securitygroup.py ├── cs_securitygroup_rule.py ├── cs_snapshot_policy.py ├── cs_sshkeypair.py ├── cs_staticnat.py ├── cs_template.py ├── cs_user.py ├── cs_vmsnapshot.py ├── cs_volume.py ├── cs_vpc.py ├── cs_zone.py ├── cs_zone_facts.py ├── helpers └── sync.sh └── tests ├── Makefile ├── ansible.cfg ├── cloudstack.yml ├── inventory └── roles ├── test_cs_account ├── meta │ └── main.yml └── tasks │ └── main.yml ├── test_cs_affinitygroup ├── meta │ └── main.yml └── tasks │ └── main.yml ├── test_cs_cluster ├── meta │ └── main.yml └── tasks │ └── main.yml ├── test_cs_common └── defaults │ └── main.yml ├── test_cs_configuration ├── defaults │ └── main.yml ├── meta │ └── main.yml └── tasks │ ├── account.yml │ ├── cluster.yml │ ├── main.yml │ ├── storage.yml │ └── zone.yml ├── test_cs_domain ├── meta │ └── main.yml └── tasks │ └── main.yml ├── test_cs_firewall ├── defaults │ └── main.yml ├── meta │ └── main.yml └── tasks │ └── main.yml ├── test_cs_host ├── defaults │ └── main.yml ├── meta │ └── main.yml └── tasks │ └── main.yml ├── test_cs_instance ├── defaults │ └── main.yml ├── meta │ └── main.yml └── tasks │ ├── absent.yml │ ├── absent_display_name.yml │ ├── cleanup.yml │ ├── main.yml │ ├── present.yml │ ├── present_display_name.yml │ ├── setup.yml │ └── tags.yml ├── test_cs_instance_facts ├── defaults │ └── main.yml ├── meta │ └── main.yml └── tasks │ └── main.yml ├── test_cs_instancegroup ├── meta │ └── main.yml └── tasks │ └── main.yml ├── test_cs_iso ├── meta │ └── main.yml └── tasks │ └── main.yml ├── test_cs_loadbalancer_rule ├── defaults │ └── main.yml ├── meta │ └── main.yml └── tasks │ └── main.yml ├── test_cs_pod ├── meta │ └── main.yml └── tasks │ └── main.yml ├── test_cs_portforward ├── defaults │ └── main.yml ├── meta │ └── main.yml └── tasks │ └── main.yml ├── test_cs_project ├── meta │ └── main.yml └── tasks │ └── main.yml ├── test_cs_resourcelimit ├── meta │ └── main.yml └── tasks │ ├── cpu.yml │ ├── instance.yml │ └── main.yml ├── test_cs_securitygroup ├── meta │ └── main.yml └── tasks │ └── main.yml ├── test_cs_securitygroup_rule ├── meta │ └── main.yml └── tasks │ ├── absent.yml │ ├── cleanup.yml │ ├── main.yml │ ├── present.yml │ └── setup.yml ├── test_cs_sshkeypair ├── meta │ └── main.yml └── tasks │ └── main.yml ├── test_cs_user ├── meta │ └── main.yml └── tasks │ └── main.yml ├── test_cs_vmsnapshot ├── defaults │ └── main.yml ├── meta │ └── main.yml └── tasks │ └── main.yml ├── test_cs_volume ├── defaults │ └── main.yml ├── meta │ └── main.yml └── tasks │ └── main.yml └── test_cs_zone ├── defaults └── main.yml ├── meta └── main.yml └── tasks └── main.yml /.gitignore: -------------------------------------------------------------------------------- 1 | cloudstack.ini 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Ansible CloudStack Modules 2 | ========================== 3 | 4 | Manages resources on Apache CloudStack, Citrix CloudPlatform and Exoscale. 5 | 6 | **NOTE: Since Ansible 2.1 was released, I don't see any more need to maintain this repo for Ansible 1.9. I mark this repo as deprecated with the next Ansible major release 2.2** 7 | 8 | 9 | Difference of CloudStack modules in ansible-modules-extras and this repo? 10 | -------------------------------------------------------------------------- 11 | This repo has been made for simple using CloudStack modules while ansible 2.0 is not yet released. 12 | I maintain the CloudStack modules in *ansible-modules-extras* as well and I am in charge to keep them in sync. 13 | 14 | **This means they are 100% compatible**. 15 | 16 | If you like to contribute, it would be fine to make PRs here first. After acceptance you should also make a PR to ansible-modules-extras (or let me know if I should do it.) 17 | 18 | AnsibleCloudStack (called utils) in upstream Ansible is located in *ansible* repo [here](https://github.com/ansible/ansible/blob/devel/lib/ansible/module_utils/cloudstack.py) and will be imported in *ansible-modules-extras* (once ansible 2.0 is released). 19 | 20 | I also sync changes between the utils in upstream ansible and *ansible_cloudstack_utils.py*, but unfortunately I didn't find a way to import *ansible_cloudstack_utils.py* in the module here. 21 | 22 | (If you know how this would be possible I would be more then happy). 23 | 24 | That is why I just copied it into the modules. Same here, if you make changes to utils make it in *ansible_cloudstack_utils.py* and I will spread it to all modules (I have my tools ready for doing this). 25 | 26 | 27 | Requirements 28 | ------------ 29 | Uses Exosclale's python cs library: `sudo pip install cs` 30 | 31 | Note: You can pass the API credentials by module arguments `api_url`, `api_key` and `api_secret` or even more comfortable by `cloudstack.ini`. Please see the https://github.com/exoscale/cs for more information. 32 | 33 | 34 | Examples 35 | -------- 36 | 37 | ~~~yaml 38 | # Upload an ISO (Note: this should have CloudStack SSH PubKey handling installed): 39 | - local_action: 40 | module: cs_iso: 41 | name: Debian 7 64-bit 42 | url: http://iso.example.com/debian-cd/7.7.0/amd64/iso-cd/debian-7.7.0-amd64-netinst.iso 43 | os_type: Debian GNU/Linux 7(64-bit) 44 | checksum: 0b31bccccb048d20b551f70830bb7ad0 45 | 46 | 47 | # Upload your SSH public key 48 | - local_action: 49 | module: cs_sshkeypair 50 | name: john@example.com 51 | public_key: '{{ lookup('file', '~/.ssh/id_rsa.pub') }}' 52 | 53 | 54 | # Ensure security group default exists 55 | - local_action: 56 | module: cs_securitygroup 57 | name: default 58 | 59 | 60 | # Add inbound tcp rules to security group default 61 | - local_action: 62 | module: cs_securitygroup_rule 63 | security_group: default 64 | start_port: '{{ item }}' 65 | end_port: '{{ item }}' 66 | with_items: 67 | - 80 68 | - 8089 69 | 70 | 71 | # Create a virtual machine on CloudStack 72 | - local_action: 73 | module: cs_instance 74 | name: web-vm-1 75 | iso: Linux Debian 7 64-bit 76 | hypervisor: VMware 77 | service_offering: Tiny 78 | disk_offering: Performance 79 | disk_size: 20 80 | ssh_key: john@example.com 81 | 82 | 83 | # Make a snapshot 84 | - local_action: 85 | module: cs_vmsnapshot 86 | name: Snapshot before upgrade 87 | vm: web-vm-1 88 | snapshot_memory: yes 89 | 90 | 91 | # Change service offering on existing VM 92 | - local_action: 93 | module: cs_instance 94 | name: web-vm-1 95 | service_offering: Medium 96 | 97 | 98 | # Stop a virtual machine 99 | - local_action: 100 | module: cs_instance 101 | name: web-vm-1 102 | state: stopped 103 | 104 | 105 | # Start a virtual machine 106 | - local_action: cs_instance name=web-vm-1 state=started 107 | 108 | 109 | # Remove a virtual machine on CloudStack 110 | - local_action: cs_instance name=web-vm-1 state=absent 111 | ~~~ 112 | -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/resmo/ansible-cloudstack/01929eccd1688584a17ef468b8624bbdfb571654/__init__.py -------------------------------------------------------------------------------- /ansible_cloudstack_utils.py: -------------------------------------------------------------------------------- 1 | import os 2 | import time 3 | from ansible.module_utils.six import iteritems 4 | 5 | try: 6 | from cs import CloudStack, CloudStackException, read_config 7 | has_lib_cs = True 8 | except ImportError: 9 | has_lib_cs = False 10 | 11 | CS_HYPERVISORS = [ 12 | "KVM", "kvm", 13 | "VMware", "vmware", 14 | "BareMetal", "baremetal", 15 | "XenServer", "xenserver", 16 | "LXC", "lxc", 17 | "HyperV", "hyperv", 18 | "UCS", "ucs", 19 | "OVM", "ovm", 20 | "Simulator", "simulator", 21 | ] 22 | 23 | def cs_argument_spec(): 24 | return dict( 25 | api_key = dict(default=None), 26 | api_secret = dict(default=None, no_log=True), 27 | api_url = dict(default=None), 28 | api_http_method = dict(choices=['get', 'post'], default='get'), 29 | api_timeout = dict(type='int', default=10), 30 | api_region = dict(default='cloudstack'), 31 | ) 32 | 33 | def cs_required_together(): 34 | return [['api_key', 'api_secret', 'api_url']] 35 | 36 | class AnsibleCloudStack(object): 37 | 38 | def __init__(self, module): 39 | if not has_lib_cs: 40 | module.fail_json(msg="python library cs required: pip install cs") 41 | 42 | self.result = { 43 | 'changed': False, 44 | 'diff' : { 45 | 'before': dict(), 46 | 'after': dict() 47 | } 48 | } 49 | 50 | # Common returns, will be merged with self.returns 51 | # search_for_key: replace_with_key 52 | self.common_returns = { 53 | 'id': 'id', 54 | 'name': 'name', 55 | 'created': 'created', 56 | 'zonename': 'zone', 57 | 'state': 'state', 58 | 'project': 'project', 59 | 'account': 'account', 60 | 'domain': 'domain', 61 | 'displaytext': 'display_text', 62 | 'displayname': 'display_name', 63 | 'description': 'description', 64 | } 65 | 66 | # Init returns dict for use in subclasses 67 | self.returns = {} 68 | # these values will be casted to int 69 | self.returns_to_int = {} 70 | # these keys will be compared case sensitive in self.has_changed() 71 | self.case_sensitive_keys = [ 72 | 'id', 73 | 'displaytext', 74 | 'displayname', 75 | 'description', 76 | ] 77 | 78 | self.module = module 79 | self._connect() 80 | 81 | # Helper for VPCs 82 | self._vpc_networks_ids = None 83 | 84 | self.domain = None 85 | self.account = None 86 | self.project = None 87 | self.ip_address = None 88 | self.network = None 89 | self.vpc = None 90 | self.zone = None 91 | self.vm = None 92 | self.vm_default_nic = None 93 | self.os_type = None 94 | self.hypervisor = None 95 | self.capabilities = None 96 | 97 | 98 | def _connect(self): 99 | api_key = self.module.params.get('api_key') 100 | api_secret = self.module.params.get('api_secret') 101 | api_url = self.module.params.get('api_url') 102 | api_http_method = self.module.params.get('api_http_method') 103 | api_timeout = self.module.params.get('api_timeout') 104 | 105 | if api_key and api_secret and api_url: 106 | self.cs = CloudStack( 107 | endpoint=api_url, 108 | key=api_key, 109 | secret=api_secret, 110 | timeout=api_timeout, 111 | method=api_http_method 112 | ) 113 | else: 114 | api_region = self.module.params.get('api_region', 'cloudstack') 115 | self.cs = CloudStack(**read_config(api_region)) 116 | 117 | 118 | def get_or_fallback(self, key=None, fallback_key=None): 119 | value = self.module.params.get(key) 120 | if not value: 121 | value = self.module.params.get(fallback_key) 122 | return value 123 | 124 | 125 | # TODO: for backward compatibility only, remove if not used anymore 126 | def _has_changed(self, want_dict, current_dict, only_keys=None): 127 | return self.has_changed(want_dict=want_dict, current_dict=current_dict, only_keys=only_keys) 128 | 129 | 130 | def has_changed(self, want_dict, current_dict, only_keys=None): 131 | result = False 132 | for key, value in want_dict.iteritems(): 133 | 134 | # Optionally limit by a list of keys 135 | if only_keys and key not in only_keys: 136 | continue 137 | 138 | # Skip None values 139 | if value is None: 140 | continue 141 | 142 | if key in current_dict: 143 | if isinstance(value, (int, float, long, complex)): 144 | # ensure we compare the same type 145 | if isinstance(value, int): 146 | current_dict[key] = int(current_dict[key]) 147 | elif isinstance(value, float): 148 | current_dict[key] = float(current_dict[key]) 149 | elif isinstance(value, long): 150 | current_dict[key] = long(current_dict[key]) 151 | elif isinstance(value, complex): 152 | current_dict[key] = complex(current_dict[key]) 153 | 154 | if value != current_dict[key]: 155 | self.result['diff']['before'][key] = current_dict[key] 156 | self.result['diff']['after'][key] = value 157 | result = True 158 | else: 159 | if self.case_sensitive_keys and key in self.case_sensitive_keys: 160 | if value != current_dict[key].encode('utf-8'): 161 | self.result['diff']['before'][key] = current_dict[key].encode('utf-8') 162 | self.result['diff']['after'][key] = value 163 | result = True 164 | 165 | # Test for diff in case insensitive way 166 | elif value.lower() != current_dict[key].encode('utf-8').lower(): 167 | self.result['diff']['before'][key] = current_dict[key].encode('utf-8') 168 | self.result['diff']['after'][key] = value 169 | result = True 170 | else: 171 | self.result['diff']['before'][key] = None 172 | self.result['diff']['after'][key] = value 173 | result = True 174 | return result 175 | 176 | 177 | def _get_by_key(self, key=None, my_dict=None): 178 | if my_dict is None: 179 | my_dict = {} 180 | if key: 181 | if key in my_dict: 182 | return my_dict[key] 183 | self.module.fail_json(msg="Something went wrong: %s not found" % key) 184 | return my_dict 185 | 186 | 187 | def get_vpc(self, key=None): 188 | """Return a VPC dictionary or the value of given key of.""" 189 | if self.vpc: 190 | return self._get_by_key(key, self.vpc) 191 | 192 | vpc = self.module.params.get('vpc') 193 | if not vpc: 194 | vpc = os.environ.get('CLOUDSTACK_VPC') 195 | if not vpc: 196 | return None 197 | 198 | args = { 199 | 'account': self.get_account(key='name'), 200 | 'domainid': self.get_domain(key='id'), 201 | 'projectid': self.get_project(key='id'), 202 | 'zoneid': self.get_zone(key='id'), 203 | } 204 | vpcs = self.cs.listVPCs(**args) 205 | if not vpcs: 206 | self.module.fail_json(msg="No VPCs available.") 207 | 208 | for v in vpcs['vpc']: 209 | if vpc in [v['displaytext'], v['name'], v['id']]: 210 | self.vpc = v 211 | return self._get_by_key(key, self.vpc) 212 | self.module.fail_json(msg="VPC '%s' not found" % vpc) 213 | 214 | 215 | def is_vm_in_vpc(self, vm): 216 | for n in vm.get('nic'): 217 | if n.get('isdefault', False): 218 | return self.is_vpc_network(network_id=n['networkid']) 219 | self.module.fail_json(msg="VM has no default nic") 220 | 221 | 222 | def is_vpc_network(self, network_id): 223 | """Returns True if network is in VPC.""" 224 | # This is an efficient way to query a lot of networks at a time 225 | if self._vpc_networks_ids is None: 226 | args = { 227 | 'account': self.get_account(key='name'), 228 | 'domainid': self.get_domain(key='id'), 229 | 'projectid': self.get_project(key='id'), 230 | 'zoneid': self.get_zone(key='id'), 231 | } 232 | vpcs = self.cs.listVPCs(**args) 233 | self._vpc_networks_ids = [] 234 | if vpcs: 235 | for vpc in vpcs['vpc']: 236 | for n in vpc.get('network',[]): 237 | self._vpc_networks_ids.append(n['id']) 238 | return network_id in self._vpc_networks_ids 239 | 240 | 241 | def get_network(self, key=None): 242 | """Return a network dictionary or the value of given key of.""" 243 | if self.network: 244 | return self._get_by_key(key, self.network) 245 | 246 | network = self.module.params.get('network') 247 | if not network: 248 | return None 249 | 250 | args = { 251 | 'account': self.get_account(key='name'), 252 | 'domainid': self.get_domain(key='id'), 253 | 'projectid': self.get_project(key='id'), 254 | 'zoneid': self.get_zone(key='id'), 255 | 'vpcid': self.get_vpc(key='id') 256 | } 257 | networks = self.cs.listNetworks(**args) 258 | if not networks: 259 | self.module.fail_json(msg="No networks available.") 260 | 261 | for n in networks['network']: 262 | # ignore any VPC network if vpc param is not given 263 | if 'vpcid' in n and not self.get_vpc(key='id'): 264 | continue 265 | if network in [n['displaytext'], n['name'], n['id']]: 266 | self.network = n 267 | return self._get_by_key(key, self.network) 268 | self.module.fail_json(msg="Network '%s' not found" % network) 269 | 270 | 271 | def get_project(self, key=None): 272 | if self.project: 273 | return self._get_by_key(key, self.project) 274 | 275 | project = self.module.params.get('project') 276 | if not project: 277 | project = os.environ.get('CLOUDSTACK_PROJECT') 278 | if not project: 279 | return None 280 | args = {} 281 | args['account'] = self.get_account(key='name') 282 | args['domainid'] = self.get_domain(key='id') 283 | projects = self.cs.listProjects(**args) 284 | if projects: 285 | for p in projects['project']: 286 | if project.lower() in [ p['name'].lower(), p['id'] ]: 287 | self.project = p 288 | return self._get_by_key(key, self.project) 289 | self.module.fail_json(msg="project '%s' not found" % project) 290 | 291 | 292 | def get_ip_address(self, key=None): 293 | if self.ip_address: 294 | return self._get_by_key(key, self.ip_address) 295 | 296 | ip_address = self.module.params.get('ip_address') 297 | if not ip_address: 298 | self.module.fail_json(msg="IP address param 'ip_address' is required") 299 | 300 | args = { 301 | 'ipaddress': ip_address, 302 | 'account': self.get_account(key='name'), 303 | 'domainid': self.get_domain(key='id'), 304 | 'projectid': self.get_project(key='id'), 305 | 'vpcid': self.get_vpc(key='id'), 306 | } 307 | ip_addresses = self.cs.listPublicIpAddresses(**args) 308 | 309 | if not ip_addresses: 310 | self.module.fail_json(msg="IP address '%s' not found" % args['ipaddress']) 311 | 312 | self.ip_address = ip_addresses['publicipaddress'][0] 313 | return self._get_by_key(key, self.ip_address) 314 | 315 | 316 | def get_vm_guest_ip(self): 317 | vm_guest_ip = self.module.params.get('vm_guest_ip') 318 | default_nic = self.get_vm_default_nic() 319 | 320 | if not vm_guest_ip: 321 | return default_nic['ipaddress'] 322 | 323 | for secondary_ip in default_nic['secondaryip']: 324 | if vm_guest_ip == secondary_ip['ipaddress']: 325 | return vm_guest_ip 326 | self.module.fail_json(msg="Secondary IP '%s' not assigned to VM" % vm_guest_ip) 327 | 328 | 329 | def get_vm_default_nic(self): 330 | if self.vm_default_nic: 331 | return self.vm_default_nic 332 | 333 | nics = self.cs.listNics(virtualmachineid=self.get_vm(key='id')) 334 | if nics: 335 | for n in nics['nic']: 336 | if n['isdefault']: 337 | self.vm_default_nic = n 338 | return self.vm_default_nic 339 | self.module.fail_json(msg="No default IP address of VM '%s' found" % self.module.params.get('vm')) 340 | 341 | 342 | def get_vm(self, key=None): 343 | if self.vm: 344 | return self._get_by_key(key, self.vm) 345 | 346 | vm = self.module.params.get('vm') 347 | if not vm: 348 | self.module.fail_json(msg="Virtual machine param 'vm' is required") 349 | 350 | vpc_id = self.get_vpc(key='id') 351 | 352 | args = { 353 | 'account': self.get_account(key='name'), 354 | 'domainid': self.get_domain(key='id'), 355 | 'projectid': self.get_project(key='id'), 356 | 'zoneid': self.get_zone(key='id'), 357 | 'vpcid': vpc_id, 358 | } 359 | vms = self.cs.listVirtualMachines(**args) 360 | if vms: 361 | for v in vms['virtualmachine']: 362 | # Due the limitation of the API, there is no easy way (yet) to get only those VMs 363 | # not belonging to a VPC. 364 | if not vpc_id and self.is_vm_in_vpc(vm=v): 365 | continue 366 | if vm.lower() in [ v['name'].lower(), v['displayname'].lower(), v['id'] ]: 367 | self.vm = v 368 | return self._get_by_key(key, self.vm) 369 | self.module.fail_json(msg="Virtual machine '%s' not found" % vm) 370 | 371 | 372 | def get_zone(self, key=None): 373 | if self.zone: 374 | return self._get_by_key(key, self.zone) 375 | 376 | zone = self.module.params.get('zone') 377 | if not zone: 378 | zone = os.environ.get('CLOUDSTACK_ZONE') 379 | zones = self.cs.listZones() 380 | 381 | # use the first zone if no zone param given 382 | if not zone: 383 | self.zone = zones['zone'][0] 384 | return self._get_by_key(key, self.zone) 385 | 386 | if zones: 387 | for z in zones['zone']: 388 | if zone.lower() in [ z['name'].lower(), z['id'] ]: 389 | self.zone = z 390 | return self._get_by_key(key, self.zone) 391 | self.module.fail_json(msg="zone '%s' not found" % zone) 392 | 393 | 394 | def get_os_type(self, key=None): 395 | if self.os_type: 396 | return self._get_by_key(key, self.zone) 397 | 398 | os_type = self.module.params.get('os_type') 399 | if not os_type: 400 | return None 401 | 402 | os_types = self.cs.listOsTypes() 403 | if os_types: 404 | for o in os_types['ostype']: 405 | if os_type in [ o['description'], o['id'] ]: 406 | self.os_type = o 407 | return self._get_by_key(key, self.os_type) 408 | self.module.fail_json(msg="OS type '%s' not found" % os_type) 409 | 410 | 411 | def get_hypervisor(self): 412 | if self.hypervisor: 413 | return self.hypervisor 414 | 415 | hypervisor = self.module.params.get('hypervisor') 416 | hypervisors = self.cs.listHypervisors() 417 | 418 | # use the first hypervisor if no hypervisor param given 419 | if not hypervisor: 420 | self.hypervisor = hypervisors['hypervisor'][0]['name'] 421 | return self.hypervisor 422 | 423 | for h in hypervisors['hypervisor']: 424 | if hypervisor.lower() == h['name'].lower(): 425 | self.hypervisor = h['name'] 426 | return self.hypervisor 427 | self.module.fail_json(msg="Hypervisor '%s' not found" % hypervisor) 428 | 429 | 430 | def get_account(self, key=None): 431 | if self.account: 432 | return self._get_by_key(key, self.account) 433 | 434 | account = self.module.params.get('account') 435 | if not account: 436 | account = os.environ.get('CLOUDSTACK_ACCOUNT') 437 | if not account: 438 | return None 439 | 440 | domain = self.module.params.get('domain') 441 | if not domain: 442 | self.module.fail_json(msg="Account must be specified with Domain") 443 | 444 | args = {} 445 | args['name'] = account 446 | args['domainid'] = self.get_domain(key='id') 447 | args['listall'] = True 448 | accounts = self.cs.listAccounts(**args) 449 | if accounts: 450 | self.account = accounts['account'][0] 451 | return self._get_by_key(key, self.account) 452 | self.module.fail_json(msg="Account '%s' not found" % account) 453 | 454 | 455 | def get_domain(self, key=None): 456 | if self.domain: 457 | return self._get_by_key(key, self.domain) 458 | 459 | domain = self.module.params.get('domain') 460 | if not domain: 461 | domain = os.environ.get('CLOUDSTACK_DOMAIN') 462 | if not domain: 463 | return None 464 | 465 | args = {} 466 | args['listall'] = True 467 | domains = self.cs.listDomains(**args) 468 | if domains: 469 | for d in domains['domain']: 470 | if d['path'].lower() in [ domain.lower(), "root/" + domain.lower(), "root" + domain.lower() ]: 471 | self.domain = d 472 | return self._get_by_key(key, self.domain) 473 | self.module.fail_json(msg="Domain '%s' not found" % domain) 474 | 475 | 476 | def get_tags(self, resource=None): 477 | existing_tags = [] 478 | for tag in resource.get('tags',[]): 479 | existing_tags.append({'key': tag['key'], 'value': tag['value']}) 480 | return existing_tags 481 | 482 | 483 | def _process_tags(self, resource, resource_type, tags, operation="create"): 484 | if tags: 485 | self.result['changed'] = True 486 | if not self.module.check_mode: 487 | args = {} 488 | args['resourceids'] = resource['id'] 489 | args['resourcetype'] = resource_type 490 | args['tags'] = tags 491 | if operation == "create": 492 | response = self.cs.createTags(**args) 493 | else: 494 | response = self.cs.deleteTags(**args) 495 | self.poll_job(response) 496 | 497 | 498 | def _tags_that_should_exist_or_be_updated(self, resource, tags): 499 | existing_tags = self.get_tags(resource) 500 | return [tag for tag in tags if tag not in existing_tags] 501 | 502 | 503 | def _tags_that_should_not_exist(self, resource, tags): 504 | existing_tags = self.get_tags(resource) 505 | return [tag for tag in existing_tags if tag not in tags] 506 | 507 | 508 | def ensure_tags(self, resource, resource_type=None): 509 | if not resource_type or not resource: 510 | self.module.fail_json(msg="Error: Missing resource or resource_type for tags.") 511 | 512 | if 'tags' in resource: 513 | tags = self.module.params.get('tags') 514 | if tags is not None: 515 | self._process_tags(resource, resource_type, self._tags_that_should_not_exist(resource, tags), operation="delete") 516 | self._process_tags(resource, resource_type, self._tags_that_should_exist_or_be_updated(resource, tags)) 517 | resource['tags'] = tags 518 | return resource 519 | 520 | 521 | def get_capabilities(self, key=None): 522 | if self.capabilities: 523 | return self._get_by_key(key, self.capabilities) 524 | capabilities = self.cs.listCapabilities() 525 | self.capabilities = capabilities['capability'] 526 | return self._get_by_key(key, self.capabilities) 527 | 528 | 529 | # TODO: for backward compatibility only, remove if not used anymore 530 | def _poll_job(self, job=None, key=None): 531 | return self.poll_job(job=job, key=key) 532 | 533 | 534 | def poll_job(self, job=None, key=None): 535 | if 'jobid' in job: 536 | while True: 537 | res = self.cs.queryAsyncJobResult(jobid=job['jobid']) 538 | if res['jobstatus'] != 0 and 'jobresult' in res: 539 | if 'errortext' in res['jobresult']: 540 | self.module.fail_json(msg="Failed: '%s'" % res['jobresult']['errortext']) 541 | if key and key in res['jobresult']: 542 | job = res['jobresult'][key] 543 | break 544 | time.sleep(2) 545 | return job 546 | 547 | 548 | def get_result(self, resource): 549 | if resource: 550 | returns = self.common_returns.copy() 551 | returns.update(self.returns) 552 | for search_key, return_key in returns.iteritems(): 553 | if search_key in resource: 554 | self.result[return_key] = resource[search_key] 555 | 556 | # Bad bad API does not always return int when it should. 557 | for search_key, return_key in self.returns_to_int.iteritems(): 558 | if search_key in resource: 559 | self.result[return_key] = int(resource[search_key]) 560 | 561 | # Special handling for tags 562 | if 'tags' in resource: 563 | self.result['tags'] = [] 564 | for tag in resource['tags']: 565 | result_tag = {} 566 | result_tag['key'] = tag['key'] 567 | result_tag['value'] = tag['value'] 568 | self.result['tags'].append(result_tag) 569 | return self.result 570 | -------------------------------------------------------------------------------- /cloudstack-routers.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # (c) 2015, René Moser 5 | # 6 | # This file is part of Ansible, 7 | # 8 | # Ansible is free software: you can redistribute it and/or modify 9 | # it under the terms of the GNU General Public License as published by 10 | # the Free Software Foundation, either version 3 of the License, or 11 | # (at your option) any later version. 12 | # 13 | # Ansible is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU General Public License 19 | # along with Ansible. If not, see . 20 | 21 | ###################################################################### 22 | 23 | """ 24 | Ansible CloudStack router inventory script. 25 | ============================================= 26 | 27 | Generates Ansible inventory of routers from CloudStack. Configuration is read from 28 | 'cloudstack.ini'. 29 | 30 | When run against a specific router, this script returns the following attributes 31 | based on the data obtained from CloudStack API: 32 | 33 | { 34 | "zone": "ZUERICH", 35 | "default_ip": "1.2.3.4", 36 | "nic": [ 37 | { 38 | "ip": "10.101.66.1", 39 | "mac": "02:00:46:28:00:02", 40 | "netmask": "255.255.255.0" 41 | }, 42 | { 43 | "ip": "10.100.9.134", 44 | "mac": "02:00:00:38:06:4c", 45 | "netmask": "255.255.255.0" 46 | }, 47 | { 48 | "ip": "1.2.3.4", 49 | "mac": "06:0c:fc:00:35:a1", 50 | "netmask": "255.255.255.128" 51 | } 52 | ], 53 | "ansible_ssh_host": "10.100.9.134", 54 | "state": "Running", 55 | "role": "VIRTUAL_ROUTER", 56 | "service_offering": "System Offering for Software Router XLarge" 57 | } 58 | 59 | 60 | usage: cloudstack-routers.py [--list] [--host HOST] 61 | """ 62 | 63 | import os 64 | import sys 65 | import argparse 66 | 67 | try: 68 | import json 69 | except: 70 | import simplejson as json 71 | 72 | 73 | try: 74 | from cs import CloudStack, CloudStackException, read_config 75 | except ImportError: 76 | print >> sys.stderr, "Error: CloudStack library must be installed: pip install cs." 77 | sys.exit(1) 78 | 79 | 80 | class CloudStackInventory(object): 81 | def __init__(self): 82 | 83 | parser = argparse.ArgumentParser() 84 | parser.add_argument('--host') 85 | parser.add_argument('--list', action='store_true') 86 | 87 | options = parser.parse_args() 88 | try: 89 | self.cs = CloudStack(**read_config()) 90 | except CloudStackException, e: 91 | print >> sys.stderr, "Error: Could not connect to CloudStack API" 92 | 93 | if options.host: 94 | data = self.get_host(options.host) 95 | print json.dumps(data, indent=2) 96 | 97 | elif options.list: 98 | data = self.get_list() 99 | print json.dumps(data, indent=2) 100 | else: 101 | print >> sys.stderr, "usage: --list | --host " 102 | sys.exit(1) 103 | 104 | 105 | def add_group(self, data, group_name, router_name): 106 | if group_name not in data: 107 | data[group_name] = { 108 | 'hosts': [] 109 | } 110 | data[group_name]['hosts'].append(router_name) 111 | return data 112 | 113 | 114 | def get_host(self, name): 115 | routers = [] 116 | 117 | routers_projects = self.cs.listRouters(projectid=-1, listall=True) 118 | if routers_projects and 'router' in routers_projects: 119 | routers = routers + routers_projects['router'] 120 | 121 | routers_accounts = self.cs.listRouters(listall=True) 122 | if routers_accounts and 'router' in routers_accounts: 123 | routers = routers + routers_accounts['router'] 124 | 125 | data = {} 126 | for router in routers: 127 | router_name = router['name'] 128 | if name == router_name: 129 | data['zone'] = router['zonename'] 130 | if 'linklocalip' in router: 131 | data['ansible_ssh_host'] = router['linklocalip'] 132 | data['state'] = router['state'] 133 | data['redundant_state'] = router['redundantstate'] 134 | if 'account' in router: 135 | data['account'] = router['account'] 136 | if 'project' in router: 137 | data['project'] = router['project'] 138 | data['service_offering'] = router['serviceofferingname'] 139 | data['role'] = router['role'] 140 | data['nic'] = [] 141 | for nic in router['nic']: 142 | data['nic'].append({ 143 | 'ip': nic['ipaddress'], 144 | 'mac': nic['macaddress'], 145 | 'netmask': nic['netmask'], 146 | }) 147 | if nic['isdefault']: 148 | data['default_ip'] = nic['ipaddress'] 149 | break; 150 | return data 151 | 152 | 153 | def get_list(self): 154 | data = { 155 | 'all': { 156 | 'hosts': [], 157 | }, 158 | '_meta': { 159 | 'hostvars': {}, 160 | }, 161 | } 162 | 163 | routers = [] 164 | 165 | routers_projects = self.cs.listRouters(projectid=-1, listall=True) 166 | if routers_projects and 'router' in routers_projects: 167 | routers = routers + routers_projects['router'] 168 | 169 | routers_accounts = self.cs.listRouters(listall=True) 170 | if routers_accounts and 'router' in routers_accounts: 171 | routers = routers + routers_accounts['router'] 172 | 173 | for router in routers: 174 | if router['state'] != 'Running': 175 | continue 176 | router_name = router['name'] 177 | data['all']['hosts'].append(router_name) 178 | # Make a group per domain 179 | data = self.add_group(data, router['domain'], router_name) 180 | 181 | data['_meta']['hostvars'][router_name] = {} 182 | data['_meta']['hostvars'][router_name]['group'] = router['domain'] 183 | data['_meta']['hostvars'][router_name]['domain'] = router['domain'] 184 | if 'networkdomain' in router: 185 | data['_meta']['hostvars'][router_name]['networkdomain'] = router['networkdomain'] 186 | 187 | data['_meta']['hostvars'][router_name]['zone'] = router['zonename'] 188 | # Make a group per zone 189 | data = self.add_group(data, router['zonename'], router_name) 190 | 191 | if 'project' in router: 192 | data['_meta']['hostvars'][router_name]['project'] = router['project'] 193 | 194 | # Make a group per project 195 | data = self.add_group(data, router['project'], router_name) 196 | 197 | if 'account' in router: 198 | data['_meta']['hostvars'][router_name]['account'] = router['account'] 199 | 200 | # Make a group per account 201 | data = self.add_group(data, router['account'], router_name) 202 | 203 | data['_meta']['hostvars'][router_name]['ansible_ssh_host'] = router['linklocalip'] 204 | data['_meta']['hostvars'][router_name]['state'] = router['state'] 205 | if 'redundantstate' in router: 206 | data['_meta']['hostvars'][router_name]['redundant_state'] = router['redundantstate'] 207 | 208 | if router['redundantstate'] in [ 'MASTER', 'BACKUP' ]: 209 | data = self.add_group(data, 'redundant_routers', router_name) 210 | 211 | if router['redundantstate'] in [ 'MASTER' ]: 212 | data = self.add_group(data, 'redundant_master_routers', router_name) 213 | 214 | if router['redundantstate'] in [ 'BACKUP' ]: 215 | data = self.add_group(data, 'redundant_backup_routers', router_name) 216 | 217 | if router['redundantstate'] in [ 'UNKNOWN' ]: 218 | data = self.add_group(data, 'non_redundant_routers', router_name) 219 | 220 | data['_meta']['hostvars'][router_name]['service_offering'] = router['serviceofferingname'] 221 | data['_meta']['hostvars'][router_name]['nic'] = [] 222 | for nic in router['nic']: 223 | data['_meta']['hostvars'][router_name]['nic'].append({ 224 | 'ip': nic['ipaddress'], 225 | 'mac': nic['macaddress'], 226 | 'netmask': nic['netmask'], 227 | }) 228 | if nic['isdefault']: 229 | data['_meta']['hostvars'][router_name]['default_ip'] = nic['ipaddress'] 230 | return data 231 | 232 | 233 | if __name__ == '__main__': 234 | CloudStackInventory() 235 | -------------------------------------------------------------------------------- /cloudstack.ini.origin: -------------------------------------------------------------------------------- 1 | [cloudstack] 2 | #endpoint = https://api.exoscale.ch/compute 3 | endpoint = https://cloud.example.com/client/api 4 | key = cloudstack api key 5 | secret = cloudstack api secret 6 | -------------------------------------------------------------------------------- /cloudstack.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # (c) 2014, René Moser 5 | # 6 | # This file is part of Ansible, 7 | # 8 | # Ansible is free software: you can redistribute it and/or modify 9 | # it under the terms of the GNU General Public License as published by 10 | # the Free Software Foundation, either version 3 of the License, or 11 | # (at your option) any later version. 12 | # 13 | # Ansible is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU General Public License 19 | # along with Ansible. If not, see . 20 | 21 | ###################################################################### 22 | 23 | """ 24 | Ansible CloudStack external inventory script. 25 | ============================================= 26 | 27 | Generates Ansible inventory from CloudStack. Configuration is read from 28 | 'cloudstack.ini'. If you need to pass the project, write a simple wrapper 29 | script, e.g. project_cloudstack.sh: 30 | 31 | #!/bin/bash 32 | cloudstack.py --project $@ 33 | 34 | 35 | When run against a specific host, this script returns the following attributes 36 | based on the data obtained from CloudStack API: 37 | 38 | "web01": { 39 | "cpu_number": 2, 40 | "nic": [ 41 | { 42 | "ip": "10.102.76.98", 43 | "mac": "02:00:50:99:00:01", 44 | "type": "Isolated", 45 | "netmask": "255.255.255.0", 46 | "gateway": "10.102.76.1" 47 | }, 48 | { 49 | "ip": "10.102.138.63", 50 | "mac": "06:b7:5a:00:14:84", 51 | "type": "Shared", 52 | "netmask": "255.255.255.0", 53 | "gateway": "10.102.138.1" 54 | } 55 | ], 56 | "default_ip": "10.102.76.98", 57 | "zone": "ZUERICH", 58 | "created": "2014-07-02T07:53:50+0200", 59 | "hypervisor": "VMware", 60 | "memory": 2048, 61 | "state": "Running", 62 | "tags": [], 63 | "cpu_speed": 1800, 64 | "affinity_group": [], 65 | "service_offering": "Small", 66 | "cpu_used": "62%" 67 | } 68 | 69 | 70 | usage: cloudstack.py [--list] [--host HOST] [--project PROJECT] 71 | """ 72 | 73 | import os 74 | import sys 75 | import argparse 76 | 77 | try: 78 | import json 79 | except: 80 | import simplejson as json 81 | 82 | 83 | try: 84 | from cs import CloudStack, CloudStackException, read_config 85 | except ImportError: 86 | print >> sys.stderr, "Error: CloudStack library must be installed: pip install cs." 87 | sys.exit(1) 88 | 89 | 90 | class CloudStackInventory(object): 91 | def __init__(self): 92 | 93 | parser = argparse.ArgumentParser() 94 | parser.add_argument('--host') 95 | parser.add_argument('--list', action='store_true') 96 | parser.add_argument('--project') 97 | 98 | options = parser.parse_args() 99 | try: 100 | self.cs = CloudStack(**read_config()) 101 | except CloudStackException, e: 102 | print >> sys.stderr, "Error: Could not connect to CloudStack API" 103 | 104 | project_id = '' 105 | if options.project: 106 | project_id = self.get_project_id(options.project) 107 | 108 | if options.host: 109 | data = self.get_host(options.host) 110 | print json.dumps(data, indent=2) 111 | 112 | elif options.list: 113 | data = self.get_list() 114 | print json.dumps(data, indent=2) 115 | else: 116 | print >> sys.stderr, "usage: --list | --host [--project ]" 117 | sys.exit(1) 118 | 119 | 120 | def get_project_id(self, project): 121 | projects = self.cs.listProjects() 122 | if projects: 123 | for p in projects['project']: 124 | if p['name'] == project or p['id'] == project: 125 | return p['id'] 126 | print >> sys.stderr, "Error: Project %s not found." % project 127 | sys.exit(1) 128 | 129 | 130 | def get_host(self, name, project_id=''): 131 | hosts = self.cs.listVirtualMachines(projectid=project_id) 132 | if not hosts: 133 | return {} 134 | 135 | data = {} 136 | for host in hosts['virtualmachine']: 137 | host_name = host['displayname'] 138 | if name == host_name: 139 | data['zone'] = host['zonename'] 140 | if 'group' in host: 141 | data['group'] = host['group'] 142 | data['state'] = host['state'] 143 | data['service_offering'] = host['serviceofferingname'] 144 | data['affinity_group'] = host['affinitygroup'] 145 | data['security_group'] = host['securitygroup'] 146 | data['cpu_number'] = host['cpunumber'] 147 | data['cpu_speed'] = host['cpuspeed'] 148 | if 'cpuused' in host: 149 | data['cpu_used'] = host['cpuused'] 150 | data['memory'] = host['memory'] 151 | data['tags'] = host['tags'] 152 | data['hypervisor'] = host['hypervisor'] 153 | data['created'] = host['created'] 154 | data['nic'] = [] 155 | for nic in host['nic']: 156 | data['nic'].append({ 157 | 'ip': nic['ipaddress'], 158 | 'mac': nic['macaddress'], 159 | 'netmask': nic['netmask'], 160 | 'gateway': nic['gateway'], 161 | 'type': nic['type'], 162 | }) 163 | if nic['isdefault']: 164 | data['default_ip'] = nic['ipaddress'] 165 | break; 166 | return data 167 | 168 | 169 | def get_list(self, project_id=''): 170 | data = { 171 | 'all': { 172 | 'hosts': [], 173 | }, 174 | '_meta': { 175 | 'hostvars': {}, 176 | }, 177 | } 178 | 179 | groups = self.cs.listInstanceGroups(projectid=project_id) 180 | if groups: 181 | for group in groups['instancegroup']: 182 | group_name = group['name'] 183 | if group_name and not group_name in data: 184 | data[group_name] = { 185 | 'hosts': [] 186 | } 187 | 188 | hosts = self.cs.listVirtualMachines(projectid=project_id) 189 | if hosts: 190 | for host in hosts['virtualmachine']: 191 | host_name = host['displayname'] 192 | data['all']['hosts'].append(host_name) 193 | data['_meta']['hostvars'][host_name] = {} 194 | data['_meta']['hostvars'][host_name]['zone'] = host['zonename'] 195 | if 'group' in host: 196 | data['_meta']['hostvars'][host_name]['group'] = host['group'] 197 | data['_meta']['hostvars'][host_name]['state'] = host['state'] 198 | data['_meta']['hostvars'][host_name]['service_offering'] = host['serviceofferingname'] 199 | data['_meta']['hostvars'][host_name]['affinity_group'] = host['affinitygroup'] 200 | data['_meta']['hostvars'][host_name]['security_group'] = host['securitygroup'] 201 | data['_meta']['hostvars'][host_name]['cpu_number'] = host['cpunumber'] 202 | data['_meta']['hostvars'][host_name]['cpu_speed'] = host['cpuspeed'] 203 | if 'cpuused' in host: 204 | data['_meta']['hostvars'][host_name]['cpu_used'] = host['cpuused'] 205 | data['_meta']['hostvars'][host_name]['memory'] = host['memory'] 206 | data['_meta']['hostvars'][host_name]['tags'] = host['tags'] 207 | data['_meta']['hostvars'][host_name]['hypervisor'] = host['hypervisor'] 208 | data['_meta']['hostvars'][host_name]['created'] = host['created'] 209 | data['_meta']['hostvars'][host_name]['nic'] = [] 210 | for nic in host['nic']: 211 | data['_meta']['hostvars'][host_name]['nic'].append({ 212 | 'ip': nic['ipaddress'], 213 | 'mac': nic['macaddress'], 214 | 'netmask': nic['netmask'], 215 | 'gateway': nic['gateway'], 216 | 'type': nic['type'], 217 | }) 218 | if nic['isdefault']: 219 | data['_meta']['hostvars'][host_name]['default_ip'] = nic['ipaddress'] 220 | 221 | group_name = '' 222 | if 'group' in host: 223 | group_name = host['group'] 224 | 225 | if group_name and group_name in data: 226 | data[group_name]['hosts'].append(host_name) 227 | return data 228 | 229 | 230 | if __name__ == '__main__': 231 | CloudStackInventory() 232 | -------------------------------------------------------------------------------- /cs_facts.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # (c) 2015, René Moser 5 | # 6 | # This file is part of Ansible 7 | # 8 | # Ansible is free software: you can redistribute it and/or modify 9 | # it under the terms of the GNU General Public License as published by 10 | # the Free Software Foundation, either version 3 of the License, or 11 | # (at your option) any later version. 12 | # 13 | # Ansible is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU General Public License 19 | # along with Ansible. If not, see . 20 | 21 | DOCUMENTATION = ''' 22 | --- 23 | module: cs_facts 24 | short_description: Gather facts on instances of Apache CloudStack based clouds. 25 | description: 26 | - This module fetches data from the metadata API in CloudStack. The module must be called from within the instance itself. 27 | version_added: '2.0' 28 | author: "René Moser (@resmo)" 29 | options: 30 | filter: 31 | description: 32 | - Filter for a specific fact. 33 | required: false 34 | default: null 35 | choices: 36 | - cloudstack_service_offering 37 | - cloudstack_availability_zone 38 | - cloudstack_public_hostname 39 | - cloudstack_public_ipv4 40 | - cloudstack_local_hostname 41 | - cloudstack_local_ipv4 42 | - cloudstack_instance_id 43 | - cloudstack_user_data 44 | requirements: [ 'yaml' ] 45 | ''' 46 | 47 | EXAMPLES = ''' 48 | # Gather all facts on instances 49 | - name: Gather cloudstack facts 50 | cs_facts: 51 | 52 | # Gather specific fact on instances 53 | - name: Gather cloudstack facts 54 | cs_facts: filter=cloudstack_instance_id 55 | ''' 56 | 57 | RETURN = ''' 58 | --- 59 | cloudstack_availability_zone: 60 | description: zone the instance is deployed in. 61 | returned: success 62 | type: string 63 | sample: ch-gva-2 64 | cloudstack_instance_id: 65 | description: UUID of the instance. 66 | returned: success 67 | type: string 68 | sample: ab4e80b0-3e7e-4936-bdc5-e334ba5b0139 69 | cloudstack_local_hostname: 70 | description: local hostname of the instance. 71 | returned: success 72 | type: string 73 | sample: VM-ab4e80b0-3e7e-4936-bdc5-e334ba5b0139 74 | cloudstack_local_ipv4: 75 | description: local IPv4 of the instance. 76 | returned: success 77 | type: string 78 | sample: 185.19.28.35 79 | cloudstack_public_hostname: 80 | description: public IPv4 of the router. Same as C(cloudstack_public_ipv4). 81 | returned: success 82 | type: string 83 | sample: VM-ab4e80b0-3e7e-4936-bdc5-e334ba5b0139 84 | cloudstack_public_ipv4: 85 | description: public IPv4 of the router. 86 | returned: success 87 | type: string 88 | sample: 185.19.28.35 89 | cloudstack_service_offering: 90 | description: service offering of the instance. 91 | returned: success 92 | type: string 93 | sample: Micro 512mb 1cpu 94 | cloudstack_user_data: 95 | description: data of the instance provided by users. 96 | returned: success 97 | type: dict 98 | sample: { "bla": "foo" } 99 | ''' 100 | 101 | import os 102 | 103 | try: 104 | import yaml 105 | has_lib_yaml = True 106 | except ImportError: 107 | has_lib_yaml = False 108 | 109 | CS_METADATA_BASE_URL = "http://%s/latest/meta-data" 110 | CS_USERDATA_BASE_URL = "http://%s/latest/user-data" 111 | 112 | class CloudStackFacts(object): 113 | 114 | def __init__(self): 115 | self.facts = ansible_facts(module) 116 | self.api_ip = None 117 | self.fact_paths = { 118 | 'cloudstack_service_offering': 'service-offering', 119 | 'cloudstack_availability_zone': 'availability-zone', 120 | 'cloudstack_public_hostname': 'public-hostname', 121 | 'cloudstack_public_ipv4': 'public-ipv4', 122 | 'cloudstack_local_hostname': 'local-hostname', 123 | 'cloudstack_local_ipv4': 'local-ipv4', 124 | 'cloudstack_instance_id': 'instance-id' 125 | } 126 | 127 | def run(self): 128 | result = {} 129 | filter = module.params.get('filter') 130 | if not filter: 131 | for key,path in self.fact_paths.iteritems(): 132 | result[key] = self._fetch(CS_METADATA_BASE_URL + "/" + path) 133 | result['cloudstack_user_data'] = self._get_user_data_json() 134 | else: 135 | if filter == 'cloudstack_user_data': 136 | result['cloudstack_user_data'] = self._get_user_data_json() 137 | elif filter in self.fact_paths: 138 | result[filter] = self._fetch(CS_METADATA_BASE_URL + "/" + self.fact_paths[filter]) 139 | return result 140 | 141 | 142 | def _get_user_data_json(self): 143 | try: 144 | # this data come form users, we try what we can to parse it... 145 | return yaml.load(self._fetch(CS_USERDATA_BASE_URL)) 146 | except: 147 | return None 148 | 149 | 150 | def _fetch(self, path): 151 | api_ip = self._get_api_ip() 152 | if not api_ip: 153 | return None 154 | api_url = path % api_ip 155 | (response, info) = fetch_url(module, api_url, force=True) 156 | if response: 157 | data = response.read() 158 | else: 159 | data = None 160 | return data 161 | 162 | 163 | def _get_dhcp_lease_file(self): 164 | """Return the path of the lease file.""" 165 | default_iface = self.facts['default_ipv4']['interface'] 166 | dhcp_lease_file_locations = [ 167 | '/var/lib/dhcp/dhclient.%s.leases' % default_iface, # debian / ubuntu 168 | '/var/lib/dhclient/dhclient-%s.leases' % default_iface, # centos 6 169 | '/var/lib/dhclient/dhclient--%s.lease' % default_iface, # centos 7 170 | '/var/db/dhclient.leases.%s' % default_iface, # openbsd 171 | ] 172 | for file_path in dhcp_lease_file_locations: 173 | if os.path.exists(file_path): 174 | return file_path 175 | module.fail_json(msg="Could not find dhclient leases file.") 176 | 177 | 178 | def _get_api_ip(self): 179 | """Return the IP of the DHCP server.""" 180 | if not self.api_ip: 181 | dhcp_lease_file = self._get_dhcp_lease_file() 182 | for line in open(dhcp_lease_file): 183 | if 'dhcp-server-identifier' in line: 184 | # get IP of string "option dhcp-server-identifier 185.19.28.176;" 185 | line = line.translate(None, ';') 186 | self.api_ip = line.split()[2] 187 | break 188 | if not self.api_ip: 189 | module.fail_json(msg="No dhcp-server-identifier found in leases file.") 190 | return self.api_ip 191 | 192 | 193 | def main(): 194 | global module 195 | module = AnsibleModule( 196 | argument_spec = dict( 197 | filter = dict(default=None, choices=[ 198 | 'cloudstack_service_offering', 199 | 'cloudstack_availability_zone', 200 | 'cloudstack_public_hostname', 201 | 'cloudstack_public_ipv4', 202 | 'cloudstack_local_hostname', 203 | 'cloudstack_local_ipv4', 204 | 'cloudstack_instance_id', 205 | 'cloudstack_user_data', 206 | ]), 207 | ), 208 | supports_check_mode=False 209 | ) 210 | 211 | if not has_lib_yaml: 212 | module.fail_json(msg="missing python library: yaml") 213 | 214 | cs_facts = CloudStackFacts().run() 215 | cs_facts_result = dict(changed=False, ansible_facts=cs_facts) 216 | module.exit_json(**cs_facts_result) 217 | 218 | from ansible.module_utils.basic import * 219 | from ansible.module_utils.urls import * 220 | from ansible.module_utils.facts import * 221 | if __name__ == '__main__': 222 | main() 223 | -------------------------------------------------------------------------------- /helpers/sync.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # this will sync the cloudstack modules in a repo located under this repo 3 | 4 | cp ../ansible-modules-extras/cloud/cloudstack/cs_*.py . 5 | str='from ansible.module_utils.cloudstack import *' 6 | for i in $(ls cs_*.py); do 7 | sed -i -e "/$str/r ansible_cloudstack_utils.py" -e "/$str/d" $i 8 | done 9 | -------------------------------------------------------------------------------- /tests/Makefile: -------------------------------------------------------------------------------- 1 | INVENTORY ?= inventory 2 | VARS_FILE ?= integration_config.yml 3 | 4 | # Create a semi-random string for use when testing cloud-based resources 5 | ifndef CLOUD_RESOURCE_PREFIX 6 | CLOUD_RESOURCE_PREFIX := $(shell python -c "import string,random; print 'ansible-testing-' + ''.join(random.choice(string.ascii_letters + string.digits) for _ in xrange(8));") 7 | endif 8 | 9 | CREDENTIALS_FILE = credentials.yml 10 | # If credentials.yml exists, use it 11 | ifneq ("$(wildcard $(CREDENTIALS_FILE))","") 12 | CREDENTIALS_ARG = -e @$(CREDENTIALS_FILE) 13 | else 14 | CREDENTIALS_ARG = 15 | endif 16 | 17 | cloudstack: 18 | ansible-playbook cloudstack.yml -i $(INVENTORY) -e @$(VARS_FILE) -e "resource_prefix=$(CLOUD_RESOURCE_PREFIX)" -v $(TEST_FLAGS) ; \ 19 | RC=$$? ; \ 20 | exit $$RC; 21 | -------------------------------------------------------------------------------- /tests/ansible.cfg: -------------------------------------------------------------------------------- 1 | [defaults] 2 | hostfile = ./inventory 3 | library = /usr/share/ansible:../ 4 | -------------------------------------------------------------------------------- /tests/cloudstack.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | connection: local 4 | gather_facts: no 5 | tags: 6 | - cloudstack 7 | vars: 8 | cs_resource_prefix: "{{ resource_prefix | default('cs-') }}" 9 | roles: 10 | - { role: test_cs_configuration, tags: [ test_cs_configuration, cs_net_basic ] } 11 | - { role: test_cs_zone, tags: [ test_cs_zone, cs_net_basic ] } 12 | - { role: test_cs_pod, tags: [ test_cs_pod, cs_net_basic ] } 13 | - { role: test_cs_cluster, tags: [ test_cs_cluster, cs_net_basic ] } 14 | - { role: test_cs_user, tags: [ test_cs_user, cs_net_basic ] } 15 | - { role: test_cs_volume, tags: [ test_cs_volume, cs_net_basic ] } 16 | - { role: test_cs_project, tags: [ test_cs_project, cs_net_basic ] } 17 | - { role: test_cs_iso, tags: [ test_cs_iso, cs_net_basic ] } 18 | - { role: test_cs_domain, tags: [ test_cs_domain, cs_net_basic ] } 19 | - { role: test_cs_vmsnapshot, tags: [ test_cs_vmsnapshot, cs_net_basic ] } 20 | - { role: test_cs_sshkeypair, tags: [ test_cs_sshkeypair, cs_net_basic ] } 21 | - { role: test_cs_affinitygroup, tags: [ test_cs_affinitygroup, cs_net_basic ] } 22 | - { role: test_cs_securitygroup, tags: [ test_cs_securitygroup, cs_net_basic ] } 23 | - { role: test_cs_securitygroup_rule, tags: [ test_cs_securitygroup_rule, cs_net_basic ] } 24 | - { role: test_cs_instancegroup, tags: [ test_cs_instancegroup, cs_net_basic ] } 25 | - { role: test_cs_instance, tags: [ test_cs_instance, cs_net_basic ] } 26 | - { role: test_cs_instance_facts, tags: [ test_cs_instance_facts, cs_net_basic ] } 27 | - { role: test_cs_portforward, tags: [ test_cs_portforward, cs_net_adv ] } 28 | - { role: test_cs_account, tags: [ test_cs_account, cs_net_basic ] } 29 | - { role: test_cs_firewall, tags: [ test_cs_firewall, cs_net_adv ] } 30 | - { role: test_cs_loadbalancer_rule, tags: [ test_cs_loadbalancer_rule, cs_lb_rule, cs_net_adv ] } 31 | - { role: test_cs_resourcelimit, tags: [ test_cs_resourcelimit, cs_net_basic ] } 32 | -------------------------------------------------------------------------------- /tests/inventory: -------------------------------------------------------------------------------- 1 | localhost 2 | -------------------------------------------------------------------------------- /tests/roles/test_cs_account/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - test_cs_common 4 | -------------------------------------------------------------------------------- /tests/roles/test_cs_account/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: setup 3 | cs_account: name={{ cs_resource_prefix }}_user state=absent 4 | register: acc 5 | - name: verify setup 6 | assert: 7 | that: 8 | - acc|success 9 | 10 | - name: test fail if missing name 11 | action: cs_account 12 | register: acc 13 | ignore_errors: true 14 | - name: verify results of fail if missing params 15 | assert: 16 | that: 17 | - acc|failed 18 | - 'acc.msg == "missing required arguments: name"' 19 | 20 | - name: test fail if missing params if state=present 21 | cs_account: 22 | name: "{{ cs_resource_prefix }}_user" 23 | register: acc 24 | ignore_errors: true 25 | - name: verify results of fail if missing params if state=present 26 | assert: 27 | that: 28 | - acc|failed 29 | - 'acc.msg == "missing required arguments: email,username,password,first_name,last_name"' 30 | 31 | - name: test create user account 32 | cs_account: 33 | name: "{{ cs_resource_prefix }}_user" 34 | username: "{{ cs_resource_prefix }}_username" 35 | password: "{{ cs_resource_prefix }}_password" 36 | last_name: "{{ cs_resource_prefix }}_last_name" 37 | first_name: "{{ cs_resource_prefix }}_first_name" 38 | email: "{{ cs_resource_prefix }}@example.com" 39 | network_domain: "{{ cs_resource_prefix }}.local" 40 | register: acc 41 | - name: verify results of create account 42 | assert: 43 | that: 44 | - acc|success 45 | - acc|changed 46 | - acc.name == "{{ cs_resource_prefix }}_user" 47 | - acc.network_domain == "{{ cs_resource_prefix }}.local" 48 | - acc.account_type == "user" 49 | - acc.state == "enabled" 50 | - acc.domain == "ROOT" 51 | 52 | - name: test create user account idempotence 53 | cs_account: 54 | name: "{{ cs_resource_prefix }}_user" 55 | username: "{{ cs_resource_prefix }}_username" 56 | password: "{{ cs_resource_prefix }}_password" 57 | last_name: "{{ cs_resource_prefix }}_last_name" 58 | first_name: "{{ cs_resource_prefix }}_first_name" 59 | email: "{{ cs_resource_prefix }}@example.com" 60 | network_domain: "{{ cs_resource_prefix }}.local" 61 | register: acc 62 | - name: verify results of create account idempotence 63 | assert: 64 | that: 65 | - acc|success 66 | - not acc|changed 67 | - acc.name == "{{ cs_resource_prefix }}_user" 68 | - acc.network_domain == "{{ cs_resource_prefix }}.local" 69 | - acc.account_type == "user" 70 | - acc.state == "enabled" 71 | - acc.domain == "ROOT" 72 | 73 | - name: test lock user account 74 | cs_account: 75 | name: "{{ cs_resource_prefix }}_user" 76 | state: locked 77 | register: acc 78 | - name: verify results of lock user account 79 | assert: 80 | that: 81 | - acc|success 82 | - acc|changed 83 | - acc.name == "{{ cs_resource_prefix }}_user" 84 | - acc.network_domain == "{{ cs_resource_prefix }}.local" 85 | - acc.account_type == "user" 86 | - acc.state == "locked" 87 | - acc.domain == "ROOT" 88 | 89 | - name: test lock user account idempotence 90 | cs_account: 91 | name: "{{ cs_resource_prefix }}_user" 92 | state: locked 93 | register: acc 94 | - name: verify results of lock user account idempotence 95 | assert: 96 | that: 97 | - acc|success 98 | - not acc|changed 99 | - acc.name == "{{ cs_resource_prefix }}_user" 100 | - acc.network_domain == "{{ cs_resource_prefix }}.local" 101 | - acc.account_type == "user" 102 | - acc.state == "locked" 103 | - acc.domain == "ROOT" 104 | 105 | - name: test disable user account 106 | cs_account: 107 | name: "{{ cs_resource_prefix }}_user" 108 | state: disabled 109 | register: acc 110 | - name: verify results of disable user account 111 | assert: 112 | that: 113 | - acc|success 114 | - acc|changed 115 | - acc.name == "{{ cs_resource_prefix }}_user" 116 | - acc.network_domain == "{{ cs_resource_prefix }}.local" 117 | - acc.account_type == "user" 118 | - acc.state == "disabled" 119 | - acc.domain == "ROOT" 120 | 121 | - name: test disable user account idempotence 122 | cs_account: 123 | name: "{{ cs_resource_prefix }}_user" 124 | state: disabled 125 | register: acc 126 | - name: verify results of disable user account idempotence 127 | assert: 128 | that: 129 | - acc|success 130 | - not acc|changed 131 | - acc.name == "{{ cs_resource_prefix }}_user" 132 | - acc.network_domain == "{{ cs_resource_prefix }}.local" 133 | - acc.account_type == "user" 134 | - acc.state == "disabled" 135 | - acc.domain == "ROOT" 136 | 137 | - name: test lock disabled user account 138 | cs_account: 139 | name: "{{ cs_resource_prefix }}_user" 140 | state: locked 141 | register: acc 142 | - name: verify results of lock disabled user account 143 | assert: 144 | that: 145 | - acc|success 146 | - acc|changed 147 | - acc.name == "{{ cs_resource_prefix }}_user" 148 | - acc.network_domain == "{{ cs_resource_prefix }}.local" 149 | - acc.account_type == "user" 150 | - acc.state == "locked" 151 | - acc.domain == "ROOT" 152 | 153 | - name: test lock disabled user account idempotence 154 | cs_account: 155 | name: "{{ cs_resource_prefix }}_user" 156 | state: locked 157 | register: acc 158 | - name: verify results of lock disabled user account idempotence 159 | assert: 160 | that: 161 | - acc|success 162 | - not acc|changed 163 | - acc.name == "{{ cs_resource_prefix }}_user" 164 | - acc.network_domain == "{{ cs_resource_prefix }}.local" 165 | - acc.account_type == "user" 166 | - acc.state == "locked" 167 | - acc.domain == "ROOT" 168 | 169 | - name: test enable user account 170 | cs_account: 171 | name: "{{ cs_resource_prefix }}_user" 172 | state: enabled 173 | register: acc 174 | - name: verify results of enable user account 175 | assert: 176 | that: 177 | - acc|success 178 | - acc|changed 179 | - acc.name == "{{ cs_resource_prefix }}_user" 180 | - acc.network_domain == "{{ cs_resource_prefix }}.local" 181 | - acc.account_type == "user" 182 | - acc.state == "enabled" 183 | - acc.domain == "ROOT" 184 | 185 | - name: test enable user account idempotence 186 | cs_account: 187 | name: "{{ cs_resource_prefix }}_user" 188 | state: enabled 189 | register: acc 190 | - name: verify results of enable user account idempotence 191 | assert: 192 | that: 193 | - acc|success 194 | - not acc|changed 195 | - acc.name == "{{ cs_resource_prefix }}_user" 196 | - acc.network_domain == "{{ cs_resource_prefix }}.local" 197 | - acc.account_type == "user" 198 | - acc.state == "enabled" 199 | - acc.domain == "ROOT" 200 | 201 | - name: test remove user account 202 | cs_account: 203 | name: "{{ cs_resource_prefix }}_user" 204 | state: absent 205 | register: acc 206 | - name: verify results of remove user account 207 | assert: 208 | that: 209 | - acc|success 210 | - acc|changed 211 | - acc.name == "{{ cs_resource_prefix }}_user" 212 | - acc.network_domain == "{{ cs_resource_prefix }}.local" 213 | - acc.account_type == "user" 214 | - acc.state == "enabled" 215 | - acc.domain == "ROOT" 216 | 217 | - name: test remove user account idempotence 218 | cs_account: 219 | name: "{{ cs_resource_prefix }}_user" 220 | state: absent 221 | register: acc 222 | - name: verify results of remove user account idempotence 223 | assert: 224 | that: 225 | - acc|success 226 | - not acc|changed 227 | 228 | - name: test create user disabled account 229 | cs_account: 230 | name: "{{ cs_resource_prefix }}_user" 231 | username: "{{ cs_resource_prefix }}_username" 232 | password: "{{ cs_resource_prefix }}_password" 233 | last_name: "{{ cs_resource_prefix }}_last_name" 234 | first_name: "{{ cs_resource_prefix }}_first_name" 235 | email: "{{ cs_resource_prefix }}@example.com" 236 | network_domain: "{{ cs_resource_prefix }}.local" 237 | state: disabled 238 | register: acc 239 | - name: verify results of create disabled account 240 | assert: 241 | that: 242 | - acc|success 243 | - acc|changed 244 | - acc.name == "{{ cs_resource_prefix }}_user" 245 | - acc.network_domain == "{{ cs_resource_prefix }}.local" 246 | - acc.account_type == "user" 247 | - acc.state == "disabled" 248 | - acc.domain == "ROOT" 249 | 250 | - name: test remove disabled user account 251 | cs_account: 252 | name: "{{ cs_resource_prefix }}_user" 253 | state: absent 254 | register: acc 255 | - name: verify results of remove disabled user account 256 | assert: 257 | that: 258 | - acc|success 259 | - acc|changed 260 | - acc.name == "{{ cs_resource_prefix }}_user" 261 | - acc.network_domain == "{{ cs_resource_prefix }}.local" 262 | - acc.account_type == "user" 263 | - acc.state == "disabled" 264 | - acc.domain == "ROOT" 265 | 266 | - name: test create user locked account 267 | cs_account: 268 | name: "{{ cs_resource_prefix }}_user" 269 | username: "{{ cs_resource_prefix }}_username" 270 | password: "{{ cs_resource_prefix }}_password" 271 | last_name: "{{ cs_resource_prefix }}_last_name" 272 | first_name: "{{ cs_resource_prefix }}_first_name" 273 | email: "{{ cs_resource_prefix }}@example.com" 274 | network_domain: "{{ cs_resource_prefix }}.local" 275 | state: locked 276 | register: acc 277 | - name: verify results of create locked account 278 | assert: 279 | that: 280 | - acc|success 281 | - acc|changed 282 | - acc.name == "{{ cs_resource_prefix }}_user" 283 | - acc.network_domain == "{{ cs_resource_prefix }}.local" 284 | - acc.account_type == "user" 285 | - acc.state == "locked" 286 | - acc.domain == "ROOT" 287 | 288 | - name: test remove locked user account 289 | cs_account: 290 | name: "{{ cs_resource_prefix }}_user" 291 | state: absent 292 | register: acc 293 | - name: verify results of remove locked user account 294 | assert: 295 | that: 296 | - acc|success 297 | - acc|changed 298 | - acc.name == "{{ cs_resource_prefix }}_user" 299 | - acc.network_domain == "{{ cs_resource_prefix }}.local" 300 | - acc.account_type == "user" 301 | - acc.state == "locked" 302 | - acc.domain == "ROOT" 303 | 304 | - name: test create user unlocked/enabled account 305 | cs_account: 306 | name: "{{ cs_resource_prefix }}_user" 307 | username: "{{ cs_resource_prefix }}_username" 308 | password: "{{ cs_resource_prefix }}_password" 309 | last_name: "{{ cs_resource_prefix }}_last_name" 310 | first_name: "{{ cs_resource_prefix }}_first_name" 311 | email: "{{ cs_resource_prefix }}@example.com" 312 | network_domain: "{{ cs_resource_prefix }}.local" 313 | state: unlocked 314 | register: acc 315 | - name: verify results of create unlocked/enabled account 316 | assert: 317 | that: 318 | - acc|success 319 | - acc|changed 320 | - acc.name == "{{ cs_resource_prefix }}_user" 321 | - acc.network_domain == "{{ cs_resource_prefix }}.local" 322 | - acc.account_type == "user" 323 | - acc.state == "enabled" 324 | - acc.domain == "ROOT" 325 | 326 | - name: test remove unlocked/enabled user account 327 | cs_account: 328 | name: "{{ cs_resource_prefix }}_user" 329 | state: absent 330 | register: acc 331 | - name: verify results of remove unlocked/enabled user account 332 | assert: 333 | that: 334 | - acc|success 335 | - acc|changed 336 | - acc.name == "{{ cs_resource_prefix }}_user" 337 | - acc.network_domain == "{{ cs_resource_prefix }}.local" 338 | - acc.account_type == "user" 339 | - acc.state == "enabled" 340 | - acc.domain == "ROOT" 341 | -------------------------------------------------------------------------------- /tests/roles/test_cs_affinitygroup/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - test_cs_common 4 | -------------------------------------------------------------------------------- /tests/roles/test_cs_affinitygroup/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: setup 3 | cs_affinitygroup: name={{ cs_resource_prefix }}_ag state=absent 4 | register: ag 5 | - name: verify setup 6 | assert: 7 | that: 8 | - ag|success 9 | 10 | - name: test fail if missing name 11 | action: cs_affinitygroup 12 | register: ag 13 | ignore_errors: true 14 | - name: verify results of fail if missing name 15 | assert: 16 | that: 17 | - ag|failed 18 | - "ag.msg == 'missing required arguments: name'" 19 | 20 | - name: test present affinity group 21 | cs_affinitygroup: name={{ cs_resource_prefix }}_ag 22 | register: ag 23 | - name: verify results of create affinity group 24 | assert: 25 | that: 26 | - ag|success 27 | - ag|changed 28 | - ag.name == "{{ cs_resource_prefix }}_ag" 29 | 30 | - name: test present affinity group is idempotence 31 | cs_affinitygroup: name={{ cs_resource_prefix }}_ag 32 | register: ag 33 | - name: verify results present affinity group is idempotence 34 | assert: 35 | that: 36 | - ag|success 37 | - not ag|changed 38 | - ag.name == "{{ cs_resource_prefix }}_ag" 39 | 40 | - name: test absent affinity group 41 | cs_affinitygroup: name={{ cs_resource_prefix }}_ag state=absent 42 | register: ag 43 | - name: verify results of absent affinity group 44 | assert: 45 | that: 46 | - ag|success 47 | - ag|changed 48 | - ag.name == "{{ cs_resource_prefix }}_ag" 49 | 50 | - name: test absent affinity group is idempotence 51 | cs_affinitygroup: name={{ cs_resource_prefix }}_ag state=absent 52 | register: ag 53 | - name: verify results of absent affinity group is idempotence 54 | assert: 55 | that: 56 | - ag|success 57 | - not ag|changed 58 | - ag.name is undefined 59 | -------------------------------------------------------------------------------- /tests/roles/test_cs_cluster/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - test_cs_common 4 | -------------------------------------------------------------------------------- /tests/roles/test_cs_cluster/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: setup cluster is absent 3 | cs_cluster: 4 | name: "{{ cs_resource_prefix }}-cluster" 5 | state: absent 6 | register: cluster 7 | - name: verify setup cluster is absent 8 | assert: 9 | that: 10 | - cluster|success 11 | 12 | - name: setup zone is present 13 | cs_zone: 14 | name: "{{ cs_resource_prefix }}-zone" 15 | dns1: 8.8.8.8 16 | dns2: 8.8.4.4 17 | network_type: basic 18 | register: zone 19 | - name: verify setup zone is present 20 | assert: 21 | that: 22 | - zone|success 23 | 24 | - name: setup pod is preset 25 | cs_pod: 26 | name: "{{ cs_resource_prefix }}-pod" 27 | zone: "{{ cs_resource_prefix }}-zone" 28 | start_ip: 10.100.10.101 29 | gateway: 10.100.10.1 30 | netmask: 255.255.255.0 31 | register: pod 32 | - name: verify setup pod is preset 33 | assert: 34 | that: 35 | - pod|success 36 | 37 | - name: test fail if missing name 38 | cs_cluster: 39 | register: cluster 40 | ignore_errors: true 41 | - name: verify results of fail if missing name 42 | assert: 43 | that: 44 | - cluster|failed 45 | - "cluster.msg == 'missing required arguments: name'" 46 | 47 | - name: test create cluster 48 | cs_cluster: 49 | name: "{{ cs_resource_prefix }}-cluster" 50 | zone: "{{ cs_resource_prefix }}-zone" 51 | hypervisor: simulator 52 | cluster_type: CloudManaged 53 | register: cluster_origin 54 | tags: disable 55 | - name: verify test create cluster 56 | assert: 57 | that: 58 | - cluster_origin|changed 59 | - cluster_origin.name == "{{ cs_resource_prefix }}-cluster" 60 | - cluster_origin.zone == "{{ cs_resource_prefix }}-zone" 61 | - cluster_origin.allocation_state == "Enabled" 62 | - cluster_origin.hypervisor == "Simulator" 63 | - cluster_origin.cluster_type == "CloudManaged" 64 | 65 | - name: test create cluster idempotence 66 | cs_cluster: 67 | name: "{{ cs_resource_prefix }}-Cluster" 68 | zone: "{{ cs_resource_prefix }}-Zone" 69 | hypervisor: Simulator 70 | cluster_type: CloudManaged 71 | register: cluster 72 | - name: verify test create cluster idempotence 73 | assert: 74 | that: 75 | - cluster.id == cluster_origin.id 76 | - not cluster|changed 77 | - cluster.name == "{{ cs_resource_prefix }}-cluster" 78 | - cluster.zone == "{{ cs_resource_prefix }}-zone" 79 | - cluster.allocation_state == "Enabled" 80 | - cluster_origin.hypervisor == "Simulator" 81 | - cluster.cluster_type == "CloudManaged" 82 | 83 | - name: test update cluster 84 | cs_cluster: 85 | name: "{{ cs_resource_prefix }}-cluster" 86 | zone: "{{ cs_resource_prefix }}-zone" 87 | hypervisor: simulator 88 | cluster_type: ExternalManaged 89 | register: cluster 90 | - name: verify test update cluster 91 | assert: 92 | that: 93 | - cluster|changed 94 | - cluster.name == "{{ cs_resource_prefix }}-cluster" 95 | - cluster.zone == "{{ cs_resource_prefix }}-zone" 96 | - cluster.allocation_state == "Enabled" 97 | - cluster.hypervisor == "Simulator" 98 | - cluster.cluster_type == "ExternalManaged" 99 | - cluster.id == cluster_origin.id 100 | 101 | - name: test update cluster idempotence 102 | cs_cluster: 103 | name: "{{ cs_resource_prefix }}-cluster" 104 | zone: "{{ cs_resource_prefix }}-zone" 105 | hypervisor: simulator 106 | cluster_type: ExternalManaged 107 | register: cluster 108 | - name: verify test update cluster idempotence 109 | assert: 110 | that: 111 | - not cluster|changed 112 | - cluster.name == "{{ cs_resource_prefix }}-cluster" 113 | - cluster.zone == "{{ cs_resource_prefix }}-zone" 114 | - cluster.allocation_state == "Enabled" 115 | - cluster.hypervisor == "Simulator" 116 | - cluster.cluster_type == "ExternalManaged" 117 | - cluster.id == cluster_origin.id 118 | 119 | - name: test disable cluster 120 | cs_cluster: 121 | name: "{{ cs_resource_prefix }}-cluster" 122 | state: disabled 123 | register: cluster 124 | tags: disable 125 | - name: verify test disable cluster 126 | assert: 127 | that: 128 | - cluster|changed 129 | - cluster.name == "{{ cs_resource_prefix }}-cluster" 130 | - cluster.zone == "{{ cs_resource_prefix }}-zone" 131 | - cluster.allocation_state == "Disabled" 132 | - cluster.hypervisor == "Simulator" 133 | - cluster.cluster_type == "ExternalManaged" 134 | - cluster.id == cluster_origin.id 135 | tags: disable 136 | 137 | - name: test disable cluster idempotence 138 | cs_cluster: 139 | name: "{{ cs_resource_prefix }}-cluster" 140 | state: disabled 141 | register: cluster 142 | tags: disable 143 | - name: verify test disable cluster idempotence 144 | assert: 145 | that: 146 | - not cluster|changed 147 | - cluster.name == "{{ cs_resource_prefix }}-cluster" 148 | - cluster.zone == "{{ cs_resource_prefix }}-zone" 149 | - cluster.allocation_state == "Disabled" 150 | - cluster.hypervisor == "Simulator" 151 | - cluster.cluster_type == "ExternalManaged" 152 | tags: disable 153 | 154 | - name: test enable cluster 155 | cs_cluster: 156 | name: "{{ cs_resource_prefix }}-cluster" 157 | state: enabled 158 | register: cluster 159 | - name: verify test enable cluster 160 | assert: 161 | that: 162 | - cluster|changed 163 | - cluster.name == "{{ cs_resource_prefix }}-cluster" 164 | - cluster.zone == "{{ cs_resource_prefix }}-zone" 165 | - cluster.allocation_state == "Enabled" 166 | - cluster.hypervisor == "Simulator" 167 | - cluster.cluster_type == "ExternalManaged" 168 | - cluster.id == cluster_origin.id 169 | 170 | - name: test enable cluster idempotence 171 | cs_cluster: 172 | name: "{{ cs_resource_prefix }}-cluster" 173 | state: enabled 174 | register: cluster 175 | - name: verify test enable cluster idempotence 176 | assert: 177 | that: 178 | - not cluster|changed 179 | - cluster.name == "{{ cs_resource_prefix }}-cluster" 180 | - cluster.zone == "{{ cs_resource_prefix }}-zone" 181 | - cluster.allocation_state == "Enabled" 182 | - cluster.hypervisor == "Simulator" 183 | - cluster.cluster_type == "ExternalManaged" 184 | - cluster.id == cluster_origin.id 185 | 186 | - name: test remove cluster 187 | cs_cluster: 188 | name: "{{ cs_resource_prefix }}-cluster" 189 | zone: "{{ cs_resource_prefix }}-zone" 190 | state: absent 191 | register: cluster 192 | - name: verify test remove cluster 193 | assert: 194 | that: 195 | - cluster.id == cluster_origin.id 196 | - cluster|changed 197 | - cluster.name == "{{ cs_resource_prefix }}-cluster" 198 | - cluster.zone == "{{ cs_resource_prefix }}-zone" 199 | - cluster.allocation_state == "Enabled" 200 | - cluster_origin.hypervisor == "Simulator" 201 | 202 | - name: test remove cluster idempotence 203 | cs_cluster: 204 | name: "{{ cs_resource_prefix }}-cluster" 205 | zone: "{{ cs_resource_prefix }}-zone" 206 | state: absent 207 | register: cluster 208 | - name: verify test remove cluster idempotence 209 | assert: 210 | that: 211 | - not cluster|changed 212 | -------------------------------------------------------------------------------- /tests/roles/test_cs_common/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | cs_resource_prefix: cloudstack 3 | -------------------------------------------------------------------------------- /tests/roles/test_cs_configuration/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | test_cs_configuration_storage: PS0 3 | test_cs_configuration_cluster: C0 4 | test_cs_configuration_account: admin 5 | test_cs_configuration_zone: Sandbox-simulator 6 | -------------------------------------------------------------------------------- /tests/roles/test_cs_configuration/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - test_cs_common 4 | -------------------------------------------------------------------------------- /tests/roles/test_cs_configuration/tasks/account.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: test configuration account 3 | cs_configuration: 4 | name: allow.public.user.templates 5 | account: "{{ test_cs_configuration_account }}" 6 | value: true 7 | register: config 8 | - name: verify test configuration storage 9 | assert: 10 | that: 11 | - config|success 12 | 13 | - name: test update configuration account 14 | cs_configuration: 15 | name: allow.public.user.templates 16 | account: "{{ test_cs_configuration_account }}" 17 | value: false 18 | register: config 19 | - name: verify update configuration account 20 | assert: 21 | that: 22 | - config|success 23 | - config|changed 24 | - config.value == "false" 25 | - config.name == "allow.public.user.templates" 26 | - config.scope == "account" 27 | - config.account == "{{ test_cs_configuration_account }}" 28 | 29 | - name: test update configuration account idempotence 30 | cs_configuration: 31 | name: allow.public.user.templates 32 | account: "{{ test_cs_configuration_account }}" 33 | value: false 34 | register: config 35 | - name: verify update configuration account idempotence 36 | assert: 37 | that: 38 | - config|success 39 | - not config|changed 40 | - config.value == "false" 41 | - config.name == "allow.public.user.templates" 42 | - config.scope == "account" 43 | - config.account == "{{ test_cs_configuration_account }}" 44 | 45 | - name: test reset configuration account 46 | cs_configuration: 47 | name: allow.public.user.templates 48 | account: "{{ test_cs_configuration_account }}" 49 | value: true 50 | register: config 51 | - name: verify update configuration account 52 | assert: 53 | that: 54 | - config|success 55 | - config|changed 56 | - config.value == "true" 57 | - config.name == "allow.public.user.templates" 58 | - config.scope == "account" 59 | - config.account == "{{ test_cs_configuration_account }}" 60 | -------------------------------------------------------------------------------- /tests/roles/test_cs_configuration/tasks/cluster.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: test configuration cluster 3 | cs_configuration: 4 | name: cpu.overprovisioning.factor 5 | cluster: "{{ test_cs_configuration_cluster }}" 6 | value: 1.0 7 | register: config 8 | - name: verify test configuration cluster 9 | assert: 10 | that: 11 | - config|success 12 | 13 | - name: test update configuration cluster 14 | cs_configuration: 15 | name: cpu.overprovisioning.factor 16 | cluster: "{{ test_cs_configuration_cluster }}" 17 | value: 2.0 18 | register: config 19 | - name: verify update configuration cluster 20 | assert: 21 | that: 22 | - config|success 23 | - config|changed 24 | - config.value == "2.0" 25 | - config.name == "cpu.overprovisioning.factor" 26 | - config.scope == "cluster" 27 | - config.cluster == "{{ test_cs_configuration_cluster }}" 28 | 29 | - name: test update configuration cluster idempotence 30 | cs_configuration: 31 | name: cpu.overprovisioning.factor 32 | cluster: "{{ test_cs_configuration_cluster }}" 33 | value: 2.0 34 | register: config 35 | - name: verify update configuration cluster idempotence 36 | assert: 37 | that: 38 | - config|success 39 | - not config|changed 40 | - config.value == "2.0" 41 | - config.name == "cpu.overprovisioning.factor" 42 | - config.scope == "cluster" 43 | - config.cluster == "{{ test_cs_configuration_cluster }}" 44 | 45 | - name: test reset configuration cluster 46 | cs_configuration: 47 | name: cpu.overprovisioning.factor 48 | cluster: "{{ test_cs_configuration_cluster }}" 49 | value: 1.0 50 | register: config 51 | - name: verify reset configuration cluster 52 | assert: 53 | that: 54 | - config|success 55 | - config|changed 56 | - config.value == "1.0" 57 | - config.name == "cpu.overprovisioning.factor" 58 | - config.scope == "cluster" 59 | - config.cluster == "{{ test_cs_configuration_cluster }}" 60 | -------------------------------------------------------------------------------- /tests/roles/test_cs_configuration/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: test fail if missing name 3 | cs_configuration: 4 | register: config 5 | ignore_errors: true 6 | - name: verify results of fail if missing arguments 7 | assert: 8 | that: 9 | - config|failed 10 | - "config.msg == 'missing required arguments: value,name'" 11 | 12 | - name: test configuration 13 | cs_configuration: 14 | name: network.loadbalancer.haproxy.stats.visibility 15 | value: global 16 | register: config 17 | - name: verify test configuration 18 | assert: 19 | that: 20 | - config|success 21 | 22 | - name: test update configuration string 23 | cs_configuration: 24 | name: network.loadbalancer.haproxy.stats.visibility 25 | value: all 26 | register: config 27 | - name: verify test update configuration string 28 | assert: 29 | that: 30 | - config|success 31 | - config|changed 32 | - config.value == "all" 33 | - config.name == "network.loadbalancer.haproxy.stats.visibility" 34 | 35 | - name: test update configuration string idempotence 36 | cs_configuration: 37 | name: network.loadbalancer.haproxy.stats.visibility 38 | value: all 39 | register: config 40 | - name: verify test update configuration string idempotence 41 | assert: 42 | that: 43 | - config|success 44 | - not config|changed 45 | - config.value == "all" 46 | - config.name == "network.loadbalancer.haproxy.stats.visibility" 47 | 48 | - name: test reset configuration string 49 | cs_configuration: 50 | name: network.loadbalancer.haproxy.stats.visibility 51 | value: global 52 | register: config 53 | - name: verify test reset configuration string 54 | assert: 55 | that: 56 | - config|success 57 | - config|changed 58 | - config.value == "global" 59 | - config.name == "network.loadbalancer.haproxy.stats.visibility" 60 | 61 | - name: test configuration 62 | cs_configuration: 63 | name: vmware.recycle.hung.wokervm 64 | value: false 65 | register: config 66 | - name: verify test configuration 67 | assert: 68 | that: 69 | - config|success 70 | 71 | - name: test update configuration bool 72 | cs_configuration: 73 | name: vmware.recycle.hung.wokervm 74 | value: true 75 | register: config 76 | - name: verify test update configuration bool 77 | assert: 78 | that: 79 | - config|success 80 | - config|changed 81 | - config.value == "true" 82 | - config.name == "vmware.recycle.hung.wokervm" 83 | 84 | - name: test update configuration bool idempotence 85 | cs_configuration: 86 | name: vmware.recycle.hung.wokervm 87 | value: true 88 | register: config 89 | - name: verify test update configuration bool idempotence 90 | assert: 91 | that: 92 | - config|success 93 | - not config|changed 94 | - config.value == "true" 95 | - config.name == "vmware.recycle.hung.wokervm" 96 | 97 | - name: test reset configuration bool 98 | cs_configuration: 99 | name: vmware.recycle.hung.wokervm 100 | value: false 101 | register: config 102 | - name: verify test reset configuration bool 103 | assert: 104 | that: 105 | - config|success 106 | - config|changed 107 | - config.value == "false" 108 | - config.name == "vmware.recycle.hung.wokervm" 109 | 110 | - name: test configuration 111 | cs_configuration: 112 | name: agent.load.threshold 113 | value: 0.7 114 | register: config 115 | - name: verify test configuration 116 | assert: 117 | that: 118 | - config|success 119 | 120 | - name: test update configuration float 121 | cs_configuration: 122 | name: agent.load.threshold 123 | value: 0.81 124 | register: config 125 | - name: verify update configuration float 126 | assert: 127 | that: 128 | - config|success 129 | - config|changed 130 | - config.value == "0.81" 131 | - config.name == "agent.load.threshold" 132 | 133 | - name: test update configuration float idempotence 134 | cs_configuration: 135 | name: agent.load.threshold 136 | value: 0.81 137 | register: config 138 | - name: verify update configuration float idempotence 139 | assert: 140 | that: 141 | - config|success 142 | - not config|changed 143 | - config.value == "0.81" 144 | - config.name == "agent.load.threshold" 145 | 146 | - name: reset configuration float 147 | cs_configuration: 148 | name: agent.load.threshold 149 | value: 0.7 150 | register: config 151 | - name: verify reset configuration float 152 | assert: 153 | that: 154 | - config|success 155 | - config|changed 156 | - config.value == "0.7" 157 | - config.name == "agent.load.threshold" 158 | 159 | - include: storage.yml 160 | - include: account.yml 161 | - include: zone.yml 162 | - include: cluster.yml 163 | -------------------------------------------------------------------------------- /tests/roles/test_cs_configuration/tasks/storage.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: test configuration storage 3 | cs_configuration: 4 | name: storage.overprovisioning.factor 5 | storage: "{{ test_cs_configuration_storage }}" 6 | value: 2.0 7 | register: config 8 | - name: verify test configuration storage 9 | assert: 10 | that: 11 | - config|success 12 | 13 | - name: test update configuration storage 14 | cs_configuration: 15 | name: storage.overprovisioning.factor 16 | storage: "{{ test_cs_configuration_storage }}" 17 | value: 3.0 18 | register: config 19 | - name: verify update configuration storage 20 | assert: 21 | that: 22 | - config|success 23 | - config|changed 24 | - config.value == "3.0" 25 | - config.name == "storage.overprovisioning.factor" 26 | - config.scope == "storagepool" 27 | - config.storage == "{{ test_cs_configuration_storage }}" 28 | 29 | - name: test update configuration storage idempotence 30 | cs_configuration: 31 | name: storage.overprovisioning.factor 32 | storage: "{{ test_cs_configuration_storage }}" 33 | value: 3.0 34 | register: config 35 | - name: verify update configuration storage idempotence 36 | assert: 37 | that: 38 | - config|success 39 | - not config|changed 40 | - config.value == "3.0" 41 | - config.name == "storage.overprovisioning.factor" 42 | - config.scope == "storagepool" 43 | - config.storage == "{{ test_cs_configuration_storage }}" 44 | 45 | - name: test reset configuration storage 46 | cs_configuration: 47 | name: storage.overprovisioning.factor 48 | storage: "{{ test_cs_configuration_storage }}" 49 | value: 2.0 50 | register: config 51 | - name: verify reset configuration storage 52 | assert: 53 | that: 54 | - config|success 55 | - config|changed 56 | - config.value == "2.0" 57 | - config.name == "storage.overprovisioning.factor" 58 | - config.scope == "storagepool" 59 | - config.storage == "{{ test_cs_configuration_storage }}" 60 | -------------------------------------------------------------------------------- /tests/roles/test_cs_configuration/tasks/zone.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: test configuration zone 3 | cs_configuration: 4 | name: use.external.dns 5 | zone: "{{ test_cs_configuration_zone }}" 6 | value: false 7 | register: config 8 | - name: verify test configuration zone 9 | assert: 10 | that: 11 | - config|success 12 | 13 | - name: test update configuration zone 14 | cs_configuration: 15 | name: use.external.dns 16 | zone: "{{ test_cs_configuration_zone }}" 17 | value: true 18 | register: config 19 | - name: verify update configuration zone 20 | assert: 21 | that: 22 | - config|success 23 | - config|changed 24 | - config.value == "true" 25 | - config.name == "use.external.dns" 26 | - config.scope == "zone" 27 | - config.zone == "{{ test_cs_configuration_zone }}" 28 | 29 | - name: test update configuration zone idempotence 30 | cs_configuration: 31 | name: use.external.dns 32 | zone: "{{ test_cs_configuration_zone }}" 33 | value: true 34 | register: config 35 | - name: verify update configuration zone idempotence 36 | assert: 37 | that: 38 | - config|success 39 | - not config|changed 40 | - config.value == "true" 41 | - config.name == "use.external.dns" 42 | - config.scope == "zone" 43 | - config.zone == "{{ test_cs_configuration_zone }}" 44 | 45 | - name: test reset configuration zone 46 | cs_configuration: 47 | name: use.external.dns 48 | zone: "{{ test_cs_configuration_zone }}" 49 | value: false 50 | register: config 51 | - name: verify reset configuration zone 52 | assert: 53 | that: 54 | - config|success 55 | - config|changed 56 | - config.value == "false" 57 | - config.name == "use.external.dns" 58 | - config.scope == "zone" 59 | - config.zone == "{{ test_cs_configuration_zone }}" 60 | -------------------------------------------------------------------------------- /tests/roles/test_cs_domain/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - test_cs_common 4 | -------------------------------------------------------------------------------- /tests/roles/test_cs_domain/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: setup 3 | cs_domain: path={{ cs_resource_prefix }}_domain state=absent 4 | register: dom 5 | - name: verify setup 6 | assert: 7 | that: 8 | - dom|success 9 | 10 | - name: test fail if missing name 11 | action: cs_domain 12 | register: dom 13 | ignore_errors: true 14 | - name: verify results of fail if missing params 15 | assert: 16 | that: 17 | - dom|failed 18 | - 'dom.msg == "missing required arguments: path"' 19 | 20 | - name: test fail if ends with / 21 | cs_domain: path={{ cs_resource_prefix }}_domain/ 22 | register: dom 23 | ignore_errors: true 24 | - name: verify results of fail if ends with / 25 | assert: 26 | that: 27 | - dom|failed 28 | - dom.msg == "Path '{{ cs_resource_prefix }}_domain/' must not end with /" 29 | 30 | - name: test create a domain 31 | cs_domain: path={{ cs_resource_prefix }}_domain 32 | register: dom 33 | - name: verify results of test create a domain 34 | assert: 35 | that: 36 | - dom|changed 37 | - dom.path == "ROOT/{{ cs_resource_prefix }}_domain" 38 | - dom.name == "{{ cs_resource_prefix }}_domain" 39 | 40 | - name: test create a domain idempotence 41 | cs_domain: path={{ cs_resource_prefix }}_domain 42 | register: dom 43 | - name: verify results of test create a domain idempotence 44 | assert: 45 | that: 46 | - not dom|changed 47 | - dom.path == "ROOT/{{ cs_resource_prefix }}_domain" 48 | - dom.name == "{{ cs_resource_prefix }}_domain" 49 | 50 | - name: test create a subdomain 51 | cs_domain: path=ROOT/{{ cs_resource_prefix }}_domain/{{ cs_resource_prefix }}_subdomain 52 | register: dom 53 | - name: verify results of test create a domain 54 | assert: 55 | that: 56 | - dom|changed 57 | - dom.path == "ROOT/{{ cs_resource_prefix }}_domain/{{ cs_resource_prefix }}_subdomain" 58 | - dom.name == "{{ cs_resource_prefix }}_subdomain" 59 | 60 | - name: test create a subdomain idempotence 61 | cs_domain: path=ROOT/{{ cs_resource_prefix }}_domain/{{ cs_resource_prefix }}_subdomain 62 | register: dom 63 | - name: verify results of test create a subdomain idempotence 64 | assert: 65 | that: 66 | - not dom|changed 67 | 68 | - name: test delete a subdomain 69 | cs_domain: path=ROOT/{{ cs_resource_prefix }}_domain/{{ cs_resource_prefix }}_subdomain state=absent 70 | register: dom 71 | - name: verify results of test delete a subdomain idempotence 72 | assert: 73 | that: 74 | - dom|changed 75 | - dom.path == "ROOT/{{ cs_resource_prefix }}_domain/{{ cs_resource_prefix }}_subdomain" 76 | - dom.name == "{{ cs_resource_prefix }}_subdomain" 77 | 78 | - name: test delete a subdomain idempotence 79 | cs_domain: path=ROOT/{{ cs_resource_prefix }}_domain/{{ cs_resource_prefix }}_subdomain state=absent 80 | register: dom 81 | - name: verify results of test delete a subdomain idempotence 82 | assert: 83 | that: 84 | - not dom|changed 85 | 86 | - name: test create a subdomain 2 87 | cs_domain: path=ROOT/{{ cs_resource_prefix }}_domain/{{ cs_resource_prefix }}_subdomain 88 | register: dom 89 | - name: verify results of test create a subdomain 2 90 | assert: 91 | that: 92 | - dom|changed 93 | - dom.path == "ROOT/{{ cs_resource_prefix }}_domain/{{ cs_resource_prefix }}_subdomain" 94 | - dom.name == "{{ cs_resource_prefix }}_subdomain" 95 | 96 | - name: test delete a domain with clean up 97 | cs_domain: path=ROOT/{{ cs_resource_prefix }}_domain state=absent clean_up=true 98 | register: dom 99 | - name: verify results of test delete a domain with clean up 100 | assert: 101 | that: 102 | - dom|changed 103 | - dom.path == "ROOT/{{ cs_resource_prefix }}_domain" 104 | - dom.name == "{{ cs_resource_prefix }}_domain" 105 | 106 | - name: test delete a domain with clean up idempotence 107 | cs_domain: path=ROOT/{{ cs_resource_prefix }}_domain state=absent clean_up=true 108 | register: dom 109 | - name: verify results of test delete a domain with clean up idempotence 110 | assert: 111 | that: 112 | - not dom|changed 113 | -------------------------------------------------------------------------------- /tests/roles/test_cs_firewall/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | cs_firewall_ip_address: 10.100.212.5 3 | cs_firewall_network: test 4 | -------------------------------------------------------------------------------- /tests/roles/test_cs_firewall/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - test_cs_common 4 | -------------------------------------------------------------------------------- /tests/roles/test_cs_firewall/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: setup 80 3 | cs_firewall: 4 | port: 80 5 | ip_address: "{{ cs_firewall_ip_address }}" 6 | state: absent 7 | register: fw 8 | - name: verify setup 9 | assert: 10 | that: 11 | - fw|success 12 | 13 | - name: setup 5300 14 | cs_firewall: 15 | ip_address: "{{ cs_firewall_ip_address }}" 16 | protocol: udp 17 | start_port: 5300 18 | end_port: 5333 19 | cidr: 1.2.3.4/24 20 | state: absent 21 | register: fw 22 | - name: verify setup 23 | assert: 24 | that: 25 | - fw|success 26 | 27 | - name: setup all 28 | cs_firewall: 29 | network: "{{ cs_firewall_network }}" 30 | protocol: all 31 | type: egress 32 | state: absent 33 | register: fw 34 | - name: verify setup 35 | assert: 36 | that: 37 | - fw|success 38 | 39 | - name: test fail if missing params 40 | action: cs_firewall 41 | register: fw 42 | ignore_errors: true 43 | - name: verify results of fail if missing params 44 | assert: 45 | that: 46 | - fw|failed 47 | - fw.msg == "missing required argument for protocol 'tcp': start_port or end_port" 48 | 49 | - name: test fail if missing params ip_address ingress 50 | cs_firewall: 51 | port: 80 52 | register: fw 53 | ignore_errors: true 54 | - name: verify results of fail if missing params ip_address 55 | assert: 56 | that: 57 | - fw|failed 58 | - fw.msg == "missing required argument for type ingress: ip_address" 59 | 60 | - name: test fail if missing params network egress 61 | cs_firewall: 62 | type: egress 63 | register: fw 64 | ignore_errors: true 65 | - name: verify results of fail if missing params ip_address 66 | assert: 67 | that: 68 | - fw|failed 69 | - fw.msg == "missing required argument for type egress: network" 70 | 71 | - name: test present firewall rule ingress 80 72 | cs_firewall: 73 | port: 80 74 | ip_address: "{{ cs_firewall_ip_address }}" 75 | register: fw 76 | - name: verify results of present firewall rule ingress 80 77 | assert: 78 | that: 79 | - fw|success 80 | - fw|changed 81 | - fw.cidr == "0.0.0.0/0" 82 | - fw.ip_address == "{{ cs_firewall_ip_address }}" 83 | - fw.protocol == "tcp" 84 | - fw.start_port == 80 85 | - fw.end_port == 80 86 | - fw.type == "ingress" 87 | 88 | - name: test present firewall rule ingress 80 idempotence 89 | cs_firewall: 90 | port: 80 91 | ip_address: "{{ cs_firewall_ip_address }}" 92 | register: fw 93 | - name: verify results of present firewall rule ingress 80 idempotence 94 | assert: 95 | that: 96 | - fw|success 97 | - not fw|changed 98 | - fw.cidr == "0.0.0.0/0" 99 | - fw.ip_address == "{{ cs_firewall_ip_address }}" 100 | - fw.protocol == "tcp" 101 | - fw.start_port == 80 102 | - fw.end_port == 80 103 | - fw.type == "ingress" 104 | 105 | - name: test present firewall rule ingress 5300 106 | cs_firewall: 107 | ip_address: "{{ cs_firewall_ip_address }}" 108 | protocol: udp 109 | start_port: 5300 110 | end_port: 5333 111 | cidr: 1.2.3.4/24 112 | register: fw 113 | - name: verify results of present firewall rule ingress 5300 114 | assert: 115 | that: 116 | - fw|success 117 | - fw|changed 118 | - fw.cidr == "1.2.3.4/24" 119 | - fw.ip_address == "{{ cs_firewall_ip_address }}" 120 | - fw.protocol == "udp" 121 | - fw.start_port == 5300 122 | - fw.end_port == 5333 123 | - fw.type == "ingress" 124 | 125 | - name: test present firewall rule ingress 5300 idempotence 126 | cs_firewall: 127 | ip_address: "{{ cs_firewall_ip_address }}" 128 | protocol: udp 129 | start_port: 5300 130 | end_port: 5333 131 | cidr: 1.2.3.4/24 132 | register: fw 133 | - name: verify results of present firewall rule ingress 5300 idempotence 134 | assert: 135 | that: 136 | - fw|success 137 | - not fw|changed 138 | - fw.cidr == "1.2.3.4/24" 139 | - fw.ip_address == "{{ cs_firewall_ip_address }}" 140 | - fw.protocol == "udp" 141 | - fw.start_port == 5300 142 | - fw.end_port == 5333 143 | - fw.type == "ingress" 144 | 145 | - name: test present firewall rule egress all 146 | cs_firewall: 147 | network: "{{ cs_firewall_network }}" 148 | protocol: all 149 | type: egress 150 | register: fw 151 | - name: verify results of present firewall rule egress all 152 | assert: 153 | that: 154 | - fw|success 155 | - fw|changed 156 | - fw.cidr == "0.0.0.0/0" 157 | - fw.network == "{{ cs_firewall_network }}" 158 | - fw.protocol == "all" 159 | - fw.type == "egress" 160 | 161 | - name: test present firewall rule egress all idempotence 162 | cs_firewall: 163 | network: "{{ cs_firewall_network }}" 164 | protocol: all 165 | type: egress 166 | register: fw 167 | - name: verify results of present firewall rule egress all idempotence 168 | assert: 169 | that: 170 | - fw|success 171 | - not fw|changed 172 | - fw.cidr == "0.0.0.0/0" 173 | - fw.network == "{{ cs_firewall_network }}" 174 | - fw.protocol == "all" 175 | - fw.type == "egress" 176 | 177 | - name: test absent firewall rule ingress 80 178 | cs_firewall: 179 | port: 80 180 | ip_address: "{{ cs_firewall_ip_address }}" 181 | state: absent 182 | register: fw 183 | - name: verify results of absent firewall rule ingress 80 184 | assert: 185 | that: 186 | - fw|success 187 | - fw|changed 188 | - fw.cidr == "0.0.0.0/0" 189 | - fw.ip_address == "{{ cs_firewall_ip_address }}" 190 | - fw.protocol == "tcp" 191 | - fw.start_port == 80 192 | - fw.end_port == 80 193 | - fw.type == "ingress" 194 | 195 | - name: test absent firewall rule ingress 80 idempotence 196 | cs_firewall: 197 | port: 80 198 | ip_address: "{{ cs_firewall_ip_address }}" 199 | state: absent 200 | register: fw 201 | - name: verify results of absent firewall rule ingress 80 idempotence 202 | assert: 203 | that: 204 | - fw|success 205 | - not fw|changed 206 | 207 | - name: test absent firewall rule ingress 5300 208 | cs_firewall: 209 | ip_address: "{{ cs_firewall_ip_address }}" 210 | protocol: udp 211 | start_port: 5300 212 | end_port: 5333 213 | cidr: 1.2.3.4/24 214 | state: absent 215 | register: fw 216 | - name: verify results of absent firewall rule ingress 5300 217 | assert: 218 | that: 219 | - fw|success 220 | - fw|changed 221 | - fw.cidr == "1.2.3.4/24" 222 | - fw.ip_address == "{{ cs_firewall_ip_address }}" 223 | - fw.protocol == "udp" 224 | - fw.start_port == 5300 225 | - fw.end_port == 5333 226 | - fw.type == "ingress" 227 | 228 | - name: test absent firewall rule ingress 5300 idempotence 229 | cs_firewall: 230 | ip_address: "{{ cs_firewall_ip_address }}" 231 | protocol: udp 232 | start_port: 5300 233 | end_port: 5333 234 | cidr: 1.2.3.4/24 235 | state: absent 236 | register: fw 237 | - name: verify results of absent firewall rule ingress 5300 idempotence 238 | assert: 239 | that: 240 | - fw|success 241 | - not fw|changed 242 | 243 | - name: test absent firewall rule egress all 244 | cs_firewall: 245 | network: "{{ cs_firewall_network }}" 246 | protocol: all 247 | type: egress 248 | state: absent 249 | register: fw 250 | - name: verify results of absent firewall rule egress all 251 | assert: 252 | that: 253 | - fw|success 254 | - fw|changed 255 | - fw.cidr == "0.0.0.0/0" 256 | - fw.network == "{{ cs_firewall_network }}" 257 | - fw.protocol == "all" 258 | - fw.type == "egress" 259 | 260 | - name: test absent firewall rule egress all idempotence 261 | cs_firewall: 262 | network: "{{ cs_firewall_network }}" 263 | protocol: all 264 | type: egress 265 | state: absent 266 | register: fw 267 | - name: verify results of absent firewall rule egress all idempotence 268 | assert: 269 | that: 270 | - fw|success 271 | - not fw|changed 272 | -------------------------------------------------------------------------------- /tests/roles/test_cs_host/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | test_cs_host_pod: my_pod 3 | test_cs_host_username: username 4 | test_cs_host_password: password 5 | test_cs_host_url: url 6 | -------------------------------------------------------------------------------- /tests/roles/test_cs_host/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - test_cs_common 4 | -------------------------------------------------------------------------------- /tests/roles/test_cs_host/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: setup host is absent 3 | cs_host: 4 | name: "{{ cs_resource_prefix }}-host" 5 | register: host 6 | - name: verify setup host is absent 7 | assert: 8 | that: 9 | - host|success 10 | 11 | - name: test fail if missing name 12 | cs_host: 13 | register: host 14 | ignore_errors: true 15 | - name: verify results of fail if missing name 16 | assert: 17 | that: 18 | - host|failed 19 | - "host.msg == 'missing required arguments: name,pod,url,username,password'" 20 | 21 | - name: test create host 22 | cs_host: 23 | name: "{{ cs_resource_prefix }}-host" 24 | pod: "{{ test_cs_host_pod }}" 25 | username: "{{ test_cs_host_username }}" 26 | password: "{{ test_cs_host_password }}" 27 | url: "{{ test_cs_host_url }}" 28 | register: host 29 | - name: verify test create host 30 | assert: 31 | that: 32 | - host|changed 33 | - host.pod == "{{ test_cs_host_pod }}" 34 | - host.username == "{{ test_cs_host_username }}" 35 | - host.password == "{{ test_cs_host_password }}" 36 | - host.url == "{{ test_cs_host_url }}" 37 | 38 | - name: test create host idempotence 39 | cs_host: 40 | name: "{{ cs_resource_prefix }}-host" 41 | register: host 42 | - name: verify test create host idempotence 43 | assert: 44 | that: 45 | - not host|changed 46 | - host.pod == "{{ test_cs_host_pod }}" 47 | - host.username == "{{ test_cs_host_username }}" 48 | - host.password == "{{ test_cs_host_password }}" 49 | - host.url == "{{ test_cs_host_url }}" 50 | 51 | - name: test disable host 52 | cs_host: 53 | name: "{{ cs_resource_prefix }}-host" 54 | state: disabled 55 | register: host 56 | - name: verify test disable host 57 | assert: 58 | that: 59 | - host|changed 60 | - host.state == "disabled" 61 | - host.pod == "{{ test_cs_host_pod }}" 62 | - host.username == "{{ test_cs_host_username }}" 63 | - host.password == "{{ test_cs_host_password }}" 64 | - host.url == "{{ test_cs_host_url }}" 65 | 66 | - name: test disable host idempotence 67 | cs_host: 68 | name: "{{ cs_resource_prefix }}-host" 69 | state: disabled 70 | register: host 71 | - name: verify test disable host idempotence 72 | assert: 73 | that: 74 | - not host|changed 75 | - host.state == "disabled" 76 | - host.pod == "{{ test_cs_host_pod }}" 77 | - host.username == "{{ test_cs_host_username }}" 78 | - host.password == "{{ test_cs_host_password }}" 79 | - host.url == "{{ test_cs_host_url }}" 80 | 81 | - name: test enable host 82 | cs_host: 83 | name: "{{ cs_resource_prefix }}-host" 84 | state: enabled 85 | register: host 86 | - name: verify test enable host 87 | assert: 88 | that: 89 | - host|changed 90 | - host.state == "enabled" 91 | - host.pod == "{{ test_cs_host_pod }}" 92 | - host.username == "{{ test_cs_host_username }}" 93 | - host.password == "{{ test_cs_host_password }}" 94 | - host.url == "{{ test_cs_host_url }}" 95 | 96 | - name: test enable host idempotence 97 | cs_host: 98 | name: "{{ cs_resource_prefix }}-host" 99 | state: enabled 100 | register: host 101 | - name: verify test enable host idempotence 102 | assert: 103 | that: 104 | - not host|changed 105 | - host.state == "enabled" 106 | - host.pod == "{{ test_cs_host_pod }}" 107 | - host.username == "{{ test_cs_host_username }}" 108 | - host.password == "{{ test_cs_host_password }}" 109 | - host.url == "{{ test_cs_host_url }}" 110 | 111 | - name: test absent host 112 | cs_host: 113 | name: "{{ cs_resource_prefix }}-host" 114 | state: absent 115 | register: host 116 | - name: verify test create host 117 | assert: 118 | that: 119 | - host|changed 120 | - host.pod == "{{ test_cs_host_pod }}" 121 | - host.username == "{{ test_cs_host_username }}" 122 | - host.password == "{{ test_cs_host_password }}" 123 | - host.url == "{{ test_cs_host_url }}" 124 | 125 | - name: test absent host idempotence 126 | cs_host: 127 | name: "{{ cs_resource_prefix }}-host" 128 | state: absent 129 | register: host 130 | - name: verify test absent host idempotence 131 | assert: 132 | that: 133 | - not host|changed 134 | - host.pod == "{{ test_cs_host_pod }}" 135 | - host.username == "{{ test_cs_host_username }}" 136 | - host.password == "{{ test_cs_host_password }}" 137 | - host.url == "{{ test_cs_host_url }}" 138 | -------------------------------------------------------------------------------- /tests/roles/test_cs_instance/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | instance_number: 1 3 | test_cs_instance_template: CentOS 5.3(64-bit) no GUI (Simulator) 4 | test_cs_instance_offering_1: Small Instance 5 | test_cs_instance_offering_2: Medium Instance 6 | -------------------------------------------------------------------------------- /tests/roles/test_cs_instance/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - test_cs_common 4 | -------------------------------------------------------------------------------- /tests/roles/test_cs_instance/tasks/absent.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: test destroy instance 3 | cs_instance: 4 | name: "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 5 | state: absent 6 | register: instance 7 | - name: verify destroy instance 8 | assert: 9 | that: 10 | - instance|success 11 | - instance|changed 12 | - instance.state == "Destroyed" 13 | 14 | - name: test destroy instance idempotence 15 | cs_instance: 16 | name: "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 17 | state: absent 18 | register: instance 19 | - name: verify destroy instance idempotence 20 | assert: 21 | that: 22 | - instance|success 23 | - not instance|changed 24 | 25 | - name: test recover to stopped state and update a deleted instance 26 | cs_instance: 27 | name: "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 28 | service_offering: "{{ test_cs_instance_offering_1 }}" 29 | state: stopped 30 | register: instance 31 | - name: verify test recover to stopped state and update a deleted instance 32 | assert: 33 | that: 34 | - instance|success 35 | - instance|changed 36 | - instance.state == "Stopped" 37 | - instance.service_offering == "{{ test_cs_instance_offering_1 }}" 38 | 39 | # force expunge, only works with admin permissions 40 | - cs_instance: 41 | name: "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 42 | state: expunged 43 | failed_when: false 44 | -------------------------------------------------------------------------------- /tests/roles/test_cs_instance/tasks/absent_display_name.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: test destroy instance with display_name 3 | cs_instance: 4 | display_name: "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 5 | state: absent 6 | register: instance 7 | - name: verify destroy instance with display_name 8 | assert: 9 | that: 10 | - instance|success 11 | - instance|changed 12 | - instance.state == "Destroyed" 13 | 14 | - name: test destroy instance with display_name idempotence 15 | cs_instance: 16 | display_name: "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 17 | state: absent 18 | register: instance 19 | - name: verify destroy instance with display_name idempotence 20 | assert: 21 | that: 22 | - instance|success 23 | - not instance|changed 24 | 25 | - name: test recover to stopped state and update a deleted instance with display_name 26 | cs_instance: 27 | display_name: "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 28 | service_offering: "{{ test_cs_instance_offering_1 }}" 29 | state: stopped 30 | register: instance 31 | - name: verify test recover to stopped state and update a deleted instance with display_name 32 | assert: 33 | that: 34 | - instance|success 35 | - instance|changed 36 | - instance.state == "Stopped" 37 | - instance.service_offering == "{{ test_cs_instance_offering_1 }}" 38 | 39 | # force expunge, only works with admin permissions 40 | - cs_instance: 41 | display_name: "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 42 | state: expunged 43 | failed_when: false 44 | -------------------------------------------------------------------------------- /tests/roles/test_cs_instance/tasks/cleanup.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: cleanup ssh key 3 | cs_sshkeypair: name={{ cs_resource_prefix }}-sshkey state=absent 4 | register: sshkey 5 | - name: verify cleanup ssh key 6 | assert: 7 | that: 8 | - sshkey|success 9 | 10 | - name: cleanup affinity group 11 | cs_affinitygroup: name={{ cs_resource_prefix }}-ag state=absent 12 | register: ag 13 | until: ag|success 14 | retries: 20 15 | delay: 5 16 | - name: verify cleanup affinity group 17 | assert: 18 | that: 19 | - ag|success 20 | 21 | - name: cleanup security group ...take a while unless instance is expunged 22 | cs_securitygroup: name={{ cs_resource_prefix }}-sg state=absent 23 | register: sg 24 | until: sg|success 25 | retries: 100 26 | delay: 10 27 | - name: verify cleanup security group 28 | assert: 29 | that: 30 | - sg|success 31 | -------------------------------------------------------------------------------- /tests/roles/test_cs_instance/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - include: setup.yml 3 | - include: present.yml 4 | - include: tags.yml 5 | - include: absent.yml 6 | 7 | - include: present_display_name.yml 8 | - include: absent_display_name.yml 9 | - include: cleanup.yml 10 | -------------------------------------------------------------------------------- /tests/roles/test_cs_instance/tasks/present.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: setup instance to be absent 3 | cs_instance: name={{ cs_resource_prefix }}-vm-{{ instance_number }} state=expunged 4 | register: instance 5 | - name: verify instance to be absent 6 | assert: 7 | that: 8 | - instance|success 9 | 10 | - name: test create instance 11 | cs_instance: 12 | name: "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 13 | template: "{{ test_cs_instance_template }}" 14 | service_offering: "{{ test_cs_instance_offering_1 }}" 15 | affinity_group: "{{ cs_resource_prefix }}-ag" 16 | security_group: "{{ cs_resource_prefix }}-sg" 17 | ssh_key: "{{ cs_resource_prefix }}-sshkey" 18 | tags: [] 19 | register: instance 20 | - name: verify create instance 21 | assert: 22 | that: 23 | - instance|success 24 | - instance|changed 25 | - instance.name == "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 26 | - instance.display_name == "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 27 | - instance.service_offering == "{{ test_cs_instance_offering_1 }}" 28 | - instance.state == "Running" 29 | - instance.ssh_key == "{{ cs_resource_prefix }}-sshkey" 30 | - not instance.tags 31 | 32 | - name: test create instance idempotence 33 | cs_instance: 34 | name: "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 35 | template: "{{ test_cs_instance_template }}" 36 | service_offering: "{{ test_cs_instance_offering_1 }}" 37 | affinity_group: "{{ cs_resource_prefix }}-ag" 38 | security_group: "{{ cs_resource_prefix }}-sg" 39 | ssh_key: "{{ cs_resource_prefix }}-sshkey" 40 | tags: [] 41 | register: instance 42 | - name: verify create instance idempotence 43 | assert: 44 | that: 45 | - instance|success 46 | - not instance|changed 47 | - instance.name == "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 48 | - instance.display_name == "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 49 | - instance.service_offering == "{{ test_cs_instance_offering_1 }}" 50 | - instance.state == "Running" 51 | - instance.ssh_key == "{{ cs_resource_prefix }}-sshkey" 52 | - not instance.tags 53 | 54 | - name: test running instance not updated 55 | cs_instance: 56 | name: "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 57 | service_offering: "{{ test_cs_instance_offering_2 }}" 58 | register: instance 59 | - name: verify running instance not updated 60 | assert: 61 | that: 62 | - instance|success 63 | - not instance|changed 64 | - instance.name == "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 65 | - instance.display_name == "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 66 | - instance.service_offering == "{{ test_cs_instance_offering_1 }}" 67 | - instance.state == "Running" 68 | 69 | - name: test stopping instance 70 | cs_instance: 71 | name: "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 72 | state: stopped 73 | register: instance 74 | - name: verify stopping instance 75 | assert: 76 | that: 77 | - instance|success 78 | - instance|changed 79 | - instance.name == "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 80 | - instance.display_name == "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 81 | - instance.service_offering == "{{ test_cs_instance_offering_1 }}" 82 | - instance.state == "Stopped" 83 | 84 | - name: test stopping instance idempotence 85 | cs_instance: 86 | name: "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 87 | state: stopped 88 | register: instance 89 | - name: verify stopping instance idempotence 90 | assert: 91 | that: 92 | - instance|success 93 | - not instance|changed 94 | - instance.state == "Stopped" 95 | 96 | - name: test updating stopped instance 97 | cs_instance: 98 | name: "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 99 | display_name: "{{ cs_resource_prefix }}-display-{{ instance_number }}" 100 | service_offering: "{{ test_cs_instance_offering_2 }}" 101 | register: instance 102 | - name: verify updating stopped instance 103 | assert: 104 | that: 105 | - instance|success 106 | - instance|changed 107 | - instance.name == "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 108 | - instance.display_name == "{{ cs_resource_prefix }}-display-{{ instance_number }}" 109 | - instance.service_offering == "{{ test_cs_instance_offering_2 }}" 110 | - instance.state == "Stopped" 111 | 112 | - name: test updating stopped instance idempotence 113 | cs_instance: 114 | name: "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 115 | display_name: "{{ cs_resource_prefix }}-display-{{ instance_number }}" 116 | service_offering: "{{ test_cs_instance_offering_2 }}" 117 | register: instance 118 | - name: verify updating stopped instance idempotence 119 | assert: 120 | that: 121 | - instance|success 122 | - not instance|changed 123 | - instance.name == "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 124 | - instance.display_name == "{{ cs_resource_prefix }}-display-{{ instance_number }}" 125 | - instance.service_offering == "{{ test_cs_instance_offering_2 }}" 126 | - instance.state == "Stopped" 127 | 128 | - name: test starting instance 129 | cs_instance: 130 | name: "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 131 | state: started 132 | register: instance 133 | - name: verify starting instance 134 | assert: 135 | that: 136 | - instance|success 137 | - instance|changed 138 | - instance.name == "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 139 | - instance.display_name == "{{ cs_resource_prefix }}-display-{{ instance_number }}" 140 | - instance.service_offering == "{{ test_cs_instance_offering_2 }}" 141 | - instance.state == "Running" 142 | 143 | - name: test starting instance idempotence 144 | cs_instance: 145 | name: "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 146 | state: started 147 | register: instance 148 | - name: verify starting instance idempotence 149 | assert: 150 | that: 151 | - instance|success 152 | - not instance|changed 153 | - instance.name == "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 154 | - instance.display_name == "{{ cs_resource_prefix }}-display-{{ instance_number }}" 155 | - instance.service_offering == "{{ test_cs_instance_offering_2 }}" 156 | - instance.state == "Running" 157 | 158 | - name: test force update running instance 159 | cs_instance: 160 | name: "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 161 | service_offering: "{{ test_cs_instance_offering_1 }}" 162 | force: true 163 | register: instance 164 | - name: verify force update running instance 165 | assert: 166 | that: 167 | - instance|success 168 | - instance|changed 169 | - instance.name == "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 170 | - instance.display_name == "{{ cs_resource_prefix }}-display-{{ instance_number }}" 171 | - instance.service_offering == "{{ test_cs_instance_offering_1 }}" 172 | - instance.state == "Running" 173 | 174 | - name: test force update running instance idempotence 175 | cs_instance: 176 | name: "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 177 | service_offering: "{{ test_cs_instance_offering_1 }}" 178 | force: true 179 | register: instance 180 | - name: verify force update running instance idempotence 181 | assert: 182 | that: 183 | - instance|success 184 | - not instance|changed 185 | - instance.name == "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 186 | - instance.display_name == "{{ cs_resource_prefix }}-display-{{ instance_number }}" 187 | - instance.service_offering == "{{ test_cs_instance_offering_1 }}" 188 | - instance.state == "Running" 189 | 190 | - name: test restore instance 191 | cs_instance: 192 | name: "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 193 | template: "{{ test_cs_instance_template }}" 194 | state: restored 195 | register: instance 196 | - name: verify restore instance 197 | assert: 198 | that: 199 | - instance|success 200 | - instance|changed 201 | - instance.name == "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 202 | - instance.display_name == "{{ cs_resource_prefix }}-display-{{ instance_number }}" 203 | - instance.service_offering == "{{ test_cs_instance_offering_1 }}" 204 | -------------------------------------------------------------------------------- /tests/roles/test_cs_instance/tasks/present_display_name.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: setup instance with display_name to be absent 3 | cs_instance: display_name={{ cs_resource_prefix }}-vm-{{ instance_number }} state=expunged 4 | register: instance 5 | - name: verify instance with display_name to be absent 6 | assert: 7 | that: 8 | - instance|success 9 | 10 | - name: test create instance with display_name 11 | cs_instance: 12 | display_name: "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 13 | template: "{{ test_cs_instance_template }}" 14 | service_offering: "{{ test_cs_instance_offering_1 }}" 15 | affinity_group: "{{ cs_resource_prefix }}-ag" 16 | security_group: "{{ cs_resource_prefix }}-sg" 17 | ssh_key: "{{ cs_resource_prefix }}-sshkey" 18 | tags: [] 19 | register: instance 20 | - name: verify create instance with display_name 21 | assert: 22 | that: 23 | - instance|success 24 | - instance|changed 25 | - instance.display_name == "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 26 | - instance.service_offering == "{{ test_cs_instance_offering_1 }}" 27 | - instance.state == "Running" 28 | - instance.ssh_key == "{{ cs_resource_prefix }}-sshkey" 29 | - not instance.tags 30 | 31 | - name: test create instance with display_name idempotence 32 | cs_instance: 33 | display_name: "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 34 | template: "{{ test_cs_instance_template }}" 35 | service_offering: "{{ test_cs_instance_offering_1 }}" 36 | affinity_group: "{{ cs_resource_prefix }}-ag" 37 | security_group: "{{ cs_resource_prefix }}-sg" 38 | ssh_key: "{{ cs_resource_prefix }}-sshkey" 39 | tags: [] 40 | register: instance 41 | - name: verify create instance with display_name idempotence 42 | assert: 43 | that: 44 | - instance|success 45 | - not instance|changed 46 | - instance.display_name == "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 47 | - instance.service_offering == "{{ test_cs_instance_offering_1 }}" 48 | - instance.state == "Running" 49 | - instance.ssh_key == "{{ cs_resource_prefix }}-sshkey" 50 | - not instance.tags 51 | 52 | - name: test running instance with display_name not updated 53 | cs_instance: 54 | display_name: "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 55 | service_offering: "{{ test_cs_instance_offering_2 }}" 56 | register: instance 57 | - name: verify running instance with display_name not updated 58 | assert: 59 | that: 60 | - instance|success 61 | - not instance|changed 62 | - instance.display_name == "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 63 | - instance.service_offering == "{{ test_cs_instance_offering_1 }}" 64 | - instance.state == "Running" 65 | 66 | - name: test stopping instance with display_name 67 | cs_instance: 68 | display_name: "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 69 | state: stopped 70 | register: instance 71 | - name: verify stopping instance with display_name 72 | assert: 73 | that: 74 | - instance|success 75 | - instance|changed 76 | - instance.display_name == "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 77 | - instance.service_offering == "{{ test_cs_instance_offering_1 }}" 78 | - instance.state == "Stopped" 79 | 80 | - name: test stopping instance with display_name idempotence 81 | cs_instance: 82 | display_name: "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 83 | state: stopped 84 | register: instance 85 | - name: verify stopping instance idempotence 86 | assert: 87 | that: 88 | - instance|success 89 | - not instance|changed 90 | - instance.state == "Stopped" 91 | 92 | - name: test updating stopped instance with display_name 93 | cs_instance: 94 | display_name: "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 95 | service_offering: "{{ test_cs_instance_offering_2 }}" 96 | register: instance 97 | - name: verify updating stopped instance with display_name 98 | assert: 99 | that: 100 | - instance|success 101 | - instance|changed 102 | - instance.display_name == "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 103 | - instance.service_offering == "{{ test_cs_instance_offering_2 }}" 104 | - instance.state == "Stopped" 105 | 106 | - name: test updating stopped instance with display_name idempotence 107 | cs_instance: 108 | display_name: "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 109 | service_offering: "{{ test_cs_instance_offering_2 }}" 110 | register: instance 111 | - name: verify updating stopped instance with display_name idempotence 112 | assert: 113 | that: 114 | - instance|success 115 | - not instance|changed 116 | - instance.display_name == "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 117 | - instance.service_offering == "{{ test_cs_instance_offering_2 }}" 118 | - instance.state == "Stopped" 119 | 120 | - name: test starting instance with display_name 121 | cs_instance: 122 | display_name: "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 123 | state: started 124 | register: instance 125 | - name: verify starting instance with display_name 126 | assert: 127 | that: 128 | - instance|success 129 | - instance|changed 130 | - instance.display_name == "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 131 | - instance.service_offering == "{{ test_cs_instance_offering_2 }}" 132 | - instance.state == "Running" 133 | 134 | - name: test starting instance with display_name idempotence 135 | cs_instance: 136 | display_name: "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 137 | state: started 138 | register: instance 139 | - name: verify starting instance with display_name idempotence 140 | assert: 141 | that: 142 | - instance|success 143 | - not instance|changed 144 | - instance.display_name == "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 145 | - instance.service_offering == "{{ test_cs_instance_offering_2 }}" 146 | - instance.state == "Running" 147 | 148 | - name: test force update running instance with display_name 149 | cs_instance: 150 | display_name: "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 151 | service_offering: "{{ test_cs_instance_offering_1 }}" 152 | force: true 153 | register: instance 154 | - name: verify force update running instance with display_name 155 | assert: 156 | that: 157 | - instance|success 158 | - instance|changed 159 | - instance.display_name == "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 160 | - instance.service_offering == "{{ test_cs_instance_offering_1 }}" 161 | - instance.state == "Running" 162 | 163 | - name: test force update running instance with display_name idempotence 164 | cs_instance: 165 | display_name: "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 166 | service_offering: "{{ test_cs_instance_offering_1 }}" 167 | force: true 168 | register: instance 169 | - name: verify force update running instance with display_name idempotence 170 | assert: 171 | that: 172 | - instance|success 173 | - not instance|changed 174 | - instance.display_name == "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 175 | - instance.service_offering == "{{ test_cs_instance_offering_1 }}" 176 | - instance.state == "Running" 177 | 178 | - name: test restore instance with display_name 179 | cs_instance: 180 | display_name: "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 181 | template: "{{ test_cs_instance_template }}" 182 | state: restored 183 | register: instance 184 | - name: verify restore instance with display_name 185 | assert: 186 | that: 187 | - instance|success 188 | - instance|changed 189 | - instance.display_name == "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 190 | - instance.service_offering == "{{ test_cs_instance_offering_1 }}" 191 | -------------------------------------------------------------------------------- /tests/roles/test_cs_instance/tasks/setup.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: setup ssh key 3 | cs_sshkeypair: name={{ cs_resource_prefix }}-sshkey 4 | register: sshkey 5 | - name: verify setup ssh key 6 | assert: 7 | that: 8 | - sshkey|success 9 | 10 | - name: setup affinity group 11 | cs_affinitygroup: name={{ cs_resource_prefix }}-ag 12 | register: ag 13 | - name: verify setup affinity group 14 | assert: 15 | that: 16 | - ag|success 17 | 18 | - name: setup security group 19 | cs_securitygroup: name={{ cs_resource_prefix }}-sg 20 | register: sg 21 | - name: verify setup security group 22 | assert: 23 | that: 24 | - sg|success 25 | -------------------------------------------------------------------------------- /tests/roles/test_cs_instance/tasks/tags.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: test add tags to instance 3 | cs_instance: 4 | name: "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 5 | template: "{{ test_cs_instance_template }}" 6 | service_offering: "{{ test_cs_instance_offering_1 }}" 7 | tags: 8 | - { key: "{{ cs_resource_prefix }}-tag1", value: "{{ cs_resource_prefix }}-value1" } 9 | - { key: "{{ cs_resource_prefix }}-tag2", value: "{{ cs_resource_prefix }}-value2" } 10 | register: instance 11 | - name: verify add tags to instance 12 | assert: 13 | that: 14 | - instance|success 15 | - instance|changed 16 | - instance.tags|length == 2 17 | - "instance.tags[0]['key'] in [ '{{ cs_resource_prefix }}-tag2', '{{ cs_resource_prefix }}-tag1' ]" 18 | - "instance.tags[1]['key'] in [ '{{ cs_resource_prefix }}-tag2', '{{ cs_resource_prefix }}-tag1' ]" 19 | - "instance.tags[0]['value'] in [ '{{ cs_resource_prefix }}-value2', '{{ cs_resource_prefix }}-value1' ]" 20 | - "instance.tags[1]['value'] in [ '{{ cs_resource_prefix }}-value2', '{{ cs_resource_prefix }}-value1' ]" 21 | 22 | - name: test tags to instance idempotence 23 | cs_instance: 24 | name: "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 25 | tags: 26 | - { key: "{{ cs_resource_prefix }}-tag1", value: "{{ cs_resource_prefix }}-value1" } 27 | - { key: "{{ cs_resource_prefix }}-tag2", value: "{{ cs_resource_prefix }}-value2" } 28 | register: instance 29 | - name: verify tags to instance idempotence 30 | assert: 31 | that: 32 | - instance|success 33 | - not instance|changed 34 | - instance.tags|length == 2 35 | - "instance.tags[0]['key'] in [ '{{ cs_resource_prefix }}-tag2', '{{ cs_resource_prefix }}-tag1' ]" 36 | - "instance.tags[1]['key'] in [ '{{ cs_resource_prefix }}-tag2', '{{ cs_resource_prefix }}-tag1' ]" 37 | - "instance.tags[0]['value'] in [ '{{ cs_resource_prefix }}-value2', '{{ cs_resource_prefix }}-value1' ]" 38 | - "instance.tags[1]['value'] in [ '{{ cs_resource_prefix }}-value2', '{{ cs_resource_prefix }}-value1' ]" 39 | 40 | - name: test change tags of instance 41 | cs_instance: 42 | name: "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 43 | tags: 44 | - { key: "{{ cs_resource_prefix }}-tag2", value: "{{ cs_resource_prefix }}-value2" } 45 | - { key: "{{ cs_resource_prefix }}-tag3", value: "{{ cs_resource_prefix }}-value3" } 46 | register: instance 47 | - name: verify tags to instance idempotence 48 | assert: 49 | that: 50 | - instance|success 51 | - instance|changed 52 | - instance.tags|length == 2 53 | - "instance.tags[0]['key'] in [ '{{ cs_resource_prefix }}-tag2', '{{ cs_resource_prefix }}-tag3' ]" 54 | - "instance.tags[1]['key'] in [ '{{ cs_resource_prefix }}-tag2', '{{ cs_resource_prefix }}-tag3' ]" 55 | - "instance.tags[0]['value'] in [ '{{ cs_resource_prefix }}-value2', '{{ cs_resource_prefix }}-value3' ]" 56 | - "instance.tags[1]['value'] in [ '{{ cs_resource_prefix }}-value2', '{{ cs_resource_prefix }}-value3' ]" 57 | 58 | - name: test not touch tags of instance if no param tags 59 | cs_instance: 60 | name: "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 61 | register: instance 62 | - name: verify not touch tags of instance if no param tags 63 | assert: 64 | that: 65 | - instance|success 66 | - not instance|changed 67 | - instance.tags|length == 2 68 | - "instance.tags[0]['key'] in [ '{{ cs_resource_prefix }}-tag2', '{{ cs_resource_prefix }}-tag3' ]" 69 | - "instance.tags[1]['key'] in [ '{{ cs_resource_prefix }}-tag2', '{{ cs_resource_prefix }}-tag3' ]" 70 | - "instance.tags[0]['value'] in [ '{{ cs_resource_prefix }}-value2', '{{ cs_resource_prefix }}-value3' ]" 71 | - "instance.tags[1]['value'] in [ '{{ cs_resource_prefix }}-value2', '{{ cs_resource_prefix }}-value3' ]" 72 | 73 | - name: test remove tags 74 | cs_instance: 75 | name: "{{ cs_resource_prefix }}-vm-{{ instance_number }}" 76 | tags: [] 77 | register: instance 78 | - name: verify remove tags 79 | assert: 80 | that: 81 | - instance|success 82 | - instance|changed 83 | - instance.tags|length == 0 84 | -------------------------------------------------------------------------------- /tests/roles/test_cs_instance_facts/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | test_cs_instance_template: CentOS 5.3(64-bit) no GUI (Simulator) 3 | test_cs_instance_offering_1: Small Instance 4 | -------------------------------------------------------------------------------- /tests/roles/test_cs_instance_facts/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - test_cs_common 4 | -------------------------------------------------------------------------------- /tests/roles/test_cs_instance_facts/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: setup ssh key 3 | cs_sshkeypair: name={{ cs_resource_prefix }}-sshkey 4 | register: sshkey 5 | - name: verify setup ssh key 6 | assert: 7 | that: 8 | - sshkey|success 9 | 10 | - name: setup affinity group 11 | cs_affinitygroup: name={{ cs_resource_prefix }}-ag 12 | register: ag 13 | - name: verify setup affinity group 14 | assert: 15 | that: 16 | - ag|success 17 | 18 | - name: setup security group 19 | cs_securitygroup: name={{ cs_resource_prefix }}-sg 20 | register: sg 21 | - name: verify setup security group 22 | assert: 23 | that: 24 | - sg|success 25 | 26 | - name: setup instance 27 | cs_instance: 28 | name: "{{ cs_resource_prefix }}-vm" 29 | template: "{{ test_cs_instance_template }}" 30 | service_offering: "{{ test_cs_instance_offering_1 }}" 31 | affinity_group: "{{ cs_resource_prefix }}-ag" 32 | security_group: "{{ cs_resource_prefix }}-sg" 33 | ssh_key: "{{ cs_resource_prefix }}-sshkey" 34 | tags: [] 35 | register: instance 36 | - name: verify create instance 37 | assert: 38 | that: 39 | - instance|success 40 | 41 | - name: test instance facts 42 | cs_instance_facts: 43 | name: "{{ cs_resource_prefix }}-vm" 44 | register: instance_facts 45 | - name: verify test instance facts 46 | assert: 47 | that: 48 | - instance_facts|success 49 | - not instance_facts|changed 50 | - cloudstack_instance.id == instance.id 51 | - cloudstack_instance.domain == instance.domain 52 | - cloudstack_instance.account == instance.account 53 | - cloudstack_instance.zone == instance.zone 54 | - cloudstack_instance.name == instance.name 55 | - cloudstack_instance.service_offering == instance.service_offering 56 | -------------------------------------------------------------------------------- /tests/roles/test_cs_instancegroup/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - test_cs_common 4 | -------------------------------------------------------------------------------- /tests/roles/test_cs_instancegroup/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: setup 3 | cs_instancegroup: name={{ cs_resource_prefix }}_ig state=absent 4 | register: ig 5 | - name: verify setup 6 | assert: 7 | that: 8 | - ig|success 9 | 10 | - name: test fail if missing name 11 | action: cs_instancegroup 12 | register: ig 13 | ignore_errors: true 14 | - name: verify results of fail if missing name 15 | assert: 16 | that: 17 | - ig|failed 18 | - "ig.msg == 'missing required arguments: name'" 19 | 20 | - name: test present instance group 21 | cs_instancegroup: name={{ cs_resource_prefix }}_ig 22 | register: ig 23 | - name: verify results of create instance group 24 | assert: 25 | that: 26 | - ig|success 27 | - ig|changed 28 | - ig.name == "{{ cs_resource_prefix }}_ig" 29 | 30 | - name: test present instance group is idempotence 31 | cs_instancegroup: name={{ cs_resource_prefix }}_ig 32 | register: ig 33 | - name: verify results present instance group is idempotence 34 | assert: 35 | that: 36 | - ig|success 37 | - not ig|changed 38 | - ig.name == "{{ cs_resource_prefix }}_ig" 39 | 40 | - name: test absent instance group 41 | cs_instancegroup: name={{ cs_resource_prefix }}_ig state=absent 42 | register: ig 43 | - name: verify results of absent instance group 44 | assert: 45 | that: 46 | - ig|success 47 | - ig|changed 48 | - ig.name == "{{ cs_resource_prefix }}_ig" 49 | 50 | - name: test absent instance group is idempotence 51 | cs_instancegroup: name={{ cs_resource_prefix }}_ig state=absent 52 | register: ig 53 | - name: verify results of absent instance group is idempotence 54 | assert: 55 | that: 56 | - ig|success 57 | - not ig|changed 58 | - ig.name is undefined 59 | -------------------------------------------------------------------------------- /tests/roles/test_cs_iso/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - test_cs_common 4 | -------------------------------------------------------------------------------- /tests/roles/test_cs_iso/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: ensure iso is deleted 3 | cs_iso: 4 | name: "{{ cs_resource_prefix }}-iso" 5 | state: absent 6 | register: iso 7 | - name: verify ensure iso is deleted 8 | assert: 9 | that: 10 | - iso|success 11 | 12 | - name: test download iso 13 | cs_iso: 14 | name: "{{ cs_resource_prefix }}-iso" 15 | url: http://mirror.switch.ch/ftp/mirror/debian-cd/current/amd64/iso-cd/debian-7.7.0-amd64-netinst.iso 16 | os_type: Debian GNU/Linux 7(64-bit) 17 | register: iso 18 | - name: verify test download iso 19 | assert: 20 | that: 21 | - iso|changed 22 | - iso.name == "{{ cs_resource_prefix }}-iso" 23 | 24 | - name: test download iso idempotence 25 | cs_iso: 26 | name: "{{ cs_resource_prefix }}-iso" 27 | url: http://mirror.switch.ch/ftp/mirror/debian-cd/current/amd64/iso-cd/debian-7.7.0-amd64-netinst.iso 28 | os_type: Debian GNU/Linux 7(64-bit) 29 | register: iso 30 | - name: verify test download iso idempotence 31 | assert: 32 | that: 33 | - not iso|changed 34 | - iso.name == "{{ cs_resource_prefix }}-iso" 35 | 36 | # TODO: on 4.6 simulator no checksum was returned 37 | # TODO: check if this is a bug in 4.6 38 | #- name: test download iso idempotence by checksum 39 | # cs_iso: 40 | # name: "{{ cs_resource_prefix }}-iso2" 41 | # checksum: "{{ iso.checksum }}" 42 | # url: http://mirror.switch.ch/ftp/mirror/debian-cd/current/amd64/iso-cd/debian-7.7.0-amd64-netinst.iso 43 | # os_type: Debian GNU/Linux 7(64-bit) 44 | # register: iso2 45 | #- name: verify test download iso idempotence by checksum 46 | # assert: 47 | # that: 48 | # - not iso2|changed 49 | # - iso2.name == "{{ cs_resource_prefix }}-iso" 50 | # - iso2.checksum == iso.checksum 51 | 52 | - name: test remove iso 53 | cs_iso: 54 | name: "{{ cs_resource_prefix }}-iso" 55 | state: absent 56 | register: iso 57 | - name: verify test remove iso 58 | assert: 59 | that: 60 | - iso|changed 61 | - iso.name == "{{ cs_resource_prefix }}-iso" 62 | 63 | - name: test remove iso idempotence 64 | cs_iso: 65 | name: "{{ cs_resource_prefix }}-iso" 66 | state: absent 67 | register: iso 68 | - name: verify test remove iso idempotence 69 | assert: 70 | that: 71 | - not iso|changed 72 | -------------------------------------------------------------------------------- /tests/roles/test_cs_loadbalancer_rule/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | test_cs_lb_public_ip: "1.2.3.4" 3 | test_cs_instance_template: CentOS 5.3(64-bit) no GUI (Simulator) 4 | test_cs_instance_offering_1: Small Instance 5 | test_cs_lb_member: "{{ cs_resource_prefix }}_member1" 6 | -------------------------------------------------------------------------------- /tests/roles/test_cs_loadbalancer_rule/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - test_cs_common 4 | -------------------------------------------------------------------------------- /tests/roles/test_cs_loadbalancer_rule/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: setup 3 | cs_loadbalancer_rule: 4 | name: "{{ cs_resource_prefix }}_lb" 5 | public_ip: "{{ test_cs_lb_public_ip }}" 6 | state: absent 7 | register: lb 8 | - name: verify setup 9 | assert: 10 | that: 11 | - lb|success 12 | 13 | - name: setup instance 14 | cs_instance: 15 | name: "{{ test_cs_lb_member }}" 16 | template: "{{ test_cs_instance_template }}" 17 | service_offering: "{{ test_cs_instance_offering_1 }}" 18 | register: instance 19 | - name: verify create instance 20 | assert: 21 | that: 22 | - instance|success 23 | 24 | - name: test rule requires params 25 | cs_loadbalancer_rule: 26 | ignore_errors: true 27 | register: lb 28 | - name: verify test rule requires params 29 | assert: 30 | that: 31 | - lb|failed 32 | - "'ip_address,name' in lb.msg" 33 | 34 | - name: test create rule 35 | cs_loadbalancer_rule: 36 | name: "{{ cs_resource_prefix }}_lb" 37 | public_ip: "{{ test_cs_lb_public_ip }}" 38 | algorithm: roundrobin 39 | public_port: 80 40 | private_port: 8080 41 | register: lb 42 | - name: verify test create rule 43 | assert: 44 | that: 45 | - lb|success 46 | - lb|changed 47 | - lb.name == "{{ cs_resource_prefix }}_lb" 48 | - lb.algorithm == "roundrobin" 49 | - lb.public_ip == "{{ test_cs_lb_public_ip }}" 50 | - lb.public_port == 80 51 | - lb.private_port == 8080 52 | 53 | - name: test create rule idempotence 54 | cs_loadbalancer_rule: 55 | name: "{{ cs_resource_prefix }}_lb" 56 | public_ip: "{{ test_cs_lb_public_ip }}" 57 | algorithm: roundrobin 58 | public_port: 80 59 | private_port: 8080 60 | register: lb 61 | - name: verify test create rule idempotence 62 | assert: 63 | that: 64 | - lb|success 65 | - not lb|changed 66 | - lb.name == "{{ cs_resource_prefix }}_lb" 67 | - lb.algorithm == "roundrobin" 68 | - lb.public_ip == "{{ test_cs_lb_public_ip }}" 69 | - lb.public_port == 80 70 | - lb.private_port == 8080 71 | 72 | - name: test update rule 73 | cs_loadbalancer_rule: 74 | name: "{{ cs_resource_prefix }}_lb" 75 | public_ip: "{{ test_cs_lb_public_ip }}" 76 | algorithm: source 77 | public_port: 80 78 | private_port: 8080 79 | register: lb 80 | - name: verify test update rule 81 | assert: 82 | that: 83 | - lb|success 84 | - lb|changed 85 | - lb.name == "{{ cs_resource_prefix }}_lb" 86 | - lb.algorithm == "source" 87 | - lb.public_ip == "{{ test_cs_lb_public_ip }}" 88 | - lb.public_port == 80 89 | - lb.private_port == 8080 90 | 91 | - name: test update rule idempotence 92 | cs_loadbalancer_rule: 93 | name: "{{ cs_resource_prefix }}_lb" 94 | public_ip: "{{ test_cs_lb_public_ip }}" 95 | algorithm: source 96 | public_port: 80 97 | private_port: 8080 98 | register: lb 99 | - name: verify test update rule idempotence 100 | assert: 101 | that: 102 | - lb|success 103 | - not lb|changed 104 | - lb.name == "{{ cs_resource_prefix }}_lb" 105 | - lb.algorithm == "source" 106 | - lb.public_ip == "{{ test_cs_lb_public_ip }}" 107 | - lb.public_port == 80 108 | - lb.private_port == 8080 109 | 110 | - name: test rule member requires params 111 | cs_loadbalancer_rule_member: 112 | ignore_errors: true 113 | register: lb 114 | - name: verify test rule requires params 115 | assert: 116 | that: 117 | - lb|failed 118 | - "'vms,name' in lb.msg" 119 | 120 | - name: test add members to rule 121 | cs_loadbalancer_rule_member: 122 | name: "{{ cs_resource_prefix }}_lb" 123 | vm: "{{ test_cs_lb_member }}" 124 | register: lb 125 | - name: verify add members to rule 126 | assert: 127 | that: 128 | - lb|success 129 | - lb|changed 130 | - lb.name == "{{ cs_resource_prefix }}_lb" 131 | - lb.algorithm == "source" 132 | - lb.public_ip == "{{ test_cs_lb_public_ip }}" 133 | - lb.public_port == 80 134 | - lb.private_port == 8080 135 | - "'{{ test_cs_lb_member }}' in lb.vms" 136 | 137 | - name: test add members to rule idempotence 138 | cs_loadbalancer_rule_member: 139 | name: "{{ cs_resource_prefix }}_lb" 140 | vm: "{{ test_cs_lb_member }}" 141 | register: lb 142 | - name: verify add members to rule idempotence 143 | assert: 144 | that: 145 | - lb|success 146 | - not lb|changed 147 | - lb.name == "{{ cs_resource_prefix }}_lb" 148 | - lb.algorithm == "source" 149 | - lb.public_ip == "{{ test_cs_lb_public_ip }}" 150 | - lb.public_port == 80 151 | - lb.private_port == 8080 152 | - "'{{ test_cs_lb_member }}' in lb.vms" 153 | 154 | - name: test remove members to rule 155 | cs_loadbalancer_rule_member: 156 | name: "{{ cs_resource_prefix }}_lb" 157 | vm: "{{ test_cs_lb_member }}" 158 | state: absent 159 | register: lb 160 | - name: verify remove members to rule 161 | assert: 162 | that: 163 | - lb|success 164 | - lb|changed 165 | - lb.name == "{{ cs_resource_prefix }}_lb" 166 | - lb.algorithm == "source" 167 | - lb.public_ip == "{{ test_cs_lb_public_ip }}" 168 | - lb.public_port == 80 169 | - lb.private_port == 8080 170 | - "'{{ test_cs_lb_member }}' not in lb.vms" 171 | 172 | - name: test remove members to rule idempotence 173 | cs_loadbalancer_rule_member: 174 | name: "{{ cs_resource_prefix }}_lb" 175 | vm: "{{ test_cs_lb_member }}" 176 | state: absent 177 | register: lb 178 | - name: verify remove members to rule 179 | assert: 180 | that: 181 | - lb|success 182 | - not lb|changed 183 | 184 | - name: test remove rule 185 | cs_loadbalancer_rule: 186 | name: "{{ cs_resource_prefix }}_lb" 187 | public_ip: "{{ test_cs_lb_public_ip }}" 188 | state: absent 189 | register: lb 190 | - name: verify remove rule 191 | assert: 192 | that: 193 | - lb|success 194 | - lb|changed 195 | - lb.name == "{{ cs_resource_prefix }}_lb" 196 | - lb.algorithm == "source" 197 | - lb.public_ip == "{{ test_cs_lb_public_ip }}" 198 | - lb.public_port == 80 199 | - lb.private_port == 8080 200 | 201 | - name: test remove rule idempotence 202 | cs_loadbalancer_rule: 203 | name: "{{ cs_resource_prefix }}_lb" 204 | public_ip: "{{ test_cs_lb_public_ip }}" 205 | state: absent 206 | register: lb 207 | - name: verify remove rule idempotence 208 | assert: 209 | that: 210 | - lb|success 211 | - not lb|changed 212 | -------------------------------------------------------------------------------- /tests/roles/test_cs_pod/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - test_cs_common 4 | -------------------------------------------------------------------------------- /tests/roles/test_cs_pod/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: setup pod is absent 3 | cs_pod: 4 | name: "{{ cs_resource_prefix }}-pod" 5 | state: absent 6 | register: pod 7 | - name: verify setup pod is absent 8 | assert: 9 | that: 10 | - pod|success 11 | 12 | - name: setup zone is present 13 | cs_zone: 14 | name: "{{ cs_resource_prefix }}-zone" 15 | dns1: 8.8.8.8 16 | dns2: 8.8.4.4 17 | network_type: basic 18 | register: zone 19 | - name: verify setup zone is present 20 | assert: 21 | that: 22 | - zone|success 23 | 24 | - name: test fail if missing name 25 | cs_pod: 26 | register: pod 27 | ignore_errors: true 28 | - name: verify results of fail if missing name 29 | assert: 30 | that: 31 | - pod|failed 32 | - "pod.msg == 'missing required arguments: name'" 33 | 34 | - name: test create pod 35 | cs_pod: 36 | name: "{{ cs_resource_prefix }}-pod" 37 | zone: "{{ cs_resource_prefix }}-zone" 38 | start_ip: 10.100.10.101 39 | gateway: 10.100.10.1 40 | netmask: 255.255.255.0 41 | register: pod_origin 42 | - name: verify test create pod 43 | assert: 44 | that: 45 | - pod_origin|changed 46 | - pod_origin.allocation_state == "Enabled" 47 | - pod_origin.start_ip == "10.100.10.101" 48 | - pod_origin.end_ip == "10.100.10.254" 49 | - pod_origin.gateway == "10.100.10.1" 50 | - pod_origin.netmask == "255.255.255.0" 51 | - pod_origin.zone == "{{ cs_resource_prefix }}-zone" 52 | 53 | - name: test create pod idempotence 54 | cs_pod: 55 | name: "{{ cs_resource_prefix }}-pod" 56 | zone: "{{ cs_resource_prefix }}-zone" 57 | start_ip: 10.100.10.101 58 | gateway: 10.100.10.1 59 | netmask: 255.255.255.0 60 | register: pod 61 | - name: verify test create pod idempotence 62 | assert: 63 | that: 64 | - not pod|changed 65 | - pod.allocation_state == "Enabled" 66 | - pod.start_ip == "10.100.10.101" 67 | - pod.end_ip == "10.100.10.254" 68 | - pod.gateway == "10.100.10.1" 69 | - pod.netmask == "255.255.255.0" 70 | - pod.zone == "{{ cs_resource_prefix }}-zone" 71 | 72 | - name: test update pod 73 | cs_pod: 74 | name: "{{ cs_resource_prefix }}-pod" 75 | zone: "{{ cs_resource_prefix }}-zone" 76 | start_ip: 10.100.10.102 77 | gateway: 10.100.10.1 78 | netmask: 255.255.255.0 79 | register: pod 80 | - name: verify test update pod 81 | assert: 82 | that: 83 | - pod|changed 84 | - pod.allocation_state == "Enabled" 85 | - pod.start_ip == "10.100.10.102" 86 | - pod.end_ip == "10.100.10.254" 87 | - pod.gateway == "10.100.10.1" 88 | - pod.netmask == "255.255.255.0" 89 | - pod.zone == "{{ cs_resource_prefix }}-zone" 90 | 91 | - name: test update pod idempotence 92 | cs_pod: 93 | name: "{{ cs_resource_prefix }}-pod" 94 | zone: "{{ cs_resource_prefix }}-zone" 95 | start_ip: 10.100.10.102 96 | gateway: 10.100.10.1 97 | netmask: 255.255.255.0 98 | register: pod 99 | - name: verify test update pod idempotence 100 | assert: 101 | that: 102 | - not pod|changed 103 | - pod.allocation_state == "Enabled" 104 | - pod.start_ip == "10.100.10.102" 105 | - pod.end_ip == "10.100.10.254" 106 | - pod.gateway == "10.100.10.1" 107 | - pod.netmask == "255.255.255.0" 108 | - pod.zone == "{{ cs_resource_prefix }}-zone" 109 | 110 | - name: test disable pod 111 | cs_pod: 112 | name: "{{ cs_resource_prefix }}-pod" 113 | zone: "{{ cs_resource_prefix }}-zone" 114 | state: disabled 115 | register: pod 116 | - name: verify test enable pod 117 | assert: 118 | that: 119 | - pod|changed 120 | - pod.allocation_state == "Disabled" 121 | - pod.id == pod_origin.id 122 | - pod.start_ip == "10.100.10.102" 123 | - pod.end_ip == "10.100.10.254" 124 | - pod.gateway == "10.100.10.1" 125 | - pod.netmask == "255.255.255.0" 126 | - pod.zone == "{{ cs_resource_prefix }}-zone" 127 | 128 | - name: test disable pod idempotence 129 | cs_pod: 130 | name: "{{ cs_resource_prefix }}-pod" 131 | zone: "{{ cs_resource_prefix }}-zone" 132 | state: disabled 133 | register: pod 134 | - name: verify test enable pod idempotence 135 | assert: 136 | that: 137 | - not pod|changed 138 | - pod.allocation_state == "Disabled" 139 | - pod.id == pod_origin.id 140 | - pod.start_ip == "10.100.10.102" 141 | - pod.end_ip == "10.100.10.254" 142 | - pod.gateway == "10.100.10.1" 143 | - pod.netmask == "255.255.255.0" 144 | - pod.zone == "{{ cs_resource_prefix }}-zone" 145 | 146 | - name: test enable pod 147 | cs_pod: 148 | name: "{{ cs_resource_prefix }}-pod" 149 | zone: "{{ cs_resource_prefix }}-zone" 150 | state: enabled 151 | register: pod 152 | - name: verify test disable pod 153 | assert: 154 | that: 155 | - pod|changed 156 | - pod.allocation_state == "Enabled" 157 | - pod.id == pod_origin.id 158 | - pod.start_ip == "10.100.10.102" 159 | - pod.end_ip == "10.100.10.254" 160 | - pod.gateway == "10.100.10.1" 161 | - pod.netmask == "255.255.255.0" 162 | - pod.zone == "{{ cs_resource_prefix }}-zone" 163 | 164 | 165 | - name: test enable pod idempotence 166 | cs_pod: 167 | name: "{{ cs_resource_prefix }}-pod" 168 | zone: "{{ cs_resource_prefix }}-zone" 169 | state: enabled 170 | register: pod 171 | - name: verify test enabled pod idempotence 172 | assert: 173 | that: 174 | - not pod|changed 175 | - pod.allocation_state == "Enabled" 176 | - pod.id == pod_origin.id 177 | - pod.start_ip == "10.100.10.102" 178 | - pod.end_ip == "10.100.10.254" 179 | - pod.gateway == "10.100.10.1" 180 | - pod.netmask == "255.255.255.0" 181 | - pod.zone == "{{ cs_resource_prefix }}-zone" 182 | 183 | - name: test absent pod 184 | cs_pod: 185 | name: "{{ cs_resource_prefix }}-pod" 186 | zone: "{{ cs_resource_prefix }}-zone" 187 | state: absent 188 | register: pod 189 | - name: verify test create pod 190 | assert: 191 | that: 192 | - pod|changed 193 | - pod.id == pod_origin.id 194 | - pod.allocation_state == "Enabled" 195 | - pod.start_ip == "10.100.10.102" 196 | - pod.end_ip == "10.100.10.254" 197 | - pod.gateway == "10.100.10.1" 198 | - pod.netmask == "255.255.255.0" 199 | - pod.zone == "{{ cs_resource_prefix }}-zone" 200 | 201 | - name: test absent pod idempotence 202 | cs_pod: 203 | name: "{{ cs_resource_prefix }}-pod" 204 | zone: "{{ cs_resource_prefix }}-zone" 205 | state: absent 206 | register: pod 207 | - name: verify test absent pod idempotence 208 | assert: 209 | that: 210 | - not pod|changed 211 | -------------------------------------------------------------------------------- /tests/roles/test_cs_portforward/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | cs_portforward_public_ip: "10.100.212.5" 3 | cs_portforward_vm: "{{ cs_resource_prefix }}-vm" 4 | -------------------------------------------------------------------------------- /tests/roles/test_cs_portforward/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - test_cs_common 4 | -------------------------------------------------------------------------------- /tests/roles/test_cs_portforward/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: setup 3 | cs_portforward: 4 | ip_address: "{{ cs_portforward_public_ip }}" 5 | public_port: 80 6 | private_port: 8080 7 | state: absent 8 | register: pf 9 | - name: verify setup 10 | assert: 11 | that: 12 | - pf|success 13 | 14 | - name: test fail if missing params 15 | action: cs_portforward 16 | register: pf 17 | ignore_errors: true 18 | - name: verify results of fail if missing params 19 | assert: 20 | that: 21 | - pf|failed 22 | - 'pf.msg == "missing required arguments: private_port,ip_address,public_port"' 23 | 24 | - name: test present port forwarding 25 | cs_portforward: 26 | ip_address: "{{ cs_portforward_public_ip }}" 27 | public_port: 80 28 | vm: "{{ cs_portforward_vm }}" 29 | private_port: 8080 30 | register: pf 31 | - name: verify results of present port forwarding 32 | assert: 33 | that: 34 | - pf|success 35 | - pf|changed 36 | - pf.vm_name == "{{ cs_portforward_vm }}" 37 | - pf.ip_address == "{{ cs_portforward_public_ip }}" 38 | - pf.public_port == 80 39 | - pf.public_end_port == 80 40 | - pf.private_port == 8080 41 | - pf.private_end_port == 8080 42 | 43 | - name: test present port forwarding idempotence 44 | cs_portforward: 45 | ip_address: "{{ cs_portforward_public_ip }}" 46 | public_port: 80 47 | vm: "{{ cs_portforward_vm }}" 48 | private_port: 8080 49 | register: pf 50 | - name: verify results of present port forwarding idempotence 51 | assert: 52 | that: 53 | - pf|success 54 | - not pf|changed 55 | - pf.vm_name == "{{ cs_portforward_vm }}" 56 | - pf.ip_address == "{{ cs_portforward_public_ip }}" 57 | - pf.public_port == 80 58 | - pf.public_end_port == 80 59 | - pf.private_port == 8080 60 | - pf.private_end_port == 8080 61 | 62 | - name: test change port forwarding 63 | cs_portforward: 64 | ip_address: "{{ cs_portforward_public_ip }}" 65 | public_port: 80 66 | vm: "{{ cs_portforward_vm }}" 67 | private_port: 8888 68 | register: pf 69 | - name: verify results of change port forwarding 70 | assert: 71 | that: 72 | - pf|success 73 | - pf|changed 74 | - pf.vm_name == "{{ cs_portforward_vm }}" 75 | - pf.ip_address == "{{ cs_portforward_public_ip }}" 76 | - pf.public_port == 80 77 | - pf.public_end_port == 80 78 | - pf.private_port == 8888 79 | - pf.private_end_port == 8888 80 | 81 | - name: test absent port forwarding 82 | cs_portforward: 83 | ip_address: "{{ cs_portforward_public_ip }}" 84 | public_port: 80 85 | private_port: 8888 86 | state: absent 87 | register: pf 88 | - name: verify results of absent port forwarding 89 | assert: 90 | that: 91 | - pf|success 92 | - pf|changed 93 | - pf.vm_name == "{{ cs_portforward_vm }}" 94 | - pf.ip_address == "{{ cs_portforward_public_ip }}" 95 | - pf.public_port == 80 96 | - pf.public_end_port == 80 97 | - pf.private_port == 8888 98 | - pf.private_end_port == 8888 99 | 100 | - name: test absent port forwarding idempotence 101 | cs_portforward: 102 | ip_address: "{{ cs_portforward_public_ip }}" 103 | public_port: 80 104 | private_port: 8888 105 | state: absent 106 | register: pf 107 | - name: verify results of absent port forwarding idempotence 108 | assert: 109 | that: 110 | - pf|success 111 | - not pf|changed 112 | -------------------------------------------------------------------------------- /tests/roles/test_cs_project/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - test_cs_common 4 | -------------------------------------------------------------------------------- /tests/roles/test_cs_project/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: ensure project does not exist 3 | cs_project: 4 | name: "{{ cs_resource_prefix }}-prj" 5 | state: absent 6 | register: prj 7 | - name: verify project did not exist 8 | assert: 9 | that: 10 | - prj|success 11 | 12 | - name: test create project 13 | cs_project: 14 | name: "{{ cs_resource_prefix }}-prj" 15 | register: prj 16 | - name: verify test create project 17 | assert: 18 | that: 19 | - prj|changed 20 | - prj.name == "{{ cs_resource_prefix }}-prj" 21 | 22 | - name: test create project idempotence 23 | cs_project: 24 | name: "{{ cs_resource_prefix }}-prj" 25 | register: prj 26 | - name: verify test create project idempotence 27 | assert: 28 | that: 29 | - not prj|changed 30 | - prj.name == "{{ cs_resource_prefix }}-prj" 31 | 32 | - name: test suspend project 33 | cs_project: 34 | name: "{{ cs_resource_prefix }}-prj" 35 | state: suspended 36 | register: prj 37 | - name: verify test suspend project 38 | assert: 39 | that: 40 | - prj|changed 41 | - prj.name == "{{ cs_resource_prefix }}-prj" 42 | - prj.state == "Suspended" 43 | 44 | - name: test suspend project idempotence 45 | cs_project: 46 | name: "{{ cs_resource_prefix }}-prj" 47 | state: suspended 48 | register: prj 49 | - name: verify test suspend project idempotence 50 | assert: 51 | that: 52 | - not prj|changed 53 | - prj.name == "{{ cs_resource_prefix }}-prj" 54 | - prj.state == "Suspended" 55 | 56 | - name: test activate project 57 | cs_project: 58 | name: "{{ cs_resource_prefix }}-prj" 59 | state: active 60 | register: prj 61 | - name: verify test activate project 62 | assert: 63 | that: 64 | - prj|changed 65 | - prj.name == "{{ cs_resource_prefix }}-prj" 66 | - prj.state == "Active" 67 | 68 | - name: test activate project idempotence 69 | cs_project: 70 | name: "{{ cs_resource_prefix }}-prj" 71 | state: active 72 | register: prj 73 | - name: verify test activate project idempotence 74 | assert: 75 | that: 76 | - not prj|changed 77 | - prj.name == "{{ cs_resource_prefix }}-prj" 78 | - prj.state == "Active" 79 | 80 | - name: test delete project 81 | cs_project: 82 | name: "{{ cs_resource_prefix }}-prj" 83 | state: absent 84 | register: prj 85 | - name: verify test delete project 86 | assert: 87 | that: 88 | - prj|changed 89 | - prj.name == "{{ cs_resource_prefix }}-prj" 90 | - prj.state == "Active" 91 | 92 | - name: test delete project idempotence 93 | cs_project: 94 | name: "{{ cs_resource_prefix }}-prj" 95 | state: absent 96 | register: prj 97 | - name: verify test delete project idempotence 98 | assert: 99 | that: 100 | - not prj|changed 101 | -------------------------------------------------------------------------------- /tests/roles/test_cs_resourcelimit/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - test_cs_common 4 | -------------------------------------------------------------------------------- /tests/roles/test_cs_resourcelimit/tasks/cpu.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: setup cpu limits account 3 | cs_resourcelimit: 4 | type: cpu 5 | limit: 20 6 | account: "{{ cs_resource_prefix }}_user" 7 | domain: "{{ cs_resource_prefix }}-domain" 8 | register: rl 9 | - name: verify setup cpu limits account 10 | assert: 11 | that: 12 | - rl|success 13 | - rl.domain == "{{ cs_resource_prefix }}-domain" 14 | - rl.account == "{{ cs_resource_prefix }}_user" 15 | - rl.limit == 20 16 | - rl.resource_type == "cpu" 17 | 18 | - name: set cpu limits for domain 19 | cs_resourcelimit: 20 | type: cpu 21 | limit: 12 22 | domain: "{{ cs_resource_prefix }}-domain" 23 | register: rl 24 | - name: verify set cpu limits for domain 25 | assert: 26 | that: 27 | - rl|changed 28 | - rl.domain == "{{ cs_resource_prefix }}-domain" 29 | - rl.limit == 12 30 | - rl.resource_type == "cpu" 31 | 32 | - name: set cpu limits for domain idempotence 33 | cs_resourcelimit: 34 | type: cpu 35 | limit: 12 36 | domain: "{{ cs_resource_prefix }}-domain" 37 | register: rl 38 | - name: verify set cpu limits for domain 39 | assert: 40 | that: 41 | - not rl|changed 42 | - rl.domain == "{{ cs_resource_prefix }}-domain" 43 | - rl.limit == 12 44 | - rl.resource_type == "cpu" 45 | 46 | - name: set cpu limits for account 47 | cs_resourcelimit: 48 | type: cpu 49 | limit: 10 50 | account: "{{ cs_resource_prefix }}_user" 51 | domain: "{{ cs_resource_prefix }}-domain" 52 | register: rl 53 | - name: verify set cpu limits for account 54 | assert: 55 | that: 56 | - rl|changed 57 | - rl.domain == "{{ cs_resource_prefix }}-domain" 58 | - rl.account == "{{ cs_resource_prefix }}_user" 59 | - rl.limit == 10 60 | - rl.resource_type == "cpu" 61 | 62 | - name: set cpu limits for account idempotence 63 | cs_resourcelimit: 64 | type: cpu 65 | limit: 10 66 | account: "{{ cs_resource_prefix }}_user" 67 | domain: "{{ cs_resource_prefix }}-domain" 68 | register: rl 69 | - name: verify set cpu limits for account idempotence 70 | assert: 71 | that: 72 | - not rl|changed 73 | - rl.domain == "{{ cs_resource_prefix }}-domain" 74 | - rl.account == "{{ cs_resource_prefix }}_user" 75 | - rl.limit == 10 76 | - rl.resource_type == "cpu" 77 | -------------------------------------------------------------------------------- /tests/roles/test_cs_resourcelimit/tasks/instance.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: setup instance limits account 3 | cs_resourcelimit: 4 | type: instance 5 | limit: 20 6 | account: "{{ cs_resource_prefix }}_user" 7 | domain: "{{ cs_resource_prefix }}-domain" 8 | register: rl 9 | - name: verify setup instance limits account 10 | assert: 11 | that: 12 | - rl|success 13 | - rl.domain == "{{ cs_resource_prefix }}-domain" 14 | - rl.account == "{{ cs_resource_prefix }}_user" 15 | - rl.limit == 20 16 | - rl.resource_type == "instance" 17 | 18 | - name: set instance limits for domain 19 | cs_resourcelimit: 20 | type: instance 21 | limit: 12 22 | domain: "{{ cs_resource_prefix }}-domain" 23 | register: rl 24 | - name: verify set instance limits for domain 25 | assert: 26 | that: 27 | - rl|changed 28 | - rl.domain == "{{ cs_resource_prefix }}-domain" 29 | - rl.limit == 12 30 | - rl.resource_type == "instance" 31 | 32 | - name: set instance limits for domain idempotence 33 | cs_resourcelimit: 34 | type: instance 35 | limit: 12 36 | domain: "{{ cs_resource_prefix }}-domain" 37 | register: rl 38 | - name: verify set instance limits for domain 39 | assert: 40 | that: 41 | - not rl|changed 42 | - rl.domain == "{{ cs_resource_prefix }}-domain" 43 | - rl.limit == 12 44 | - rl.resource_type == "instance" 45 | 46 | - name: set instance limits for account 47 | cs_resourcelimit: 48 | type: instance 49 | limit: 10 50 | account: "{{ cs_resource_prefix }}_user" 51 | domain: "{{ cs_resource_prefix }}-domain" 52 | register: rl 53 | - name: verify set instance limits for account 54 | assert: 55 | that: 56 | - rl|changed 57 | - rl.domain == "{{ cs_resource_prefix }}-domain" 58 | - rl.account == "{{ cs_resource_prefix }}_user" 59 | - rl.limit == 10 60 | - rl.resource_type == "instance" 61 | 62 | - name: set instance limits for account idempotence 63 | cs_resourcelimit: 64 | type: instance 65 | limit: 10 66 | account: "{{ cs_resource_prefix }}_user" 67 | domain: "{{ cs_resource_prefix }}-domain" 68 | register: rl 69 | - name: verify set instance limits for account idempotence 70 | assert: 71 | that: 72 | - not rl|changed 73 | - rl.domain == "{{ cs_resource_prefix }}-domain" 74 | - rl.account == "{{ cs_resource_prefix }}_user" 75 | - rl.limit == 10 76 | - rl.resource_type == "instance" 77 | -------------------------------------------------------------------------------- /tests/roles/test_cs_resourcelimit/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: setup domain 3 | cs_domain: path={{ cs_resource_prefix }}-domain 4 | register: dom 5 | - name: verify setup domain 6 | assert: 7 | that: 8 | - dom|success 9 | 10 | - name: setup account 11 | cs_account: 12 | name: "{{ cs_resource_prefix }}_user" 13 | username: "{{ cs_resource_prefix }}_username" 14 | password: "{{ cs_resource_prefix }}_password" 15 | last_name: "{{ cs_resource_prefix }}_last_name" 16 | first_name: "{{ cs_resource_prefix }}_first_name" 17 | email: "{{ cs_resource_prefix }}@example.com" 18 | network_domain: "{{ cs_resource_prefix }}-local" 19 | domain: "{{ cs_resource_prefix }}-domain" 20 | register: acc 21 | - name: verify setup account 22 | assert: 23 | that: 24 | - acc|success 25 | 26 | - name: test failed unkonwn type 27 | cs_resourcelimit: 28 | type: unkonwn 29 | limit: 20 30 | domain: "{{ cs_resource_prefix }}-domain" 31 | register: rl 32 | ignore_errors: yes 33 | - name: verify test failed unkonwn type 34 | assert: 35 | that: 36 | - rl|failed 37 | 38 | - name: test failed missing type 39 | cs_resourcelimit: 40 | register: rl 41 | ignore_errors: yes 42 | - name: verify test failed missing type 43 | assert: 44 | that: 45 | - rl|failed 46 | 47 | - name: setup resource limits domain 48 | cs_resourcelimit: 49 | type: instance 50 | limit: 20 51 | domain: "{{ cs_resource_prefix }}-domain" 52 | register: rl 53 | - name: verify setup resource limits domain 54 | assert: 55 | that: 56 | - rl|success 57 | - rl.domain == "{{ cs_resource_prefix }}-domain" 58 | - rl.limit == 20 59 | 60 | - include: instance.yml 61 | - include: cpu.yml 62 | -------------------------------------------------------------------------------- /tests/roles/test_cs_securitygroup/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - test_cs_common 4 | -------------------------------------------------------------------------------- /tests/roles/test_cs_securitygroup/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: setup 3 | cs_securitygroup: name={{ cs_resource_prefix }}_sg state=absent 4 | register: sg 5 | - name: verify setup 6 | assert: 7 | that: 8 | - sg|success 9 | 10 | - name: test fail if missing name 11 | action: cs_securitygroup 12 | register: sg 13 | ignore_errors: true 14 | - name: verify results of fail if missing name 15 | assert: 16 | that: 17 | - sg|failed 18 | - "sg.msg == 'missing required arguments: name'" 19 | 20 | - name: test present security group 21 | cs_securitygroup: name={{ cs_resource_prefix }}_sg 22 | register: sg 23 | - name: verify results of create security group 24 | assert: 25 | that: 26 | - sg|success 27 | - sg|changed 28 | - sg.name == "{{ cs_resource_prefix }}_sg" 29 | 30 | - name: test present security group is idempotence 31 | cs_securitygroup: name={{ cs_resource_prefix }}_sg 32 | register: sg 33 | - name: verify results present security group is idempotence 34 | assert: 35 | that: 36 | - sg|success 37 | - not sg|changed 38 | - sg.name == "{{ cs_resource_prefix }}_sg" 39 | 40 | - name: test absent security group 41 | cs_securitygroup: name={{ cs_resource_prefix }}_sg state=absent 42 | register: sg 43 | - name: verify results of absent security group 44 | assert: 45 | that: 46 | - sg|success 47 | - sg|changed 48 | - sg.name == "{{ cs_resource_prefix }}_sg" 49 | 50 | - name: test absent security group is idempotence 51 | cs_securitygroup: name={{ cs_resource_prefix }}_sg state=absent 52 | register: sg 53 | - name: verify results of absent security group is idempotence 54 | assert: 55 | that: 56 | - sg|success 57 | - not sg|changed 58 | - sg.name is undefined 59 | -------------------------------------------------------------------------------- /tests/roles/test_cs_securitygroup_rule/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - test_cs_common 4 | -------------------------------------------------------------------------------- /tests/roles/test_cs_securitygroup_rule/tasks/absent.yml: -------------------------------------------------------------------------------- 1 | - name: test remove http range rule 2 | cs_securitygroup_rule: 3 | security_group: default 4 | start_port: 8000 5 | end_port: 8888 6 | cidr: 1.2.3.4/32 7 | state: absent 8 | register: sg_rule 9 | - name: verify create http range rule 10 | assert: 11 | that: 12 | - sg_rule|success 13 | - sg_rule|changed 14 | - sg_rule.type == 'ingress' 15 | - sg_rule.security_group == 'default' 16 | - sg_rule.protocol == 'tcp' 17 | - sg_rule.start_port == 8000 18 | - sg_rule.end_port == 8888 19 | - sg_rule.cidr == '1.2.3.4/32' 20 | 21 | - name: test remove http range rule idempotence 22 | cs_securitygroup_rule: 23 | security_group: default 24 | start_port: 8000 25 | end_port: 8888 26 | cidr: 1.2.3.4/32 27 | state: absent 28 | register: sg_rule 29 | - name: verify create http range rule idempotence 30 | assert: 31 | that: 32 | - sg_rule|success 33 | - not sg_rule|changed 34 | 35 | - name: test remove single port udp rule 36 | cs_securitygroup_rule: 37 | security_group: default 38 | port: 5353 39 | protocol: udp 40 | type: egress 41 | user_security_group: '{{ cs_resource_prefix }}_sg' 42 | state: absent 43 | register: sg_rule 44 | - name: verify remove single port udp rule 45 | assert: 46 | that: 47 | - sg_rule|success 48 | - sg_rule|changed 49 | - sg_rule.type == 'egress' 50 | - sg_rule.security_group == 'default' 51 | - sg_rule.protocol == 'udp' 52 | - sg_rule.start_port == 5353 53 | - sg_rule.end_port == 5353 54 | - sg_rule.user_security_group == '{{ cs_resource_prefix }}_sg' 55 | 56 | - name: test remove single port udp rule idempotence 57 | cs_securitygroup_rule: 58 | security_group: default 59 | port: 5353 60 | protocol: udp 61 | type: egress 62 | user_security_group: '{{ cs_resource_prefix }}_sg' 63 | state: absent 64 | register: sg_rule 65 | - name: verify remove single port udp rule idempotence 66 | assert: 67 | that: 68 | - sg_rule|success 69 | - not sg_rule|changed 70 | 71 | - name: test remove icmp rule 72 | cs_securitygroup_rule: 73 | security_group: default 74 | protocol: icmp 75 | type: ingress 76 | icmp_type: -1 77 | icmp_code: -1 78 | state: absent 79 | register: sg_rule 80 | - name: verify icmp rule 81 | assert: 82 | that: 83 | - sg_rule|success 84 | - sg_rule|changed 85 | - sg_rule.type == 'ingress' 86 | - sg_rule.security_group == 'default' 87 | - sg_rule.cidr == '0.0.0.0/0' 88 | - sg_rule.protocol == 'icmp' 89 | - sg_rule.icmp_code == -1 90 | - sg_rule.icmp_type == -1 91 | 92 | - name: test remove icmp rule idempotence 93 | cs_securitygroup_rule: 94 | security_group: default 95 | protocol: icmp 96 | type: ingress 97 | icmp_type: -1 98 | icmp_code: -1 99 | state: absent 100 | register: sg_rule 101 | - name: verify icmp rule idempotence 102 | assert: 103 | that: 104 | - sg_rule|success 105 | - not sg_rule|changed 106 | -------------------------------------------------------------------------------- /tests/roles/test_cs_securitygroup_rule/tasks/cleanup.yml: -------------------------------------------------------------------------------- 1 | - name: cleanup custom security group 2 | cs_securitygroup: name={{ cs_resource_prefix }}_sg state=absent 3 | register: sg 4 | - name: verify setup 5 | assert: 6 | that: 7 | - sg|success 8 | -------------------------------------------------------------------------------- /tests/roles/test_cs_securitygroup_rule/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - include: setup.yml 2 | - include: present.yml 3 | - include: absent.yml 4 | - include: cleanup.yml 5 | -------------------------------------------------------------------------------- /tests/roles/test_cs_securitygroup_rule/tasks/present.yml: -------------------------------------------------------------------------------- 1 | - name: test create http range rule 2 | cs_securitygroup_rule: 3 | security_group: default 4 | start_port: 8000 5 | end_port: 8888 6 | cidr: 1.2.3.4/32 7 | register: sg_rule 8 | - name: verify create http range rule 9 | assert: 10 | that: 11 | - sg_rule|success 12 | - sg_rule|changed 13 | - sg_rule.type == 'ingress' 14 | - sg_rule.security_group == 'default' 15 | - sg_rule.protocol == 'tcp' 16 | - sg_rule.start_port == 8000 17 | - sg_rule.end_port == 8888 18 | - sg_rule.cidr == '1.2.3.4/32' 19 | 20 | - name: test create http range rule idempotence 21 | cs_securitygroup_rule: 22 | security_group: default 23 | start_port: 8000 24 | end_port: 8888 25 | cidr: 1.2.3.4/32 26 | register: sg_rule 27 | - name: verify create http range rule idempotence 28 | assert: 29 | that: 30 | - sg_rule|success 31 | - not sg_rule|changed 32 | - sg_rule.type == 'ingress' 33 | - sg_rule.security_group == 'default' 34 | - sg_rule.protocol == 'tcp' 35 | - sg_rule.start_port == 8000 36 | - sg_rule.end_port == 8888 37 | - sg_rule.cidr == '1.2.3.4/32' 38 | 39 | - name: test create single port udp rule 40 | cs_securitygroup_rule: 41 | security_group: default 42 | port: 5353 43 | protocol: udp 44 | type: egress 45 | user_security_group: '{{ cs_resource_prefix }}_sg' 46 | register: sg_rule 47 | - name: verify create single port udp rule 48 | assert: 49 | that: 50 | - sg_rule|success 51 | - sg_rule|changed 52 | - sg_rule.type == 'egress' 53 | - sg_rule.security_group == 'default' 54 | - sg_rule.protocol == 'udp' 55 | - sg_rule.start_port == 5353 56 | - sg_rule.end_port == 5353 57 | - sg_rule.user_security_group == '{{ cs_resource_prefix }}_sg' 58 | 59 | 60 | - name: test single port udp rule idempotence 61 | cs_securitygroup_rule: 62 | security_group: default 63 | port: 5353 64 | protocol: udp 65 | type: egress 66 | user_security_group: '{{ cs_resource_prefix }}_sg' 67 | register: sg_rule 68 | - name: verify single port udp rule idempotence 69 | assert: 70 | that: 71 | - sg_rule|success 72 | - not sg_rule|changed 73 | - sg_rule.type == 'egress' 74 | - sg_rule.security_group == 'default' 75 | - sg_rule.protocol == 'udp' 76 | - sg_rule.start_port == 5353 77 | - sg_rule.end_port == 5353 78 | - sg_rule.user_security_group == '{{ cs_resource_prefix }}_sg' 79 | 80 | - name: test icmp rule 81 | cs_securitygroup_rule: 82 | security_group: default 83 | protocol: icmp 84 | type: ingress 85 | icmp_type: -1 86 | icmp_code: -1 87 | register: sg_rule 88 | - name: verify icmp rule 89 | assert: 90 | that: 91 | - sg_rule|success 92 | - sg_rule|changed 93 | - sg_rule.type == 'ingress' 94 | - sg_rule.security_group == 'default' 95 | - sg_rule.cidr == '0.0.0.0/0' 96 | - sg_rule.protocol == 'icmp' 97 | - sg_rule.icmp_code == -1 98 | - sg_rule.icmp_type == -1 99 | 100 | - name: test icmp rule idempotence 101 | cs_securitygroup_rule: 102 | security_group: default 103 | protocol: icmp 104 | type: ingress 105 | icmp_type: -1 106 | icmp_code: -1 107 | register: sg_rule 108 | - name: verify icmp rule idempotence 109 | assert: 110 | that: 111 | - sg_rule|success 112 | - not sg_rule|changed 113 | - sg_rule.type == 'ingress' 114 | - sg_rule.security_group == 'default' 115 | - sg_rule.cidr == '0.0.0.0/0' 116 | - sg_rule.protocol == 'icmp' 117 | - sg_rule.icmp_code == -1 118 | - sg_rule.icmp_type == -1 119 | -------------------------------------------------------------------------------- /tests/roles/test_cs_securitygroup_rule/tasks/setup.yml: -------------------------------------------------------------------------------- 1 | - name: setup custom security group 2 | cs_securitygroup: name={{ cs_resource_prefix }}_sg 3 | register: sg 4 | - name: verify setup 5 | assert: 6 | that: 7 | - sg|success 8 | 9 | - name: setup default security group 10 | cs_securitygroup: name=default 11 | register: sg 12 | - name: verify setup 13 | assert: 14 | that: 15 | - sg|success 16 | 17 | - name: setup remove icmp rule 18 | cs_securitygroup_rule: 19 | security_group: default 20 | protocol: icmp 21 | type: ingress 22 | icmp_type: -1 23 | icmp_code: -1 24 | state: absent 25 | register: sg_rule 26 | - name: verify remove icmp rule 27 | assert: 28 | that: 29 | - sg_rule|success 30 | 31 | - name: setup remove http range rule 32 | cs_securitygroup_rule: 33 | security_group: default 34 | start_port: 8000 35 | end_port: 8888 36 | cidr: 1.2.3.4/32 37 | state: absent 38 | register: sg_rule 39 | - name: verify remove http range rule 40 | assert: 41 | that: 42 | - sg_rule|success 43 | 44 | - name: setup remove single port udp rule 45 | cs_securitygroup_rule: 46 | security_group: default 47 | port: 5353 48 | protocol: udp 49 | type: egress 50 | user_security_group: '{{ cs_resource_prefix }}-user-sg' 51 | state: absent 52 | register: sg_rule 53 | - name: verify remove single port udp rule 54 | assert: 55 | that: 56 | - sg_rule|success 57 | -------------------------------------------------------------------------------- /tests/roles/test_cs_sshkeypair/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - test_cs_common 4 | -------------------------------------------------------------------------------- /tests/roles/test_cs_sshkeypair/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: setup cleanup 3 | cs_sshkeypair: name={{ cs_resource_prefix }}-sshkey state=absent 4 | 5 | - name: test fail on missing name 6 | action: cs_sshkeypair 7 | ignore_errors: true 8 | register: sshkey 9 | - name: verify results of fail on missing name 10 | assert: 11 | that: 12 | - sshkey|failed 13 | - "sshkey.msg == 'missing required arguments: name'" 14 | 15 | - name: test ssh key creation 16 | cs_sshkeypair: name={{ cs_resource_prefix }}-sshkey 17 | register: sshkey 18 | - name: verify results of ssh key creation 19 | assert: 20 | that: 21 | - sshkey|success 22 | - sshkey|changed 23 | - sshkey.fingerprint is defined and sshkey.fingerprint != "" 24 | - sshkey.private_key is defined and sshkey.private_key != "" 25 | - sshkey.name == "{{ cs_resource_prefix }}-sshkey" 26 | 27 | - name: test ssh key creation idempotence 28 | cs_sshkeypair: name={{ cs_resource_prefix }}-sshkey 29 | register: sshkey2 30 | - name: verify results of ssh key creation idempotence 31 | assert: 32 | that: 33 | - sshkey2|success 34 | - not sshkey2|changed 35 | - sshkey2.fingerprint is defined and sshkey2.fingerprint == sshkey.fingerprint 36 | - sshkey2.private_key is not defined 37 | - sshkey2.name == "{{ cs_resource_prefix }}-sshkey" 38 | 39 | - name: test replace ssh public key 40 | cs_sshkeypair: | 41 | name={{ cs_resource_prefix }}-sshkey 42 | public_key="ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDsTI7KJZ8tz/CwQIrSol41c6s3vzkGYCMI8o7P9Et48UG9eRoGaMaGYaTvBTj/VQrD7cfurI6Bn0HTT3FLK3OHOweyelm9rIiQ2hjkSl+2lIKWHu992GO58E5Gcy9yYW4sHGgGLNZkPBKrrj0w7lhmiHjPtVnf+2+7Ix1WOO2/HXPcAHhsX/AlyItDewIL4mr/BT83vq0202sPCiM2cFQJl+5WGwS1wYYK8d167cspsmdyX7OyAFCUB0vueuqjE8MFqJvyIJR9y8Lj9Ny71pSV5/QWrXUgELxMYOKSby3gHkxcIXgYBMFLl4DipRTO74OWQlRRaOlqXlOOQbikcY4T rene.moser@swisstxt.ch" 43 | register: sshkey3 44 | - name: verify results of replace ssh public key 45 | assert: 46 | that: 47 | - sshkey3|success 48 | - sshkey3|changed 49 | - sshkey3.fingerprint is defined and sshkey3.fingerprint != sshkey2.fingerprint 50 | - sshkey3.private_key is not defined 51 | - sshkey3.name == "{{ cs_resource_prefix }}-sshkey" 52 | 53 | - name: test replace ssh public key idempotence 54 | cs_sshkeypair: | 55 | name={{ cs_resource_prefix }}-sshkey 56 | public_key="ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDsTI7KJZ8tz/CwQIrSol41c6s3vzkGYCMI8o7P9Et48UG9eRoGaMaGYaTvBTj/VQrD7cfurI6Bn0HTT3FLK3OHOweyelm9rIiQ2hjkSl+2lIKWHu992GO58E5Gcy9yYW4sHGgGLNZkPBKrrj0w7lhmiHjPtVnf+2+7Ix1WOO2/HXPcAHhsX/AlyItDewIL4mr/BT83vq0202sPCiM2cFQJl+5WGwS1wYYK8d167cspsmdyX7OyAFCUB0vueuqjE8MFqJvyIJR9y8Lj9Ny71pSV5/QWrXUgELxMYOKSby3gHkxcIXgYBMFLl4DipRTO74OWQlRRaOlqXlOOQbikcY4T rene.moser@swisstxt.ch" 57 | register: sshkey4 58 | - name: verify results of ssh public key idempotence 59 | assert: 60 | that: 61 | - sshkey4|success 62 | - not sshkey4|changed 63 | - sshkey4.fingerprint is defined and sshkey4.fingerprint == sshkey3.fingerprint 64 | - sshkey4.private_key is not defined 65 | - sshkey4.name == "{{ cs_resource_prefix }}-sshkey" 66 | 67 | - name: test ssh key absent 68 | cs_sshkeypair: name={{ cs_resource_prefix }}-sshkey state=absent 69 | register: sshkey5 70 | - name: verify result of key absent 71 | assert: 72 | that: 73 | - sshkey5|success 74 | - sshkey5|changed 75 | - sshkey5.fingerprint is defined and sshkey5.fingerprint == sshkey3.fingerprint 76 | - sshkey5.private_key is not defined 77 | - sshkey5.name == "{{ cs_resource_prefix }}-sshkey" 78 | 79 | - name: test ssh key absent idempotence 80 | cs_sshkeypair: name={{ cs_resource_prefix }}-sshkey state=absent 81 | register: sshkey6 82 | - name: verify result of ssh key absent idempotence 83 | assert: 84 | that: 85 | - sshkey6|success 86 | - not sshkey6|changed 87 | - sshkey6.fingerprint is not defined 88 | - sshkey6.private_key is not defined 89 | - sshkey6.name is not defined 90 | -------------------------------------------------------------------------------- /tests/roles/test_cs_user/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - test_cs_common 4 | -------------------------------------------------------------------------------- /tests/roles/test_cs_user/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: setup 3 | cs_user: username={{ cs_resource_prefix }}_user state=absent 4 | register: user 5 | - name: verify setup 6 | assert: 7 | that: 8 | - user|success 9 | 10 | - name: test fail if missing username 11 | action: cs_user 12 | register: user 13 | ignore_errors: true 14 | - name: verify results of fail if missing params 15 | assert: 16 | that: 17 | - user|failed 18 | - 'user.msg == "missing required arguments: username"' 19 | 20 | - name: test fail if missing params if state=present 21 | cs_user: 22 | username: "{{ cs_resource_prefix }}_user" 23 | register: user 24 | ignore_errors: true 25 | - name: verify results of fail if missing params if state=present 26 | assert: 27 | that: 28 | - user|failed 29 | - 'user.msg == "missing required arguments: account,email,password,first_name,last_name"' 30 | 31 | - name: test create user 32 | cs_user: 33 | username: "{{ cs_resource_prefix }}_user" 34 | password: "{{ cs_resource_prefix }}_password" 35 | last_name: "{{ cs_resource_prefix }}_last_name" 36 | first_name: "{{ cs_resource_prefix }}_first_name" 37 | email: "{{ cs_resource_prefix }}@example.com" 38 | account: "admin" 39 | register: user 40 | - name: verify results of create user 41 | assert: 42 | that: 43 | - user|success 44 | - user|changed 45 | - user.username == "{{ cs_resource_prefix }}_user" 46 | - user.first_name == "{{ cs_resource_prefix }}_first_name" 47 | - user.last_name == "{{ cs_resource_prefix }}_last_name" 48 | - user.email == "{{ cs_resource_prefix }}@example.com" 49 | - user.account_type == "root_admin" 50 | - user.account == "admin" 51 | - user.state == "enabled" 52 | - user.domain == "ROOT" 53 | 54 | - name: test create user idempotence 55 | cs_user: 56 | username: "{{ cs_resource_prefix }}_user" 57 | password: "{{ cs_resource_prefix }}_password" 58 | last_name: "{{ cs_resource_prefix }}_last_name" 59 | first_name: "{{ cs_resource_prefix }}_first_name" 60 | email: "{{ cs_resource_prefix }}@example.com" 61 | account: "admin" 62 | register: user 63 | - name: verify results of create user idempotence 64 | assert: 65 | that: 66 | - user|success 67 | - not user|changed 68 | - user.username == "{{ cs_resource_prefix }}_user" 69 | - user.first_name == "{{ cs_resource_prefix }}_first_name" 70 | - user.last_name == "{{ cs_resource_prefix }}_last_name" 71 | - user.email == "{{ cs_resource_prefix }}@example.com" 72 | - user.account_type == "root_admin" 73 | - user.account == "admin" 74 | - user.state == "enabled" 75 | - user.domain == "ROOT" 76 | 77 | - name: test update user 78 | cs_user: 79 | username: "{{ cs_resource_prefix }}_user" 80 | password: "{{ cs_resource_prefix }}_password" 81 | last_name: "{{ cs_resource_prefix }}_last_name1" 82 | first_name: "{{ cs_resource_prefix }}_first_name1" 83 | email: "{{ cs_resource_prefix }}@example.com1" 84 | account: "admin" 85 | register: user 86 | - name: verify results of update user 87 | assert: 88 | that: 89 | - user|success 90 | - user|changed 91 | - user.username == "{{ cs_resource_prefix }}_user" 92 | - user.first_name == "{{ cs_resource_prefix }}_first_name1" 93 | - user.last_name == "{{ cs_resource_prefix }}_last_name1" 94 | - user.email == "{{ cs_resource_prefix }}@example.com1" 95 | - user.account_type == "root_admin" 96 | - user.account == "admin" 97 | - user.state == "enabled" 98 | - user.domain == "ROOT" 99 | 100 | - name: test update user idempotence 101 | cs_user: 102 | username: "{{ cs_resource_prefix }}_user" 103 | password: "{{ cs_resource_prefix }}_password" 104 | last_name: "{{ cs_resource_prefix }}_last_name1" 105 | first_name: "{{ cs_resource_prefix }}_first_name1" 106 | email: "{{ cs_resource_prefix }}@example.com1" 107 | account: "admin" 108 | register: user 109 | - name: verify results of update user idempotence 110 | assert: 111 | that: 112 | - user|success 113 | - not user|changed 114 | - user.username == "{{ cs_resource_prefix }}_user" 115 | - user.first_name == "{{ cs_resource_prefix }}_first_name1" 116 | - user.last_name == "{{ cs_resource_prefix }}_last_name1" 117 | - user.email == "{{ cs_resource_prefix }}@example.com1" 118 | - user.account_type == "root_admin" 119 | - user.account == "admin" 120 | - user.state == "enabled" 121 | - user.domain == "ROOT" 122 | 123 | - name: test lock user 124 | cs_user: 125 | username: "{{ cs_resource_prefix }}_user" 126 | state: locked 127 | register: user 128 | - name: verify results of lock user 129 | assert: 130 | that: 131 | - user|success 132 | - user|changed 133 | - user.username == "{{ cs_resource_prefix }}_user" 134 | - user.account_type == "root_admin" 135 | - user.account == "admin" 136 | - user.state == "locked" 137 | - user.domain == "ROOT" 138 | 139 | - name: test lock user idempotence 140 | cs_user: 141 | username: "{{ cs_resource_prefix }}_user" 142 | state: locked 143 | register: user 144 | - name: verify results of lock user idempotence 145 | assert: 146 | that: 147 | - user|success 148 | - not user|changed 149 | - user.username == "{{ cs_resource_prefix }}_user" 150 | - user.account_type == "root_admin" 151 | - user.account == "admin" 152 | - user.state == "locked" 153 | - user.domain == "ROOT" 154 | 155 | - name: test disable user 156 | cs_user: 157 | username: "{{ cs_resource_prefix }}_user" 158 | state: disabled 159 | register: user 160 | - name: verify results of disable user 161 | assert: 162 | that: 163 | - user|success 164 | - user|changed 165 | - user.username == "{{ cs_resource_prefix }}_user" 166 | - user.account_type == "root_admin" 167 | - user.account == "admin" 168 | - user.state == "disabled" 169 | - user.domain == "ROOT" 170 | 171 | - name: test disable user idempotence 172 | cs_user: 173 | username: "{{ cs_resource_prefix }}_user" 174 | state: disabled 175 | register: user 176 | - name: verify results of disable user idempotence 177 | assert: 178 | that: 179 | - user|success 180 | - not user|changed 181 | - user.username == "{{ cs_resource_prefix }}_user" 182 | - user.account_type == "root_admin" 183 | - user.account == "admin" 184 | - user.state == "disabled" 185 | - user.domain == "ROOT" 186 | 187 | - name: test lock disabled user 188 | cs_user: 189 | username: "{{ cs_resource_prefix }}_user" 190 | state: locked 191 | register: user 192 | - name: verify results of lock disabled user 193 | assert: 194 | that: 195 | - user|success 196 | - user|changed 197 | - user.username == "{{ cs_resource_prefix }}_user" 198 | - user.account_type == "root_admin" 199 | - user.account == "admin" 200 | - user.state == "locked" 201 | - user.domain == "ROOT" 202 | 203 | - name: test lock disabled user idempotence 204 | cs_user: 205 | username: "{{ cs_resource_prefix }}_user" 206 | state: locked 207 | register: user 208 | - name: verify results of lock disabled user idempotence 209 | assert: 210 | that: 211 | - user|success 212 | - not user|changed 213 | - user.username == "{{ cs_resource_prefix }}_user" 214 | - user.account_type == "root_admin" 215 | - user.account == "admin" 216 | - user.state == "locked" 217 | - user.domain == "ROOT" 218 | 219 | - name: test enable user 220 | cs_user: 221 | username: "{{ cs_resource_prefix }}_user" 222 | state: enabled 223 | register: user 224 | - name: verify results of enable user 225 | assert: 226 | that: 227 | - user|success 228 | - user|changed 229 | - user.username == "{{ cs_resource_prefix }}_user" 230 | - user.account_type == "root_admin" 231 | - user.account == "admin" 232 | - user.state == "enabled" 233 | - user.domain == "ROOT" 234 | 235 | - name: test enable user idempotence using unlocked 236 | cs_user: 237 | username: "{{ cs_resource_prefix }}_user" 238 | state: unlocked 239 | register: user 240 | - name: verify results of enable user idempotence 241 | assert: 242 | that: 243 | - user|success 244 | - not user|changed 245 | - user.username == "{{ cs_resource_prefix }}_user" 246 | - user.account_type == "root_admin" 247 | - user.account == "admin" 248 | - user.state == "enabled" 249 | - user.domain == "ROOT" 250 | 251 | - name: test remove user 252 | cs_user: 253 | username: "{{ cs_resource_prefix }}_user" 254 | state: absent 255 | register: user 256 | - name: verify results of remove user 257 | assert: 258 | that: 259 | - user|success 260 | - user|changed 261 | - user.username == "{{ cs_resource_prefix }}_user" 262 | - user.account_type == "root_admin" 263 | - user.account == "admin" 264 | - user.state == "enabled" 265 | - user.domain == "ROOT" 266 | 267 | - name: test remove user idempotence 268 | cs_user: 269 | username: "{{ cs_resource_prefix }}_user" 270 | state: absent 271 | register: user 272 | - name: verify results of remove user idempotence 273 | assert: 274 | that: 275 | - user|success 276 | - not user|changed 277 | 278 | - name: test create locked user 279 | cs_user: 280 | username: "{{ cs_resource_prefix }}_user" 281 | password: "{{ cs_resource_prefix }}_password" 282 | last_name: "{{ cs_resource_prefix }}_last_name" 283 | first_name: "{{ cs_resource_prefix }}_first_name" 284 | email: "{{ cs_resource_prefix }}@example.com" 285 | account: "admin" 286 | state: locked 287 | register: user 288 | - name: verify results of create locked user 289 | assert: 290 | that: 291 | - user|success 292 | - user|changed 293 | - user.username == "{{ cs_resource_prefix }}_user" 294 | - user.first_name == "{{ cs_resource_prefix }}_first_name" 295 | - user.last_name == "{{ cs_resource_prefix }}_last_name" 296 | - user.email == "{{ cs_resource_prefix }}@example.com" 297 | - user.account_type == "root_admin" 298 | - user.account == "admin" 299 | - user.state == "locked" 300 | - user.domain == "ROOT" 301 | 302 | - name: test remove locked user 303 | cs_user: 304 | username: "{{ cs_resource_prefix }}_user" 305 | state: absent 306 | register: user 307 | - name: verify results of remove locked user 308 | assert: 309 | that: 310 | - user|success 311 | - user|changed 312 | - user.username == "{{ cs_resource_prefix }}_user" 313 | - user.account_type == "root_admin" 314 | - user.account == "admin" 315 | - user.state == "locked" 316 | - user.domain == "ROOT" 317 | 318 | - name: test create disabled user 319 | cs_user: 320 | username: "{{ cs_resource_prefix }}_user" 321 | password: "{{ cs_resource_prefix }}_password" 322 | last_name: "{{ cs_resource_prefix }}_last_name" 323 | first_name: "{{ cs_resource_prefix }}_first_name" 324 | email: "{{ cs_resource_prefix }}@example.com" 325 | account: "admin" 326 | state: disabled 327 | register: user 328 | - name: verify results of create disabled user 329 | assert: 330 | that: 331 | - user|success 332 | - user|changed 333 | - user.username == "{{ cs_resource_prefix }}_user" 334 | - user.first_name == "{{ cs_resource_prefix }}_first_name" 335 | - user.last_name == "{{ cs_resource_prefix }}_last_name" 336 | - user.email == "{{ cs_resource_prefix }}@example.com" 337 | - user.account_type == "root_admin" 338 | - user.account == "admin" 339 | - user.state == "disabled" 340 | - user.domain == "ROOT" 341 | 342 | - name: test remove disabled user 343 | cs_user: 344 | username: "{{ cs_resource_prefix }}_user" 345 | state: absent 346 | register: user 347 | - name: verify results of remove disabled user 348 | assert: 349 | that: 350 | - user|success 351 | - user|changed 352 | - user.username == "{{ cs_resource_prefix }}_user" 353 | - user.account_type == "root_admin" 354 | - user.account == "admin" 355 | - user.state == "disabled" 356 | - user.domain == "ROOT" 357 | 358 | - name: test create enabled user 359 | cs_user: 360 | username: "{{ cs_resource_prefix }}_user" 361 | password: "{{ cs_resource_prefix }}_password" 362 | last_name: "{{ cs_resource_prefix }}_last_name" 363 | first_name: "{{ cs_resource_prefix }}_first_name" 364 | email: "{{ cs_resource_prefix }}@example.com" 365 | account: "admin" 366 | state: enabled 367 | register: user 368 | - name: verify results of create enabled user 369 | assert: 370 | that: 371 | - user|success 372 | - user|changed 373 | - user.username == "{{ cs_resource_prefix }}_user" 374 | - user.first_name == "{{ cs_resource_prefix }}_first_name" 375 | - user.last_name == "{{ cs_resource_prefix }}_last_name" 376 | - user.email == "{{ cs_resource_prefix }}@example.com" 377 | - user.account_type == "root_admin" 378 | - user.account == "admin" 379 | - user.state == "enabled" 380 | - user.domain == "ROOT" 381 | 382 | - name: test remove enabled user 383 | cs_user: 384 | username: "{{ cs_resource_prefix }}_user" 385 | state: absent 386 | register: user 387 | - name: verify results of remove enabled user 388 | assert: 389 | that: 390 | - user|success 391 | - user|changed 392 | - user.username == "{{ cs_resource_prefix }}_user" 393 | - user.account_type == "root_admin" 394 | - user.account == "admin" 395 | - user.state == "enabled" 396 | - user.domain == "ROOT" 397 | -------------------------------------------------------------------------------- /tests/roles/test_cs_vmsnapshot/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | test_cs_instance_template: CentOS 5.3(64-bit) no GUI (Simulator) 3 | test_cs_instance_offering_1: Small Instance 4 | -------------------------------------------------------------------------------- /tests/roles/test_cs_vmsnapshot/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - test_cs_common 4 | -------------------------------------------------------------------------------- /tests/roles/test_cs_vmsnapshot/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: setup instance 3 | cs_instance: 4 | name: "{{ cs_resource_prefix }}-vm-snapshot" 5 | template: "{{ test_cs_instance_template }}" 6 | service_offering: "{{ test_cs_instance_offering_1 }}" 7 | register: instance 8 | - name: verify create instance 9 | assert: 10 | that: 11 | - instance|success 12 | 13 | - name: ensure no snapshot exists 14 | cs_vmsnapshot: 15 | name: "{{ cs_resource_prefix }}_snapshot" 16 | vm: "{{ cs_resource_prefix }}-vm-snapshot" 17 | state: absent 18 | register: snap 19 | - name: verify setup 20 | assert: 21 | that: 22 | - snap|success 23 | 24 | - name: test fail if missing name 25 | action: cs_vmsnapshot 26 | register: snap 27 | ignore_errors: true 28 | - name: verify results of fail if missing params 29 | assert: 30 | that: 31 | - snap|failed 32 | - 'snap.msg == "missing required arguments: vm,name"' 33 | 34 | - name: test create snapshot 35 | cs_vmsnapshot: 36 | name: "{{ cs_resource_prefix }}_snapshot" 37 | vm: "{{ cs_resource_prefix }}-vm-snapshot" 38 | snapshot_memory: yes 39 | register: snap 40 | - name: verify test create snapshot 41 | assert: 42 | that: 43 | - snap|changed 44 | - snap.display_name == "{{ cs_resource_prefix }}_snapshot" 45 | 46 | - name: test create snapshot idempotence 47 | cs_vmsnapshot: 48 | name: "{{ cs_resource_prefix }}_snapshot" 49 | vm: "{{ cs_resource_prefix }}-vm-snapshot" 50 | snapshot_memory: yes 51 | register: snap 52 | - name: verify test create snapshot idempotence 53 | assert: 54 | that: 55 | - not snap|changed 56 | - snap.display_name == "{{ cs_resource_prefix }}_snapshot" 57 | 58 | - name: test revert snapshot 59 | cs_vmsnapshot: 60 | name: "{{ cs_resource_prefix }}_snapshot" 61 | vm: "{{ cs_resource_prefix }}-vm-snapshot" 62 | state: revert 63 | register: snap 64 | - name: verify test revert snapshot 65 | assert: 66 | that: 67 | - snap|changed 68 | - snap.display_name == "{{ cs_resource_prefix }}_snapshot" 69 | 70 | - name: test remove snapshot 71 | cs_vmsnapshot: 72 | name: "{{ cs_resource_prefix }}_snapshot" 73 | vm: "{{ cs_resource_prefix }}-vm-snapshot" 74 | state: absent 75 | register: snap 76 | - name: verify test remove snapshot 77 | assert: 78 | that: 79 | - snap|changed 80 | - snap.display_name == "{{ cs_resource_prefix }}_snapshot" 81 | 82 | - name: test remove snapshot idempotence 83 | cs_vmsnapshot: 84 | name: "{{ cs_resource_prefix }}_snapshot" 85 | vm: "{{ cs_resource_prefix }}-vm-snapshot" 86 | state: absent 87 | register: snap 88 | - name: verify test remove snapshot idempotence 89 | assert: 90 | that: 91 | - not snap|changed 92 | 93 | - name: cleanup instance 94 | cs_instance: 95 | name: "{{ cs_resource_prefix }}-vm-snapshot" 96 | state: expunged 97 | register: instance 98 | - name: verify destroy instance 99 | assert: 100 | that: 101 | - instance|success 102 | -------------------------------------------------------------------------------- /tests/roles/test_cs_volume/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | test_cs_instance_1: "{{ cs_resource_prefix }}-vm1" 3 | test_cs_instance_2: "{{ cs_resource_prefix }}-vm2" 4 | test_cs_instance_template: CentOS 5.3(64-bit) no GUI (Simulator) 5 | test_cs_instance_offering_1: Small Instance 6 | test_cs_disk_offering_1: Custom 7 | -------------------------------------------------------------------------------- /tests/roles/test_cs_volume/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - test_cs_common 4 | -------------------------------------------------------------------------------- /tests/roles/test_cs_volume/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: setup 3 | cs_volume: name={{ cs_resource_prefix }}_vol state=absent 4 | register: vol 5 | - name: verify setup 6 | assert: 7 | that: 8 | - vol|success 9 | 10 | - name: setup instance 1 11 | cs_instance: 12 | name: "{{ test_cs_instance_1 }}" 13 | template: "{{ test_cs_instance_template }}" 14 | service_offering: "{{ test_cs_instance_offering_1 }}" 15 | register: instance 16 | - name: verify create instance 17 | assert: 18 | that: 19 | - instance|success 20 | 21 | - name: setup instance 2 22 | cs_instance: 23 | name: "{{ test_cs_instance_2 }}" 24 | template: "{{ test_cs_instance_template }}" 25 | service_offering: "{{ test_cs_instance_offering_1 }}" 26 | register: instance 27 | - name: verify create instance 28 | assert: 29 | that: 30 | - instance|success 31 | 32 | - name: test fail if missing name 33 | action: cs_volume 34 | register: vol 35 | ignore_errors: true 36 | - name: verify results of fail if missing name 37 | assert: 38 | that: 39 | - vol|failed 40 | - "vol.msg == 'missing required arguments: name'" 41 | 42 | - name: test create volume 43 | cs_volume: 44 | name: "{{ cs_resource_prefix }}_vol" 45 | disk_offering: "{{ test_cs_disk_offering_1 }}" 46 | size: 20 47 | register: vol 48 | - name: verify results test create volume 49 | assert: 50 | that: 51 | - vol|changed 52 | - vol.size == 20 * 1024 ** 3 53 | - vol.name == "{{ cs_resource_prefix }}_vol" 54 | 55 | - name: test create volume idempotence 56 | cs_volume: 57 | name: "{{ cs_resource_prefix }}_vol" 58 | disk_offering: "{{ test_cs_disk_offering_1 }}" 59 | size: 20 60 | register: vol 61 | - name: verify results test create volume idempotence 62 | assert: 63 | that: 64 | - not vol|changed 65 | - vol.size == 20 * 1024 ** 3 66 | - vol.name == "{{ cs_resource_prefix }}_vol" 67 | 68 | - name: test shrink volume 69 | cs_volume: 70 | name: "{{ cs_resource_prefix }}_vol" 71 | disk_offering: "{{ test_cs_disk_offering_1 }}" 72 | size: 10 73 | shrink_ok: yes 74 | register: vol 75 | - name: verify results test create volume 76 | assert: 77 | that: 78 | - vol|changed 79 | - vol.size == 10 * 1024 ** 3 80 | - vol.name == "{{ cs_resource_prefix }}_vol" 81 | 82 | - name: test shrink volume idempotence 83 | cs_volume: 84 | name: "{{ cs_resource_prefix }}_vol" 85 | disk_offering: "{{ test_cs_disk_offering_1 }}" 86 | size: 10 87 | shrink_ok: yes 88 | register: vol 89 | - name: verify results test create volume 90 | assert: 91 | that: 92 | - not vol|changed 93 | - vol.size == 10 * 1024 ** 3 94 | - vol.name == "{{ cs_resource_prefix }}_vol" 95 | 96 | - name: test attach volume 97 | cs_volume: 98 | name: "{{ cs_resource_prefix }}_vol" 99 | vm: "{{ test_cs_instance_1 }}" 100 | state: attached 101 | register: vol 102 | - name: verify results test attach volume 103 | assert: 104 | that: 105 | - vol|changed 106 | - vol.name == "{{ cs_resource_prefix }}_vol" 107 | - vol.vm == "{{ test_cs_instance_1 }}" 108 | - vol.attached is defined 109 | 110 | - name: test attach volume idempotence 111 | cs_volume: 112 | name: "{{ cs_resource_prefix }}_vol" 113 | vm: "{{ test_cs_instance_1 }}" 114 | state: attached 115 | register: vol 116 | - name: verify results test attach volume idempotence 117 | assert: 118 | that: 119 | - not vol|changed 120 | - vol.name == "{{ cs_resource_prefix }}_vol" 121 | - vol.vm == "{{ test_cs_instance_1 }}" 122 | - vol.attached is defined 123 | 124 | - name: test attach attached volume to another vm 125 | cs_volume: 126 | name: "{{ cs_resource_prefix }}_vol" 127 | vm: "{{ test_cs_instance_2 }}" 128 | state: attached 129 | register: vol 130 | - name: verify results test attach attached volume to another vm 131 | assert: 132 | that: 133 | - vol|changed 134 | - vol.name == "{{ cs_resource_prefix }}_vol" 135 | - vol.vm == "{{ test_cs_instance_2 }}" 136 | - vol.attached is defined 137 | 138 | - name: test attach attached volume to another vm idempotence 139 | cs_volume: 140 | name: "{{ cs_resource_prefix }}_vol" 141 | vm: "{{ test_cs_instance_2 }}" 142 | state: attached 143 | register: vol 144 | - name: verify results test attach attached volume to another vm idempotence 145 | assert: 146 | that: 147 | - not vol|changed 148 | - vol.name == "{{ cs_resource_prefix }}_vol" 149 | - vol.vm == "{{ test_cs_instance_2 }}" 150 | - vol.attached is defined 151 | 152 | - name: test detach volume 153 | cs_volume: 154 | name: "{{ cs_resource_prefix }}_vol" 155 | state: detached 156 | register: vol 157 | - name: verify results test detach volume 158 | assert: 159 | that: 160 | - vol|changed 161 | - vol.name == "{{ cs_resource_prefix }}_vol" 162 | - vol.attached is undefined 163 | 164 | - name: test detach volume idempotence 165 | cs_volume: 166 | name: "{{ cs_resource_prefix }}_vol" 167 | state: detached 168 | register: vol 169 | - name: verify results test detach volume idempotence 170 | assert: 171 | that: 172 | - not vol|changed 173 | - vol.name == "{{ cs_resource_prefix }}_vol" 174 | - vol.attached is undefined 175 | 176 | - name: test delete volume 177 | cs_volume: 178 | name: "{{ cs_resource_prefix }}_vol" 179 | state: absent 180 | register: vol 181 | - name: verify results test create volume 182 | assert: 183 | that: 184 | - vol|changed 185 | - vol.name == "{{ cs_resource_prefix }}_vol" 186 | 187 | - name: test delete volume idempotence 188 | cs_volume: 189 | name: "{{ cs_resource_prefix }}_vol" 190 | state: absent 191 | register: vol 192 | - name: verify results test delete volume idempotence 193 | assert: 194 | that: 195 | - not vol|changed 196 | 197 | - name: cleanup instance 1 198 | cs_instance: 199 | name: "{{ test_cs_instance_1 }}" 200 | state: absent 201 | register: instance 202 | - name: verify create instance 203 | assert: 204 | that: 205 | - instance|success 206 | 207 | - name: cleanup instance 2 208 | cs_instance: 209 | name: "{{ test_cs_instance_2 }}" 210 | state: absent 211 | register: instance 212 | - name: verify create instance 213 | assert: 214 | that: 215 | - instance|success 216 | -------------------------------------------------------------------------------- /tests/roles/test_cs_zone/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # defaults file for test_cs_host 3 | -------------------------------------------------------------------------------- /tests/roles/test_cs_zone/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - test_cs_common 4 | -------------------------------------------------------------------------------- /tests/roles/test_cs_zone/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: setup zone is absent 3 | cs_zone: 4 | name: "{{ cs_resource_prefix }}-zone" 5 | state: absent 6 | register: zone 7 | - name: verify setup zone is absent 8 | assert: 9 | that: 10 | - zone|success 11 | 12 | - name: test fail if missing name 13 | cs_zone: 14 | register: zone 15 | ignore_errors: true 16 | - name: verify results of fail if missing name 17 | assert: 18 | that: 19 | - zone|failed 20 | - "zone.msg == 'missing required arguments: name'" 21 | 22 | - name: test create zone 23 | cs_zone: 24 | name: "{{ cs_resource_prefix }}-zone" 25 | dns1: 8.8.8.8 26 | dns2: 8.8.4.4 27 | network_type: basic 28 | register: zone_origin 29 | - name: verify test create zone 30 | assert: 31 | that: 32 | - zone_origin|changed 33 | - zone_origin.allocation_state == "Disabled" 34 | - zone_origin.dns1 == "8.8.8.8" 35 | - zone_origin.internal_dns1 == "8.8.8.8" 36 | - zone_origin.dns2 == "8.8.4.4" 37 | - zone_origin.internal_dns2 == "8.8.4.4" 38 | - zone_origin.network_type == "Basic" 39 | 40 | - name: test create zone idempotence 41 | cs_zone: 42 | name: "{{ cs_resource_prefix }}-zone" 43 | dns1: 8.8.8.8 44 | dns2: 8.8.4.4 45 | network_type: basic 46 | register: zone 47 | - name: verify test create zone idempotence 48 | assert: 49 | that: 50 | - not zone|changed 51 | - zone.id == zone_origin.id 52 | - zone.allocation_state == "Disabled" 53 | - zone.dns1 == "8.8.8.8" 54 | - zone.internal_dns1 == "8.8.8.8" 55 | - zone.dns2 == "8.8.4.4" 56 | - zone.internal_dns2 == "8.8.4.4" 57 | - zone.network_type == "Basic" 58 | 59 | - name: test update zone 60 | cs_zone: 61 | name: "{{ cs_resource_prefix }}-zone" 62 | dns1: 8.8.4.4 63 | dns2: 8.8.8.8 64 | network_type: Basic 65 | register: zone 66 | - name: verify test create zone 67 | assert: 68 | that: 69 | - zone|changed 70 | - zone.id == zone_origin.id 71 | - zone.allocation_state == "Disabled" 72 | - zone.dns1 == "8.8.4.4" 73 | - zone.internal_dns1 == "8.8.4.4" 74 | - zone.dns2 == "8.8.8.8" 75 | - zone.internal_dns2 == "8.8.8.8" 76 | - zone.network_type == "Basic" 77 | 78 | - name: test update zone idempotence 79 | cs_zone: 80 | name: "{{ cs_resource_prefix }}-zone" 81 | dns1: 8.8.4.4 82 | dns2: 8.8.8.8 83 | network_type: Basic 84 | register: zone 85 | - name: verify test create zone 86 | assert: 87 | that: 88 | - not zone|changed 89 | - zone.id == zone_origin.id 90 | - zone.allocation_state == "Disabled" 91 | - zone.dns1 == "8.8.4.4" 92 | - zone.internal_dns1 == "8.8.4.4" 93 | - zone.dns2 == "8.8.8.8" 94 | - zone.internal_dns2 == "8.8.8.8" 95 | - zone.network_type == "Basic" 96 | 97 | #- name: test enable zone 98 | # cs_zone: 99 | # name: "{{ cs_resource_prefix }}-zone" 100 | # state: enabled 101 | # register: zone 102 | #- name: verify test enable zone 103 | # assert: 104 | # that: 105 | # - zone|changed 106 | # - zone.allocation_state == "Enabled" 107 | 108 | #- name: test enable zone idempotence 109 | # cs_zone: 110 | # name: "{{ cs_resource_prefix }}-zone" 111 | # state: enabled 112 | # register: zone 113 | #- name: verify test enable zone idempotence 114 | # assert: 115 | # that: 116 | # - not zone|changed 117 | # - zone.allocation_state == "Enabled" 118 | 119 | #- name: test disable zone 120 | # cs_zone: 121 | # name: "{{ cs_resource_prefix }}-zone" 122 | # state: disabled 123 | # register: zone 124 | #- name: verify test disable zone 125 | # assert: 126 | # that: 127 | # - zone|changed 128 | # - zone.allocation_state == "Disabled" 129 | 130 | #- name: test disable zone idempotence 131 | # cs_zone: 132 | # name: "{{ cs_resource_prefix }}-zone" 133 | # state: disabled 134 | # register: zone 135 | #- name: verify test disable zone idempotence 136 | # assert: 137 | # that: 138 | # - not zone|changed 139 | # - zone.allocation_state == "Disabled" 140 | 141 | - name: test absent zone 142 | cs_zone: 143 | name: "{{ cs_resource_prefix }}-zone" 144 | state: absent 145 | register: zone 146 | - name: verify test create zone 147 | assert: 148 | that: 149 | - zone|changed 150 | - zone.id == zone_origin.id 151 | - zone.allocation_state == "Disabled" 152 | - zone.dns1 == "8.8.4.4" 153 | - zone.internal_dns1 == "8.8.4.4" 154 | - zone.dns2 == "8.8.8.8" 155 | - zone.internal_dns2 == "8.8.8.8" 156 | - zone.network_type == "Basic" 157 | 158 | - name: test absent zone idempotence 159 | cs_zone: 160 | name: "{{ cs_resource_prefix }}-zone" 161 | state: absent 162 | register: zone 163 | - name: verify test absent zone idempotence 164 | assert: 165 | that: 166 | - not zone|changed 167 | --------------------------------------------------------------------------------