2015年03月02日

このエントリーをはてなブックマークに追加

CLI(jenkins-cli.jar)を扱った情報が少ない

今回はCLI(jenkins-cli.jar)を使ってジョブをbuildしてみる。軽く検索した限りでは欲しい日本語情報が見つからなかったので、探していた人にとっての有用情報になってくれたなら、幸いである。

CLI(jenkins-cli.jar)セットアップ手順は、以下のエントリ。

検証環境

  • CentOS release 6.6
  • jenkins-1.599-1.1.noarch
  • java-1.6.0-openjdk-1.6.0.0-11.1.13.4.el6.x86_64

CLI(jenkins-cli.jar)でbuildする方法

http://127.0.0.1:8080/cli/command/buildより:

java -jar jenkins-cli.jar -s http://127.0.0.1:8080/ build JOB [-c] [-f] [-p] [-r N] [-s] [-v] [-w]
Starts a build, and optionally waits for a completion.
Aside from general scripting use, this command can be
used to invoke another job from within a build of one job.
With the -s option, this command changes the exit code based on
the outcome of the build (exit code 0 indicates a success)
and interrupting the command will interrupt the job.
With the -f option, this command changes the exit code based on
the outcome of the build (exit code 0 indicates a success)
however, unlike -s, interrupting the command will not interrupt
the job (exit code 125 indicates the command was interrupted)
With the -c option, a build will only run if there has been
an SCM change
 JOB : Name of the job to build
 -c  : Check for SCM changes before starting the build, and if there's no
       change, exit without doing a build
 -f  : Follow the build progress. Like -s only interrupts are not passed
       through to the build.
 -p  : Specify the build parameters in the key=value format.
 -s  : Wait until the completion/abortion of the command. Interrupts are passed
       through to the build.
 -v  : Prints out the console output of the build. Use with -s
 -w  : Wait until the start of the command

オプション指定方法を除くと、基本は

java -jar jenkins-cli.jar -s http://127.0.0.1:8080/ build JOB

である事が分かる。

基本編

ここからは基本的なbuildを順に試して行く。

基本1: オプションなし/ジョブ登録(予約)

ジョブ登録(予約)である。何故、予約なのか?それは、CLIがジョブの結果を待たないからだ。これはWebUIからbuildするのと同じである。WebUIの操作に慣れている場合は、いつもの操作であるはずだ。

$ java -jar jenkins-cli.jar -s http://127.0.0.1:8080/ -i /path/to/id_rsa build testing

ジョブ登録が成功した場合は何も表示されず、凄くUNIXらしい振る舞いをする。終了コードもUNIXらしい振る舞いをする。成功時の$?0で、失敗時はnon 0だ。 ‘

基本2: -w/ジョブが開始するまで待つ

ジョブ予約するだけでなく、ジョブが起動するまでは待ちたい場合もある。そんな時は、-wオプションの出番だ。

$ java -jar jenkins-cli.jar -s http://127.0.0.1:8080/ -i /path/to/id_rsa build testing -w
Started testing #39

Started <JOB> #<build-ID>が表示され、コマンドが正常終了する。

基本3: -s/ジョブの実行結果を待つ

ジョブが予約・起動するのを確認するだけでなく、ジョブの結果が出るまで待ちたい場合もある。そんな時は、-sオプションの出番だ。

$ java -jar jenkins-cli.jar -s http://127.0.0.1:8080/ -i /path/to/id_rsa build testing -s
Started testing #40
Completed testing #40 : SUCCESS

先程の-wオプションによる実行結果に加え、Completed <JOB> #<build-ID>: <build>成否が表示され、コマンドが正常終了する。

基本4: -s -v/ジョブの実行結果を待ち、buildのconsoleログを表示

-sオプションで分かるのは、buildの成否までだ。しかし、buildのconsoleログが表示されない。デバッグ時やJOB登録直後の調整時にはconsoleログを表示したくなる。そんな時は、-vオプションの出番だ。-vは単体では無く-sと一緒に使う事が期待されている。

$ java -jar jenkins-cli.jar -s http://127.0.0.1:8080/ -i /path/to/id_rsa build testing -s -v
Started testing #41
Started from command line by hansode
Building remotely on ct103.ci03.dh (centos-6.4 vz.vm vz.kemumaki fpmbox rbenv) in workspace /var/lib/jenkins/workspace/testing
 > git rev-parse --is-inside-work-tree # timeout=10
Fetching changes from the remote Git repository
 > git config remote.origin.url https://github.com/axsh/wakame-vdc.git # timeout=10
Fetching upstream changes from https://github.com/axsh/wakame-vdc.git
 > git --version # timeout=10
 > git fetch --tags --progress https://github.com/axsh/wakame-vdc.git +refs/heads/*:refs/remotes/origin/*
 > git rev-parse origin/master^{commit} # timeout=10
Checking out Revision ed54f8de7e72f8902700fff011a26398790bf710 (origin/master)
 > git config core.sparsecheckout # timeout=10
 > git checkout -f ed54f8de7e72f8902700fff011a26398790bf710
 > git rev-list ed54f8de7e72f8902700fff011a26398790bf710 # timeout=10
 > git tag -a -f -m Jenkins Build #41 jenkins-testing-41 # timeout=10
