ansible-collections / community.mongodb

MongoDB Ansible Collection
http://galaxy.ansible.com/community/mongodb
GNU General Public License v3.0
108 stars 72 forks source link

mongodb_shard does not recognize mongos with custom process name #55

Closed dirkaholic closed 4 years ago

dirkaholic commented 4 years ago
SUMMARY

When adding a shard the module checks for the connected server being a mongos by comparing the process name returned from the serverStatus to 'mongos'. That process name can be changed by using a custom name for the mongos binary (different versions on the same server or other reasons). Therefor the module fails in that case complaining that the process running on the specified host/port is not a mongos.

See https://github.com/ansible-collections/community.mongodb/blob/master/plugins/modules/mongodb_shard.py#L478

ISSUE TYPE
COMPONENT NAME

mongodb_shard

ANSIBLE VERSION
ansible 2.8.11
  config file = /ansible/playbooks/de/ansible.cfg
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.7/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 3.7.5 (default, Oct 17 2019, 12:25:15) [GCC 8.3.0]
CONFIGURATION
ANSIBLE_PIPELINING(/ansible/playbooks/de/ansible.cfg) = True
ANSIBLE_SSH_ARGS(/ansible/playbooks/de/ansible.cfg) = -o ForwardAgent=yes -o ControlMaster=auto -o ControlPersist=60s -o PreferredAuthentications=password,publickey
DEFAULT_ACTION_PLUGIN_PATH(env: ANSIBLE_ACTION_PLUGINS) = ['/ansible/plugins/action_plugins']
DEFAULT_FORKS(/ansible/playbooks/de/ansible.cfg) = 20
DEFAULT_LOG_PATH(/ansible/playbooks/de/ansible.cfg) = /ansible/playbooks/de/ansible.log
DEFAULT_TIMEOUT(/ansible/playbooks/de/ansible.cfg) = 30
DEFAULT_VAULT_IDENTITY_LIST(env: ANSIBLE_VAULT_IDENTITY_LIST) = ['production-de@/tmp/.vault-password-production-de', 'staging-de@/tmp/.vault-password-staging-de', 'test-de@/tmp/.vault-password-test-de']
HOST_KEY_CHECKING(/ansible/playbooks/de/ansible.cfg) = False
OS / ENVIRONMENT

Debian 10.2

STEPS TO REPRODUCE

Rename the mongos binary to some random name or create a symlink with another name (like custom-mongos-1) and use that for starting the mongos service. The server status of the mongos should show the custom binary in the process field:

mongos> db.serverStatus()
{
    "host" : "mongos-1.yourdomain.net:58350",
    "version" : "3.4.24",
    "process" : "custom-mongos-1",
        ...
}

Now try adding a shard using the mongodb_shard module.

- name: Add all shards to the cluster
  mongodb_shard:
    login_host: "{{ item.0.mongos_login_host }}"
    login_port: "{{ item.0.mongos_login_port|int }}"
    shard: "{{ item.0.replicaset }}/{{ item.1 }}"
    state: present
  loop: "{{ mongodb_shards|subelements('members') }}"
  when: item.0.type == 'shard'
  run_once: yes
EXPECTED RESULTS

Shard is added to MongoDB cluster

ACTUAL RESULTS
failed: [shard1-1.yourdomain.net] (item=[{'replicaset': 'shard1', 'type': 'shard', 'login_host': 'shard1-1.yourdomain.net', 'login_port': 28351, 'mongos_login_host': 'mongos-1.yourdomain.net', 'mongos_login_port': 58350, 'members': ['shard1-1.yourdomain.net:28351', 'shard1-2.yourdomain.net:28351', 'shard1-3.yourdomain.net:28351']}, 'shard1-3.yourdomain.net:28351']) => {"ansible_loop_var": "item", "changed": false, "item": [{"login_host": "shard1-1.yourdomain.net", "login_port": 28351, "members": ["shard1-1.yourdomain.net:28351", "shard1-2.yourdomain.net:28351", "shard1-3.yourdomain.net:28351"], "mongos_login_host": "mongos-1.yourdomain.net", "mongos_login_port": 58350, "replicaset": "shard1", "type": "shard"}, "shard1-3.yourdomain.net:28351"], "msg": "Process running on mongos-1.yourdomain.net:58350 is not a mongos"}

Migrated issue from https://github.com/ansible/ansible/issues/69256.

rhysmeister commented 4 years ago

Probably quite an unusual requirement but this could be easy enough to fix. How about another module parameter, i.e. mongos_process with an obvious default of mongos. i.e.

- name: Add all shards to the cluster
  mongodb_shard:
    login_host: "{{ item.0.mongos_login_host }}"
    login_port: "{{ item.0.mongos_login_port|int }}"
    shard: "{{ item.0.replicaset }}/{{ item.1 }}"
    state: present
    mongos_process: "my-custom-mongos"
  loop: "{{ mongodb_shards|subelements('members') }}"
  when: item.0.type == 'shard'
  run_once: yes

Would this work for you?

dirkaholic commented 4 years ago

I think that would work, yes.

rhysmeister commented 4 years ago

Implemented in https://github.com/ansible-collections/community.mongodb/pull/56

dirkaholic commented 4 years ago

Wow, @rhysmeister that one was fast. Thanks a lot.

rhysmeister commented 4 years ago

Merged to master.