[Alexandre Martins] Deployment Smoke Tests: Is Anyone Being Slack?

August 12th, 2010

I’ve always been a huge fan and advocate of using tests for developing applications. For me, working on a software without a decent suite of test is like walking on eggshells, each modification brings out the risk of breaking something on the system. To mitigate this risk I always make sure I have a minimum set of unit, integration and acceptance tests covering my application.

But does all that gives us the confidence that the system will work perfectly when it’s deployed to any of the environments, on its way through the release pipeline? I thought so until work with this guy and read this book. Tom Czarniecki firstly introduced me the concept os smoke tests, then reading Jez Humble and David Farley’s Continuous Delivery I could grok the real values of using it in conjunction with a build pipeline.

What are smoke tests?

As aforementioned, deployment smoke tests are quite handy because they give you the confidence that your application is actually running after being deployed. It uses automated scripts to launch the application and check that the main pages are coming up with the expected contents, and also check that any services your application depends on— like database, message bus, third-party systems, etc —are up and running. Alternatively you can reuse some acceptance or integration tests as smoke ones, given that they are testing critical parts of the system. The name smoke test is because it checks each of the components in isolation, and see if it emits smoke, as did with electronic circuits.

smoke_tests.png

Provide clear failure diagnostics

If something goes wrong, then your smoke tests should give you some basic diagnostics explaining the reasons why your application is not working properly. In our current project at Globo.com, we are progressing towards start using Cucumber to write our smoke tests, thus having a set of meaningful and executable scripts, like this one below.

Feature: database configure
  System should connect to the database
  Scenario: should connect to the database
    When I connect to "my_app" database as root
    Then it should contain tables "users, products"

For those who like using Nagios for monitoring infrastructure, Lindsay Holmwood wrote a program called cucumber-nagios which allows you to write Cucumber tests that output the format expected of Nagios plugins, so that you can write BDD-style tests in cucumber and monitor the results in Nagios.

Knowing quickly whether you are ready or not!

Clearly rapid feedback and safety are the two major benefits of introducing smoke tests as part of a release process.

Rapid feedback

In our project, we implemented a deployment pipeline, so each new commit into the source repository is a potential deployable version to any environment, even to production. So we have the commit-stage where we run all the quick tests, and as soon as all of them passes, the acceptance-test-stage is automatically triggered, and the longer tests— integration and acceptance —are run, and once they’ve also passed, the application is automatically deployed into the dev environment. Getting a green at this stage means that it’s successfully deployed and smoke tested. But there still some exploratory testing to be performed before releasing this version into the staging environment. And in our team, this is done by the product owner, together with a developer. So as soon as they are ready to sign the story off, all they have to do is click the manual button which in turn deploy the application into the qa1 (UAT) environment, and if it’s green they can proceed, otherwise they pull the cord because something is malfunctioning, as you can see on the picture.

Screen shot 2010-08-11 at 4.13.01 PM.png

Don’t let the application deceive you

It’s quite frustrating, when all you need is the system to work as expected, because you are about to showcase it to your customers, and the first thing you click, all you see is a big and ugly error screen, instead of the page they were expecting. And later on you find out that it was due to database breakdown. What an embarrassing situation that could have been avoided by simply checking the smoke test diagnostics before showcasing.

[Tiago Motta] Aumento de produtividade por ponto de complexidade

August 9th, 2010

Tenho ouvido ultimamente muitos amigos da área comentando sobre pressão por aumento de produtividade baseada em pontos de complexidade. Isso me deixa bastante preocupado. Embora seja nobre o desejo de aumentar as entregas da área de desenvolvimento, quantificar isso usando os pontos de complexidade das histórias não quer dizer muita coisa.

Contudo antes de simplesmente reclamar contra a pressão, é preciso analisar as possiveis causas de produtividade baixa que possam estimular esse tipo de pressão. Pensando bastante cheguei a três possibilidades, e com elas, possiveis soluções, que seriam mais eficazes do que estimular aumento desse tipo de numero.

1- Não há confiança de que o time esteja trabalhando em seu máximo. Ou seja, o agente gerador de pressão acredita que os integrantes estão fazendo corpo mole ou gastando o dia com amenidades ao invés de se focar na entrega do projeto. A pressão por aumento de pontos de complexidade pode até resolver esse problema temporariamente, mas também pode ser mascarado por integrantes do time que se sentem coagidos a fazer horas extras para cobrir as entregas esperadas. Ou seja, o problema só se resolve mesmo com conversas francas e com uma presença mais ativa do interessado.

2- O time percebendo folga na iteração aproveita para melhorar a qualidade da entrega ainda mais. Esse tipo de preciosismo costuma acontecer com bastante frequência. Muitas vezes o desenvolvedor por ter mais tempo para pensar aproveita para implementar testes e fluxos mais rebuscados evitando bugs que no futuro tomariam o triplo do tempo, e o designer aproveita para criar e rebuscar as interfaces e assim encantar ainda mais o cliente. Neste caso a pressão pelo aumento de entrega de pontos de complexidade apenas estimula a diminuição da qualidade. Ou seja, embora haja um aumento imediato na velocidade, em pouco tempo ela cairá por causa das correções de bugs e dos ajustes visuais.

3- O time é inexperiente ou não conhece a tecnologia adotada. Neste caso pressionar pelo aumento de entrega de pontos de complexidade de nada adianta. De certa forma, com o tempo, naturalmente as entregas serão maiores, ou em muitos casos menores pois o time começará a estimar com menos pontos, demonstrando assim a ineficácia desse numeros para medir produtividade. Para resolver este problema existem diversas opções como, organizar dojos, estimular programação em par, indicar livros e treinamentos, estimular a experimentação com tempo para projetos pessoais.

Todas três possibilidades acima eu vi acontecer de perto nos times em que trabalhei. E quase sempre o problema foi resolvido sem utilizar os pontos de complexidade como parâmetro de medição. E vocês lembram de alguma outra causa de produtividade baixa? Tem idéia de como solucionar? Qual sua opinião sobre o assunto?

[Rafael Biriba] Crontab: rodando um script a cada 15 segundos

August 1st, 2010

crontab
Criei esse POST com 2 objetivos: Para compartilhar a minha idéia e quem sabe também obter novas maneiras de resolver um pequeno problema.

Problema: Digamos que você tenha que acessar uma URL qualquer (exemplo: http://localhost:3000/coletar ) a cada 15 segundos. Isso rodará um script que irá colher uma série de dados e armazena-los em banco.

Então, se você rodar um comando como este: “curl http://localhost:3000/coletar” a cada 15 segundos, resolveria meu problema. Agora, como fazer isso usando crontab ?

Se você procurar a solução na internet, encontrará algumas boas idéias como fazer um script e com alguns sleeps e um loop interno você não precisa nem de cron:

#!/bin/sh
while [ 1 ]; do
    curl "http://localhost:3000/coletar"
    sleep 15
done

Basta rodar esse script, que com um loop eterno, vai rodar o comando de 15 em 15 segundos… Agora você deve estar pensando: “Problema resolvido!” …

Na verdade, não. Os dados precisam ser coletados necessariamente a cada 15 segundos. Isso significa que se por acaso, quando for feito um request, se o servidor demorar pra responder aquela solicitação, isso pode atrasar a próxima coleta, e depois de algum tempo, o atraso só tende a piorar.

Então qual a melhor solução para este problema ?
Como eu preciso coletar a cada 15 segundos sem que uma coleta atrapalhe a outra, acho que a melhor forma de fazer isso foi adicionar no crontab do usuário:

* * * * * curl 'http://localhost:3000/coletar'
* * * * * sleep 15 && curl 'http://localhost:3000/coletar'
* * * * * sleep 30 && curl 'http://localhost:3000/coletar'
* * * * * sleep 45 && curl 'http://localhost:3000/coletar'

Com isso, os comandos serão executados independentemente a cada 15 segundos…

Então é isso…

Se você conhece alguma forma mais eficiente para fazer isso… Não deixe de  compartilhar a sua idéia comigo ;)


Leia também:

[Alexandre Martins] TDD: Listen to the tests… they tell smells in your code!

July 28th, 2010

These days, reading the Goos book, by Steve Freeman and Nat Pryce, it reminded me of a project I worked on a while ago. It was a one year old system, poorly tested, integrating to a handful of other systems, and the code-base… well I prefer not to remember. Despite this scenario, I joined the team to help them implement some new functionalities.

I remember sometimes it was difficult to write tests, the classes were tightly coupled, with no clear responsibilities, several attributes, bloated constructors, etc. And despite our best effort, working around the bits that were preventing us from writing the tests, we felt we were getting down the wrong road, trying to do it in such a crappy code-base. As a result some of our tests were massive! A bunch of lines of mocks, stubs, and expectations, making it impossible to understand their purpose.

What have I learned?

Reading one of the book chapters I learned that the same qualities that makes an object easy to test also makes the code responsive to change. In my situation, the tests were telling me how clumsy the code was and how difficult it would be to extend it.

I also learned that when we come across a functionality that is difficult to test, asking ourselves how to test it is not enough, we also have to ask why is it difficult to test, and check whether it’s an opportunity to improve our code. The trick is to do it driven by tests, so we can get rapid feedback on code’s internal qualities and on whether it’s doing what it’s supposed to do.

So they introduced a variation for the well-known TDD cycle— Write a failing test” => “Make the test pass” => “Refactor. As described on the figure below (extracted from the book), if we’re finding it hard to write the next failing test for our application, we should look again at the design of the production code and often refactor it before moving on, until we get to the point that we can write tests that reads well.

Extracted from Growing Object-Oriented Software, Guided By Tests— Steve Freeman and Nat Pryce