[testing] $ /bin/bash -xe /tmp/hudson9218072417606499332.sh
+ date
Sun Mar  1 22:53:02 JST 2015
Finished: SUCCESS
Completed testing #41 : SUCCESS

-sオプション単体指定時よりも出力結果が多い事は一目瞭然だ。

基本編のまとめ
  1. オプションなし: ジョブ登録のみ
  2. -w: ジョブ登録、そしてジョブ起動するまで待つ
  3. -s: ジョブ登録・ジョブ起動、そしてジョブ成否が出るまで待つ
  4. -s -v: ジョブ成否が出るまで待ち、更にconsoleを出力

応用編

次に応用編を試して行く。

応用1: -p KEY=VALUE/パラメタつきbuild

ジョブの中には、パラメタ化してあるものもあるはずだ。常にデフォルト値で良い訳が無い。そんな時は-p KEY=VALUEの出番だ。以下の例ではビルド結果表示を分かりやすくするために-wを指定している。

$ java -jar jenkins-cli.jar -s http://127.0.0.1:8080/ -i /path/to/id_rsa build testing -w -p GIT_BRANCH=ci-fail
Started testing #80

もしも存在しないパラメタを指定すると、その旨を表示して教えてくれる。

$ java -jar jenkins-cli.jar -s http://127.0.0.1:8080/ -i /path/to/id_rsa build testing -w -p GIT_BRANCH2=ci-fail
'GIT_BRANCH2' is not a valid parameter. Did you mean GIT_BRANCH?

似たパラメタが存在する場合は、なんと、似たパラメタ名を教えてくれている!

応用2: -c/ソースコードに変更がある場合のみbuild

build命令を受け取ると、Jenkinsはソースコードに変更があろうともなかろうともbuildする。時には変更がある場合のみbuildした場合もある。そんな時は、-cオプションの出番だ。

$ java -jar jenkins-cli.jar -s http://127.0.0.1:8080/ -i /path/to/id_rsa build testing -c
Using strategy: Default
[poll] Last Built Revision: Revision e6cc9351e46bc8d062d5b7d27d18cba366e138bf (origin/ci-fail)
 > git --version # timeout=10
 > git ls-remote -h https://github.com/axsh/wakame-vdc.git # timeout=10
[poll] Latest remote head revision on origin/ci-fail is: e6cc9351e46bc8d062d5b7d27d18cba366e138bf - already built by 80

この結果では、already built by 80と表示され、buildされない事が分かる。もしも疑わしい場合は再度-cオプション指定で実行してみると良い。何度実行しても同じbuild番号が出力されるので、buildされてない事を確認出来る。

応用3: -f/ジョブの中断を無視?

-fオプション指定で実行した場合、コマンドを中断した場合でも、ジョブを中断しないように制御出来るらしい。それに対し、-sオプションの場合はコマンドを中断すると、それに応じてジョブを中断するようである。

ここで曖昧な表現になっているのは、-f-sの違いを明確に確認出来なかった為である。今後もしも明確な差を得られた場合は、この内容を加筆・修正する。

応用編のまとめ
  1. -p KEY=VALUE: パラメタ付きbuild
  2. -c: 変化がある時のみbuild
  3. -f: ジョブ中断を無視?

参考文献

補足:終了コードの扱い

コマンド成否は、コマンドの終了コードを使って判断可能である。その為、パイプと組み合せたコマンドライン操作やシェルスクリプトとの相性は良い。

ジョブが正しく失敗する場合

意図的にジョブが失敗するように設定を変更してみる。確認したいのは、出力結果と終了コードだ。実行し、結果を確認してみる。

$ java -jar jenkins-cli.jar -s http://127.0.0.1:8080/ -i /path/to/id_rsa build testing -s -v
Started testing #94
Started from command line by hansode
Building remotely on ct103.ci03.dh (centos-6.4 vz.vm vz.kemumaki fpmbox rbenv) in workspace /var/lib/jenkins/workspace/testing
 > git rev-parse --is-inside-work-tree # timeout=10
Fetching changes from the remote Git repository
 > git config remote.origin.url https://github.com/axsh/wakame-vdc.git # timeout=10
Fetching upstream changes from https://github.com/axsh/wakame-vdc.git
 > git --version # timeout=10
 > git fetch --tags --progress https://github.com/axsh/wakame-vdc.git +refs/heads/*:refs/remotes/origin/*
 > git rev-parse origin/master^{commit} # timeout=10
Checking out Revision ed54f8de7e72f8902700fff011a26398790bf710 (origin/master)
 > git config core.sparsecheckout # timeout=10
 > git checkout -f ed54f8de7e72f8902700fff011a26398790bf710
 > git rev-list ed54f8de7e72f8902700fff011a26398790bf710 # timeout=10
 > git tag -a -f -m Jenkins Build #94 jenkins-testing-94 # timeout=10
[testing] $ /bin/bash /tmp/hudson2042532681956823107.sh
+ hoge
/tmp/hudson2042532681956823107.sh: line 5: hoge: command not found
Build step 'Execute shell' marked build as failure
Finished: FAILURE
Completed testing #94 : FAILURE

