Использование Gitlab CI для Puppet-кода

Начиная с 8-й версии сервер Gitlab включает в себя систему continuous integration. Это позволяет относительно просто и штатными средствами настроить проверку кода, сборку или даже установку в промышленную среду. В этой заметке я хочу описать пример использования Gitlab CI и GitLab Runner для Puppet-кода. GitLab Runner — это агент, который собственно и занимается выполнением инструкций описанных в специальном файле .gitlab-ci.yml. Тестирование кода будет выполняться в docker-контейнере.

Вместо предисловия

Чтобы тестирование кода работало он должен содержать описание правил проверки. Например, если модуль был создан с использованием:

$ puppet module generate hello-world

то все необходимое уже есть. Если же это не так, необходимо создать несколько файлов в корневом каталоге
Rakefile

require 'puppetlabs_spec_helper/rake_tasks'
require 'puppet-lint/tasks/puppet-lint'
PuppetLint.configuration.send('disable_80chars')
PuppetLint.configuration.ignore_paths = ["spec/**/*.pp", "pkg/**/*.pp"]

desc "Validate manifests, templates, and ruby files"
task :validate do
  Dir['manifests/**/*.pp'].each do |manifest|
    sh "puppet parser validate --noop #{manifest}"
  end
  Dir['spec/**/*.rb','lib/**/*.rb'].each do |ruby_file|
    sh "ruby -c #{ruby_file}" unless ruby_file =~ /spec\/fixtures/
  end
  Dir['templates/**/*.erb'].each do |template|
    sh "erb -P -x -T '-' #{template} | ruby -c"
  end
end

spec/spec_helper.rb

require 'puppetlabs_spec_helper/module_spec_helper'

Более подробно о том что это, зачем и как еще можно этим пользоваться доступно на сайте puppet.

Подготовка контейнера с GitLab Runner

Для тестирования будем использовать контейнер, поэтому первым делом необходимо его собрать. Внутри образа с помощью Ruby Version Manager (RVM) можно использовать несколько версий ruby одновременно. Это будет полезно в некоторых случаях, например если используется 3-я версия puppet на разных версиях Linux и кастомизированные факты написанные на ruby.
Dockerfile

FROM gitlab/gitlab-runner:latest

RUN apt-get update -y && \
    apt-get upgrade -y && \
    apt-get install -y build-essential make curl git && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3

RUN rm /bin/sh && ln -s /bin/bash /bin/sh

RUN \curl -L https://get.rvm.io | bash -s stable

RUN /bin/bash -c "source /etc/profile.d/rvm.sh; \
    rvm install ruby-2.1.8 && \
    rvm use --default ruby-2.1.8"

RUN /bin/bash -c "source /usr/local/rvm/scripts/rvm; \
    gem install metadata-json-lint puppet puppet-lint puppetlabs_spec_helper"

VOLUME ["/etc/gitlab-runner", "/home/gitlab-runner"]
ENTRYPOINT ["/usr/bin/dumb-init", "/entrypoint"]
CMD ["run", "--user=gitlab-runner", "--working-directory=/home/gitlab-runner"]

docker-compose.yml

version: '2'
services:
  gitlab_runner:
    restart: always
    build: .
    container_name: gitlab_runner
    volumes:
     - /export/containers/gitlab-runner-conf:/etc/gitlab-runner
     - /export/containers/gitlab-runner-data:/home/gitlab-runner
    network_mode: "bridge"

Сборка и запуск контейнера:

$ docker-compose build
$ docker-compose up -d
$ docker ps
CONTAINER ID        IMAGE                        COMMAND                  CREATED             STATUS              PORTS                                             NAMES
db3a5edadfec        gitlabrunner_gitlab_runner   "/usr/bin/dumb-init /"   2 seconds ago       Up 2 seconds                                                          gitlab_runner

Настройка Gitlab CI для тестирования и установки модуля puppet

Для настройки gitlab-runner необходимо зайти в веб-интерфейс gitlab
gitlab runners

Полученные данные применяются для настройки gitLab runner в созданном docker-контейнере:

$ docker exec -i -t gitlab_runner gitlab-runner register
Running in system-mode.                            
                                                   
Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/ci):
http://gitlab.rascal.local:8080/ci       
Please enter the gitlab-ci token for this runner:
6FwQc7tKoMsVr7UQyYos
Please enter the gitlab-ci description for this runner:
[db3a5edadfec]: code-validator
Please enter the gitlab-ci tags for this runner (comma separated):
test
Registering runner... succeeded                     runner=6FwQc7tK
Please enter the executor: ssh, virtualbox, docker+machine, docker-ssh+machine, docker, docker-ssh, parallels, shell:
shell
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded! 

Теперь можно активировать Gitlab CI для проекта:
gitlab ci set up

Содержимое файла конфигурации Gitlab CI:

stages:
  - test
  - deploy
  - import

test_job:
  stage: test
  script:
    - rake validate lint
  tags:
    - test

deploy_job:
  stage: deploy
  script:
    - cd /etc/puppetlabs/code/
    - sudo /usr/local/bin/r10k puppetfile install
  tags:
    - puppet
  only:
    - master

import_job:
  stage: import
  script:
    - sudo hammer proxy import-classes --id 1
  tags:
    - foreman
  only:
    - master

Приведенная конфигурация описывает три этапа:

  • Проверку кода (на созданном в начале заметки docker-контейнере).
  • Развертывание кода из ветки master на сервере Puppet
  • Импорт классов puppet на сервере Foreman

В итоге получается вот так:
gitlab ci generalgitlab ci testgitlab ci puppetgitlab ci foreman

На мой взгляд GitLab Runner может использоваться в 90% случаев. Для остального есть Jenkins и TeamCity.