An Example of a Smell Tests Might Be Telling You

Reference data rather than behavior

When applying “Tell Don’t Ask” or “Law of Demeter” consistently, we end up with a coding style where we tend to pass behavior into the system instead of pulling values up through the stack. So picking up the famous Paperboy example, before refactoring the code applying the “Law of Demeter” the code and test would look something along the lines of the snippet showed below.

class Paperboy
  def collect_money(customer, due_amount)
    if due_amount > customer.wallet.cash
      raise InsuficientFundsError
    else
      customer.wallet.cash -= due_amount
      @total_collected += due_amount
    end
  end
end
it "should collect money from customer" do
  customer = Customer.new :wallet => Wallet.new(:amount => 200)
  paperboy = Paperboy.new
  paperboy.total_collected.should == 0
  paperboy.collect_money(customer, 50)
  customer.wallet.cash.should == 150
  paperboy.total_collected.should == 50
end

We can easily see that the test is telling us it knows too much detail about Customer class implementation. We can see its internals, which objects it’s related to, and even worse, we’re also exposing implementation details of its peers. So it’s clear for me that it needs some design improvement. My main goal here is to hide Customer implementation details from the users of the Paperboy class. Which means that I don’t wanna see anything but Customer and Money classes referenced on the test!

class Paperboy
  def collect_money(customer, due_amount)
    @collected_amount += customer.pay(due_amount)
  end
end
it "should collect money from customer" do
  customer = Customer.new :total_cash => 200
  paperboy = Paperboy.new
  paperboy.total_collected.should == 0
  paperboy.collect_money(customer, 50)
  customer.total_cash.should == 150
  paperboy.total_collected.should == 50
end

The method customer.pay(due_amount) wraps all the implementation detail up behind a single call. The client of paperboy no longer needs to know anything about the types in the chain. We’ve reduced the risk that a design change might cause ripples in remote parts of the codebase.

As well as hiding information, there’s a more subtle benefit from “Tell, Don’t Ask.” It forces us to make explicit and so name the interactions between objects, rather than leaving them implicit in the chain of getters. The shorter version above is much clearer about what it’s for, not just how it happens to be implemented.

All the logic necessary to collect the money is inside the Customer object, so it doesn’t have to expose its state to its peers.

Now it’s safer to continue writing new failing tests to our objects.
Remember, listen to the tests!

[Felipe Santiago] Vida de freela [Semana 4] – Algumas considerações

July 26th, 2010

O primeiro mês dessa nova vida se foi e com ele pude adquirir alguma experiência, embora esteja muito aquém do nível organizacional e de produtividade que pretendo alcançar. As linhas a seguir visam questionar alguns pontos que tenho refletido mais, sobre opções e escolhas da vida diária.

Organização pessoal

Definitivamente, as pessoas que desejam alcançar algum objetivo na vida precisam se organizar. É necessário organizar suas tarefas e compromissos diários, definir seus objetivos, corrigir sua trajetória e manter sempre uma caminhada direcionada. O ganho que se tem com a organização pessoal é enorme para a produtividade. No caso da organização digital, existem diversas ferramentas gratuitas: para e-mail, o Gmail; para agenda, o Google Calendar; e para tarefas, o TadaList ou até mesmo o bloco de notas do seu sistema operacional. Não espere sentado que sua vida se organize de maneira milagrosa: tome atitude e aja!

Ambiente de trabalho

Ter um canto da casa onde possa ser considerado como escritório é essencial. Finalmente poderei ter meu espaço, pois as mudanças no apartamento onde moro aconteceram, e estou migrando para um quarto maior, com espaço suficiente para montar meu home office. Assim que estiver pronto eu publicarei fotos e compartilharei minhas observações sobre os benefícios deste ambiente.

Qualidade de vida

Priorize sua saúde. Cada dia que passa dessa minha vida de home office e freelancer eu me convenço que devo priorizar minha saúde. Procuro fugir dos estresses urbanos e cultivar uma boa saúde e programas de lazer. Tento ao menos 3 vezes por semana correr na orla e nos finais de semana, ter um programa cultural (seja assistir ao jogo do Vascão ou ir ao cinema/teatro). Além disso tudo, tento manter uma boa alimentação e o fruto disso é que, mesmo sendo alérgico, já tem alguns meses que não fico gripado, o que é raro na minha vida.

Foco

Manter o foco é primordial. Nesses últimos tempos, além de ter conseguido trabalhar em projetos freelance, também consegui dar andamento aos projetos pessoais. Exemplo disso é o lançamento da versão alpha do novo Primeira Chance. É claro que preciso melhor muito ainda na questão do foco, mas já observo progresso nesse meu esforço diário.

Conclusão

Este foi o último artigo da série Vida de freela. Pretendo continuar publicando informações relevantes para profissionais autônomos e compartilhar minhas experiências e observações. Quero agradecer pelo retorno que recebi e apoio dos amigos. Vocês são uma peça fundamental da minha trajetória

[Emerson Macedo] RVM com Passenger e múltiplas instâncias HTTPD

July 19th, 2010

No artigo anterior, falei sobre sobre RVM (Ruby Version Manager), explicando sobre instalação, configuração e seu funcionamento interno. Porém, não mencionei nada sobre seu uso com o Phusion Passenger (A.K.A mod_rails, mod_rack), e algumas pessoas me perguntaram sobre isso. Eu não abordei essa parte no artigo anterior por duas razões: A primeira é porque já era madrugada e o sono já me dominava :) e a segunda porque o artigo iria ficar muito grande e o conteúdo inicial já era suficiente para montar um ambiente local na máquina do desenvolvedor.

Esse artigo basea-se no uso do Apache 2.x e no Sistema Operacional OSX. Porém, as configurações em SOs POSIX se assemelham, portanto usuários do Ubuntu e afins não deverão ter nenhum problema.

Instalando o Passenger em uma Rubie/Gemset

Se você já usa RVM ou seguiu os passos do artigo anterior, já deve ter tudo instalado e configurado e já possui uma Rubie com ou sem Gemsets (não faz diferença ter Gemsets para esse artigo). Caso contrário, leia novamente.

Abra o terminal e entre na sua Rubie/Gemset, instale a gem do passenger e o módulo do apache (ou nginx):

$ rvm use rubie@gemset #ex: rvm use 1.8.7@minhaapp
$ gem install passenger
$ rvmsudo passenger-install-apache2-module

Muita atenção nesse momento. A instalação do módulo do apache (ou nginx) deve ser feita usando rvmsudo. Sem isso não funcionou comigo e acho que com ninguém vai funcionar :)

Feito isso, no fim da instalação do módulo ele vai mandar você colocar aquelas 3 linhas de configuração do Passenger nas suas configs do apache. Eu sugiro criar um arquivo passenger.conf ou similar e colar esse código dentro desse arquivo, pra não misturar com as configs básicas do Servidor Http. Se você estiver usando Mac, as configurações do apache provavelmente estarão em /etc/apache2 e existe um diretório other, onde colocamos as configurações adicionais, como esta que acabamos de criar para o passenger.

Agora precisamos ajustar um detalhe nessas configurações do Passenger. Quando instalamos o Passenger e módulo do apache em uma RVM, a terceira linha da configuração (PassengerRuby) que a instalação sugere, não aponta para o diretório correto, e não funciona. É necessário fazer uma modificação e vou explicar.

Quando instalamos a RMV, ele cria um diretório chamado ~/.rvm/bin, onde ficam todos os executáveis das rubies (ruby, irb, gem, ri, rdoc). A instalação do Passenger não entende isso e aponta para uma estrutura diferente, formada da seguinte maneira: ~/.rvm/rubies/{Rubie}/bin/ruby, e isso não funciona. Portanto, precisamos alterar essa linha para que fique da segunte forma:

$ PassengerRuby ~/.rvm/bin/{Rubie}@{Gemset}

A documentação sugere uma forma diferente dessa, nos indicando executar rvm {Rubie@Gemset} –passenger e substituir essa terceira linha da segunte forma:

$ PassengerRuby ~/.rvm/bin/passenger_ruby

O que isso faz é criar um link symbólico de passenger_ruby apontando para o {Rubie}@{Gemset} que você quer. Eu acho isso desnecessário, principalmente porque você pode querer usar o passenger com várias Rubies diferentes, que é o que vou abordar mais adiante. Portanto, eu prefiro ficar com a primeira opção.

Agora basta configurar o VirtualHost (presumo que você já sabiba fazer isso) e reiniciar o Apache. Nesse momento tudo já deve estar funcionando corretamente e você deve estar conseguindo ver sua aplicação funcionando. Não se esqueça de configurar o /etc/hosts (é bastante comum ver gente capotando porque esqueceu essa parte, rs).

Múltiplas apps em Rubies diferentes

Segundo a documentação do Passenger, a diretiva PassengerRuby deve ser usada apenas uma vez, nos limitando a ter nossas aplicações em uma Rubie/Gemset única. Uma maneira comum de trabalhar com essa limitação é instalar o Ruby Enterprise Edition (i.e. Ruby EE) ou qualquer versão de Ruby e instalar todas as gems de todos os projetos nessa Rubie. A partir daí, basta criar um VirtualHost para cada Aplicação. Essa era a forma que trabalhavamos sem RVM. Com RVM a idéia e sair dessa limitação, podendo por exemplo rodar uma app usando Ruby 1.8.7 com Rails 2.3 e outra com Ruby 1.9.2 e Rails3. Isso inclusive num ambiente de produção, isolando bem as apps e evitando conflitos. Vamos portanto resolver o problema de outra maneira.

Criando uma nova configuração para o Apache