ジョブは完了し、結果はFAILURE

$ echo $?
2

そして終了コードは2non 0だ。

終了コードのまとめ
  1. 成功時: 0
  2. 失敗時: non 0

失敗時の終了コードは、失敗内容によって変化する。

あとがき

CLI(jenkins-cli.jar)を使ってみて分かったのは、curlコマンドなどによるRemote API経由操作よりも、細かな操作が可能である事だ。認証プラグインとの組み合わせ課題をきっかけに検証を始めた訳だが、今の所は使ってみて良かったと思える。もしかしたら、近いうちに他のコマンドも試してみるかも知れない。




編集
@hansode at 10:30|PermalinkComments(0)TrackBack(0)Jenkins 

2015年03月01日

このエントリーをはてなブックマークに追加

ライブドアブログ(livedoor Blog)は、Markdownで書けない

この内容には背景説明が必要だ。

背景1: Markdown生活

GitHubを本格利用し始めた4年前辺りから、Markdown形式でドキュメントを書いている。Markdownは実に単純な形式・規則であり、気持ちよく執筆作業を行える。そして、すっかりMarkdownに慣れてしまった身体では、HTMLを書くのは苦行に近い...。本来書きたい事を書く為の時間だけでなく、HTMLによる整形が、執筆作業の邪魔をする。

背景2: ライブドアブログ(livedoor Blog)を本ブログでは利用している

記事投稿画面のエディタ形式を変える - livedoor Blog ヘルプセンターより(2015/03/01現在):

記事投稿画面のエディタ部分(本文を入力する部分)は、デフォルトでは記事の見た目そのままに近い表示がされる「HTMLエディタ」になっていますが、右上の「HTMLタグ編集」をクリックすると、HTMLタグを直接編集できる画面に切り替えることができます。

エディタの種類は、HTMLかシンプルの2種類。Markdownは対応してないのである。そのうち対応してくれえるのかも知れない。

背景3: 移行か、継続か

Markdown対応ブログサービスへの移行を考えた事もある。サービス移行先候補を使ってみると、無料プラン・有料プランに限らず、上手くURIを引き継げないなどの課題が出て来た。どうにかして・思い切って移行するか、それとも、ライブドアブログを継続利用するか...。検討した結果、移行によるデメリットが大きかったので、ライブドアブログ継続利用に落ち着いた。しかしながら、相変わらずMarkdown形式で書きたかったのである。

どうにかしてMarkdownで書く

MarkdownをHTMLに変換できさえすれば、ほぼ解決する。幾つか試した中で辿り着いたのが、以下の執筆から出稿までのフロー。

  1. Dillingerを使う
    1. Markdownで記述
    2. HTML形式で出力
  2. 出力されたHTMLソースを表示
  3. <body></body> に挟まれた領域をコピー
  4. コピーした内容を、livedoorブログの記事領域に貼り付けて投稿

それぞれの手順内容を補足して行く。

手順1: Dillingerを使いMarkdownで記述しHTMLで出力

Dillingerは、無料で利用可能(2015/03/01現在)。アクセスすると直ぐに利用可能で、以下の様な編集画面が表示される。

  • 左ペイン: Markdown記述領域
  • 右ペイン: プレビュー内容

基本的には左ペインにMarkdown形式で記述して行く。記述した内容は随時プレビューされるので、レンダリング後の状態と、Markdown的に間違いがあるのかどうかを、同時に確認出来る。

手順2: 出力されたHTMLソースを表示

切りの良い所まで書けたら、

  1. メニューバーのEXPORT ASをクリックして開き、
  2. HTMLを選択すると、
  3. HTMLが自動的にダウンロードされる
手順3: <body></body> に挟まれた領域をコピー

  1. ダウンロードされたHTMLをエディタ等で開き、
  2. <body>...</body>で挟まれた領域を選択・コピー
手順4: コピーした内容を、livedoorブログの記事領域に貼り付けて投稿

ここまで来ると、今までのHTMLエディタによる操作と同じである。仮に誤字脱字を見つけた場合は、手順1へ戻り、同じ手順を繰り返す。こうする事によりMakdown対応してないサービスと上手く付き合って行ける。

おまけ: MarkdownをHTMLへ変換するツールの選択

今回紹介した内容ではDillingerだけで完結しているが、自分が一番愛用しているMarkdownエディタサービスは StackEditだ。

このStackeditもMarkdownからHTMLを出力可能だ。しかしながら、StackEditが出力したHTMLには着色やレイアウト用途の余計なHTML要素が含まれている。この余計な要素は、シンプルなHTMLを期待するツールとの相性が悪い。

今回紹介したDillingerでは、シンプルなHTMLを出力してくれる。Markdownに対応してないサービスとの連携に注目した場合は、Dillingerが良い訳である。

あとがき

本エントリでは、Markdownファイル管理については触れていない。例えばMarkdownエディタが持ち合わせている管理機能を使って管理すれば良い。参考ままでに、自分は専用Gitリポジトリで管理している。この管理方法に関する内容は本エントリの主題から逸れるので、触れないでおく。




編集
このエントリーをはてなブックマークに追加

「変態Jenkins」の裏側を少しずつ公開

ChatOps導入検討にて、WebUIを介さずにJenkinsジョブ操作をする必要性が高まった。手元のJenkinsさんが世に出回ってる様な設定・構成であれば問題はないのだが、世の中のそれとは違う為に遭遇したであろう事を、ここにまとめておく。

背景・経緯

Jenkins設定にて:

  1. グローバルセキュリティの設定を有効化
  2. アクセス制御にはGithub Authentication pluginを使用
    1. 深く掘り下げてないが、結果としてGitHub Authentication pluginを使用していると、API Tokenを利用できない。
  3. WebUI経由でしかジョブ実行する手段がないのか…と調べた結果、Jenkins CLIとCredentialの組み合せに辿り着いた。
おまけ:GitHub Authentication plugin有効時のTokenによるAPI呼び出し失敗結果

Jenkins CLI導入前は、Remote APIをAPI Token付きで使用する事を検討・検証していた。しかし、この検証ではGitHub Authentication pluginとの組み合わせ問題に遭遇した。参考までにGitHub Authentication pluginを有効にしたJenkinsにHTTPリクエストしてみると、こうなる。

$ curl curl -fsSkL -X POST -u hansode:******** http://127.0.0.1:8080/job/testing/build
curl: (22) The requested URL returned error: 400 Nothing is submitted

調査・検討した結果、自分はJenkins CLIを使う事にした。

Jenkins CLIとCredentialを使って動かす

Jenkins CLI - 日本語 - Jenkins Wikiを参考に設定して行く。

1: CLIの取得

CLIの取得 Jenkins CLIは jenkins.war の中に、jarファイルとして含まれています。http://yourserver.com/cli からダウンロードすることができます。CLI jarはJenkinsのバージョンに依存していますが、実際には異なるバージョン間でも互換性を保つことができるようになっています。

このように書かれている。手元のJenkinsUI(http://yourserver.com/cli)にアクセスしてみると、以下の様なページが表示される。ページ内にはjenkins-cli.jarダウンロードURIが存在するので、ダウンロードURIをクリックし、手元にダウンロードする。

jenkins-cli

2: Credentials(証明書) を使って動かす (1.419 以降)

Credentials(証明書) を使って動かす (1.419 以降) Jenkinsの利用に認証が求められる場合は、公開鍵認証を設定する必要があります。Web UIからログインし、 http://yourserver.com/me/configure にアクセスして下さい。そして、公開鍵を所定のテキストエリアに入力します。

http://yourserver.com/me/configureにアクセスすると、以下の様な個人設定画面が表示されるので、SSH Public Keysに公開鍵を貼り付けて、保存する。

jenkins me config

3: 秘密鍵指定で認証確認

先程ダウンロードしたjenkins-cli.jarを使い、who-am-iコマンドを実行してみる。認証が成功すると、以下の様にユーザー名が表示される。

$ java -jar jenkins-cli.jar -s http://127.0.0.1:8080/ -i /path/to/id_rsa who-am-i
Authenticated as: hansode
Authorities:
  authenticated

hansodeとして認証された事が分かる。これ以降は好みのコマンドでJenkinsを操作可能だ。

あとがき

やや不本意な状況で辿り着いたCredentialを使ったCLIではあるが、意外と使い勝手が良さそう。




編集
@hansode at 16:00|PermalinkComments(0)TrackBack(0)Jenkins 

2015年02月01日

このエントリーをはてなブックマークに追加

@mirakuiさんの1年前の自分と暮らす - 昼メシ物語を参考にmirakui/retrobotを導入してみた。

過去5年分のツイートをするretrobot達:

retrobot検証環境

retrobot環境構築には、Vagrantを利用し、下記リポジトリにまとめた。

これを使うと、自分が利用している環境と同環境を手に入れられる。これから構築する場合には役に立てるかも知れない。なお、システム要件や構築手順は本エントリの主題からはずれるので、省略する。

ところで、何故5年分なのか?

当初は先輩retrobotさん達と同様に、1年前のツイートをさせるbotのみだった。

数日間、1年前のツイートを観察してみると、自動化作業は収束しつつある時期だった。それ以前の自動化と悪戦苦闘していた約3年前までのツイートに興味が広がった。

更に数日運用してみると、CI環境構築以前の自分自身にも興味が出て来た。

今の所は、5年分で落ち着いている。これ等5年分のretrobot達を専用リストに登録し、自分の『1〜5年前の今』を振り返っている。

ヒントが詰まっている

過去のツイートには、これまでの自動化へのプロセスが記録されている。今の自分の記憶から揮発しているような情報の数々だ。これ等は最近増えているCIに関する質問者が、どの様に困っているのか、それを知るヒントに近い物が多々詰まってるはず>である。過去の自分を今の自分が活用し始めようとしている。

未来のために。

お礼

生みの親の@mirakuiさん、そして、先輩retrobotを運用している@sonotsさんと@kenjiskywalkerさんには、導入に関して助言を頂いた。この場 にて、お礼申し上げます。

参考文献

続きを読む


編集

2015年01月31日

このエントリーをはてなブックマークに追加

本エントリは、@mikedaさんの下記エントリに影響を受け、書き始めた。

自分もblogへアウトプットしていなくなっていた。自分も書かなくなった理由を振り返ってみた。

約3年前からアウトプット先がGitHubへ

内容と共に、アウトプットが多い順に並べる。

定期的にblogエントリを書いていた頃よりも、総アウトプット数は増えている。例えば、約1年前の時点でGitHubの芝生を365日間以上継続して生やした事がある。

なお、コミットの大半は、インフラのコード化作業(Code as Infrastructure)だ。どうやら、GitHubにアウトプットして満足感を得て終わってしまってたようである。仕事そのものは上手く運ぶようになった。

総アウトプット数が増加した一方で、減少したのは中長期的に振り返る事だ。そう、、、blogだ。

振り返りツールとしてのblog

GitHubへのアウトプットは、粒度が細かい。それゆえ、概要や中長期的な内容を把握する事は困難である。振り返りツールとしてblogを活用する事が必要だ。かつての自分自身のエントリの大半は、そう言った内容が多かった。振り返りエントリを書き溜めてなかったからこそ、聞かれる事が幾つかある。

  • Wakame-vdc
    • 開発舞台裏
    • 冗長化
  • CI環境周り
    • 変態Jenkinsクラスタ
    • 構築する際の苦労談

これらを週1ペースを目安に、2015年前半でまとめ終えたなら、振り返り習慣を取り戻しつつ、周りが欲するドキュメントの一部を提供出来る。

未来のために。




編集

2015年01月30日

このエントリーをはてなブックマークに追加

CVE-2015-0235: GHOST Buster シェルスクリプト #CentOS-6 | blog.hansode.orgのCentOS-7編。

CVE-2015-0235関連

RHEL-7 / CentOS-7 関連

glibcを入れ替える必要がある。

2015/01/30時点の対応

検証用にbuildワーカーを複数環境扱ってるので、それぞれ対応する必要があった。CentOS-7系に関しては7.0.1406のみで良いので対応は大分軽度だ。手順と動作を確認し、上手く行ったのが下記シェルスクリプト。

 ghost-buster-rhel7.sh

バージョン判定には、

  • /etc/yum/vars/releaseverが存在する場合は使用し、
  • 存在しない場合は/etc/centos-releaseから情報取得
#!/bin/bash
#
# requires:
#  bash
#
set -e
set -o pipefail
set -x

if [[ -f /etc/yum/vars/releasever ]]; then
  releasever=$(< /etc/yum/vars/releasever)
else
  releasever=$(
   sed \
    -e '/^CentOS /!d' \
    -e 's/CentOS.*\srelease\s*\([0-9][0-9.]*\)\s.*/\1/' \
    < /etc/centos-release
  )
fi

arch=$(arch)
case "${arch}" in
  i*86)   basearch=i386 arch=i686 ;;
  x86_64) basearch=${arch} ;;
esac

case "${releasever}" in
  7.0.1406)
    yum update  -y \
      glibc \
      glibc-common \
      glibc-devel \
      glibc-headers
    ;;
esac

対象環境で実行するとglibcが入れ替わる。

あとがき

手元に都合の良く手頃な検証環境があるのは幸せな事なのだろう。




編集
@hansode at 18:00|PermalinkComments(0)TrackBack(0)bash 

2015年01月29日

このエントリーをはてなブックマークに追加

CVE-2015-0235関連

RHEL-6 / CentOS-6 関連

glibcを入れ替える必要がある。

2015/01/29時点の対応

検証用にbuildワーカーを複数環境扱ってるので、それぞれ対応する必要があった。updatesが反映されているのは6.6のみ。それ以下を放置する訳にもいかない。それゆえ、6.66.[0-5]と言う場合分けが必要だ。手順と動作を確認し、上手く行ったのが下記シェルスクリプト。

 ghost-buster-rhel6.sh

バージョン判定には、

  • /etc/yum/vars/releaseverが存在する場合は使用し、
  • 存在しない場合は/etc/centos-releaseから情報取得
#!/bin/bash
#
# requires:
#  bash
#
set -e
set -o pipefail
set -x

if [[ -f /etc/yum/vars/releasever ]]; then
  releasever=$(< /etc/yum/vars/releasever)
else
  releasever=$(
   sed \
    -e '/^CentOS /!d' \
    -e 's/CentOS.*\srelease\s*\([0-9][0-9.]*\)\s.*/\1/' \
    < /etc/centos-release
  )
fi

arch=$(arch)
case "${arch}" in
  i*86)   basearch=i386 arch=i686 ;;
  x86_64) basearch=${arch} ;;
esac

case "${releasever}" in
  6.6)
    yum update  -y \
      glibc \
      glibc-common \
      glibc-devel \
      glibc-headers
    ;;
  6.[0-5])
    expected_version=2.12-1.149.el6_6.5
    case "$(rpm -qa --qf '%{Version}-%{Release}\n' glibc)" in
      ${expected_version})
        ;;
      *)
        base_uri=http://ftp.jaist.ac.jp/pub/Linux/CentOS/6.6/updates/${basearch}/Packages
        yum install -y \
          ${base_uri}/glibc-${expected_version}.${arch}.rpm \
          ${base_uri}/glibc-common-${expected_version}.${arch}.rpm \
          ${base_uri}/glibc-devel-${expected_version}.${arch}.rpm \
          ${base_uri}/glibc-headers-${expected_version}.${arch}.rpm
        ;;
    esac
    ;;
esac

対象環境で実行するとglibcが入れ替わる。

あとがき

手元に都合の良く手頃な検証環境があるのは幸せな事か。

続きを読む


編集
@hansode at 21:30|PermalinkComments(0)TrackBack(0)bash 

2015年01月26日

このエントリーをはてなブックマークに追加

UI経由ではバージョン指定できない(2015/01/26現在)

Jenkinsは、恐らく手頃なCIツールだ。個人的には2年半近く使っている。他のツールと同様に、ある程度使い続けていると、どこか使い辛さを感じ始める。Jenkinsにおける使い辛さの1つは、狙ったバージョンのJenkinsプラグインをインストール出来ない事。通常のJenkinsプラグインインストール手順は、こうだ。

  1. プラグインマネージャhttp://jenkins/pluginManager/からプラグインを検索
  2. 欲しいプラグインを選択
  3. プラグインをダウンロード・インストール
  4. Jenkinsを再起動

この手順には、プラグインのバージョンが登場しない。暗黙のルールとして、最新バージョン(latest)が指定され、プラグインがインストールされて行く。しかも、管理者の意図とは関係のない所で、だ。これは問題を含んでいる。とある日に構築したシステム構築を再現する様な場合は、要件を満たせない。そこをどうにかしたくて、手順を確立させた。こんな手順、本当は無くなって欲しい。

プラグインインストールの裏側を理解する

Plugins - Jenkins - Jenkins Wiki より、

By hand Download Site

