ruby-on-railspostgresqlamazon-ec2hstorerubber

Enabling hstore when deploying with rubber


I'm deploying a Rails app that uses PostgreSQL and HSTORE.

To deploy it, I'm ussing rubber.

Everything works, except for HSTORE not being properly enabled. When the migration that contains execute("CREATE EXTENSION hstore") runs, I get the following errors:

** [out :: production.---] 
** [out :: production.---] -- execute("CREATE EXTENSION hstore")
** [out :: production.---] 
** [out :: production.---] rake aborted!
** [out :: production.---] An error has occurred, this and all later migrations canceled:
** [out :: production.---] 
** [out :: production.---] PG::Error: ERROR:  permission denied to create extension "hstore"
** [out :: production.---] HINT:  Must be superuser to create this extension.

The script that creates the postgres instance has this code:

create_user_cmd = "CREATE USER #{env.db_user} WITH NOSUPERUSER CREATEDB NOCREATEROLE"

so I think the problem might be related to the NOSUPERUSER attribute being set here.

Is there any way to enable hstore using rubber while keeping most of the generated files unchanged?


Solution

  • The problem is that rubber creates the DB user as NOSUPERUSER. My workaround is to create tasks that run before and after capistrano's deploy:migrate that will change the user to SUPERUSER and back.

    Here's the code:

    namespace :rubber do
    
      namespace :project do
    
        before "deploy:migrate", "rubber:project:add_pg_superuser_and_enable_hstore"
        after "deploy:migrate", "rubber:project:remove_pg_superuser"
    
        task :add_pg_superuser_and_enable_hstore,
             :roles => [:postgresql_master, :postgresql_slave] do
          alter_user_cmd = "ALTER USER #{rubber_env.db_user} SUPERUSER"
          create_hstore_cmd = "CREATE EXTENSION IF NOT EXISTS hstore;"
          rubber.sudo_script "add_superuser_create_hstore", <<-ENDSCRIPT
            sudo -i -u postgres psql -c "#{alter_user_cmd}"
            sudo -i -u postgres psql -c "#{create_hstore_cmd}"
          ENDSCRIPT
        end
    
        task :remove_pg_superuser, :roles => [:postgresql_master,
                                              :postgresql_slave] do
          alter_user_cmd = "ALTER USER #{rubber_env.db_user} NOSUPERUSER"
          rubber.sudo_script "add_superuser_create_hstore", <<-ENDSCRIPT
            sudo -i -u postgres psql -c "#{alter_user_cmd}"
          ENDSCRIPT
        end
    
      end
    
    end