diff --git a/README.md b/README.md index f6001728a0..ac4c9dfc7c 100644 --- a/README.md +++ b/README.md @@ -103,3 +103,52 @@ You will also need to export the following environment variables for running the * `IAAS_CLASSIC_USERNAME` - The IBM Cloud Classic Infrastructure username associated with the Classic InfrastAPI Key. Additional environment variables may be required depending on the tests being run. Check console log for warning messages about required variables. + + +# IBM Cloud Ansible Modules + +An implementation of generated Ansible modules using the +[IBM Cloud Terraform Provider]. + +## Prerequisites + +1. Install [Python3] + +2. [RedHat Ansible] 2.8+ + + ``` + pip install "ansible>=2.8.0" + ``` + + +## Install + +1. Download IBM Cloud Ansible modules from [release page] + +2. Extract module archive. + + ``` + unzip ibmcloud_ansible_modules.zip + ``` + +3. Add modules and module_utils to the [Ansible search path]. E.g.: + + ``` + cp build/modules/* $HOME/.ansible/plugins/modules/. + cp build/module_utils/* $HOME/.ansible/plugins/module_utils/. + + ``` + +### Example Projects + +1. [VPC Virtual Server Instance](examples/ansible/examples/simple-vm-ssh/) + +2. [Power Virtual Server Instance](examples/ansible/examples/simple-vm-power-vs/) + + +[IBM Cloud Terraform Provider]: https://github.com/IBM-Cloud/terraform-provider-ibm +[Python3]: https://www.python.org/downloads/ +[RedHat Ansible]: https://www.ansible.com/ +[Ansible search path]: https://docs.ansible.com/ansible/latest/dev_guide/overview_architecture.html#ansible-search-path +[release page]:https://github.com/IBM-Cloud/terraform-provider-ibm/releases + diff --git a/examples/ansible/examples/install_modules.yml b/examples/ansible/examples/install_modules.yml new file mode 100755 index 0000000000..3e93ed8f7e --- /dev/null +++ b/examples/ansible/examples/install_modules.yml @@ -0,0 +1,25 @@ +--- +- name: Install IBM Cloud Ansible Modules + hosts: localhost + vars: + ibmcloud_provider_version: 1.1.0 + ansible_modules_base_url: http://ausgsa.ibm.com/~jwcarman/public/ # TODO: External URL + + tasks: + - name: Create Ansible Plugins Directory + file: + path: $HOME/.ansible/plugins + state: directory + mode: '0755' + + - name: Download Ansible Modules + get_url: + url: "{{ ansible_modules_base_url }}/ibmcloud-ansible_v{{ ibmcloud_provider_version }}.zip" + dest: /tmp/ + register: ibmcloud_ansible_zip + + - name: Unarchive IBM Cloud Ansible Modules + unarchive: + src: "{{ ibmcloud_ansible_zip.dest }}" + dest: $HOME/.ansible/plugins + remote_src: yes diff --git a/examples/ansible/examples/simple-vm-power-vs/README.md b/examples/ansible/examples/simple-vm-power-vs/README.md new file mode 100755 index 0000000000..07581dd167 --- /dev/null +++ b/examples/ansible/examples/simple-vm-power-vs/README.md @@ -0,0 +1,94 @@ +# IBM Power Virtual Server in IBM Cloud + +This example creates a Power Systems Virtual Server running AIX or IBMi. The +server is configured to allow incoming SSH connections through a publicly +accessible IP address and authenticated using the provided SSH key. + +## Power Systems Virtual Server Resources + +The following infrastructure resources will be created (Ansible modules in +parentheses): + +* SSH Key (ibm_pi_key) +* Virtual Server Instance (ibm_pi_instance) + +## Configuration Parameters + +The following parameters can be set by the user: + +* `pi_name`: Name assigned to Virtual Server Instance +* `sys_type`: The type of system on which to create the VM (s922/e880/any) +* `pi_image`: VM image name ([retrieve available images]) +* `proc_type`: The type of processor mode in which the VM will run + (shared/dedicated) +* `processors`: The number of vCPUs to assign to the VM (as visibile within the + guest operating system) +* `memory`: The amount of memory (GB) to assign to the VM +* `pi_cloud_instance_id`: The cloud_instance_id for this account +* `ssh_public_key`: The value of the ssh public key to be authorized for SSH + access + +## Running + +### Install IBM Cloud Ansible Modules + +Note: Alternate install path is to use 'examples/install_modules.yml' playbook. + +1. Download IBM Cloud Ansible modules from [release page]. + +2. Extract module archive. + + ``` + unzip ibmcloud_ansible_modules.zip + ``` + +3. Add modules and module_utils to the [Ansible search path]. E.g.: + + ``` + cp build/modules/* $HOME/.ansible/plugins/modules/. + cp build/module_utils/* $HOME/.ansible/plugins/module_utils/. + + ``` + +### Set API Key and Region + +1. [Obtain an IBM Cloud API key]. + +2. Export your API key to the `IC_API_KEY` environment variable: + + ``` + export IC_API_KEY= + ``` + + Note: Modules also support the 'ibmcloud_api_key' parameter, but it is + recommended to only use this when encrypting your API key value. + +3. Export desired IBM Cloud region to the 'IC_REGION' environment variable: + + ``` + export IC_REGION= + ``` + + Note: Modules also support the 'ibmcloud_region' parameter. + +### Create + +1. To create all resources and test public SSH connection to the VM, run the + 'create' playbook: + + ``` + ansible-playbook create.yml + ``` + +### List Available PI VM Images + +1. To list available images run the 'list_pi_images' playbook. *note: Images + are specific to a PI instance, and thus the 'pi_cloud_instance_id' var + must be set before running this playbook.: + + ``` + ansible-playbook list_pi_images.yml + ``` + +[retrieve available images]: #list-available-pi-images +[release page]:https://github.com/IBM-Cloud/terraform-provider-ibm/releases diff --git a/examples/ansible/examples/simple-vm-power-vs/create.yml b/examples/ansible/examples/simple-vm-power-vs/create.yml new file mode 100755 index 0000000000..8335ed9c61 --- /dev/null +++ b/examples/ansible/examples/simple-vm-power-vs/create.yml @@ -0,0 +1,121 @@ +--- +- name: POWER VSI Creation Demo + hosts: localhost + vars: + pi_name: ansible-demo-power-vm + sys_type: s922 + pi_image: "7200-03-03" + proc_type: shared + processors: "0.25" + memory: "2" + pi_cloud_instance_id: "YOUR PI CLOUD INSTANCE ID" + ssh_public_key: "YOUR SSH PUBLIC KEY" + tasks: + - name: Check for existing SSH Key + ibm_pi_key_info: + pi_key_name: "{{ pi_name }}-ssh-key" + pi_cloud_instance_id: "{{ pi_cloud_instance_id }}" + failed_when: + - pi_ssh_key_existing_output.rc != 0 + - '"does not exist" not in pi_ssh_key_existing_output.stderr' + register: pi_ssh_key_existing_output + + - name: Save existing SSH Key as fact + set_fact: + cacheable: True + pi_ssh_key: "{{ pi_ssh_key_existing_output.resource }}" + when: pi_ssh_key_existing_output.resource.id is defined + + - name: Add new SSH Key + ibm_pi_key: + pi_key_name: "{{ pi_name }}-ssh-key" + pi_ssh_key: "{{ ssh_public_key }}" + pi_cloud_instance_id: "{{ pi_cloud_instance_id }}" + register: pi_ssh_key_create_output + when: pi_ssh_key_existing_output.resource.id is not defined + + - name: Save new SSH Key as fact + set_fact: + cacheable: True + pi_ssh_key: "{{ pi_ssh_key_create_output.resource }}" + when: pi_ssh_key_existing_output.resource.id is not defined + + - name: Retrieve image list + ibm_pi_images_info: + pi_cloud_instance_id: "{{ pi_cloud_instance_id }}" + register: images_list + + - name: Set VM image name/id dictionary fact + set_fact: + image_dict: "{{ images_list.resource.image_info | + items2dict(key_name='image_name', + value_name='image_id') }}" + + - name: Check for existing Virtual Server Instance + ibm_pi_instance_info: + pi_instance_name: "{{ pi_name }}" + pi_cloud_instance_id: "{{ pi_cloud_instance_id }}" + failed_when: + - pi_instance_existing_output.rc != 0 + - '"does not exist" not in pi_instance_existing_output.stderr' + register: pi_instance_existing_output + + - name: Save existing Power VSI fact + set_fact: + cacheable: True + pi_instance: "{{ pi_instance_existing_output.resource }}" + when: pi_instance_existing_output.rc == 0 + + - name: Create a POWER Virtual Server Instance + ibm_pi_instance: + state: available + pi_memory: "{{ memory }}" + pi_processors: "{{ processors }}" + pi_instance_name: "{{ pi_name }}" + pi_proc_type: "{{ proc_type }}" + pi_migratable: True + pi_image_id: "{{ image_dict[pi_image] }}" + pi_volume_ids: [] + pi_network_ids: ['249859ed-2ff2-4534-8862-f2c2cc8eeda9'] + pi_public_network: True + pi_key_pair_name: "{{ pi_ssh_key.pi_key_name }}" + pi_sys_type: "{{ sys_type }}" + pi_replication_policy: none + pi_replication_scheme: suffix + pi_replicants: "1" + pi_cloud_instance_id: "{{ pi_cloud_instance_id }}" + id: "{{ pi_instance.resource.id | default(omit) }}" + register: pi_instance_create_output + when: pi_instance_existing_output.rc != 0 + + - name: Save new Power VSI fact + set_fact: + cacheable: True + pi_instance: "{{ pi_instance_create_output.resource }}" + when: pi_instance_create_output.resource is defined + + - name: Print Public IP Address + debug: + var: pi_instance.addresses[0].externalip + + - name: Add VSI to Ansible inventory + add_host: + name: "{{ pi_instance.addresses[0].externalip }}" + ansible_user: root + groups: new_vsi + ansible_ssh_extra_args: -o StrictHostKeyChecking=no + +- name: Connect to VSI + hosts: new_vsi + gather_facts: False + tasks: + - name: Wait for VSI to become reachable over SSH + wait_for_connection: + + - name: Collect OS login message + command: cat /etc/motd + register: os_motd + + - name: Print MOTD + debug: + var: os_motd.stdout_lines diff --git a/examples/ansible/examples/simple-vm-power-vs/list_pi_images.yml b/examples/ansible/examples/simple-vm-power-vs/list_pi_images.yml new file mode 100755 index 0000000000..614f156f13 --- /dev/null +++ b/examples/ansible/examples/simple-vm-power-vs/list_pi_images.yml @@ -0,0 +1,14 @@ +--- +- name: List Power Virtual Server Cloud Images + hosts: localhost + vars: + pi_cloud_instance_id: "YOUR PI CLOUD INSTANCE ID" + + tasks: + - ibm_pi_images_info: + pi_cloud_instance_id: "{{ pi_cloud_instance_id }}" + register: images_list + + - debug: + var: images_list.resource.image_info | + items2dict(key_name='image_name', value_name='image_id') diff --git a/examples/ansible/examples/simple-vm-ssh/README.md b/examples/ansible/examples/simple-vm-ssh/README.md new file mode 100755 index 0000000000..ff38827b6b --- /dev/null +++ b/examples/ansible/examples/simple-vm-ssh/README.md @@ -0,0 +1,102 @@ +# IBM Cloud Ansible: VPC Virtual Server Instance + +This example creates a Virtual Server Instance (VSI) inside of a Virtual +Private Cloud (VPC). The VSI is configured to allow incoming SSH connections +through a publicly accessible IP address and authenticated using an SSH key +pair. + +## VPC Resources + +The following VPC infrastructure resources will be created (Ansible modules in +parentheses): + +* VPC (ibm_is_vpc) +* Subnet (ibm_is_subnet) +* VSI (ibm_is_instance) +* Floating IP Address (ibm_is_floating_ip) +* Security Group Rule (ibm_is_security_group_rule) + +## Configuration Parameters + +The following parameters can be set by the user: + +* `name_prefix`: Prefix used to name created resources +* `vsi_image`: VSI image name ([retrieve available images]) +* `vsi_profile`: VSI profile name ([retrieve available profiles]) +* `ssh_public_key`: SSH Public Key +* `ipv4_cidr_block`: IPv4 CIDR Block for VPC Subnet +* `zone`: IBM Cloud zone + +## Running + +### Install IBM Cloud Ansible Modules + +Note: Alternate install path is to use 'examples/install_modules.yml' playbook. + +1. Download IBM Cloud Ansible modules from [release page] + +2. Extract module archive. + + ``` + unzip ibmcloud_ansible_modules.zip + ``` + +3. Add modules and module_utils to the [Ansible search path]. E.g.: + + ``` + cp build/modules/* $HOME/.ansible/plugins/modules/. + cp build/module_utils/* $HOME/.ansible/plugins/module_utils/. + + ``` + +### Set API Key and Region + +1. [Obtain an IBM Cloud API key]. + +2. Export your API key to the `IC_API_KEY` environment variable: + + ``` + export IC_API_KEY= + ``` + + Note: Modules also support the 'ibmcloud_api_key' parameter, but it is + recommended to only use this when encrypting your API key value. + +3. Export desired IBM Cloud region to the 'IC_REGION' environment variable: + + ``` + export IC_REGION= + ``` + + Note: Modules also support the 'ibmcloud_region' parameter. + +### Create + +1. To create all resources and test public SSH connection to the VM, run the + 'create' playbook: + + ``` + ansible-playbook create.yml + ``` + +### Destroy + +1. To destroy all resources run the 'destroy' playbook: + + ``` + ansible-playbook destroy.yml + ``` + +### List Available VSI Images and Profiles + +1. To destroy all resources run the 'destroy' playbook: + + ``` + ansible-playbook list_vsi_images_and_profiles.yml + ``` + +[retrieve available images]: #list-available-vsi-images-and-profiles +[retrieve available profiles]: #list-available-vsi-images-and-profiles +[Ansible search path]:https://docs.ansible.com/ansible/latest/dev_guide/overview_architecture.html#ansible-search-path +[Obtain an IBM Cloud API key]:https://cloud.ibm.com/docs/iam?topic=iam-userapikey +[release page]:https://github.com/IBM-Cloud/terraform-provider-ibm/releases diff --git a/examples/ansible/examples/simple-vm-ssh/create.yml b/examples/ansible/examples/simple-vm-ssh/create.yml new file mode 100755 index 0000000000..25d53f96f8 --- /dev/null +++ b/examples/ansible/examples/simple-vm-ssh/create.yml @@ -0,0 +1,145 @@ +--- +- name: Create IBM Cloud VPC VSI + hosts: localhost + vars: + name_prefix: ansible-demo + vsi_image: ibm-ubuntu-18-04-64-ppc64le-minimal-for-vsi + vsi_profile: cp2-2x4 + ssh_public_key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDHi3DUs4s2TE8oZF\ + Q5m9dzKFFNTrMJonT5DwKA+F40pD0Me4T1JEndqJkPkbsUWj1V3LZX\ + s+gE5t/WSivHxJTjDg6BSWjTmr7wn5dsYj8FjFbQEC5T9jwzz8UCvW\ + AsZcXAE0Gukdz50ewGnLEUZV05eWEkDHr8ifmiqNxFgaP2dR1SIV5q\ + mJgR4fU3XXXZaLbQVgA5s97qU1mgtr7Ofz1d4PxxyqHmmmS7lIufwm\ + 3FHqNQ00IxijrTkPkrFKoOrv9IEsOvrVoHrFvYymRqEPSaL8ZPfbtn\ + r6i+AcwFu284BgxJn0IPPwAHkttIHomZyY9JJfATTI4/ERia3I7PGh\ + +zfxIdwuom0Y0iRDc1jVFfa+Il4za9zKAiNiAqYE7DRNkaIK3UF0y/\ + tsKnUTdgtw3Euliz5/D5F/5/MZkrNHII/Ip0heJTk6u8V4SyjYgU84\ + BfO9o1JXb+CScItISJKiZz/EYhUf/Rc8PLBJzpaz5OKuS6zgFRs514\ + wKnDbj/JOJt/sPl1TdyJ/ohu1cDBnYVJuJN9LTVTFxk+U/zB+5zJ0z\ + js6Hn1XG+X9VjQvmaLw9GnVwSfAvmeyaoF4RRPzGrAULVH86Q/MRn0\ + zu22b+aoF07moZgvHeKn7BlAcSvAEgnZaLBmoGJqV7iS1p1HpDMO3F\ + 7Wi/p6exFCvStIGC4pQQ== jwcarman@jx1" + ipv4_cidr_block: 10.240.128.0/24 + zone: us-south-3 + + tasks: + - name: Configure VPC + ibm_is_vpc: + name: "{{ name_prefix }}-vpc" + state: available + id: "{{ vpc.id | default(omit) }}" + register: vpc_create_output + + - name: Save VPC as fact + set_fact: + cacheable: True + vpc: "{{ vpc_create_output.resource }}" + + - name: Configure VPC Subnet + ibm_is_subnet: + name: "{{ name_prefix }}-subnet" + state: available + id: "{{ subnet.id | default(omit) }}" + vpc: "{{ vpc.id }}" + ipv4_cidr_block: "{{ ipv4_cidr_block }}" + zone: "{{ zone }}" + register: subnet_create_output + + - name: Save VPC Subnet as fact + set_fact: + cacheable: True + subnet: "{{ subnet_create_output.resource }}" + + - name: Configure SSH Key + ibm_is_ssh_key: + name: "{{ name_prefix }}-ssh-key" + public_key: "{{ ssh_public_key }}" + id: "{{ ssh_key.id | default(omit) }}" + register: ssh_key_create_output + + - name: Save SSH Key as fact + set_fact: + cacheable: True + ssh_key: "{{ ssh_key_create_output.resource }}" + + - name: Retrieve image list + ibm_is_images_info: + register: images_list + + - name: Set VM image name/id dictionary fact + set_fact: + cacheable: True + image_dict: "{{ images_list.resource.images | + items2dict(key_name='name', value_name='id') }}" + + - name: Configure VSI + ibm_is_instance: + name: "{{ name_prefix }}-vsi" + state: available + id: "{{ vsi.id | default(omit) }}" + vpc: "{{ vpc.id }}" + profile: "{{ vsi_profile }}" + image: "{{ image_dict[vsi_image] }}" + keys: + - "{{ ssh_key.id }}" + primary_network_interface: + - subnet: "{{ subnet.id }}" + zone: "{{ zone }}" + register: vsi_create_output + + - name: Save VSI as fact + set_fact: + cacheable: True + vsi: "{{ vsi_create_output.resource }}" + + - name: Configure Floating IP Address + ibm_is_floating_ip: + name: "{{ name_prefix }}-fip" + state: available + id: "{{ fip.id | default(omit) }}" + target: "{{ vsi.primary_network_interface[0]['id'] }}" + register: fip_create_output + + - name: Save Floating IP as fact + set_fact: + cacheable: True + fip: "{{ fip_create_output.resource }}" + + - name: Print Floating IP Address + debug: + msg: "IP Address: {{ fip.address }}" + + - name: Configure Security Group Rule to open SSH on the VSI + ibm_is_security_group_rule: + state: available + group: "{{ vpc.default_security_group }}" + direction: inbound + remote: 0.0.0.0/0 + tcp: + - port_max: 22 + port_min: 22 + + - name: Add VSI to Ansible inventory + add_host: + name: "{{ fip.address }}" + ansible_user: root + groups: new_vsi + ansible_ssh_extra_args: -o StrictHostKeyChecking=no + +- name: Check Ansible connection to new DEMO VSI + hosts: new_vsi + gather_facts: False + tasks: + - name: Wait for VSI to become reachable over SSH + wait_for_connection: + +- name: Check Ansible connection to new DEMO VSI + hosts: new_vsi + tasks: + - name: Collect OS information + command: cat /etc/os-release + register: os_info + + - name: Print OS information + debug: + var: os_info.stdout_lines diff --git a/examples/ansible/examples/simple-vm-ssh/destroy.yml b/examples/ansible/examples/simple-vm-ssh/destroy.yml new file mode 100755 index 0000000000..9d42225964 --- /dev/null +++ b/examples/ansible/examples/simple-vm-ssh/destroy.yml @@ -0,0 +1,35 @@ +--- +- name: Destroy IBM Cloud VPC VSI + hosts: localhost + + tasks: + - name: Release Floating IP + ibm_is_floating_ip: + state: absent + id: "{{ fip.id }}" + when: fip is defined + + - name: Remove VSI + ibm_is_instance: + state: absent + id: "{{ vsi.id }}" + keys: [] + when: vsi is defined + + - name: Remove SSH Key + ibm_is_ssh_key: + state: absent + id: "{{ ssh_key.id }}" + when: ssh_key is defined + + - name: Remove VPC Subnet + ibm_is_subnet: + state: absent + id: "{{ subnet.id }}" + when: subnet is defined + + - name: Remove VPC + ibm_is_vpc: + state: absent + id: "{{ vpc.id }}" + when: vpc is defined diff --git a/examples/ansible/examples/simple-vm-ssh/list_vsi_images_and_profiles.yml b/examples/ansible/examples/simple-vm-ssh/list_vsi_images_and_profiles.yml new file mode 100755 index 0000000000..13a25677ca --- /dev/null +++ b/examples/ansible/examples/simple-vm-ssh/list_vsi_images_and_profiles.yml @@ -0,0 +1,17 @@ +--- +- name: List VPC Images and Instance Profiles + hosts: localhost + + tasks: + - ibm_is_images_info: + register: images_list + + - debug: + var: images_list.resource.images | + items2dict(key_name='name', value_name='id') + + - ibm_is_instance_profiles_info: + register: instance_profiles_list + + - debug: + var: instance_profiles_list.resource.profiles | list