Jenkins — Active Choice: AWS ECR Images tag (AWS Cli)

 

Для параметризованной сборки с выбором тега образа, понадобится плагин Active Choices

Переходим в настройки Jenkins

 

Раздел "Управление плагинами"

 

Переходим к вкладке "Доступные" и в поиске указываем "Active Choice"

Устанавливаем его.

Создаем "New Item" — "Pipeline", указываем, что это будет параметризованной сборка, и добавляем параметр "Active Choices Reactive Parameter"

 

Указываем, что это "Groovy Script" и вставляем туда следующее:

def command = ['/bin/sh', '-c', '/var/lib/jenkins/.local/bin/aws ecr describe-images --region eu-west-1 --repository-name artem-services --query "sort_by(imageDetails,& imagePushedAt)[ * ].imageTags[ * ]" --output text']
  def proc = command.execute()
  return proc.text.readLines()

 

Где, "/var/lib/jenkins/.local/bin/aws" — полный путь к AWS Cli;

"eu-west-1" — регион, в котором находится ECR репозиторий;

"artem-services"  — имя вашего ECR репозитория;

 

 

Тоже самое, но уже через Pipeline

Pipeline:

properties([
  parameters([
    [$class: 'CascadeChoiceParameter', 
      choiceType: 'PT_SINGLE_SELECT', 
      description: 'Select Image',
      filterLength: 1,
      filterable: false,
      name: 'ImageTag', 
      script: [
        $class: 'GroovyScript', 
        script: [
          classpath: [], 
          sandbox: false, 
          script: 
            '''
            def command = ['/bin/sh', '-c', '/var/lib/jenkins/.local/bin/aws ecr describe-images --region eu-west-1 --repository-name artem-services --query "sort_by(imageDetails,& imagePushedAt)[ * ].imageTags[ * ]" --output text']
              def proc = command.execute()
              return proc.text.readLines()
            '''
        ]
      ]
    ]
  ])
])

AWS Cli — ECR вывести только теги образов в репозитории

Пример только с использованием AWS Cli, без сторонних утилит

aws ecr describe-images \
--region eu-west-1 \
--repository-name artem-services \
--query "sort_by(imageDetails,& imagePushedAt)[ * ].imageTags[ * ]" \
--output text

 

Пример с использованием утилиты jq

aws ecr describe-images \
--region eu-west-1 \
--repository-name artem-services \
| jq '.imageIds | map (.imageTag)|sort|.[]'

Jenkins — Kubeconfig

 

Для хранения и переключения между конфигурациями Kubernetes'а, можно воспользоваться плагином Kubernetes CLI, для работы с ним в системе должен быть установлен "kubectl"

Устанавливаем плагин

Переходим в настройки Jenkins

 

Раздел "Управление плагинами"

 

Переходим к вкладке "Доступные" и в поиске указываем "Kubernetes CLI"

Устанавливаем его.

 

Добавляем Kubernetes config

 

Переходим в "Credentials" и создаем "Secret file"

 

Загружаем конфиг и указываем "ID". Сохраняем.

 

Pipeline

Пример использования плагина в Pipeline:

pipeline {
  agent any
  stages {   
    stage("K8s") {
      steps {
        withKubeConfig([credentialsId: 'kubeconfig-artem-services-staging']) {
          script {
            sh "kubectl get pod"
          }
        }
      }
    }
  }
}

FIX ERROR — CentOS 7 kubectl: Invalid choice: 'eks', maybe you meant

При попытке выполнить любую команду "kubectl" на EKS кластере возникает следующая ошибка:

Invalid choice: 'eks', maybe you meant:

 

Возможная причина этого, это старая версия "kubectl", доступная в репозитории.

 

Решение:

Установить последнюю версию "kubectl" используя PIP3

sudo yum install -y python3 python3-pip
sudo pip3 install --upgrade --user awscli

 

Для использования "kubectl" установленным с помощью PIP, нужно чтобы директория бинарных файлов PIP была в переменной PATH, для этого выполняем:

export PATH=~/.local/bin:$PATH
source ~/.bash_profile

 

Чтобы не выполнять это каждый раз, нужно добавить строку:

export PATH=~/.local/bin:$PATH

 

В ваш профиль, зависит от оболочки:

  • Bash – .bash_profile, .profile, or .bash_login
  • Zsh – .zshrc
  • Tcsh – .tcshrc, .cshrc or .login

Jenkins — Добавить путь в PATH

 

Чтобы добавить путь в окружение Jenkins'а глобально, не делая это каждый раз в Pipeline, перейдем в настройки Jenkins

 

Далее вкладка "Конфигурация системы"

 

Находим блок "Global properties", ставим галочку "Environment variables". И добавляем переменную, с именем "PATH+EXTRA" и значением — пути, которые необходимо добавить, разделенные ":" между собой, если их несколько.

Helm — Создание Secret’а с переменной

 

Для того, чтобы сохранить значение переменной как Secret, переменную необходимо закодировать в base64, для этого воспользуемся "_helpers.tpl"