Talvez você não saiba, mas o diretório /etc/apache2 não é o servidor Apache HTTPD propriamente dito, mas as configurações que esse servidor usa quando você sobe a instância. Por padrão, o apachectl procura as configurações nesse diretório, mas é perfeitamente possível indicar o path do arquivo de configuração que você quer usar, e é baseado nisto que vamos usar uma alternativa melhor.

Antes de qualquer coisa, vamos trocar alguns parâmetros na configuração default do Apache, para podermos rodar mais de uma instância sem nenhum tipo de problema acidental. Por padrão, nas configurações em /etc/apache2/httpd.conf tem um Listen definito para *:80. Vamos mudar isso:

Listen 127.0.0.1:80

Mudemos também quaisquer configurações de VirtualHost existentes que estejam usando *:80:

VirtualHost 127.0.0.1:80

Agora chegou a hora de clonar essas configurações para uma nova. Esse trabalho é um pouco chato, portanto resolvi criar um Shell Script para isso chamado osx-clone-apache.sh que pode ser baixado aqui e está no meu gist. Já testei no Snow Leopard e Leopard. Se alguém quiser fazer um para ubuntu e outros SOs é bem vindo e eu coloco como update no artigo.

Baixe o Script e execute a seguinte linha no terminal:

$ sudo ./osx-clone-apache.sh http-clone 127.0.0.1:80 127.0.0.2:80

Onde http-clone é o nome da nova configuração que será criada dentro de /etc, 127.0.0.1:80 é o Listen que está configurado em /etc/apache2 e 127.0.0.2:80 é o novo Listen. Essa nova configuração não leva nada do diretório other nem do passenger_pane_vhosts se você estiver usando o Passenger Preference Pane.

Agora que temos uma nova config do apache apontando para 127.0.0.2:80 precisamos configurar nossa interface de rede para passar a responder a esse ip:

$ ifconfig lo0 alias 127.0.0.2/32

Se não me engano, no Ubuntu isso não é necessário, mas no Mac eu não conheço outra forma de fazer isso. Se alguém souber é bem vindo.

Nesse ponto basta repetir os mesmos procedimentos de configuração de Passenger para novas Rubies e Gemsets para essa nova configuração do apache que acabamos de criar. Mais uma vez não esqueça de ajustar suas configurações no /etc/hosts.

O último passo é subir uma instância do apache usando as novas configurações criadas.

$ sudo apachectl -f /etc/{novaconfig}/httpd.conf -k start

Pronto, você já tem 2 instâncias do Apache rodando versões de Ruby/Rails diferentes na mesma máquina.

Conclusão

O RVM (Ruby Version Manager) trouxe uma nova perspectiva no gerênciamento de ambientes Ruby/Rails. O Deploy de Aplicações com versões de Ruby e Rails usando Phusion Passenger numa mesma máquina se torna trivial, desde que se saiba o que está fazendo. As configurações apresentadas neste artigo podem (e acho que devem) ser usadas também em ambiente de produção, pois a SANDBOX criada é muito mais simples de ser gerênciada do que aquela mistura habitual de VirtualHosts, Gems e afins.

Mãos a obra !!!

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

[Emerson Macedo] Gerencie seu ambiente Ruby com RVM

July 16th, 2010

Introdução

Ruby 1.8, Ruby 1.9, Rails 2, Rails 3, cada projeto usando diversas gems. Como isolar esses ambientes para evitar conflitos?

Em Outubro de 2007, surgiu uma ferramenta chamada RVM, com o objetivo de criar ambientes isolados para desenvolver software em Ruby, permitindo que programadores pudessem usar várias versões de Ruby e Gems numa mesma máquina de forma limpa e sem conflitos. O projeto vem se tornando mais popular este ano, e de fato tem se mostrado muito útil. A lista dos autores pode ser conferida aqui.

Instalação

Para instalar o RVM, não é preciso muita coisa além de um ambiente POSIX (linux, bsd, etc). Eu instalei no meu Mac sem problemas. Eu acho que a única coisa que não vem por padrão que você precisa instalar é o git, que é usado para instalar/atualizar o RVM e instalar/atualizar as versões de Ruby.

Dito isso, abra o terminal e execute o seguinte comando:

$ bash < <( curl http://rvm.beginrescueend.com/releases/rvm-install-head )

O procedimento não deve demorar mais que alguns minutos, dependendo da sua conexão. Em seguida, abra seu profile (.bash_profile, .profile, .bashrc, etc) e adicione as seguintes linhas:

[[ -s "$HOME/.rvm/scripts/rvm" ]] && source “$HOME/.rvm/scripts/rvm”
PS1=”\$(~/.rvm/bin/rvm-prompt) $PS1″

A segunda linha é para que a versão do Ruby que você estiver usando apareça no prompt, caso contrário você vai precisar ficar verificando a todo momento qual versão você está usando e isso pode ser bem chato.

Em seguida, carregue o rvm (da próxima vez que abrir o shell isso não será mais necessário):

$ source ~/.rvm/scripts/rvm

Pronto, o RVM está instalado e é hora de começar a arrumar nosso ambiente.

Instalando versões de Ruby

A partir do RVM, é possível instalar qualquer implementação Ruby. Por exemplo, podemos instalar o Ruby, Ruby Enterprise e o Jruby. Para uma lista completa acesse aqui.

Nesse tutorial, vamos instalar o ruby 1.8.7 . Execute o comando abaixo no terminal:

$ rvm install 1.8.7

1.8.7 é um atalho para o último patchlevel da verão 1.8.7 do Ruby. Em geral, isso funciona para todas as versões. A instalação demora um pouquinho, mas nada absurdo, portanto vá tomar um café e volte. Após o termino, “entre” no ambiente do Ruby instalado.

$ rvm –default 1.8.7

Nesse momento, você entrou no Ruby 1.8.7 e definiu essa VM como default no RVM.

Para voltar ao Ruby do systema (fora da RVM), basta ir no shell e digital:

$ rvm use system

Para listar as VMs instaladas (ou Rubies como preferem os criadores e como chamaresmo a partir de agora), basta digitar:

$ rvm list

Escolha a Rubie e use-a conforme o exemplo abaixo:

$ rvm use 1.8.7

Instalando as Gems

Uma das manias que a maioria dos Rubistas tem é instalar as gems usando sudo. Isso hoje em dia é considerado má prática. Ainda mais com RVM, já que a intenção é criar uma espécie de SANDBOX por usuário/aplicação, conforme veremos a seguir.

Primeiramente vamos ver as gems que estão instaladas na nova Rubie. O comando é o já conhecido gem list. Ao rodar esse comando na Rubie instalada pelo RVM, você pode ter a impressão que suas gems sumiram, mas na verdade isso é exatamente o esperado, pois cada Rubie tem seu ambiente totalmente isolado. Para ter uma idéia, rode o seguinte comando e veja o output:

$ rvm info

O output fornece toda a informação sobre o ambiente dessa Rubie que está sendo usada no momento. Observe bem a linha home: \n gem:. Nela você verá onde estão sendo instaladas as gems. Repare que ele cria uma estrutura de diretórios sugestiva para você manter suas gems bem isoladas. A estrutura é a seguinte:

~/.rvm/gems/{Rubie@Gemset}/

Todas as gems serão instaladas nesse diretório. Não estranhe o @Gemset, falaremos dele adiante.

Vamos então instalar o Rails nessa Rubie. Não use sudo pelo amor de Deus :)

$ gem install Rails –no-ri –no-rdoc

Depois execute um gem list para ver seu ambiente instalado. Se quiser, execute rvm system e veja que suas gems no ruby do sistema provavelmente são totalmente diferentes.

Gemsets

Vamos falar agora do tal @Gemset que eu coloquei na estrutura. Gemsets é uma forma de criar uma SANDBOX mais “profunda”. Em um primeiro momento pode parecer desnecessário, mas se você pensar que pode ter mais de um projeto por Rubie e não quer que as gems deles se misturem nem gerem algum tipo de conflito, essa estrutura passa a fazer todo sentido.

Supunha que você tenha um projeto chamado blog. Para criar uma gemset (e entrar nele) para esse projeto basta executar o seguinte comando:

$ rvm gemset create blog && rvm gemset use blog

Feito isso você verá que no seu prompt (se você fez essa configuração de instalação) estará aparecendo da seguinte forma: rubie@gemset. Rode o comando gemlist e verá que novamente suas gems que foram instaladas na Rubie sumiram. Mais uma vez isso é esperado, pois acabamos de criar uma nova SANDBOX para esse projeto específico. Nesse momento, basta instalar suas gems nessa gemset que seu projeto terá um ambiente totalmente isolado.

Se você executar o rvm info, verá que a home das suas gems está com um path diferente do anterior, pois o rvm criou um diretório para a Ruby com a nova Gemset, deixando tudo muito bem organizado.

Existem algumas gems que todos os projetos podem precisar, como Rake e Capistrano. Não seria uma boa idéia instalar essas gems em cada gemset. O RVM nos dá uma ajuda nesse sentido, criando uma gemset global, permitindo compartilhar gems entre todas as gemsets de uma Rubie. Para instalar uma gem nessa gemset basta mudar para ela e installar, como já vimos anteriormente. Vamos a um exemplo:

$ rvm gemset use global
$ gem install capistrano capistrano-ext –no-ri –no-rdoc

Pronto, essas gems não precisam mais ser instaladas para cada projeto novo que você for rodar nessa Rubie.

Conclusão

