Saltar para o conteúdo

PET

Fonte: Wikiversidade

Autores: Tiago R. Assunção e Wesley Araújo

Este projeto de Gerência de Configuração foi desenvolvido como pré requisito parcial para a disciplina de GCS(Gerência de Configuração de Software) da Faculdade UnB-Gama(FGA). De acordo com o RUP, o Plano de Gerenciamento de Configuração (CM) descreve todas as atividades do Gerenciamento de Controle de Configuração que serão executadas durante o ciclo de vida do produto ou do projeto. Este presente plano apresentará os pontos envolvendo gerência de configuração no projeto Package Entropy Tracker(PET), que pode ser acessado neste link, que faz o Tracking dos pacotes que estão sendo desenvolvidos pelos Debian Developers(DD's).

O PET é dividido em oito módulos:

  1. bts
  2. classifier
  3. models
  4. perlre
  5. sql
  6. update
  7. vcs
  8. watch

Este software busca nos repositórios estabelecidos todos os pacotes desenvolvidos para o Debian. Ele possibilita a visualização das versões dos pacotes, branchs, diferenças entre elas, os repositórios dos UpStreams, quantidade de bugs em cada pacote, entre outros pontos. Além disso, todos os pacotes são divididos por time de desenvolvimento, por exemplo:

  • Time de Perl
  • Time de Java
  • Time de Ruby

Assim, possuem vários outros times que desenvolvem os pacotes.

Atualmente, o processo de instalação pode ser feito através do Vagrant, que já está configurado ou instalando as dependências diretamente em sua máquina.

O repositório atual pode ser encontrado no GitHub-PET

Repositórios

[editar | editar código-fonte]

Empacotamento pyramid_chameleon: https://github.com/gcs-fga/pyramid-chameleon_packing

Empacotamento debian: https://github.com/gcs-fga/pet

Vagrant usando puppet: https://github.com/gcs-fga/pet_vagrant_puppet

Empacotamento pip: https://github.com/gcs-fga/pet_pip_packing

Iremos descrever aqui os pontos necessários quanto a Gerecia de Configuração de Software que será aplicado no PET, bem como algumas diretrizes para a normatização de que se procederá para aplicar os pontos propostos.

  1. Empacotar o PET em um arquivo .deb.
  2. Automatizar o deploy no ambiente de produção usando uma receita chef

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

[editar | editar código-fonte]

PET - Package Entropy Tracker

RUP - Rational Unified Process

Debian - Sistema Operacional de distribuição Linux que segue a licença GNU.

Definição das Sprints

[editar | editar código-fonte]
Sprint Data Atividade
01 27/04 - 11/05 Início do Processo de Empacotamento do PET
02 12/05 - 25/05 Finalização do Processo de Empacotamento do PET
03 26/05 - 15/06 Vagrant usando puppet

Empacotamento pip na Pypi

Definição das Milestones

[editar | editar código-fonte]
  1. 27/06 - Definição do Plano de SCM
  2. 01/06 - Ponto de Controle
  3. 22/06 - Entrega Final do Trabalho

Ferramentas Utilizadas

[editar | editar código-fonte]

Empacotadores Debian

[editar | editar código-fonte]
  • dpkg
  • dh_make
  • debuid

Manipulador de pacotes debian .deb. Para utilização do dpkg acessar https://debian-handbook.info/browse/pt-BR/stable/sect.manipulating-packages-with-dpkg.html

Vagrant é uma ferramenta de virtualização de ambientes que, aliado ao Virtual Box da Oracle, permite criar ambientes de desenvolvimento sem a necessidade de configuração direta no computador, trazendo vantagens de, por exemplo, ter múltiplos ambientes de desenvolvimento no mesmo computador.

Empacotamento Pyramid-Chameleon
[editar | editar código-fonte]

O pacote pyramid-chameleon só é possível instalar por meio do pip. Como o PET utiliza essa dependência, porém não consegue acessar pelo pip, é necessário empacotar o pyramid-chameleon também para .deb. Todas as instruções do empacotamento geral estão na subceção "Ambiente Necessário para o Empacotamento", aqui da Seção de resultado, por isso, nesta subceção só será tratado de como está configurado os arquivos principais da pasta debian para o pyramid_chameleon.

Para que seja possível a instalação do pacote, é preciso ter duas dependências que são instaladas com o APT:

  • python-pyramid
  • python-chameleon
Processo de Empacotamento
[editar | editar código-fonte]

Primeiro, é necessário fazer o clone da source do pyramid_chameleon

# Clona o repositório
git clone https://github.com/gcs-fga/pyramid-chameleon_packing.git

# Sincroniza as branchs
git fetch

# Altera a branch para a de empacotamento 
git checkout packing-debian

Renomear o diretório do repositório local

mv pyramid-chameleon_packing pyramid-chameleon-0.1

Após isso, é preciso criar um .tar.gz do diretório, porém, como no nosso repositório já existe uma pasta debian, pode-se ignora-la pelo comando tar:

tar -zcvf pyramid-chameleon-0.1.tar.gz pyramid-chameleon-0.1/ --exclude=/debian
Arquivo Control
[editar | editar código-fonte]

O arquivo control precisa das dependências do python. Como esse pacote está apenas para o python 2, então não foi adicionado o python3.

Source: pyramid-chameleon
Section: unknown
Priority: optional
Maintainer: Tiago Assuncao <tiago@sof2u.com>
            Wesley Araujo <wesley.sickert@gmail.com>
Build-Depends: debhelper (>= 9), python (>= 2.6.6-3~) 
X-Python-Version: >= 2.6
Standards-Version: 3.9.5
Homepage: <insert the upstream URL, if relevant>
#Vcs-Git: git://anonscm.debian.org/collab-maint/pyramid-chameleon.git
#Vcs-Browser: http://anonscm.debian.org/?p=collab-maint/pyramid-chameleon.git;a=summary

Package: pyramid-chameleon
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}, ${python:Depends}
Description: pyramid-chameleon to python2
 pyramid_chameleon is a set of bindings that make templates written for the Cham eleon templating system work under the Pyramid web framework