К примеру, нам нужно сохранить значение переменной "applicationSecret"

values.yaml:

# Default values for artem-services.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.

replicaCount: 1
namespace: default

image:
  repository: XXXXXXXXXXXX.dkr.ecr.eu-east-1.amazonaws.com/artem-services
  tag: 1.0.1
  pullPolicy: IfNotPresent

nameOverride: ""
fullnameOverride: "artem-services"

applicationSecret: |
  var1=value1
  var2=value2
  var3=value3
  var4=value4

 

Добавляем в "_helpers.tpl" следующее:

_helpers.tpl:

{{- define "applicationSecret" }}
{{- printf .Values.applicationSecret | b64enc }}
{{- end }}

 

Теперь в директории "templates" создадим файл "secret.yaml"

secret.yaml:

apiVersion: v1
kind: Secret
type: Opaque
metadata:
  name: "{{ .Chart.Name }}-application"
data:
  application.conf: {{ template "applicationSecret" . }}

Ansible — Запуск Playbook’а с определенной версией Python

К примеру есть инстанс, на котором установлен Python 2-ой и 3-ей версий, но по умолчанию используется 2-ая, и чтобы не менять версию по умолчанию и запустить Playbook используя Python3, можно воспользоваться следующей командой:

python3 $(which ansible-playbook) -i localhost my-playbook.yaml

 

Так же можно указать интерпретатор в инвентори файле:

[localhost]
localhost ansible_connection=local ansible_python_interpreter=python3

 

Убедитесь, что для нужной версии Python установлен Ansible модуль

sudo pip3 install --user ansible

Ansible — Template: to_nice_json

Для того, чтобы создать из шаблона файл и сразу его сохранить как "Pretty JSON" можно воспользоваться модулем "copy" с ключем "content".

К примеру сохраним шаблон "config.j2" как файл "/app/config.json"

Playbook:

- name: Template a file to configuration files
  copy:
    content: "{{ lookup('template', 'templates/config.j2') | to_nice_json }}"
    dest: "/app/config.json"
    owner: artem
    group: artem
    mode: '0644'

Jenkins — Active Choice: CheckBox — Значения по умолчанию

 

При работе с параметром Active Choice CheckBox, можно выбрать значения по умолчанию добавив параметр ":selected"

Pipeline:

properties([
  parameters([
    [$class: 'CascadeChoiceParameter', 
      choiceType: 'PT_CHECKBOX', 
      description: 'Select environment',
      filterLength: 1,
      filterable: false,
      name: 'Environment', 
      script: [
        $class: 'GroovyScript', 
        script: [
          classpath: [], 
          sandbox: false, 
          script: 
            'return[\'Development:selected\',\'Production:selected\']'
        ]
      ]
    ]
  ])
])

 

При сборке с параметрами сразу два окружения, "Development" и "Production" будут выбраны по умолчанию

Jenkins — Active Choice: CheckBox — Работа с массивом

При работе с параметром Active Choice CheckBox, значения параметра записываются в переменную, через запятую. Для работы с ними как отдельными элементами, нужно их сохранить в массив. К примеру есть следующий  Active Choice, который выдает список окружений в виде CheckBox

Pipeline:

properties([
  parameters([
    [$class: 'CascadeChoiceParameter', 
      choiceType: 'PT_CHECKBOX', 
      description: 'Select Environment',
      filterLength: 1,
      filterable: false,
      name: 'Environment', 
      script: [
        $class: 'GroovyScript', 
        script: [
          classpath: [], 
          sandbox: false, 
          script: 
            'return[\'Development\',\'QA\',\'Staging\',\'Production\']'
        ]
      ]
    ]
  ])
])

 

Выглядит это следующим образом:

 

Выберем два окружения, "Development" и "QA"

 

Значение переменной "Environment" будет следующее: "Development,QA". Сохраним эти значения в массив, для дальнейшей работы с ним.

String[] Env_Array = "${params.Environment}".split(',');

 

Полностью Pipeline будет иметь следующий вид

Pipeline:

properties([
  parameters([
    [$class: 'CascadeChoiceParameter', 
      choiceType: 'PT_CHECKBOX', 
      description: 'Select Environment',
      filterLength: 1,
      filterable: false,
      name: 'Environment', 
      script: [
        $class: 'GroovyScript', 
        script: [
          classpath: [], 
          sandbox: false, 
          script: 
            'return[\'Development\',\'QA\',\'Staging\',\'Production\']'
        ]
      ]
    ]
  ])
])

pipeline {
  agent any
  stages {
    stage('Check env') {
      steps {
        script {
          if ( env.Environment.isEmpty() ) {
            echo "Environment not specified."
            autoCancelled = true
            error('Aborting the build.')
          }
          else {
            echo "Environment total: ${env.Environment}"
            String[] Env_Array = "${params.Environment}".split(',');
            for (x in Env_Array) {
              echo "ENV: ${x}"
            }
          }
        }
      }
    }
  }
}

 

Результат выполнения Jenkins задачи: