Fix all issues and warnings

This commit is contained in:
Sergei Antipov 2019-05-23 00:37:39 -04:00
parent 1d0593464e
commit 852ad2149e
No known key found for this signature in database
GPG Key ID: B167B87787407B3A
11 changed files with 66 additions and 512 deletions

View File

@ -19,3 +19,22 @@
- name: restart sysfsutils - name: restart sysfsutils
service: name=sysfsutils state=restarted service: name=sysfsutils state=restarted
- name: service started
service:
name: "{{ mongodb_daemon_name }}"
state: started
- name: wait when mongodb is started
wait_for:
host: "{{ item }}"
port: "{{ mongodb_net_port }}"
timeout: 120
with_items: "{{ mongodb_net_bindip.split(',') | map('replace', '0.0.0.0', '127.0.0.1') | list }}"
- name: wait when mongodb is started on localhost
wait_for:
host: "127.0.0.1"
port: "{{ mongodb_net_port }}"
delay: 5
timeout: 120

View File

@ -1,462 +0,0 @@
#!/usr/bin/python
# (c) 2012, Elliott Foster <elliott@fourkitchens.com>
# Sponsored by Four Kitchens http://fourkitchens.com.
# (c) 2014, Epic Games, Inc.
#
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: mongodb_user
short_description: Adds or removes a user from a MongoDB database.
description:
- Adds or removes a user from a MongoDB database.
version_added: "1.1"
options:
login_user:
description:
- The username used to authenticate with
required: false
default: null
login_password:
description:
- The password used to authenticate with
required: false
default: null
login_host:
description:
- The host running the database
required: false
default: localhost
login_port:
description:
- The port to connect to
required: false
default: 27017
login_database:
version_added: "2.0"
description:
- The database where login credentials are stored
required: false
default: admin
replica_set:
version_added: "1.6"
description:
- Replica set to connect to (automatically connects to primary for writes)
required: false
default: null
database:
description:
- The name of the database to add/remove the user from
required: true
name:
description:
- The name of the user to add or remove
required: true
default: null
aliases: [ 'user' ]
password:
description:
- The password to use for the user
required: false
default: null
ssl:
version_added: "1.8"
description:
- Whether to use an SSL connection when connecting to the database
default: False
ssl_cert_reqs:
version_added: "2.2"
description:
- Specifies whether a certificate is required from the other side of the connection, and whether it will be validated if provided.
required: false
default: "CERT_REQUIRED"
choices: ["CERT_REQUIRED", "CERT_OPTIONAL", "CERT_NONE"]
roles:
version_added: "1.3"
description:
- >
The database user roles valid values could either be one or more of the following strings:
'read', 'readWrite', 'dbAdmin', 'userAdmin', 'clusterAdmin', 'readAnyDatabase', 'readWriteAnyDatabase', 'userAdminAnyDatabase',
'dbAdminAnyDatabase'
- "Or the following dictionary '{ db: DATABASE_NAME, role: ROLE_NAME }'."
- "This param requires pymongo 2.5+. If it is a string, mongodb 2.4+ is also required. If it is a dictionary, mongo 2.6+ is required."
required: false
default: "readWrite"
state:
description:
- The database user state
required: false
default: present
choices: [ "present", "absent" ]
update_password:
required: false
default: always
choices: ['always', 'on_create']
version_added: "2.1"
description:
- C(always) will update passwords if they differ. C(on_create) will only set the password for newly created users.
notes:
- Requires the pymongo Python package on the remote host, version 2.4.2+. This
can be installed using pip or the OS package manager. @see http://api.mongodb.org/python/current/installation.html
requirements: [ "pymongo" ]
author:
- "Elliott Foster (@elliotttf)"
- "Julien Thebault (@lujeni)"
'''
EXAMPLES = '''
# Create 'burgers' database user with name 'bob' and password '12345'.
- mongodb_user:
database: burgers
name: bob
password: 12345
state: present
# Create a database user via SSL (MongoDB must be compiled with the SSL option and configured properly)
- mongodb_user:
database: burgers
name: bob
password: 12345
state: present
ssl: True
# Delete 'burgers' database user with name 'bob'.
- mongodb_user:
database: burgers
name: bob
state: absent
# Define more users with various specific roles (if not defined, no roles is assigned, and the user will be added via pre mongo 2.2 style)
- mongodb_user:
database: burgers
name: ben
password: 12345
roles: read
state: present
- mongodb_user:
database: burgers
name: jim
password: 12345
roles: readWrite,dbAdmin,userAdmin
state: present
- mongodb_user:
database: burgers
name: joe
password: 12345
roles: readWriteAnyDatabase
state: present
# add a user to database in a replica set, the primary server is automatically discovered and written to
- mongodb_user:
database: burgers
name: bob
replica_set: belcher
password: 12345
roles: readWriteAnyDatabase
state: present
# add a user 'oplog_reader' with read only access to the 'local' database on the replica_set 'belcher'. This is useful for oplog access (MONGO_OPLOG_URL).
# please notice the credentials must be added to the 'admin' database because the 'local' database is not syncronized and can't receive user credentials
# To login with such user, the connection string should be MONGO_OPLOG_URL="mongodb://oplog_reader:oplog_reader_password@server1,server2/local?authSource=admin"
# This syntax requires mongodb 2.6+ and pymongo 2.5+
- mongodb_user:
login_user: root
login_password: root_password
database: admin
user: oplog_reader
password: oplog_reader_password
state: present
replica_set: belcher
roles:
- db: local
role: read
'''
RETURN = '''
user:
description: The name of the user to add or remove.
returned: success
type: string
'''
import os
import ssl as ssl_lib
import traceback
from distutils.version import LooseVersion
try:
from pymongo.errors import ConnectionFailure
from pymongo.errors import OperationFailure
from pymongo import version as PyMongoVersion
from pymongo import MongoClient
except ImportError:
try: # for older PyMongo 2.2
from pymongo import Connection as MongoClient
except ImportError:
pymongo_found = False
else:
pymongo_found = True
else:
pymongo_found = True
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.six import binary_type, text_type
from ansible.module_utils.six.moves import configparser
from ansible.module_utils._text import to_native
# =========================================
# MongoDB module specific support methods.
#
def check_compatibility(module, client):
"""Check the compatibility between the driver and the database.
See: https://docs.mongodb.com/ecosystem/drivers/driver-compatibility-reference/#python-driver-compatibility
Args:
module: Ansible module.
client (cursor): Mongodb cursor on admin database.
"""
loose_srv_version = LooseVersion(client.server_info()['version'])
loose_driver_version = LooseVersion(PyMongoVersion)
if loose_srv_version >= LooseVersion('3.2') and loose_driver_version < LooseVersion('3.2'):
module.fail_json(msg=' (Note: you must use pymongo 3.2+ with MongoDB >= 3.2)')
elif loose_srv_version >= LooseVersion('3.0') and loose_driver_version <= LooseVersion('2.8'):
module.fail_json(msg=' (Note: you must use pymongo 2.8+ with MongoDB 3.0)')
elif loose_srv_version >= LooseVersion('2.6') and loose_driver_version <= LooseVersion('2.7'):
module.fail_json(msg=' (Note: you must use pymongo 2.7+ with MongoDB 2.6)')
elif LooseVersion(PyMongoVersion) <= LooseVersion('2.5'):
module.fail_json(msg=' (Note: you must be on mongodb 2.4+ and pymongo 2.5+ to use the roles param)')
def user_find(client, user, db_name):
"""Check if the user exists.
Args:
client (cursor): Mongodb cursor on admin database.
user (str): User to check.
db_name (str): User's database.
Returns:
dict: when user exists, False otherwise.
"""
for mongo_user in client["admin"].system.users.find():
if mongo_user['user'] == user:
# NOTE: there is no 'db' field in mongo 2.4.
if 'db' not in mongo_user:
return mongo_user
if mongo_user["db"] == db_name:
return mongo_user
return False
def user_add(module, client, db_name, user, password, roles):
# pymongo's user_add is a _create_or_update_user so we won't know if it was changed or updated
# without reproducing a lot of the logic in database.py of pymongo
db = client[db_name]
if roles is None:
db.add_user(user, password, False)
else:
db.add_user(user, password, None, roles=roles)
def user_remove(module, client, db_name, user):
exists = user_find(client, user, db_name)
if exists:
if module.check_mode:
module.exit_json(changed=True, user=user)
db = client[db_name]
db.remove_user(user)
else:
module.exit_json(changed=False, user=user)
def load_mongocnf():
config = configparser.RawConfigParser()
mongocnf = os.path.expanduser('~/.mongodb.cnf')
try:
config.readfp(open(mongocnf))
creds = dict(
user=config.get('client', 'user'),
password=config.get('client', 'pass')
)
except (configparser.NoOptionError, IOError):
return False
return creds
def check_if_roles_changed(uinfo, roles, db_name):
# We must be aware of users which can read the oplog on a replicaset
# Such users must have access to the local DB, but since this DB does not store users credentials
# and is not synchronized among replica sets, the user must be stored on the admin db
# Therefore their structure is the following :
# {
# "_id" : "admin.oplog_reader",
# "user" : "oplog_reader",
# "db" : "admin", # <-- admin DB
# "roles" : [
# {
# "role" : "read",
# "db" : "local" # <-- local DB
# }
# ]
# }
def make_sure_roles_are_a_list_of_dict(roles, db_name):
output = list()
for role in roles:
if isinstance(role, (binary_type, text_type)):
new_role = {"role": role, "db": db_name}
output.append(new_role)
else:
output.append(role)
return output
roles_as_list_of_dict = make_sure_roles_are_a_list_of_dict(roles, db_name)
uinfo_roles = uinfo.get('roles', [])
if sorted(roles_as_list_of_dict) == sorted(uinfo_roles):
return False
return True
# =========================================
# Module execution.
#
def main():
module = AnsibleModule(
argument_spec=dict(
login_user=dict(default=None),
login_password=dict(default=None, no_log=True),
login_host=dict(default='localhost'),
login_port=dict(default='27017'),
login_database=dict(default="admin"),
replica_set=dict(default=None),
database=dict(required=True, aliases=['db']),
name=dict(required=True, aliases=['user']),
password=dict(aliases=['pass'], no_log=True),
ssl=dict(default=False, type='bool'),
roles=dict(default=None, type='list'),
state=dict(default='present', choices=['absent', 'present']),
update_password=dict(default="always", choices=["always", "on_create"]),
ssl_cert_reqs=dict(default='CERT_REQUIRED', choices=['CERT_NONE', 'CERT_OPTIONAL', 'CERT_REQUIRED']),
),
supports_check_mode=True
)
if not pymongo_found:
module.fail_json(msg='the python pymongo module is required')
login_user = module.params['login_user']
login_password = module.params['login_password']
login_host = module.params['login_host']
login_port = module.params['login_port']
login_database = module.params['login_database']
replica_set = module.params['replica_set']
db_name = module.params['database']
user = module.params['name']
password = module.params['password']
ssl = module.params['ssl']
roles = module.params['roles'] or []
state = module.params['state']
update_password = module.params['update_password']
try:
connection_params = {
"host": login_host,
"port": int(login_port),
"username": login_user,
"password": login_password,
"authSource": login_database,
}
if replica_set:
connection_params["replicaset"] = replica_set
if ssl:
connection_params["ssl"] = ssl
connection_params["ssl_cert_reqs"] = getattr(ssl_lib, module.params['ssl_cert_reqs'])
client = MongoClient(**connection_params)
# NOTE: this check must be done ASAP.
# We doesn't need to be authenticated.
check_compatibility(module, client)
if login_user is None and login_password is None:
mongocnf_creds = load_mongocnf()
if mongocnf_creds is not False:
login_user = mongocnf_creds['user']
login_password = mongocnf_creds['password']
elif login_password is None or login_user is None:
module.fail_json(msg='when supplying login arguments, both login_user and login_password must be provided')
if login_user is not None and login_password is not None:
client.admin.authenticate(login_user, login_password, source=login_database)
elif LooseVersion(PyMongoVersion) >= LooseVersion('3.0'):
if db_name != "admin":
module.fail_json(msg='The localhost login exception only allows the first admin account to be created')
# else: this has to be the first admin user added
except Exception as e:
module.fail_json(msg='unable to connect to database: %s' % to_native(e), exception=traceback.format_exc())
if state == 'present':
if password is None and update_password == 'always':
module.fail_json(msg='password parameter required when adding a user unless update_password is set to on_create')
try:
if update_password != 'always':
uinfo = user_find(client, user, db_name)
if uinfo:
password = None
if not check_if_roles_changed(uinfo, roles, db_name):
module.exit_json(changed=False, user=user)
if module.check_mode:
module.exit_json(changed=True, user=user)
user_add(module, client, db_name, user, password, roles)
except Exception as e:
module.fail_json(msg='Unable to add or update user: %s' % to_native(e), exception=traceback.format_exc())
# Here we can check password change if mongo provide a query for that : https://jira.mongodb.org/browse/SERVER-22848
# newuinfo = user_find(client, user, db_name)
# if uinfo['role'] == newuinfo['role'] and CheckPasswordHere:
# module.exit_json(changed=False, user=user)
elif state == 'absent':
try:
user_remove(module, client, db_name, user)
except Exception as e:
module.fail_json(msg='Unable to remove user: %s' % to_native(e), exception=traceback.format_exc())
module.exit_json(changed=True, user=user)
if __name__ == '__main__':
main()

View File

@ -6,7 +6,7 @@ galaxy_info:
company: Self-employed company: Self-employed
description: Manage MongoDB with authentication and replica sets description: Manage MongoDB with authentication and replica sets
license: GPLv2 license: GPLv2
min_ansible_version: 2.4 min_ansible_version: 2.5
platforms: platforms:
- name: Ubuntu - name: Ubuntu
versions: versions:

View File

@ -1,13 +1,17 @@
--- ---
- name: Use different mongod.conf for auth initialization - name: Use different mongod.conf for auth initialization
template: src=mongod_init.conf.j2 dest=/etc/mongod.conf owner=root group=root mode=0644 template:
src: mongod_init.conf.j2
dest: /etc/mongod.conf
owner: root
group: root
mode: 0644
notify:
- mongodb restart
- wait when mongodb is started on localhost
- name: Restart mongodb service - name: Flush all handlers at this point
service: name={{ mongodb_daemon_name }} state=restarted meta: flush_handlers
when: mongodb_manage_service
- name: wait MongoDB port is listening
wait_for: host=127.0.0.1 port="{{ mongodb_net_port }}" delay=5 state=started
- name: create administrative user siteUserAdmin - name: create administrative user siteUserAdmin
mongodb_user: mongodb_user:
@ -58,12 +62,15 @@
no_log: true no_log: true
- name: Move back mongod.conf - name: Move back mongod.conf
template: src=mongod.conf.j2 dest=/etc/mongod.conf owner=root group=root mode=0644 template:
src: mongod.conf.j2
dest: /etc/mongod.conf
owner: root
group: root
mode: 0644
notify:
- mongodb restart
- wait when mongodb is started
- name: Restart mongodb service - name: Flush all handlers at this point
service: name={{ mongodb_daemon_name }} state=restarted meta: flush_handlers
when: mongodb_manage_service
- name: Wait MongoDB port is listening
wait_for: host="{{ item }}" port="{{ mongodb_net_port }}" delay=5 state=started
with_items: "{{ mongodb_net_bindip.split(',') | map('replace', '0.0.0.0', '127.0.0.1') | list }}"

View File

@ -7,7 +7,7 @@
owner: "{{ mongodb_user }}" owner: "{{ mongodb_user }}"
group: "root" group: "root"
mode: 0600 mode: 0600
when: mongodb_replication_replset when: mongodb_replication_replset|default("") != ""
- name: set mongodb gid - name: set mongodb gid
group: group:
@ -68,18 +68,10 @@
owner: root owner: root
group: root group: root
mode: 0644 mode: 0644
register: config_result notify:
- mongodb restart
- service started
- wait when mongodb is started
- name: mongodb restart - name: Flush all handlers at this point
service: name={{ mongodb_daemon_name }} state=restarted meta: flush_handlers
when: config_result is changed and mongodb_manage_service
- name: Ensure service is started
service: name={{ mongodb_daemon_name }} state=started
- name: Wait when mongodb is started
wait_for:
host: "{{ item }}"
port: "{{ mongodb_net_port }}"
timeout: 120
with_items: "{{ mongodb_net_bindip.split(',') | map('replace', '0.0.0.0', '127.0.0.1') | list }}"

View File

@ -47,8 +47,12 @@
or mongodb_repository[mongodb_major_version] is not defined)) or mongodb_repository[mongodb_major_version] is not defined))
- name: Add APT repository - name: Add APT repository
apt_repository: repo="{{ mongodb_repository[item] }}" update_cache=yes apt_repository:
repo: "{{ mongodb_repository[version_item] }}"
update_cache: yes
with_items: "{{ mongodb_major_version }}" with_items: "{{ mongodb_major_version }}"
loop_control:
loop_var: version_item
when: mongodb_package == 'mongodb-org' when: mongodb_package == 'mongodb-org'
- name: Install MongoDB and numactl packages - name: Install MongoDB and numactl packages
@ -66,10 +70,8 @@
- name: Add symlink for systemd - name: Add symlink for systemd
file: src=/lib/systemd/system/mongodb.service dest=/etc/systemd/system/multi-user.target.wants/mongodb.service state=link file: src=/lib/systemd/system/mongodb.service dest=/etc/systemd/system/multi-user.target.wants/mongodb.service state=link
when: ansible_service_mgr == "systemd" when: ansible_service_mgr == "systemd"
notify:
- block: - reload systemd
- meta: flush_handlers
when: ansible_service_mgr == "systemd"
- name: Install PyMongo package - name: Install PyMongo package
apt: apt:

View File

@ -20,14 +20,14 @@
- name: Include replication and auth configuration - name: Include replication and auth configuration
include: replication_init_auth.yml include: replication_init_auth.yml
when: ( mongodb_replication_replset when: ( mongodb_replication_replset is defined
and mongodb_security_authorization == 'enabled' and mongodb_security_authorization == 'enabled'
and mongodb_master is defined and mongodb_master ) and mongodb_master is defined and mongodb_master )
tags: [mongodb] tags: [mongodb]
- name: Include replication configuration - name: Include replication configuration
include: replication.yml include: replication.yml
when: mongodb_replication_replset when: mongodb_replication_replset is defined and mongodb_replication_replset
tags: [mongodb] tags: [mongodb]
- name: Check where admin user already exists - name: Check where admin user already exists
@ -51,7 +51,7 @@
tags: [mongodb] tags: [mongodb]
- name: create normal users with replicaset - name: create normal users with replicaset
mongodb_user_fixed: mongodb_user:
database: "{{ item.database }}" database: "{{ item.database }}"
name: "{{ item.name }}" name: "{{ item.name }}"
password: "{{ item.password }}" password: "{{ item.password }}"
@ -70,7 +70,7 @@
tags: [mongodb] tags: [mongodb]
- name: create normal users without replicaset - name: create normal users without replicaset
mongodb_user_fixed: mongodb_user:
database: "{{ item.database }}" database: "{{ item.database }}"
name: "{{ item.name }}" name: "{{ item.name }}"
password: "{{ item.password }}" password: "{{ item.password }}"
@ -87,7 +87,7 @@
tags: [mongodb] tags: [mongodb]
- name: create oplog user with replicaset - name: create oplog user with replicaset
mongodb_user_fixed: mongodb_user:
database: admin database: admin
user: "{{ item.user }}" user: "{{ item.user }}"
password: "{{ item.password }}" password: "{{ item.password }}"

View File

@ -19,7 +19,7 @@
ignore_errors: true ignore_errors: true
- include: auth_initialization.yml - include: auth_initialization.yml
when: mongodb_replica_init|failed when: mongodb_replica_init is failed
- name: Replication configuration | 2nd Pt - name: Replication configuration | 2nd Pt
mongodb_replication: mongodb_replication:
@ -35,6 +35,6 @@
hidden: "{{ item.hidden|default(false) }}" hidden: "{{ item.hidden|default(false) }}"
priority: "{{ item.priority|default(1.0) }}" priority: "{{ item.priority|default(1.0) }}"
votes: "{{ item.votes|default(omit) }}" votes: "{{ item.votes|default(omit) }}"
when: mongodb_replica_init|failed when: mongodb_replica_init is failed
with_items: with_items:
- "{{ mongodb_replication_params|default([]) }}" - "{{ mongodb_replication_params|default([]) }}"

View File

@ -2,7 +2,7 @@
net: net:
bindIp: {{ mongodb_net_bindip }} bindIp: {{ mongodb_net_bindip }}
{% if mongodb_major_version is version_compare("3.6", "<") -%} {% if mongodb_major_version is version("3.6", "<") -%}
http: http:
enabled: {{ mongodb_net_http_enabled | to_nice_json }} enabled: {{ mongodb_net_http_enabled | to_nice_json }}
{% endif -%} {% endif -%}
@ -39,9 +39,7 @@ security:
storage: storage:
dbPath: {{ mongodb_storage_dbpath }} dbPath: {{ mongodb_storage_dbpath }}
directoryPerDB: {{ mongodb_storage_dirperdb | to_nice_json }} directoryPerDB: {{ mongodb_storage_dirperdb | to_nice_json }}
{% if mongodb_major_version is version_compare("3.0", ">=") -%}
engine: {{ mongodb_storage_engine }} engine: {{ mongodb_storage_engine }}
{% endif -%}
journal: journal:
enabled: {{ mongodb_storage_journal_enabled | to_nice_json }} enabled: {{ mongodb_storage_journal_enabled | to_nice_json }}
{% if mongodb_storage_engine == 'mmapv1' -%} {% if mongodb_storage_engine == 'mmapv1' -%}

View File

@ -2,7 +2,7 @@
net: net:
bindIp: '127.0.0.1' bindIp: '127.0.0.1'
{% if mongodb_major_version | version_compare("3.6", "<") -%} {% if mongodb_major_version is version("3.6", "<") -%}
http: http:
enabled: {{ mongodb_net_http_enabled | to_nice_json }} enabled: {{ mongodb_net_http_enabled | to_nice_json }}
{% endif -%} {% endif -%}
@ -22,9 +22,7 @@ security:
storage: storage:
dbPath: {{ mongodb_storage_dbpath }} dbPath: {{ mongodb_storage_dbpath }}
directoryPerDB: {{ mongodb_storage_dirperdb | to_nice_json }} directoryPerDB: {{ mongodb_storage_dirperdb | to_nice_json }}
{% if mongodb_major_version | version_compare("3.0", ">=") -%}
engine: {{ mongodb_storage_engine }} engine: {{ mongodb_storage_engine }}
{% endif -%}
journal: journal:
enabled: {{ mongodb_storage_journal_enabled | to_nice_json }} enabled: {{ mongodb_storage_journal_enabled | to_nice_json }}
{% if mongodb_storage_engine == 'mmapv1' -%} {% if mongodb_storage_engine == 'mmapv1' -%}

View File

@ -1,6 +1,6 @@
--- ---
mongodb_net_port: 30000 mongodb_net_port: 30000
mongodb_storage_journal_enabled: "{{ mongodb_major_version | version_compare('4.0', '>=') }}" mongodb_storage_journal_enabled: "{{ mongodb_major_version is version('4.0', '>=') }}"
mongodb_storage_smallfiles: true mongodb_storage_smallfiles: true
mongodb_storage_prealloc: false mongodb_storage_prealloc: false
mongodb_replication_params: mongodb_replication_params: