From dacfd72bd6c661a3ee2565ca081bfe75882e6d0c Mon Sep 17 00:00:00 2001 From: Rhys Campbell Date: Wed, 31 Jul 2019 21:45:21 +0200 Subject: [PATCH] Integeration tests for mongodb_shard and mongodb_replicaset modules (#53900) --- .../targets/mongodb_replicaset/aliases | 6 + .../mongodb_replicaset/defaults/main.yml | 24 + .../mongodb_replicaset/files/js/is_primary.js | 13 + .../targets/mongodb_replicaset/meta/main.yml | 3 + .../targets/mongodb_replicaset/tasks/main.yml | 496 ++++++++++++++++++ .../tasks/mongod_replicaset.yml | 44 ++ .../tasks/mongod_teardown.yml | 27 + .../integration/targets/mongodb_shard/aliases | 6 + .../targets/mongodb_shard/defaults/main.yml | 16 + .../files/bash/ensure_primary.sh.j2 | 38 ++ .../mongodb_shard/files/js/is_primary.js | 13 + .../targets/mongodb_shard/meta/main.yml | 3 + .../targets/mongodb_shard/tasks/main.yml | 458 ++++++++++++++++ .../mongodb_shard/tasks/mongod_replicaset.yml | 51 ++ .../mongodb_shard/tasks/mongod_teardown.yml | 35 ++ .../templates/create_user_root_3.2.js.j2 | 8 + .../targets/setup_mongodb/defaults/main.yml | 50 ++ .../targets/setup_mongodb/handlers/main.yml | 19 + .../targets/setup_mongodb/tasks/main.yml | 186 +++++++ 19 files changed, 1496 insertions(+) create mode 100644 test/integration/targets/mongodb_replicaset/aliases create mode 100644 test/integration/targets/mongodb_replicaset/defaults/main.yml create mode 100644 test/integration/targets/mongodb_replicaset/files/js/is_primary.js create mode 100644 test/integration/targets/mongodb_replicaset/meta/main.yml create mode 100644 test/integration/targets/mongodb_replicaset/tasks/main.yml create mode 100644 test/integration/targets/mongodb_replicaset/tasks/mongod_replicaset.yml create mode 100644 test/integration/targets/mongodb_replicaset/tasks/mongod_teardown.yml create mode 100644 test/integration/targets/mongodb_shard/aliases create mode 100644 test/integration/targets/mongodb_shard/defaults/main.yml create mode 100644 test/integration/targets/mongodb_shard/files/bash/ensure_primary.sh.j2 create mode 100644 test/integration/targets/mongodb_shard/files/js/is_primary.js create mode 100644 test/integration/targets/mongodb_shard/meta/main.yml create mode 100644 test/integration/targets/mongodb_shard/tasks/main.yml create mode 100644 test/integration/targets/mongodb_shard/tasks/mongod_replicaset.yml create mode 100644 test/integration/targets/mongodb_shard/tasks/mongod_teardown.yml create mode 100644 test/integration/targets/mongodb_shard/templates/create_user_root_3.2.js.j2 create mode 100644 test/integration/targets/setup_mongodb/defaults/main.yml create mode 100644 test/integration/targets/setup_mongodb/handlers/main.yml create mode 100644 test/integration/targets/setup_mongodb/tasks/main.yml diff --git a/test/integration/targets/mongodb_replicaset/aliases b/test/integration/targets/mongodb_replicaset/aliases new file mode 100644 index 00000000000..e9fc78ee6de --- /dev/null +++ b/test/integration/targets/mongodb_replicaset/aliases @@ -0,0 +1,6 @@ +destructive +shippable/posix/group1 +skip/osx +skip/freebsd +skip/rhel +needs/root diff --git a/test/integration/targets/mongodb_replicaset/defaults/main.yml b/test/integration/targets/mongodb_replicaset/defaults/main.yml new file mode 100644 index 00000000000..343d48e96ad --- /dev/null +++ b/test/integration/targets/mongodb_replicaset/defaults/main.yml @@ -0,0 +1,24 @@ +--- +# defaults file for test_mongodb_replicaset +mongodb_replicaset1: rs1 +mongodb_replicaset2: rs2 +mongodb_replicaset3: rs3 +mongodb_replicaset4: rs4 +mongodb_replicaset5: rs5 +mongodb_replicaset6: rs6 +mongodb_replicaset7: rs7 +mongodb_replicaset8: rs8 +test_mongo_auth: yes +mongodb_admin_user: test_root +mongodb_admin_password: saE_Rr9!gE6gh#e~R#nZ +debug: False +mongodb_nodes: + - 3001 + - 3002 + - 3003 +mongod_auth: false +kill_signal: SIGTERM +# Should be one of +mongod_storage_engine_opts: "--storageEngine wiredTiger --wiredTigerEngineConfigString='cache_size=200M'" +#mongod_storage_engine_opts: "--storageEngine mmapv1 --nojournal" +mongodb_user: mongodb diff --git a/test/integration/targets/mongodb_replicaset/files/js/is_primary.js b/test/integration/targets/mongodb_replicaset/files/js/is_primary.js new file mode 100644 index 00000000000..7bb130614f2 --- /dev/null +++ b/test/integration/targets/mongodb_replicaset/files/js/is_primary.js @@ -0,0 +1,13 @@ +var done = false; +var iterations = 0; +while(rs.status()['myState'] != 1) { + if (!done) { + //print("State is not yet PRIMARY. Waiting..."); + done = true + } + sleep(1000); + iterations++; + if (iterations == 100) { + throw new Error("Exceeded iterations limit."); + } + } diff --git a/test/integration/targets/mongodb_replicaset/meta/main.yml b/test/integration/targets/mongodb_replicaset/meta/main.yml new file mode 100644 index 00000000000..9d941be0bcc --- /dev/null +++ b/test/integration/targets/mongodb_replicaset/meta/main.yml @@ -0,0 +1,3 @@ +dependencies: + - setup_mongodb + - setup_remote_tmp_dir diff --git a/test/integration/targets/mongodb_replicaset/tasks/main.yml b/test/integration/targets/mongodb_replicaset/tasks/main.yml new file mode 100644 index 00000000000..d416bfc84ed --- /dev/null +++ b/test/integration/targets/mongodb_replicaset/tasks/main.yml @@ -0,0 +1,496 @@ +# test code for the mongodb_replicaset module +# (c) 2019, Rhys Campbell + +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +# ============================================================ + +- name: Ensure tests home exists + file: + path: "{{ remote_tmp_dir }}/tests" + state: directory + +- include_tasks: mongod_teardown.yml + +- set_fact: + current_replicaset: "{{ mongodb_replicaset1 }}" + +- include_tasks: mongod_replicaset.yml + +# test with yaml list +- name: Create replicaset with module + mongodb_replicaset: + login_user: admin + login_password: secret + login_host: "localhost" + login_port: 3001 + login_database: "admin" + replica_set: "{{ mongodb_replicaset1 }}" + heartbeat_timeout_secs: 1 + election_timeout_millis: 1000 + members: + - "localhost:3001" + - "localhost:3002" + - "localhost:3003" + +- name: Ensure is_primary script exists on host + copy: + src: js/is_primary.js + dest: "{{ remote_tmp_dir }}/tests/is_primary.js" + +- name: Get replicaset info + command: mongo admin --eval "rs.status()" --port 3001 + register: mongo_output + +- name: Assert replicaset name is in mongo_output + assert: + that: + - "mongo_output.changed == true" + - "'{{ mongodb_replicaset1 }}' in mongo_output.stdout" + - "'localhost:3001' in mongo_output.stdout" + - "'localhost:3002' in mongo_output.stdout" + - "'localhost:3003' in mongo_output.stdout" + +- name: Add mongodb admin user + mongodb_user: + login_host: localhost + login_port: 3001 + replica_set: "{{ mongodb_replicaset1 }}" + database: admin + name: "{{ mongodb_admin_user }}" + password: "{{ mongodb_admin_password }}" + roles: ["root"] + state: present + register: mongo_admin_user + when: test_mongo_auth + +- name: Murder all mongod processes + shell: pkill -{{ kill_signal }} mongod; + +- name: Getting pids for mongod + pids: + name: mongod + register: pids_of_mongod + +- name: Wait for all mongod processes to exit + wait_for: + path: "/proc/{{ item }}/status" + state: absent + with_items: "{{ pids_of_mongod }}" + +- set_fact: + current_replicaset: "{{ mongodb_replicaset1 }}" + +- set_fact: + mongod_auth: true + +- name: Execute mongod script to restart with auth enabled + include_tasks: mongod_replicaset.yml + +- name: Validate replicaset previously created + mongodb_replicaset: + login_user: "{{ mongodb_admin_user }}" + login_password: "{{ mongodb_admin_password }}" + login_host: "localhost" + login_port: 3001 + login_database: "admin" + replica_set: "{{ mongodb_replicaset1 }}" + election_timeout_millis: 1000 + members: + - "localhost:3001" + - "localhost:3002" + - "localhost:3003" + register: mongodb_replicaset + +- name: Assert replicaset name has not changed + assert: + that: mongodb_replicaset.changed == False + +- name: Test with bad password + mongodb_replicaset: + login_user: "{{ mongodb_admin_user }}" + login_password: XXXXXXXXXXXXXXXX + login_host: "localhost" + login_port: 3001 + login_database: "admin" + replica_set: "{{ mongodb_replicaset1 }}" + election_timeout_millis: 1000 + members: + - "localhost:3001" + - "localhost:3002" + - "localhost:3003" + register: mongodb_replicaset_bad_pw + ignore_errors: True + +- name: Assert login failed + assert: + that: + - "mongodb_replicaset_bad_pw.rc == 1" + - "'Authentication failed' in mongodb_replicaset_bad_pw.module_stderr" + + ############################################################# + +- include_tasks: mongod_teardown.yml + +- set_fact: + current_replicaset: "{{ mongodb_replicaset2 }}" + +- set_fact: + mongod_auth: false + +- name: Execute mongod script to restart with auth enabled + include_tasks: mongod_replicaset.yml + +# Test with python style list +- name: Create replicaset with module + mongodb_replicaset: + login_user: admin + login_password: secret + login_host: "localhost" + login_port: 3001 + login_database: "admin" + replica_set: "{{ mongodb_replicaset2 }}" + members: [ "localhost:3001", "localhost:3002", "localhost:3003" ] + election_timeout_millis: 1000 + heartbeat_timeout_secs: 1 + +- name: Get replicaset info + command: mongo admin --eval "rs.status()" --port 3001 + register: mongo_output + +- name: Assert replicaset name is in mongo_output + assert: + that: + - "mongo_output.changed == true" + - "'{{ mongodb_replicaset2 }}' in mongo_output.stdout" + - "'localhost:3001' in mongo_output.stdout" + - "'localhost:3002' in mongo_output.stdout" + - "'localhost:3003' in mongo_output.stdout" + +############################################################# + +- include_tasks: mongod_teardown.yml + +- set_fact: + current_replicaset: "{{ mongodb_replicaset3 }}" + +- set_fact: + mongod_auth: false + +- name: Launch mongod processes + include_tasks: mongod_replicaset.yml + +# Test with csv string +- name: Create replicaset with module + mongodb_replicaset: + login_user: admin + login_password: secret + login_host: "localhost" + login_port: 3001 + login_database: "admin" + replica_set: "{{ mongodb_replicaset3 }}" + members: "localhost:3001,localhost:3002,localhost:3003" + election_timeout_millis: 1000 + +- name: Get replicaset info + command: mongo admin --eval "rs.status()" --port 3001 + register: mongo_output + +- name: Assert replicaset name is in mongo_output + assert: + that: + - "mongo_output.changed == true" + - "'{{ mongodb_replicaset3 }}' in mongo_output.stdout" + - "'localhost:3001' in mongo_output.stdout" + - "'localhost:3002' in mongo_output.stdout" + - "'localhost:3003' in mongo_output.stdout" + + ############################################################# + +- include_tasks: mongod_teardown.yml + +- set_fact: + current_replicaset: "{{ mongodb_replicaset4 }}" + +- set_fact: + mongod_auth: false + +- name: Launch mongod processes + include_tasks: mongod_replicaset.yml + +# Test with arbiter_at_index +- name: Create replicaset with module + mongodb_replicaset: + login_user: admin + login_password: secret + login_host: "localhost" + login_port: 3001 + login_database: "admin" + arbiter_at_index: 2 + replica_set: "{{ mongodb_replicaset4 }}" + members: "localhost:3001,localhost:3002,localhost:3003" + election_timeout_millis: 1000 + +- name: Ensure host reaches primary before proceeding 3001 + command: mongo admin --port 3001 "{{ remote_tmp_dir }}/tests/is_primary.js" + +- name: Get replicaset info + command: mongo admin --eval "rs.status()" --port 3001 + register: mongo_output + +- name: Assert replicaset name is in mongo_output + assert: + that: + - "mongo_output.changed == true" + - "'{{ mongodb_replicaset4 }}' in mongo_output.stdout" + - "'localhost:3001' in mongo_output.stdout" + - "'localhost:3002' in mongo_output.stdout" + - "'localhost:3003' in mongo_output.stdout" + - "'ARBITER' in mongo_output.stdout" + +############################################################# + +- include_tasks: mongod_teardown.yml + +- set_fact: + current_replicaset: "{{ mongodb_replicaset5 }}" + +- set_fact: + mongod_auth: false + +- name: Launch mongod processes + include_tasks: mongod_replicaset.yml + +# Test with chainingAllowed +- name: Create replicaset with module + mongodb_replicaset: + login_user: admin + login_password: secret + login_host: "localhost" + login_port: 3001 + login_database: "admin" + chaining_allowed: no + replica_set: "{{ mongodb_replicaset5 }}" + election_timeout_millis: 1000 + members: + - localhost:3001 + - localhost:3002 + - localhost:3003 + +- name: Get replicaset info + command: mongo admin --eval "rs.conf()" --port 3001 + register: mongo_output + +- name: Assert replicaset name is in mongo_output + assert: + that: + - "mongo_output.changed == true" + - "'{{ mongodb_replicaset5 }}' in mongo_output.stdout" + - "'localhost:3001' in mongo_output.stdout" + - "'localhost:3002' in mongo_output.stdout" + - "'localhost:3003' in mongo_output.stdout" + - "'chainingAllowed\" : false,' in mongo_output.stdout" + +############################################################# + +- include_tasks: mongod_teardown.yml + +- set_fact: + current_replicaset: "{{ mongodb_replicaset6 }}" + +- set_fact: + mongodb_nodes: [ 3001, 3002, 3003, 3004, 3005] + +- set_fact: + mongod_auth: false + +- name: Launch mongod processes + include_tasks: mongod_replicaset.yml + +# Test with 5 mongod processes +- name: Create replicaset with module + mongodb_replicaset: + login_user: admin + login_password: secret + login_host: "localhost" + login_port: 3001 + login_database: "admin" + replica_set: "{{ mongodb_replicaset6 }}" + election_timeout_millis: 1000 + members: + - localhost:3001 + - localhost:3002 + - localhost:3003 + - localhost:3004 + - localhost:3005 + +- name: Get replicaset info + command: mongo admin --eval "rs.conf()" --port 3001 + register: mongo_output + +- name: Assert replicaset name is in mongo_output + assert: + that: + - "mongo_output.changed == true" + - "'{{ mongodb_replicaset6 }}' in mongo_output.stdout" + - "'localhost:3001' in mongo_output.stdout" + - "'localhost:3002' in mongo_output.stdout" + - "'localhost:3003' in mongo_output.stdout" + - "'localhost:3004' in mongo_output.stdout" + - "'localhost:3005' in mongo_output.stdout" + +############################################################# + +- include_tasks: mongod_teardown.yml + +- set_fact: + current_replicaset: "{{ mongodb_replicaset7 }}" + +- set_fact: + mongod_auth: false + +- set_fact: + mongodb_nodes: [ 3001, 3002, 3003 ] + +- name: Launch mongod processes + include_tasks: mongod_replicaset.yml + +# Test withheartbeatTimeoutSecs +- name: Create replicaset with module + mongodb_replicaset: + login_user: admin + login_password: secret + login_host: "localhost" + login_port: 3001 + login_database: "admin" + election_timeout_millis: 9999 + replica_set: "{{ mongodb_replicaset7 }}" + members: + - localhost:3001 + - localhost:3002 + - localhost:3003 + +- name: Get replicaset info + command: mongo admin --eval "rs.conf()" --port 3001 + register: mongo_output + +- name: Assert replicaset name is in mongo_output + assert: + that: + - "mongo_output.changed == true" + - "'{{ mongodb_replicaset7 }}' in mongo_output.stdout" + - "'localhost:3001' in mongo_output.stdout" + - "'localhost:3002' in mongo_output.stdout" + - "'localhost:3003' in mongo_output.stdout" + - "'electionTimeoutMillis\" : 9999,' in mongo_output.stdout" + +############################################################# + +- include_tasks: mongod_teardown.yml + +- set_fact: + current_replicaset: "{{ mongodb_replicaset8 }}" + +- name: Launch mongod processes + include_tasks: mongod_replicaset.yml + +# Test with heartbeatTimeoutSecs +- name: Create replicaset with module protocolVersion 0 (Mongodb 3.0) + mongodb_replicaset: + login_user: admin + login_password: secret + login_host: "localhost" + login_port: 3001 + login_database: "admin" + protocol_version: 0 + heartbeat_timeout_secs: 9 + replica_set: "{{ mongodb_replicaset8 }}" + election_timeout_millis: 1000 + members: + - localhost:3001 + - localhost:3002 + - localhost:3003 + when: mongodb_version.startswith('3') == True + +- name: Create replicaset with module protocolVersion 1 (MongoDB 4.0+) + mongodb_replicaset: + login_user: admin + login_password: secret + login_host: "localhost" + login_port: 3001 + login_database: "admin" + protocol_version: 1 + election_timeout_millis: 9000 + replica_set: "{{ mongodb_replicaset8 }}" + members: + - localhost:3001 + - localhost:3002 + - localhost:3003 + when: mongodb_version.startswith('4') == True + +- name: Get replicaset info + command: mongo admin --eval "rs.conf()" --port 3001 + register: mongo_output + +- name: Assert replicaset name is in mongo_output MongoDB 3.0+ + assert: + that: + - "mongo_output.changed == true" + - "'{{ mongodb_replicaset8 }}' in mongo_output.stdout" + - "'localhost:3001' in mongo_output.stdout" + - "'localhost:3002' in mongo_output.stdout" + - "'localhost:3003' in mongo_output.stdout" + - "'heartbeatTimeoutSecs\" : 9,' in mongo_output.stdout" + when: mongodb_version.startswith('3') == True + +- name: Assert replicaset name is in mongo_output MongoDB 4.0+ + assert: + that: + - "mongo_output.changed == true" + - "'{{ mongodb_replicaset8 }}' in mongo_output.stdout" + - "'localhost:3001' in mongo_output.stdout" + - "'localhost:3002' in mongo_output.stdout" + - "'localhost:3003' in mongo_output.stdout" + - "'electionTimeoutMillis\" : 9000,' in mongo_output.stdout" + when: mongodb_version.startswith('4') == True + +# TODO - Readd this test once we support serverSelectionTimeoutMS / connectTimeoutMS +#- name: Run test with unknown host +# mongodb_replicaset: +# login_user: admin +# login_password: secret +# login_host: "idonotexist" +# login_port: 3001 +# login_database: "admin" +# protocol_version: 0 +# heartbeat_timeout_secs: 9 +# replica_set: "{{ mongodb_replicaset8 }}" +# election_timeout_millis: 1000 +# members: +# - idonotexist:3001 +# - idonotexist:3002 +# - idonotexist:3003 +# ignore_errors: True +# register: host_does_not_exist + +#- name: Assert that "Name or service not known" is in error +# assert: +# that: +# - "host_does_not_exist.rc == 1" +# - "'Name or service not known' in host_does_not_exist.module_stderr" + +# Final clean up to prevent "directory not empty" error +- include_tasks: mongod_teardown.yml diff --git a/test/integration/targets/mongodb_replicaset/tasks/mongod_replicaset.yml b/test/integration/targets/mongodb_replicaset/tasks/mongod_replicaset.yml new file mode 100644 index 00000000000..9ad3bb14964 --- /dev/null +++ b/test/integration/targets/mongodb_replicaset/tasks/mongod_replicaset.yml @@ -0,0 +1,44 @@ +- name: Set mongodb_user user for redhat + set_fact: + mongodb_user: "mongod" + when: ansible_os_family == "RedHat" + +- name: Create directories for mongod processes + file: + path: "{{ remote_tmp_dir }}/mongod{{ item }}" + state: directory + owner: "{{ mongodb_user }}" + group: "{{ mongodb_user }}" + mode: 0755 + recurse: yes + with_items: "{{ mongodb_nodes }}" + +- name: Create keyfile + copy: + dest: "{{ remote_tmp_dir }}/my.key" + content: | + fd2CUrbXBJpB4rt74A6F + owner: "{{ mongodb_user }}" + group: "{{ mongodb_user }}" + mode: 0600 + when: mongod_auth == True + +- name: Spawn mongod process without auth + command: mongod --shardsvr --smallfiles {{ mongod_storage_engine_opts }} --dbpath mongod{{ item }} --port {{ item }} --replSet {{ current_replicaset }} --logpath mongod{{ item }}/log.log --fork + args: + chdir: "{{ remote_tmp_dir }}" + with_items: "{{ mongodb_nodes | sort }}" + when: mongod_auth == False + +- name: Spawn mongod process with auth + command: mongod --shardsvr --smallfiles {{ mongod_storage_engine_opts }} --dbpath mongod{{ item }} --port {{ item }} --replSet {{ current_replicaset }} --logpath mongod{{ item }}/log.log --fork --auth --keyFile my.key + args: + chdir: "{{ remote_tmp_dir }}" + with_items: "{{ mongodb_nodes | sort }}" + when: mongod_auth == True + ignore_errors: yes + +- name: Wait for mongod to start responding + wait_for: + port: "{{ item }}" + with_items: "{{ mongodb_nodes }}" diff --git a/test/integration/targets/mongodb_replicaset/tasks/mongod_teardown.yml b/test/integration/targets/mongodb_replicaset/tasks/mongod_teardown.yml new file mode 100644 index 00000000000..7bc5d3d0a0a --- /dev/null +++ b/test/integration/targets/mongodb_replicaset/tasks/mongod_teardown.yml @@ -0,0 +1,27 @@ +- name: Kill all mongod processes + command: pkill -{{ kill_signal }} mongod + ignore_errors: true + +- name: Getting pids for mongod + pids: + name: mongod + register: pids_of_mongod + +- name: Wait for all mongod processes to exit + wait_for: + path: "/proc/{{ item }}/status" + state: absent + delay: 1 + with_items: "{{ pids_of_mongod }}" + +- name: Remove all mongod folders + file: + path: "{{ remote_tmp_dir }}/{{ item }}" + state: absent + with_items: + - mongod3001 + - mongod3002 + - mongod3003 + +- name: Remove all mongod sock files + shell: rm -Rf /tmp/mongodb*.sock diff --git a/test/integration/targets/mongodb_shard/aliases b/test/integration/targets/mongodb_shard/aliases new file mode 100644 index 00000000000..e9fc78ee6de --- /dev/null +++ b/test/integration/targets/mongodb_shard/aliases @@ -0,0 +1,6 @@ +destructive +shippable/posix/group1 +skip/osx +skip/freebsd +skip/rhel +needs/root diff --git a/test/integration/targets/mongodb_shard/defaults/main.yml b/test/integration/targets/mongodb_shard/defaults/main.yml new file mode 100644 index 00000000000..7ad82d68069 --- /dev/null +++ b/test/integration/targets/mongodb_shard/defaults/main.yml @@ -0,0 +1,16 @@ +--- +# defaults file for test_mongodb_shard +mongodb_replicaset1: rs1 +mongodb_replicaset2: rs2 +configsrv_replicaset: cfg +test_mongo_auth: yes +mongodb_admin_user: test_root +mongodb_admin_password: saE_Rr9!gE6gh#e~R#nZ +debug: yes +mongod_auth: false +kill_signal: SIGTERM +# Should be one of +# --storageEngine wiredTiger --wiredTigerEngineConfigString="cache_size=200M" +# --storageEngine mmapv1 --nojournal +mongod_storage_engine_opts: "--storageEngine wiredTiger --wiredTigerEngineConfigString='cache_size=200M'" +mongodb_user: mongodb diff --git a/test/integration/targets/mongodb_shard/files/bash/ensure_primary.sh.j2 b/test/integration/targets/mongodb_shard/files/bash/ensure_primary.sh.j2 new file mode 100644 index 00000000000..cff0638f108 --- /dev/null +++ b/test/integration/targets/mongodb_shard/files/bash/ensure_primary.sh.j2 @@ -0,0 +1,38 @@ +#!/usr/bin/env bash + +# This script is here because on some occassions the head mongodb does not become primary. + +PRIMARY=$1; +AUTH=$2; + +if [ "$AUTH" == "1" ]; then + if [ "$PRIMARY" == "3001" ]; then + mongo admin --port 3002 -u {{ mongodb_admin_user }} -p {{ mongodb_admin_password }} --eval "rs.freeze(120)"; + mongo admin --port 3003 -u {{ mongodb_admin_user }} -p {{ mongodb_admin_password }} --eval "rs.freeze(120)"; + mongo admin --port 3002 -u {{ mongodb_admin_user }} -p {{ mongodb_admin_password }} --eval "rs.stepDown()"; + mongo admin --port 3003 -u {{ mongodb_admin_user }} -p {{ mongodb_admin_password }} --eval "rs.stepDown()"; + elif [ "$PRIMARY" == "3004" ]; then + mongo admin --port 3005 -u {{ mongodb_admin_user }} -p {{ mongodb_admin_password }} --eval "rs.freeze(120)"; + mongo admin --port 3006 -u {{ mongodb_admin_user }} -p {{ mongodb_admin_password }} --eval "rs.freeze(120)"; + mongo admin --port 3005 -u {{ mongodb_admin_user }} -p {{ mongodb_admin_password }} --eval "rs.stepDown()"; + mongo admin --port 3006 -u {{ mongodb_admin_user }} -p {{ mongodb_admin_password }} --eval "rs.stepDown()"; + else + echo "Unsupported port!"; + exit 1; + fi; +else + if [ "$PRIMARY" == "3001" ]; then + mongo admin --port 3002 --eval "rs.freeze(120)"; + mongo admin --port 3003 --eval "rs.freeze(120)"; + mongo admin --port 3002 --eval "rs.stepDown()"; + mongo admin --port 3003 --eval "rs.stepDown()"; + elif [ "$PRIMARY" == "3004" ]; then + mongo admin --port 3005 --eval "rs.freeze(120)"; + mongo admin --port 3006 --eval "rs.freeze(120)"; + mongo admin --port 3005 --eval "rs.stepDown()"; + mongo admin --port 3006 --eval "rs.stepDown()"; + else + echo "Unsupported port!"; + exit 1; + fi; +fi; diff --git a/test/integration/targets/mongodb_shard/files/js/is_primary.js b/test/integration/targets/mongodb_shard/files/js/is_primary.js new file mode 100644 index 00000000000..7bb130614f2 --- /dev/null +++ b/test/integration/targets/mongodb_shard/files/js/is_primary.js @@ -0,0 +1,13 @@ +var done = false; +var iterations = 0; +while(rs.status()['myState'] != 1) { + if (!done) { + //print("State is not yet PRIMARY. Waiting..."); + done = true + } + sleep(1000); + iterations++; + if (iterations == 100) { + throw new Error("Exceeded iterations limit."); + } + } diff --git a/test/integration/targets/mongodb_shard/meta/main.yml b/test/integration/targets/mongodb_shard/meta/main.yml new file mode 100644 index 00000000000..9d941be0bcc --- /dev/null +++ b/test/integration/targets/mongodb_shard/meta/main.yml @@ -0,0 +1,3 @@ +dependencies: + - setup_mongodb + - setup_remote_tmp_dir diff --git a/test/integration/targets/mongodb_shard/tasks/main.yml b/test/integration/targets/mongodb_shard/tasks/main.yml new file mode 100644 index 00000000000..53f9b2d2224 --- /dev/null +++ b/test/integration/targets/mongodb_shard/tasks/main.yml @@ -0,0 +1,458 @@ +# test code for the mongodb_shard module +# (c) 2019, Rhys Campbell + +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +# ============================================================ + +- name: Ensure tests home exists + file: + path: "{{ remote_tmp_dir }}/tests" + state: directory + +- include_tasks: mongod_teardown.yml + +- set_fact: + current_replicaset: "{{ mongodb_replicaset1 }}" + +- set_fact: + mongodb_nodes: [ 3001, 3002, 3003 ] + +- include_tasks: mongod_replicaset.yml + +- set_fact: + current_replicaset: "{{ mongodb_replicaset2 }}" + +- set_fact: + mongodb_nodes: [ 3004, 3005, 3006 ] + +- include_tasks: mongod_replicaset.yml + +- name: Launch cfg server + command: mongod --configsvr --port 4000 --dbpath {{ remote_tmp_dir }}/config --logpath {{ remote_tmp_dir }}/config.log --smallfiles --replSet "{{ configsrv_replicaset }}" --fork + +- name: Create replicaset1 with module + mongodb_replicaset: + login_user: admin + login_password: secret + login_host: "localhost" + login_port: 3001 + login_database: "admin" + replica_set: "{{ mongodb_replicaset1 }}" + members: + - "localhost:3001" + - "localhost:3002" + - "localhost:3003" + +- name: Create replicaset2 with module + mongodb_replicaset: + login_user: admin + login_password: secret + login_host: "localhost" + login_port: 3004 + login_database: "admin" + replica_set: "{{ mongodb_replicaset2 }}" + members: + - "localhost:3004" + - "localhost:3005" + - "localhost:3006" + +- name: Create config srv replicaset with module + mongodb_replicaset: + login_user: admin + login_password: secret + login_host: "localhost" + login_port: 4000 + login_database: "admin" + replica_set: "{{ configsrv_replicaset }}" + validate: no + members: + - "localhost:4000" + +- name: Get config server replset mongo_output + command: mongo admin --port 4000 --eval "rs.status();" + register: cfg_replset_output + +- name: Assert that replset is a config server + assert: + that: + - "'\"configsvr\" : true' in cfg_replset_output.stdout" + - "'\"set\" : \"{{ configsrv_replicaset }}\"' in cfg_replset_output.stdout" + +- name: Launch mongos + command: mongos --configdb "{{ configsrv_replicaset }}/localhost:4000" --logpath "{{ remote_tmp_dir }}/tests/mongos.log" --port 27017 --fork + +- name: Ensure is_primary script exists on host + copy: + src: js/is_primary.js + dest: "{{ remote_tmp_dir }}/tests/is_primary.js" + +- name: Ensure host reaches primary before proceeding 3001 + command: mongo admin --port 3001 "{{ remote_tmp_dir }}/tests/is_primary.js" + +- name: Ensure host reaches primary before proceeding 3004 + command: mongo admin --port 3004 "{{ remote_tmp_dir }}/tests/is_primary.js" + +- name: Add shard 1 + mongodb_shard: + login_user: admin + login_password: admin + shard: "{{ mongodb_replicaset1 }}/localhost:3001" + state: present + +- name: Add shard 2 + mongodb_shard: + login_user: admin + login_password: admin + shard: "{{ mongodb_replicaset2 }}/localhost:3004" + state: present + +- name: Get replicaset info + command: mongo admin --eval "sh.status()" --port 27017 + register: mongo_output + +- name: Assert shard name is in mongo_output + assert: + that: + - "mongo_output.changed == true" + - "'{{ mongodb_replicaset1 }}/localhost:3001,localhost:3002,localhost:3003' in mongo_output.stdout" + - "'{{ mongodb_replicaset2 }}/localhost:3004,localhost:3005,localhost:3006' in mongo_output.stdout" + - "'balancer' in mongo_output.stdout" + +- name: Remove shard 2 + mongodb_shard: + login_user: admin + login_password: admin + shard: "{{ mongodb_replicaset2 }}" + state: absent + +- name: Get replicaset info + command: mongo admin --eval "sh.status()" --port 27017 + register: mongo_output + +- name: Assert shard 2 is draining + assert: + that: + - "mongo_output.changed == true" + - "'{{ mongodb_replicaset1 }}/localhost:3001,localhost:3002,localhost:3003' in mongo_output.stdout" + - "'\"draining\" : true' in mongo_output.stdout" + - "'balancer' in mongo_output.stdout" + +- name: Run remove command again to finalize shard removal + mongodb_shard: + login_user: admin + login_password: admin + shard: "{{ mongodb_replicaset2 }}" + state: absent + +- name: Get replicaset info + command: mongo admin --eval "sh.status()" --port 27017 + register: mongo_output + +- name: Assert shard 2 is not present + assert: + that: + - "mongo_output.changed == true" + - "'{{ mongodb_replicaset1 }}/localhost:3001,localhost:3002,localhost:3003' in mongo_output.stdout" + - "'{{ mongodb_replicaset2 }}/localhost:3004,localhost:3005,localhost:3006' not in mongo_output.stdout" + - "'balancer' in mongo_output.stdout" + +# Repeat of above with auth enabled +- include_tasks: mongod_teardown.yml + +- set_fact: + current_replicaset: "{{ mongodb_replicaset1 }}" + +- set_fact: + mongodb_nodes: [ 3001, 3002, 3003 ] + +- include_tasks: mongod_replicaset.yml + +- set_fact: + current_replicaset: "{{ mongodb_replicaset2 }}" + +- set_fact: + mongodb_nodes: [ 3004, 3005, 3006 ] + +- include_tasks: mongod_replicaset.yml + +- name: Create replicaset1 with module + mongodb_replicaset: + login_user: admin + login_password: secret + login_host: "localhost" + login_port: 3001 + login_database: "admin" + replica_set: "{{ mongodb_replicaset1 }}" + members: + - "localhost:3001" + - "localhost:3002" + - "localhost:3003" + +- name: Create replicaset2 with module + mongodb_replicaset: + login_user: admin + login_password: secret + login_host: "localhost" + login_port: 3004 + login_database: "admin" + replica_set: "{{ mongodb_replicaset2 }}" + members: + - "localhost:3004" + - "localhost:3005" + - "localhost:3006" + +- name: Launch cfg server + command: mongod --configsvr --port 4000 --dbpath {{ remote_tmp_dir }}/config --logpath {{ remote_tmp_dir }}/config.log --smallfiles --replSet "{{ configsrv_replicaset }}" --fork + +- name: Create config srv replicaset with module + mongodb_replicaset: + login_user: "{{ mongodb_admin_user }}" + login_password: "{{ mongodb_admin_password }}" + login_port: 4000 + login_database: "admin" + replica_set: "{{ configsrv_replicaset }}" + validate: no + members: + - "localhost:4000" + +- name: Ensure host reaches primary before proceeding 3001 + command: mongo admin --port 3001 "{{ remote_tmp_dir }}/tests/is_primary.js" + +- name: Ensure host reaches primary before proceeding 3004 + command: mongo admin --port 3004 "{{ remote_tmp_dir }}/tests/is_primary.js" + +- name: Ensure host reaches primary before proceeding 4000 + command: mongo admin --port 4000 "{{ remote_tmp_dir }}/tests/is_primary.js" + +- name: Add mongodb admin user to each shard 3.4+ + mongodb_user: + login_host: localhost + login_port: "{{ item.port }}" + replica_set: "{{ item.rs }}" + database: admin + name: "{{ mongodb_admin_user }}" + password: "{{ mongodb_admin_password }}" + roles: ["root"] + state: present + register: mongo_admin_user + with_items: + - { "port": 3001, "rs": "{{ mongodb_replicaset1 }}" } + - { "port": 3004, "rs": "{{ mongodb_replicaset2 }}" } + - { "port": 4000, "rs": "{{ configsrv_replicaset }}" } + when: mongodb_version not in ["3.2", "4.0"] and test_mongo_auth == True + +- name: Add mongodb admin user to each shard 3.2 ^ 4.0 + mongodb_user: + login_host: localhost + login_port: "{{ item.port }}" + replica_set: "{{ item.rs }}" + database: admin + name: "{{ mongodb_admin_user }}" + password: "{{ mongodb_admin_password }}" + roles: ["root"] + state: present + register: mongo_admin_user + with_items: + - { "port": 3001, "rs": "{{ mongodb_replicaset1 }}" } + - { "port": 3004, "rs": "{{ mongodb_replicaset2 }}" } + when: mongodb_version not in ["3.2", "4.0"] and test_mongo_auth == True + +# mongodb_user throws an error when creating a user on 3.2 (also on 4.0 with Ubuntu 18.04) +# 'majority' is the only valid write concern when writing to config server replica sets +- name: Copy create_user_root_3.2.js.j2 template to host + template: + src: create_user_root_3.2.js.j2 + dest: /root/create_user_root_3.2.js + when: mongodb_version in ["3.2", "4.0"] + +- name: Copy script to host + template: + src: files/bash/ensure_primary.sh.j2 + dest: /root/ensure_primary.sh + +- name: Execute script for 3001 + script: /root/ensure_primary.sh 3001 0 +# We do this here because sometimes 3004 instance seems to be demoted +- name: Execute script for 3004 + script: /root/ensure_primary.sh 3004 0 + +- name: Create admin user on 3.2 and 4.0 config replset + shell: mongo admin --port {{ item }} /root/create_user_root_3.2.js + with_items: + - 4000 + - 3001 + - 3004 + when: mongodb_version in ["3.2", "4.0"] + +- name: Murder all mongod processes + shell: pkill -{{ kill_signal }} mongod || true; + +- name: Getting pids for mongod + pids: + name: mongod + register: pids_of_mongod + +- name: Wait for all mongod processes to exit + wait_for: + path: "/proc/{{ item }}/status" + state: absent + with_items: "{{ pids_of_mongod }}" + +- set_fact: + current_replicaset: "{{ mongodb_replicaset1 }}" + +- set_fact: + mongodb_nodes: [ 3001, 3002, 3003 ] + +- set_fact: + mongod_auth: true + +- include_tasks: mongod_replicaset.yml + +- set_fact: + current_replicaset: "{{ mongodb_replicaset2 }}" + +- set_fact: + mongodb_nodes: [ 3004, 3005, 3006 ] + +- set_fact: + mongod_auth: true + +- include_tasks: mongod_replicaset.yml + +- name: Launch cfg server with auth + command: mongod --configsvr --port 4000 --dbpath {{ remote_tmp_dir }}/config --logpath {{ remote_tmp_dir }}/config.log --smallfiles --replSet "{{ configsrv_replicaset }}" --fork --auth --keyFile {{ remote_tmp_dir }}/my.key + +- name: Execute script for 3001 + script: /root/ensure_primary.sh 3001 1 + +- name: Execute script for 3004 + script: /root/ensure_primary.sh 3004 1 + +- name: Ensure host reaches primary before proceeding 3001 + command: mongo admin --port 3001 -u {{ mongodb_admin_user }} -p {{ mongodb_admin_password }} "{{ remote_tmp_dir }}/tests/is_primary.js" + +- name: Ensure host reaches primary before proceeding 3004 + command: mongo admin --port 3004 -u {{ mongodb_admin_user }} -p {{ mongodb_admin_password }} "{{ remote_tmp_dir }}/tests/is_primary.js" + +- name: Launch mongos + command: mongos --configdb "{{ configsrv_replicaset }}/localhost:4000" --logpath "{{ remote_tmp_dir }}/mongos.log" --port 27017 --fork --keyFile {{ remote_tmp_dir }}/my.key + +- name: Wait for mongos to become active + wait_for: + host: localhost + port: 4000 + delay: 1 + +- name: Add shard 1 + mongodb_shard: + login_user: "{{ mongodb_admin_user }}" + login_password: "{{ mongodb_admin_password }}" + shard: "{{ mongodb_replicaset1 }}/localhost:3001" + state: present + +- name: Add shard 2 + mongodb_shard: + login_user: "{{ mongodb_admin_user }}" + login_password: "{{ mongodb_admin_password }}" + shard: "{{ mongodb_replicaset2 }}/localhost:3004" + state: present + +- name: Test with bad password + mongodb_shard: + login_user: "{{ mongodb_admin_user }}" + login_password: XXXXXXXXXXXX + shard: "{{ mongodb_replicaset2 }}/localhost:3004" + state: present + register: mongodb_shard_bad_pw + ignore_errors: True + +- name: Assert login failed + assert: + that: + - "mongodb_shard_bad_pw.changed == False" + - "'unable to connect to database: Authentication failed.' == mongodb_shard_bad_pw.msg" + +- name: Get replicaset info + command: mongo admin --eval "sh.status()" --port 27017 -u "{{ mongodb_admin_user }}" -p "{{ mongodb_admin_password }}" + register: mongo_output + +- name: Assert shard name is in mongo_output + assert: + that: + - "mongo_output.changed == true" + - "'{{ mongodb_replicaset1 }}/localhost:3001,localhost:3002,localhost:3003' in mongo_output.stdout" + - "'{{ mongodb_replicaset2 }}/localhost:3004,localhost:3005,localhost:3006' in mongo_output.stdout" + - "'balancer' in mongo_output.stdout" + +- name: Remove shard 2 + mongodb_shard: + login_user: "{{ mongodb_admin_user }}" + login_password: "{{ mongodb_admin_password }}" + shard: "{{ mongodb_replicaset2 }}" + state: absent + +- name: Get replicaset info + command: mongo admin --eval "sh.status()" --port 27017 -u "{{ mongodb_admin_user }}" -p "{{ mongodb_admin_password }}" + register: mongo_output + +- name: Assert shard 2 is draining + assert: + that: + - "mongo_output.changed == true" + - "'{{ mongodb_replicaset1 }}/localhost:3001,localhost:3002,localhost:3003' in mongo_output.stdout" + - "'\"draining\" : true' in mongo_output.stdout" + - "'balancer' in mongo_output.stdout" + +- name: Run remove command again to finalize shard removal + mongodb_shard: + login_user: "{{ mongodb_admin_user }}" + login_password: "{{ mongodb_admin_password }}" + shard: "{{ mongodb_replicaset2 }}" + state: absent + +- name: Get replicaset info + command: mongo admin --eval "sh.status()" --port 27017 -u "{{ mongodb_admin_user }}" -p "{{ mongodb_admin_password }}" + register: mongo_output + +- name: Assert shard 2 is not present + assert: + that: + - "mongo_output.changed == true" + - "'{{ mongodb_replicaset1 }}/localhost:3001,localhost:3002,localhost:3003' in mongo_output.stdout" + - "'{{ mongodb_replicaset2 }}/localhost:3004,localhost:3005,localhost:3006' not in mongo_output.stdout" + - "'balancer' in mongo_output.stdout" + +# TODO - Readd this test once we support serverSelectionTimeoutMS / connectTimeoutMS +#- name: Run test with unknown host +# mongodb_shard: +# login_user: "{{ mongodb_admin_user }}" +# login_password: "{{ mongodb_admin_password }}" +# login_host: "idonotexist" +# shard: "{{ mongodb_replicaset2 }}" +# state: absent +# ignore_errors: True +# register: host_does_not_exist + +#- name: Assert that "Name or service not known" is in error +# assert: +# that: +# - "host_does_not_exist.changed == False" +# - "'unable to connect to database: idonotexist:27017: [Errno -2] Name or service not known' == host_does_not_exist.msg" + +# Final clean up to prevent "directory not empty" error +- include_tasks: mongod_teardown.yml diff --git a/test/integration/targets/mongodb_shard/tasks/mongod_replicaset.yml b/test/integration/targets/mongodb_shard/tasks/mongod_replicaset.yml new file mode 100644 index 00000000000..fe1c2ffe626 --- /dev/null +++ b/test/integration/targets/mongodb_shard/tasks/mongod_replicaset.yml @@ -0,0 +1,51 @@ +- name: Set mongodb_user user for redhat + set_fact: + mongodb_user: "mongod" + when: ansible_os_family == "RedHat" + +- name: Create directories for mongod processes + file: + path: "{{ remote_tmp_dir }}/mongod{{ item }}" + state: directory + owner: "{{ mongodb_user }}" + group: "{{ mongodb_user }}" + mode: 0755 + recurse: yes + with_items: "{{ mongodb_nodes }}" + +- name: Ensure {{ remote_tmp_dir }}/config dir exists + file: + path: "{{ remote_tmp_dir }}/config" + state: directory + owner: "{{ mongodb_user }}" + group: "{{ mongodb_user }}" + mode: 0755 + +- name: Create keyfile + copy: + dest: "{{ remote_tmp_dir }}/my.key" + content: | + fd2CUrbXBJpB4rt74A6F + owner: "{{ mongodb_user }}" + group: "{{ mongodb_user }}" + mode: 0600 + when: mongod_auth == True + +- name: Spawn mongod process without auth + command: mongod --shardsvr --smallfiles {{ mongod_storage_engine_opts }} --dbpath mongod{{ item }} --port {{ item }} --replSet {{ current_replicaset }} --logpath mongod{{ item }}/log.log --fork + args: + chdir: "{{ remote_tmp_dir }}" + with_items: "{{ mongodb_nodes | sort }}" + when: mongod_auth == False + +- name: Spawn mongod process with auth + command: mongod --shardsvr --smallfiles {{ mongod_storage_engine_opts }} --dbpath mongod{{ item }} --port {{ item }} --replSet {{ current_replicaset }} --logpath mongod{{ item }}/log.log --fork --auth --keyFile my.key + args: + chdir: "{{ remote_tmp_dir }}" + with_items: "{{ mongodb_nodes | sort }}" + when: mongod_auth == True + +- name: Wait for mongod to start responding + wait_for: + port: "{{ item }}" + with_items: "{{ mongodb_nodes }}" diff --git a/test/integration/targets/mongodb_shard/tasks/mongod_teardown.yml b/test/integration/targets/mongodb_shard/tasks/mongod_teardown.yml new file mode 100644 index 00000000000..3af09d59be6 --- /dev/null +++ b/test/integration/targets/mongodb_shard/tasks/mongod_teardown.yml @@ -0,0 +1,35 @@ +- name: Kill all mongod processes + command: pkill -{{ kill_signal }} mongod + ignore_errors: true + +- name: Kill all mongos processes + command: pkill -{{ kill_signal }} mongos + ignore_errors: true + +- name: Getting pids for mongod + pids: + name: mongod + register: pids_of_mongod + +- name: Wait for all mongod processes to exit + wait_for: + path: "/proc/{{ item }}/status" + state: absent + delay: 1 + with_items: "{{ pids_of_mongod }}" + +- name: Remove all mongod folders + file: + path: "{{ remote_tmp_dir }}/{{ item }}" + state: absent + with_items: + - mongod3001 + - mongod3002 + - mongod3003 + - mongod3004 + - mongod3005 + - mongod3006 + - config + +- name: Remove all mongod sock files + shell: rm -Rf /tmp/mongodb*.sock diff --git a/test/integration/targets/mongodb_shard/templates/create_user_root_3.2.js.j2 b/test/integration/targets/mongodb_shard/templates/create_user_root_3.2.js.j2 new file mode 100644 index 00000000000..368cb966bf6 --- /dev/null +++ b/test/integration/targets/mongodb_shard/templates/create_user_root_3.2.js.j2 @@ -0,0 +1,8 @@ +db.createUser( + { + user: "{{ mongodb_admin_user }}", + pwd: "{{ mongodb_admin_password }}", + roles: [ { role: "root", db: "admin" } ] + }, + { w: "majority", j: true, wtimeout: 10000 } +) diff --git a/test/integration/targets/setup_mongodb/defaults/main.yml b/test/integration/targets/setup_mongodb/defaults/main.yml new file mode 100644 index 00000000000..ee3e822f413 --- /dev/null +++ b/test/integration/targets/setup_mongodb/defaults/main.yml @@ -0,0 +1,50 @@ +mongodb_version: "4.0" + +apt_xenial: + keyserver: "keyserver.ubuntu.com" + keyserver_id: "2930ADAE8CAF5059EE73BB4B58712A2291FA4AD5" + repo: "deb [ arch=amd64 ] http://repo.mongodb.org/apt/ubuntu {{ansible_distribution_release}}/mongodb-org/{{mongodb_version}} multiverse" + +apt_bionic: + keyserver: "keyserver.ubuntu.com" + keyserver_id: "9DA31620334BD75D9DCB49F368818C72E52529D4" + repo: "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu {{ansible_distribution_release}}/mongodb-org/{{mongodb_version}} multiverse" + +mongodb_packages: + mongod: mongodb-org-server + mongos: mongodb-org-mongos + mongo: mongodb-org-shell + +yum: + name: mongodb-org + description: "Official MongoDB {{mongodb_version}} yum repo" + baseurl: https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/{{mongodb_version}}/x86_64/ + gpgcheck: 1 + gpgkey: https://www.mongodb.org/static/pgp/server-{{mongodb_version}}.asc + redhat8url: https://repo.mongodb.org/yum/redhat/7/mongodb-org/{{mongodb_version}}/x86_64/ + fedoraurl: https://repo.mongodb.org/yum/amazon/2013.03/mongodb-org/{{mongodb_version}}/x86_64/ + +debian_packages_py2: + - python-dev + - python-setuptools + - python-pip + +debian_packages_py36: + - python3.6-dev + - python3-setuptools + - python3-pip + +redhat_packages_py2: + - python-devel + - python-setuptools + - python-pip + +redhat_packages_py3: + - python3-devel + - python3-setuptools + - python3-pip + +pip_packages: + - psutil + - requests[security] + - pymongo diff --git a/test/integration/targets/setup_mongodb/handlers/main.yml b/test/integration/targets/setup_mongodb/handlers/main.yml new file mode 100644 index 00000000000..af1b8f4baa8 --- /dev/null +++ b/test/integration/targets/setup_mongodb/handlers/main.yml @@ -0,0 +1,19 @@ +- name: Remove debian_packages_py2 + apt: + name: "{{ debian_packages_py2 }}" + state: absent + +- name: Remove debian_packages_py36 + apt: + name: "{{ debian_packages_py36 }}" + state: absent + +- name: Remove redhat_packages_py2 + yum: + name: "{{ redhat_packages_py36 }}" + state: absent + +- name: Remove redhat_packages_py36 + yum: + name: "{{ redhat_packages_py36 }}" + state: absent diff --git a/test/integration/targets/setup_mongodb/tasks/main.yml b/test/integration/targets/setup_mongodb/tasks/main.yml new file mode 100644 index 00000000000..4477762f721 --- /dev/null +++ b/test/integration/targets/setup_mongodb/tasks/main.yml @@ -0,0 +1,186 @@ +# (c) 2019, Rhys Campbell + +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +# ============================================================ + +# https://docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu/ +# Support for Ubuntu 14.04 has been removed from MongoDB 4.0.10+, 3.6.13+, and 3.4.21+. +# CentOS6 has python version issues +- meta: end_play + when: (ansible_distribution == 'Ubuntu' and ansible_distribution_version == '14.04') + or (ansible_os_family == "RedHat" and ansible_distribution_major_version == '6') + or ansible_os_family == "Suse" + or ansible_distribution == 'Fedora' + or (ansible_distribution == 'CentOS' and ansible_distribution_version == '7') + +# Ubuntu +- name: Import MongoDB public GPG Key xenial + apt_key: + keyserver: "{{ apt_xenial.keyserver }}" + id: "{{ apt_xenial.keyserver_id }}" + when: + - ansible_distribution_version == "16.04" + - ansible_distribution == 'Ubuntu' + +- name: Add MongoDB repository into sources list xenial + apt_repository: + repo: "{{ apt_xenial.repo }}" + state: present + when: + - ansible_distribution_version == "16.04" + - ansible_distribution == 'Ubuntu' + +- name: Import MongoDB public GPG Key bionic + apt_key: + keyserver: "{{ apt_bionic.keyserver }}" + id: "{{ apt_bionic.keyserver_id }}" + when: + - ansible_distribution_version == "18.04" + - ansible_distribution == 'Ubuntu' + +- name: Add MongoDB repository into sources list bionic + apt_repository: + repo: "{{ apt_bionic.repo }}" + state: present + when: + - ansible_distribution_version == "18.04" + - ansible_distribution == 'Ubuntu' + +- name: Update apt keys + shell: apt-key update && apt-get update + when: + - mongodb_version != "4.0" + - ansible_distribution == 'Ubuntu' + +# Need to handle various platforms here. Package name will not always be the same +- name: Ensure mongod package is installed + apt: + name: "{{ mongodb_packages.mongod }}" + state: present + force: yes + when: + - ansible_distribution == 'Ubuntu' + +- name: Ensure mongos package is installed + apt: + name: "{{ mongodb_packages.mongos }}" + state: present + force: yes + when: + - ansible_distribution == 'Ubuntu' + +- name: Ensure mongo client is installed + apt: + name: "{{ mongodb_packages.mongo }}" + state: present + force: yes + when: + - ansible_distribution == 'Ubuntu' +# EOF Ubuntu + +# Redhat +- name: Add MongopDB repo + yum_repository: + name: "{{ yum.name }}" + description: "{{ yum.description }}" + baseurl: "{{ yum.baseurl }}" + gpgcheck: "{{ yum.gpgcheck }}" + gpgkey: "{{ yum.gpgkey }}" + when: + - ansible_os_family == "RedHat" + - ansible_distribution_version.split('.')[0]|int <= 7 + - not ansible_distribution == "Fedora" + + +- name: RedHat 8 repo not yet available so use 7 url + yum_repository: + name: "{{ yum.name }}" + description: "{{ yum.description }}" + baseurl: "{{ yum.redhat8url }}" + gpgcheck: "{{ yum.gpgcheck }}" + gpgkey: "{{ yum.gpgkey }}" + when: + - ansible_os_family == "RedHat" + - ansible_distribution_version.split('.')[0]|int == 8 + - not ansible_distribution == "Fedora" + +- name: Another url for Fedora based systems + yum_repository: + name: "{{ yum.name }}" + description: "{{ yum.description }}" + baseurl: "{{ yum.fedoraurl }}" + gpgcheck: "{{ yum.gpgcheck }}" + gpgkey: "{{ yum.gpgkey }}" + when: + - ansible_distribution == "Fedora" + +- name: Ensure mongod package is installed + yum: + name: "{{ mongodb_packages.mongod }}" + state: present + when: ansible_os_family == "RedHat" + +- name: Ensure mongos package is installed + yum: + name: "{{ mongodb_packages.mongos }}" + state: present + when: ansible_os_family == "RedHat" + +- name: Ensure mongo client is installed + yum: + name: "{{ mongodb_packages.mongo }}" + state: present + when: ansible_os_family == "RedHat" +# EOF Redhat + +- name: Install debian_packages + apt: + name: "{{ debian_packages_py2 }}" + when: + - ansible_os_family == "Debian" + - ansible_distribution_version == "16.04" + notify: Remove debian_packages_py2 + +- name: Install debian_packages + apt: + name: "{{ debian_packages_py36 }}" + when: + - ansible_os_family == "Debian" + - ansible_distribution_version == "18.04" + notify: Remove debian_packages_py36 + +- name: Install redhat_packages_py2 + yum: + name: "{{ redhat_packages_py2 }}" + when: + - ansible_os_family == "RedHat" + - ansible_distribution_version|float < 8 + - not (ansible_os_family == "RedHat" and ansible_distribution_version|float < 8) + notify: Remove redhat_packages_py2 + +- name: Install redhat_packages_py3 + yum: + name: "{{ redhat_packages_py3 }}" + when: + - ansible_os_family == "RedHat" + - ansible_distribution_version|float >= 8 + notify: Remove redhat_packages_py3 + +- name: Install pip packages + pip: + name: "{{ pip_packages }}" + state: present