AgileOps: Jira-центричный подход

от автора

Intro

Благородя своей гибкости, Jira в большинстве крупных компаний, используется в качестве единой системы принятия решений и отслеживания изменений.

Вопреки расхожему мнению, далеко не все компании занимаются разработкой софта.

Во многих крупных организациях Dev и Ops – это всего лишь одно структурное подразделение, так называемый Cost Center (то есть напрямую компании доходы не приносит). При этом одной из главных задач в Agile является обеспечение прозрачности процессов для всех заинтересованных сторон (stakeholders).

Для многих компаний парадигма JiraOps или скорее IssueTrackingOps подходит гораздо лучше, чем GitOps.

Для того, чтобы убрать препоны между бизнесом, DEV, OPS, SEC, QA и обеспечить прозрачность процессов можно разрабатывать свою автоматизацию для Jira, либо использовать инструменты от сторонних разработчиков.


Jira Server

Для работы нам понадобится Jira Data Center – тестовый стенд с триальной версией Jira.
Для этих целей будем использовать docker-compose.yml:

version: '3.7'  services:   node:     image: atlassian/jira-software:latest     ports:      - 9099:8080     volumes:       - ./jira-home-node1:/var/atlassian/application-data/jira:Z     ulimits:       nproc: 65535       nofile:         soft: 65535         hard: 65535    database:     image: postgres:10.5-alpine     volumes:       - ./postgresql-data:/var/lib/postgresql/data:Z       - ./postgre-db-init.sql:/docker-entrypoint-initdb.d/postgre-db-init.sql:Z     ports:      - 5432:5432     environment:       POSTGRES_PASSWORD: 1234 

Запускаем Jira Server:

docker-compose up -d 

Jira UI будет доступен по адресу http://<IP_ADDRESS>:9099

Нужно будет прокликать установочный визард, сгенерировать триальный ключ и создать пользователя.

jira_setup

jira_setup

CLI

