Forum: Rails-ES Usar diferentes base de datos y único codigo fuente

812234510d2f75ab0c70b922a1d5e3b2?d=identicon&s=25 Gonzalo Cao (gonzalo)
on 2009-03-17 14:25
Hola a todos,

  hemos desarrollado una sencilla aplicación de ingresos y gastos para
un departamento de mi empresa. Mantenemos el código con svn y
desplegamos con capistrano.

  Ahora otro departamento está interesado en la misma aplicación con las
mismas especificaciones. El problema es que debemos desplegarla en el
mismo servidor con una base de datos diferente por un tema legal.
¿alguna idea de como hacerlo?

  De momento hemos conseguido encontrar la forma de desplegar dos
aplicaciones con el mismo código en el mismo servidor a través de
capistrano. Se puede ver en el siguiente código:

task :scenario_a do
  set :deploy_to, "/path/to/scenario_a"
  role :web, "scenario_a.web"
  role :app, "scenario_a.app"
end
task :scenario_b do
  set :deploy_to, "/path/to/scenario_b"
  role :web, "scenario_b.web"
  role :app, "scenario_b.app"
end

  De esta forma podemos hacer "$ cap scenario_a deploy" o "$ cap
scenario_b deploy" y desplegar ambas aplicaciones con el mismo código.
Ahí viene el problema, ambos comparten el mismo "database.yml" y es lo
que no me interesa.

¿alguna idea? ¿otra aproximación?
9b3b1fd6baa8379638d8399ecd60045d?d=identicon&s=25 Emili Parreño (emili)
on 2009-03-17 15:33
(Received via mailing list)
EL problema es que tienes el database.yml en el repositorio y eso no
debes
hacerlo nunca. Para esto, capistrano te crea el directorio shared, ahi
debes
poner los archivos que sean comunes entre versiones y que no se
descargan
del repo.Puedes crear un directorio shared/config y meter ahi el
database.yml para cada aplicación. Luego configuras capistrano para que
en
cada deploy te haga un enlasce simbolico del archivo
current/config/database.yml hacia shared/config/database.yml

task :after_symlink do
    run "ln -nfs #{shared_path}/config/database.yml
#{release_path}/config/database.yml"
end


2009/3/17 Gonzalo Cao <ruby-forum-incoming@andreas-s.net>
812234510d2f75ab0c70b922a1d5e3b2?d=identicon&s=25 Gonzalo Cao (gonzalo)
on 2009-03-17 15:49
Gracias Emili por tu respuesta,

  efectivamente estoy viendo que el problema va por ahí. En la lista de
capistrano sugieren la misma solución que propones tú para un problema
similar.

http://groups.google.com/group/capistrano/browse_t...

Primero recomiendan poner el database.yml en la lista de ignore del svn
para que no se actulice cada vez. Además añaden otra tarea adicional
para crear un archivo shared/resources/database.yml automáticamente en
al hacer el cap setup. Finalmente meten una tarea que enlaza el archivo
en cada release. Pego aquí el código entero a excepción de lo del svn.


For each developer, they can have their own database.yml
with their dev information.  For your production servers, and assuming
you are using capistrano, you can add this to your capistrano.rake file
(or to your own recipe file) to do the following:

  desc "create a shared/resources directory for common, non-svn files
(like database.yml)"
  task :after_setup, :roles => [:app, :db, :web] do
    run <<-CMD
    mkdir -p -m 777 #{shared_path}/resources &&
    mkdir -p -m 777 #{shared_db} &&
    touch #{shared_path}/resources/database.yml
    chmod 600 #{shared_path}/resources/database.yml
    CMD
  end

  desc "create a symlink for the database.yml file for the current