O Ruby Version Manager é uma ferramenta muito interessante para gerênciar seu ambiente Ruby. Ter vários Rubies instalado se torna cada vez mais comum, pois os projetos antigos precisam ser mantidos e novos projetos surgem, usando Rubies mais novos. O uso dos gemsets para isolar as gems também faz toda a diferença, evitando diversas dores de cabeça e deixando o ambiente organizado e limpo. Vale a pena experimentar.

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

[Tiago Peczenyj] Testando o wordpress 3.0

July 14th, 2010

Este blog volta a ativa, com muitas novidades, aguarde :)

[Rafael Biriba] VirtualBox: Criando e iniciando uma VM pelo terminal com o VBoxManage

July 14th, 2010

virtualbox-imageJá tem algum tempo que ando brincando com o VirtualBox e um dos objetivos era automatizar a criação de novas VMs.

Durante as pesquisas e testes, descobri que criar máquinas virtuais utilizando o VBoxManage* é bastante simples.

*VBoxManage: É uma interface do virtualbox por linha de comando (terminal), onde você pode controlar totalmente suas máquinas virtuais.

Dica: Leia a documentação para conhecer todas as funções disponíveis: http://www.virtualbox.org/manual/ch08.html

Então vamos começar… No exemplo a seguir vou criar uma vm para um CentOS 5.4: (Os comandos em negrito devem ser executados no terminal)

VBoxManage createvm -name “centos54″ –register
Cria uma vm com o nome ‘centos54′ e com configurações padrões

VBoxManage modifyvm “centos54″ –ostype RedHat –memory “128″ –acpi on –boot1 dvd –nic1 bridged –bridgeadapter1 wlan0
Altera o tipo da vm para RedHat (por causa do CentOS), altera a memória para 128 MB, configura o dvd para ser o primeiro boot, e habilita uma placa de rede em modo bridge apontando para minha interface de rede wireless wlan0 (em alguns casos talvez seja eth0). Você pode habilitar mais de uma interface de rede, basta passar as configurações das placas assim: –nic1 … –nic2 … -nic3 …

VBoxManage createhd -filename “centos54.vdi” -size 6000 –remember
Cria o HD da nova vm com 6 GB de espaço

VBoxManage storagectl “centos54″ –name “IDE Controller” –add ide –controller PIIX4
Habilita o controlador IDE de disco na vm

VBoxManage storageattach “centos54″ –storagectl “IDE Controller” –port 0 –device 0 –type hdd –medium “centos54.vdi”
Adiciona o disco vdi da vm no controlador IDE e define o tipo com hard disk drive (hdd)

VBoxManage openmedium dvd /home/rafael/Desktop/CentOS-5.4-i386-bin-1of6.iso
Adiciona ao virtualbox (não na vm), o link para a imagem do disco

VBoxManage storageattach “centos54″ –storagectl “IDE Controller” –port 0 –device 1 –type dvd –medium /home/rafael/Desktop/CentOS-5.4-i386-bin-1of6.iso
Adiociona a imagem do disco para boot e instalação do sistema operacional na VM. Note que agora o device é definido como 1, pois o hd está no device 0.

Feito isso, agora estamos prontos para poder iniciar a VM:
nohup VBoxHeadless –startvm “centos54″ -p 3001
O vboxheadless responsável por iniciar a vm prende o processo ao terminal. Portanto se você fechar o terminal, o processo de start da vm morre. Para resolver isso, usamos o nohup que mantém o processo rodando mesmo que o terminal seja fechado. O vboxheadless inicia a vm e habilita o protocolo RDP (Remote Desktop Protocol) para que você possa acessar a vm. O parâmetro -p serve exatamente para definir a porta de acesso do RDP, e o endereço de acesso é 127.0.0.1 ou localhost.

Para desligar a VM:
VBoxManage controlvm “centos54″ poweroff

Para remover o DVD de boot da VM:
VBoxManage storageattach “centos54″ –storagectl “IDE Controller” –port 0 –device 1 –type dvd –medium noneforceunmount

Então é isso… Em breve vou mostrar como duplicar as vms e seus discos.
Dica: Leia a documentação para conhecer todas as funções disponíveis do VBoxManage:
http://www.virtualbox.org/manual/ch08.html


Leia também:

[Emerson Macedo] Computação Ubíqua e Dispositivos móveis

July 13th, 2010

Introdução

É fato que nos dias de hoje muitas tecnologias novas surgiram no cenário mundial. Temos sido inundados por celulares, smartphones, notebooks, netbooks e outros mais. Hoje em dia existe internet 3G nas principais grandes cidades do mundo. Internet WIFI já é algo comum faz tempo. Esses recursos estão começando a mudar nossas vidas de uma forma surpreendente. Mas será que essa idéia é nova? Quando será que começaram as pesquisas sobre essas tecnologias? Qual será o impacto futuro em nossas vidas? Acredito que estamos realmente num caminho onde a computação fará parte de quase todos os objetos que usamos no dia a dia.

Definição

Ubíquo não é uma palavra muito usada em nosso cotidiano. Portanto, vale a pena apresentarmos alguns significados para nos ajudar a aprofundar mais no assunto.

Ubíquo significa algo universal, ou seja, algo que todos entendem, conhecem. Ubíquo também pode ser interpretado como aquilo que esta presente em todos os lugares, ao mesmo tempo. É como onipresença. Essa segunda definição tem mais a ver com o conteúdo desse artigo.

História

Em 1991, Mark Weiser escreveu um artigo chamado “O Computador do Século 21 (The Computer for the 21st Century). Weiser era cientista chefe do Centro de Pesquisa Xerox PARC. Nesse artigo, ele definiu o termo Computação Ubíqua, que define um contexto onde a presença computacional em algum objeto é totalmente transparente para quem usa e em alguns cenários totalmente invisível. Weiser também exemplifica a escrita, que foi provavelmente a primeira tecnologia de informação e que se tornou Ubíqua em países industrializados. Ele usa esse exemplo para definir que as tecnologias que são mais profundas são as aquelas que “desaparecem”. Por desaparecer, acho que Weiser quis dizer que a tecnologia fica tão arraigada no nosso dia a dia tornando seu uso automático, deixando de ser aquele algo novo e surpreendente. Vislumbrando como seria a computação do nosso século, Weiser também fala sobre redes gigabits, armazenamento de terabytes e sobre Tabs e Pads, que seriam os palms, smartphones, Kindles e iPads que temos hoje. Quase no fim do artigo, ele conta uma estória ilustrativa de uma pessoa vivendo nesse mundo todo conectado e apresenta diversos protótipos feitos por ele e sua equipe de alguns desses equipamentos e tecnologias.

No que diz respeito a tecnologias, lembro-me bem que Java era uma dessas que originalmente foi criada para ser usada em dispositivos embarcados, especialmente na informatização da casa, mas era algo muito avançado para época. Isso surgiu no mesmo ano em que Weiser escreveu seu artigo. No fim das contas a linguagem Java tomou outro rumo, muito bem sucedido por sinal.

Contexto atual e futuro

É impossível negar que a computação Ubíqua tem afetado nosso dia a dia. Hoje temos Hotspots WIFI em diversos lugares. A internet 3G está presente nos celulares modernos, possibilitando infinitas formas de comunicação. Serviços de Voz sobre IP tornaram possível usarmos ferramentas como Skype, que permite obter um número de um País e utilizar em qualquer lugar do mundo. Cada vez mais fazem parte do nosso dia a dia tecnologias como as de automóveis com computador de bordo, iPhones, iPads, totem para compra de ingressos no cinema, totem para check-in de voos, e outros mais.

Outra tecnologia que está acelerando o processo da computação Ubíqua é o Cloud Computing. Há alguns anos, milhares de pessoas tem suas contas de email online em serviços como gmail, yahoo mail e similares, de forma a não precisarem mais de um cliente de email como ferramenta obrigatória em seus computadores. Essa modalidade é conhecida como SaaS (Software as a Service). Outra modalidade é o IaaS (Infrastructure as a Service), onde existe uma infraestrutura transparente para quem contrata servidores, podendo adicionar mais recursos computacionais ao invés de mais um computador ou hardware físico. Mais recentemente surgiram também plataformas para desenvolvimento de software totalmente na web como o Google App Engine, Heroku e outros. Esse é o modelo PaaS (Platform as a Service).

Hoje em dia fala-se muito também em casas inteligentes, um conceito onde toda a casa está interligada e conectada, permitindo que luzes acendam com comando de voz, geladeiras enviem pedidos de compras ao supermercado quando estiverem perto de esvaziar, cafeteiras saberem o horário do seu café da manhã e prepararem o café sem você precisar fazer nada, e por ai vai. Esse conceito está ligado a Computação Pervasiva, que é uma espécie de subárea da Computação Ubíqua. Quem assistiu o filme “O Demolidor” (1993), com os atores Silvestre Stalone e Welsey Snipes, lembra que esses conceitos estão presentes no filme. Embora atualmente existam algumas iniciativas de empresas nesse ramo de Computação Pervasiva, essa tecnologia ainda está bem distante de uma adoção em massa.

Falando de futuro, é bem verdade que ainda não chegamos no nível onde Weiser aponta em seu artigo, mas afinal, ainda estamos no início do século, tendo passado apenas uma década. Uma das frases ditas por ele nesse artigo que chamou muito a atenção sobre esse futuro foi: “Não precisamos de nenhuma revolução na inteligência artificial, apenas incorporar a computação no cotidiano”.

Conclusão

O Caminho para Computação Ubíqua tem avançado muito nos últimos anos. As pesquisas e previsões de Mark Weiser tem se concretizado, quase que como uma profecia. Como profissionais de TI, nos resta estar atentos as oportunidades de negócio que essas tecnologias tem a nos oferecer e tirar proveito disso.

Post Footer automatically generated by Add Post Footer Plugin for wordpress.