mirror of
https://github.com/status-im/ansible-role-mongodb.git
synced 2025-02-24 02:38:07 +00:00
Merge pull request #94 from UnderGreen/fix_build
Fix build + several significant changes
This commit is contained in:
commit
7a03b85012
121
.travis.yml
121
.travis.yml
@ -1,7 +1,12 @@
|
||||
# .travis.yml
|
||||
---
|
||||
|
||||
dist: trusty
|
||||
sudo: required
|
||||
language: python
|
||||
python:
|
||||
- "2.7"
|
||||
- "3.6"
|
||||
env:
|
||||
- >
|
||||
DISTRIBUTION=ubuntu-upstart
|
||||
@ -11,38 +16,6 @@ env:
|
||||
DISTRIBUTION=ubuntu-upstart
|
||||
DIST_VERSION=14.04
|
||||
MONGODB_VERSION=3.2
|
||||
- >
|
||||
DISTRIBUTION=ubuntu-upstart
|
||||
DIST_VERSION=14.04
|
||||
MONGODB_VERSION=3.0
|
||||
- >
|
||||
DISTRIBUTION=ubuntu-upstart
|
||||
DIST_VERSION=14.04
|
||||
MONGODB_VERSION=2.6
|
||||
- >
|
||||
DISTRIBUTION=ubuntu-upstart
|
||||
DIST_VERSION=12.04-builded
|
||||
MONGODB_VERSION=3.4
|
||||
- >
|
||||
DISTRIBUTION=ubuntu-upstart
|
||||
DIST_VERSION=12.04-builded
|
||||
MONGODB_VERSION=3.2
|
||||
- >
|
||||
DISTRIBUTION=ubuntu-upstart
|
||||
DIST_VERSION=12.04-builded
|
||||
MONGODB_VERSION=3.0
|
||||
- >
|
||||
DISTRIBUTION=ubuntu-upstart
|
||||
DIST_VERSION=12.04-builded
|
||||
MONGODB_VERSION=2.6
|
||||
- >
|
||||
DISTRIBUTION=centos
|
||||
DIST_VERSION=6-builded
|
||||
MONGODB_VERSION=2.6
|
||||
- >
|
||||
DISTRIBUTION=centos
|
||||
DIST_VERSION=6-builded
|
||||
MONGODB_VERSION=3.0
|
||||
- >
|
||||
DISTRIBUTION=centos
|
||||
DIST_VERSION=6-builded
|
||||
@ -51,14 +24,6 @@ env:
|
||||
DISTRIBUTION=centos
|
||||
DIST_VERSION=6-builded
|
||||
MONGODB_VERSION=3.4
|
||||
- >
|
||||
DISTRIBUTION=centos
|
||||
DIST_VERSION=7-builded
|
||||
MONGODB_VERSION=2.6
|
||||
- >
|
||||
DISTRIBUTION=centos
|
||||
DIST_VERSION=7-builded
|
||||
MONGODB_VERSION=3.0
|
||||
- >
|
||||
DISTRIBUTION=centos
|
||||
DIST_VERSION=7-builded
|
||||
@ -68,84 +33,14 @@ env:
|
||||
DIST_VERSION=7-builded
|
||||
MONGODB_VERSION=3.4
|
||||
# - >
|
||||
# distribution=ubuntu-upstart
|
||||
# version=12.04
|
||||
# - >
|
||||
# distribution=debian
|
||||
# version=7
|
||||
|
||||
services:
|
||||
- docker
|
||||
|
||||
before_install:
|
||||
- sudo apt-get update
|
||||
# Latest Ansible install
|
||||
- sudo apt-add-repository -y ppa:ansible/ansible
|
||||
- sudo apt-get update
|
||||
- sudo apt-get install ansible python-pip -y
|
||||
- sudo pip install docker-py==1.5.0
|
||||
# Pull docker image or build it
|
||||
- >
|
||||
if [ -f tests/Dockerfile.${DISTRIBUTION}_${DIST_VERSION} ]; then
|
||||
sudo docker build --rm=true --file=tests/Dockerfile.${DISTRIBUTION}_${DIST_VERSION}
|
||||
--tag ${DISTRIBUTION}:${DIST_VERSION} tests; else sudo docker pull ${DISTRIBUTION}:${DIST_VERSION}; fi
|
||||
- sudo ln -s ${PWD} /etc/ansible/roles/greendayonfire.mongodb
|
||||
install:
|
||||
- bash tests/scripts/before_install.sh
|
||||
|
||||
script:
|
||||
# Test 1
|
||||
- >
|
||||
sudo ansible-playbook -i tests/hosts tests/site.yml -e target=mongo1 -e mongodb_version=${MONGODB_VERSION} -e image_name=${DISTRIBUTION}:${DIST_VERSION}
|
||||
# Idempotence test
|
||||
- >
|
||||
sudo ansible-playbook -i tests/hosts tests/site.yml -e target=mongo1 -e mongodb_version=${MONGODB_VERSION} -e image_name=${DISTRIBUTION}:${DIST_VERSION}
|
||||
| grep -q 'changed=0.*failed=0'
|
||||
&& (echo 'Idempotence test: pass' && exit 0)
|
||||
|| (echo 'Idempotence test: fail' && exit 1)
|
||||
|
||||
# Delete all containers
|
||||
- sudo docker kill mongo{1,2,3} && docker rm mongo{1,2,3}
|
||||
|
||||
# Test 2
|
||||
- >
|
||||
sudo ansible-playbook -i tests/hosts tests/site.yml -e target=mongo1 -e image_name=${DISTRIBUTION}:${DIST_VERSION}
|
||||
-e mongodb_version=${MONGODB_VERSION} -e mongodb_security_authorization='enabled'
|
||||
# Idempotence test
|
||||
- >
|
||||
sudo ansible-playbook -i tests/hosts tests/site.yml -e target=mongo1 -e image_name=${DISTRIBUTION}:${DIST_VERSION}
|
||||
-e mongodb_version=${MONGODB_VERSION} -e mongodb_security_authorization='enabled'
|
||||
| grep -q 'changed=0.*failed=0'
|
||||
&& (echo 'Idempotence test: pass' && exit 0)
|
||||
|| (echo 'Idempotence test: fail' && exit 1)
|
||||
|
||||
# Delete all containers
|
||||
- sudo docker kill mongo{1,2,3} && docker rm mongo{1,2,3}
|
||||
|
||||
# Test 3
|
||||
- >
|
||||
sudo ansible-playbook -i tests/hosts tests/site.yml -e target=mongo -e image_name=${DISTRIBUTION}:${DIST_VERSION}
|
||||
-e mongodb_version=${MONGODB_VERSION} -e mongodb_replication_replset='testrs'
|
||||
# Idempotence test
|
||||
- >
|
||||
sudo ansible-playbook -i tests/hosts tests/site.yml -e target=mongo -e image_name=${DISTRIBUTION}:${DIST_VERSION}
|
||||
-e mongodb_version=${MONGODB_VERSION} -e mongodb_replication_replset='testrs'
|
||||
| grep -q 'changed=0.*failed=0'
|
||||
&& (echo 'Idempotence test: pass' && exit 0)
|
||||
|| (echo 'Idempotence test: fail' && exit 1)
|
||||
|
||||
# Delete all containers
|
||||
- sudo docker kill mongo{1,2,3} && docker rm mongo{1,2,3}
|
||||
|
||||
# Test 4
|
||||
- >
|
||||
sudo ansible-playbook -i tests/hosts tests/site.yml -e target=mongo -e image_name=${DISTRIBUTION}:${DIST_VERSION}
|
||||
-e mongodb_version=${MONGODB_VERSION} -e mongodb_replication_replset='testrs'
|
||||
-e mongodb_security_authorization='enabled'
|
||||
# Idempotence test
|
||||
- >
|
||||
sudo ansible-playbook -i tests/hosts tests/site.yml -e target=mongo -e image_name=${DISTRIBUTION}:${DIST_VERSION}
|
||||
-e mongodb_version=${MONGODB_VERSION} -e mongodb_replication_replset='testrs'
|
||||
-e mongodb_security_authorization='enabled'
|
||||
| grep -q 'changed=0.*failed=0'
|
||||
&& (echo 'Idempotence test: pass' && exit 0)
|
||||
|| (echo 'Idempotence test: fail' && exit 1)
|
||||
|
||||
- bash tests/scripts/test.sh
|
||||
|
11
README.md
11
README.md
@ -13,16 +13,15 @@ MongoDB support matrix:
|
||||
| Distribution | MongoDB 2.4 | MongoDB 2.6 | MongoDB 3.0 | MongoDB 3.2 | MongoDB 3.4 |
|
||||
| ------------ |:-----------:|:-----------:|:-----------:|:-----------:|:-----------:|
|
||||
| Ubuntu 14.04 | :no_entry: | :white_check_mark: | :white_check_mark: | :white_check_mark:| :x:|
|
||||
| Ubuntu 12.04 | :no_entry: | :white_check_mark: | :white_check_mark: | :white_check_mark:| :x:|
|
||||
| Ubuntu 16.04 | :no_entry: | :x: | :x: | :x:| :x:|
|
||||
| Debian 7.x | :no_entry: | :interrobang: | :interrobang: | :interrobang:| :x:|
|
||||
| Debian 8.x | :no_entry: | :x: | :x: | :x:| :x:|
|
||||
| Debian 9.x | :no_entry: | :x: | :x: | :x:| :x:|
|
||||
| RHEL 6.x | :no_entry: | :interrobang: | :interrobang: | :interrobang: | :interrobang: |
|
||||
| RHEL 7.x | :no_entry: | :interrobang: | :interrobang: | :interrobang: | :interrobang: |
|
||||
|
||||
:white_check_mark: - fully tested, should work fine
|
||||
:interrobang: - will be added testing suite soon
|
||||
:x: - don't have official support
|
||||
:white_check_mark: - fully tested, should work fine
|
||||
:interrobang: - will be added testing suite soon
|
||||
:x: - don't have official support
|
||||
:no_entry: - does't have support, because used old format of configuration files
|
||||
|
||||
#### Variables
|
||||
@ -89,7 +88,7 @@ mongodb_replication_oplogsize: 1024 # specifies a maximum size in
|
||||
|
||||
## setParameter options
|
||||
# Configure setParameter option.
|
||||
# Example :
|
||||
# Example :
|
||||
mongodb_set_parameters: { "enableLocalhostAuthBypass": "true", "authenticationMechanisms": "SCRAM-SHA-1,MONGODB-CR" }
|
||||
|
||||
# MMS Agent
|
||||
|
@ -1,13 +1,12 @@
|
||||
---
|
||||
|
||||
mongodb_package: mongodb-org
|
||||
mongodb_version: "3.4"
|
||||
mongodb_version: "3.6"
|
||||
mongodb_apt_keyserver: keyserver.ubuntu.com
|
||||
mongodb_apt_key_id:
|
||||
"2.6": "7F0CEB10"
|
||||
"3.0": "7F0CEB10"
|
||||
"3.2": "EA312927"
|
||||
"3.4": "0C49F3730359A14518585931BC711F9BA15703C6"
|
||||
"3.6": "2930ADAE8CAF5059EE73BB4B58712A2291FA4AD5"
|
||||
|
||||
mongodb_pymongo_from_pip: true # Install latest PyMongo via PIP or package manager
|
||||
|
||||
@ -41,7 +40,7 @@ mongodb_security_keyfile: /etc/mongodb-keyfile # Specify path to keyfile with
|
||||
mongodb_storage_dbpath: /data/db # Directory for datafiles
|
||||
# The storage engine for the mongod database. Available values:
|
||||
# 'mmapv1', 'wiredTiger'
|
||||
mongodb_storage_engine: "{{ 'mmapv1' if mongodb_version[0:3] == '3.0' else 'wiredTiger' }}"
|
||||
mongodb_storage_engine: "wiredTiger"
|
||||
# mmapv1 specific options
|
||||
mongodb_storage_quota_enforced: false # Limits each database to a certain number of files
|
||||
mongodb_storage_quota_maxfiles: 8 # Number of quota files per DB
|
||||
@ -95,8 +94,8 @@ mongodb_user_admin_password: passw0rd
|
||||
mongodb_root_admin_name: siteRootAdmin
|
||||
mongodb_root_admin_password: passw0rd
|
||||
|
||||
mongodb_root_backup_name: "backupuser"
|
||||
mongodb_root_backup_password: "passw0rd"
|
||||
mongodb_root_backup_name: backupuser
|
||||
mongodb_root_backup_password: passw0rd
|
||||
|
||||
# setParameter config
|
||||
mongodb_set_parameters:
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# (c) 2015-2016, Sergei Antipov, 2GIS LLC
|
||||
# (c) 2015-2018, Sergei Antipov, 2GIS LLC
|
||||
#
|
||||
# This file is part of Ansible
|
||||
#
|
||||
@ -23,7 +23,7 @@ module: mongodb_replication
|
||||
short_description: Adds or removes a node from a MongoDB Replica Set.
|
||||
description:
|
||||
- Adds or removes host from a MongoDB replica set. Initialize replica set if it needed.
|
||||
version_added: "2.2"
|
||||
version_added: "2.4"
|
||||
options:
|
||||
login_user:
|
||||
description:
|
||||
@ -105,7 +105,7 @@ options:
|
||||
default: present
|
||||
choices: [ "present", "absent" ]
|
||||
notes:
|
||||
- Requires the pymongo Python package on the remote host, version 3.0+. It
|
||||
- Requires the pymongo Python package on the remote host, version 3.2+. It
|
||||
can be installed using pip or the OS package manager. @see http://api.mongodb.org/python/current/installation.html
|
||||
requirements: [ "pymongo" ]
|
||||
author: "Sergei Antipov @UnderGreen"
|
||||
@ -166,11 +166,14 @@ else:
|
||||
# MongoDB module specific support methods.
|
||||
#
|
||||
def check_compatibility(module, client):
|
||||
if LooseVersion(PyMongoVersion) <= LooseVersion('3.0'):
|
||||
module.fail_json(msg='Note: you must use pymongo 3.0+')
|
||||
srv_info = client.server_info()
|
||||
if LooseVersion(srv_info['version']) >= LooseVersion('3.2') and LooseVersion(PyMongoVersion) <= LooseVersion('3.2'):
|
||||
module.fail_json(msg=' (Note: you must use pymongo 3.2+ with MongoDB >= 3.2)')
|
||||
if LooseVersion(PyMongoVersion) <= LooseVersion('3.2'):
|
||||
module.fail_json(msg='Note: you must use pymongo 3.2+')
|
||||
if LooseVersion(srv_info['version']) >= LooseVersion('3.4') and LooseVersion(PyMongoVersion) <= LooseVersion('3.4'):
|
||||
module.fail_json(msg='Note: you must use pymongo 3.4+ with MongoDB 3.4.x')
|
||||
if LooseVersion(srv_info['version']) >= LooseVersion('3.6') and LooseVersion(PyMongoVersion) <= LooseVersion('3.6'):
|
||||
module.fail_json(msg='Note: you must use pymongo 3.6+ with MongoDB 3.6.x')
|
||||
|
||||
|
||||
def check_members(state, module, client, host_name, host_port, host_type):
|
||||
admin_db = client['admin']
|
||||
@ -236,7 +239,7 @@ def add_host(module, client, host_name, host_port, host_type, timeout=180, **kwa
|
||||
cfg['members'].append(new_host)
|
||||
admin_db.command('replSetReconfig', cfg)
|
||||
return
|
||||
except (OperationFailure, AutoReconnect), e:
|
||||
except (OperationFailure, AutoReconnect) as e:
|
||||
timeout = timeout - 5
|
||||
if timeout <= 0:
|
||||
module.fail_json(msg='reached timeout while waiting for rs.reconfig(): %s' % str(e))
|
||||
@ -265,7 +268,7 @@ def remove_host(module, client, host_name, timeout=180):
|
||||
else:
|
||||
fail_msg = "couldn't find member with hostname: {0} in replica set members list".format(host_name)
|
||||
module.fail_json(msg=fail_msg)
|
||||
except (OperationFailure, AutoReconnect), e:
|
||||
except (OperationFailure, AutoReconnect) as e:
|
||||
timeout = timeout - 5
|
||||
if timeout <= 0:
|
||||
module.fail_json(msg='reached timeout while waiting for rs.reconfig(): %s' % str(e))
|
||||
@ -318,7 +321,7 @@ def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec = dict(
|
||||
login_user=dict(default=None),
|
||||
login_password=dict(default=None),
|
||||
login_password=dict(default=None, no_log=True),
|
||||
login_host=dict(default='localhost'),
|
||||
login_port=dict(default='27017'),
|
||||
replica_set=dict(default=None),
|
||||
@ -374,9 +377,9 @@ def main():
|
||||
wait_for_ok_and_master(module, client)
|
||||
replica_set_created = True
|
||||
module.exit_json(changed=True, host_name=host_name, host_port=host_port, host_type=host_type)
|
||||
except OperationFailure, e:
|
||||
except OperationFailure as e:
|
||||
module.fail_json(msg='Unable to initiate replica set: %s' % str(e))
|
||||
except ConnectionFailure, e:
|
||||
except ConnectionFailure as e:
|
||||
module.fail_json(msg='unable to connect to database: %s' % str(e))
|
||||
|
||||
check_compatibility(module, client)
|
||||
@ -394,13 +397,13 @@ def main():
|
||||
priority = float(module.params['priority']),
|
||||
slave_delay = module.params['slave_delay'],
|
||||
votes = module.params['votes'])
|
||||
except OperationFailure, e:
|
||||
except OperationFailure as e:
|
||||
module.fail_json(msg='Unable to add new member to replica set: %s' % str(e))
|
||||
|
||||
elif state == 'absent':
|
||||
try:
|
||||
remove_host(module, client, host_name)
|
||||
except OperationFailure, e:
|
||||
except OperationFailure as e:
|
||||
module.fail_json(msg='Unable to remove member of replica set: %s' % str(e))
|
||||
|
||||
module.exit_json(changed=True, host_name=host_name, host_port=host_port, host_type=host_type)
|
||||
|
@ -1,363 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# (c) 2012, Elliott Foster <elliott@fourkitchens.com>
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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 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:
|
||||
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=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 usefull 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" }
|
||||
|
||||
'''
|
||||
|
||||
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 check_compatibility(module, client):
|
||||
srv_info = client.server_info()
|
||||
if LooseVersion(srv_info['version']) >= LooseVersion('3.2') and LooseVersion(PyMongoVersion) <= LooseVersion('3.2'):
|
||||
module.fail_json(msg=' (Note: you must use pymongo 3.2+ with MongoDB >= 3.2)')
|
||||
elif LooseVersion(srv_info['version']) >= LooseVersion('3.0') and LooseVersion(PyMongoVersion) <= LooseVersion('2.8'):
|
||||
module.fail_json(msg=' (Note: you must use pymongo 2.8+ 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+ 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):
|
||||
for mongo_user in client["admin"].system.users.find():
|
||||
if mongo_user['user'] == user and 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:
|
||||
try:
|
||||
db.add_user(user, password, None, roles=roles)
|
||||
except OperationFailure, e:
|
||||
err_msg = str(e)
|
||||
module.fail_json(msg=err_msg)
|
||||
|
||||
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, basestring):
|
||||
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),
|
||||
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, type='bool'),
|
||||
roles=dict(default=None, type='list'),
|
||||
state=dict(default='present', choices=['absent', 'present']),
|
||||
update_password=dict(default="always", choices=["always", "on_create"]),
|
||||
),
|
||||
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']
|
||||
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))
|
||||
|
||||
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')
|
||||
|
||||
uinfo = user_find(client, user, db_name)
|
||||
if update_password != 'always' and 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)
|
||||
|
||||
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))
|
||||
|
||||
# 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 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()
|
@ -4,10 +4,10 @@ dependencies: []
|
||||
|
||||
galaxy_info:
|
||||
author: Sergei Antipov
|
||||
company: 2GIS
|
||||
company: Self-employed
|
||||
description: Manage MongoDB with authentication and replica sets
|
||||
license: GPLv2
|
||||
min_ansible_version: 2.0
|
||||
min_ansible_version: 2.4
|
||||
platforms:
|
||||
- name: Ubuntu
|
||||
versions:
|
||||
|
@ -32,8 +32,9 @@
|
||||
|
||||
- name: Create log if missing
|
||||
file: state=touch dest={{ mongodb_systemlog_path }} owner={{ mongodb_user }} group={{mongodb_user}} mode=0755
|
||||
when: logfile_stat is defined and not logfile_stat.stat.exists
|
||||
when: mongodb_systemlog_destination == "file"
|
||||
when: ( logfile_stat is defined
|
||||
and not logfile_stat.stat.exists
|
||||
and mongodb_systemlog_destination == "file" )
|
||||
|
||||
- name: Ensure dbpath directory
|
||||
file:
|
||||
|
@ -4,7 +4,7 @@
|
||||
stat: path=/sbin/init
|
||||
register: sbin_init
|
||||
changed_when: false
|
||||
always_run: yes # side-effect free, so it can be run in check-mode as well
|
||||
check_mode: no
|
||||
|
||||
- name: Establish some role-related facts
|
||||
set_fact:
|
||||
|
@ -7,15 +7,15 @@
|
||||
- "{{ ansible_os_family }}.yml"
|
||||
|
||||
- name: Include installation on Debian-based OS
|
||||
include: "install.{{ ansible_os_family | lower }}.yml"
|
||||
include_tasks: "install.{{ ansible_os_family | lower }}.yml"
|
||||
tags: [mongodb]
|
||||
|
||||
- name: Include configuration.yml
|
||||
include: configure.yml
|
||||
include_tasks: configure.yml
|
||||
tags: [mongodb]
|
||||
|
||||
- name: Include replication and auth configuration
|
||||
include: replication_init_auth.yml
|
||||
include_tasks: replication_init_auth.yml
|
||||
when: ( mongodb_replication_replset
|
||||
and mongodb_replication_replset != ''
|
||||
and mongodb_security_authorization == 'enabled'
|
||||
@ -23,7 +23,7 @@
|
||||
tags: [mongodb]
|
||||
|
||||
- name: Include replication configuration
|
||||
include: replication.yml
|
||||
include_tasks: replication.yml
|
||||
when: mongodb_replication_replset and mongodb_replication_replset != ''
|
||||
tags: [mongodb]
|
||||
|
||||
@ -33,7 +33,7 @@
|
||||
-p {{ mongodb_user_admin_password }} --port {{ mongodb_net_port }} --eval 'db.version()' admin
|
||||
register: mongodb_user_admin_check
|
||||
changed_when: false
|
||||
always_run: yes # side-effect free, so it can be run in check-mode as well
|
||||
check_mode: no
|
||||
ignore_errors: true
|
||||
when: ( mongodb_security_authorization == 'enabled'
|
||||
and (not mongodb_replication_replset
|
||||
@ -42,7 +42,7 @@
|
||||
tags: [mongodb]
|
||||
|
||||
- name: Include authorization configuration
|
||||
include: auth_initialization.yml
|
||||
include_tasks: auth_initialization.yml
|
||||
when: ( mongodb_security_authorization == 'enabled'
|
||||
and (not mongodb_replication_replset
|
||||
or mongodb_replication_replset == '')
|
||||
@ -88,6 +88,6 @@
|
||||
tags: [mongodb]
|
||||
|
||||
- name: Include MMS Agent configuration
|
||||
include: mms-agent.yml
|
||||
include_tasks: mms-agent.yml
|
||||
when: mongodb_mms_api_key != ""
|
||||
tags: [mongodb]
|
||||
|
@ -16,7 +16,7 @@
|
||||
register: mongodb_replica_init
|
||||
ignore_errors: true
|
||||
|
||||
- include: auth_initialization.yml
|
||||
- include_tasks: auth_initialization.yml
|
||||
when: mongodb_replica_init|failed
|
||||
|
||||
- name: Replication configuration | 2nd Pt
|
||||
|
@ -1,53 +0,0 @@
|
||||
FROM ubuntu:12.04
|
||||
|
||||
# much of this was gleaned from https://github.com/lxc/lxc/blob/lxc-0.8.0/templates/lxc-ubuntu.in
|
||||
# and then heavily modified and hacked like crazy
|
||||
|
||||
# we're going to want this bad boy installed so we can connect :)
|
||||
RUN apt-get update && apt-get install -y ssh python
|
||||
|
||||
ADD builds/init-fake.conf /etc/init/fake-container-events.conf
|
||||
|
||||
# undo some leet hax of the base image
|
||||
RUN rm /usr/sbin/policy-rc.d; \
|
||||
rm /sbin/initctl; dpkg-divert --rename --remove /sbin/initctl
|
||||
|
||||
# generate a nice UTF-8 locale for our use
|
||||
RUN locale-gen en_US.UTF-8 && update-locale LANG=en_US.UTF-8
|
||||
|
||||
# remove some pointless services
|
||||
RUN /usr/sbin/update-rc.d -f ondemand remove; \
|
||||
for f in \
|
||||
/etc/init/u*.conf \
|
||||
/etc/init/mounted-dev.conf \
|
||||
/etc/init/mounted-proc.conf \
|
||||
/etc/init/mounted-run.conf \
|
||||
/etc/init/mounted-tmp.conf \
|
||||
/etc/init/mounted-var.conf \
|
||||
/etc/init/hostname.conf \
|
||||
/etc/init/networking.conf \
|
||||
/etc/init/tty*.conf \
|
||||
/etc/init/plymouth*.conf \
|
||||
/etc/init/hwclock*.conf \
|
||||
/etc/init/module*.conf\
|
||||
; do \
|
||||
dpkg-divert --local --rename --add "$f"; \
|
||||
done; \
|
||||
echo '# /lib/init/fstab: cleared out for bare-bones Docker' > /lib/init/fstab
|
||||
|
||||
# small fix for SSH in 13.10 (that's harmless everywhere else)
|
||||
RUN sed -ri 's/^session\s+required\s+pam_loginuid.so$/session optional pam_loginuid.so/' /etc/pam.d/sshd
|
||||
|
||||
RUN sed -ri 's/^PermitRootLogin\s+.*/PermitRootLogin yes/' /etc/ssh/sshd_config
|
||||
|
||||
# let Upstart know it's in a container
|
||||
ENV container docker
|
||||
|
||||
# set a cheap, simple password for great convenience
|
||||
RUN echo 'root:docker.io' | chpasswd
|
||||
|
||||
# we can has SSH
|
||||
EXPOSE 22
|
||||
|
||||
# pepare for takeoff
|
||||
CMD ["/sbin/init"]
|
10
tests/hosts
10
tests/hosts
@ -1,13 +1,13 @@
|
||||
[local]
|
||||
localhost ansible_connection=local ansible_python_interpreter=python2
|
||||
localhost ansible_connection=local ansible_python_interpreter=python
|
||||
|
||||
[mongo_master]
|
||||
mongo1 ansible_connection=docker ansible_user=root ansible_python_interpreter=python2
|
||||
mongo1 ansible_connection=docker ansible_user=root ansible_python_interpreter=python
|
||||
|
||||
[mongo_replicas]
|
||||
mongo2 ansible_connection=docker ansible_user=root ansible_python_interpreter=python2
|
||||
mongo3 ansible_connection=docker ansible_user=root ansible_python_interpreter=python2
|
||||
mongo2 ansible_connection=docker ansible_user=root ansible_python_interpreter=python
|
||||
mongo3 ansible_connection=docker ansible_user=root ansible_python_interpreter=python
|
||||
|
||||
[mongo:children]
|
||||
mongo_master
|
||||
mongo_replicas
|
||||
mongo_replicas
|
||||
|
25
tests/scripts/before_install.sh
Normal file
25
tests/scripts/before_install.sh
Normal file
@ -0,0 +1,25 @@
|
||||
#!/usr/bin/env bash
|
||||
# -*- mode: sh; -*-
|
||||
|
||||
# File: before_install.sh
|
||||
# Time-stamp: <2018-02-15 15:54:06>
|
||||
# Copyright (C) 2018 Sergei Antipov
|
||||
# Description:
|
||||
|
||||
# set -o xtrace
|
||||
set -o nounset
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
|
||||
# Latest Ansible install
|
||||
pip install docker-py ansible
|
||||
|
||||
# Pull docker image or build it
|
||||
if [ -f tests/Dockerfile.${DISTRIBUTION}_${DIST_VERSION} ]
|
||||
then
|
||||
docker build --rm=true --file=tests/Dockerfile.${DISTRIBUTION}_${DIST_VERSION} --tag ${DISTRIBUTION}:${DIST_VERSION} tests
|
||||
else
|
||||
docker pull ${DISTRIBUTION}:${DIST_VERSION}
|
||||
fi
|
||||
|
||||
ln -s ${PWD} tests/greendayonfire.mongodb
|
45
tests/scripts/test.sh
Normal file
45
tests/scripts/test.sh
Normal file
@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env bash
|
||||
# -*- mode: sh; -*-
|
||||
|
||||
# File: test.sh
|
||||
# Time-stamp: <2018-02-15 17:02:22>
|
||||
# Copyright (C) 2018 Sergei Antipov
|
||||
# Description:
|
||||
|
||||
# set -o xtrace
|
||||
set -o nounset
|
||||
set -o errexit
|
||||
|
||||
# Test 1
|
||||
ansible-playbook -i tests/hosts tests/site.yml -e target=mongo1 -e mongodb_version=${MONGODB_VERSION} -e image_name=${DISTRIBUTION}:${DIST_VERSION}
|
||||
# Idempotence test
|
||||
ansible-playbook -i tests/hosts tests/site.yml -e target=mongo1 -e mongodb_version=${MONGODB_VERSION} -e image_name=${DISTRIBUTION}:${DIST_VERSION} | \
|
||||
grep -q 'changed=0.*failed=0' && \
|
||||
(echo 'Idempotence test: pass' && exit 0) || (echo 'Idempotence test: fail' && exit 1)
|
||||
# Delete all containers
|
||||
docker kill mongo{1,2,3} && docker rm mongo{1,2,3}
|
||||
|
||||
# Test 2
|
||||
ansible-playbook -i tests/hosts tests/site.yml -e target=mongo1 -e image_name=${DISTRIBUTION}:${DIST_VERSION} -e mongodb_version=${MONGODB_VERSION} -e mongodb_security_authorization='enabled'
|
||||
# Idempotence test
|
||||
ansible-playbook -i tests/hosts tests/site.yml -e target=mongo1 -e image_name=${DISTRIBUTION}:${DIST_VERSION} -e mongodb_version=${MONGODB_VERSION} -e mongodb_security_authorization='enabled' \
|
||||
| grep -q 'changed=0.*failed=0' \
|
||||
&& (echo 'Idempotence test: pass' && exit 0) || (echo 'Idempotence test: fail' && exit 1)
|
||||
# Delete all containers
|
||||
docker kill mongo{1,2,3} && docker rm mongo{1,2,3}
|
||||
|
||||
# Test 3
|
||||
ansible-playbook -i tests/hosts tests/site.yml -e target=mongo -e image_name=${DISTRIBUTION}:${DIST_VERSION} -e mongodb_version=${MONGODB_VERSION} -e mongodb_replication_replset='testrs'
|
||||
# Idempotence test
|
||||
ansible-playbook -i tests/hosts tests/site.yml -e target=mongo -e image_name=${DISTRIBUTION}:${DIST_VERSION} -e mongodb_version=${MONGODB_VERSION} -e mongodb_replication_replset='testrs' \
|
||||
| grep -q 'changed=0.*failed=0' \
|
||||
&& (echo 'Idempotence test: pass' && exit 0) || (echo 'Idempotence test: fail' && exit 1)
|
||||
# Delete all containers
|
||||
docker kill mongo{1,2,3} && docker rm mongo{1,2,3}
|
||||
|
||||
# Test 4
|
||||
ansible-playbook -i tests/hosts tests/site.yml -e target=mongo -e image_name=${DISTRIBUTION}:${DIST_VERSION} -e mongodb_version=${MONGODB_VERSION} -e mongodb_replication_replset='testrs' -e mongodb_security_authorization='enabled'
|
||||
# Idempotence test
|
||||
ansible-playbook -i tests/hosts tests/site.yml -e target=mongo -e image_name=${DISTRIBUTION}:${DIST_VERSION} -e mongodb_version=${MONGODB_VERSION} -e mongodb_replication_replset='testrs' -e mongodb_security_authorization='enabled' \
|
||||
| grep -q 'changed=0.*failed=0' \
|
||||
&& (echo 'Idempotence test: pass' && exit 0) || (echo 'Idempotence test: fail' && exit 1)
|
@ -6,7 +6,7 @@
|
||||
gather_facts: no
|
||||
tasks:
|
||||
- name: Run MongoDB cluster in Docker
|
||||
docker:
|
||||
docker_container:
|
||||
name: "{{ item }}"
|
||||
image: "{{ image_name }}"
|
||||
command: "/sbin/init"
|
||||
@ -31,4 +31,3 @@
|
||||
roles:
|
||||
- role: greendayonfire.mongodb
|
||||
when: "'mongo_replicas' in group_names"
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
---
|
||||
mongodb_repository:
|
||||
"2.6": "deb http://downloads-distro.mongodb.org/repo/debian-sysvinit dist 10gen"
|
||||
"3.0": "deb http://repo.mongodb.org/apt/debian wheezy/mongodb-org/3.0 main"
|
||||
"3.2": "deb http://repo.mongodb.org/apt/debian {{ ansible_distribution_release }}/mongodb-org/3.2 main"
|
||||
"3.4": "deb http://repo.mongodb.org/apt/debian {{ ansible_distribution_release }}/mongodb-org/3.4 main"
|
||||
"3.6": "deb http://repo.mongodb.org/apt/debian {{ ansible_distribution_release }}/mongodb-org/3.6 main"
|
||||
|
@ -1,13 +1,13 @@
|
||||
---
|
||||
|
||||
mongodb_repository:
|
||||
"2.6": "http://downloads-distro.mongodb.org/repo/redhat/os/$basearch/"
|
||||
"3.0": "https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.0/$basearch/"
|
||||
"3.2": "https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.2/$basearch/"
|
||||
"3.4": "https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.4/$basearch/"
|
||||
"3.6": "https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.6/$basearch/"
|
||||
|
||||
mongodb_repository_gpgkey:
|
||||
"3.2": "https://www.mongodb.org/static/pgp/server-3.2.asc"
|
||||
"3.4": "https://www.mongodb.org/static/pgp/server-3.4.asc"
|
||||
"3.6": "https://www.mongodb.org/static/pgp/server-3.6.asc"
|
||||
|
||||
mongodb_pidfile_path: "{{ '/var/run/mongodb/mongod.pid' if ('mongodb-org' in mongodb_package) else '' }}"
|
||||
|
@ -1,6 +1,5 @@
|
||||
---
|
||||
mongodb_repository:
|
||||
"2.6": "deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen"
|
||||
"3.0": "deb http://repo.mongodb.org/apt/ubuntu {{ ansible_distribution_release }}/mongodb-org/3.0 multiverse"
|
||||
"3.2": "deb http://repo.mongodb.org/apt/ubuntu {{ ansible_distribution_release }}/mongodb-org/3.2 multiverse"
|
||||
"3.4": "deb http://repo.mongodb.org/apt/ubuntu {{ ansible_distribution_release }}/mongodb-org/3.4 multiverse"
|
||||
"3.6": "deb http://repo.mongodb.org/apt/ubuntu {{ ansible_distribution_release }}/mongodb-org/3.6 multiverse"
|
||||
|
Loading…
x
Reference in New Issue
Block a user