Pausing MongoDB Atlas Clusters with Ansible

· 3min · Dan F.

It's been awhile since my last post! Life changes, and so has my work responsibilities. Lately, I've been working a lot with MongoDB, specifically MongoDB Atlas. In order to reducing my bill each month, I developed a way to shutdown my test replicasets each evening.

For those of you who have never used MongoDB before, it is a very popular NoSql document database. A MongoDB cluster that is replicated across multiple nodes is called a replicaset. A typical MongoDB replicaset is comprised of three nodes. There is always one node that is elected as the primary, with the remaining two nodes being secondaries. The secondaries always contain an exact copy of the primary's data.

I have been using this playbook to pause my test replicasets each evening, and unpausing them in the morning. This reduces my monthly bill by at least 40%. This playbook utilizes the MongoDB Atlas API, as documented here. For this playbook to function, you will have to create an API key that has modification rights to your project's replicasets. You can read about how to generate and utilize the API key here.

First, you will need to create a vars file at the ansible project level. You will need both the name of the replicaset, as well as the group id of the project, which can be found in the url of your project. An example of the required vars file is below:

vars/atlas_clusters.yml

atlas_clusters:
  replicaset-poc-one: 401d7833e6a61470d581318f
  replicaset-poc-two: 4024342e2363fa2f8f18f9e2

Next, create a role folder in your ansible project, named atlas-api, where we create the three files shown below. These two tasks will either pause, or unpause your Atlas replicasets. The main.yml simply gives your atlas-api role a little more flexibility:

roles/atlas-api/main.yml

+++
- include_tasks: "atlas_{{ atlas_api_object }}_{{ atlas_api_operation }}.yml"
  when: atlas_api_object is defined and atlas_api_operation is defined

roles/atlas-api/atlas_cluster_pause.yml

- name: Ensure mandatory variables are defined
  fail:
    msg: "Missing variable {{ item }}"
  when: vars[item] is undefined
  with_items:
    - atlas_clusters
    - atlas_public_key
    - atlas_private_key

- name: Pause clusters
  uri:
    url: "https://cloud.mongodb.com/api/atlas/v1.0/groups/{{ item.value }}/clusters/{{ item.key }}"
    user: "{{ atlas_public_key }}"
    password: "{{ atlas_private_key }}"
    method: PATCH
    body: '{ "paused": true }'
    force_basic_auth: no
    status_code: [200, 409]
    body_format: json
  loop: "{{ atlas_clusters | dict2items }}"
  register: response
  changed_when: response.status == 200

roles/atlas-api/atlas_cluster_unpause.yml

- name: Ensure mandatory variables are defined
  fail:
    msg: "Missing variable {{ item }}"
  when: vars[item] is undefined
  with_items:
    - atlas_clusters
    - atlas_public_key
    - atlas_private_key

- name: Unpause clusters
  uri:
    url: "https://cloud.mongodb.com/api/atlas/v1.0/groups/{{ item.value }}/clusters/{{ item.key }}"
    user: "{{ atlas_public_key }}"
    password: "{{ atlas_private_key }}"
    method: PATCH
    body: '{ "paused": false }'
    force_basic_auth: no
    status_code: [200,409]
    body_format: json
  loop: "{{ atlas_clusters | dict2items }}"
  register: response
  changed_when: response.status == 200

Next, we will need to create the playbook that calls these two roles. Create the following playbooks that will either pause, or unpause your clusters:

pause_playbook.yml

- hosts: localhost

  tasks:
    - name: Import default deployment variables
      include_vars:
        file: "vars/atlas_clusters.yml"

    - name: Include atlas-api role
      include_role:
        role: atlas-api
      vars:
        atlas_api_object: cluster
        atlas_api_operation: pause
        atlas_public_key: <YOUR API PUBLIC KEY>
        atlas_private_key: <YOUR API PRIVATE KEY>

unpause_playbook.yml

- hosts: localhost

  tasks:
    - name: Import default deployment variables
      include_vars:
        file: "vars/atlas_clusters.yml"

    - name: Include atlas-api role
      include_role:
        role: atlas-api
      vars:
        atlas_api_object: cluster
        atlas_api_operation: unpause
        atlas_public_key: <YOUR API PUBLIC KEY>
        atlas_private_key: <YOUR API PRIVATE KEY>

To pause your clusters, simply run ansible-playbook -i localhost pause_playbook.yml, and to unpause them, run ansible-playbook -i localhost unpause_playbook.yml.