We use MongoDB as our primary store and have built a healthy amount of automation around various database instances and operational environments. For example, we backup databases to S3 using mongodump, mirror data between instances with mongorestore and often need to open a MongoDB shell with mongo to examine data at the lowest level.

Generating MongoDB command-lines is tedious and error-prone. Introducing a new gem called mongoid-shell to help with this. The library can generate command-lines for various MongoDB shell tools from your Mongoid configuration.

For example, connect to your production MongoDB instance from a db:production:shell Rake task.

namespace :db
  namespace :production
    task :shell
      Mongoid.load! "mongoid.yml", :production
      system Mongoid::Shell::Commands::Mongo.new.to_s
    end
  end
end

Commands can be created for the current default session or you can pass a session as an argument to a new command.

# will use Mongoid.default_session
Mongoid::Shell::Commands::Mongodump.new

# use a hand-crafted session
s = Moped::Session.new([ "127.0.0.1:27017" ])
Mongoid::Shell::Commands::Mongodump.new(session: s)

Commands accept parameters. Here’s how to backup my_database to /tmp/db_backup.

out = File.join(Dir.tmpdir, 'db_backup')
db = 'my_database'
dump = Mongoid::Shell::Commands::Mongodump.new(db: db, out: out)
# mongodump --db my_database --out /tmp/db_backup
system dump.to_s

The mongoid-shell gem currently supports mongo, mongodump, mongorestore and mongostat and various MongoDB configurations, including replica-sets.

Please note that we don’t recommend you store passwords for production environments in your mongoid.yml. At Artsy, we set all sensitive values directly on our Heroku instances with heroku config:add and use heroku-commander to retrieve these settings in rake. We also have a bit of convention in our application name, such as “app-staging” and “app-production”.

Here’s a complete Rake task that dynamically fetches Heroku configuration and opens a MongoDB shell on a production or staging environment.

namespace :db do
  [ :staging, :production ].each do |env|
    namespace env do
      task :shell do
        app = "myapp-#{env}"
        config = Heroku::Commander.new(app: app).config
        config.each_pair do |k, v|
          ENV[k] = v
        end
        mongoid_yml = File.join(Rails.root, "config/mongoid.yml")
        Mongoid.load! mongoid_yml, env
        system Mongoid::Shell::Commands::Mongo.new.to_s
      end
    end
  end
end

Run rake db:staging:shell or rake db:production:shell, which works as long as you have access to the Heroku app itself. A bonus feature is that the mongoid-shell gem will automatically connect to the primary node of a replica-set.

$ rake db:staging:shell
 mongo db:10007/app-staging --username user --password ************
 MongoDB shell version: 2.0.7
 connecting to: db:10007/app-staging
 >

Categories: MongoDB, Mongoid, Rake, Shell


Comments