1# test code for the mongodb_shard module 2# (c) 2019, Rhys Campbell <rhys.james.campbell@googlemail.com> 3 4# This file is part of Ansible 5# 6# Ansible is free software: you can redistribute it and/or modify 7# it under the terms of the GNU General Public License as published by 8# the Free Software Foundation, either version 3 of the License, or 9# (at your option) any later version. 10# 11# Ansible is distributed in the hope that it will be useful, 12# but WITHOUT ANY WARRANTY; without even the implied warranty of 13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14# GNU General Public License for more details. 15# 16# You should have received a copy of the GNU General Public License 17# along with Ansible. If not, see <http://www.gnu.org/licenses/>. 18 19# ============================================================ 20 21- name: Ensure tests home exists 22 file: 23 path: "{{ remote_tmp_dir }}/tests" 24 state: directory 25 26- include_tasks: mongod_teardown.yml 27 28- set_fact: 29 current_replicaset: "{{ mongodb_replicaset1 }}" 30 31- set_fact: 32 mongodb_nodes: [ 3001, 3002, 3003 ] 33 34- include_tasks: mongod_replicaset.yml 35 36- set_fact: 37 current_replicaset: "{{ mongodb_replicaset2 }}" 38 39- set_fact: 40 mongodb_nodes: [ 3004, 3005, 3006 ] 41 42- include_tasks: mongod_replicaset.yml 43 44- name: Launch cfg server 45 command: mongod --configsvr --port 4000 --dbpath {{ remote_tmp_dir }}/config --logpath {{ remote_tmp_dir }}/config.log --smallfiles --replSet "{{ configsrv_replicaset }}" --fork 46 47- name: Create replicaset1 with module 48 mongodb_replicaset: 49 login_host: "localhost" 50 login_port: 3001 51 login_database: "admin" 52 replica_set: "{{ mongodb_replicaset1 }}" 53 members: 54 - "localhost:3001" 55 - "localhost:3002" 56 - "localhost:3003" 57 58- name: Create replicaset2 with module 59 mongodb_replicaset: 60 login_host: "localhost" 61 login_port: 3004 62 login_database: "admin" 63 replica_set: "{{ mongodb_replicaset2 }}" 64 members: 65 - "localhost:3004" 66 - "localhost:3005" 67 - "localhost:3006" 68 69- name: Create config srv replicaset with module 70 mongodb_replicaset: 71 login_host: "localhost" 72 login_port: 4000 73 login_database: "admin" 74 replica_set: "{{ configsrv_replicaset }}" 75 validate: no 76 members: 77 - "localhost:4000" 78 79- name: Get config server replset mongo_output 80 command: mongo admin --port 4000 --eval "rs.status();" 81 register: cfg_replset_output 82 83- name: Assert that replset is a config server 84 assert: 85 that: 86 - "'\"configsvr\" : true' in cfg_replset_output.stdout" 87 - "'\"set\" : \"{{ configsrv_replicaset }}\"' in cfg_replset_output.stdout" 88 89- name: Launch mongos 90 command: mongos --configdb "{{ configsrv_replicaset }}/localhost:4000" --logpath "{{ remote_tmp_dir }}/tests/mongos.log" --port 27017 --fork 91 92- name: Ensure is_primary script exists on host 93 copy: 94 src: js/is_primary.js 95 dest: "{{ remote_tmp_dir }}/tests/is_primary.js" 96 97- name: Ensure host reaches primary before proceeding 3001 98 command: mongo admin --port 3001 "{{ remote_tmp_dir }}/tests/is_primary.js" 99 100- name: Ensure host reaches primary before proceeding 3004 101 command: mongo admin --port 3004 "{{ remote_tmp_dir }}/tests/is_primary.js" 102 103- name: Add shard 1 104 mongodb_shard: 105 login_user: admin 106 login_password: admin 107 shard: "{{ mongodb_replicaset1 }}/localhost:3001" 108 state: present 109 110- name: Add shard 2 111 mongodb_shard: 112 login_user: admin 113 login_password: admin 114 shard: "{{ mongodb_replicaset2 }}/localhost:3004" 115 state: present 116 117- name: Get replicaset info 118 command: mongo admin --eval "sh.status()" --port 27017 119 register: mongo_output 120 121- name: Assert shard name is in mongo_output 122 assert: 123 that: 124 - "mongo_output.changed == true" 125 - "'{{ mongodb_replicaset1 }}/localhost:3001,localhost:3002,localhost:3003' in mongo_output.stdout" 126 - "'{{ mongodb_replicaset2 }}/localhost:3004,localhost:3005,localhost:3006' in mongo_output.stdout" 127 - "'balancer' in mongo_output.stdout" 128 129- name: Remove shard 2 130 mongodb_shard: 131 login_user: admin 132 login_password: admin 133 shard: "{{ mongodb_replicaset2 }}" 134 state: absent 135 136- name: Get replicaset info 137 command: mongo admin --eval "sh.status()" --port 27017 138 register: mongo_output 139 140- name: Assert shard 2 is draining 141 assert: 142 that: 143 - "mongo_output.changed == true" 144 - "'{{ mongodb_replicaset1 }}/localhost:3001,localhost:3002,localhost:3003' in mongo_output.stdout" 145 - "'\"draining\" : true' in mongo_output.stdout" 146 - "'balancer' in mongo_output.stdout" 147 148- name: Run remove command again to finalize shard removal 149 mongodb_shard: 150 login_user: admin 151 login_password: admin 152 shard: "{{ mongodb_replicaset2 }}" 153 state: absent 154 155- name: Get replicaset info 156 command: mongo admin --eval "sh.status()" --port 27017 157 register: mongo_output 158 159- name: Assert shard 2 is not present 160 assert: 161 that: 162 - "mongo_output.changed == true" 163 - "'{{ mongodb_replicaset1 }}/localhost:3001,localhost:3002,localhost:3003' in mongo_output.stdout" 164 - "'{{ mongodb_replicaset2 }}/localhost:3004,localhost:3005,localhost:3006' not in mongo_output.stdout" 165 - "'balancer' in mongo_output.stdout" 166 167# Repeat of above with auth enabled 168- include_tasks: mongod_teardown.yml 169 170- set_fact: 171 current_replicaset: "{{ mongodb_replicaset1 }}" 172 173- set_fact: 174 mongodb_nodes: [ 3001, 3002, 3003 ] 175 176- include_tasks: mongod_replicaset.yml 177 178- set_fact: 179 current_replicaset: "{{ mongodb_replicaset2 }}" 180 181- set_fact: 182 mongodb_nodes: [ 3004, 3005, 3006 ] 183 184- include_tasks: mongod_replicaset.yml 185 186- name: Create replicaset1 with module 187 mongodb_replicaset: 188 login_host: "localhost" 189 login_port: 3001 190 login_database: "admin" 191 replica_set: "{{ mongodb_replicaset1 }}" 192 members: 193 - "localhost:3001" 194 - "localhost:3002" 195 - "localhost:3003" 196 197- name: Create replicaset2 with module 198 mongodb_replicaset: 199 login_host: "localhost" 200 login_port: 3004 201 login_database: "admin" 202 replica_set: "{{ mongodb_replicaset2 }}" 203 members: 204 - "localhost:3004" 205 - "localhost:3005" 206 - "localhost:3006" 207 208- name: Launch cfg server 209 command: mongod --configsvr --port 4000 --dbpath {{ remote_tmp_dir }}/config --logpath {{ remote_tmp_dir }}/config.log --smallfiles --replSet "{{ configsrv_replicaset }}" --fork 210 211- name: Create config srv replicaset with module 212 mongodb_replicaset: 213 login_port: 4000 214 login_database: "admin" 215 replica_set: "{{ configsrv_replicaset }}" 216 validate: no 217 members: 218 - "localhost:4000" 219 220- name: Ensure host reaches primary before proceeding 3001 221 command: mongo admin --port 3001 "{{ remote_tmp_dir }}/tests/is_primary.js" 222 223- name: Ensure host reaches primary before proceeding 3004 224 command: mongo admin --port 3004 "{{ remote_tmp_dir }}/tests/is_primary.js" 225 226- name: Ensure host reaches primary before proceeding 4000 227 command: mongo admin --port 4000 "{{ remote_tmp_dir }}/tests/is_primary.js" 228 229- name: Add mongodb admin user to each shard 3.4+ 230 mongodb_user: 231 login_host: localhost 232 login_port: "{{ item.port }}" 233 replica_set: "{{ item.rs }}" 234 database: admin 235 name: "{{ mongodb_admin_user }}" 236 password: "{{ mongodb_admin_password }}" 237 roles: ["root"] 238 state: present 239 register: mongo_admin_user 240 with_items: 241 - { "port": 3001, "rs": "{{ mongodb_replicaset1 }}" } 242 - { "port": 3004, "rs": "{{ mongodb_replicaset2 }}" } 243 - { "port": 4000, "rs": "{{ configsrv_replicaset }}" } 244 when: mongodb_version not in ["3.2", "4.0"] and test_mongo_auth == True 245 246- name: Add mongodb admin user to each shard 3.2 ^ 4.0 247 mongodb_user: 248 login_host: localhost 249 login_port: "{{ item.port }}" 250 replica_set: "{{ item.rs }}" 251 database: admin 252 name: "{{ mongodb_admin_user }}" 253 password: "{{ mongodb_admin_password }}" 254 roles: ["root"] 255 state: present 256 register: mongo_admin_user 257 with_items: 258 - { "port": 3001, "rs": "{{ mongodb_replicaset1 }}" } 259 - { "port": 3004, "rs": "{{ mongodb_replicaset2 }}" } 260 when: mongodb_version not in ["3.2", "4.0"] and test_mongo_auth == True 261 262# mongodb_user throws an error when creating a user on 3.2 (also on 4.0 with Ubuntu 18.04) 263# 'majority' is the only valid write concern when writing to config server replica sets 264- name: Copy create_user_root_3.2.js.j2 template to host 265 template: 266 src: create_user_root_3.2.js.j2 267 dest: /root/create_user_root_3.2.js 268 when: mongodb_version in ["3.2", "4.0"] 269 270- name: Copy script to host 271 template: 272 src: files/bash/ensure_primary.sh.j2 273 dest: /root/ensure_primary.sh 274 275- name: Execute script for 3001 276 script: /root/ensure_primary.sh 3001 0 277# We do this here because sometimes 3004 instance seems to be demoted 278- name: Execute script for 3004 279 script: /root/ensure_primary.sh 3004 0 280 281- name: Create admin user on 3.2 and 4.0 config replset 282 shell: mongo admin --port {{ item }} /root/create_user_root_3.2.js 283 with_items: 284 - 4000 285 - 3001 286 - 3004 287 when: mongodb_version in ["3.2", "4.0"] 288 289- name: Murder all mongod processes 290 shell: pkill -{{ kill_signal }} mongod || true; 291 292- name: Wait for ports to get out of TIME_WAIT 293 wait_for: 294 port: '{{ item }}' 295 state: drained 296 with_sequence: start=3001 end=3006 297 298- set_fact: 299 current_replicaset: "{{ mongodb_replicaset1 }}" 300 301- set_fact: 302 mongodb_nodes: [ 3001, 3002, 3003 ] 303 304- set_fact: 305 mongod_auth: true 306 307- include_tasks: mongod_replicaset.yml 308 309- set_fact: 310 current_replicaset: "{{ mongodb_replicaset2 }}" 311 312- set_fact: 313 mongodb_nodes: [ 3004, 3005, 3006 ] 314 315- set_fact: 316 mongod_auth: true 317 318- include_tasks: mongod_replicaset.yml 319 320- name: Launch cfg server with auth 321 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 322 323- name: Execute script for 3001 324 script: /root/ensure_primary.sh 3001 1 325 326- name: Execute script for 3004 327 script: /root/ensure_primary.sh 3004 1 328 329- name: Ensure host reaches primary before proceeding 3001 330 command: mongo admin --port 3001 -u {{ mongodb_admin_user }} -p {{ mongodb_admin_password }} "{{ remote_tmp_dir }}/tests/is_primary.js" 331 332- name: Ensure host reaches primary before proceeding 3004 333 command: mongo admin --port 3004 -u {{ mongodb_admin_user }} -p {{ mongodb_admin_password }} "{{ remote_tmp_dir }}/tests/is_primary.js" 334 335- name: Launch mongos 336 command: mongos --configdb "{{ configsrv_replicaset }}/localhost:4000" --logpath "{{ remote_tmp_dir }}/mongos.log" --port 27017 --fork --keyFile {{ remote_tmp_dir }}/my.key 337 338- name: Wait for mongos to become active 339 wait_for: 340 host: localhost 341 port: 4000 342 delay: 1 343 344- name: Add shard 1 345 mongodb_shard: 346 login_user: "{{ mongodb_admin_user }}" 347 login_password: "{{ mongodb_admin_password }}" 348 shard: "{{ mongodb_replicaset1 }}/localhost:3001" 349 state: present 350 351- name: Add shard 2 352 mongodb_shard: 353 login_user: "{{ mongodb_admin_user }}" 354 login_password: "{{ mongodb_admin_password }}" 355 shard: "{{ mongodb_replicaset2 }}/localhost:3004" 356 state: present 357 358- name: Test with bad password 359 mongodb_shard: 360 login_user: "{{ mongodb_admin_user }}" 361 login_password: XXXXXXXXXXXX 362 shard: "{{ mongodb_replicaset2 }}/localhost:3004" 363 state: present 364 register: mongodb_shard_bad_pw 365 ignore_errors: True 366 367- name: Assert login failed 368 assert: 369 that: 370 - "mongodb_shard_bad_pw.changed == False" 371 - "'unable to connect to database: Authentication failed.' == mongodb_shard_bad_pw.msg" 372 373- name: Get replicaset info 374 command: mongo admin --eval "sh.status()" --port 27017 -u "{{ mongodb_admin_user }}" -p "{{ mongodb_admin_password }}" 375 register: mongo_output 376 377- name: Assert shard name is in mongo_output 378 assert: 379 that: 380 - "mongo_output.changed == true" 381 - "'{{ mongodb_replicaset1 }}/localhost:3001,localhost:3002,localhost:3003' in mongo_output.stdout" 382 - "'{{ mongodb_replicaset2 }}/localhost:3004,localhost:3005,localhost:3006' in mongo_output.stdout" 383 - "'balancer' in mongo_output.stdout" 384 385- name: Remove shard 2 386 mongodb_shard: 387 login_user: "{{ mongodb_admin_user }}" 388 login_password: "{{ mongodb_admin_password }}" 389 shard: "{{ mongodb_replicaset2 }}" 390 state: absent 391 392- name: Get replicaset info 393 command: mongo admin --eval "sh.status()" --port 27017 -u "{{ mongodb_admin_user }}" -p "{{ mongodb_admin_password }}" 394 register: mongo_output 395 396- name: Assert shard 2 is draining 397 assert: 398 that: 399 - "mongo_output.changed == true" 400 - "'{{ mongodb_replicaset1 }}/localhost:3001,localhost:3002,localhost:3003' in mongo_output.stdout" 401 - "'\"draining\" : true' in mongo_output.stdout" 402 - "'balancer' in mongo_output.stdout" 403 404- name: Run remove command again to finalize shard removal 405 mongodb_shard: 406 login_user: "{{ mongodb_admin_user }}" 407 login_password: "{{ mongodb_admin_password }}" 408 shard: "{{ mongodb_replicaset2 }}" 409 state: absent 410 411- name: Get replicaset info 412 command: mongo admin --eval "sh.status()" --port 27017 -u "{{ mongodb_admin_user }}" -p "{{ mongodb_admin_password }}" 413 register: mongo_output 414 415- name: Assert shard 2 is not present 416 assert: 417 that: 418 - "mongo_output.changed == true" 419 - "'{{ mongodb_replicaset1 }}/localhost:3001,localhost:3002,localhost:3003' in mongo_output.stdout" 420 - "'{{ mongodb_replicaset2 }}/localhost:3004,localhost:3005,localhost:3006' not in mongo_output.stdout" 421 - "'balancer' in mongo_output.stdout" 422 423# TODO - Readd this test once we support serverSelectionTimeoutMS / connectTimeoutMS 424#- name: Run test with unknown host 425# mongodb_shard: 426# login_user: "{{ mongodb_admin_user }}" 427# login_password: "{{ mongodb_admin_password }}" 428# login_host: "idonotexist" 429# shard: "{{ mongodb_replicaset2 }}" 430# state: absent 431# ignore_errors: True 432# register: host_does_not_exist 433 434#- name: Assert that "Name or service not known" is in error 435# assert: 436# that: 437# - "host_does_not_exist.changed == False" 438# - "'unable to connect to database: idonotexist:27017: [Errno -2] Name or service not known' == host_does_not_exist.msg" 439 440# Final clean up to prevent "directory not empty" error 441- include_tasks: mongod_teardown.yml 442