REPL para Java com Groovy Shell em projetos Maven

Por Alexandre Barbosa em 28/05/2014

Uma das coisas que sinto falta ao desenvolver em Java é a falta de um modo interativo (ou REPL), como os disponíveis em Python e Ruby. Um REPL é de grande ajuda quando queremos rapidamente testar a sintaxe de um método/função, ou executar uma tarefa simples. No projeto que estou trabalhando atualmente, que está sendo desenvolvido em Java me deparei com uma destas tarefas.

Uma das funcionalidades do sistema resulta na geração de um arquivo PDF a partir de algumas entidades do sistema. Isto foi implementado utilizando Jasper Reports. Basicamente, ela permite que se modele um relatório através de um arquivo XML, que é então compilado. O arquivo compilado pode então ser utilizado para gerar os arquivos PDF de forma dinâmica.

Ao entrar no projeto, a equipe utilizava a ferramenta iReport para modelar e compilar os relatórios. Como eu estava com preguiça de instalar esta aplicação, e precisava realizar mudanças pontuais, resolvi editar o XML e compilá-lo manualmente. Para isto, um REPL seria perfeito. Mas Java não possui um, então como fazer?

A resposta no meu caso foi utilizar Groovy, uma linguagem dinâmica para a JVM, que possui uma sintaxe própria, mas que permite fazer uso das classes e bibliotecas Java existentes. E, como era de se esperar, possui um REPL - Groovy Shell.

A única dificuldade seria configurar o classpath do Groovy Shell, para carregar as bibliotecas do Jasper Reports. Mas como o projeto utiliza Maven para gerenciar suas dependências, procurei uma forma de integrar os dois. E para nossa alegria, há um plugin para o Maven que viabiliza esta integração: Groovy-maven-plugin. Uma vez configurado, basta executar

mvn groovy:shell

e pronto, você poderá importar qualquer classe do seu projeto, ou de suas dependências, e brincar à vontade. Eis como ao final compilei meu relatório:

groovy:000> import net.sf.jasperreports.engine.JasperCompileManager 
===> [import net.sf.jasperreports.engine.JasperCompileManager]
groovy:000> JasperCompileManager.compileReportToFile("src/main/resources/jrxml/relatorio.jrxml", "relatorio.jasper")


Gostou do artigo? Compartilhe!




Usando redis como backend de cache no Django

Por Miguel Galves em 16/10/2013

Um dos patterns mais simples implementáveis com Redis é o de armazenamento de pares (chave, valor):

SET key value
GET key
DEL key 

E assim como em outras ferramentas como memcache, é possível definir um tempo de vida máximo da chave no Redis, em segundos (EX), ou milisegundos (PX):

SET key value EX 60 # 1 minuto
SET key value PX 1000 # 1s

Com estas primitivas, podemos montar um mecanismo de cache de dados, com a grande vantagem de ser um cache compartilhável por várias máquinas / processos separados, uma vez que o Redis é um servidor acessível via IP/porta.

Usando a biblioteca redis-py, o código para armazenar um texto no cache seria:

import redis
backend = redis.Redis()
backend.set("mycache", "this is a cached string")

Se quisermos definir um tempo máximo de vida para esta entrada no cache, utilizaramos a chamada setex:

import redis
backend = redis.Redis()
backend.setex("mycache", "this is a cached string", 60) # cache vive por 1 minuto

O código para obter os dados no cache, evitando um novo processamento, seria o seguinte:

import redis
backend = redis.Redis()

cached = backend.get("mycache"):
if cached:
    return cached:

# Dados não estao no cache...efetua o processamento
o processamento ocorre aqui

Quem desenvolve sistemas web com Django sabe que o framework oferece uma abstração de Cache, disponível no pacote django.core.cache, que permite vários níveis de granularidade (site inteiro, por view, por fragmentos de template, chamada direta) e vários backends diferentes (de fábrica estão disponíveis cache em memória, arquivo, base de dados, e memcache).

