Launching a Droplet

As per previous playbooks we have written, you can create the skeleton structure by running the following commands:

$ mkdir digitalocean digitalocean/group_vars digitalocean/roles
$ ansible-galaxy init digitalocean/roles/droplet
$ touch digitalocean/production digitalocean/site.yml digitalocean/group_vars/common.yml

There are two tasks we need to complete to launch our Droplet; the first is that we need to make sure that a copy of our public SSH key is uploaded to DigitalOcean so that we can inject it into our Droplet launched during the second task.

Before we proceed with looking at the role which launches the Droplet we should figure what we are going to do with the personal access token required by the playbook to access the DigitalOcean API. For this we are going to use Ansible Vault to encode just the token; run the following command, making sure you replace the contents of encrypt_string with your own token:

ansible-vault 
encrypt_string 'pLgVbM2hswiLFWbemyD4Nru3a2yYwAKm2xbL6WmPBtzqvnMTrVTXYuabWbp7vArQ'
--name 'do_token'
The tokens used throughout these chapters are randomly generated; please make sure you replace them with your own.

The following screenshot shows the output for the preceding commands:

As you can see, this returns the encrypted token, so place the encrypted token in the group_vars/common.yml file. While we are populating variables, let's take a look at what the content of roles/droplet/defaults/main.yml should look like:

---
# defaults file for digitalocean/roles/droplet

key:
name: "Ansible"
path: "~/.ssh/id_rsa.pub"

droplet:
name: "AnsibleDroplet"
region: "lon1"
size: "s-1vcpu-2gb"
image: "centos-7-x64"
timeout: "500"

There are two collections of key values; the first deals with the SSH key, which the playbook will be uploading, and the second contains the information for launching the Droplet. The defaults for our initial playbook run will launch a 1-CPU core, 2 GB RAM, 50-GB HDD CentOS 7 Droplet in the DigitalOcean London data center.

The tasks for the launching the Droplet, which should be in roles/droplet/tasks/main.yml, contain two separate parts; the first part deals with uploading the SSH key, which needs to be there so we can launch the Droplet using it:

- name: "upload SSH key to DigitalOcean"
digital_ocean_sshkey:
oauth_token: "{{ do_token }}"
name: "{{ key.name }}"
ssh_pub_key: "{{ item }}"
state: present
with_file: "{{ key.path }}"

As you can see, this task uses the token we encrypted with Ansible Vault; we are also using the with_file directive to copy the contents of the key file, which is at ~/.ssh/id_rsa.pub. This task will do one of three things depending on what you already have in your DigitalOcean account:

  • If the key does not exist, it will upload it
  • If a key matches the fingerprint of ~/.ssh/id_rsa.pub but has a different name, then it will rename that key
  • If the key and name match, nothing will be uploaded or changed

Now that we know that we have our key uploaded, we need to know its unique ID. To find this out, we should gather facts on all of the keys that are configured in our DigitalOcean account by running the following task:

- name: "gather facts on all of the SSH keys in DigitalOcean"
digital_ocean_sshkey_facts:
oauth_token: "{{ do_token }}"

This will return a JSON array named ssh_keys which contains the name of the key, the fingerprint of the key, the contents of the key itself, and also the key's unique ID; this information is returned for each of the keys that are configured in our DigitalOcean account. As we need to know the ID of just one of those keys, we need to manipulate the results to filter the list down to just the single key we uploaded, and then set the ID as a variable.

As we know, we have a JSON array of potential keys stored in the ssh_keys value; for me, this looked like the following:

