Olá, pessoal!
Esse artigo é uma continuação do Vagrant e seus plugins e, para falar a verdade, começou a ser escrito antes do original. É que percebi que, sem uma explicação mais básica do que eram os plugins, ia “faltar base” – como dizia um professor do cursinho. Então, mais uma vez, se quiser primeiro saber o que são os plugins no Vagrant, leia o artigo original primeiro, ok?
O que é o método Vagrant.has_plugin?
O has_plugin?
é um método da API do Vagrant, para ser usado no seu Vagrantfile, que verifica se um plugin está disponível no sistema. Com o grande número de plugins disponíveis (confira os listados na wiki oficial), é importante ter uma forma de garantir que quem for usar seu projeto Vagrant tenha os plugins que você definiu/utilizou, e, se não tiver, fazer algo com essa informação.
Vamos ver um exemplo para deixar mais fácil o entendimento:
# Vagrant.configure("2") do |config| ... # configs for vagrant-cachier if Vagrant.has_plugin?("vagrant-cachier") config.cache.auto_detect = true end # ...
Nesse trecho acima vemos um Vagrantfile que utiliza oplugin vagrant-cachier para acelerar o vagrant up
se o usuário tem o plugin instalado na máquina. Caso não tenha, tudo continua funcionando, apenas sem a aceleração. Sem usar o has_plugin?
o Vagrant interromperia o processo com uma mensagem de erro.
Parece bastante com o conceito de progressive enhancement/graceful degradation: forneça ao usuário que tem apenas o requisito básico uma versão funcional do seu projeto, sem traumas. E, para os que tem mais requisitos (no caso o plugin que definimos), entregue também as funções melhoradas (nesse caso, uma camada de cache que vai acelerar o provisionamento das máquinas virtuais. Se você ainda não conhece o vagrant-cachier, do brasileiro Fabio Rehm, ou @fgrehm, é uma boa hora de começar!).
Um outro exemplo segue abaixo:
# Warns to use Bindler unless Vagrant.has_plugin?("Bindler") puts "--- WARNING ---" puts "I'm using Bindler, https://github.com/fgrehm/bindler" puts "It's for 'Dead easy Vagrant plugins management'" puts "If you have not it installed in your system," puts "visit https://github.com/fgrehm/bindler#installation for more information" end # Vagrant.configure("2") do |config| ...
Nesse caso, ao contrário do anterior, é feita uma ação quando um plugin não existe no sistema. E quando que isso é útil? Principalmente para os casos em que precisamos avisar para o usuário que um plugin é necessário/recomendável para executar a aplicação, dando algum caminho para que ele possa resolver a situação. No exemplo acima, avisamos que o projeto está usando o plugin vagrant-bindler para fazer a gestão dos plugins e passamos um caminho para que o usuário faça a instalação do mesmo se ele ainda não tiver (plugin também criado pelo @fgrehm).
Há tempos… um problema!
A função Vagrant.has_plugin? foi introduzida no Vagrant na versão 1.3.0, com alguns problemas, e na versão 1.3.2 foi realmente consertada – isso tudo em setembro de 2013. Mas por que então, mesmo tendo uma certa idade, essa função ainda não é tão utilizada?
Isso acontece por uma pequena inconsistência na implementação dessa API, que faz com que o nome do plugin internamente para o Vagrant (que vai ser usada na chamada Vagrant.has_plugin?
) seja diferente do nome do plugin que é usado na instalação via linha de comando $ vagrant plugin install
.
Antes de perceber isso acima, eu mesmo no começo não conseguia entender a lógica, que parecia ser tão simples: fazer uma condição ruby IF ou UNLESS, passando o nome do plugin. Por que não funcionava? Era essa bendita inconsistência de nomes. Ainda bem que não desisti de entender!
Para facilitar, vamos chamar esses nomes da seguinte forma:
- nome de instalação do plugin: usado no comando
$ vagrant plugin install ...
. - nome interno do plugin: usado no Vagrantfile, com o método
has_plugin?
Com isso em mente, vamos para os exemplos:
HOW IS LISTED WITH VAGRANT PLUGIN LIST |
HOW TO USE IN VAGRANT.HAS_PLUGIN? | LINK TO PLUGIN.RB IN REPO |
---|---|---|
bindler | Bindler | fgrehm/bindler |
vagrant-hostmanager | HostManager | smdahlen/vagrant-hostmanager |
vagrant-cachier | vagrant-cachier | fgrehm/vagrant-cachier |
vagrant-aws | AWS | mitchellh/vagrant-aws |
vagrant-rackspace | RackSpace Cloud | mitchellh/vagrant-rackspace |
vagrant-hp | HP | mohitsethi/vagrant-hp |
vagrant-digitalocean | DigitalOcean | smdahlen/vagrant-digitalocean |
Quando acessamos a lista oficial dos plugins disponíveis para Vagrant, não encontramos o nome interno (ainda, estou trabalhando nisso); apenas aparece o nome de instalação. Uma diferença que, às vezes, é apenas de maiúsculas ou minúsculas entre os nomes das duas versões mas que já atrapalha tudo!
Peguemos o Bindler. Para instalá-lo no sistema, é usado o nome daGem (em minúsculas):
$ vagrant plugin install bindler
Já para usar no seu Vagrantfile, com o has_plugin?
, tem que ser onome interno do plugin (começando com maíscula):
Vagrant.has_plugin?("Bindler")
É, realmente é complicado. Por não haver um padrão, é possível encontrar todos os tipos de combinações: nomes iguais, totalmente diferentes ou apenas a diferença de capitulares. Mas existe uma solução! Vamos vê-la?
A solução!
E a solução é: aprender a ler o repositório do plugin! Puxa, não é o que você estava esperando, não é mesmo… É, por enquanto, não existe uma solução perfeita, por isso vamos aprender aqui a ler o repositório sempre que você precisar.
Arquivos importantes
O primeiro passo é saber localizar, dentro de um repositório, o nome de instalação do plugin e o nome interno do plugin:
- /nome-de-instalação-do-plugin.gemspec: é nesse arquivo que temos o nome de instalação. O arquivo fica na pasta raiz do repositório do plugin. Exemplos: bindler.gemspec, vagrant-aws.gemspec, vagrant-cachier.gemspec etc.
- /lib/nome-de-instalação-do-plugin/plugin.rb: é nesse arquivo que temos o nome interno. O arquivo fica no terceiro nível do repositório do plugin. Dentro desse arquivo, existe um atributo
name
, que é o nome interno que você vai usar. Exemplos para os mesmos plugins acima: Bindler, AWS, vagrant-cachier.
Achar o repositório do plugin
O segundo passo é saber onde está o repositório do plugin. Minha sugestão, comece pela lista oficial, e siga o link de lá. Na maioria das vezes, você vai cair num repositório no GitHub (ou em algum outro serviço de hospedagem de projetos open source).
A partir daí é só navegar buscando os arquivos mostrados ali em cima, que você já terá a informação necessária para trabalhar.
Considerações finais
Vimos que o Vagrant.has_plugin?
é um método da API do Vagrant muito útil para utilizar nos seus projetos. Principalmente importante para os projetos compartilhados com muitas pessoas, verificando no tempo de execução a existência ou não de um plugin determinado; permitindo que quem tenha o plugin, aproveite as funcionalidades, mas não impeça que os usuários sem o plugin tenham uma experiência pelo menos básica.
Entendemos também que existem dois nomes para os plugins: onome de instalação e o nome interno, e qual deles deve ser usado junto com o Vagrant.has_plugin?
. Aprendemos quando usar cada um deles, e como descobrir o nome lendo o repositório do plugin (fique de olho na wiki da lista oficial de plugins, pois vou fazer um trabalho visando facilitar a pesquisa centralizada desses nomes, seria interessante, certo?).
Quer uma dica de plugins para começar a trabalhar? Dê uma olhada no meu artigo original, Vagrant e seus plugins, que tem algumas opções que já utilizo. Agora é sua vez de montar uma estratégia de uso dos plugins e do has_plugin? nos seus projetos Vagrant e
Fique à vontade para tirar suas dúvidas nos comentários (ou me procure, estou em quase todo lugar na internet como rogeriopradoj, é só chamar!)
Feliz vagrant up!