Status API Training Shop Blog About
Criando o .deb
[editar | editar código-fonte]

Após a preparação do arquivo control, o dh_make é executado no diretório do projeto, fora do /debian. O dh_make não irá sobrescrever o diretório /debian já criado.

dh_make -f ../pyramid-chameleon-0.1.tar.gz

Depois de executado o dh_make, o build é criado através do debuild.

debuild -us -uc

Quando o debuild é executado, o nosso pacote .deb estará fora do nosso diretório do projeto, o diretório anterior.

Ambiente Necessário para o Empacotamento

[editar | editar código-fonte]

Iniciando o processo de empacotamento, é necessário instalar duas ferramentas que utilizadas para gerar a primeira estrutura do pacote e outro para fazer a build do pacote montado. Eles são o dh_make e o debuild.

O primeiro pacote é o dh_make, que gera um template dos arquivos necessários para o empacotamento. Ele pode ser instalado pelo repositório do debian:

$ sudo apt-get install dh-make

Após, o pacote necessário para fazer a build do pacote deve ser instalado:

$ sudo apt-get install build-essential

Pronto. Seu ambiente está pronto para gerar os pacotes básicos do debian.

Elaboração do Script de Empacotamento

[editar | editar código-fonte]

Seguirá aqui um roteiro da elaboração do pacote utilizando o repositório do PET para GCS: https://github.com/gcs-fga/pet.

O primeiro passo para criar nosso pacote é obter o código do Upstream. Assim, foi feito um clone nas nossas máquinas dos mantenedores:

$ git clone https://anonscm.debian.org/cgit/pet/pet3.git/

Após, faz-se necessário para o dh_make que o diretório do empacotamento esteja no formato contento a versão do pacote, da seguinte maneira: pet-0.1/.

Criação da estrutura do empacotamento
[editar | editar código-fonte]

Assim, a pasta pet foi renomeada:

$ mv pet pet-0.1

Além disso, o dh utiliza de um aquivo comprimido para executar o empacotamento. Dessa maneira, o seguinte comando foi utilizado para transformar o diretório em um arquivo .tar.gz:

$ tar -zcvf pet-0.1.tar.gz pet-0.1/

Assim, a primeira estrutura contendo templates pode ser criada utilizando o dh(se faz necessário entrar na pasta pet-0.1 e rodar o dh_make lá de dentro passando como argumento o arquivo .tar.gz):

$ dh_make -f ../pet-0.1.tar.gz

Dessa maneira, a pasta debian/ é criada. Ela armazena todos os arquivos necessários para fazer o empacotamento. São criados vários arquivos exemplos com a extensão .ex e .EX. Além deles, outros arquivos como watch são desnecessários. Assim, todos esses arquivos foram apagados a partir da raiz do diretório:

$ cd debian/
$ rm *.ex
$ rm *.EX
$ rm watch
$ cd ..

Dentro do arquivo rules, existe vários conteúdos desnecessários que foram apagados. E apenas o código a seguir permaneceu:

#!/usr/bin/make -f
# -*- makefile -*-

# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1

%:
	dh $@
Criação da secret key
[editar | editar código-fonte]

Para a autenticação do pacote, é necessário criar um par de chaves assimétricas no computador de quem gera o pacote. Para isso, usa-se a ferramenta gpg:

Primeiramente, cria-se um arquivo na home com alguns parâmetros pessoais para a utilização do gpg. Um exemplo pode ser o arquivo criado a seguir, que pode ser visto também no site https://keyring.debian.org/creating-key.html:

$ mkdir -p ~/.gnupg/
$ vim ~/.gnupg/gpg.conf

E adicione o seguinte conteúdo no arquivo gpg.conf:

 personal-digest-preferences SHA256
 cert-digest-algo SHA256
 default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed

Agora pode-se gerar a chave através do comando:

$ gpg --gen-key

Ao criar a chave, ele dará 4 opções de tipo de chaves assimétricas. A mais comum no dia de hoje é a RSA. Pode-se escolher a primeira opção que utiliza a assinatura digital com RSA e o par de chaves com RSA, a opção 1.

Após, é indagado sobre em quanto tempo sua chave deve expirar, pode escolher quanto tempo desejar. Assim, ele questiona qual o nome do quem está gerando a chave, bem como seu email. Esse par de campos será utilizado como identificador da sua chave.

