# test code for the mongodb_replicaset module
# (c) 2019,  Rhys Campbell <rhys.james.campbell@googlemail.com>

# 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 <http://www.gnu.org/licenses/>.

# ============================================================

- 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_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: Wait for ports to get out of TIME_WAIT
  wait_for:
    port: '{{ item }}'
    state: drained
  with_sequence: start=3001 end=3003

- 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

  #############################################################

- 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_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_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_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_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_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_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_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_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
