【Jenkins】ジョブの無効化をする方法

CI/CD
https://jenkins.io/

はじめに

こんにちはSREエンジニアのMakiです。

この記事ではJenkinsのジョブを無効化するやり方を紹介します。
Jenkinsのジョブを一時的に動かないようにさせたいということってありませんか?定期実行しているジョブを動かないようにさせるなどのニーズは時々あるのではないかと思います。この記事ではそのような場合への対処方法をまとめていきます。

プロジェクトの無効化

では、さっそくジョブの無効化をするやり方を見ていきます。

  • Jenkinsでジョブを実行できなくしたい場合はプロジェクトの無効化をしましょう。

プロジェクトを無効化すると パラメータ付きビルドRebuild といったジョブ実行にかかわる捜査が行えなくなります。

  • 再び ジョブを使えるようにする場合は有効化をしましょう。

どんなときに無効化するの?

ではどんなの時にジョブの無効化を制御する必要があるのか?

  • Jenkinsジョブをほかの環境に移行するときに実行されないように制御しておきたい。
  • 承認されていないジョブが実行されないようにしたい。
  • 失敗したジョブの原因調査が終わるまで実行させないようにしたい。

こういったことが考えられますね。

一定期間更新がなかったジョブを一括で無効化したい。

以下のようなスクリプトを作って一定期間更新がなかったジョブは一括で無効化するといった運用も可能です。

Python にもJenkinsのライブラリがあり、それを使って実装したものが下記の内容です。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import json
import sys
import datetime
from argparse import ArgumentParser
import jenkins

BUILDABLE = 'buildable'
FULLNAME = 'fullname'
JOB_CONFIG_HISTORY = 'jobConfigHistory'
LAST_UPDATE_CONFIG = 'jobLastUpdateConfig'
DATE = 'date'
NONE = 'none'

def login(args):
    server = jenkins.Jenkins(args.jenkins_url, username=args.jenkins_username, password=args.jenkins_password)
    return server

def getDisableTargetJobInfos(server,args):
    _disable_target_job_infos = []
    jobs = server.get_all_jobs()
    for job in jobs :
        if not job[FULLNAME].startswith(args.disable_job_prefix):
            continue
        if server.is_folder(job[FULLNAME]) :
            continue
        job_info = server.get_job_info(job[FULLNAME])
        if not (BUILDABLE in job_info and job_info[BUILDABLE]) :
            continue
        _config_history_info = getJobConfigHistry(server, job[FULLNAME])

        # if job config history is not empty add last update config history info
        if _config_history_info[JOB_CONFIG_HISTORY] :
            job_info[LAST_UPDATE_CONFIG] = _config_history_info[JOB_CONFIG_HISTORY][0]
        else :
            job_info[LAST_UPDATE_CONFIG] = {}
            job_info[LAST_UPDATE_CONFIG][DATE] = NONE

        if isDisableTargetJob(job_info, args):
            _disable_target_job_infos.append(job_info)
            print("Hit : " + job[FULLNAME] +" LastUpdated:" + job_info[LAST_UPDATE_CONFIG][DATE])
    return  _disable_target_job_infos

def getJobConfigHistry(server,name):
    folder_url, short_name = server._get_job_folder(name)
    _config_history_url = folder_url + 'job/' + short_name + '/' + JOB_CONFIG_HISTORY + '/'
    _config_history_info = server.get_info(_config_history_url)
    return _config_history_info

def isDisableTargetJob(job_info,args):
    _isDisableTarget = False
    if job_info[LAST_UPDATE_CONFIG][DATE] == NONE or isNotUpdatedRecentryJob(job_info[LAST_UPDATE_CONFIG][DATE], args.days_ago):
        _isDisableTarget = True
    return _isDisableTarget