E obviamente que neste mundão de meu deus alguma boa alma implementou um pacote que conecta o cache do django ao Redis. Existem aliás algumas opções, e depois de alguns testes acabei optando pelo django-redis. A instalação pode ser feita através do pip

pip install django-redis

A integração com o Django se faz através do arquivo settings.py:

CACHES = {
    "default": {
        "BACKEND": "redis_cache.cache.RedisCache",
        "LOCATION": "127.0.0.1:6379:0",
        "OPTIONS": {
            "CLIENT_CLASS": "redis_cache.client.DefaultClient",
            'PARSER_CLASS': 'redis.connection.HiredisParser',
        }
    }
}

O parâmetro LOCATION define o IP, porta e database usada pelo cache, e o OPTIONS define a classe cliente (redis_cache.client.DefaultClient), e o parser usado para comunicação com o Redis (redis.connection.HiredisParser).

Em relação ao parser, é aconselhável a instalação do pacote hiredis, uma implementação em C do protocolo de comunicação com Redis que chega a ser 10x mais rápida do que o driver padrão em Python. A instalação do HiRedis é muito simples:

pip install hiredis

O django-redis oferece uma série de opções interessantes, como configuração de SHARDING) usando diferentes instancias de Redis, entre outras. Sugiro a leitura da documentação.

Sim, as vezes ajuda.


Gostou do artigo? Compartilhe!




REDISCO

Por Miguel Galves em 14/10/2013

Nos últimos meses, tenho escrito uma enorme quantidade de código em Python usando Redis como servidor de estrutura de dados e cache. Aliás, posso dizer que Redis se tornou uma ferramenta central e essencial nos meus projetos. E com o aumento de linhas de código usando basicamente a excelente biblioteca redis-py, tem aumentado a minha necessidade de jogar certas coisas por debaixo dos panos. Tipo ORM.

ORMs são temas de discussões acaloradas: pessoas amam, pessoas odeiam. Eu odiava, muito por conta do Hibernate. Com o Django, aprendi a usar, gostar, e saber que ele irá falhar em algum momento, sobretudo quando performance entra em jogo. No caso do Redis, conseguir abstrair um pouco as estruturas de dados, e trabalhar um nível acima com objetos deixaria o código mais elegante, conciso e fácil de trabalhar. Além disso, seria muito útil poder trabalhar com estruturas de dados de uma forma pythonica.

Tendo isto em mente, fui à caça de opções disponíveis, e descobri que não haviam muitas. Nas minhas várias pesquisas, acabava sempre esbarrando no rom e no redisco. Minha primeira tentativa foi com o rom, por parecer ser um projeto mais ativo e mais recente. Um dia de trabalho foi suficiente para fazer a primeira migração e perceber que 1) funciona 2) tem sérias limitações. O que mais me incomodou foi uma API um tanto quanto inconsistente e com alguns furos. Sem contar que a versão 0.20 disponível no PyPi simplesmente não rodava, por falta de um arquivo no pacote (a versão 0.21 saiu graças à minha reclamação).

Depois de alguns dias tentando contornar as limitações e tentando conversar com os desenvolvedores (que não se mostraram muito flexíveis), resolvi começar a escrever uma biblioteca própria. A idéia inicialmente era mapear as estruturas de dados disponíveis no Redis (List, Set, SortedSet, Dict) em estruturas de dados Python, mantendo sempre que possível uma sintaxe pythonica. O resultado foi o projeto redis-datastore, cujo resultado ficou bem razoável e cheio de testes.

Mas aí, chegou o momento de implementar o mapeamento de objetos, e, confesso, bateu certa preguiça. Resolvi revisitar os projetos mencionados anteriormente, e desta vez escolhi experimentar o Redisco. O ponto interessante era o fato dos desenvolvedores terem implementado uma API mais consistente, inspirada no QuerySet do Django, implementado estruturas de dados e algumas funcionalidades extras úteis. Mas haviam alguns bugs e ainda sentia falta de algumas funcionalidades. Seguindo as premissãs do mundo do Software Livre, decidi fazer um fork próprio, disponível aqui, e implementar as modificações.

Alguns dos pontos que estou trabalhando neste fork:

  • Corrigir bugs (já encontrei e corrigi alguns);
  • Performance;
  • Evoluir a API, adicionando funcionalidades e usando como base a API do QuerySet do Django, que já se tornou padrão e está bem maduro;
  • Evoluir arquitetura, sempre que possível. Estou aos poucos mergulhando no código, e sempre que encontro algo questionável, faço refactoring;
  • Fazer o merge do redis-datastore.

Fiz alguns pulls requests para o projeto original (que já é um fork do projeto criado pelo Tim Medina e que foi oficialmente descontinuado), e a julgar pela falta de resposta, me parece que este foi descontinuado também. Veremos. No caso do meu fork, estou trabalhando ele em paralelo com um projeto profissional que usa a biblioteca. Portanto, estou “vivendo o projeto”.

Interessado em colaborar? Chega mais!


Gostou do artigo? Compartilhe!




Calatrava

Por Alexandre Barbosa em 12/09/2013

A questão da experiência do usuário (UX) tem se tornado cada vez mais importante no desenvolvimento de aplicações, em especial no mundo das aplicações móveis, em função das limitações físicas dos dispositivos, e das especificidades de cada plataforma. Idealmente, desenvolver uma aplicação nativa para cada plataforma seria a melhor solução, pois pode-se assim entregar ao usuário a melhor experiência de acordo com os padrões definidos para o seu dispositivo. No entanto, isto implicaria em um alto investimento em desenvolvimento. Neste instante, passamos a pensar em alternativas para reduzir este investimento.

Calatrava é um framework que se apresenta como uma destas alternativas (ao menos quando se pensa em iOS, Android e Web Mobile). Diferente de outros “cross platform frameworks” como PhoneGap que substitui o poder das interfaces nativas por interfaces web, Calatrava permite que você desenvolva a lógica de sua aplicação em JavaScript, e então a compartilhe entre as diversas plataformas.

Para tanto este framework faz uso da separação entre a camada de apresentação e a lógica do domínio. Calatrava define o conceito de Page, que corresponde à uma tela ou página de sua app. Em uma aplicação para iOS uma Page é implementada por uma ViewController, em Android por uma Activity, e para Web Mobile por um trecho de Haml e CoffeeScript.

Uma Page emite eventos que são processados por controllers, que implementam a lógica de sua aplicação em JavaScript. Estes controllers são executados em um interpretador JavaScript embarcado na aplicação nativa. Calatrava então provê uma bridge nativa, que faz a orquestração entre as pages e os controllers.

Esta estratégia permite ainda uma estratégia de desenvolvimento evolutivo: desenvolva inicialmente sua aplicação para Web Mobile e então utilize a interface web implementada nas aplicações iOS e Android. Para tanto, basta que em iOS as pages sejam implementadas por extensões de WebViewController, e em Android por extensões de WebViewActivity. A partir disto, pode-se evoluir as aplicações nativas iOS e Android uma page de cada vez, iniciando-se por aquelas que mais se beneficiariam com os elementos nativos.

O projeto é recente, e tem ainda muito a caminhar. Atualmente, a maior deficiência desta plataforma está no restrito número de plugins para integração de elementos nativos com o código de negócio. No entanto, o código é aberto, o que permite que qualquer um colabore para sua evolução, e por isto acredito que em breve esta plataforma estará em um nível de maturidade comparável ao PhoneGap, por exemplo.


Gostou do artigo? Compartilhe!




Schemeless URLs

Por Miguel Galves em 14/06/2013

Descobri esta semana a existência dos schemeless URIs, endereços sem a definição do protocolo (HTTP ou HTTPS). Já tinha esbarrado com os dito-cujos no CDN do Google, caçando bibliotecas JS. Os mais atentos já notaram que os códigos de embed são sempre no formato

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>

Na minha ignorância e pedância costumeiras, achava que era um erro do Google. Mas Google não erra.

