Desenvolvimento de módulos para bonecos com kit de desenvolvimento de bonecos

Há cerca de um mês, tive uma escolha: escrever o módulo para o fantoche "na mesa" (ou seja, para a infraestrutura interna) ou torná-lo universal, abrir o código-fonte e publicá-lo no Puppet Forge . Obviamente, seria mais rápido e fácil desenhar rapidamente 2-3 aulas para você e se acalmar, mas a experiência adquirida no processo de publicação do módulo é valiosa e eu quero compartilhá-lo. No RuNet, não há informações sobre o uso do kit de desenvolvimento de marionetes (doravante PDK ); portanto, você pode considerar esse tipo de tutorial.


Sobre o que é o artigo


No processo de desenvolvimento de um módulo (ou melhor, dois), descobri o PDK, que facilita muito o desenvolvimento e a manutenção de módulos. Ou seja:


  • Formate automaticamente metadata.json ao atualizar pela última vez
  • Geração de configuração para vários sistemas de IC que podem fazer o seguinte:
    • Verificando o código ruby ​​com o rubocop linter
    • Execução de testes de unidade
    • Sob certas condições - preenchimento automático do código de trabalho da forja de marionetes
  • Gerando documentação baseada em tags nos comentários usando o yard
  • Placa [PDK] para o módulo na forja de marionetes. Um pouco, mas legal!

Todos os interessados Eu peço um gato!


Como exemplos


Se você quiser ver e sentir o que se entende durante o processo de leitura, poderá abrir um dos dois (ou ambos) módulos mencionados: clickhouse e xmlsimple . Ambos foram desenvolvidos usando o PDK e outras ferramentas descritas no artigo.


Conteúdo



O que é PDK


A partir da documentação oficial:


Crie um módulo completo com classes, tipos definidos e tarefas, e teste e valide seu trabalho à medida que avança. O PDK fornece uma estrutura completa de módulos, modelos para classes, tipos e tarefas definidos e uma infraestrutura de teste. Você pode validar e testar seu módulo em relação a vários sistemas operacionais e várias versões do Puppet.

Na minha tradução gratuita:


Permite criar um módulo completo com classes, tipos, tarefas e testes para verificar a operação do módulo. O PDK fornece uma estrutura completa e modelos para todos os itens acima. Usando esta ferramenta, você pode verificar o funcionamento do módulo com várias versões do fantoche, bem como em vários sistemas operacionais.

Parece bom? Bem, é assim que realmente é. Até o momento em que comecei a trabalhar no módulo, que foi decidido escrever imediatamente para código aberto, não suspeitava dessa ferramenta e agora pretendo transferir toda a infraestrutura interna para usar o PDK.


Descreverei como colocá-lo e quais ferramentas e comandos ele contém.


Instalação


A página de instalação oficial . Com esse link, você quase garante a maneira correta de instalar o PDK em seu host. Se, por algum motivo, você não tiver sorte e seu sistema operacional não estiver lá, sempre haverá uma rotatória no formulário:


 gem install pdk 

De fato, o PDK é apenas uma jóia, e é assim definido.


Conteúdo PDK


Em geral, o PDK nada mais é do que um conjunto de gemas para facilitar o desenvolvimento do módulo. Ele contém as seguintes ferramentas:


UtilitárioDescrição do produto
metadata-json-lintVerifica metadata.json para encontrar guias de estilo de fantoche correspondentes
pdkUma ferramenta para gerar e testar módulos e seu conteúdo (classes, tipos, etc.) na linha de comando
marioneteVerifica o código do fantoche para obter os guias de estilo do Puppet Language
sintaxe do fantocheVerifique a sintaxe do manifesto
puppetlabs_spec_helperFornece classes, métodos e tarefas Rake para testes de especificação de código fantoche
rspec-puppetTesta o comportamento do fantoche ao compilar manifestos no diretório de recursos (?)
fatos-fantoche-rspecPermite executar rspec-puppet com fatos de fantoche especificados pelo usuário

Crie um módulo


PDK instalado, agora você pode brincar. O comando mais simples da pdk help exibirá os comandos disponíveis. Suponha que estamos na pasta onde você tem todos os outros módulos. Então vamos criar um novo:


 $ pdk new module --template-url=https://github.com/puppetlabs/pdk-templates.git *** We need to create the metadata.json file for this module, so we're going to ask you 5 questions. *** [Q 1/5] If you have a name for your module, add it here. --> dummy [Q 2/5] If you have a Puppet Forge username, add it here. --> felixoid [Q 3/5] Who wrote this module? --> Mikhail f. Shiryaev [Q 4/5] What license does this module code fall under? --> MIT [Q 5/5] What operating systems does this module support? --> RedHat based Linux, Debian based Linux, Windows Metadata will be generated based on this information, continue? Yes pdk (INFO): Module 'dummy' generated at path '/tmp/dummy', from template 'https://github.com/puppetlabs/pdk-templates.git'. 

O utilitário faz perguntas para preencher o arquivo metadata.json e, na saída, temos exatamente o que é indicado: o módulo e os arquivos auxiliares compilados a partir de modelos do git.