project (since it isn't in source control)"
  task :after_update_code, :roles => [:app, :db, :web] do
    run <<-CMD
    ln -nfs #{shared_path}/resources/database.yml
#{release_path}/config/database.yml
    CMD
  end

and then put the information you need for your production environment
in the #{shared_path}/resources/database.yml
90ea347c45cdfbc1c5767dd6304d9c10?d=identicon&s=25 Borja Martín (Guest)
on 2009-03-17 17:32
(Received via mailing list)
otra opción parecida si no te apetece estar poniendo cosas a mano en el
servidor y te apetece tener los ficheros bajo control, es tener los
ficheros
de configuración de la base de datos renombrados y estos sí tenerlos en
svn
en plan:
database.yml.site1
database.yml.site2

luego tu database.yml local no lo tendrías en el svn tal como ha
comentado
Emili, ya que dos desarrolladores no tienen por qué estar trabajando
sobre
la misma db

luego a la hora de hacer el deploy le pasas como parámetro el nombre del
site(o lo pides por consola) y al finalizarlo, simplemente renombras el
fichero pertinente(o haces un enlace, lo que más rabia te dé)



2009/3/17 Gonzalo Cao <ruby-forum-incoming@andreas-s.net>
812234510d2f75ab0c70b922a1d5e3b2?d=identicon&s=25 Gonzalo Cao (gonzalo)
on 2009-03-17 19:35
Gracias a todos, ya lo he solucionado.

El método seguido es el que digo arriba. Aquí está el código que estoy
usando para el capistrano. Espero que le sirva a alguien más.

#Archivo deploy.rb
#Aquí mi repositorio (eliminando lo que no podéis ver)
set :repository,
"svn+ssh://xxxxx@[ip_servidor_repos]/home/xxxxx/repos/nombre_proyecto"


# selector de despliegue según escenario
task :nombre_proyecto_a do
  set :application, "nombre_proyecto_a"
  set :deploy_to, "/home/xxxxx/apps/#{application}"
end

task :nombre_proyecto_b do
  set :application, "nombre_proyecto_b"
  set :deploy_to, "/home/xxxxx/apps/#{application}"
end

role :app, "[ip_servidor]"
role :web, "[ip_servidor]"
role :db,  "[ip_servidor]", :primary => true

set :use_sudo, false

namespace :deploy do
  #esto correponde a mi conf de passenger
  desc "Restart Application"
  task :restart, :roles => :app do
    run "touch #{current_path}/tmp/restart.txt"
  end

  #esto genera en enlace de la versión actual al archivo de conf
  #  de la base de datos
  desc "create a symlink for the database.yml file for the current
project"
  task :after_update_code, :roles => [:app, :db, :web] do
    run <<-CMD
    ln -nfs #{shared_path}/resources/database.yml
#{release_path}/config/database.yml
    CMD
  end
end

  desc "create a shared/resources directory for common, non-svn files
(like database.yml)"
  task :after_setup, :roles => [:app, :db, :web] do
    run <<-CMD
    mkdir -p -m 777 #{shared_path}/resources &&
    touch #{shared_path}/resources/database.yml
    chmod 600 #{shared_path}/resources/database.yml
    CMD
  end


Primero habría que hacer "$cap nombre_proyecto_a deploy:setup" y editar
el archivo
"/home/xxxxx/apps/nombre_proyecto_a/shared/resources/database.yml" con
los valores correspondientes a la BD que queramos usar. Después ya
podemos hacer los deploys con "$cap nombre_proyecto_a deploy". Lo mimso
para nombre_proyecto_b.

Ale, hasta otra
39086eb3d9a1437276d07c08ea0c3821?d=identicon&s=25 Guillermo (Guest)
on 2009-03-17 22:01
(Received via mailing list)
2009/3/17 Gonzalo Cao <ruby-forum-incoming@andreas-s.net>

>  Ahora otro departamento está interesado en la misma aplicación con las
> mismas especificaciones. El problema es que debemos desplegarla en el
> mismo servidor con una base de datos diferente por un tema legal.
> ¿alguna idea de como hacerlo?


Pues visto que es el mismo servidor y la misma aplicación, un simple
before_filter basado en dominio que establezca la conexión


class ApplicationController < ActionController::Base

before_filter :set_database

def set_database
  ActiveRecord::Base.establish_connection(ENV['domain'].split[1].to_sym)
end

end

y en el config/database.yml una base de datos por cada dominio.
ENV["domain"] no creo que sea correcto.

Aunque ahora me entra la duda de si este método es válido con los pool
de
conexiones.
812234510d2f75ab0c70b922a1d5e3b2?d=identicon&s=25 Gonzalo Cao (gonzalo)
on 2009-03-18 09:35
Hola  Guillermo,

el inconveniente que le veo a tu propuesta es precisamente el incluir
información de la conexión de base de datos en los ordenadores de
desarrollo. Como comentaban en la lista de capistrano eso es un problema
serio de seguridad ya que cualquier persona con acceso a los ordenadores
de desarrollo o al svn podría ganar acceso a la BD de producción. El
otro método propuesto, aunque algo más confuso al principio, la verdad
es que se despliega fácilmente y se pueden incluir nuevos proyectos con
facilidad.

En cualquier caso gracias por explicar cómo se puede cambiar de base de
datos en el ámbito de aplicación. Era algo que quería saber.

Saludos

Guillermo wrote:
> 2009/3/17 Gonzalo Cao <ruby-forum-incoming@andreas-s.net>
>
>>  Ahora otro departamento está interesado en la misma aplicación con las
>> mismas especificaciones. El problema es que debemos desplegarla en el
>> mismo servidor con una base de datos diferente por un tema legal.
>> ¿alguna idea de como hacerlo?
>
>
> Pues visto que es el mismo servidor y la misma aplicación, un simple
> before_filter basado en dominio que establezca la conexión
>
>
> class ApplicationController < ActionController::Base
>
> before_filter :set_database
>
> def set_database
>   ActiveRecord::Base.establish_connection(ENV['domain'].split[1].to_sym)
> end
>
> end
>
> y en el config/database.yml una base de datos por cada dominio.
> ENV["domain"] no creo que sea correcto.
>
> Aunque ahora me entra la duda de si este método es válido con los pool
> de
> conexiones.
39086eb3d9a1437276d07c08ea0c3821?d=identicon&s=25 Guillermo (Guest)
on 2009-03-18 11:58
(Received via mailing list)
2009/3/18 Gonzalo Cao <ruby-forum-incoming@andreas-s.net>

> Hola  Guillermo,
>
> el inconveniente que le veo a tu propuesta es precisamente el incluir
> información de la conexión de base de datos en los ordenadores de
> desarrollo.


No. Siempre puedes tener un config/database.yml en el repo, y un hook de
capistrano before :update_code, que haga vínculo simbólico al
config/database.yml. Si no me equivoco, lo que se comentaba en mensajes
anteriores. Una solución no quita la otra.

Mi propuesta lo que evita es cargar la memoria de la máquina, ya que
solo
tienes que tener un appserver para las dos applicaciones.



> Como comentaban en la lista de capistrano eso es un problema
> serio de seguridad


Me hace gracia eso, proteger el config/database, cuando mucha gente que
me
lo ha comentado:
a) Tiene puesto a mano db_password en capistrano
b) Tiene puesto password en capistrano y una máquina con sudo.
c) Accede por ssh por un sistema de llaves pero con una phrase nula.
d) Tiene habilitado el acceso a la granja de producción desde fuera de
la
oficina.


>  se pueden incluir nuevos proyectos con facilidad.

Y cada uno de ellos come más memoria. No digo que sea malo, pero
prefiero
tener 6 mongrels con capacidad de atender cualquier petición, a tener
que
tener 3 mongrel por cada aplicación (suponiendo que son 2). Eso es para
estudiar el entorno al completo. Pongamos que crece y la requiren más
departamentos. Para una misma máquina a 200 Megas por app, 200*6= 1,2
Gigas,
por lo que no se pueden poner más apps sin poner más memoria (suponiendo
que
tiene dos gigas). El rendimiento será mejor si esos 6 son capaces de
procesar cualquier petición, ha tener 2 por cada uno o incluso 1 por
cada
uno.



En cualquier caso gracias por explicar cómo se puede cambiar de base de
> datos en el ámbito de aplicación. Era algo que quería saber.


De nada, pero esto era antes de meter Threads y el correspondiente pool
de
conexiones. No se si ahora mismo seguirá funcionando. No lo he
investigado.

Saludos.
812234510d2f75ab0c70b922a1d5e3b2?d=identicon&s=25 Gonzalo Cao (gonzalo)
on 2009-03-18 12:12
Guillermo wrote:
> 2009/3/18 Gonzalo Cao <ruby-forum-incoming@andreas-s.net>
>
>> Hola  Guillermo,
>>
>> el inconveniente que le veo a tu propuesta es precisamente el incluir
>> información de la conexión de base de datos en los ordenadores de
>> desarrollo.
>
>
> No. Siempre puedes tener un config/database.yml en el repo, y un hook de
> capistrano before :update_code, que haga vínculo simbólico al
> config/database.yml. Si no me equivoco, lo que se comentaba en mensajes
> anteriores. Una solución no quita la otra.
>