def isNotUpdatedRecentryJob(update_date,days_ago):
    _isNotUpdatedRecentry = False
    _days_ago = datetime.datetime.today() - datetime.timedelta(days=days_ago)
    datetime_formatted = datetime.datetime.strptime(update_date, "%Y-%m-%d_%H-%M-%S")
    if(datetime_formatted < _days_ago):
        _isNotUpdatedRecentry = True
    return _isNotUpdatedRecentry

def disableJobs(server,job_infos,args):
    _FULL_NAME = 'fullName'
    for job_info in job_infos :
        server.disable_job(job_info[_FULL_NAME])
        print("Disabled : " + job_info[_FULL_NAME]  +" LastUpdated:" + job_info[LAST_UPDATE_CONFIG][DATE])

def writeJson(job_infos,outfile):
    with open(outfile, 'w') as jsonfile:
        json.dump(job_infos, jsonfile)

def parse_args():
    argparser = ArgumentParser()
    argparser.add_argument('-j', '--jenkins-url', type=str, default="",required = True,  help='input $JENKINS_URL')
    argparser.add_argument('-u', '--jenkins-username', type=str, default="", required=True, help='input jenkins username')
    argparser.add_argument('-p', '--jenkins-password', type=str, default="", required=True, help='input jenkins password')
    argparser.add_argument('-a', '--days-ago', type=int, default="14", required=False, help='input days before get target')
    argparser.add_argument('-o', '--output-json', type=str, default="jenkins_job_infos.json", required=False, help='input disable target job prefix')
    argparser.add_argument('-d', '--disable-job-prefix', type=str, default="operation-working/", required=False, help='input disable target job prefix')
    argparser.add_argument('-s', '--skip-disable', action='store_true', required=False, help = 'skip disable job')
    return argparser.parse_args()

def main():
    args = parse_args()
    server = login(args)

    print('--- start detect disable target jobs ---')
    disable_target_job_infos = getDisableTargetJobInfos(server,args)
    writeJson(disable_target_job_infos, args.output_json)
    print('--- finish detect disable target jobs ---')

    if not args.skip_disable :
        print('--- start disable jobs ---')
        disableJobs(server,disable_target_job_infos,args)
        print('--- finish disable jobs ---')

if __name__ == '__main__':
    sys.exit(main())

実行コマンド

python disable-not-recentry-updated-jobs.py -j ${JENKINS_URL} -u ${JENKINS_USER} -p ${JENKINS_PASS} -a ${BEFORE_DAYS_AGO} -o ${OLD_JENKINS_JOBS_JSON} -d ${DISABLE_TARGET_JOB_PREFIX}

※実行には以下のライブラリが必要です。

  • python-jenkins
  • argparse

オプションについて
-j : jenkinsのURLを指定します。
-u : jenkinsのログインユーザーを指定します。
-p : jenkinsのログインパスワードを指定します。
-a : 何日より古いものを対象にするかを数字で指定します。
-o : 対象のジョブを書き込むjsonの名前を指定します。
-d : 無効化の対象とするジョブのプレフィックスを指定します。
-s : 無効化をしないで対象となるジョブの確認のみを行う際に指定するオプションです。

サンプルコマンド

python disable-not-recentry-updated-jobs.py -j http://my.jenkins.host:8080/ -u hoge -p fuga -a 30 -o old_jenkins_jobs.json -d work/

このコマンドの例だと30日より古いジョブでプレフィックスが work/ となっているジョブを一括で無効化します。
無効化する前に確認したいという場合は -s オプションをつけると先に確認が行えます。

まとめ

  • ジョブの無効化は プロジェクトの無効化を操作すると行えます。
  • 環境移行やトラブル調査の時に無効化をするといった利用が考えられます。
  • 一括でジョブを無効化したいときはスクリプトを作ると便利です。

おすすめ書籍


[改訂第3版]Jenkins実践入門 ――ビルド・テスト・デプロイを自動化する技術 (WEB+DB PRESS plus)

初めてJenkinsを学ぶ方におすすめです。


Jenkins

Jenkinsでできることについてもう少し詳しく学びたい方におすすめです。

コメント

タイトルとURLをコピーしました