Será solicitado uma palavra passe para você utilizar a chave(Não esqueça essa palavra passe).

Logo após, o algorítimo que faz a geração da chave aleatória necessita de uma fonte de entropia para gerar os números primos que compõem o RSA. O sistema operacional irá utilizar as fontes de entropia do seu computador, que são as entradas do mouse e do teclado, além dos movimentos da pinça que posiciona a agulha do disco rígido. Depois de algum tempo, que todos os bytes aleatórios forem gerados, a sua chave será criada.

Registro da Chave no Changelog
[editar | editar código-fonte]

No final da geração da chave, uma ID da chave será indicada na tela. Ela é composta pelo nome e email citados pelo gerador da chave no seguinte formato:

 Test User <test@example.org>

A final, pra que server essa chave?

Ela deve ser adicionada no arquivo de Changelog com as mudanças que foram feitas no empacotamento. E a chave deve ser adicionada no Initial Release, como o exemplo a seguir:

pet (0.1-1) unstable; urgency=low

  * Initial release (Closes: #nnnn)  <nnnn is the bug number of your ITP>

 -- Tiago Assuncao <tiago@sof2u.com>  Tue, 31 May 2016 21:44:08 -0300
Edição do Control
[editar | editar código-fonte]

O control é o principal arquivo do empacotamento, onde são colocadas informações tais como o nome do pacote, versão, importância, arquitetura dos sistemas(32, 64, etc), pacotes necessários para a build da instalação e pacotes para a sua execução. O arquivo control vem com um template gerado pelo dh_make quem vem a seguir:

 1 Source: package_name
 2 Section: unknown
 3 Priority: extra
 4 Maintainer: User Test <user_test@debian.org>
 5 Build-Depends: debhelper (>=9)
 6 Standards-Version: 3.9.4
 7 Homepage: <insert the upstream URL, if relevant>
 8
 9 Package: package_name
10 Architecture: any
11 Depends: ${shlibs:Depends}, ${misc:Depends}
12 Description: <insert up to 60 chars description>
13  <insert long description, indented with spaces>

O pacote do PET tem algumas propriedades específicas. A descrição foi utilizada por padrão a do pet.

E o ponto mais crítico é adicionar as dependências do projeto. Dentro do PET, foram identificadas todas as dependências de execução do software. Os seguintes pacotes foram identificados:

  1. python,
  2. postgresql-9.4-debversion,
  3. postgresql-9.4,
  4. wget,
  5. python-paste,
  6. python-argparse,
  7. python-debian,
  8. python-debianbts,
  9. python-inotifyx,
  10. python-psycopg2,
  11. python-pyramid,
  12. python-sqlalchemy,
  13. python-subversion

Além das dependências do python em geral, pois, o PET é escrito nesta linguagem, que pode ser entendido como: ${python:Depends}

Para as dependências de Build foram identificados os seguintes pacotes:

  • debhelper (>= 8.0.0),
  • postgresql-9.4

Dessa forma, o arquivo control se encontra desta maneira até o momento:

Source: pet
Section: base
Maintainer: Tiago Assuncao <tiago@sof2u.com>
            Wesley Araujo <wesley.sickert@gmail.com>
Build-Depends: debhelper (>= 8.0.0), postgresql-9.4
Standards-Version: 3.9.4
Priority: optional

Package: pet
# Version: 0.1
Architecture: any
Depends: ${shlibs:Depends}, ${python:Depends}, ${misc:Depends}, postgresql-9.4-debversion, postgresql-9.4, wget, python-argparse, python-debian, python-debianbts, python-inotifyx, python-paste, python-psycopg2, python-pyramid, python-sqlalchemy, python-subversion
Description: PET - Package Entropy Tracker
	PET is a collection of scripts that gather information about your (or your group's) packages. It allows you to see in a bird's eye view the health of hundreds of packages, instantly realizing where work is needed.

Criação do Pacote

[editar | editar código-fonte]

Para criar o pacote, a segunda ferramenta é utlizada: debuild. Este passo é bem simples. Basta rodar o comando e ele irá compilar o pacote dentro de um .deb e colocá-lo no mesmo diretório que o arquivo .tar.gz foi criado. Dessa maneira:

$ debuild

Dessa maneira, o pacote pode ser distribuído e instalado. Um exemplo de instalação vem a seguir:

$ cd ..
$ sudo dpkg -i pet_0.1-1_i386.deb

Assim o pacote será instalado, para mais detalhes, ir para a Subseção de instalação.

Como dito anteriormente, o source do pacote pode ser encontrado no seguinte repositório: https://github.com/gcs-fga/pet/

Instalação do PET via pacote Debian

[editar | editar código-fonte]

Antes da instalação do pacote PET, é necessário instalar o pacote do pyramid_chamaleon.

$ sudo dpkg -i pyramid-chameleon

Depois, a instalação do PET

$ sudo dpkg -i pet

Utilização do PET

[editar | editar código-fonte]

Quando instalado, o PET é executado por meio do comando pet, no qual permite atualizar o repositório local, pegar os pacotes do repositorio atualizado usando o nome do pacote como argumento e rodar o servidor. Para informações da utilização do pet, utuilizar a opção -h ou --help:

# Atualiza o repositório
$ pet -u -r 

# Pega pacote(s)
$ update-package nome_pacotes

# Atualiza os pacotes 
$ pet -u -p

# Roda o PET
$ pet -s

Observações:

Caso o comando pet não possa ser encontrado, configurar para que a variável PATH tenha as paths /usr/bin/pet para o comando update-package e /usr/bin/pet/shell para o comando pet.

A opção -h detalha as opções e argumentos e também mostra como rodar o pet em um mini-tutorial.

Criação dos Parâmetros com o Vagrant

[editar | editar código-fonte]

Vagrant usando Puppet

[editar | editar código-fonte]

O Puppet foi utilizado como ferramenta de gerência de configuração para a instalação de todas as dependências na virtualização do vagrant, apesar do Chef estar disponível antes por outra equipe.

Configuração do Vagrantfile
[editar | editar código-fonte]

O Vagrantfile foi configurado para que o ambiente de desenvolvimento contesse o puppet já instalado, sendo utilizado o shell que está na subseção de instalação do puppet.

# -*- mode: ruby -*-
# vi: set ft=ruby :

# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.box = "debian/jessie64"
  config.vm.provider "virtualbox" do |vm, override|
    override.vm.network 'forwarded_port', guest: "8080" , host: "4567"
  end

  # puppet-bootstrap
  config.vm.provision "shell", path: "scripts/debian.sh"

  config.vm.provision "puppet" do |puppet|
    puppet.manifest_file = "site.pp"
    puppet.manifests_path = "manifests"
  end
end
Execução do Shell de Instalação do Puppet
[editar | editar código-fonte]

Esta parte é importante para que seja executado o shell de instalação, que é detalhado na subseção Instalação do Puppet, utilizando-se do provisioner "shell" do Vagrant.

# puppet-bootstrap
  config.vm.provision "shell", path: "scripts/debian.sh"
Configuração do puppet para o Manifest
[editar | editar código-fonte]

Com o provisioner "puppet" disponível no Vagrant, o arquivo manifest, que conterá as dependências, é criado e também o caminho no qual os manifests estarão.

 config.vm.provision "puppet" do |puppet|
    puppet.manifest_file = "site.pp"
    puppet.manifests_path = "manifests"
  end
Instalação do Puppet
[editar | editar código-fonte]

A instalação do Puppet é feita pelo script "debian.sh", que foi referenciado no Vagrantfile no provisioner "shell".

#!/usr/bin/env sh
echo "Initial apt-get update..."
apt-get update >/dev/null
REPO_DEB_URL="http://apt.puppetlabs.com/puppetlabs-release-jessie.deb"
echo "Installing wget..."
apt-get --yes install wget >/dev/null
echo "Configuring PuppetLabs repo..."
repo_deb_path=$(mktemp)
wget --output-document="${repo_deb_path}" "${REPO_DEB_URL}" 2>/dev/null
dpkg -i "${repo_deb_path}" >/dev/null
rm "${repo_deb_path}"
apt-get update >/dev/null
echo "Installing Puppet..."
DEBIAN_FRONTEND=noninteractive apt-get -y  install puppet >/dev/null
echo "Puppet installed!"
Atualizando apt-get e instalando o wget
[editar | editar código-fonte]

Antes de tudo, o apt-get é atualizado para que seja mais recente e os pacotes também. Logo depois é criada uma variável de ambiente com o nome REPO_DEB_URL que contém o pacote Debian para o Puppet. Então é utilizado o apt-get para a instalação do wget que será usado posteriormente.

echo "Initial apt-get update..."
apt-get update >/dev/null
REPO_DEB_URL="http://apt.puppetlabs.com/puppetlabs-release-jessie.deb"
echo "Installing wget..."
apt-get --yes install wget >/dev/null
Configurando o Repositório do PuppetLabs
[editar | editar código-fonte]

É criada um diretório temporário e armazenado o path na variável repo_deb_path.

Utiliza-se o comando --output-document do wget para adicionar os parâmetros do path onde será armazenado o repositório e a url de onde virá, que está na variável de ambiente REPO_DEB_URL. Depois disso o arquivo .deb é desempacotado com o dpkg e então a path temporária é removida. O apt-get é atualizado novamente.

echo "Configuring PuppetLabs repo..."
repo_deb_path=$(mktemp)
wget --output-document="${repo_deb_path}" "${REPO_DEB_URL}" 2>/dev/null
dpkg -i "${repo_deb_path}" >/dev/null
rm "${repo_deb_path}"
apt-get update >/dev/null
Conclusão da Instalação
[editar | editar código-fonte]

Finalmente é instalado o Puppet. É importante que a instalação por meio do apt-get não seja interativo [1]

echo "Installing Puppet..."
DEBIAN_FRONTEND=noninteractive apt-get -y  install puppet >/dev/null
echo "Puppet installed!"
Configuração do Manifest
[editar | editar código-fonte]

Após a instalação correta do Puppet com o Vagrant, o nosso manifest "site.pp" é configurado com as dependências necessárias. É importante notar que os pacotes que não são instalados com o apt-get devem ter seu comando explicitado, como é o caso do pyramid_chameleon, que é executado pelo pip. Um usuário "pet" é criado e o arquivo postgresql.conf é substituído por outro que está na path manifests/files, o mesmo ocorre com o pg_hba.conf. Depois o um banco é criado no postgres e populado com as devidas configurações que o PET necessita.

package { [
  'python',
  'vim',
  'vagrant',
  'python-pip',
  'postgresql-9.4',
  'postgresql-9.4-debversion',
  'python-argparse',
  'python-debian',
  'python-debianbts',
  'python-inotifyx',
  'python-paste',
  'python-psycopg2',
  'python-pyramid',
  'python-sqlalchemy',
  'python-subversion',
]:
  ensure => present,
}
package { 'pyramid_chameleon':
  provider => pip,
  ensure =>present,
}

include user
class user{
  user { 'pet':
    ensure     => present,
    shell      => '/bin/bash',
    home       => '/home/pet',
  }

  file { 'postgresql conf':
    path => '/etc/postgresql/9.4/main/postgresql.conf',
    ensure => file,
    content => template("/tmp/vagrant-puppet-4/manifests/files/postgresql.conf"),
  }

  file { 'pg_hba conf':
    path => '/etc/postgresql/9.4/main/pg_hba.conf',
    ensure => file,
    content => template("/tmp/vagrant-puppet-4/manifests/files/pg_hba.conf"),
  }

  exec { 'psql create user':
    user => "postgres",
    command => "/usr/bin/createuser pet",
    path => "/home/pet",
    unless => "/usr/bin/psql postgres -tAc \"SELECT 1 FROM pg_roles WHERE rolname='pet'\" | /bin/grep -q 1"
  }

  exec { 'create db pet':
    user => "postgres",
    command => "/usr/bin/createdb -O pet pet",
    path => "/home/pet",
    unless => "/usr/bin/psql -lqt | /usr/bin/cut -d \| -f 1 | /bin/grep -qw pet",
  }

  exec { 'implements deb version':
    user => "postgres",
    command => "/usr/bin/psql pet < /usr/share/postgresql/9.4/contrib/debversion.sql",
    path => "/home/pet",
  }

  file { 'hosts file':
    path => "/etc/hosts",
    ensure => file,
    content => template("/tmp/vagrant-puppet-4/manifests/files/hosts"),
  }

  service {"postgresql":
    ensure => running,
    enable => true,
    hasrestart => true,
  }

  exec { "creating tables":
    command => "/usr/bin/python /vagrant/pet-update -c -nc",
    user => "pet",
    unless => "/usr/bin/psql pet -tAc \"SELECT 1 FROM team\" | /bin/grep -q 1",
    path => "/",
  }

  exec{ "insert a team on bd":
    command => "/usr/bin/psql pet --command \"INSERT INTO team (name, maintainer, url) VALUES ('pkg-perl', 'Debian Perl Group <pkg-perl-maintainers@lists.alioth.debian.org>', 'http://pkg-perl.alioth.debian.org/');\"",
    user => "pet",
    unless => "/usr/bin/psql pet -tAc \"SELECT * FROM team WHERE name='pkg-perl'\" | /bin/grep -q 'pkg-perl'",
  }
  exec{ "database insert repository table":
    command => "/usr/bin/psql pet --command \"INSERT INTO repository (name, type, root, web_root, team_id) VALUES ('git','git','https://pet.alioth.debian.org/pet2-data/pkg-perl/git-pkg-perl-packages.json','http://anonscm.debian.org/gitweb/?p=pkg-perl/packages', 1);\"",
    user => "pet",
    unless => "/usr/bin/psql pet -tAc \"SELECT * FROM repository WHERE name='git'\" | /bin/grep -q 'git'",
  }
  exec{ "database insert package table":
    command => "/usr/bin/psql pet --command \"INSERT INTO package (name, repository_id) VALUES ('clive', 1);\"",
    user => "pet",
    unless => "/usr/bin/psql pet -tAc \"SELECT * FROM package WHERE name='clive'\" | /bin/grep -q 'clive'"
  }

  exec{ "database insert archive table":
    command => "/usr/bin/psql pet --command \"INSERT INTO archive (name, url, web_root) VALUES ('debian', 'http://cdn.debian.net/debian', 'http://packages.qa.debian.org/');\"",
    user => "pet",
    unless => "/usr/bin/psql pet -tAc \"SELECT * FROM archive WHERE name='debian'\" | /bin/grep -q 'debian'",
  }
  exec{ "database insert suite table":
    command => "/usr/bin/psql pet --command \"INSERT INTO suite (archive_id, name) VALUES (1, 'unstable');\"",
    user => "pet",
    unless => "/usr/bin/psql pet -tAc \"SELECT * FROM suite WHERE name='unstable'\" | /bin/grep -q 'unstable'",
  }
}

Empacotamento Pip

[editar | editar código-fonte]

O pip é a ferramenta de controle de pacotes padrão dos pacotes python. Qualquer desenvolvedor pode desenvolver seus pacotes e deixá-los disponíveis para download e instalação. Eles são todos controlados pela Pypi https://pypi.python.org/pypi.

De ante mão, nosso pacote encontra-se disponível na seguinte url: https://pypi.python.org/pypi/pet-debian/

O processo de instalação seguido foi o estabelecido no site oficial do python: https://packaging.python.org/en/latest/distributing/.

Bem, para a criação do pacote, é necessário que haja uma estrutura correta dos arquivos e da criação de alguns arquivos, como: setup.py, MANIFESTS.in, setup.cfg, entre outros que serão listados a seguir:

Estrutura de diretórios

[editar | editar código-fonte]

Há a necessidade que uma estrutura de diretórios seja seguida para o setup.py consiga fazer todo o empacotamento de maneira correta. Primeiramente, todos os arquivos de configuração do pypi devem ser colocados dentro da pasta raiz. E tudo o que será utilizado no software deve ser implementado dentro da sub pasta com mesmo nome do projeto, contendo o arquivo __init__.py do projeto.

funniest/
    funniest/
        __init__.py
        app1/
            models.py
            views.py
        app2/
            models.py
        update.py
        server.py
    COPYING
    README.rst
    README.md
    MANIFEST.in
    setup.py
    setup.cfg

O projeto do pet ficou com a seguinte estrutura de diretórios:

.
├── [4.0K]  build/
│   ├── [4.0K]  bdist.linux-i686/
│   └── [4.0K]  lib.linux-i686-2.7/
│       └── [4.0K]  pet/
│           ├── [4.0K]  web/
│           │   ├── [1.5K]  __init__.py
│           │   └── [3.1K]  views.py
│           ├── [   0]  asdfas.py
│           ├── [5.2K]  bts.py
│           ├── [6.6K]  classifier.py
│           ├── [1.5K]  exceptions.py
│           ├── [1.2K]  __init__.py
│           ├── [7.5K]  models.py
│           ├── [4.0K]  perlre.py
│           ├── [1.4K]  pet_update.py
│           ├── [ 122]  serve.py
│           ├── [ 11K]  sql.py
│           ├── [ 16K]  update.py
│           ├── [ 13K]  vcs.py
│           └── [ 11K]  watch.py
├── [4.0K]  cookbooks/
│   └── [4.0K]  pet/
│       ├── [4.0K]  files/
│       │   ├── [ 248]  hosts
│       │   ├── [4.6K]  pg_hba.conf
│       │   └── [ 21K]  postgresql.conf
│       └── [4.0K]  recipes/
│           └── [3.4K]  default.rb
├── [4.0K]  dist/
│   ├── [ 34K]  pet_debian-1.2.72-py2-none-any.whl
│   └── [ 28K]  pet-debian-1.2.72.tar.gz
├── [4.0K]  doc/
│   └── [2.8K]  debconf11-pet-bof.txt
├── [ 12K]  log/
│   ├── [ 33K]  pet_debian-1.2.0-py2-none-any.whl
│   ├── [ 24K]  pet-debian-1.2.0.tar.gz
├── [4.0K]  pet/
│   ├── [4.0K]  __pycache__/
│   │   ├── [ 492]  __init__.cpython-34.pyc
│   │   └── [9.3K]  models.cpython-34.pyc
│   ├── [4.0K]  web/
│   │   ├── [4.0K]  __pycache__/
│   │   │   └── [1.2K]  __init__.cpython-34.pyc
│   │   ├── [4.0K]  static/
│   │   │   ├── [3.7K]  default.css
│   │   │   └── [1.4K]  overview.js
│   │   ├── [4.0K]  templates/
│   │   │   ├── [ 612]  changelog.pt
│   │   │   └── [3.9K]  overview.pt
│   │   ├── [1.5K]  __init__.py
│   │   └── [3.1K]  views.py
│   ├── [5.2K]  bts.py
│   ├── [6.6K]  classifier.py
│   ├── [1.5K]  exceptions.py
│   ├── [1.2K]  __init__.py
│   ├── [7.5K]  models.py
│   ├── [4.0K]  perlre.py
│   ├── [1.4K]  pet_update.py*
│   ├── [4.0K]  README.rst
│   ├── [ 122]  serve.py
│   ├── [ 11K]  sql.py
│   ├── [ 16K]  update.py
│   ├── [ 13K]  vcs.py
│   └── [ 11K]  watch.py
├── [4.0K]  pet_debian.egg-info/
│   ├── [   1]  dependency_links.txt
│   ├── [  90]  entry_points.txt
│   ├── [5.8K]  PKG-INFO
│   ├── [  29]  requires.txt
│   ├── [ 580]  SOURCES.txt
│   └── [   4]  top_level.txt
├── [4.0K]  __pycache__/
│   ├── [ 414]  serve.cpython-34.pyc
│   └── [ 267]  teste.cpython-34.pyc
├── [  74]  COPYING
├── [2.6K]  Dockerfile
├── [ 161]  Makefile
├── [  79]  MANIFEST.in
├── [3.3K]  pet-cat-file*
├── [2.9K]  petd*
├── [ 873]  pet.wsgi
├── [4.0K]  README.md
├── [4.0K]  README.rst
├── [ 300]  serve.py
├── [  44]  setup.cfg
├── [5.4K]  setup-pkg-go
├── [3.3K]  setup.py
├── [1.1K]  TODO
├── [1.2K]  update-archive*
├── [1.0K]  update-bts*
├── [1.3K]  update-package*
├── [1.6K]  update-repository*
├── [1.5K]  update-watch*
└── [3.3K]  Vagrantfile

20 directories, 213 files

Configuração do setup.py

[editar | editar código-fonte]

O arquivo setup.py é o principal arquivo do empacotamento, e sua configuração será descrita nas variáveis que tem que ser configuradas a seguir:

Para compilar o setup, são necessários alguns imports. O primeiro deles é o próprio método de setup, que receberá todos os parâmetros de configuração. Outro módulo é o find_packages, que irá fazer uma busca automática dos pacotes que o seu depende. Por fim, dois módulos de configuração de arquivos, o open e o path, para encontrar algum caminho no sistema e para abrir o README.rst.

from setuptools import setup, find_packages
from codecs import open
from os import path
Descrição longa
[editar | editar código-fonte]

Para utilizar posteriormente, é necessário declarar algumas variáveis úteis. A primeira delas é o here, que captura, utilizando o path, o diretório absoluto do arquivo setup.py. Além disso, guardamos a descrição longa do pacote oriunda do README.rst através do open, utilizando o path.

here = path.abspath(path.dirname(__file__))

with open(path.join(here, 'README.rst'), encoding='utf-8') as f:
    long_description = f.read()
Dados iniciais
[editar | editar código-fonte]

Para identificar o pacote com nome, versão, descrição curta, url do source, nome e email do autor e a licença devem ser passados nas seguintes variáveis:

    name='pet-debian',
    version='1.2.71',
    description='PET is a collection of scripts that gather informatio about your packages',
    long_description=long_description,
    url='https://github.com/PET-UnB/pet',
    author='Tiago Assuncao',
    author_email='tiago@sof2u.com',
    license='GPL3',
Classificadores
[editar | editar código-fonte]

Os classificadores são parâmetros que servem para facilitar que os usuários encontrem pacotes por categorias. Você deve sempre colocar as categorias condizentes com o seu pacote. No link a seguir, estão listadas todas as categorias existentes: https://pypi.python.org/pypi?%3Aaction=list_classifiers.

Segue a baixo um exemplo de lista de classificadores:

    classifiers=[
        # How mature is this project? Common values are
        #   3 - Alpha
        #   4 - Beta
        #   5 - Production/Stable
        'Development Status :: 3 - Alpha',

        # Indicate who your project is intended for
        'Intended Audience :: Developers',
        'Topic :: Software Development :: Build Tools',

        # Pick your license as you wish (should match "license" above)
        'License :: OSI Approved :: MIT License',

        # Specify the Python versions you support here. In particular, ensure
        # that you indicate whether you support Python 2, Python 3 or both.
        'Programming Language :: Python :: 2',
        'Programming Language :: Python :: 2.6',
        'Programming Language :: Python :: 2.7',
        'Programming Language :: Python :: 3',
        'Programming Language :: Python :: 3.3',
        'Programming Language :: Python :: 3.4',
        'Programming Language :: Python :: 3.5',
    ],
Palavras chave e pacotes
[editar | editar código-fonte]

Para facilidade de indexação da Pypi, eles utilizam um mecanismo de palavras chave. Essas podem ser passadas em uma variável chamada keywords. Além disso, pode-se setar a variável packages, utilizando o find_packages citado no início. O código ilustra o funcionamento:

    keywords='sample setuptools development',
    packages=find_packages(),
Dependências
[editar | editar código-fonte]

Além do find_packages, é possível especificar quais outros pacotes são necessários para instalar. A variável install_requires é responsável por isso:

install_requires=[
     'pyramid_chameleon',
     'SQLAlchemy',
],
Pontos de Entrada
[editar | editar código-fonte]

Os pontos de entrada são as interfaces que você irá configurar para que o sistema operacional do usuários se comunique com seu software empacotado através de comandos. Para que funcione, deve-se passar o nome desejado do comando seguido do arquivo e o módulo desejado. A sintaxe esperada é a seguinte:

nome_do_comando = nome_do_arquivo:nome_do_metodo

Neste software, nós utilizamos dois pontos de entrada. O primeiro com link para iniciar o servidor e o segundo para atualizar o sistema. Os pontos de entrada do pet podem ser visualizados abaixo.

    entry_points={
        'console_scripts': [
            'pet_serve=pet.serve:pet_serve',
            'pet_update=pet.pet_update:pet_update',
        ],
    },

Dessa maneira, o setup.py do pet como inteiro ficou da seguinte maneira:

# Always prefer setuptools over distutils
from setuptools import setup, find_packages
# To use a consistent encoding
from codecs import open
from os import path

here = path.abspath(path.dirname(__file__))

# Get the long description from the README file
with open(path.join(here, 'README.rst'), encoding='utf-8') as f:
    long_description = f.read()

setup(
    name='pet-debian',

    # Versions should comply with PEP440.  For a discussion on single-sourcing
    # the version across setup.py and the project code, see
    # https://packaging.python.org/en/latest/single_source_version.html
    version='1.2.73',

    description='PET is a collection of scripts that gather informatio about your packages',
    long_description=long_description,

    # The project's main homepage.
    url='https://github.com/PET-UnB/pet',

    # Author details
    author='Tiago Assuncao',
    author_email='tiago@sof2u.com',

    # Choose your license
    license='GPL3',

    # See https://pypi.python.org/pypi?%3Aaction=list_classifiers
    classifiers=[
        # How mature is this project? Common values are
        #   3 - Alpha
        #   4 - Beta
        #   5 - Production/Stable
        'Development Status :: 5 - Production/Stable',

        # Indicate who your project is intended for
        'Intended Audience :: Developers',
        'Topic :: Software Development :: Build Tools',
        'Topic :: Software Development :: Bug Tracking',
        'Topic :: Software Development :: Libraries :: Perl Modules',
        'Topic :: Software Development :: Version Control',

        # Pick your license as you wish (should match "license" above)
        'License :: OSI Approved :: GNU General Public License v3 (GPLv3)',

        # Specify the Python versions you support here. In particular, ensure
        # that you indicate whether you support Python 2, Python 3 or both.
        'Programming Language :: Python :: 2',
        'Programming Language :: Python :: 2.6',
        'Programming Language :: Python :: 2.7',
    ],

    # What does your project relate to?
    keywords='debian packaging development',

    # You can just specify the packages manually here if your project is
    # simple. Or you can use find_packages().
    packages=find_packages(),

    # Alternatively, if you want to distribute just a my_module.py, uncomment
    # this:
    #   py_modules=["my_module"],

    # List run-time dependencies here.  These will be installed by pip when
    # your project is installed. For an analysis of "install_requires" vs pip's
    # requirements files see:
    # https://packaging.python.org/en/latest/requirements.html
    install_requires=[
        'pyramid_chameleon',
        'SQLAlchemy'
    ],

    # List additional groups of dependencies here (e.g. development
    # dependencies). You can install these using the following syntax,
    # for example:
    # $ pip install -e .[dev,test]
    # extras_require={
    #     'dev': ['check-manifest'],
    #     'test': ['coverage'],
    # },


    # To provide executable scripts, use entry points in preference to the
    # "scripts" keyword. Entry points provide cross-platform support and allow
    # pip to create the appropriate form of executable for the target platform.
    entry_points={
        'console_scripts': [
            'pet_serve=pet.serve:pet_serve',
            'pet_update=pet.pet_update:pet_update',
        ],
    },
)

Configurando o Manifest.in

[editar | editar código-fonte]

Dentro do empacotamento python, só são transmitidos para a produção os arquivos com extensão .py. Dessa maneira, qualquer aplicação que utilize outros arquivos não será carregado automaticamente. Uma aplicação web, por exemplo, se utiliza de arquivos css, html, etc. A maneira para especificar os arquivos que podem entrar na pasta do empacotamento é utilizando o arquivo manifests.in. Nele pode-se especificar todos os arquivos que devem entrar. No nosso exemplo, tínhamos a necessidade de enviar todos os arquivos com extensão .css, .js e .pt. Então utilizamos a seguinte regra:

# Include the license file
# include README.rst
global-include *.css *.js *.pt

O formato padrão para o readme na pypi é o rst. Você deve converter seu readme para essa extensão, caso não esteja. Ainda sim, pode-se manter os outros formatos.

Para criar um pacote e fazer upload da sua versão, sempre eram necessários vários comandos repetidos, que serão explicados posteriormente. Para facilitar a tarefa de rodar todos os mesmos comandos todas as vezes em que era necessário fazer uma nova build, um makefile foi gerado, necessitando então, apenas rodar o comando make e o upload é realizado. O makefile utilizado pode ser visto abaixo:

all:
	-mv -f dist/* log
	python setup.py sdist bdist_wheel
	twine upload dist/*
	mkdir -p log
	mv dist/* log

Registro na Pypi

[editar | editar código-fonte]

Para fazer o upload, é necessário possuir uma conta na Pypi. O processo é bastante simples.

  1. Primeiramente, deve-se criar uma conta no site do pyhotn https://pypi.python.org/pypi?%3Aaction=register_form
  2. Setar seu usuário no seu ambiente de desenvolvimento

Este último passo é realizado com o auxilio de um arquivo de configuração que deve ficar localizado na raiz do usuário do sistema( /home/user ) e deve-se chamar: ~/.pypirc

Um exemplo desse arquivo segue abaixo:

[distutils]
index-servers=pypi

[pypi]
repository = https://upload.pypi.io/legacy/
username = <username>
password = <password>

Caso não queira disponibilizar a senha, pode-se utilizar o upload passando a flag -p PASSWORD.

Processo de geração das builds

[editar | editar código-fonte]

Toda vez que uma nova build é gerada, o setuptools a compila e a transforma em arquivos executáveis, prontos para passarem pelo upload. Para gerar essas builds, o seguinte comando deve ser utilizado:

$ python setup.py sdist bdist_wheel

As builds serão geradas e armazenadas na pasta dist/ Para fazer o upload, deve-se rodar o comando:

$ twine upload dist/*

Assim, já é possível procurar pelo nome do pacote na pypi que ele estará disponível para download. Neste caso, ficou no link: https://pypi.python.org/pypi/pet-debian/