From 8500b9b1ede21f7874c3f62bbb714ea2715b750f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dariusz=20=C5=81uksza?= Date: Sat, 25 Jul 2015 11:46:34 +0200 Subject: [PATCH 01/14] Ensure /data/db directory on debina It appears that standard mongo install process on debian doesn't create the /data/db directory. This prevents mongo process from starting and required manual job on the server. With this fix the /data/db directory will be created by ansible during install process. --- tasks/install.deb.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tasks/install.deb.yml b/tasks/install.deb.yml index f846a22..4a24509 100644 --- a/tasks/install.deb.yml +++ b/tasks/install.deb.yml @@ -27,6 +27,9 @@ apt_repository: repo="{{mongodb_repository}}" update_cache=yes when: '"mongodb-org" in mongodb_package' +- name: Endure /data directory + file: path=/data/db state=directory owner=mongodb recurse=yes + - name: Install MongoDB package apt: name={{item}} state=present with_items: From b315a70cc0e1c4a2712c466a65dc9af8eebd8e17 Mon Sep 17 00:00:00 2001 From: James Yang Date: Fri, 14 Aug 2015 13:25:37 -0700 Subject: [PATCH 02/14] parameterize apt key and apt repo variables remove when conditional --- defaults/main.yml | 2 ++ tasks/install.deb.yml | 4 +--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 0dafae3..fbbfa14 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -1,6 +1,8 @@ --- mongodb_package: mongodb-org +mongodb_apt_key_url: http://docs.mongodb.org/10gen-gpg-key.asc +mongodb_apt_key_id: 7F0CEB10 mongodb_force_wait_for_port: false mongodb_pymongo_from_pip: false # Install latest PyMongo via PIP or package manager mongodb_disable_thp: true diff --git a/tasks/install.deb.yml b/tasks/install.deb.yml index 4a24509..acea3fd 100644 --- a/tasks/install.deb.yml +++ b/tasks/install.deb.yml @@ -20,12 +20,10 @@ when: "'systemd' in systemd.stdout" - name: Add APT key - apt_key: url=http://docs.mongodb.org/10gen-gpg-key.asc id=7F0CEB10 - when: '"mongodb-org" in mongodb_package' + apt_key: url="{{mongodb_apt_key_url}}" id="{{mongodb_apt_key_id}}" - name: Add APT repository apt_repository: repo="{{mongodb_repository}}" update_cache=yes - when: '"mongodb-org" in mongodb_package' - name: Endure /data directory file: path=/data/db state=directory owner=mongodb recurse=yes From 96c609e72265284d2b19770eef6999bb614fce8b Mon Sep 17 00:00:00 2001 From: Sergei Antipov Date: Sat, 15 Aug 2015 11:36:03 +0500 Subject: [PATCH 03/14] Version bump --- meta/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta/main.yml b/meta/main.yml index a16c496..c618ab0 100644 --- a/meta/main.yml +++ b/meta/main.yml @@ -1,6 +1,6 @@ --- -version: 1.4.3 +version: 1.4.4 dependencies: [] galaxy_info: From a1d109d0abba786d971b3705b72816fcc1d81d39 Mon Sep 17 00:00:00 2001 From: Dariusz Luksza Date: Tue, 18 Aug 2015 23:40:34 +0200 Subject: [PATCH 04/14] Fix typo --- tasks/install.deb.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/install.deb.yml b/tasks/install.deb.yml index acea3fd..513efe5 100644 --- a/tasks/install.deb.yml +++ b/tasks/install.deb.yml @@ -25,7 +25,7 @@ - name: Add APT repository apt_repository: repo="{{mongodb_repository}}" update_cache=yes -- name: Endure /data directory +- name: Ensure /data directory file: path=/data/db state=directory owner=mongodb recurse=yes - name: Install MongoDB package From 9d98bc002b3f63464b29d7ecec211a0c98a3a9a4 Mon Sep 17 00:00:00 2001 From: Dariusz Luksza Date: Tue, 18 Aug 2015 23:42:18 +0200 Subject: [PATCH 05/14] Move /data ensuring task after package install --- tasks/install.deb.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tasks/install.deb.yml b/tasks/install.deb.yml index 513efe5..0102177 100644 --- a/tasks/install.deb.yml +++ b/tasks/install.deb.yml @@ -25,15 +25,15 @@ - name: Add APT repository apt_repository: repo="{{mongodb_repository}}" update_cache=yes -- name: Ensure /data directory - file: path=/data/db state=directory owner=mongodb recurse=yes - - name: Install MongoDB package apt: name={{item}} state=present with_items: - "{{mongodb_package}}" - numactl +- name: Ensure /data directory + file: path=/data/db state=directory owner=mongodb recurse=yes + - name: reload systemd shell: systemctl daemon-reload changed_when: false From c5e2a1f70a8f78cdb1ae24f06ffa3cf8c39134cd Mon Sep 17 00:00:00 2001 From: Sergei Antipov Date: Thu, 20 Aug 2015 17:10:41 +0500 Subject: [PATCH 06/14] Version bump --- meta/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta/main.yml b/meta/main.yml index c618ab0..748aeb4 100644 --- a/meta/main.yml +++ b/meta/main.yml @@ -1,6 +1,6 @@ --- -version: 1.4.4 +version: 1.4.5 dependencies: [] galaxy_info: From 348c874f494d9b85c3b52df3b589fcd829434a4b Mon Sep 17 00:00:00 2001 From: Adam Snodgrass Date: Thu, 3 Sep 2015 14:48:56 -0400 Subject: [PATCH 07/14] Use mongodb_conf_dbpath rather than a hard-coded path name --- tasks/install.deb.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasks/install.deb.yml b/tasks/install.deb.yml index 0102177..b47d155 100644 --- a/tasks/install.deb.yml +++ b/tasks/install.deb.yml @@ -31,8 +31,8 @@ - "{{mongodb_package}}" - numactl -- name: Ensure /data directory - file: path=/data/db state=directory owner=mongodb recurse=yes +- name: Ensure dbpath directory + file: path={{mongodb_conf_dbpath}} state=directory owner=mongodb recurse=yes - name: reload systemd shell: systemctl daemon-reload From cfe6c7fc5d398374ff04c38817bba837d0672022 Mon Sep 17 00:00:00 2001 From: Sergei Antipov Date: Mon, 5 Oct 2015 12:57:40 +0500 Subject: [PATCH 08/14] Version bump --- meta/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta/main.yml b/meta/main.yml index 748aeb4..a74e955 100644 --- a/meta/main.yml +++ b/meta/main.yml @@ -1,6 +1,6 @@ --- -version: 1.4.5 +version: 1.4.6 dependencies: [] galaxy_info: From 58ccde41b1d881cab9ac2f8be08e510501436b18 Mon Sep 17 00:00:00 2001 From: Sergei Antipov Date: Mon, 16 Nov 2015 15:00:25 +0600 Subject: [PATCH 09/14] Added fixed mongodb_user module --- library/mongodb_user.py | 287 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 287 insertions(+) create mode 100644 library/mongodb_user.py diff --git a/library/mongodb_user.py b/library/mongodb_user.py new file mode 100644 index 0000000..839cb15 --- /dev/null +++ b/library/mongodb_user.py @@ -0,0 +1,287 @@ +#!/usr/bin/python + +# (c) 2012, Elliott Foster +# Sponsored by Four Kitchens http://fourkitchens.com. +# (c) 2014, Epic Games, Inc. +# +# 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 . + +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: null + 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 + roles: + version_added: "1.3" + description: + - "The database user roles valid values are one or more of the following: read, 'readWrite', 'dbAdmin', 'userAdmin', 'clusterAdmin', 'readAnyDatabase', 'readWriteAnyDatabase', 'userAdminAnyDatabase', 'dbAdminAnyDatabase'" + - This param requires mongodb 2.4+ and pymongo 2.5+ + required: false + default: "readWrite" + state: + 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)" +''' + +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=blecher password=12345 roles='readWriteAnyDatabase' state=present +''' + +import ConfigParser +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 + +# ========================================= +# MongoDB module specific support methods. +# + +def user_find(client, user): + for mongo_user in client["admin"].system.users.find(): + if mongo_user['user'] == user: + return mongo_user + return False + +def user_add(module, client, db_name, user, password, roles): + #pymono'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: + try: + db.add_user(user, password, None, roles=roles) + except OperationFailure, e: + err_msg = str(e) + srv_info = client.server_info() + if LooseVersion(srv_info['version']) >= LooseVersion('3.0') and LooseVersion(PyMongoVersion) <= LooseVersion('3.0'): + err_msg = err_msg + ' (Note: you must use pymongo 3.0+ with MongoDB >= 3.0)' + elif LooseVersion(srv_info['version']) >= LooseVersion('2.6') and LooseVersion(PyMongoVersion) <= LooseVersion('2.7'): + err_msg = err_msg + ' (Note: you must use pymongo 2.7.x-2.9.x with MongoDB 2.6)' + elif LooseVersion(PyMongoVersion) <= LooseVersion('2.5'): + err_msg = err_msg + ' (Note: you must be on mongodb 2.4+ and pymongo 2.5+ to use the roles param)' + module.fail_json(msg=err_msg) + +def user_remove(module, client, db_name, user): + exists = user_find(client, user) + if exists: + 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 + +# ========================================= +# Module execution. +# + +def main(): + module = AnsibleModule( + argument_spec = dict( + login_user=dict(default=None), + login_password=dict(default=None), + login_host=dict(default='localhost'), + login_port=dict(default='27017'), + login_database=dict(default=None), + replica_set=dict(default=None), + database=dict(required=True, aliases=['db']), + name=dict(required=True, aliases=['user']), + password=dict(aliases=['pass']), + ssl=dict(default=False), + roles=dict(default=None, type='list'), + state=dict(default='present', choices=['absent', 'present']), + update_password=dict(default="always", choices=["always", "on_create"]), + ) + ) + + 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'] + state = module.params['state'] + update_password = module.params['update_password'] + + try: + if replica_set: + client = MongoClient(login_host, int(login_port), replicaset=replica_set, ssl=ssl) + else: + client = MongoClient(login_host, int(login_port), ssl=ssl) + + 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 ConnectionFailure, e: + module.fail_json(msg='unable to connect to database: %s' % str(e)) + + 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') + + if update_password != 'always' and user_find(client, user): + password = None + + try: + user_add(module, client, db_name, user, password, roles) + except OperationFailure, e: + module.fail_json(msg='Unable to add or update user: %s' % str(e)) + + elif state == 'absent': + try: + user_remove(module, client, db_name, user) + except OperationFailure, e: + module.fail_json(msg='Unable to remove user: %s' % str(e)) + + module.exit_json(changed=True, user=user) + +# import module snippets +from ansible.module_utils.basic import * +main() From 94ebb6e2cd7817ad815f18c5a2e52da89d0bfbef Mon Sep 17 00:00:00 2001 From: Sergei Antipov Date: Mon, 16 Nov 2015 16:46:18 +0600 Subject: [PATCH 10/14] Fixed problem with mongodb_users param --- tasks/auth_initialization.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tasks/auth_initialization.yml b/tasks/auth_initialization.yml index f1668be..ea6454a 100644 --- a/tasks/auth_initialization.yml +++ b/tasks/auth_initialization.yml @@ -50,13 +50,12 @@ name: "{{ item.name }}" password: "{{ item.password }}" roles: "{{ item.roles }}" - replica_set: "{{ mongodb_conf_replSet }}" login_user: "{{ mongodb_user_admin_name }}" login_password: "{{ mongodb_user_admin_password }}" login_port: "{{ mongodb_conf_port }}" with_items: - "{{ mongodb_users }}" - when: mongodb_users + when: mongodb_users is defined and mongodb_users - name: Move back mongod.conf template: src=mongod.conf.j2 dest=/etc/mongod.conf owner=root group=root mode=0644 From 09ff5f902a1a193f68da7b7ea9239da336306e68 Mon Sep 17 00:00:00 2001 From: Sergei Antipov Date: Mon, 16 Nov 2015 16:46:46 +0600 Subject: [PATCH 11/14] Fixed problem with wrong pymongo package --- library/mongodb_user.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/library/mongodb_user.py b/library/mongodb_user.py index 839cb15..985559d 100644 --- a/library/mongodb_user.py +++ b/library/mongodb_user.py @@ -148,6 +148,15 @@ else: # MongoDB module specific support methods. # +def check_compatibility(module, client): + srv_info = client.server_info() + if LooseVersion(srv_info['version']) >= LooseVersion('3.0') and LooseVersion(PyMongoVersion) <= LooseVersion('3.0'): + module.fail_json(msg=' (Note: you must use pymongo 3.0+ with MongoDB >= 3.0)') + elif LooseVersion(srv_info['version']) >= LooseVersion('2.6') and LooseVersion(PyMongoVersion) <= LooseVersion('2.7'): + module.fail_json(msg=' (Note: you must use pymongo 2.7.x-2.9.x 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): for mongo_user in client["admin"].system.users.find(): if mongo_user['user'] == user: @@ -165,13 +174,6 @@ def user_add(module, client, db_name, user, password, roles): db.add_user(user, password, None, roles=roles) except OperationFailure, e: err_msg = str(e) - srv_info = client.server_info() - if LooseVersion(srv_info['version']) >= LooseVersion('3.0') and LooseVersion(PyMongoVersion) <= LooseVersion('3.0'): - err_msg = err_msg + ' (Note: you must use pymongo 3.0+ with MongoDB >= 3.0)' - elif LooseVersion(srv_info['version']) >= LooseVersion('2.6') and LooseVersion(PyMongoVersion) <= LooseVersion('2.7'): - err_msg = err_msg + ' (Note: you must use pymongo 2.7.x-2.9.x with MongoDB 2.6)' - elif LooseVersion(PyMongoVersion) <= LooseVersion('2.5'): - err_msg = err_msg + ' (Note: you must be on mongodb 2.4+ and pymongo 2.5+ to use the roles param)' module.fail_json(msg=err_msg) def user_remove(module, client, db_name, user): @@ -262,6 +264,8 @@ def main(): except ConnectionFailure, e: module.fail_json(msg='unable to connect to database: %s' % str(e)) + check_compatibility(module, client) + 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') From 0c9f6be59d32a6e3d2f5ced3925c447be2e11f35 Mon Sep 17 00:00:00 2001 From: Sergei Antipov Date: Mon, 16 Nov 2015 16:48:15 +0600 Subject: [PATCH 12/14] Added Emacs special files into gitignore --- .gitignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 723ef36..63f1968 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ -.idea \ No newline at end of file +.idea +*~ +\#*\# +.\#* \ No newline at end of file From 240769f0caf8e2004f7ecece256c81c45688f235 Mon Sep 17 00:00:00 2001 From: Sergei Antipov Date: Mon, 16 Nov 2015 16:50:08 +0600 Subject: [PATCH 13/14] Version bump --- meta/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta/main.yml b/meta/main.yml index a74e955..7e52eb5 100644 --- a/meta/main.yml +++ b/meta/main.yml @@ -1,6 +1,6 @@ --- -version: 1.4.6 +version: 1.4.7 dependencies: [] galaxy_info: From cacf4879d09a4346a05ff09266dba8e22bebac93 Mon Sep 17 00:00:00 2001 From: Sergei Antipov Date: Tue, 17 Nov 2015 11:54:21 +0600 Subject: [PATCH 14/14] Added version for pymongo --- .gitignore | 3 ++- defaults/main.yml | 1 + tasks/install.deb.yml | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 63f1968..d389fa1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .idea *~ \#*\# -.\#* \ No newline at end of file +.\#* +.ropeproject/ \ No newline at end of file diff --git a/defaults/main.yml b/defaults/main.yml index fbbfa14..f495981 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -5,6 +5,7 @@ mongodb_apt_key_url: http://docs.mongodb.org/10gen-gpg-key.asc mongodb_apt_key_id: 7F0CEB10 mongodb_force_wait_for_port: false mongodb_pymongo_from_pip: false # Install latest PyMongo via PIP or package manager +mongodb_pymongo_pip_version: "2.9" mongodb_disable_thp: true mongodb_manage_service: true diff --git a/tasks/install.deb.yml b/tasks/install.deb.yml index b47d155..bb18682 100644 --- a/tasks/install.deb.yml +++ b/tasks/install.deb.yml @@ -51,5 +51,5 @@ when: mongodb_pymongo_from_pip - name: Install PyMongo from PIP - pip: name=pymongo state=latest + pip: name=pymongo version="{{ mongodb_pymongo_pip_version }}" state=latest when: mongodb_pymongo_from_pip