ajgon / opsworks_ruby

Set of chef recipes for OpsWorks based Ruby projects.
MIT License
82 stars 93 forks source link

No way to set RAILS_ENV other than 'production' #34

Closed jn202205 closed 8 years ago

jn202205 commented 8 years ago

From opsworks_ruby/libraries/drivers_framework_rails.rb:12

def raw_out
  super.merge(deploy_environment: { 'RAILS_ENV' => 'production' })
end

This method always sets the RAILS_ENV as production with no way to set it to beta, staging, etc. Unless I'm missing some other place RAILS_ENV is supposed to be set. Should this method maybe be reversed like so?

def raw_out
  {deploy_environment: { 'RAILS_ENV' => 'production' }}.merge(super)
end

That way you can set it in opsworks stack settings via

{
  "deploy": { 
    "app_name": {
      "framework": {
        "deploy_environment": { "RAILS_ENV": "beta" }
      }
    }
  }
}
beirigo commented 8 years ago

@ajgon I have solved this in my fork by adding the following setting:

{
  "deploy": {
    "<my_app_name>": {
        "environment": "staging"
    }
}

The reason I'm not setting this under app['framework'] is that the environment is needed not only by the framework driver, but also by sidekiq (you need to send -e <environment> option to the command line) and unicorn (to generate the unicorn.conf with the proper rails env).

Let me know what you think of this approach. If you dislike it, I'm open to suggestions :)

ajgon commented 8 years ago

I resolved it slightly differently, by intoducing the app['framework']['rails_env'] attribute. The reason behind this is, that not every framework uses those variables, and some of them uses different ones (RACK_ENV for example). By leaving it tied to the framework, we can exclude it from anywhere, when framework is disabled.

However it remains an opened question - should we stick to 'deploy_environment' => { 'RAILS_ENV' => 'whatever', 'RACK_ENV' => 'whatever' } or should we introduce framework.rails_env, framework.rack_env etc. The first solution feels more consistent, while the second one feels more clean.

Or maybe something like framework.deploy_env which gets resolved automatically (RAILS_ENV for Rails, RACK_ENV for raw server etc.).

Thoughts? :)

beirigo commented 8 years ago

That would be great if RAILS_ENV was only used by framework. But what about the other drivers?

I noticed that the environment is also used on the unicorn service template: https://github.com/ajgon/opsworks_ruby/blob/master/templates/default/unicorn.service.erb#L40

For the template above to be rendered with the proper RACK_ENV, Drivers::Appserver::Unicornshould also have access to the environment.

Another component that could also make use of this is the Sidekiq driver. I realised that the sidekiq monit template (sidekiq.monitrc.erb) is not passing the -e option to the sidekiq command.

How could we design it so other drivers (not only framework) could also access the environment?

beirigo commented 8 years ago

I think the way OpsWorks solved this for for stacks prior to Chef 12 was to store it under search(:aws_opsworks_app)[<app_short_name>]['rails_env']. That made sense because stacks using chef <12 can have a type (Rails, elasticsearch...). The problem is that setting a rails environment is not available for stacks using Chef 12 (Since you can't choose a type). I Think it would be great if we could achieve the same in a similar way.

jn202205 commented 8 years ago

@ajgon When would you want a different environment setting for different drivers on the same stack? I like @marcosbeirigo solution of putting it under deploy['app_name']['envrironment'], which would set the environment for all drivers.

If its actually needed to be different for certain drivers maybe allow them to also be set at a more granular level which would override the higher level deploy['app_name']['envrironment'] setting.

Something like

{
  "deploy": { 
    "app_name": {
      "environment": "staging",
      "framework": {
        "deploy_environment": { "RAILS_ENV": "beta" }
      }
    }
  }
}
ajgon commented 8 years ago

I see the point, but from different perspective. By hardwiring the environment to the framework, we can't set it when no framework is present at all (i.e. custom Ruby app, but with some kind of environment variation i.e. RACK_ENV).

I followed the more general approach (deploy_env instead of rails_env), but I will add next commit soon, which extracts the environment to app['environment'] as you suggest...

ajgon commented 8 years ago

app['environment'] implemented (as suggested).

beirigo commented 8 years ago

Awesome 💚 💙 💛