jueves, 22 de marzo de 2007

Subversion + UBUNTU + Apache + MySQL - Parte 5

A continuación les describo los pasos necesarios para que la autenticación de acceso a svn se haga contra una base de datos MySQL y no contra el archivo de passwords generado por htpasswd2.

Lo primero que debemos hacer es instalar mysql y el modulo de autenticación para apache.

$ sudo apt-get install mysql-server libapache2-mod-auth-mysql

Lo segundo es decirle a apache que tiene un nuevo modulo disponible para hacer autenticación.

$ cd /etc/apache2/mods-enabled/
$ sudo ln -s /etc/apache2/mods-available/auth_mysql.load .

Lo siguiente es configurar MySQL para que almacene la información de los usuarios:

Si MySQL no estaba configurado antes debemos asignarle un password al usuario root

$ mysqladmin -u root password

Después debemos crear la base de datos y la tabla de usuarios

mysql -uroot -p

mysql> grant all on svn_auth.* to svn_admin_user@localhost identified by 'password';

mysql> flush privileges;

mysql> create database svn_auth;

CREATE TABLE `clients` (
`username` varchar(25) NOT NULL default '',
`passwd` varchar(25) NOT NULL default '',
`groups` varchar(25) NOT NULL default '',
PRIMARY KEY (`username`),
KEY `groups` (`groups`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;


Para insertar usuarios se puede usar el siguiente sql:

INSERT INTO `clients` VALUES ('id del usuario', 'password', 'grupo');

El password se puede crear como encrypt('password') o se puede usar uno generado por el comando htpasswd2

insert into `clients` values ('user', encrypt('user1'), '');

$ htpasswd2 -bnm user user1
user:$apr1$l.Iwf/..$uSY81FEI6BT5SNozcT51t1

insert into `clients` values ('user', '$apr1$l.Iwf/..$uSY81FEI6BT5SNozcT51t1', '');

Ahora solo nos queda modificar Apache para que tome el cambio. Para eso debemos modificar el Location de /svn

$ sudo vi /etc/apache2/apach2.conf


DAV svn
# Directorio padre de todos los repositorios
SVNParentPath /ruta/a/dir/padre/de/repositorios
# Archivo con definicion de acceso a los repositorios
AuthzSVNAccessFile /etc/apache2/.svn_access_control
# Solo usuarios autorizados
Require valid-user
# How to authenticate a user
AuthType Basic
AuthName "Coloque su clave de acceso a Subversion"
# Configuracion de acceso a MySQL
AuthMYSQL on
AuthMySQL_Authoritative on
AuthMySQL_Host localhost
AuthMySQL_DB svn_auth
AuthMySQL_Password_Table clients
# Aqui se deben colocar los datos del usuario con acceso a la BD
AuthMySQL_User svn_admin_user
AuthMySQL_Password svn_admin_user_password
AuthMySQL_Group_Table clients
AuthMySQL_Empty_Passwords off
AuthMySQL_Encryption_Types Crypt_DES PHP_MD5 MD5
# Otros valores posibles
#AuthMySQL_Encryption_Types PHP_MD5 SHA1Sum Crypt_DES Plaintext Crypt_MD5 Crypt MySQL MD5
# Esto ya no hace falta
#AuthUserFile /etc/apache2/.dav_svn.passwd


Por ultimo, reiniciamos Apache

$ sudo /etc/init.d/apache2 force-reload

Y listo, así de fácil se hace la configuración.

lunes, 19 de marzo de 2007

Subversion + UBUNTU + Apache - Parte 4

A continuación voy a describir los pasos para usar Subversion con el protocolo http. Lo primero que debemos hacer es instalar Apache web server y el modulo de Subversion para Apache

$ sudo apt-get install apache2
$ sudo apt-get install libapache2-svn


Una vez instalados vamos a crear el contexto bajo el cual vamos a accesar los repositorios. Para eso debemos editar el archivo de configuracion de Apache

$ sudo vi /etc/apache2/apache2.conf

y agregar la definición del contexto, en este caso lo vamos a llamar /svn. La definición es la siguiente

<location /svn>
DAV svn
SVNParentPath /ruta/a/dir/padre/de/repositorios
AuthzSVNAccessFile /etc/apache2/.svn_access_control
Require valid-user
AuthType Basic
AuthName "Enter password for Subversion Repository"
AuthUserFile /etc/apache2/.dav_svn.passwd
</location>


Esta definición solo permite acceso a usuarios validos (Require valid-user), si se quieren permitir usuarios anónimos o colocar otro tipo de restricciones a los accesos deben consultar la documentación de Apache. Fijense en los 3 valores a modificar

SVNParentPath: debe apuntar al directorio padre de los repositorios
AuthzSVNAccessFile: define los accesos de los usuarios a los repositorios
AuthUserFile: archivo con la definición de usuarios y los passwords

Para definir usuarios se debe usar el comando htpasswd2. Este comando agrega una entrada a un archivo de password por cada usuario registrado. La encriptación es MD5. El archivo de password se especifica en la línea de comando y debe ser el mismo usado en AuthUserFile.

$ sudo htpasswd2 -m /etc/apache2/.dav_svn.passwd user1
New password:
Re-type new password:
Updating password for user user1


Si se quiere limpiar el archivo y definir usuarios desde cero se debe ejecutar el comando (se recomienda hacer esto la primera vez)

$ sudo htpasswd2 -cm /etc/apache2/.dav_svn.passwd svnuser

La definición de los accesos se hace en el archivo definido por la entrada AuthzSVNAccessFile, en nuestro caso es /etc/apache2/.svn_access_control. En este archivo se definen grupos de accesos y perisología de acceso a cada repositorio. Para una descripción detallada ver la documentación ( http://svnbook.red-bean.com/)

$ sudo nano /etc/apache2/svn_access_control

# Se definen los grupos de trabajo
[groups]
devteam=user1, user2
guest=user3, user4
everyone=@devteam, @guest

# Acceso de lectura para todo el mundo
[/]
* = r

# Guest pueden leer pero solo devteam actualizar en
# el repositorio repo
[repo:/]
@devteam=rw
@guest=r

# Todo el musndo puede leer el repo test pero solo
# user5 lo puede modificar
[test:/]
user5=rw
@everyone=r

# Solo el grupo devteam tiene acceso total al
# repositorio bcol. Guest no tienen ningun acceso
[bcol:/]
@devteam = rw
@guest =


Para que Apache tome los cambios se deben habilitar los módulos de svn y reiniciar el servicio

$ sudo a2enmod dav
$ sudo a2enmod dav_svn
$ sudo /etc/init.d/apache2 force-reload


Y por ultimo para probar que todo esta ok ejecutamos desde el browser

http://svn_server/svn/nombre_del_repo

Debe salir una pagina con el titulo "Revision 0: /"

Asi de facil se configura http con svn. Fijense que el esquema es mas seguro que el usado con svnserve porque el archivo de passwords esta encriptado. En la proxima parte vamos a usar MySQL para guardar los passwords, asi agregamos un nivel de seguridad mayor.

sábado, 17 de marzo de 2007

Arranco el baseball de Grandes Ligas

Para mi el momento en que arranca la temporada de baseball corresponde al momento en que creo mi equipo de Fantasy. Ya tengo unos cuantos años compitiendo en ligas de Sporting News y Yahoo y de verdad no me ha ido mal, una vez incluso gane una liga pero no me dieron el premio por vivir en la Florida :(

Ayer fue el día del draft de mi equipo de Yahoo en una liga con unos panas del trabajo. En esta liga se gana puntos por performance colectivo (mas hr, r, sb, w, etc) mientras que en la liga de Sporting News se gana puntos por performance individual. La verdad que pase una semana revisando estadísticas de jugadores y revisando la lista de lesionados (para no embarcarme) esperando armar un equipo balanceado, pero cuando llego el momento de hacer el draft había quedado en el turno 7!!!! Eso significa que mi equipo casi que automáticamente no iba a tener a Santana, Pujols, Howard, Utley, Cabrera o Alex Rodríguez al menos que los otros jugadores fuesen novatos o no supieran de baseball. En la primera ronda pude agarrar a Soriano y después me dedique a obtener jugadores que robaran bases por lo menos para ver si gano en esa categoría. Al final quede con un equipo con potencial de robar 200+ bases, batear 250+ hr, 800 +r, 1000+k, 120+w, todos esos numeritos basados en resultados de la temporada 2006. Creo que no me puedo quejar, el equipo se ve balanceado, ya el tiempo dira si fue buena mi decisión.

viernes, 16 de marzo de 2007

StatSVN

Una herramienta interesante para analizar los repositorios de subversion es StatSVN. Con ella se pueden obtener una serie de reportes interesantes que muestran la evolución de cada repositorio. Entre los reportes tenemos:
  1. Total de lineas de código en el tiempo
  2. Lineas de código por desarrollador
  3. Actividad por día y hora
  4. Total de archivos y tamaño promedio
  5. Repo map: una vista jerárquica dinámica del repo en los últimos 30 dias
  6. Archivos con mas revisiones

jueves, 15 de marzo de 2007

Subversion + UBUNTU - Parte 3

En la ultima parte nos encontramos con el problema de que no teníamos acceso al repositorio usando el protocolo svn. Para solventar esto debemos modificar la configuración de repositorio editando el archivo svnserve.conf ubicado en el directorio conf del repositorio.

$ cd ~/svn_repos/prueba/conf
$ vi svnserve.conf

Este archivo permite definir los accesos al repositorio. Fijense que esto se hace por repositorio y no de forma global. Este archivo contiene una sección general donde se definen las siguientes propiedades

[general]
#
# Acceso anonimo (read|write|none)
anon-access = read
#
# Acceso autorizado (read|write|none)
auth-access = write
#
# Archivo de claves de usuarios. Por defecto se usa passwd
# en el mismo directorio de configuracion pero se puede usar un
# archivo maestro para todos los repos
password-db = passwd
#
# Archivo de definicion de autorizaciones. Por defecto es authz
# en el mismo directorio de configuracion pero se puede usar un
# archivo maestro para todos los repos
authz-db = authz
#
#
realm = Autenticacion a repo prueba

Los archivos de passwords y de autorizaciones son similares al de configuración.

El de password contiene una entrada por cada usuario en formato texto. No muy seguro por cierto.

$ cat passwd
# Users
[users]
user1=pass1
user2=pass2
user3=pass3

El de autorización permite agrupar usuarios y asignarles accesos de lectura (r), escritura (rw) o ninguno (blanco). En el siguiente ejemplo vemos que solo el usuario user1 puede modificar el repositorio en su totalidad, y todos los usuarios del grupo 1 (user1, user2) pueden modificar lo que esta bajo /security en el repositorio. El resto de los usuarios o no tienen acceso o solo tienen acceso de lectura.

$ cat authz

[groups]
group1 = user1, user2
group2 = user3

[/]
user1 = rw
group2 = r

[/security]
group1 = rw
group2 =

Ahora ya estamos listos para subir algo al repositorio.

$ svn import . svn://localhost/prueba --message "Cambio"
Authentication realm: Autenticacion a repo prueba
Password for 'user1':
Adding prueba
Adding prueba/delete_svn_user.sh
Adding prueba/create_svn_user.sh
Adding prueba/create_svn_repo.sh
Committed revision 4.

En una siguiente parte voy a explicar como configurar subversion con apache para poder usar los protocolos http/https y para poder usar un tipo de autenticacion mas segura (evitar passwords en texto).


Subversion + UBUNTU - Parte 2

Como les comente en la sección anterior, para poder accesar los repositorios de forma remota debemos utilizar un server de svn. Actualmente hay 2 opciones Apache web server y svnserve. El primero nos permite accesar por http/https y el segundo nos permite accesar por tcp/ip usando un protocolo propietario (svn/svn+ssh). svnserve forma parte de la instalación de svn.

El servidor svnserve se puede invocar de tres formas

  1. Usando inetd: svnserve -i
  2. Standalone : svnserve -d
  3. Modo tunel: svnserve -t

El puerto por defecto es 3690. Para el primer caso se puede modificar en /etc/services, cambiando/agregando las siguientes entradas

svn 3690/tcp # Subversion
svn 3690/udp # Subversion

Si la ejecución es standalone el puerto se puede configurar por linea de comando usando los parametros --listen-port= y --listen-host=

El modo tunel se utiliza con SSH o RSH para autenticar el usuario.

Una vez que svnserve esta corriendo, todos los repositorios en el servidor estan disponibles para ser accesados de forma remota. Si se quiere aumentar la seguridad se puede indicar un directorio raiz y solo los repositorios bajo ese directorio estarán dsiponibles. Esto se logra con el parametro -r :

$ svnserve -d -r /dir/raiz/a/repositorios

Para accesar los repo se usa el url svn o svn+ssh. Aqui tenemos dos ejemplos de como accesar un repo con o sin directorio raiz. Como podran ver con el dierctorio raiz es mas dificil obtener informacion de la configuracion en el servidor.

Sin directorio raiz

$ svn checkout svn://host.svnserver.com/usr/local/svn_repos/proyectoA

Con directorio raiz

$ svn checkout svn://host.svnserver.com/proyectoA

Hasta este momento todo indica que estamos listos para trabajar con el repo, asi que podemos intentar subir algo en el repositorio creado durante la instalación de svn.

$ cd ~/tmp
$ svn import . svn://localhost/prueba --message "Inicio"
svn: Authorization failed


Fijense que aunque el checkout funciono de forma correcta el checkin no nos deja. En la siguiente parte explicare como arreglar este problemita.



Pruebas continuas

Una parte importante de la integración continua es probar los cambios para garantizar que hay integridad funcional en una aplicación. Aquí pueden ver un articulo interesante acerca de como hacer diferentes tipos de pruebas, desde la mas simples pruebas unitarias hasta las funcionales pasando por pruebas unitarias a la base de datos. El articulo habla de JUnit, DBUnit, Ant, JUnitPerf, Selenium, Cobertura y CruiseControl.

miércoles, 14 de marzo de 2007

PermGen OutOfMemoryError

Este problemita me ha estado dando desde hace un tiempo y por fin encontré un articulo que explica muy claro el porque del mismo y como solventarlo. Pueden leerlo en este link http://my.opera.com/karmazilla/blog/2007/03/13/good-riddance-permgen-outofmemoryerror

viernes, 9 de marzo de 2007

Subversion + UBUNTU

El primer paso para implementar una solución de integración continua consiste en seleccionar una herramienta de control de versiones para centralizar los fuentes. Existen varias opciones comerciales (PVCS, SourceSafe) y open source (CVS, SVN). Todas tienen sus pros y sus contras pero al final todas cumplen con su objetivo. Yo realmente considero que no hay herramienta mala sino mal utilizada. La experiencia me dice que si uno no se organiza y establece procesos claros la herramienta solo servirá para mantener un backup de nuestro propio desastre.

Para nuestro ejemplo voy a utilizar Subversion (SVN) , en primer lugar porque es gratis (viva el software libre), en segundo lugar porque las características que se describen en su site cumplen con mis requerimientos y en tercer lugar porque es popular. La instalación la voy a hacer sobre Ubuntu.

A continuación describo los pasos para hacer la instalación, crear un primer repositorio y accesarlo. Después veremos como usar Apache web server para accesar por http/https los repositorios y por ultimo como usar MySql para guardar la información de autenticación.

  1. Si no se trabaja como root se debe usar un usuario que pueda ejecutar el comando sudo. Esto se puede hacer colocando el usuario en un grupo que este definido en el archivo /etc/sudoers o agregando el usuario al mismo. Cuando se ejecuta el comando sudo el password que pide es el del usuario.
  2. Se debe verificar que se tiene acceso al repositorio universal de Ubuntu. Esto se hace revisando el archivo /etc/apt/sources.list para ver si las siguientes lineas están comentadas o no

    deb http://us.archive.ubuntu.com/ubuntu/ edgy universe
    deb-src http://us.archive.ubuntu.com/ubuntu/ edgy universe

  3. Instalar svn con el comando

    sudo apt-get install subversion

  4. Para probar la instalación usamos

    svn --version

  5. Para crear nuestro primer repositorio vamos a usar el comando svnadmin. Para ser practicos vamos a usar un mismo directorio padre para todos los repositorios. En este ejemplo voy a usar un directorio padre llamado svn_repos en el home del usuario y allí voy a crear un repo llamado prueba

    cd ~
    mkdir svn_repos
    svnadmin create ~/svn_repos/prueba

    Ahora verificamos que el repo se creo de forma correcta

    ls ~/svn_repos/prueba
    conf dav db format hooks locks README.txt


  6. Una vez creado el repo se puede importar data con el comando svn import. Por ejemplo, podemos cargar todo lo que este en ~/bin con el siguiente comando

    cd ~/bin
    svn import . file:///export/home/svn_repos/prueba
    --message 'Version inicial'



Fijense que si estamos en la misma máquina donde esta svn podemos accesar el repositorio usando urls del tipo file:///ruta/repo, pero en la realidad este escenario es muy raro, generalmente los repos se accesan desde máquinas remotas y para eso debemos configurar algun tipo de servicio que nos permita hacerlo. Actualmente svn se puede accesar de 2 formas, usando svnserve o usando Apache. Mas adelante hablare un poco de como usar svnserve y luego de como integrar svn con Apache web server para accesarlo con http/https.

Integración continua - CruiseControl + Maven 2

Buscando por la red encontré este podcast acerca de como utilizar CruiseControl con Maven 2 para implementar integración continua. Esta interesante, lo malo es que esta en ingles avanzado.

miércoles, 7 de marzo de 2007

Integración continua

Quizás uno de los mayores problemas que tenemos los desarrolladores que trabajamos en grupos es la de mantener consistencia en el código que modificamos. Mantener la integridad de una aplicación cuando muchas personas "le meten mano" se puede convertir en un caos si no se mantienen ciertos controles. Esto se evidencia mas si los desarrolladores no están en una misma ubicación física sino regados por el mundo. Este escenario particular es el que me encuentro actualmente, donde los desarrolladores se encuentra ubicados en Venezuela, Ecuador, Colombia, Argentina, España y USA.

Aquí la pregunta de las "40 mil lochas" es como hacer para lograr estos controles de tal forma que los desarrolladores puedan trabajar de forma estable sin verse afectados por los otros, y si ocurre el caso en que un desarrollador introduce un problema en el código este sea detectado de forma rápida. Bueno, la respuesta a esta pregunta la podemos encontrar aplicando el concepto de Integración Continua el cual es descrito en uno de los artículos mas famosos de Martin Fowler.

Básicamente el articulo indica que la mejor forma de mantener la integridad durante el desarrollo de software es que cada programador integre sus cambios al menos una vez por día y que una herramienta automatizada se encargue de verificarla además de ejecutar los unit tests respectivos, de tal forma de poder detectar errores lo mas pronto posible.

Actualmente existen una gran cantidad de herramientas que nos permiten realizar estas tareas. A continuación las enumero:

  1. Control de versiones: Es importante tener un repositorio donde se mantengan los fuentes y se lleve la historia de todos los cambios y quen los hizo. Varios ejemplos son Subversion, CVS, PVCS, Source Safe, etc. Todos los cambios en la aplicacion se ven reflejados en el repositorio, y la herramienta automatica genera los componentes a partir de alli. Es recomendable usar uno que este integrado al IDE de desarrollo.
  2. Generación de componentes (Build & Test) : En vez de realizar compilaciones manuales se deben usar herramientas que permitan la construcción de los componentes de una forma rapida, basicamente con la ejecucion de un solo comando, y que ademas permitan ejecutar una serie de test unitarios para verificar la integridad funcional de la aplicación. Varios ejemplos son make, Maven, Rake, Ant, Nant, etc.
  3. Automatización de la generación (Automate): La idea es tener una herramienta que permita obtener la ultima versión del repositorio, generar los artefactos de forma automatizada y ejecutar los test que permitan verificar la integridad funcional de la aplicación. En este grupo tenemos Cruise Control y Continuum. Adicionalmente la herramienta puede notificar los problemas encontrados usando diferentes medios como emails, irc, messengers, etc.
Los puntos 2 y 3 también son conocidos como BAT (Build, Automate & Test). El hecho de usar estas técnicas realmente nos facilita la vida y nos permiten dedicar mas tiempo a lo que realmente nos interesa, programar ... o navegar por internet :)

En un próximo articulo voy a explicar como implementar una solución completa de Integración continua usando algunas de las herramientas mencionadas arriba.