diff --git a/REFERENCE.md b/REFERENCE.md index 1169a603d..9883f50e1 100644 --- a/REFERENCE.md +++ b/REFERENCE.md @@ -127,6 +127,7 @@ The following parameters are available in the `mongodb::globals` class: * [`server_package_name`](#-mongodb--globals--server_package_name) * [`client_package_name`](#-mongodb--globals--client_package_name) +* [`client_version`](#-mongodb--globals--client_version) * [`mongod_service_manage`](#-mongodb--globals--mongod_service_manage) * [`service_enable`](#-mongodb--globals--service_enable) * [`service_ensure`](#-mongodb--globals--service_ensure) @@ -168,6 +169,14 @@ If not specified, the module will use whatever service name is the default for y Default value: `undef` +##### `client_version` + +Data type: `Any` + +Version of the client package to install. + +Default value: `undef` + ##### `mongod_service_manage` Data type: `Any` diff --git a/lib/facter/is_master.rb b/lib/facter/is_master.rb index 40ce49e59..6aeea3c01 100644 --- a/lib/facter/is_master.rb +++ b/lib/facter/is_master.rb @@ -39,17 +39,17 @@ def get_options_from_config(file) Facter.add('mongodb_is_master') do setcode do - if %w[mongo mongod].all? { |m| Facter::Util::Resolution.which m } + if %w[mongosh mongod].all? { |m| Facter::Util::Resolution.which m } file = mongod_conf_file if file options = get_options_from_config(file) - e = File.exist?('/root/.mongorc.js') ? 'load(\'/root/.mongorc.js\'); ' : '' + e = File.exist?('/root/.mongoshrc.js') ? 'load(\'/root/.mongoshrc.js\'); ' : '' # Check if the mongodb server is responding: - Facter::Core::Execution.exec("mongo --quiet #{options} --eval \"#{e}printjson(db.adminCommand({ ping: 1 }))\"") + Facter::Core::Execution.exec("mongosh --quiet #{options} --eval \"#{e}EJSON.stringify(db.adminCommand({ ping: 1 }))\"") if $CHILD_STATUS.success? - Facter::Core::Execution.exec("mongo --quiet #{options} --eval \"#{e}db.isMaster().ismaster\"") + Facter::Core::Execution.exec("mongosh --quiet #{options} --eval \"#{e}db.isMaster().ismaster\"") else 'not_responding' end diff --git a/lib/puppet/provider/mongodb.rb b/lib/puppet/provider/mongodb.rb index 81e4ed7d8..b8f59cb2c 100644 --- a/lib/puppet/provider/mongodb.rb +++ b/lib/puppet/provider/mongodb.rb @@ -8,15 +8,15 @@ class Puppet::Provider::Mongodb < Puppet::Provider # Without initvars commands won't work. initvars - commands mongo: 'mongo' + commands mongosh: 'mongosh' # Optional defaults file - def self.mongorc_file - "load('#{Facter.value(:root_home)}/.mongorc.js'); " if File.file?("#{Facter.value(:root_home)}/.mongorc.js") + def self.mongoshrc_file + "load('#{Facter.value(:root_home)}/.mongoshrc.js'); " if File.file?("#{Facter.value(:root_home)}/.mongoshrc.js") end - def mongorc_file - self.class.mongorc_file + def mongoshrc_file + self.class.mongoshrc_file end def self.mongod_conf_file @@ -74,7 +74,7 @@ def self.tls_invalid_hostnames(config = nil) config['tlsallowInvalidHostnames'] end - def self.mongo_cmd(db, host, cmd) + def self.mongosh_cmd(db, host, cmd) config = mongo_conf args = [db, '--quiet', '--host', host] @@ -101,7 +101,7 @@ def self.mongo_cmd(db, host, cmd) end args += ['--eval', cmd] - mongo(args) + mongosh(args) end def self.conn_string @@ -138,7 +138,7 @@ def self.conn_string def self.db_ismaster cmd_ismaster = 'db.isMaster().ismaster' db = 'admin' - res = mongo_cmd(db, conn_string, cmd_ismaster).to_s.split(%r{\n}).last.chomp + res = mongosh_cmd(db, conn_string, cmd_ismaster).to_s.split(%r{\n}).last.chomp res.eql?('true') end @@ -155,14 +155,14 @@ def self.auth_enabled(config = nil) def self.mongo_eval(cmd, db = 'admin', retries = 10, host = nil) retry_count = retries retry_sleep = 3 - cmd = mongorc_file + cmd if mongorc_file + cmd = mongoshrc_file + cmd if mongoshrc_file out = nil begin out = if host - mongo_cmd(db, host, cmd) + mongosh_cmd(db, host, cmd) else - mongo_cmd(db, conn_string, cmd) + mongosh_cmd(db, conn_string, cmd) end rescue StandardError => e retry_count -= 1 @@ -173,7 +173,7 @@ def self.mongo_eval(cmd, db = 'admin', retries = 10, host = nil) end end - raise Puppet::ExecutionFailure, "Could not evaluate MongoDB shell command: #{cmd}" unless out + raise Puppet::ExecutionFailure, "Could not evaluate MongoDB shell command: #{cmd}, with: #{e.message}" unless out Puppet::Util::MongodbOutput.sanitize(out) end diff --git a/lib/puppet/provider/mongodb_database/mongodb.rb b/lib/puppet/provider/mongodb_database/mongodb.rb index 5dabe4365..a03cd6294 100644 --- a/lib/puppet/provider/mongodb_database/mongodb.rb +++ b/lib/puppet/provider/mongodb_database/mongodb.rb @@ -9,8 +9,8 @@ def self.instances require 'json' - pre_cmd = 'try { rs.secondaryOk() } catch (err) { rs.slaveOk() }' - dbs = JSON.parse mongo_eval("#{pre_cmd};printjson(db.getMongo().getDBs())") + pre_cmd = 'db.getMongo().setReadPref("primaryPreferred")' + dbs = JSON.parse mongo_eval("#{pre_cmd};EJSON.stringify(db.getMongo().getDBs())") dbs['databases'].map do |db| new(name: db['name'], diff --git a/lib/puppet/provider/mongodb_replset/mongo.rb b/lib/puppet/provider/mongodb_replset/mongo.rb index 7837533e2..98cc89404 100644 --- a/lib/puppet/provider/mongodb_replset/mongo.rb +++ b/lib/puppet/provider/mongodb_replset/mongo.rb @@ -153,31 +153,32 @@ def get_hosts_status(members) members.select do |member| host = member['host'] Puppet.debug "Checking replicaset member #{host} ..." - status = rs_status(host) - raise Puppet::Error, "Can't configure replicaset #{name}, host #{host} is not supposed to be part of a replicaset." if status.key?('errmsg') && status['errmsg'] == 'not running with --replSet' - - if auth_enabled && status.key?('errmsg') && (status['errmsg'].include?('unauthorized') || status['errmsg'].include?('not authorized') || status['errmsg'].include?('requires authentication')) - Puppet.warning "Host #{host} is available, but you are unauthorized because of authentication is enabled: #{auth_enabled}" - alive.push(member) - end - - if status.key?('errmsg') && status['errmsg'].include?('no replset config has been received') - Puppet.debug 'Mongo v4 rs.status() RS not initialized output' - alive.push(member) - end - - if status.key?('set') - raise Puppet::Error, "Can't configure replicaset #{name}, host #{host} is already part of another replicaset." if status['set'] != name - - # This node is alive and supposed to be a member of our set - Puppet.debug "Host #{host} is available for replset #{status['set']}" - alive.push(member) - elsif status.key?('info') - Puppet.debug "Host #{host} is alive but unconfigured: #{status['info']}" - alive.push(member) + begin + status = rs_status(host) + + if status.key?('set') + raise Puppet::Error, "Can't configure replicaset #{name}, host #{host} is already part of another replicaset." if status['set'] != name + + # This node is alive and supposed to be a member of our set + Puppet.debug "Host #{host} is available for replset #{status['set']}" + alive.push(member) + elsif status.key?('info') + Puppet.debug "Host #{host} is alive but unconfigured: #{status['info']}" + alive.push(member) + end + rescue Puppet::ExecutionFailure => e + raise Puppet::Error, "Can't configure replicaset #{name}, host #{host} is not supposed to be part of a replicaset." if e.message =~ %r{not running with --replSet} + + if auth_enabled && (e.message.include?('unauthorized') || e.message.include?('not authorized') || e.message.include?('requires authentication')) + Puppet.warning "Host #{host} is available, but you are unauthorized because of authentication is enabled: #{auth_enabled}" + alive.push(member) + elsif e.message.include?('no replset config has been received') + Puppet.debug 'Mongo v4 rs.status() RS not initialized output' + alive.push(member) + else + Puppet.warning "Can't connect to replicaset member #{host}." + end end - rescue Puppet::ExecutionFailure - Puppet.warning "Can't connect to replicaset member #{host}." end alive.uniq! dead = members - alive @@ -383,7 +384,7 @@ def mongo_command(command, host, retries = 4) def self.mongo_command(command, host = nil, retries = 4) begin - output = mongo_eval("printjson(#{command})", 'admin', retries, host) + output = mongo_eval("EJSON.stringify(#{command})", 'admin', retries, host) rescue Puppet::ExecutionFailure => e Puppet.debug "Got an exception: #{e}" raise diff --git a/lib/puppet/provider/mongodb_shard/mongo.rb b/lib/puppet/provider/mongodb_shard/mongo.rb index 283d6cce2..6347bf59b 100644 --- a/lib/puppet/provider/mongodb_shard/mongo.rb +++ b/lib/puppet/provider/mongodb_shard/mongo.rb @@ -13,7 +13,7 @@ mk_resource_methods - commands mongo: 'mongo' + commands mongosh: 'mongosh' def initialize(value = {}) super(value) @@ -152,8 +152,8 @@ def self.mongo_command(command, host = nil, _retries = 4) args = [] args << '--quiet' args << ['--host', host] if host - args << ['--eval', "printjson(#{command})"] - output = mongo(args.flatten) + args << ['--eval', "EJSON.stringify(#{command})"] + output = mongosh(args.flatten) rescue Puppet::ExecutionFailure => e raise unless e =~ %r{Error: couldn't connect to server} && wait <= (2**max_wait) diff --git a/lib/puppet/provider/mongodb_user/mongodb.rb b/lib/puppet/provider/mongodb_user/mongodb.rb index d9db0fa45..7eeb79eba 100644 --- a/lib/puppet/provider/mongodb_user/mongodb.rb +++ b/lib/puppet/provider/mongodb_user/mongodb.rb @@ -10,13 +10,12 @@ def self.instances require 'json' if db_ismaster - script = 'printjson(db.system.users.find().toArray())' + script = 'EJSON.stringify(db.system.users.find().toArray())' # A hack to prevent prefetching failures until admin user is created - script = "try {#{script}} catch (e) { if (e.message.match(/not authorized on admin/)) { 'not authorized on admin' } else {throw e}}" if auth_enabled + script = "try {#{script}} catch (e) { if (e.message.match(/requires authentication/) || e.message.match(/not authorized on admin/)) { 'not authorized on admin' } else {throw e}}" if auth_enabled out = mongo_eval(script) - - return [] if auth_enabled && out.include?('not authorized on admin') + return [] if auth_enabled && (out.include?('requires authentication') || out.include?('not authorized on admin')) users = JSON.parse out diff --git a/manifests/client/params.pp b/manifests/client/params.pp index 554345997..4207921c9 100644 --- a/manifests/client/params.pp +++ b/manifests/client/params.pp @@ -3,16 +3,10 @@ # @api private # class mongodb::client::params inherits mongodb::globals { - $package_ensure = pick($mongodb::globals::version, 'present') + $package_ensure = pick($mongodb::globals::client_version, 'present') $manage_package = pick($mongodb::globals::manage_package, $mongodb::globals::manage_package_repo, false) - if $manage_package { - $package_name = "mongodb-${mongodb::globals::edition}-shell" - } else { - $package_name = $facts['os']['family'] ? { - 'Debian' => 'mongodb-clients', - 'Redhat' => "mongodb-${mongodb::globals::edition}-shell", - default => 'mongodb', - } - } + # the new mongosh package is the same for all distros. + # and it follows its own versioning + $package_name = 'mongodb-mongosh' } diff --git a/manifests/globals.pp b/manifests/globals.pp index 6e32eb432..191207f3c 100644 --- a/manifests/globals.pp +++ b/manifests/globals.pp @@ -36,6 +36,8 @@ # This setting can be used to specify the name of the client package that should be installed. # If not specified, the module will use whatever service name is the default for your OS distro. # +# @param client_version +# Version of the client package to install. # @param mongod_service_manage # This setting can be used to override the default management of the mongod service. # By default the module will manage the mongod process. @@ -118,6 +120,7 @@ class mongodb::globals ( $server_package_name = undef, $client_package_name = undef, + $client_version = undef, $mongod_service_manage = undef, $service_enable = undef, diff --git a/manifests/params.pp b/manifests/params.pp index 18aab19b9..552b810dd 100644 --- a/manifests/params.pp +++ b/manifests/params.pp @@ -22,7 +22,7 @@ ] $handle_creds = true $store_creds = false - $rcfile = "${facts['root_home']}/.mongorc.js" + $rcfile = "${facts['root_home']}/.mongoshrc.js" $dbpath_fix = false $manage_package = pick($mongodb::globals::manage_package, $mongodb::globals::manage_package_repo, false) diff --git a/manifests/server/config.pp b/manifests/server/config.pp index 289cefe29..f4f1531fd 100644 --- a/manifests/server/config.pp +++ b/manifests/server/config.pp @@ -179,7 +179,7 @@ if $handle_creds { file { $rcfile: ensure => file, - content => template('mongodb/mongorc.js.erb'), + content => template('mongodb/mongoshrc.js.erb'), owner => 'root', group => 'root', mode => '0600', diff --git a/spec/acceptance/database_spec.rb b/spec/acceptance/database_spec.rb index 100c21892..023f40fa0 100644 --- a/spec/acceptance/database_spec.rb +++ b/spec/acceptance/database_spec.rb @@ -23,8 +23,8 @@ class { 'mongodb::server': } end it 'creates the databases' do - shell("mongo testdb1 --eval 'printjson(db.getMongo().getDBs())'") - shell("mongo testdb2 --eval 'printjson(db.getMongo().getDBs())'") + shell("mongosh testdb1 --eval 'EJSON.stringify(db.getMongo().getDBs())'") + shell("mongosh testdb2 --eval 'EJSON.stringify(db.getMongo().getDBs())'") end end @@ -50,8 +50,8 @@ class { 'mongodb::server': end it 'creates the database' do - shell("mongo testdb1 --port 27018 --eval 'printjson(db.getMongo().getDBs())'") - shell("mongo testdb2 --port 27018 --eval 'printjson(db.getMongo().getDBs())'") + shell("mongosh testdb1 --port 27018 --eval 'EJSON.stringify(db.getMongo().getDBs())'") + shell("mongosh testdb2 --port 27018 --eval 'EJSON.stringify(db.getMongo().getDBs())'") end end end diff --git a/spec/acceptance/mongos_spec.rb b/spec/acceptance/mongos_spec.rb index b1839027d..2d821aceb 100644 --- a/spec/acceptance/mongos_spec.rb +++ b/spec/acceptance/mongos_spec.rb @@ -46,7 +46,7 @@ class { 'mongodb::server': it { is_expected.to be_listening } end - describe command('mongo --version') do + describe command('mongod --version') do its(:exit_status) { is_expected.to eq 0 } end end diff --git a/spec/acceptance/replset_spec.rb b/spec/acceptance/replset_spec.rb index 97f9c9bc9..954138378 100644 --- a/spec/acceptance/replset_spec.rb +++ b/spec/acceptance/replset_spec.rb @@ -6,7 +6,7 @@ describe 'mongodb_replset resource' do after :all do # Have to drop the DB to disable replsets for further testing - on hosts, %{mongo local --verbose --eval 'db.dropDatabase()'} + on hosts, %{mongosh local --verbose --eval 'db.dropDatabase()'} pp = <<-EOS class { 'mongodb::globals': } @@ -48,7 +48,7 @@ class { 'mongodb::client': } } EOS apply_manifest_on(hosts_as('master'), pp, catch_failures: true) - on(hosts_as('master'), 'mongo --quiet --eval "printjson(rs.conf())"') do |r| + on(hosts_as('master'), 'mongosh --quiet --eval "EJSON.stringify(rs.conf())"') do |r| expect(r.stdout).to match %r{#{hosts[0]}:27017} expect(r.stdout).to match %r{#{hosts[1]}:27017} end @@ -56,18 +56,18 @@ class { 'mongodb::client': } it 'inserts data on the master' do sleep(30) - on hosts_as('master'), %{mongo --verbose --eval 'db.test.save({name:"test1",value:"some value"})'} + on hosts_as('master'), %{mongosh --verbose --eval 'db.test.save({name:"test1",value:"some value"})'} end it 'checks the data on the master' do - on hosts_as('master'), %{mongo --verbose --eval 'printjson(db.test.findOne({name:"test1"}))'} do |r| + on hosts_as('master'), %{mongosh --verbose --eval 'EJSON.stringify(db.test.findOne({name:"test1"}))'} do |r| expect(r.stdout).to match %r{some value} end end it 'checks the data on the slave' do sleep(10) - on hosts_as('slave'), %{mongo --verbose --eval 'try { rs.secondaryOk() } catch (err) { rs.slaveOk() }; printjson(db.test.findOne({name:"test1"}))'} do |r| + on hosts_as('slave'), %{mongosh --verbose --eval 'db.getMongo().setReadPref("primaryPreferred"); EJSON.stringify(db.test.findOne({name:"test1"}))'} do |r| expect(r.stdout).to match %r{some value} end end @@ -76,7 +76,7 @@ class { 'mongodb::client': } describe 'mongodb_replset resource with auth => true' do after :all do # Have to drop the DB to disable replsets for further testing - on hosts, %{mongo local --verbose --eval 'db.dropDatabase()'} + on hosts, %{mongosh local --verbose --eval 'db.dropDatabase()'} pp = <<-EOS class { 'mongodb::globals': } @@ -177,7 +177,7 @@ class { 'mongodb::server': EOS apply_manifest_on(hosts_as('master'), pp, catch_failures: true) apply_manifest_on(hosts_as('master'), pp, catch_changes: true) - on(hosts_as('master'), 'mongo --quiet --eval "load(\'/root/.mongorc.js\');printjson(rs.conf())"') do |r| + on(hosts_as('master'), 'mongosh --quiet --eval "load(\'/root/.mongoshrc.js\');EJSON.stringify(rs.conf())"') do |r| expect(r.stdout).to match %r{#{hosts[0]}:27017} expect(r.stdout).to match %r{#{hosts[1]}:27017} end @@ -185,18 +185,18 @@ class { 'mongodb::server': it 'inserts data on the master' do sleep(30) - on hosts_as('master'), %{mongo test --verbose --eval 'load("/root/.mongorc.js");db.dummyData.insert({"created_by_puppet": 1})'} + on hosts_as('master'), %{mongosh test --verbose --eval 'load("/root/.mongoshrc.js");db.dummyData.insert({"created_by_puppet": 1})'} end it 'checks the data on the master' do - on hosts_as('master'), %{mongo test --verbose --eval 'load("/root/.mongorc.js");printjson(db.dummyData.findOne())'} do |r| + on hosts_as('master'), %{mongosh test --verbose --eval 'load("/root/.mongoshrc.js");EJSON.stringify(db.dummyData.findOne())'} do |r| expect(r.stdout).to match %r{created_by_puppet} end end it 'checks the data on the slave' do sleep(10) - on hosts_as('slave'), %{mongo test --verbose --eval 'load("/root/.mongorc.js");try { rs.secondaryOk() } catch (err) { rs.slaveOk() };printjson(db.dummyData.findOne())'} do |r| + on hosts_as('slave'), %{mongosh test --verbose --eval 'load("/root/.mongoshrc.js");db.getMongo().setReadPref("primaryPreferred");EJSON.stringify(db.dummyData.findOne())'} do |r| expect(r.stdout).to match %r{created_by_puppet} end end diff --git a/spec/acceptance/server_spec.rb b/spec/acceptance/server_spec.rb index 2609d2423..9ad85a906 100644 --- a/spec/acceptance/server_spec.rb +++ b/spec/acceptance/server_spec.rb @@ -35,7 +35,7 @@ class { 'mongodb::server': } it { is_expected.to be_listening } end - describe command('mongo --version') do + describe command('mongod --version') do its(:exit_status) { is_expected.to eq 0 } end end @@ -120,11 +120,11 @@ class { 'mongodb::client': } it { is_expected.to be_listening } end - describe command('mongo --quiet --eval "db.serverCmdLineOpts().code"') do - its(:stdout) { is_expected.to match '13' } + describe command('mongosh --quiet --eval "db.serverCmdLineOpts().ok"') do + its(:stderr) { is_expected.to match %r{requires authentication} } end - describe file('/root/.mongorc.js') do + describe file('/root/.mongoshrc.js') do it { is_expected.to be_file } it { is_expected.to be_owned_by 'root' } it { is_expected.to be_grouped_into 'root' } @@ -132,12 +132,12 @@ class { 'mongodb::client': } it { is_expected.to contain 'db.auth(\'admin\', \'password\')' } end - describe command("mongo admin --quiet --eval \"load('/root/.mongorc.js');printjson(db.getUser('admin')['customData'])\"") do + describe command("mongosh admin --quiet --eval \"load('/root/.mongoshrc.js');EJSON.stringify(db.getUser('admin')['customData'])\"") do its(:exit_status) { is_expected.to eq 0 } - its(:stdout) { is_expected.to match "{ \"createdBy\" : \"Puppet Mongodb_user['User admin on db admin']\" }\n" } + its(:stdout) { is_expected.to match "{\"createdBy\":\"Puppet Mongodb_user['User admin on db admin']\"}\n" } end - describe command('mongo --version') do + describe command('mongod --version') do its(:exit_status) { is_expected.to eq 0 } end end diff --git a/spec/acceptance/sharding_spec.rb b/spec/acceptance/sharding_spec.rb index d659c1eb6..ea8815ebc 100644 --- a/spec/acceptance/sharding_spec.rb +++ b/spec/acceptance/sharding_spec.rb @@ -46,7 +46,7 @@ class { 'mongodb::client': } EOS apply_manifest_on(hosts_as('router'), pp, catch_failures: true) - on(hosts_as('router'), 'mongo --quiet --eval "printjson(sh.status())"') do |r| + on(hosts_as('router'), 'mongosh --quiet --eval "EJSON.stringify(sh.status())"') do |r| expect(r.stdout).to match %r{foo/shard:27018} expect(r.stdout).to match %r{foo\.toto} end diff --git a/spec/acceptance/user_spec.rb b/spec/acceptance/user_spec.rb index ee119561f..6ce5d81b9 100644 --- a/spec/acceptance/user_spec.rb +++ b/spec/acceptance/user_spec.rb @@ -22,8 +22,8 @@ class { 'mongodb::server': } end it 'creates the user' do - shell("mongo testdb --quiet --eval 'db.auth(\"testuser\",\"passw0rd\")'") do |r| - expect(r.stdout.chomp).to eq('1') + shell("mongosh testdb --quiet --eval 'db.auth(\"testuser\",\"passw0rd\")'") do |r| + expect(r.stdout.chomp).to eq('{ ok: 1 }') end end @@ -45,9 +45,7 @@ class { 'mongodb::server': } end it 'auth should fail' do - shell("mongo testdb --quiet --eval 'db.auth(\"testuser\",\"passw0rd\")'") do |r| - expect(r.stdout.chomp).to contain('Error: Authentication failed') - end + expect(`mongosh testdb --quiet --eval 'db.auth(\"testuser\",\"passw0rd\")'`).to output('MongoServerError: Authentication failed.').to_stderr end end @@ -70,8 +68,8 @@ class { 'mongodb::server': port => 27018 } end it 'creates the user' do - shell("mongo testdb --quiet --port 27018 --eval 'db.auth(\"testuser\",\"passw0rd\")'") do |r| - expect(r.stdout.chomp).to eq('1') + shell("mongosh testdb --quiet --port 27018 --eval 'db.auth(\"testuser\",\"passw0rd\")'") do |r| + expect(r.stdout.chomp).to eq('{ ok: 1 }') end end end @@ -96,8 +94,8 @@ class { 'mongodb::server': } end it 'creates the user' do - shell("mongo testdb --quiet --eval 'db.auth(\"testuser\",\"passw0rd\")'") do |r| - expect(r.stdout.chomp).to eq('1') + shell("mongosh testdb --quiet --eval 'db.auth(\"testuser\",\"passw0rd\")'") do |r| + expect(r.stdout.chomp).to eq('{ ok: 1 }') end end end @@ -130,25 +128,25 @@ class { 'mongodb::server': } end it 'allows the testuser' do - shell("mongo testdb --quiet --eval 'db.auth(\"testuser\",\"passw0rd\")'") do |r| - expect(r.stdout.chomp).to eq('1') + shell("mongosh testdb --quiet --eval 'db.auth(\"testuser\",\"passw0rd\")'") do |r| + expect(r.stdout.chomp).to eq('{ ok: 1 }') end end it 'assigns roles to testuser' do - shell("mongo testdb --quiet --eval 'db.auth(\"testuser\",\"passw0rd\"); db.getUser(\"testuser\")[\"roles\"].forEach(function(role){print(role.role + \"@\" + role.db)})'") do |r| + shell("mongosh testdb --quiet --eval 'db.auth(\"testuser\",\"passw0rd\"); db.getUser(\"testuser\")[\"roles\"].forEach(function(role){print(role.role + \"@\" + role.db)})'") do |r| expect(r.stdout.split(%r{\n})).to contain_exactly('readWrite@testdb', 'dbAdmin@testdb') end end it 'allows the second user to connect to its default database' do - shell("mongo testdb2 --quiet --eval 'db.auth(\"testuser2\",\"passw0rd\")'") do |r| - expect(r.stdout.chomp).to eq('1') + shell("mongosh testdb2 --quiet --eval 'db.auth(\"testuser2\",\"passw0rd\")'") do |r| + expect(r.stdout.chomp).to eq('{ ok: 1 }') end end it 'assigns roles to testuser2' do - shell("mongo testdb2 --quiet --eval 'db.auth(\"testuser2\",\"passw0rd\"); db.getUser(\"testuser2\")[\"roles\"].forEach(function(role){print(role.role + \"@\" + role.db)})'") do |r| + shell("mongosh testdb2 --quiet --eval 'db.auth(\"testuser2\",\"passw0rd\"); db.getUser(\"testuser2\")[\"roles\"].forEach(function(role){print(role.role + \"@\" + role.db)})'") do |r| expect(r.stdout.split(%r{\n})).to contain_exactly('readWrite@testdb2', 'dbAdmin@testdb2', 'readWrite@testdb', 'dbAdmin@testdb') end end diff --git a/spec/classes/client_spec.rb b/spec/classes/client_spec.rb index c8574b05c..09381ba3b 100644 --- a/spec/classes/client_spec.rb +++ b/spec/classes/client_spec.rb @@ -9,7 +9,7 @@ context 'with defaults' do it { is_expected.to compile.with_all_deps } - it { is_expected.to create_package('mongodb_client').with_ensure('present').with_name('mongodb-org-shell').with_tag('mongodb_package') } + it { is_expected.to create_package('mongodb_client').with_ensure('present').with_name('mongodb-mongosh').with_tag('mongodb_package') } end context 'with manage_package_repo set to false' do diff --git a/spec/classes/server_spec.rb b/spec/classes/server_spec.rb index 6318601ac..c2801743b 100644 --- a/spec/classes/server_spec.rb +++ b/spec/classes/server_spec.rb @@ -56,7 +56,7 @@ it { is_expected.to contain_file(config_file).with_content(%r{^ fork: true$}) } end - it { is_expected.to contain_file('/root/.mongorc.js').with_ensure('file').without_content(%r{db\.auth}) } + it { is_expected.to contain_file('/root/.mongoshrc.js').with_ensure('file').without_content(%r{db\.auth}) } it { is_expected.not_to contain_exec('fix dbpath permissions') } end @@ -173,7 +173,7 @@ end it { is_expected.to contain_file(config_file).with_content(%r{^security\.authorization: enabled$}) } - it { is_expected.to contain_file('/root/.mongorc.js') } + it { is_expected.to contain_file('/root/.mongoshrc.js') } end describe 'when specifying set_parameter array value' do @@ -270,7 +270,7 @@ end it { - is_expected.to contain_file('/root/.mongorc.js'). + is_expected.to contain_file('/root/.mongoshrc.js'). with_ensure('file'). with_owner('root'). with_group('root'). @@ -286,7 +286,7 @@ } end - it { is_expected.to contain_file('/root/.mongorc.js').with_ensure('file').without_content(%r{db\.auth}) } + it { is_expected.to contain_file('/root/.mongoshrc.js').with_ensure('file').without_content(%r{db\.auth}) } end end diff --git a/spec/unit/puppet/provider/mongodb_database/mongodb_spec.rb b/spec/unit/puppet/provider/mongodb_database/mongodb_spec.rb index c783d6898..8f25fb384 100644 --- a/spec/unit/puppet/provider/mongodb_database/mongodb_spec.rb +++ b/spec/unit/puppet/provider/mongodb_database/mongodb_spec.rb @@ -38,7 +38,7 @@ tmp = Tempfile.new('test') mongodconffile = tmp.path allow(provider.class).to receive(:mongod_conf_file).and_return(mongodconffile) - allow(provider.class).to receive(:mongo_eval).with('try { rs.secondaryOk() } catch (err) { rs.slaveOk() };printjson(db.getMongo().getDBs())').and_return(raw_dbs) + allow(provider.class).to receive(:mongo_eval).with('db.getMongo().setReadPref("primaryPreferred");EJSON.stringify(db.getMongo().getDBs())').and_return(raw_dbs) allow(provider.class).to receive(:db_ismaster).and_return(true) end diff --git a/spec/unit/puppet/provider/mongodb_replset/mongodb_spec.rb b/spec/unit/puppet/provider/mongodb_replset/mongodb_spec.rb index 1a7872845..2b6b2c825 100644 --- a/spec/unit/puppet/provider/mongodb_replset/mongodb_spec.rb +++ b/spec/unit/puppet/provider/mongodb_replset/mongodb_spec.rb @@ -166,7 +166,7 @@ end it 'raises an error when at least one member is not running with --replSet' do - allow(provider).to receive(:rs_status).and_return('ok' => 0, 'errmsg' => 'not running with --replSet') + allow(provider).to receive(:rs_status).and_raise(Puppet::ExecutionFailure, 'MongoServerError: not running with --replSet') provider.members = valid_members expect { provider.flush }.to raise_error(Puppet::Error, %r{is not supposed to be part of a replicaset\.$}) end diff --git a/spec/unit/puppet/provider/mongodb_user/mongodb_spec.rb b/spec/unit/puppet/provider/mongodb_user/mongodb_spec.rb index 9f77872f0..7f74adf5d 100644 --- a/spec/unit/puppet/provider/mongodb_user/mongodb_spec.rb +++ b/spec/unit/puppet/provider/mongodb_user/mongodb_spec.rb @@ -59,7 +59,7 @@ tmp = Tempfile.new('test') mongodconffile = tmp.path allow(provider.class).to receive(:mongod_conf_file).and_return(mongodconffile) - allow(provider.class).to receive(:mongo_eval).with('printjson(db.system.users.find().toArray())').and_return(raw_users) + allow(provider.class).to receive(:mongo_eval).with('EJSON.stringify(db.system.users.find().toArray())').and_return(raw_users) allow(provider.class).to receive(:mongo_version).and_return('4.4.0') allow(provider.class).to receive(:db_ismaster).and_return(true) end diff --git a/templates/mongorc.js.erb b/templates/mongoshrc.js.erb similarity index 54% rename from templates/mongorc.js.erb rename to templates/mongoshrc.js.erb index 9e060306f..8cf68f0fa 100644 --- a/templates/mongorc.js.erb +++ b/templates/mongoshrc.js.erb @@ -19,31 +19,32 @@ function rsReconfigSettings(settings){ <% if @auth and @store_creds -%> function authRequired() { try { - return db.serverCmdLineOpts().code == 13; + return db.serverCmdLineOpts().ok != 1; } catch (err) { - return false; + if (err.message.match(/requires authentication/) || err.message.match(/not authorized on admin/)) { + return true + } else { + throw("Unknown error :" + err) + } } } if (authRequired()) { <%- if @replset -%> - // rs.slaveOk has been deprecated, use secondaryOk if available - try { - rs.secondaryOk() - } - catch (err) { - rs.slaveOk() - } + db.getMongo().setReadPref('primaryPreferred') <%- end -%> try { - var prev_db = db + var prev_db = db.getName() db = db.getSiblingDB('admin') db.auth('<%= @admin_username %>', '<%= @admin_password_unsensitive %>') db = db.getSiblingDB(prev_db) } catch (err) { - // This isn't catching authentication errors as I'd expect... - abort('Unknown error') + // Silently ignore this error, we can't really do anything about it. + // If authentication fails here, that can mean 2 things: + // - Some error or corruption + // - Authentication is required, but no user is set up yet. + // This is normal when setting up a new cluster/server. } } <% end -%>