E aí, a audiciência se pergunta: what the hell?

Bom, a grande vantagem deste esquema é que os navegadores, quando encontram um link num documento HTML sem HTTP ou HTTPS, assumem que devem usar o protocolo da página pai. Portanto, se eu acesso

http://siga.st

o navegador irá acessar

http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js 

Se eu acessar

https://siga.st

o navegador irá acessar

https://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js 

Se eu acessar

gopher://siga.st

não vai dar em nada (Definição de Gopher aqui).

O grande interesse desta funcionalidade é que alguns navegadores, como o Chrome por exemplo, não permitem carregar arquivos externos via HTTP a partir de um endereço base HTTPS (quem já tentar verá uma mensagem no console do tipo “SITE A ran insecure content from SITE B”).

Usando o esquema sem protocolo definido, o programador web cobrirá todos os casos.


Gostou do artigo? Compartilhe!




Eu fui no Google I/O 2013

Por Daniel Cassiano em 07/06/2013

Estive em San Francisco para acompanhar de perto as novidades que o Google lançaria no I/O 2013, realizado entre os dias 15 a 17 de maio, no Moscone Center - local que inclusive também é realizada a WWDC da Apple.

Foi minha primeira vez no evento, porém foi fácil perceber que as outras edições já contavam com a mesma super estrutura (segundo alguns até melhor nos anos anteriores): uma área de expositores chamada Sandbox, a famosa lojinha de gadgets do Google e é claro: as sessions e os code labs.

O keynote foi recheado de releases e seguiu os rumores: o foco estava em software e não em hardware como em 2012. A cada pacote de features um diretor ou engenheiro responsável era chamado para detalhar o que estava por vir.

Os destaques foram:

  • release de mais de 40 features para o Chrome Dev Tools, que dá a partir de agora muito mais ferramentas para os devs de frontend;
  • release do Android Studio que coloca o desenvolvimento de apps pra plataforma em outro patamar;
  • Google+ Photo Tools fazendo frente ao Instagram;
  • Google Now enfim utilizando o Knowledge Graph e basicamente “lendo seus pensamentos”;
  • Google Play Music All Access tentando abocanhar o espaço de Spotify e Rdio;
  • e por último, o novo Maps que além de um novo design e maior velocidade, agora tem previsão do tempo do momento e o Earth incluso.

As sessions foram de um teor mais comercial/evangelizador do que técnico em si. Em todas que participei havia um engenheiro do Google e em algumas raras vezes, algum parceiro. Em diversos momentos houveram questionamentos onde as respostas foram “I can’t talk about that”, o que nos frustrava imensamente na hora pois a maioria ali queria isso. Mas enfim, o evento era deles. O meu destaque foi para algumas sessions que participei de Go que foram realmente úteis e de quebrar a cabeça. As que envolviam o Google Glass eram impossíveis de se entrar sem pegar 1 hora de fila pelo menos.

Já estão disponíveis todas as sessions no canal dos Developers no YouTube.

Tive a oportunidade de testar o Google Glass e devo dizer: é sensacional! Não tive tempo suficiente para explorar porém foi altamente entusiasmante experimentar a tecnologia. Existem diversos vídeos no YouTube porém nunca se sabe o que é real o que é uma paródia. Fato é que o trem 1 funciona muito bem e dá outro nível de possibilidades ao dia-a-dia. Como haviam desenvolvedores que já estavam com os seus (2 mil “sortudos” residentes nos EUA que se cadastraram no I/O do ano passado ganharam um), era possível ver pessoas andando nas ruas próximas ao evento interagindo com o Glass, dando comandos de voz. Foi uma sensação de Jetsons ao extremo!

![](/images/cassiano_google_glass.png)

