In part two of this tutorial we’ll be going over how we upload the exercise content to Confluence. If you missed the first part, please check it out here.

Using the Confluence REST API to create and update pages is fairly simple. The tricky part is knowing how to format the HTML body of the page in your request; however; you can use the Confluence web editor to format a template then grab the body from there. Making the GET request on the following URL will provide the HTML storage format that you can use to create or update a page later. Make sure to grab the value of the body where representation equals storage.

https://<confluence>/rest/api/content/{pageId}?expand=body.storage
 
 
"body": {
    "storage": {
        "value": "

This is a blog post.

",
        "representation": "storage",
        "_expandable": {
            "webresource": "",
            "content": "/rest/api/content/141952152"
        }
    },

Great, now we have the body that we can put into a jinja2 template. Since Ansible should be idempotent, we decided to have a check to determine if the Confluence page already exists. If it does, then we can just update the page if the content of the body is different. We used the search REST API to determine if a page with our generated title is already in Confluence. The search REST API uses CQL to search for content.

- name: check if Confluence page exists
    uri:
    url: "https://wiki.isostech.com/rest/api/content/search/?cql=title=%22{{ cql_wiki_title | regex_replace(' ', '%20') }}%22&expand=version"
    method: GET
    user: "{{ confluence_user }}"
    password: "{{ confluence_pass }}"
    force_basic_auth: yes
    status_code: 200
    register: confluence_validate

The JSON object returned from the search API has a convenient “size” property. If the value is 0, we create a new page. If the value is 1, then we update the existing page. The JSON data that we use to create and update the page is generated by our jinja2 template, and variables are used to make the page unique for each consultant. The logic is handled by the when conditional in Ansible.

- name: Create Confluence page
    uri:
        url: https://wiki.isostech.com/rest/api/content/
        method: POST
        user: "{{ confluence_user }}"
        password: "{{ confluence_pass }}"
        body: "{{ lookup('file','{{ aws_vpc_stackName }}-click2clone-exercise.json') }}"
        force_basic_auth: yes
        status_code: 201,200
        body_format: json
    when: confluence_validate.json.size == 0
 
 
- name: Update Confluence page
    uri:
        url: "https://wiki.isostech.com/rest/api/content/{{ confluence_validate.json.results[0].id }}"
        method: PUT
        user: "{{ confluence_user }}"
        password: "{{ confluence_pass }}"
        body: "{{ lookup('file','{{ aws_vpc_stackName }}-click2clone-exercise.json') }}"
        force_basic_auth: yes
        status_code: 201,200
        body_format: json
    when: confluence_validate.json.size == 1

As Andrew stated in part 1 of this blog post, our Ansible exercise creates a key pair in AWS. The generated pem file is used by the technical consultant to connect to the instances created by the cloud formation stack . We decided to use Confluence REST API to attach the pem file to the page as well. We handled attachment upload in a similar way to page creation just in case the Ansible had to be ran multiple times. First we use the REST API to get attachments of the page. If no page attachments with the title for the pem file was found, then we would upload the attachment. Unfortunately, Ansible’s uri module does not support uploading multipart/form-data yet. So we had to use curl with the command module to make the REST call to Confluence.


- name: check if Attachment exists on Confluence page
    uri:
        url: "https://wiki.isostech.com/rest/api/content/{{ confluence_validate.json.results[0].id }}/child/attachment"
        method: GET
        user: "{{ confluence_user }}"
        password: "{{ confluence_pass }}"
        force_basic_auth: true
        status_code: 200
    register: confluence_attachment_validate
 
- name: set var if attachment is found
    set_fact:
        attachment_found: true
    when: item.title == "{{ aws_key_name }}.pem"
    with_items: "{{ confluence_attachment_validate.json.results }}"
 
- name: upload attachment to Confluence page
    command: "curl -S -u {{ confluence_user }}:{{ confluence_pass }} -X POST -H \"X-Atlassian-Token: no-check\" -F \"file=@{{ aws_key_name }}.pem\" \"https://wiki.isostech.com/rest/api/content/{{ confluence_validate.json.results[0].id }}/child/attachment\""
    when: attachment_found is not defined

Red Hat encourages using Ansible to automate everything in IT. We managed to use Ansible as a way to on-board new technical consultants. Not just by creating just the infrastructure as you would think, but also by creating a unique page for the user to get started on their exercises. We look forward to using Ansible to automate more here at Isos.