1. Introdução editar

1.1 Visão Geral editar

Esse documento irá descrever e especificar o plano de gerência de configuração que será aplicado no projeto Busine.me Web. O projeto se trata de um aplicativo que pretende resolver problemas de mobilidade urbana, e está sendo desenvolvido nas disciplinas de GPP e MDS da Universidade de Brasilia. A wiki do projeto pode ser acessada a partir do seguinte link:

http://lappis.unb.br/redm/projects/grupo-2-busine-me/wiki

Na wiki é possível ver documentação de Visão do projeto, arquitetura, casos de uso etc. A documentação do projeto também está em desenvolvimento.


O repositório de desenvolvimento da disciplina MDS pode ser encontrado no seguinte link:

https://github.com/aldarionsevero/BusinemeWeb

O repositório oficial do aplicativo pode ser encontrado nesse outro link:

https://github.com/Busineme/BusinemeWeb

Por ser um aplicativo que começou seu desnvolvimeno nesse semestre (2015/1), o mesmo da confecção desse documento, várias abordagens e melhorias de GCS podem ser feitas para, tanto facilitar o desenvolvimento, quanto facilitar manutenção e implantação.

1.2 Propósito editar

Com o plano proposto por esse documento, espera-se que melhorias significativas com relação a Gerência de configuração de Software sejam assimiladas pelo software Busine.me Web. A metodologia proposta por esse plano será desenvolvida e implantada durante 2 meses da disciplina de GCS, juntamente com o desenvolvimento do software das diciplinas de MDS e GPP, mas após esses dois meses essas melhorias continuarão trazendo as melhorias propostas enquanto elas estiverem sendo utilizadas. A disciplina de MDS requere que seus projetos tenham versionamento e controle de mudança, que tenha testes e razoável cobertura, logo essa parte fica fora do escopo deste documento. Assim sendo, integração contínua e Automação de implantação passa a ser o escopo real da metodologia proposta nesse documento.


1.3 Escopo editar

O escopo do projeto abrange as seguintes demandas para o software:

  • Automação de testes e de builds por meio de integração contínua utilizando Travis
  • Automação de implantação utilizando a ferramenta Chef
  • Para auxiliar o Travis utilizaremos a ferramenta Fabric ou Chake para executar comandos em máquinas remotas auxiliando a implantação automática.
  • Garantir localmente o mesmo ambiente versionado com a ferramenta Vagrant, evitando problemas de quebras ao utilizar localhost.

1.4 Definições, Acrônimos e Abreviações editar

Abreviação Significado
GCS Gerência de Configuração de Software
MDS Método de Desenvolvimento de Software
GPP Gerência de Projeto e Portifólio de Software
IC Integração Contínua
VM Virtual Machine (máquina virtual)
AWS Amazon Web Service


2. Milestones editar

Os milestones serão os marcos dos pequenos entregáveis e releases reais do projeto.

DATA Descrição
9/05/2015 Configurar repositório para que o script do Travis execute a suite de testes, chame o serviço do coveralls e poste no Slack
02/06/2015 Atomatização da implantação utilizando o Chef
16/06/2015 Utilização do Fabric ou Chake para facilitar utilização do Chef
27/06/2015 Finalizar o fluxo de automação e integração


3. Andamento editar

Andamento do desenvolvimento e alterações de escopo do projeto.

3.1 Alterações de Escopo editar

Inicialmente, a integração contínua a ser empregada no projeto estava planejada para acontecer com a ajuda da ferramenta Travis, mas já que a integração contínua irá disparar a implantação automática usando o rake + chef (+ chake) para execução de comandos na máquina remota, diversas informações, como senhas ssh, iriam ficar visíveis no serviço aberto do travis. Para tornar isso fechado, decidimos mudar a ferramenta de integração contínua do Travis para o Jenkins, e levantá-lo em um servidor pessoal.

Antes Agora
Travis Jenkins
Fabric ou Chake Decisão pelo Chake
Serviço aberto inseguro Instancia própria com mais segurança

3.2 Progresso editar

Progresso de tarefas do desenvolvimento de GSC no projeto.