Podemos dizer que o foco do evento foi mostrar que o Google quer consolidar suas plataformas e dispositivos e que estavam trabalhando há muito tempo em novas features. Estão atacando mercados recém abertos e explorados por outras marcas como o Instagram e o Spotify e trazendo grande evolução aos seus produtos já lançados. Só agora estão fazendo uso da infinidade de dados que coletam/processam com o Knowledge Graph o que nos deixa curiosos com o que está por vir. O Android é uma realidade, o Glass uma excitante incógnita e Chrome OS algo que talvez esteja uns 5 ou 10 anos adiantado. Estão mais fortes do que nunca, inovando como sempre.


  1. termo genérico utilizado por pessoas oriundas do estado de Minas Gerais para falar de absolutamente qualquer coisa.


Gostou do artigo? Compartilhe!




MySQL e os collations da vida

Por Miguel Galves em 06/06/2013

AWS virou minha plataforma base para deploy de 100% dos meus projetos. E com ele, veio o MySQL, já que o RDS (serviço de base de dados do AWS) não oferece a opção de usar Postgres. O Raphael Lullis dirá para eu deixar de ser preguiçoso e fazer o meu próprio deploy…e meu próprio backup….e minha própria manutenção…..fiquemos com o MySQL.

É fato que o ORM do Django simplifica bastante o trabalho de lidar com diferentes bases de dados. Mas nunca devemos nos esquecer do conceito das Leaky Abstractions do Joel Spolsky: desde que passei a usar o MySQL, esbarro constantesmente com a necessidade de ajustes de baixo nível.

No início da semana, resolvi migrar a base de dados do produto novo que estamos desenvolvendo de SQLite (ambiente de desenvolvimento) para MySQL (ambiente de produção). Rodei os scripts de migração / geração de tabelas e afins, e fui importar dados de uma tabela para outra. Entre estes dados, uma lista gigantesca de nomes de países e cidades em diversas línguas, construída para um serviço simples de detecção de localização em textos e perfis de Twitter (projeto este que provavelmente algum dia vira Open Source e vai para no GitHub).

Obviamente, falou em nome de países e cidades em diversas línguas (incluindo russo, coreano, japonês, chinês e árabe), falou UNICODE e UTF8. Falou UNICODE e UTF8, falou em dores de cabeça. Duro viver num mundo tecnológico criado por pessoas que falam uma língua ASCII.

Usei a ferramenta de dump / load de dados do próprio Django, que exporta os dados para um formato intermediário independente de base de dados (JSON ou XML), e que funciona muito bem. Mas na hora de gravar o nome Albânia na base nova, recebi uma mensagem de erro dizendo que estava violando uma regra de integridade porque já havia uma linha com este nome. Fucei um pouco e descobri que havia sim um Albania (note a falta do acento circunflexo). Ou seja, para o MySQL, Albania era igual a Albânia.

Inicialmente pensei que fosse um problema de codificação do arquivo de dump gerado. Pesquisei no Google, cacei fóruns obscuros e achei algumas pessoas dizendo que algumas vezes o JSON podia ser gerado errado, sugerindo o uso de XML. Gerei XML, mesmo erro.

Daí, tive um lampejo genial (só que não): o Django permite gerenciar múltiplas bases de dados, e permite selecionar em runtime quais bases serão usadas para leitura e para escrita. Bastava portanto escrever um script que lesse os dados do SQLite e gravasse no MySQL. No meio do caminho, o próprio Python se encarregaria de tratar de forma apropriada a codificação dos caracteres. Escrevi o script e …. PAU: Albania continuava sendo igual a Albânia. Aí, era inevitável: teria que passar por cima do ORM e enfiar a cabeça debaixo do capô do MySQL.

As tabelas haviam sido criadas em UTF-8, portanto o problema era outro. Rodando o comando SHOW TABLE STATUS, que exibe informações uteis sobre as tabelas de sua base, descobri o tal do Collation, que nada mais é do que a regra usada pelo MySQL para fazer comparações entre campos de texto. No caso das minhas tabelas, todas estavam com collation utf8_general_ci; isso basicamente significava que as comparações eram CASE INSENSITIVE (ci), e que A era equivalente A, Ã, Â, etc… (a título de curiosidade, mudando ci por cs, a comparação vira CASE SENSITIVE).