Uma pequena observação - os temlites mudam com bastante frequência, incluindo alguns bugs críticos que foram corrigidos recentemente. Portanto, é melhor usar não os padrões do PDK instalado, mas a versão mais recente. É verdade que há um outro lado: ao usar o argumento --template-url , o PDK adiciona esse parâmetro ao ~.pdk/cache/answers.json e, a julgar pelos atrasos na execução posterior de qualquer um dos comandos pdk , tenta baixá-los. Portanto, remova esse parâmetro de answers.json ou não o utilize ao criar um módulo e altere-o em metadata.json .


Vamos seguir as etapas adicionais que podem ser executadas usando o PDK.


nova classe


 $ pdk new class dummy::class pdk (INFO): Creating '/tmp/dummy/manifests/class.pp' from template. pdk (INFO): Creating '/tmp/dummy/spec/classes/class_spec.rb' from template. $ cat manifests/class.pp # A description of what this class does # # @summary A short summary of the purpose of this class # # @example # include dummy::class class dummy::class { } $ cat spec/classes/class_spec.rb require 'spec_helper' describe 'dummy::class' do on_supported_os.each do |os, os_facts| context "on #{os}" do let(:facts) { os_facts } it { is_expected.to compile } end end end 

Este comando cria 2 arquivos: o próprio manifesto para a classe e o arquivo spec para testá-lo. Vou me debruçar sobre as tags para documentação mais tarde em mais detalhes.


new defined_type


 $ pdk new defined_type type pdk (INFO): Creating '/tmp/dummy/manifests/type.pp' from template. pdk (INFO): Creating '/tmp/dummy/spec/defines/type_spec.rb' from template. 

Mesmo assim: manifesto para o tipo de recurso e o arquivo de especificação.


novo provedor e tarefa


O PDK também pode criar um novo provedor ou tarefa, mas eu não trabalhei em estreita colaboração com eles, por isso vou dizer honestamente que, se necessário, é melhor estudar esse tópico mais profundamente por conta própria.


Gerando documentação com strings de marionetes


Eu realmente não entendo por que as puppet strings não puppet strings parte do kit de ferramentas do PDK, mas isso é a la vie. Se, durante o desenvolvimento, você colocou corretamente as tags para o quintal, existem 2 maneiras principais de fornecer documentação ao usuário:


  • Gere-o como HTML / Markdown / JSON e coloque-o ao lado do código. Isso é feito com o comando puppet string generate [--format FORMAT] , onde o formato pode ser omitido ou definido como json / markdown .
    • É habitual ter o arquivo REFERENCE.md na raiz do repositório como o padrão de documentação, gerado pelas puppet strings generate --format markdown .
  • Publique no repositório com o código (desde que esteja no github) github-pages. Isso é bastante simples, você precisa de 3 comandos:
     #  Gemfile.lock,    PDK rm -f Gemfile.lock #     Gemfile   bundle bundle install --path vendor/bundle #   gh-pages   rake-task bundle exec rake strings:gh_pages:update 

Parece não haver mágica, mas na saída temos um módulo com instruções. A vantagem é que, mesmo que você não descreva, digamos, cada um dos parâmetros usando a tag @param , a saída ainda será uma classe / tipo / função com uma descrição mínima dos parâmetros com o tipo e o valor padrão. Na minha humilde opinião, mesmo isso é melhor que nada e tornará o módulo mais atraente para o uso.


Obviamente, tudo isso pode ser automatizado e adicionado como um estágio de IC. Isso seria perfeito. Minhas mãos ainda não chegaram, mas estão acumulando poeira na lista de pendências. Se de repente alguém tiver algo a dizer sobre esse assunto - ficarei grato. Como pensamentos: pelo menos, adicione uma verificação para ver se REFERENCE.md muda após executar as seqüências de marionetes. E, se assim for, considere que os testes falharam.


Personalização de modelos


A documentação para modelos está localizada no repositório pdk-templates . Em resumo, tudo é configurado usando o arquivo .sync.yml no diretório raiz do módulo, e as alterações são aplicadas usando o comando pdk update . Cada um dos parâmetros deste arquivo é o nome de outro arquivo no diretório do módulo, que deve ser alterado de uma maneira ou de outra. A maioria dos parâmetros para cada um dos modelos tive que selecionar "por toque", olhando o código fonte, frequentemente - por tentativa e erro. A documentação aqui às vezes fica muito atrás. Infelizmente, não há quase mais nada a dizer, exceto dar um link para um exemplo do seu próprio repositório.


Descreverei rapidamente alguns parâmetros que foram alterados usando o .sync.yml do exemplo acima:


  • Gemfile : duas Gemfile foram adicionadas como dependências em diferentes grupos: pdk no grupo de desenvolvimento; xml-simple no grupo de dependências. Ao iniciar os testes, o grupo system_tests não está instalado, então adiciono a dependência a outro grupo.
  • spec/spec_helper.rb : o método moking foi alterado, o limite mínimo de cobertura de teste foi adicionado, abaixo do qual os testes são considerados falhos.
  • .travis.yml : esse arquivo foi polido por um longo tempo, pois é usado para verificar a base de código e carregar o módulo finalizado no puppet-forge. Alterações:
    • Usuário e senha criptografada para preencher o módulo na marionete-forja. Você pode ler mais sobre como implantar marionetes com Travis aqui .
    • Uma sequência de testes foi criada → implantação com o lançamento deste último apenas com testes bem-sucedidos.
    • Adicionado o estágio de implantação do módulo no fantoche-forja, desde que o IC seja iniciado a partir da tag começando com o caractere "v".
  • Rakefile : adicionadas algumas exceções para o linter.

Executando vários IC


Tudo é bem simples aqui. Imediatamente após a geração do módulo usando o PDK, a validação inicia no appveyor, travis e gitlab-ci. Para executar os testes, tudo está pronto imediatamente, para o ajuste, o mesmo .sync.yml . Não tenho preferências particulares, portanto não recomendarei nada. Basta usar o que for mais conveniente.


Bônus: escrevemos testes de unidade para classes, tipos e funções


Esse ponto vai um pouco além do material básico que planejei descrever, mas me parece muito útil.


Portanto, temos um módulo com manifestos e uma biblioteca que, por sua vez, contém classes, tipos e funções (também não esquecemos as tarefas e os provedores, mas não tenho nenhum conhecimento nesta parte). Como existe qualquer código com o objetivo de alterar, seria bom, obviamente, cobri-lo com testes para garantir duas coisas:


  • As mudanças não quebram o comportamento atual (ou o comportamento muda com os testes)
  • Seus manifestos fazem exatamente o que você espera e usam todos os recursos que você espera.

O Puppetlabs fornece uma extensão para a estrutura rspec chamada puppet-rspec . Links para a documentação para testar classes , tipos e funções . Não tenha preguiça de olhar de perto, existem outras seções.


Para começar a usá-lo, é bastante simples, sem sequer conhecer o ruby. Se classes ou tipos foram criados, como mostrado acima, usando pdk new <thing> , o arquivo *_spec.rb também já existe. Então, suponha que tenhamos uma dummy::class . Para testá-lo, um arquivo spec/classes/class_spec.rb deve ser criado com o seguinte conteúdo:


 require 'spec_helper' describe 'dummy::class' do on_supported_os.each do |os, os_facts| context "on #{os}" do let(:facts) { os_facts } it { is_expected.to compile } end end end 

Você pode verificar executando a pdk test unit no diretório raiz do módulo.


Isso é quase tudo o que precisamos. Agora resta suplementar class_spec.rb is_expected necessário com as condições apropriadas. Por exemplo, para verificar se a classe contém o recurso file {'/file/path': } com determinados parâmetros, você pode fazer isso:


 it do is_expected.to contain_file('/file/path').with( 'ensure' => 'file', 'mode' => '0644' ) end 

Você pode definir parâmetros de classe usando let(:params) { {'param1' => 'value'} } , é possível realizar testes sob várias condições de entrada colocando cada it dentro das seções selecionadas do context 'some description' {} . É possível verificar ambas as dependências entre recursos e entre classes: se for assumido, por exemplo, que a declaração de classe contém inherits , você poderá adicionar a verificação is_expected.to contain_class('parent_class_name') . Precisa testar o comportamento em diferentes sistemas operacionais Também é possível: simplesmente indicamos em um contexto separado os fatos necessários:


 context 'with Debian' do let(:facts) do { os: { architecture: 'amd64', distro: { codename: 'stretch', id: 'Debian', release: { full: '9.6', major: '9', minor: '6', }, }, family: 'Debian', name: 'Debian', release: { full: '9.6', major: '9', minor: '6', }, selinux: { enabled: false, }, }, osfamily: 'Debian', } end it { is_expected.to something } end 

Em geral, tanto quanto consegui notar no processo de escrever testes, a estrutura permite verificar quase tudo o que for necessário. E a presença de testes uma vez me ajudou quando alguns parâmetros foram movidos das classes filho para a classe superior do módulo: eles mostraram que a refatoração não quebrou nada e o comportamento de todo o módulo não mudou.


Em vez de saída


Como já pode ser entendido a partir da entonação geral do artigo, estou muito encorajado pelo quanto o Puppet facilitou o trabalho com os módulos e se manifesta graças ao PDK. As ações de rotina são automatizadas, os modelos são usados ​​sempre que possível, as configurações para o IC popular estão disponíveis imediatamente. Pode parecer uma espécie de sobrecarga, e o uso pode não trazer a fruta esperada, mas definitivamente vale a pena. Se você comparar como desenvolver módulos sem e com PDK, então, para mim, será assim:


Desenvolvimento sem barbas PDKDesenvolvimento PDK

Tente, coloque, facilite a vida para você e seus colegas. Ficarei feliz em responder a possíveis perguntas.


Que a atomatização esteja conosco!

Source: https://habr.com/ru/post/pt435954/


All Articles