3.2.1 Feito editar
  • Sincronização do repositório com o serviço do Travis
  • Estudo a respeito do Chef e das dependências que ele precisa trazer
    • Dependências para trazer na receita de configuração de ambiente de desenvolvimento
    • Dependências para trazer na receita de configuração de ambiente de implantação
  • Estudo a respeito do Fabric e Chake, e decisão pelo Fabric
    • Decisão pela mudança de ferramenta de IC
  • Utilização de uma VM na Amazon Web Service (trial de um ano grátis) para a instância do Jenkins
    • Configuração do servidor nginx para o levantamento do Jenkins
    • Configuração do Jenkins, seus plugins, geração de relatórios, e Jobs para IC do projeto
  • Desenvolvimento da receita de configuração de ambiente de desenvolvimento (agora sendo a mesma que a de deploy, mas generalizada para funcionar local ou deploy)
  • Adaptação do script do Jenkins para integração entre IC e ambiente de implantação com o Chake

4. Passo a passo da execução do projeto editar

Os temas abordados nesse projeto, como integração contínua, automatização de ambientes e de deploy, podem ser reproduzidos em diversos outros projetos, e de maneira geral, seguem passo a passo semelhante. Por esse motivo, a execução desse projeto será detalhada aqui.

4.1 VMs em Web Service editar

Existem diversas opções de Web Services disponíveis, algumas pagas, e outras com período de trial. Utilizamos duas VMs de ubuntu 15 da azure (pagas) para implantar a aplicação. Também utilizamos uma VM ubuntu 14.04 (trial) para configuração do jenkins.

4.1.1 Azure editar

O Microsoft Azure é um serviço pago, entretanto, um dos integrantes do Busine.me possui o plano BizSpark, onde o usuário tem direito à US$150,00 mensais para gastar com os serviços do Azure. Para criar uma VM no Azure:

  • Acesse o dashboard do Azure[1] e faça login na sua conta.
  • Clique em "+ new" -> "Compute" -> "Virtual Machines" -> "From Gallery"
  • Escolha uma das imagens disponíveis. Para o projeto, foi escolhido o Ubuntu Server 15.04.
  • Defina o nome da sua VM, que será usado como DNS, sua configuração e o usuário padrão, bem como a forma de login, se por chave .pem ou senha. Para o projeto, foram definidas duas VMs:
    • businemeweb.cloudapp.net: 1 core, 1.75 GB RAM. Login por senha.
    • businemeapi.cloudapp.net: 1 core, 1.75 GB RAM. Login por senha.
  • Defina as portas/saídas da VM. Para o projeto, em todas as VMs foram abertas as portas:
    • 22 - SSH
    • 80 - HTTP
  • Finalize a criação da VM e aguarde até que o Azure termine de levantar a máquina.
4.1.2 Amazon Web Service editar

Para criar uma VM na AWS, é necessário primeiro ter uma conta na amazon (mesma conta do site de compras).

  • Com a conta criada, acesse https://aws.amazon.com/, faça login, e clique em MyAccount e em AWS management console.
  • Depois siga para VMs EC2.
  • Clique em launch Instance e então na distro desejada (Ubuntu 14.04).
  • Siga as configurações, revendo os valores padrões. Nesse projeto só algumas portas sofreram port forward, mas não é necessário fazer isso nessemomento.
  • Siga até o lanch, crie um novo keypair, nomei-o e faça o download do mesmo e guarde com cuidade o arquivo. Ele é utilizado para fazer ssh na máquina.
  • Finalize o processo e então terá uma VM levantada pronta para acesso remoto.
  • Para acessá-la via ssh, fique no diretório onde baixou o arquivo ".pem" e rode o comando utilizando nome do arquivo e ip da máquina:
$ ssh -i nome_do_arquivo.pem ubuntu@XX.XX.XXX.XXX

4.2 Levantar os Serviços editar

Nesse projeto diversas aplicações devem ser levantadas por trás de um nginx reverse proxy. Para o jenkins na maquina da AWS é necessário seguir as instruções desse link https://wiki.jenkins-ci.org/display/JENKINS/Running+Jenkins+behind+Nginx.

Para a aplicação em si rodando no servidor de homologação, ou no vagrant local, veja no tópico falando sobre a receita que configura isso.

4.3 Como Aplicar IC editar

Após devidas configurações do supervisor e nginx do tópico anterior, é necessário iniciar o jenkins por trás dessa configuração e então configurá-lo. Para instalar o Jenkins:

$ wget -q -O - https://jenkins-ci.org/debian/jenkins-ci.org.key | sudo apt-key add -
$ sudo sh -c 'echo deb http://pkg.jenkins-ci.org/debian binary/ > /etc/apt/sources.list.d/jenkins.list'
$ sudo apt-get update
$ sudo apt-get install jenkins
4.3.1 Plugins editar

Para instalar plugins no Jenkins basta navegar por "Manage Jenkins", "Manage Plugins" e selecionar a aba "Available". Os plugins necessários são:

  • Cobertura
  • Git client plugin
  • Git parameter plugin
  • Git plugin
  • Git server plugin
  • GitHub API plugin
  • GitHub plugin

E assim que forem instalados, selecione opção de reiniciar o Jenkins para que estejam utilizáveis.

4.3.2 Configuração Jenkins editar
  • Estando na dashboard do Jenkins, Selecione "New Item".
  • Nomeie o Job que irá rodar builds da aplicação.
  • Coloque o link do projto no GitHub (https://github.com/aldarionsevero/BusinemeWeb/)
  • Em Source Code Management, selecione git. Coloque a branch a ser monitorada, e suas credenciais.
  • Escolha qual evnto irá dispará uma build do projeto (push).
  • E por fim coloque os passos necessários anteriores para execução dos testes.

Nesse projeo são (pode-se separar em diversos blocos de "Execute Shell"):

sudo apt-get install ruby chef python2.7 python-pip -y && \
sudo apt-get install libxml2 && \
sudo apt-get install libxslt1.1 && \
sudo apt-get install libxml2-dev && \
sudo apt-get install libxslt1-dev && \
sudo apt-get install python-libxml2 && \
sudo apt-get install python-libxslt1 && \
sudo apt-get install python-dev && \
sudo apt-get install python-lxml && \
sudo apt-get install python-setuptools && \
sudo pip install -r requirements.txt && \
sudo pip install python-Levenshtein && \
cp configuration/databases.py.template configuration/databases.py && \
cp configuration/security.py.template configuration/security.py && \
cp configuration/api.py.template configuration/api.py && \
rm models/migrations/0* && \
python manage.py makemigrations && \
python manage.py migrate && \
python manage.py jenkins && \
clonedigger --cpd-output -o ./reports/clonedigger.xml . && \
coverage run manage.py test && \

4.5 Vagrant editar

O Vagrant é a ferraemnta utilizada no projeto para gerenciamento de VMs para o ambiente de desenvolvimento. A criação e destruição de um abiente limpo e padronizado com o Vagrant garante integridade do ambiente, e é possível seguindo os seguintes passos:

$ vagrant init

Esse comando cria o vagrant file que utilizaremos para configuração das VMS

  • Não utilizaremos o chef como provisioner do Vagrant, como inicialmente planejado (tutorial para seguir com provisioner pode ser encontrado em outros projetos dessa turma), em vez disso utilizaremos o rake para acionar funcionalidades do chef por intermédio do chake. Dessa forma o nosso vagrant file fica assim:
# -*- mode: ruby -*-
# vi: set ft=ruby :
require 'yaml'

Vagrant.configure(2) do |config|
  config.vm.box = "ubuntu/trusty64"

  env = ENV.fetch('BUSINEME_ENV', 'local')

  if File.exist?("config/#{env}/ips.yaml")
    ips = YAML.load_file("config/#{env}/ips.yaml")
  else
    ips = nil
  end

  config.vm.define 'api' do |api|
    api.vm.network 'private_network', ip: ips['api'] if ips
    api.vm.network "forwarded_port", guest: 8080, host: 8079
  end

  config.vm.define 'web' do |web|
    web.vm.network 'private_network', ip: ips['web'] if ips
    web.vm.network "forwarded_port", guest: 8000, host: 8001
  end
end

Podemos observar que temos uma box limpa do ubuntu 14.04 (trusty64), que setamos um ambiente local e outro de deploy (BUSINEME_ENV), que fazemos as configurações de ip por meio de um arquivo yaml e que levantamos as VMS com essas configurações. Esses arquivos de configuração dependem do chake e serão melhor explicados no tópico apropriado.

4.5 Integrar rake e chef com o chake editar

A parte mais trabalhosa do projeto vem dessa integração. Para isso é necessário primeiro instalar ruby, rake, chef e o chake:

$ sudo apt-get install ruby
$ sudo gem install rake chef chake

Em seguida partimos para a configuração de tudo nos diretórios onde temos o Vagrantfile.

4.5.1 Local (Vagrant) editar

Nesse diretório, executamos o seguinte comando:

$ chake init

que criará os seguintes arquivos:

[create] nodes.yaml                                    # que configurará os nós em que as receitas serão executadas
[create] config.rb                                     # que irá linkar os diretórios do chef para que o rake consiga puxar as funcionalidades
[ mkdir] config/roles                                  # iremos mudar para que configuremos nossos dois ambientes (local, BUSINEME_ENV)
[ mkdir] cookbooks/basics/recipes/                     # receita básica (geralmente executada em todos os nós)
[create] cookbooks/basics/recipes/default.rb
[create] Rakefile                                      # Arquivo de configuração do rake para nós etc
  • Antes de tudo iremos configurar o arquivo Rakefile, para que ao longo do tutorial possamos, além de levantar a VM, possamos rodar o rake.

Esse arquivo irá se utilizar de outros arquivos de configuração que iremos confecionar para que o rake possa passar valores que estarão nos arquivos dentro da pasta config, para as receitas e templates. Além disso seta nós e o script para gerar o bootstrap_common do ssh_config.

require 'yaml'


$BUSINEME_ENV = ENV.fetch('BUSINEME_ENV','local')


ips_file = "config/#{$BUSINEME_ENV}/ips.yaml"
ssh_config_file = "config/#{$BUSINEME_ENV}/ssh_config"
config_file = "config/#{$BUSINEME_ENV}/config.yaml"

ENV['CHAKE_TMPDIR'] = "tmp/chake.#{$BUSINEME_ENV}"
ENV['CHAKE_SSH_CONFIG'] = ssh_config_file

require "chake"

ips ||= YAML.load_file(ips_file)
config ||= YAML.load_file(config_file)

$nodes.each do |node|
	node.data['config'] = config
	node.data['peers'] = ips
end

file 'ssh_config.erb'
if ['local'].include?($BUSINEME_ENV)
	file ssh_config_file => ['nodes.yaml', ips_file, 'ssh_config.erb', 'Rakefile'] do |t|
		require 'erb'
		template = ERB.new(File.read('ssh_config.erb'))
		File.open(t.name, 'w') do |f|
			f.write(template.result(binding))
		end
	puts 'ERB %s' % t.name
	end
end

task :bootstrap_common => 'config/local/ssh_config'

  • Em seguida, após criar a estrutura de diretórios é deletar o diretório roles e criar dois diretórios novos: "local", "homologa", que são nossos ambientes de desenvolvimento e de deploy.
  • Em cada um desses diretórios iremos criar os seguintes arquivos:
$ cd config/local
$ touch config.yaml
$ touch ips.yaml
$ ssh_config                                           # Esse arquivo pode ser gerado pelo bootstrap_common do rake, mas também pode ser feito na mão (enquanto o bootstrap_não está genérico)

O mesmo pro outro diretório:

$ cd config/homologa
$ touch config.yaml
$ touch ips.yaml
$ ssh_config  

No arquivo config.yaml iremos colocar todos os paths de diretórios, URLs necessárias, nomes e versões. Principalmente as que sabemos que serão diferentes entre aplicação e api.

O arquivo ips.yaml segue mesmo padrão, mas colocaremos somente ips.

O arquivo ssh_config irá guardar as configurações de ssh e localização de chaves para as VMs.

Iremos configurar a parte local primeiro então os conteúdos desses arquivos ficam:

# config.yaml (não copie esse comentario)
DIRECTORIES:
  API_REPO: /vagrant/repo/busineme-api
  WEB_REPO: /vagrant/repo/busineme-web
APPLICATION:
  WEB_REPOSITORY: https://github.com/Busineme/BusinemeWeb.git
  API_REPOSITORY: https://github.com/Busineme/BusinemeAPI.git
  API_URL: http://10.10.10.2:8080/api/v1/
  SECRET_KEY: secret-key
DATABASE:
  NAME: busineme
  USER: busineme
  PASSWORD: 1234
  VERSION: 9.3
# ips.yaml (não copie esse comentário)
api:	10.10.10.2
web:	10.10.10.3
# ssh_config (não copie esse comentário)
Host *
  User vagrant
  UserKnownHostsFile /dev/null
  StrictHostKeyChecking no
  PasswordAuthentication no
  IdentitiesOnly yes
  LogLevel FATAL


Host api
  Hostname 10.10.10.2
  Port 22
  IdentityFile .vagrant/machines/api/virtualbox/private_key

Host web
  Hostname 10.10.10.3
  Port 22
  IdentityFile .vagrant/machines/web/virtualbox/private_key


# vim: ft=sshconfig
  • Em seguida iremos configurar nossos nós (nessa aplicação: API e WEB). Fazemos isso no arquivo nodes.yaml. Aqui ja podemos chamar as receitas que posteriormente incluiremos nos diretórios de cookbooks (comente se quiser já levantar o vagrant com o comando vagrant up e uma VM limpa).
# dois nós chamando suas receitas
api:
  run_list:
    - recipe[basics]
  #  - recipe[busineme::postgresql] # comentado pois ainda iremos fazer essa receita
  #  - recipe[busineme::api]

web:
  run_list:
    - recipe[basics]
  #  - recipe[busineme::postgresql]
  #  - recipe[busineme::web]
  • O conteudo do config.rb pode ser mantido.
  • Agora baixaremos as recipes/cookbooks externas que usaremos, e então faremos a nossa recipe interna do chef.
    • Baixe as seguintes cookbooks no diretório cookbooks: git, apt, build-essential, chef-sugar, chef_handler, dmg, openssl, windows, yum, yum-epel. O site para o download é: https://supermarket.chef.io/
    • No arquivo cookbooks/basics/recipes/default.rb, adicione o conteúdo:
# default.rb
execute "apt-get update"
package 'openssh-server'

Para dar um apt-get update e ter servidor ssh em suas VMs, antes de rodar outras receitas.

  • Crie os seguintes diretórios agora:
$ mkdir busineme/files/default busineme/recipes/ busineme/templates/default

No files/default irão os arquivos que, durante a configuração, deverão ser copiados sem alteração. No recipes criaremos nossas receitas. No templates default, colocaremos os arquivos que precisam de alguma generalização antes de serem copiados para algum diretório, durante a configuração feita pela receita.

Já que são muitos arquivos de configuração e templates, recomendamos consulta ao repositório:

https://github.com/Busineme/BusinemeChef/tree/master/cookbooks/busineme/files/default

https://github.com/Busineme/BusinemeChef/tree/master/cookbooks/busineme/templates/default

  • Agora criaremos nossas receitas internas:
$ touch busineme/recipes/web.rb busineme/recipes/api.rb busineme/recipes/postgresql.rb

A receita da base de dados postgresql serve para a criação do usuário, criação do banco e inicialização do serviço. E tem o seguinte conteúdo:

#instala psql
package "postgresql"

# modo debug para ambiente local
if ['local'].include?($BUSINEME_ENV)
  DEBUG = 'True'
  directory "#{REPODIR}" do
    recursive true
  end
else
  DEBUG = 'False'
end

# arquivo configuracao
template "/etc/postgresql/#{node['config']['DATABASE']['VERSION']}/main/pg_hba.conf" do
	source 'pg_hba.conf.erb'
	user 'postgres'
	group 'postgres'
	mode 0600
	notifies :restart, 'service[postgresql]', :immediately
end

# criacao do usuario
DB_USER = node['config']['DATABASE']['USER']
DB_PASSWORD = node['config']['DATABASE']['PASSWORD']
DB_NAME = node['config']['DATABASE']['NAME']
execute "createuser:#{DB_USER}" do
	command "psql -c \"CREATE USER #{DB_USER} WITH PASSWORD '#{DB_PASSWORD}';\""
	user 'postgres'
	not_if "sudo -u postgres psql -c \"select * from pg_user where usename = '#{DB_USER}';\" | grep -c #{DB_USER}"
end

# criacao do banco
execute "createdb:#{DB_NAME}" do
	command "createdb #{DB_NAME} --owner=#{DB_USER}"
	user 'postgres'
	not_if "sudo -u postgres psql -c \"select * from pg_database where datname = '#{DB_NAME}';\" | grep -c #{DB_NAME}"
end

service 'postgresql' do
	action [:enable, :start]
	supports :restart => true
end
  • A receita web.rb é a que configurará a máquina que rodará a aplicação principal. Por partes temos:

Configuração de ambiente local e de deploy e instalações de dependências.

# Variables
$BUSINEME_ENV = ENV.fetch('BUSINEME_ENV', 'local')
package "vim"

package "python2.7" 
package "python-pip" 
package "python-dev"
package "postgresql-contrib"
package "libpq-dev" 
package "postgresql"
package "git"

package "libxml2"
package "libxslt1.1"
package "libxml2-dev"
package "libxslt1-dev"
package "python-libxml2"
package "python-libxslt1"
package "python-lxml"
package "python-setuptools"
package "python-Levenshtein"
package "python-psycopg2"
execute "pip install gunicorn"
package "nginx"
package "supervisor"
package "nginx"


include_recipe "git"

Modo debug para ambiente local e sem debug para ambiente de deploy.

REPODIR = node['config']['DIRECTORIES']['WEB_REPO']
if ['local'].include?($BUSINEME_ENV)
  DEBUG = 'True'
  directory "#{REPODIR}" do
    recursive true
  end
else
  DEBUG = 'False'
end

Clone do repositorio usando a receita externa do git.

git "#{REPODIR}" do
  repository node['config']['APPLICATION']['WEB_REPOSITORY']
  action :sync
end

Instalaçã de requerimentos especificos da aplicação e configuração de ambiente da mesma por meio de templates.

execute 'pip install -r requirements.txt' do
  cwd "#{REPODIR}"
end

template "#{REPODIR}/configuration/databases.py" do
  source "databases.py.erb"
end

template "#{REPODIR}/configuration/security.py" do
  source "security.py.erb"
  variables({:DEBUG => DEBUG})
end

template "#{REPODIR}/configuration/api.py" do
  source "api.py.erb"
end

Criação das tabelas no banco que ja foi criado pela receita do postgresql.

execute 'python manage.py makemigrations' do
  cwd "#{REPODIR}"
end

execute 'python manage.py migrate' do
  cwd "#{REPODIR}"
end

Configuração do supervisor para levantar o nginx como processo, script para levantar o gunicorn que faz o nginx entender o projeto Django como aplicação.

template "/etc/supervisor/conf.d/busineme.conf" do
  source "busineme.conf.erb"
  variables({:REPODIR => REPODIR})
  mode 0600
end

template "#{REPODIR}/gunicorn_script" do
  source "gunicorn_script.erb"
  variables({:REPODIR => REPODIR})
  mode 0775
end

service 'supervisor' do
  action :restart
end

execute 'supervisorctl start busineme' do
  cwd "#{REPODIR}"
end

file "/etc/nginx/sites-available/default" do
  action :delete
end

file "/etc/nginx/sites-enabled/default" do
  action :delete
end

template "/etc/nginx/sites-available/busineme.conf" do
  source "busineme-nginx.conf.erb"
  variables({:REPODIR => REPODIR})
  mode 0600
end

link "/etc/nginx/sites-enabled/busineme.conf" do
  to "/etc/nginx/sites-available/busineme.conf"
  notifies :restart, "service[nginx]"
end

service "nginx" do
  action [:enable, :start]
  supports :restart => true
end

Resultado final:

# Variables
$BUSINEME_ENV = ENV.fetch('BUSINEME_ENV', 'local')
package "vim"

package "python2.7" 
package "python-pip" 
package "python-dev"
package "postgresql-contrib"
package "libpq-dev" 
package "postgresql"
package "git"

package "libxml2"
package "libxslt1.1"
package "libxml2-dev"
package "libxslt1-dev"
package "python-libxml2"
package "python-libxslt1"
package "python-lxml"
package "python-setuptools"
package "python-Levenshtein"
package "python-psycopg2"
execute "pip install gunicorn"
package "nginx"
package "supervisor"
package "nginx"


include_recipe "git"

REPODIR = node['config']['DIRECTORIES']['WEB_REPO']
if ['local'].include?($BUSINEME_ENV)
  DEBUG = 'True'
  directory "#{REPODIR}" do
    recursive true
  end
else
  DEBUG = 'False'
end

git "#{REPODIR}" do
  repository node['config']['APPLICATION']['WEB_REPOSITORY']
  action :sync
end


execute 'pip install -r requirements.txt' do
  cwd "#{REPODIR}"
end

template "#{REPODIR}/configuration/databases.py" do
  source "databases.py.erb"
end

template "#{REPODIR}/configuration/security.py" do
  source "security.py.erb"
  variables({:DEBUG => DEBUG})
end

template "#{REPODIR}/configuration/api.py" do
  source "api.py.erb"
end


execute 'python manage.py makemigrations' do
  cwd "#{REPODIR}"
end

execute 'python manage.py migrate' do
  cwd "#{REPODIR}"
end

template "/etc/supervisor/conf.d/busineme.conf" do
  source "busineme.conf.erb"
  variables({:REPODIR => REPODIR})
  mode 0600
end

template "#{REPODIR}/gunicorn_script" do
  source "gunicorn_script.erb"
  variables({:REPODIR => REPODIR})
  mode 0775
end

service 'supervisor' do
  action :restart
end

execute 'supervisorctl start busineme' do
  cwd "#{REPODIR}"
end

file "/etc/nginx/sites-available/default" do
  action :delete
end

file "/etc/nginx/sites-enabled/default" do
  action :delete
end

template "/etc/nginx/sites-available/busineme.conf" do
  source "busineme-nginx.conf.erb"
  variables({:REPODIR => REPODIR})
  mode 0600
end

link "/etc/nginx/sites-enabled/busineme.conf" do
  to "/etc/nginx/sites-available/busineme.conf"
  notifies :restart, "service[nginx]"
end

service "nginx" do
  action [:enable, :start]
  supports :restart => true
end
  • Com isso já é possível levantar o ambiente de desenvolvimento local. Basta seguir o diagrama de desenvolviemnto com os seguintes comandos:
$ vagrant up
$ rake # ou rake converge:web ou rake convege:api para rodar receitas específicas

Esses dois comandos podem demorar bastante pois levantam a VM sem nada e instalam tudo das receitas. A segunda vez irá só atualizar com mudanças (se houverem) nas receitas. Se for necessário destruir as VMs e todos seus vestígios, rode:

$ vagrant destroy

Para logar em alguma vm use:

$ rake login:web

ou

$ rake login:api 
  • Para visualizar o desenvolvimento, não é necessário rodar o runserver pra VM web, pois ele já está rodando pelo nginx. Basta acessar no ip 10.10.10.3 (arquivo de configuração de ips).
  • Entretanto é necessário rodar o runserver da API
$ ./manage.py runserver 0.0.0.0:8080


4.5.2 Deploy editar

Para as configurações de deploy temos que ter conteúdo diferentes nos arquivos config.yaml, ips.yaml e ssh_config, agora no diretorio config/homologa. Esses conteúdos diferentes estão sendo passados para os templates e para as receitas, justamente para fazer com que sejam genéricos para rodarem locais ou em deploy.

Esses conteúdos serão:

# config.yaml (não copie esse comentário)
DIRECTORIES:
  API_REPO: /opt/busineme-api
  WEB_REPO: /opt/busineme-web
APPLICATION:
  WEB_REPOSITORY: https://github.com/Busineme/BusinemeWeb.git
  API_REPOSITORY: https://github.com/Busineme/BusinemeAPI.git
  API_URL: http://businemeweb.cloudapp.net/api/v1/
  SECRET_KEY: secret-key
DATABASE:
  NAME: busineme
  USER: busineme
  PASSWORD: 1234
  VERSION: 9.4
# ips.yaml (não copie esse comentário)
api:	23.96.43.247
web:	23.96.100.196
# ssh_config
Host api
 Hostname 23.96.43.247
 Port 22
 User busineme

Host web
 Hostname 23.96.100.196
 Port 22
 User busineme

# vim: ft=sshconfig
  • Também é necessário adicionar um post build action no Jenkins fazendo o seguinte:
git pull https://github.com/Busineme/BusinemeChef.git && \
cd BusinemeChef && \
sudo gem install rake && \
sudo gem install chake && \
rake BUSINEME_ENV=homologa

Sendo que o repositório do BusinemeChef na máquina do jenkins já tem que estar clonado.

  • Para rodar o chake para deploy:
$ rake BUSINEME_ENV=homologa
  • Para fazer um teste rápido talvez seja interessante rodar um
$ rake run BUSINEME_ENV=homologa

E digitar

$ date

Para verificar se o output é semelhante a esse:

api: $ date
api: Thu Jul  2 04:41:18 UTC 2015
web: $ date
web: Thu Jul  2 04:41:19 UTC 2015

Para ter certeza que tudo está em ordem antes de executar receitas.


5. Resultado editar

Diagrama de automatização do ambiente de desenvolvimento. editar

 

Diagrama de automatização de build e deploy. editar