Encurtando a história: no meu caso a solução era usar utf8_bin, que faz a comparação de forma binária, sendo portanto mais precisa e mais lenta também. Uma lista bem completa dos tipos de collations pode ser encontrada aqui.

Minha opinião sobre o tema: faz todo o sentido poder definir a precisão da comparação de textos. Isso pode se tornar uma otimização muito útil, dependendo da classe de aplicações desejadas (eu diria que 99% dos sistemas podem se beneficiar disto).

Nada como conhecer minimamente a ferramenta que se está usando….


Gostou do artigo? Compartilhe!




Vagrant + Chef + AWS

Por Miguel Galves em 26/04/2013

![](/images/phyno.jpg)

Quando comecei a me interessar pelo tema Vagrant + Chef (cuja solução eu descrevi aqui), uma questão básica que eu quis responder desde o início era:

OK, eu consigo montar uma VM local e ter um ambiente de desenvolvimento / testes idêntico ao ambiente de produção. Mas como eu uso essas ferramentas para criar o meu ambiente de produção no AWS?

A versão 1.1 do Vagrant trouxe uma resposta parcial para o meu questionamento, ao criar o conceito de PROVIDER de virtualização, e permitir o uso de outros serviços além do VirtualBox. Entre eles, o uso de AWS. O Vagrant 1.2, lançado recentemente, parece permitir a gestão de diversas máquinas usando vagrant (coisa que acabo de descobrir, e que será objeto de nova pesquisa e novo post).

Vamos a mais uma receitinha de bolo. Sigam-me os bons:

  • Execute o passo-a-passo descrito no post Vagrant + Chef;

  • Crie uma conta no AWS, caso já não tenha uma (sempre é bom verificar…);

  • Instale o plugin vagrant-aws:

    > vagrant plugin install vagrant-aws

  • Adicione uma Dummy Box no vagrant, que será considerada como um box AWS. O jeito mais simples de fazer isso é utilizando a box criada por Mitchell Hashimoto:

    > vagrant box add dummy https://github.com/mitchellh/vagrant-aws/raw/master/dummy.box

  • Adicione um bloco novo no seu Vagrantfile, descrevendo e parametrizando a instância a ser criada no EC2:

      Vagrant.configure("2") do |config|
          config.vm.provider :aws do |aws|
              aws.access_key_id = "CHAVE DE ACESSO API AWS"
              aws.secret_access_key = "CHAVE SECRETA DE ACESSO API AWS"
              aws.keypair_name = "NOME DO PAR CHAVE/VALOR PARA ACESSO SSH"
              aws.ssh_private_key_path = "CAMINHO DO ARQUIVO CHAVE/VALOR PARA ACESSO SSH"
              aws.ami = "ami-3d4ff254"
              aws.ssh_username = "USERNAME"
              config.ssh.username = "USERNAME"
              aws.instance_type = "TIPO DE INSTANCIA. Ex: c1.medium"
              aws.security_groups = ["LISTA DE GRUPOS DE SEGURANCA",]
          end
      end
  • Execute:

    > vagrant up --provider=aws

Seguindo este passo-a-passo, o resultado final será uma instancia do EC2 provisionada com seus scripts Chef. Caso tenha usado o script descrito no post anterior, você terá um servidor NGinx servindo um Hello World.

O plugins vagrant-ssh está disponível no github.


Gostou do artigo? Compartilhe!




DevOps, NoOps. Afinal, que raios é isso?

Por Miguel Galves em 15/04/2013

Estou como autor deste post, mas na verdade o autor deveria ser o nosso colega Thiago Ganzarolli, que é o real autor da apresentação sobre DevOps abaixo. Achei propício, tendo em vista o tema abordado no meu último post.


Gostou do artigo? Compartilhe!




Vagrant + Chef

Por Miguel Galves em 11/04/2013