Tienes toda la razón, yo mismo comentaba que una opción era hacer que
svn ignorara el database.yml. Así permitimos además que cada
desarrollador tenga su propia configuración de base de datos.

> Mi propuesta lo que evita es cargar la memoria de la máquina, ya que
> solo
> tienes que tener un appserver para las dos applicaciones.
>

Muy interesante la reflexión, a tener en cuenta.

>> Como comentaban en la lista de capistrano eso es un problema
>> serio de seguridad
>
>
> Me hace gracia eso, proteger el config/database, cuando mucha gente que
> me
> lo ha comentado:
> a) Tiene puesto a mano db_password en capistrano
> b) Tiene puesto password en capistrano y una máquina con sudo.
> c) Accede por ssh por un sistema de llaves pero con una phrase nula.
> d) Tiene habilitado el acceso a la granja de producción desde fuera de
> la
> oficina.

Hombre, en lista lo comentaban desde el punto de vista de un auditor de
seguridad que jamás permitiría eso. Y malas costumbres las hay a
montones.

>
>
>>  se pueden incluir nuevos proyectos con facilidad.
>
> Y cada uno de ellos come más memoria. No digo que sea malo, pero
> prefiero
> tener 6 mongrels con capacidad de atender cualquier petición, a tener
> que
> tener 3 mongrel por cada aplicación (suponiendo que son 2). Eso es para
> estudiar el entorno al completo. Pongamos que crece y la requiren más
> departamentos. Para una misma máquina a 200 Megas por app, 200*6= 1,2
> Gigas,
> por lo que no se pueden poner más apps sin poner más memoria (suponiendo
> que
> tiene dos gigas). El rendimiento será mejor si esos 6 son capaces de
> procesar cualquier petición, ha tener 2 por cada uno o incluso 1 por
> cada
> uno.
>

Como te comentaba antes, me parece una reflexión muy interesante y la
tendré en cuenta. Mis usuarios acceden al mismo código.

>
>
> En cualquier caso gracias por explicar cómo se puede cambiar de base de
>> datos en el ámbito de aplicación. Era algo que quería saber.
>
>
> De nada, pero esto era antes de meter Threads y el correspondiente pool
> de
> conexiones. No se si ahora mismo seguirá funcionando. No lo he
> investigado.
>
> Saludos.

Gracias por el comentario. Muy ilustrativo. ¡Cada día esto más encantado
con Rails y con este foro!

Saludos
De8b0ca150dc20d07c2bda01c0bab007?d=identicon&s=25 Ernesto Mederos (eamederos)
on 2012-02-29 04:33
Tengo una aplicacion que corre sobre Ruby on Rails framework. Estoy
construyendo un nuevo plugin y necesito que este se conecte a otra base
de datos y ejecute algunas funciones en el lenguaje plpgsql. Utilizo
Postgresql como gestor de base de datos. ¿Que puedo hacer para
conectarme a esta otra base de datos?
This topic is locked and can not be replied to.