Save the downloaded *.hpi/*.jpi file into the $JENKINS_HOME/plugins directory. You will then need to restart Jenkins (many containers let you do this without restarting the container)

http://updates.jenkins-ci.org/download/plugins/からJenkinsプラグインをダウンロード出来る事が分かる。プラグインリポジトリを注意深く調査していると、過去のバージョンもダウンロード出来る事が分かる。wikiの内容と調査結果をまとめると、こうなる。

最新版:

  • http://updates.jenkins-ci.org/latest/${name}.hpi

特定バージョン:

  • http://updates.jenkins-ci.org/download/plugins/${name}/${version}/${name}.hpi

保存先:

  • ${JENKINS_HOME}/plugins/${name}.hpi

反映方法:

  • Jenkins再起動

サービス起動後、プラグインマネージャを確認すると、狙ったバージョンのプラグインがインストールされている事を確認できるはずだ。少なくとも、自分が検証した限りでは、期待通りの結果となっている。

おまけ:プラグイン名とバージョンのペアを管理する

パッケージを1つ1つインストールするのは、実に面倒臭い。プラグインによっては最新版が良い場合もある。それを一括管理する為、自分は下記のようなスクリプトによりシステム構築している。

jenkins-plugin.sh:

#!/bin/bash
#
# requires:
#  bash
#
set -e
set -o pipefail

JENKINS_HOME=${JENKINS_HOME:-/var/lib/jenkins}
base_url=http://updates.jenkins-ci.org

function plugin_list() {
  cat <<_EOS_ | egrep -v '^$|^#'
PrioritySorter 1.3
config-autorefresh-plugin
configurationslicing
config-file-provider
cron_column
downstream-buildview
git        1.4.0
git-client 1.1.1
hipchat 0.1.5
greenballs
managed-scripts 1.1
nested-view
next-executions
parameterized-trigger 2.18
rebuild 1.20
timestamper 1.5.6
token-macro
urltrigger
view-job-filters
_EOS_
}

while read line; do
  set ${line}
  name=${1} version=${2}
  if [[ -z "${version}" ]]; then
    version=latest
  else
    version=download/plugins/${name}/${version}
  fi
  curl -fSkL ${base_url}/${version}/${name}.hpi -o ${JENKINS_HOME}/plugins/${name}.hpi
done < <(plugin_list)

chown -R jenkins:jenkins ${JENKINS_HOME}/plugins

ヒアドキュメント部分が、プラグイン名とバージョンを指定のペアを管理。

  • プラグイン名のみの場合は、最新版(latest)をインストール
  • プラグイン名とバージョン指定している場合は、そのバージョンをインストール

上記ヒアドキュメント部分を説明すると、こうなる。

  • バージョン固定:
    • PrioritySorter 1.3
    • git 1.4.0
    • git-client 1.1.1
    • hipchat 0.1.5
    • managed-scripts 1.1
    • parameterized-trigger 2.18
    • rebuild 1.20
    • timestamper 1.5.6
  • 最新版:
    • config-autorefresh-plugin
    • configurationslicing
    • config-file-provider
    • cron_column
    • downstream-buildview
    • greenballs
    • nested-view
    • next-executions
    • token-macro
    • urltrigger
    • view-job-filters

なお、これは自分が今までに使って来た厳選プラグインでもある。

あとがき

使い辛い所を分かった上で使い続けるJenkinsさんとの生活。もう少し続きそう。




編集
@hansode at 10:30|PermalinkComments(0)TrackBack(0)Jenkins | wakameci

2015年01月25日

このエントリーをはてなブックマークに追加

if文を省略可

GitHub API v3をcurlコマンド経由でAPI呼び出しをしていると、Token有無による場合分けが、しばしば必要となる。普段は当たり前の様にbashスクリプトを活用してcurlコマンドオプションを組み立てている。そして、-n-zによる文字列テストによる場合分けをしていた。そう、今までは。

[[ -n "${GITHUB_TOKEN}" ]] && { echo "-H \"Authorization: token ${GITHUB_TOKEN}\""; }

ある日、時々シェルスクリプトを書く@unakatsuoが言う。

文字列展開のうち、+の使い方・使い処が分かった。 echo ${var:+"foo ${var}"} みたいに書くと良い。

存在は知っていたが、使わずに来た。

未開拓のパラメタ展開

man bash(1)より。

   Parameter Expansion

       ${parameter:+word}
              Use Alternate Value.  If parameter is null or unset, nothing is substituted, otherwise the expansion of word is substituted.
  • parameterがnullかunsetの場合は置き換えない
  • そうでない場合は置き換える

これを上手く使うと、if文を省略して書けると言う。先述のコードを、+によるパラメタ展開を使い書き直すと、

before:

[[ -n "${GITHUB_TOKEN}" ]] && { echo "-H \"Authorization: token ${GITHUB_TOKEN}\""; }

after:

echo ${GITHUB_TOKEN:+"-H \"Authorization: token ${GITHUB_TOKEN}\""}

コードが短くなった。

おまけ:test-github-issues.sh

普段使いのスクリプトから一部を抜粋。

#!/bin/bash
#
#
set -e
set -o pipefail

function curl() {
  echo curl "${@}"
}

function github_issues() {
  curl \
   -fsSkL \
   $([[ -n "${GITHUB_TOKEN}" ]] && { echo "-H \"Authorization: token ${GITHUB_TOKEN}\""; } ) \
   "https://api.github.com/repos/${owner}/${repo}/issues"
}

function github_issues2() {
  curl \
   -fsSkL \
   ${GITHUB_TOKEN:+"-H \"Authorization: token ${GITHUB_TOKEN}\""} \
   "https://api.github.com/repos/${owner}/${repo}/issues"
}

owner=github
repo=github

GITHUB_TOKEN=     github_issues
GITHUB_TOKEN=     github_issues2

GITHUB_TOKEN=asdf github_issues
GITHUB_TOKEN=asdf github_issues2

[[ "$(GITHUB_TOKEN=     github_issues)" == "$(GITHUB_TOKEN=     github_issues2)" ]]
echo ${?}
[[ "$(GITHUB_TOKEN=asdf github_issues)" == "$(GITHUB_TOKEN=asdf github_issues2)" ]]
echo ${?}

上記スクリプトを実行すると、こうなる。

$ chmod +x ./test-github-issues.sh
$ ./test-github-issues.sh
curl -fsSkL https://api.github.com/repos/github/github/issues
curl -fsSkL https://api.github.com/repos/github/github/issues
curl -fsSkL -H "Authorization: token asdf" https://api.github.com/repos/github/github/issues
curl -fsSkL -H "Authorization: token asdf" https://api.github.com/repos/github/github/issues
0
0
  • GITHUB_TOKEN あり / なし
  • github_issuesgithub_issues2 による生成文字列

生成された文字列が改良前後で同一かどうかをテストし、同一である事を確認。

あとがき

多用し過ぎると可読性が低下しそうなので、ご利用は計画的に。




編集
@hansode at 17:00|PermalinkComments(0)TrackBack(0)bash 

2015年01月24日

このエントリーをはてなブックマークに追加

新規構築は問題が無い

気にすべきは、マイグレーションが実行されるので、ビルドログが多い環境ほど注意が必要となる事。いつものアップグレード時間よりも長く待たされる事を、承知した上でメンテナンスを行えたなら 、言う事は無い。なお、手元のJenkinsクラスタでは、1.596から1.597へのアップグレードは問題なくマイグレーションが完了した。

ハイライトを追いかける。

Changelog | Jenkins CI より

What's new in 1.597 (2015/01/19)

  • JENKINS_HOME layout change: builds are now keyed by build numbers and not timestamps. See Wiki for details and downgrade. (issue 24380)

JENKINS_HOMEのレイアウトを変更したとの事。

レイアウト変更により、buildIDとbuild時刻の関係が逆転

[#JENKINS-24380] Use build numbers as IDs - Jenkins JIRA より

Before:

% ls -la
total 16
drwxrwxr-x 4 kohsuke kohsuke 4096 Sep 15 17:51 .
drwxrwxr-x 4 kohsuke kohsuke 4096 Sep 15 17:51 ..
lrwxrwxrwx 1 kohsuke kohsuke   19 Apr 18 10:42 1 -> 2014-04-18_10-42-35
lrwxrwxrwx 1 kohsuke kohsuke   19 Sep 15 17:51 2 -> 2014-09-15_17-51-46
drwxrwxr-x 2 kohsuke kohsuke 4096 Apr 18 10:42 2014-04-18_10-42-35
drwxrwxr-x 2 kohsuke kohsuke 4096 Sep 15 17:51 2014-09-15_17-51-46
lrwxrwxrwx 1 kohsuke kohsuke    2 Apr 18 10:39 lastFailedBuild -> -1
lrwxrwxrwx 1 kohsuke kohsuke    1 Sep 15 17:51 lastStableBuild -> 2
lrwxrwxrwx 1 kohsuke kohsuke    1 Sep 15 17:51 lastSuccessfulBuild -> 2
lrwxrwxrwx 1 kohsuke kohsuke    2 Apr 18 10:39 lastUnstableBuild -> -1
lrwxrwxrwx 1 kohsuke kohsuke    2 Apr 18 10:39 lastUnsuccessfulBuild -> -1

After:

% ls -la
total 16
drwxrwxr-x 4 kohsuke kohsuke 4096 Sep 15 17:52 .
drwxrwxr-x 4 kohsuke kohsuke 4096 Sep 15 17:51 ..
drwxrwxr-x 2 kohsuke kohsuke 4096 Apr 18 10:42 1
drwxrwxr-x 2 kohsuke kohsuke 4096 Sep 15 17:51 2
lrwxrwxrwx 1 kohsuke kohsuke    1 Sep 15 17:52 2014-04-18_10-42-35 -> 1
lrwxrwxrwx 1 kohsuke kohsuke    1 Sep 15 17:52 2014-09-15_17-51-46 -> 2
lrwxrwxrwx 1 kohsuke kohsuke    2 Apr 18 10:39 lastFailedBuild -> -1
lrwxrwxrwx 1 kohsuke kohsuke    1 Sep 15 17:51 lastStableBuild -> 2
lrwxrwxrwx 1 kohsuke kohsuke    1 Sep 15 17:51 lastSuccessfulBuild -> 2
lrwxrwxrwx 1 kohsuke kohsuke    2 Apr 18 10:39 lastUnstableBuild -> -1
lrwxrwxrwx 1 kohsuke kohsuke    2 Apr 18 10:39 lastUnsuccessfulBuild -> -1
  • 以前は、日付が実態で、build番号がsymlink
  • 今後は、日付がsymlinkで、build番号が実態

この仕様変更によるマイグレーション処理が、システムアップグレード時(プロセス起動時)に発生する。今までのbuildログが多く残されていれば多く残されている程、マイグレーションに時間がかかる。

念の為、アップグレード前にJENKINS_HOMEをバックアップしておいた方が良いかも知れない。それと、事前にbuildログをある程度掃除しておいた方が良いかも知れない。

migration進捗は/var/log/jenkins/jenkins.logで確認可能

migration進捗が気になる場合は/var/log/jenkins/jenkins.logtail -fしておくと良い。過去のbuild番号の数だけdoMigrateが記録されて行く。

Jan 24, 2015 4:08:11 PM jenkins.model.RunIdMigrator doMigrate
WARNING: found no build.xml in 2014-03-06_16-55-39
Jan 24, 2015 4:08:11 PM jenkins.model.RunIdMigrator doMigrate
WARNING: found no build.xml in 2014-01-10_16-56-22
Jan 24, 2015 4:08:11 PM jenkins.model.RunIdMigrator doMigrate
WARNING: found no build.xml in 2013-10-23_16-56-23
Jan 24, 2015 4:08:11 PM jenkins.model.RunIdMigrator doMigrate
WARNING: found no build.xml in 2014-06-16_16-56-47
Jan 24, 2015 4:08:11 PM jenkins.model.RunIdMigrator doMigrate
WARNING: found no build.xml in 2013-12-22_16-56-22

おまけ:buildログ定期削除スクリプト

参考までに、自分が使用しているbuildログ定期削除スクリプト。これを日次実行させている。Jenkinsの定期実行ジョブとして。

#!/bin/bash
#
# requires:
#  bash
#
set -e
set -o pipefail

LANG=C
LC_ALL=C

threshold=+$((30 * 2))

function disk_usage() {
  df -h
  df -k
}

disk_usage

for target_dir in /var/lib/jenkins/jobs/*/builds; do
  [[ -d "${target_dir}" ]] || continue
  echo ... ${target_dir}

  while read line; do
    [[ -f "${line}" ]] || continue
    rm ${line}
  done < <(find ${target_dir} -type f -mtime ${threshold})
done

disk_usage
  • threshold=+$((30 * 2))

thresholdで直近60日分を残すように指定している。この文字列は、findコマンドの引数として使用されるので、+に意味があるので、+を決して忘れぬように。

あとがき

Jenkinsコアパッケージアップグレードは、細目に実施した方が良い。




編集
@hansode at 18:00|PermalinkComments(0)TrackBack(0)Jenkins | wakameci