У Jira есть отличный API и клиентские библиотеки для Python и Jira.
Для автоматизации CI/CD и мониторинга мы будем использовать go-jira (https://github.com/go-jira/jira), а для BI и ad-hoc аналитики Python и SQL.

Go-jira это и библиотека для работы с API Jira и инструмент командной строки, который идеально подходит для встраивания в CI/CD процессы.

Пример использования Go-клиента – получаем jira issues для проекта OpenJDK:
main.go:

package main  import ( "fmt" "github.com/andygrunwald/go-jira" )  func main() { jiraClient, _ := jira.NewClient(nil, "https://bugs.openjdk.org")  jql := "project = JDK and status = Open ORDER BY updated ASC"  issues, resp, err := jiraClient.Issue.Search(jql, nil) if err != nil { fmt.Println(err) panic(resp.StatusCode) }  for _, issue := range issues { fmt.Printf("%s: %+v\n", issue.Key, issue.Fields.Summary) } } 

Получаем issues для проекта OpenJDK:

go run main.go | head -10  JDK-4158929: 8 bit Dithering problem in SwingSet HTML Text tab. JDK-4184200: Color profiles for screen device should be used when available. JDK-4199882: splotchy highlight at 24 bit True Color JDK-4345973: Add set/get methods for boolean datatype in ParameterBlock JDK-4148927: Input method highlighting needs to handle highlight segments JDK-4102920: 12x: Multi-font caching scheme inadequate for non-Latin text JDK-4387892: swing components show all black @ 16-bit depth (VNC on Linux) JDK-4398379: java.awt.image.DataBufferShort constructor should verify size of array JDK-4398381: java.awt.image.DataBufferShort should check for negative size JDK-4396157: Merlin: Consonant RA Rule R2 doesn't hold true with Lucida font 

Благородя CLI с Jira можно работать так же как и Git:

jira mine  +--------+------------+-------+----------+--------+----------+--------------+--------------+ | Issue  |  Summary   | Type  | Priority | Status |   Age    |   Reporter   |   Assignee   | +--------+------------+-------+----------+--------+----------+--------------+--------------+ | JIRA-1 | Jira-1     | Story | Medium   | To Do  | an hour  | Anton Krylov | Anton Krylov | | JIRA-2 | Demo Issue | Bug   | Medium   | To Do  | a minute | Anton Krylov | Anton Krylov | +--------+------------+-------+----------+--------+----------+--------------+--------------+ 

Только сначала нужно будет создать конфиг для Jira:

mkdir ~/.jira.d  cat <<EOM >~/.jira.d/config.yml endpoint: https://jira.mycompany.com EOM 
config.yml
config:   stop: true password-source: stdin endpoint: http://<IP>:9099 user: <user> login: <login>  project: JIRA  queries:   todo: >-     resolution = unresolved {{if .project}}AND project = '{{.project}}'{{end}} AND status = 'To Do'  custom-commands:   - name: env     help: print the JIRA environment variables available to custom commands     script: |-       env | sort | grep JIRA   - name: print-project     help: print the name of the configured project     script: "echo $JIRA_PROJECT"   - name: jira-path     help: print the path the jira command that is running this alias     script: |-       echo {{jira}}   - name: mine     help: display issues assigned to me     script: |-       {{jira}} list --template table --query "resolution = unresolved AND project=$JIRA_PROJECT AND assignee=currentuser() ORDER BY status, issue"   - name: mine-created     help: display issues created by me     script: |-       {{jira}} list --template table --query "resolution = unresolved AND project=$JIRA_PROJECT AND creator=currentuser() ORDER BY created"   - name: watching     help: display issues watched by me     script: |-       {{jira}} list --template table --query "resolution = unresolved AND project=$JIRA_PROJECT AND watcher=currentuser() ORDER BY created"     script: |-       if [ -n "$JIRA_PROJECT" ]; then           # if `project: ...` configured just list the issues for current project           {{jira}} list --template table --query "resolution = unresolved and assignee=currentuser() and project = $JIRA_PROJECT ORDER BY priority asc, created"       else           # otherwise list issues for all project           {{jira}} list --template table --query "resolution = unresolved and assignee=currentuser() ORDER BY priority asc, created"       fi   - name: sprint     help: display issues for active sprint     script: |-       if [ -n "$JIRA_PROJECT" ]; then           # if `project: ...` configured just list the issues for current project           {{jira}} list --template table --query "sprint in openSprints() and type != epic and resolution = unresolved and project=$JIRA_PROJECT ORDER BY rank asc, created"       else           # otherwise list issues for all project           {{jira}} list --template table --query "sprint in openSprints() and type != epic and resolution = unresolved ORDER BY rank asc, created"       fi 

Если в кофиге password-source: stdin то пароль для jira нужно передавать следующим образом:

export JIRA_PASSWORD='<PASSWORD>\n' echo $JIRA_PASSWORD| jira ls 

Если будет password-source: pass то jira «попросит» его в интерактивном режиме.

jira mine это custom-command который выводит все jira issues для текущего пользователя.
Таким образом можно создавать различные команды использующие api и jql для работы с jira.

  - name: mine     help: display issues assigned to me     script: |-       {{jira}} list --template table --query "resolution = unresolved AND project=$JIRA_PROJECT AND assignee=currentuser() ORDER BY status, issue" 

Можно быстро прикреплять файлы к issues из Bash:

jira attach create JIRA-1 exec.zip  OK 10000 http://109.207.172.67:9099/secure/attachment/10000/exec.zip 

А если их несколько то можно написать Bash-скрипт:

for i in exec1.zip exec2.zip exec3.zip exec4.zip; do jira attach create JIRA-1 $i; done  OK 10003 http://109.207.172.67:9099/secure/attachment/10003/exec1.zip OK 10004 http://109.207.172.67:9099/secure/attachment/10004/exec2.zip OK 10005 http://109.207.172.67:9099/secure/attachment/10005/exec3.zip OK 10006 http://109.207.172.67:9099/secure/attachment/10006/exec4.zip 

Вложения можно быстро скачивать из командной строки:

jira attach list JIRA-1  +-------+-----------+---------+--------------+-----------+ |  id   | filename  |  bytes  |     user     |  created  | +-------+-----------+---------+--------------+-----------+ | 10000 | exec.zip  | 4209783 | Anton Krylov | 5 minutes | | 10001 | exec.zip  | 4209783 | Anton Krylov | 3 minutes | | 10002 | exec.zip  | 4209783 | Anton Krylov | 3 minutes | | 10003 | exec1.zip | 4209783 | Anton Krylov | a minute  | | 10004 | exec2.zip | 4209783 | Anton Krylov | a minute  | | 10005 | exec3.zip | 4209783 | Anton Krylov | a minute  | | 10006 | exec4.zip | 4209783 | Anton Krylov | a minute  | +--- 

Представьте себе, что вам нужно выполнять какие-то однокипные действия – например генерировать сертификаты для нового кластера Kubernetes.

Вы написали скрипт, который делает это автоматически:

make -f mkcerts.mk root-ca  generating root-key.pem generating root-cert.csr generating root-cert.pem Certificate request self-signature ok subject=O=Istio, CN=Root CA 

А теперь эту задачу должен проконтролировать ИБ:

jira attach create JIRA-1 kube_certs.tar  OK 10007 http://109.207.172.67:9099/secure/attachment/10007/kube_certs.tar 
kube-certs

kube-certs

Представим себе, что нужно создать SSH-ключ для нового сотрудника. И конечно эта задача должны пройти несколько стадий проверки, а в случаи если сотрудник покидает компанию, вся информацию об этой задачи и ключах будет хранится в Jira:

ssh-key

ssh-key

Эту задачу можно превратить в YAML-шаблон, параметризовать и хранить в Git:

ssh-key-template

ssh-key-template

Задача может быть и посложней – например генерировать сертификаты для кластера Kafka:

bash genkeys.sh 

Эти файлы нужно заархивировать:

tree . ├── broker-ca-signed.crt ├── broker.csr ├── broker_keystore_creds ├── broker_sslkey_creds ├── broker_truststore_creds ├── consumer-ca-signed.crt ├── consumer.csr ├── consumer_keystore_creds ├── consumer_sslkey_creds ├── consumer_truststore_creds ├── genkeys.sh ├── jcerts-kafka-ca-key.pem ├── jcerts-kafka-ca.pem ├── jcerts-kafka-ca.srl ├── kafka.broker.keystore.cer.pem ├── kafka.broker.keystore.jks ├── kafka.broker.keystore.key.pem ├── kafka.broker.keystore.p12 ├── kafka.broker.truststore.jks ├── kafka.consumer.keystore.cer.pem ├── kafka.consumer.keystore.jks ├── kafka.consumer.keystore.key.pem ├── kafka.consumer.keystore.p12 ├── kafka.consumer.truststore.jks ├── kafka.producer.keystore.cer.pem ├── kafka.producer.keystore.jks ├── kafka.producer.keystore.key.pem ├── kafka.producer.keystore.p12 ├── kafka.producer.truststore.jks ├── producer-ca-signed.crt ├── producer.csr ├── producer_keystore_creds ├── producer_sslkey_creds └── producer_truststore_creds 

И прикрепить к задаче:

find . -print0 | tar -cvf kafka_certs.tar --null -T -  jira attach create JIRA-2 kafka_certs.tar  OK 10100 http://109.207.172.67:9099/secure/attachment/10100/kafka_certs.tar 

Автоматизация может быть и сложнее, поэтому неплохо было-бы это все «завернуть» в Docker, положить в Git и добавить в CI:

Dockerfile:

ARG JIRA_PROJECT ENV JIRA_PASSWORD=JIRA_PROJECT  RUN apt-get update && apt-get -y install golang RUN go install github.com/go-jira/jira/cmd/jira@latest RUN ln -s ~/go/bin/jira /usr/local/bin/jira COPY config.yml ~/.jira.d/config.yml  COPY gencerts.sh gencerts.sh RUN bash gencerts.sh RUN jira attach create INFRA kafka_certs.tar 

положить в Git и сделать частью CI:

docker build . --build-arg='JIRA_PROJECT=INFRA' 

GUI

Существует несколько GUI клиентов для Jira.

Один из них давно перешел в статус «Deprecated», но без проблем работает с последними версиями Jira:

GUI1

GUI1
GUI2

GUI2

Для чего это нужно?

  • Бывает множество нетехнических пользователей, которым сложно привыкнуть к Web-UI Jira.

  • Иногда в закрытом контуре, в принципе нет доступа к браузеру, на рабочем месте.


End

PS. Если наберется 50 лайков, то я напишу вторую, часть, где мы разберем как прикрутить продвинутый BI для Jira, без лишних хлопот и скриптов на Groovy.


ссылка на оригинал статьи https://habr.com/ru/articles/786444/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *