diff --git a/lib/puppet/provider/mongodb_database/mongodb.rb b/lib/puppet/provider/mongodb_database/mongodb.rb index 1cf061d25..7b91895a7 100644 --- a/lib/puppet/provider/mongodb_database/mongodb.rb +++ b/lib/puppet/provider/mongodb_database/mongodb.rb @@ -9,12 +9,16 @@ def self.instances require 'json' - pre_cmd = 'db.getMongo().setReadPref("primaryPreferred")' - dbs = JSON.parse mongo_eval("#{pre_cmd};EJSON.stringify(db.getMongo().getDBs())") + if db_ismaster + dbs = JSON.parse mongo_eval('EJSON.stringify(db.getMongo().getDBs())') - dbs['databases'].map do |db| - new(name: db['name'], - ensure: :present) + dbs['databases'].map do |db| + new(name: db['name'], + ensure: :present) + end + else + Puppet.warning 'Database info is available only from master host' + [] end end diff --git a/spec/acceptance/replset_spec.rb b/spec/acceptance/replset_spec.rb index 68d0a3c37..4393ed56c 100644 --- a/spec/acceptance/replset_spec.rb +++ b/spec/acceptance/replset_spec.rb @@ -8,9 +8,6 @@ if hosts.length > 1 && supported_version?(default[:platform], repo_version) describe 'mongodb_replset resource' do after :all do - # Have to drop the DB to disable replsets for further testing - on hosts, %{mongosh local --verbose --eval 'db.dropDatabase()'} - pp = <<-EOS class { 'mongodb::globals': #{repo_ver_param} @@ -20,10 +17,8 @@ class { 'mongodb::globals': package_ensure => purged, service_ensure => stopped } - if $::osfamily == 'RedHat' { - class { 'mongodb::client': - ensure => purged - } + -> class { 'mongodb::client': + ensure => purged } EOS @@ -36,12 +31,10 @@ class { 'mongodb::globals': #{repo_ver_param} } -> class { 'mongodb::server': - bind_ip => '0.0.0.0', + bind_ip => ['0.0.0.0'], replset => 'test', } - if $::osfamily == 'RedHat' { - class { 'mongodb::client': } - } + -> class { 'mongodb::client': } EOS apply_manifest_on(hosts.reverse, pp, catch_failures: true) @@ -59,11 +52,81 @@ class { 'mongodb::client': } expect(r.stdout).to match %r{#{hosts[0]}:27017} expect(r.stdout).to match %r{#{hosts[1]}:27017} end + sleep(30) + on(hosts_as('slave'), '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 end it 'inserts data on the master' do + on hosts_as('master'), %{mongosh --verbose --eval 'db.test.insertOne({name:"test1",value:"some value"})'} + end + + it 'checks the data on the master' do + 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'), %{mongosh --verbose --eval 'EJSON.stringify(db.test.findOne({name:"test1"}))'} do |r| + expect(r.stdout).to match %r{some value} + end + end + end + + describe 'mongodb::server with replset_members' do + after :all do + pp = <<-EOS + class { 'mongodb::globals': + #{repo_ver_param} + } + -> class { 'mongodb::server': + ensure => absent, + package_ensure => purged, + service_ensure => stopped + } + -> class { 'mongodb::client': + ensure => purged + } + EOS + + apply_manifest_on(hosts.reverse, pp, catch_failures: true) + end + + it 'configures mongo on both nodes' do + pp = <<-EOS + class { 'mongodb::globals': + #{repo_ver_param} + } + -> class { 'mongodb::server': + bind_ip => ['0.0.0.0'], + replset => 'test', + replset_members => [#{hosts.map { |x| "'#{x}:27017'" }.join(',')}], + } + -> class { 'mongodb::client': } + EOS + + apply_manifest_on(hosts, pp, catch_failures: true) + apply_manifest_on(hosts, pp, catch_changes: true) + end + + it 'sets up the replset with puppet' do + 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 sleep(30) - on hosts_as('master'), %{mongosh --verbose --eval 'db.test.save({name:"test1",value:"some value"})'} + on(hosts_as('slave'), '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 + end + + it 'inserts data on the master' do + on hosts_as('master'), %{mongosh --verbose --eval 'db.getMongo().setReadPref("primaryPreferred");db.test.insertOne({name:"test1",value:"some value"})'} end it 'checks the data on the master' do @@ -74,7 +137,7 @@ class { 'mongodb::client': } it 'checks the data on the slave' do sleep(10) - on hosts_as('slave'), %{mongosh --verbose --eval 'db.getMongo().setReadPref("primaryPreferred"); EJSON.stringify(db.test.findOne({name:"test1"}))'} do |r| + on hosts_as('slave'), %{mongosh --verbose --eval 'EJSON.stringify(db.test.findOne({name:"test1"}))'} do |r| expect(r.stdout).to match %r{some value} end end @@ -82,9 +145,6 @@ 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, %{mongosh local --verbose --eval 'db.dropDatabase()'} - pp = <<-EOS class { 'mongodb::globals': #{repo_ver_param} @@ -94,28 +154,36 @@ class { 'mongodb::globals': package_ensure => purged, service_ensure => stopped } - if $::osfamily == 'RedHat' { - class { 'mongodb::client': - ensure => purged - } + -> class { 'mongodb::client': + ensure => purged } EOS apply_manifest_on(hosts.reverse, pp, catch_failures: true) end + let(:keyfile_path) do + os_family = fact('os.family') + if os_family == 'RedHat' + '/var/lib/mongo' + else + '/var/lib/mongodb' + end + end + it 'configures mongo on both nodes' do pp = <<~EOS class { 'mongodb::globals': #{repo_ver_param} - } -> - class { 'mongodb::server': + } + -> class { 'mongodb::server': admin_username => 'admin', admin_password => 'password', auth => true, - bind_ip => '0.0.0.0', + store_creds => true, + bind_ip => ['0.0.0.0'], replset => 'test', - keyfile => '/var/lib/mongodb/mongodb-keyfile', + keyfile => "#{keyfile_path}/mongodb-keyfile", key => '+dxlTrury7xtD0FRqFf3YWGnKqWAtlyauuemxuYuyz9POPUuX1Uj3chGU8MFMHa7 UxASqex7NLMALQXHL+Th4T3dyb6kMZD7KiMcJObO4M+JLiX9drcTiifsDEgGMi7G vYn3pWSm5TTDrHJw7RNWfMHw3sHk0muGQcO+0dWv3sDJ6SiU8yOKRtYcTEA15GbP @@ -131,11 +199,9 @@ class { 'mongodb::server': g+Bybk5qHv1b7M8Tv9/I/BRXcpLHeIkMICMY8sVPGmP8xzL1L3i0cws8p5h0zPBa YG/QX0BmltAni8owgymFuyJgvr/gaRX4WHbKFD+9nKpqJ3ocuVNuCDsxDqLsJEME nc1ohyB0lNt8lHf1U00mtgDSV3fwo5LkwhRi6d+bDBTL/C6MZETMLdyCqDlTdUWG - YXIsJ0gYcu9XG3mx10LbdPJvxSMg' - } - if $::osfamily == 'RedHat' { - include mongodb::client + YXIsJ0gYcu9XG3mx10LbdPJvxSMg', } + -> class { 'mongodb::client': } EOS apply_manifest_on(hosts.reverse, pp, catch_failures: true) @@ -145,9 +211,16 @@ class { 'mongodb::server': it 'sets up the replset with puppet' do pp = <<~EOS mongodb_replset { 'test': - auth_enabled => true, - members => [#{hosts.map { |x| "'#{x}:27017'" }.join(',')}], - before => Mongodb_user['admin'] + members => [#{hosts.map { |x| "'#{x}:27017'" }.join(',')}], + } + -> mongodb_user { "User admin on db admin": + ensure => present, + password_hash => mongodb_password('admin', 'password'), + username => 'admin', + database => 'admin', + roles => ['userAdmin', 'readWrite', 'dbAdmin', 'dbAdminAnyDatabase', 'readAnyDatabase', + 'readWriteAnyDatabase', 'userAdminAnyDatabase', 'clusterAdmin', + 'clusterManager', 'clusterMonitor', 'hostManager', 'root', 'restore',], } EOS apply_manifest_on(hosts_as('master'), pp, catch_failures: true) @@ -156,11 +229,112 @@ class { 'mongodb::server': expect(r.stdout).to match %r{#{hosts[0]}:27017} expect(r.stdout).to match %r{#{hosts[1]}:27017} end + sleep(30) + on(hosts_as('slave'), '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 end it 'inserts data on the master' do + on hosts_as('master'), %{mongosh test --verbose --eval 'load("/root/.mongoshrc.js");db.dummyData.insertOne({"created_by_puppet": 1})'} + end + + it 'checks the data on the master' do + 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'), %{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 + end + + describe 'mongodb::server with replset_members and auth => true' do + after :all do + pp = <<-EOS + class { 'mongodb::globals': + #{repo_ver_param} + } + -> class { 'mongodb::server': + ensure => absent, + package_ensure => purged, + service_ensure => stopped + } + -> class { 'mongodb::client': + ensure => purged + } + EOS + + apply_manifest_on(hosts.reverse, pp, catch_failures: true) + end + + let(:keyfile_path) do + os_family = fact('os.family') + if os_family == 'RedHat' + '/var/lib/mongo' + else + '/var/lib/mongodb' + end + end + + it 'configures mongo on both nodes' do + pp = <<~EOS + class { 'mongodb::globals': + #{repo_ver_param} + } + -> class { 'mongodb::client': } + -> class { 'mongodb::server': + admin_username => 'admin', + admin_password => 'password', + auth => true, + store_creds => true, + create_admin => true, + bind_ip => ['0.0.0.0'], + replset => 'test', + replset_members => [#{hosts.map { |x| "'#{x}:27017'" }.join(',')}], + keyfile => "#{keyfile_path}/mongodb-keyfile", + key => '+dxlTrury7xtD0FRqFf3YWGnKqWAtlyauuemxuYuyz9POPUuX1Uj3chGU8MFMHa7 + UxASqex7NLMALQXHL+Th4T3dyb6kMZD7KiMcJObO4M+JLiX9drcTiifsDEgGMi7G + vYn3pWSm5TTDrHJw7RNWfMHw3sHk0muGQcO+0dWv3sDJ6SiU8yOKRtYcTEA15GbP + ReDZuHFy1T1qhk5NIt6pTtPGsZKSm2wAWIOa2f2IXvpeQHhjxP8aDFb3fQaCAqOD + R7hrimqq0Nickfe8RLA89iPXyadr/YeNBB7w7rySatQBzwIbBUVGNNA5cxCkwyx9 + E5of3xi7GL9xNxhQ8l0JEpofd4H0y0TOfFDIEjc7cOnYlKAHzBgog4OcFSILgUaF + kHuTMtv0pj+MMkW2HkeXETNII9XE1+JiZgHY08G7yFEJy87ttUoeKmpbI6spFz5U + 4K0amj+N6SOwXaS8uwp6kCqay0ERJLnw+7dKNKZIZdGCrrBxcZ7wmR/wLYrxvHhZ + QpeXTxgD5ebwCR0cf3Xnb5ql5G/HHKZDq8LTFHwELNh23URGPY7K7uK+IF6jSEhq + V2H3HnWV9teuuJ5he9BB/pLnyfjft6KUUqE9HbaGlX0f3YBk/0T3S2ESN4jnfRTQ + ysAKvQ6NasXkzqXktu8X4fS5QNqrFyqKBZSWxttfJBKXnT0TxamCKLRx4AgQglYo + 3KRoyfxXx6G+AjP1frDJxFAFEIgEFqRk/FFuT/y9LpU+3cXYX1Gt6wEatgmnBM3K + g+Bybk5qHv1b7M8Tv9/I/BRXcpLHeIkMICMY8sVPGmP8xzL1L3i0cws8p5h0zPBa + YG/QX0BmltAni8owgymFuyJgvr/gaRX4WHbKFD+9nKpqJ3ocuVNuCDsxDqLsJEME + nc1ohyB0lNt8lHf1U00mtgDSV3fwo5LkwhRi6d+bDBTL/C6MZETMLdyCqDlTdUWG + YXIsJ0gYcu9XG3mx10LbdPJvxSMg', + } + EOS + + apply_manifest_on(hosts, pp, catch_failures: true) + apply_manifest_on(hosts, pp, catch_changes: true) + end + + it 'sets up the replset with puppet' do + 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 sleep(30) - on hosts_as('master'), %{mongosh test --verbose --eval 'load("/root/.mongoshrc.js");db.dummyData.insert({"created_by_puppet": 1})'} + on(hosts_as('slave'), '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 + end + + it 'inserts data on the master' do + on hosts_as('master'), %{mongosh test --verbose --eval 'load("/root/.mongoshrc.js");db.dummyData.insertOne({"created_by_puppet": 1})'} end it 'checks the data on the master' do diff --git a/spec/unit/puppet/provider/mongodb_database/mongodb_spec.rb b/spec/unit/puppet/provider/mongodb_database/mongodb_spec.rb index 8f25fb384..c0a4825de 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('db.getMongo().setReadPref("primaryPreferred");EJSON.stringify(db.getMongo().getDBs())').and_return(raw_dbs) + allow(provider.class).to receive(:mongo_eval).with('EJSON.stringify(db.getMongo().getDBs())').and_return(raw_dbs) allow(provider.class).to receive(:db_ismaster).and_return(true) end