{
"fingerprint": "9e:ad:42:e9:86:01:3c:5f:de:11:60:11:e0:11:9e:11",
"id": 2663259,
"name": "Work",
"public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAv2cUTYCHnGcwHYjVh3vu09T6UwLEyXEKDnv3039KStLpQV3H7PvhOIpAbY7Gvxi1t2KyqkOvuBdIat5fdQKzGQMEFZiwlcgWDVQGJBKuMH02w+ceMqNYaD8sZqUO+bQQwkUDt3PuDKoyNRzhcDLsc//Dp6wAwJsw75Voe9bQecI3cWqjT54n+oareqADilQ/nO2cdFdmCEfVJP4CqOmL1QLJQNe46yQoGJWLNa9VPC8/ffmUPnwJRWa9AZRPAQ2vGbDF6meSsFwVUfhtxkn+0bof7PFxrcaycGa3zqt6m1y6o3BDh29eFN94TZf9lUK/nQrXuby2/FhrMBrRcgWE4gQ== russ@work"
},
{
"fingerprint": "7d:ce:56:5f:af:45:71:ab:af:fe:77:c2:9f:90:bc:cf",
"id": 19646265,
"name": "Ansible",
"public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDmuoFR01i/Yf3HATl9c3sufJvghTFgYzK/Zt29JiTqWlSQhmXhNNTh6iI6nXuPVhQGQaciWbqya6buncQ3vecISx6+EwsAmY3Mwpz1a/eMiXOgO/zn6Uf79dXcMN2JwpLFoON1f9PR0/DTpEkjwqb+eNLw9ThjH0J994+Pev+m8OrqgReFW36a/kviUYKsHxkXmkgxtPJgwKU90STNab4qyfKEGhi2w/NzECgseeQYs1H3klORaHQybhpXkoCIMmgy9gnzSH7oa2mJqKilVed27xoirkXzWPaAQlfiEE1iup+2xMqWY6Jl9qb8tJHRS+l8UcxTMNaWsQkTysLTgBAZ [email protected]"
}

You may have noticed I have already executed the playbook and uploaded my key so that I can walk through this task with you. We now need to find the key called key.name, which in our case is Ansible, and then return just the ID. To do this, we are going to add the following task:

- name: "set the SSH key ID as a fact"
set_fact:
pubkey: "{{ item.id }}"
with_items: "{{ ssh_keys | json_query(key_query) }}"
vars:
key_query: "[?name=='{{ key.name }}']"

As you can see, we are using the set_fact module to create a key-value pair called pubkey; we are using the ID of an item, and to make sure we return just one item, we are applying a JSON query to our array. This query makes sure that only the JSON that contains the key.name is returned in the with_items list; from here we can take the id of the single item, which allows us to move on to the second part, which is launching the Droplet.

Now that we know the ID of the SSH key we want to launch our Droplet with, we can move on to the second part of the role. The following task launches the Droplet:

- name: "launch the droplet"
digital_ocean:
state: "present"
command: "droplet"
name: "{{ droplet.name }}"
unique_name: "yes"
api_token: "{{ do_token }}"
size_id: "{{ droplet.size }}"
region_id: "{{ droplet.region }}"
image_id: "{{ droplet.image }}"
ssh_key_ids: [ "{{ pubkey }}" ]
wait_timeout: "{{ droplet.timeout }}"
register: droplet

This uses the digital_ocean module to launch the Droplet. Most of the items are self-explanatory; however, there is one important option we have to set a value for and that is unique_name. By default, unique_name is set to no, and what this means is that if we were to run our playbook a second time, a new Droplet with exactly the same details as the first Droplet we launched would be created; run it a third time and a third Droplet will be created. Setting unique_name to yes will mean that only a single Droplet with whatever the value of droplet.name is active at one time.

As you can see, we are registering the output of the task as a value. Some details about the Droplet are returned as part of the task execution; the IP address of the Droplet is one of them, so we can use this to set a fact and then print a message with the IP address:

- name: "set the droplet IP address as a fact"
set_fact:
droplet_ip: "{{ droplet.droplet.ip_address }}"

- name: "print the IP address of the droplet"
debug:
msg: "The IP of the droplet is {{ droplet_ip }}"

That completes the basic playbook and once we have updated the site.yml file, we can run it. This should contain the following:

---

- hosts: localhost
connection: local
gather_facts: false

vars_files:
- group_vars/common.yml

roles:
- roles/droplet

As you can see, we are just using localhost so there is no need to call the host inventory file.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.141.29.145