![](http://devopsdotcom.files.wordpress.com/2013/02/devops-define-roles.jpg)

Desenvolvedor de startup codifica, testa, publica, mantém infra, desenha telas, atende telefone e lava a louça do cafezinho no fim da tarde. E aí, o único jeito de se manter digno e produtivo é automatizar tudo o que puder ser automatizado, economizando tempo e erros bestas. Além do mais, em tempos de computação nas nuvens, hardware virou software e a melhor forma de tirar proveito desta flexibilidade é automatizando o processo de criação e configuração de suas máquinas. Assim, fica possível expandir, reduzir e substituir servidores com um ou dois cliques.

No SIGA, usamos intensivamente os serviços da Amazon AWS, temos alguns servidores rodando (e em alguns casos, este número varia automaGicamente conforme a necessidade), e apenas um coitado gerenciando tudo: eu. Me vi obrigado a procurar soluções, e o Fabric caiu como uma luva. Montei um script capaz de gerenciar minhas máquinas na Amazon (start, stop, reboot), os serviços disponíveis em cada, além de configuração inicial e atualização de código.

Tudo muito bom, tudo muito bem, cheguei ao limite desta solução, por vários motivos:

  1. Totalmente amarrado à infra da Amazon;
  2. Totalmente amarrado ao Ubuntu;
  3. Desenvolvido de forma orgânica e sem muito planejamento. A portabilidade do script entre projetos melhorou muito, mas ainda é precária;

Procurando soluções, comecei a prestar mais atenção no Chef. E a coisa realmente começou a me interessar quando fui apresentado ao Vagrant. Resumindo muito cada ferramenta, o Chef é um sistema que automatiza a configuração de máquinas e instalação de pacotes, através de receitas (recipes), sendo capaz de lidar com sutilidades de diversos sistemas operacionais.

Chef provides a flexible model for reuse by enabling users to model infrastructure as code to easily and consistently configure and deploy infrastructure across any platform.

Já o Vagrant é um criador de máquinas virtuais, sendo capaz de gerar VMs do VirtualBox e VMWare a partir de um script.

Create a single file for your project to describe the type of machine you want, the software that needs to be installed, and the way you want to access the machine. Store this file with your project code.

Como você já deve ter adivinhado, o Vagrant usa o Chef para configurar e instalar pacotes em uma VM. Ambos permitem transformar a configuração de uma máquina em um simples script, que pode ser facilmente distribuido entre todos os desenvolvedores de um projeto (resolvendo outra dor de cabeça: ambientes heterogêneos. Quem nunca sofreu com isso que jogue a primeira pedra).

Resolvi por a mão na massa e montar setup básico para criar uma VM Ubuntu 12.04 com NGINX servindo uma página HELLO WORLD. Deu certo, e resolvi compartilhar este código com o mundo. Como este texto já está ficando longo, vou dar aqui apenas a receitinha de bolo pra executar o meu setup que, espero, poderá servir de ponto de partida para outros interessados no assunto.

Vamos lá:

  1. Instale o VirtualBox, disponível em https://www.virtualbox.org/;

  2. Instale Vagrant >= 1.1.X, disponivel no site http://vagrantup.com;

  3. Instale ruby 1.9;

  4. Instale chef:

    > gem install chef

  5. Instale o plugin vagrant-omnibus. Ele garante que o Chef estará instalado na versão correta na VM:

    > vagrant plugin install vagrant-omnibus

  6. Instale uma box do Ubuntu 12.04 no Vagrant :

    > vagrant box add precise64 http://dl.dropbox.com/u/1537815/precise64.box

    (caso prefira outro sabor de Linux, existe uma lista bastante grande de listadas em http://www.vagrantbox.es/)

  7. Baixe o meu template de código no GitHub:

    > git clone git://github.com/mgalves/vagrant-chef-nginx.git

  8. Entre no diretório vagrant-chef-nginx/chef_repo;

  9. Rode o comando:

    > vagrant up

  10. Acesse http://192.168.33.10/;

  11. Hello World!


Gostou do artigo? Compartilhe!




Ver textos anteriores