ようへいの日々精進XP

よかろうもん

Array クラス、String クラスとかパーセント記法(Ruby)

tl;dr

Array クラスのメソッドをちょろっと触ってみたメモ。

参考

メモ

delete_if メソッドと reject! メソッド

  • 要素の数だけ繰り返しブロックを実行してブロックの戻り値が真になった要素を削除
$ pry
[1] pry(main)> words = ["a", "b", "c", "d", "e"] # 配列の生成
=> ["a", "b", "c", "d", "e"]
[2] pry(main)> words.delete_if do |item| item =~ /^[ace]/ end # delete_if メソッドで要素を削除
=> ["b", "d"]

reject! メソッドも同様の結果となる。

$ pry                                                                                                                                       
[1] pry(main)> words = ["a", "b", "c", "d", "e"] # 配列の生成                                                                                                      
=> ["a", "b", "c", "d", "e"]
[2] pry(main)> words.reject! do |item| item =~ /^[ace]/ end # reject! メソッドで要素を削除
=> ["b", "d"]

但し、delete_ifreject! メソッドではレシーバ自体に変化が無かった(要素が削除されなかった)場合の挙動が以下のように異なる。

$ pry                                                                                                                                       
[1] pry(main)> words = ["a", "b", "c", "d", "e"]                                                                                                                              
=> ["a", "b", "c", "d", "e"]
[2] pry(main)> words.delete_if do |item| item =~ /^[xyz]/ end
=> ["a", "b", "c", "d", "e"] # delete_if はレシーバー自身が返る
[3] pry(main)> words.reject! do |item| item =~ /^[xyz]/ end
=> nil # reject! は nil が返る
[4] pry(main)> p words
["a", "b", "c", "d", "e"]

each_with_index

  • 要素の数だけブロックを繰り返し実行
  • ブロック引数には各要素と番号が入る
$ pry
[1] pry(main)> a = ["hage", "pika", "tsuru"]
=> ["hage", "pika", "tsuru"]
[2] pry(main)> a.each_with_index { |atama, i| print i, ":", atama, "\n" }
0:hage
1:pika
2:tsuru
=> ["hage", "pika", "tsuru"]

shift / unshift / push

  • shift ... 配列の最初の要素を削除し、その要素を返す
  • unshift ... 配列の先頭に要素を追加(引数が無い場合には何もしない)
  • push ... 配列の末尾に要素を追加
$ pry
[1] pry(main)> words = ["one", "two", "three"]
=> ["one", "two", "three"]
[2] pry(main)> words.shift
=> "one"
[3] pry(main)> words.shift
=> "two"
[4] pry(main)> words.unshift
=> ["three"]
[5] pry(main)> words.push("four")
=> ["three", "four"]
[6] pry(main)> p words
["three", "four"]
=> ["three", "four"]
[7] pry(main)> words.unshift("two")
=> ["two", "three", "four"]

concat / compact / uniq

  • concat ... 要素を連結
  • compact ... nil を削除(非破壊的メソッド)
  • uniq ... 重複している要素を削除(非破壊的メソッド)
$ pry
[1] pry(main)> a = [:a, :a, :b, :c] # 配列を生成
=> [:a, :a, :b, :c]
[2] pry(main)> a[5] = :e # 配列の要素を追加
=> :e
[3] pry(main)> a.concat([:a, :b, :c]) # 配列を連結
=> [:a, :a, :b, :c, nil, :e, :a, :b, :c]
[4] pry(main)> a.compact # 配列から nil から削除(但し非破壊的)
=> [:a, :a, :b, :c, :e, :a, :b, :c]
[5] pry(main)> a.uniq # 重複している要素を削除(但し非破壊的)
=> [:a, :b, :c, nil, :e]
[6] pry(main)> p a # 結果として a.concat([:a, :b, :c]) と同じ出力となる
[:a, :a, :b, :c, nil, :e, :a, :b, :c]
=> [:a, :a, :b, :c, nil, :e, :a, :b, :c]

find / detect

  • find ... 要素を探して取り出し、ブロックが真となったら処理を中断する(該当する要素があれば処理を中断する)
  • detect ... find の別名
$ pry
[1] pry(main)> words = ["ab", "bc", "cd", "de"]
=> ["ab", "bc", "cd", "de"]
[2] pry(main)> words.find do |word| word =~ /c/ end
=> "bc"
[3] pry(main)> words.detect do |word| word =~ /c/ end
=> "bc"

パーセント記法

以下の記事がとても参考になった。

blog.toshimaru.net

slice

  • 引数で指定した位置の要素を取り出す
$ pry
[1] pry(main)> a = [1,2,3,4,5]
=> [1, 2, 3, 4, 5]
[2] pry(main)> p a.slice(1,3)
[2, 3, 4]
=> [2, 3, 4]
[3] pry(main)> p a.slice(1..3)
[2, 3, 4]
=> [2, 3, 4]

index

  • 文字列の中に第一引数で指定した文字が含まれていれば、その開始位置を整数で返す
  • 第二引数が指定されている場合、その位置から検索する
$ pry                                                                                                                                       
[1] pry(main)> p "oe!oe!oe!oe!oe!oe".index("!", 3)                                                                                                                            
5
=> 5
[2] pry(main)> p "oe!oe!oe!oe!oe!oe".index("!")                                                                                                                               
2
=> 2

chop / chomp

  • chop ... 末尾の一文字を削除(非破壊的)
  • chomp ... 末尾の改行を削除(非破壊的)(※改行が無ければ何もしない)
[3] pry(main)> x = "Hello world.\n"
=> "Hello world.\n"
[4] pry(main)> x.chop # \n を削除(非破壊的)
=> "Hello world."
[5] pry(main)> x.chop # \n を削除(非破壊的)
=> "Hello world."
[6] pry(main)> x.chomp # \n を削除(非破壊的)
=> "Hello world."
[7] pry(main)> p x # 結局南極 chop や chomp は非破壊的メソッドな為、x の値は変化なし
"Hello world.\n"
=> "Hello world.\n"

引き続き、色々とメモる予定。

配列の & 演算子と | 演算子と + 演算子と - 演算子(Ruby)

tl;dr

これもよく記憶が飛んでしまうので...メモ。「愛しさと切なさと心強さと」みたいなタイトルですいません。

メモ

& 演算子

  • 両方に含まれる要素を配列で返す
$ ruby
[1] pry(main)> a = [1,2,3]  # 配列の生成
=> [1, 2, 3]
[2] pry(main)> b = [1,3,5]  # 配列の生成
=> [1, 3, 5]
[3] pry(main)> p a & b      # 比較
[1, 3]
=> [1, 3]

| 演算子

  • どちらかに含まれる要素を配列で返す
$ pry
[1] pry(main)> a = [1,2,3]  # 配列の生成
=> [1, 2, 3]
[2] pry(main)> b = [1,3,5]  # 配列の生成
=> [1, 3, 5]
[3] pry(main)> p a | b      # 比較
[1, 2, 3, 5]
=> [1, 2, 3, 5]

+ 演算子

  • 要素を連結(ガッチャンコ)して配列で返す
$ pry                                                                                                                                       
[1] pry(main)> a = [1,2,3]  # 配列の生成
=> [1, 2, 3]
[2] pry(main)> b = [1,3,5]  # 配列の生成
=> [1, 3, 5]
[3] pry(main)> p a + b      # ガッチャンコ
[1, 2, 3, 1, 3, 5]
=> [1, 2, 3, 1, 3, 5]

- 演算子

  • 対象の要素を取り除いた配列を返す
$ pry
[1] pry(main)> a = [1,2,3]  # 配列の生成
=> [1, 2, 3]
[2] pry(main)> b = [1,3,5]  # 配列の生成
=> [1, 3, 5]
[3] pry(main)> p a + b      # ガッチャンコ
[1, 2, 3, 1, 3, 5]
=> [1, 2, 3, 1, 3, 5]
[4] pry(main)> c = [2,3,4]  # 配列の生成
=> [2, 3, 4]
[5] pry(main)> p a + b - c  # 引き算
[1, 1, 5]
=> [1, 1, 5]

以上

メモでした。

配列の添字演算子メモ(Ruby)

tl;dr

すぐに混乱するのでメモ。

memo

$ pry
[1] pry(main)> a = [1,2,3,4,5]     # 配列生成
=> [1, 2, 3, 4, 5]
[2] pry(main)> p a[0,5]            # a[0] から 5 つの要素
[1, 2, 3, 4, 5]
=> [1, 2, 3, 4, 5]
[3] pry(main)> p a[0..4]           # a[0] から a[4] まで
[1, 2, 3, 4, 5]
=> [1, 2, 3, 4, 5]
[4] pry(main)> p a[0..1]           # a[0] から a[1] まで
[1, 2]
=> [1, 2]
[5] pry(main)> p a[0,2]            # a[0] から 2 つの要素
[1, 2]
=> [1, 2]
[6] pry(main)> p a[0..-1]          # a[0] から a[-1] まで
[1, 2, 3, 4, 5]
=> [1, 2, 3, 4, 5]

以上、以下、未満

そう言えば、先日、「以上」、「以下」、「未満」を派手に混同して使っていて恥ずかしい思いをしたので、こちらもメモっておく。

  • 100 円以上であれば... 100 円を含む
  • 100 円以下であれば... 100 円を含む
  • 100 円未満であれば... 100 円を含まない

ついカッとなって Neustar のコマンドラインツールを作ってみたくさ

tl;dr

ついカッとなってシリーズ化したい。

そんなにカッとはなっていないけど、ギョームで利用している Neustar の Web UI がたまに重かったり、負荷試験の自動化なんかを視野にいれるとコマンドラインツールとかあると嬉しいようなあと資料を見ていたら、以下のように API が提供されていたので、この API を叩いて返ってくる結果をそのまま出力するだけの雑なコマンドラインツールを作ってみたくさ。


neustar とは

www.neustar.biz

Web サイトの負荷試験を行う SaaS サービス。Selenium WebDriver にも対応した負荷試験のシナリオは JavaScript で記述することが出来たり、負荷試験の結果は SQL を使って詳細な解析を行うことが出来る...が、日本では多分、かなりマイナー。


作ったもの

github

github.com

Gem でも配ってみるという暴挙。

何が出来ると?

  • シナリオスクリプトの一覧取得
  • シナリオスクリプトの Local Validate
  • シナリオスクリプトのアップロード
  • 負荷試験一覧の取得
  • 負荷試験のスケジューリング
  • 負荷試験の削除

詳しくは...

demo

  • 事前に...API キーと Shared Secret 及び Local Validator のパスを環境変数に指定
export NEUSTAR_API_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxx"
export NEUSTAR_SHARED_KEY="xxxxxxx"
export NEUSTAR_LOCAL_VALIDATOR_PATH="/path/to/local-validator-4.34.17/bin/validator"
var c = test.openHttpClient();
c.setFollowRedirects(false);
test.beginTransaction();
test.beginStep("Check Website");
c.get("http://kome.inokara.com/", 200);
test.endStep();
test.endTransaction();

script.js というファイル名で保存する。

bundle exec bin/npc-scripting val -f path/to/script.js

以下のように出力される。

Neustar Web Performance Script Validator 4.34.17
Copyright (c) Neustar Inc - All Rights Reserved.
VNC Support is NOT Available

INFO 07/16 02:36:13 b.n.w.a.s.JavaScrip~ - LITE mode starting up
INFO 07/16 02:36:13 b.n.w.a.s.JavaScrip~ - Starting script executor 0
INFO 07/16 02:36:13 b.n.w.a.a.Webmetric~ - Using DNS Server: [192.168.24.1]
INFO 07/16 02:36:13 b.n.w.a.s.JavaScrip~ - Script complete.
INFO 07/16 02:36:13 b.n.w.v.ValidationR~ - Saving validation logs to 'validation.txt'...
INFO 07/16 02:36:13 b.n.w.v.ValidationR~ - Saving Http Archive(HAR) to 'har.js'...
#
# -n : スクリプト名を指定
# -f : スクリプトファイルのパスを指定
# -t : タグを指定(複数指定する場合にはカンマで区切る)
# -d : スクリプトの詳細を指定
#
bundle exec bin/npc-scripting up -n demo01 -f path/to/script.js -t tag1,tag2 -d "this is sample"

以下のように出力される。

{"name":"demo01","scriptBody":"var c = test.openHttpClient();\nc.setFollowRedirects(false);\ntest.beginTransaction();\ntest.beginStep(\"Check Website\");\nc.get(\"http://kome.inokara.com/\", 200);\ntest.endStep();\ntest.endTransaction();\n","tags":["demo","test"],"description":"description"}
{"result":"OK","data":{"script":{"id":"1234567890xxxxxxxxxxxxxxxxxxxxxxxxxxx","accountId":"xxxxxxxxxxxxxxxxxxxxxxxxxx","name":"demo01","description":"description","scriptType":"VirtualUser","validationState":"VALIDATING","validationBypassed":false,"lastValidated":null,"lastValidationAttempted":"2016-07-16T02:39:42.544+0000","validationResults":null,"numRequests":0,"pageViews":0,"stepCount":0,"txTime":0,"hasScreenshot":false,"hasScreenVideo":false,"logFileAvailable":false,"harFileAvailable":false,"transactionFileAvailable":false,"maxBps":0,"created":"2016-07-16T02:39:39.195+0000","deleted":false,"versionId":"h9OBnizehhH89yVZkKDA2aKGPBvw05la","format":"JavaScript","scriptBody":"var c = test.openHttpClient();\nc.setFollowRedirects(false);\ntest.beginTransaction();\ntest.beginStep(\"Check Website\");\nc.get(\"http://kome.inokara.com/\", 200);\ntest.endStep();\ntest.endTransaction();\n","scriptUploaded":true,"screenshotUrl":null,"screenVideoUrl":null,"harFileUrl":null,"logFileUrl":null,"transactionFileUrl":null,"scriptExecutionTimeout":0,"versionHistory":[{"versionId":"h9OBnizehhH89yVZkKDA2aKGPBvw05la","modifiedByUsername":"xxxxx@xxxx.com","lastModified":"2016-07-16T02:39:42.513+0000","validated":false,"stepLabels":null,"validationBrowser":null,"validationQueue":null}],"tags":["test","demo"],"availableFormats":["JavaScript"],"maxBpsOverride":0,"maxTotalTimeOverride":0,"monitorCount":0,"loadTestCount":0,"updateMonitors":false,"regOptIn":false}}}
bundle exec bin/npc-scripting ls | jq '.data.items[]|{name,id}|select(contains({name:"demo"}))'

JSON のパースは jq におまかせ。以下のように出力される。

{
  "id": "1234567890xxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "name": "demo01"
}
  • 負荷試験定義ファイルを作成

負荷試験の定義は YAML ファイルで書くようにした。

# 負荷試験名を指定
name: "myloadtest"

# ソースとなるリージョンを指定
region: "AP_NORTHEAST"

# 試験で利用するシナリオスクリプトの ID と割合を指定
scripts:
  - percentage: 100
    scriptId: "1234567890xxxxxxxxxxxxxxxxxxxxxxxxxxx"

# ワークロード(という言い方が合っているか判らないけど)を指定(duration = 5 min / maxUsers = 10 / type = RAMP)
parts:
  - duration: 5
    maxUsers: 10
    type: "RAMP"

この定義ファイルを loadtest.yml という名前で保存しておく。

  • 負荷試験をスケジューリング
bundle exec bin/npc-loadtest sc -f loadtest.yml

以下のように出力される。

{"name":"myloadtest","region":"AP_NORTHEAST","scripts":[{"percentage":100,"scriptId":"1234567890xxxxxxxxxxxxxxxxxxxxxxxxxxx"}],"parts":[{"duration":5,"maxUsers":10,"type":"RAMP"}]}
{"data":{"loadTest":{"name":"myloadtest","id":275822,"state":"SCHEDULED","type":"VirtualUser","region":"AP_NORTHEAST","end":"2016-07-16T03:05:14.000+0000","parts":[{"type":"RAMP","duration":5,"maxUsers":10}],"accountId":"xxxxxxxxxxxxxxxxxxxxxxxx","start":"2016-07-16T03:00:14.000+0000","scripts":[{"percentage":100,"scriptId":"1234567890xxxxxxxxxxxxxxxxxxxxxxxxxxx"}],"overrideCode":null,"numTransactions":0,"numFailures":0,"launchedUsers":0,"privateUrl":"https://load.wpm.neustar.biz/load/test/275822","publicUrl":"https://load.wpm.neustar.biz/load/test/share/xxxxxxxxxxxxxxxxxxxxxxxxxxx","durationFormatted":"5 minutes","numScripts":1,"numParts":1}},"result":"OK"}

Nuestar の WebUI でも負荷試験がスケジューリングがされている。

f:id:inokara:20160716115609p:plain

  • 負荷試験一覧から任意の負荷試験の情報を取得する
bundle exec bin/npc-loadtest ls | jq '.data.items[]|{name,id,privateUrl,state,numTransactions}|select(.name=="myloadtest")'

以下のように出力される。

{
  "numTransactions": 102,
  "state": "RUNNING",
  "privateUrl": "https://load.wpm.neustar.biz/load/test/1234567",
  "id": 1234567,
  "name": "myloadtest"
}

privateUrl にアクセスすると以下のように試験が開始されている。

f:id:inokara:20160716120706p:plain

  • 任意の負荷試験の情報を取得する
 bundle exec bin/npc-loadtest get -i 123456 | jq '.data.loadTest|{name, state, numTransactions, numFailures}'

以下のように出力される。

{
  "numFailures": 0,
  "numTransactions": 16435,
  "state": "FINISHED",
  "name": "myloadtest"
}

最後に

自分以外は誰も使うことが無いであろう...

ちなみに、Thor というコマンドラインツールが簡単に使える Gem を多分初めて利用してみたけど、とても簡単にコマンドラインツールが作れることに感動した。

2016 年 07 月 10 月(日)

tl;dr

参議院議員選挙だった。

  • vim の snippet について勉強
  • ゴルフ中継の煽りをうけてガンダムとジューオージャーは休止、仮面ライダーゴーストだけ見る
  • 車の掃除
  • ジョギングシューズを新調したのでウキウキウォッチングで走ってきた、いい感じ

  • どん兵衛とおにぎりでランチ
  • Docker のストレージドライバを devicemapper から overlayfs に変えたらコンテナの起動が早くてビビったのでブログにしたい

  • ソファで寝落ち
  • neustar の Scripting API と Load Testing API について勉強、Ruby で簡単なサンプルを作って遊ぶ

2016 年 07 月 05 月(火)

tl;dr

福岡マラソンの抽選に落ちた。出場は絶望的。

  • 暑いを通り越して熱い
  • ひとっ走りしてきた

  • 洗濯物の乾きがとても良い(夏の醍醐味)

夕方

  • 一日中エアコンの中で過ごした

夏は始まったばかり。

2016 年 07 月 03 月(日)

tl;dr

うっかりしていたら 7 月になっていた。

そういうことなのかと納得。

  • 暑くならないうちにジョギングに行ったけど暑かった

  • 遅い朝ごはんを食べる
  • 朝ごはん後、本を読もうとソファーに横になったら stop インスタンス(昼寝)してた
  • 覚醒してジョギングシューズを買いに行くが、在庫が無かったので取り寄せ
  • イオンモール香椎浜に車で向かう途中、道路を逆走してコンビニに入っていく BMW が怖かった
  • イオンモール香椎浜で 31 アイスクリームを食べる(ダブルを注文したらトリプルというサービスを享受)

  • ハッカソン的なイベントに参加予定なので、一緒に参加するチームメンバーと会話
  • ソファーでダラダラ

  • 福岡で車を運転する際はホントに気をつけた方が良い

Infrataster の DNS プラグインメモ

tl;dr

加齢と共に目視チェックが辛くなってきた年寄りインフラエンジニアには Infrataster がうってつけだと思って、Infrataster の DNS プラグインを使ってみたのでメモ。


Infrataster と Infrataster の DNS プラグイン


memo

試した環境

% sw_vers
ProductName:    Mac OS X
ProductVersion: 10.11.6
BuildVersion:   15G19a

% bundle exec gem list | grep infrataster
infrataster (0.3.2)
infrataster-plugin-dns (0.0.2)

準備

こちらを参考にさせて頂いて準備。

  • Gemfile
source 'https://rubygems.org'
gem 'infrataster-plugin-dns'
  • bundle install
bundle install --path vendor/bundle
  • spec/spec_helper.rb
require "infrataster/rspec"
require "infrataster-plugin-dns"

Infrataster::Server.define(
  :dns01,
  "8.8.8.8"
)

Infrataster::Server.define(
  :dns02,
  "8.8.4.4"
)

spec ファイル

  • spec/inokara-com_spec.rb
require "spec_helper"

%w(dns01 dns02).each do |dns|

  # こんな書き方するのが正しいのか判らないけど
  describe server(dns.to_sym) do
    describe dns("inokara.com") do
      it { is_expected.to have_dns.with_type("NS").and_domainname(/dns.ne.jp/) }
    end

    %w(
      kome.inokara.com
    ).each do |domain|
      describe dns(domain) do
        it { is_expected.to have_entry.with_type("CNAME").and_domainname(/s3-website-ap-northeast-1/) }
      end
    end
  end

end
  • spec/test-inokara-com_spec.rb
require "spec_helper"

%w(dns01 dns02).each do |dns|

  # こんな書き方するのが正しいのか判らないけど
  describe server(dns.to_sym) do
    describe dns("test.inokara.com") do
      it { is_expected.to have_dns.with_type("NS").and_domainname(/awsdns/) }
    end
 
    %w(
      pm25.test.inokara.com
    ).each do |domain|
      describe dns(domain) do
        it { is_expected.to have_entry.with_type("A").and_address(/54.231/) }
      end
    end
  end

end

テスト

  • run
bundle exec rspec spec
  • output
server 'dns01'
  dns 'inokara.com'
    should have the correct dns entries with {:type=>"NS", :domainname=>/dns.ne.jp/}
  dns 'kome.inokara.com'
    should have the correct dns entries with {:type=>"CNAME", :domainname=>/s3-website-ap-northeast-1/}

server 'dns02'
  dns 'inokara.com'
    should have the correct dns entries with {:type=>"NS", :domainname=>/dns.ne.jp/}
  dns 'kome.inokara.com'
    should have the correct dns entries with {:type=>"CNAME", :domainname=>/s3-website-ap-northeast-1/}

server 'dns01'
  dns 'test.inokara.com'
    should have the correct dns entries with {:type=>"NS", :domainname=>/awsdns/}
  dns 'pm25.test.inokara.com'
    should have the correct dns entries with {:type=>"A", :address=>/54.231/}

server 'dns02'
  dns 'test.inokara.com'
    should have the correct dns entries with {:type=>"NS", :domainname=>/awsdns/}
  dns 'pm25.test.inokara.com'
    should have the correct dns entries with {:type=>"A", :address=>/54.231/}

Finished in 0.59681 seconds (files took 1.07 seconds to load)
8 examples, 0 failures

いい感じ。


ということで

DNS 移行時際のテスト等に非常に有効だと思う。また、プロジェクト終盤に疲弊した状態にはこのような(シェルスクリプトだってイイと思う)機械的な確認の方が安全なのは言うまでも無い。特に自分のような年寄りが関わっている場合にはなおさら。

素敵なインフラテストライフを。

Jenkins CLI で Jenkins プラグインをインストールしたメモ

tl;dr

Jenkins の練習していたら CLI で操作出来るとのことなので、Jenkins プラグインCLI 利用してインストールしてみたメモ。


メモ

試した環境

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 14.04.3 LTS
Release:        14.04
Codename:       trusty

$ java -jar jenkins-cli.jar -s http://localhost:8080 version                                                                                                               
1.651.3

参考

CLI をダウンロード

wget http://localhost:8080/jnlpJars/jenkins-cli.jar

ヘルプ

java -jar jenkins-cli.jar -s http://localhost:8080 help

以下のように出力される。

  add-job-to-view
    Adds jobs to view.
  build
    Builds a job, and optionally waits until its completion.
  cancel-quiet-down
    Cancel the effect of the "quiet-down" command.
  clear-queue
    Clears the build queue.
  connect-node
    Reconnect to a node.
  console
    Retrieves console output of a build.
  copy-job
    Copies a job.

(snip)

  update-view
    Updates the view definition XML from stdin. The opposite of the get-view command.
  version
    Outputs the current version.
  wait-node-offline
    Wait for a node to become offline.
  wait-node-online
    Wait for a node to become online.
  who-am-i
    Reports your credential and permissions.

前後してしまうが、CLI は以下のように実行する。

java -jar jenkins-cli.jar [-s JENKINS_URL] command [options...] [arguments...]

プラグインのインストール

インストールしたいプラグイン

以下のように実行する。

java -jar jenkins-cli.jar -s http://localhost:8080 install-plugin github
java -jar jenkins-cli.jar -s http://localhost:8080 install-plugin build-pipeline-plugin
java -jar jenkins-cli.jar -s http://localhost:8080 install-plugin docker-build-publish

尚、引数として指定するプラグインの名前は Plugins ページから辿れる個々のプラグインページで確認するプラグイン ID を指定する。

f:id:inokara:20160702085300p:plain

プラグインのインストール後は Jenkins プロセスを再起動して設定を反映させる。

プラグインで何が出来そうか

適当に利用出来るオプションを叩いてみた。

  • バージョンを確認
$ java -jar jenkins-cli.jar -s http://localhost:8080 version
1.651.3
  • ジョブの一覧を取得
$ java -jar jenkins-cli.jar -s http://localhost:8080 list-jobs
Docker_Build_Push
Serverspec_Handson
  • ジョブの詳細を取得
$ java -jar jenkins-cli.jar -s http://localhost:8080 get-job Docker_Build_Push 

以下のように出力される。

<?xml version='1.0' encoding='UTF-8'?>
<project>
  <actions/>
  <description></description>
  <keepDependencies>false</keepDependencies>
  <properties/>
  <scm class="hudson.scm.NullSCM"/>
  <canRoam>true</canRoam>
  <disabled>false</disabled>
  <blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
  <blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
  <triggers/>
  <concurrentBuild>false</concurrentBuild>
  <builders>

(snip)

  </builders>
  <publishers/>
  <buildWrappers/>
</project>
  • Jenkins の再起動
$ java -jar jenkins-cli.jar -s http://localhost:8080 restart

セキュアにアクセス

あくまでも試してみた感じだと Jenkins CLI でセキュアに Jenkins にアクセスしたい場合には以下を設定したほうが良さそう。

  • セキュリティを有効化(グローバルセキュリティの設定)
  • アクセス制御で「ユーザー情報」を環境に応じて設定(今回は「Jenkins のユーザーデータベース」を選択した)
  • 同じくアクセス制御の「権限管理」において「ログイン済みユーザーに許可」を選択

尚、上記の設定を行った場合、Jenkins のジョブの詳細(get-job コマンド)等は以下のように利用出来なくなる。

$ java -jar jenkins-cli.jar -s http://localhost:8080 get-job Docker_Build_Push

ERROR: anonymous is missing the Job/ExtendedRead permission

これを解決するには Jenkins に Jenkins CLI を実行するユーザーの公開鍵を Jenkins 上のユーザーに登録することで利用出来るようになる。

f:id:inokara:20160702085019p:plain

上記を設定した後に get-job コマンドを実行すると以下のようにジョブの詳細を確認することが出来る。

$ java -jar jenkins-cli.jar -s http://localhost:8080 get-job Docker_Build_Push
<?xml version='1.0' encoding='UTF-8'?>
<project>
  <actions/>
  <description></description>
  <keepDependencies>false</keepDependencies>
  <properties/>
  <scm class="hudson.scm.NullSCM"/>
  <canRoam>true</canRoam>
  <disabled>false</disabled>
  <blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
  <blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
  <triggers/>
  <concurrentBuild>false</concurrentBuild>
  <builders>

(snip)

  </builders>
  <publishers/>
  <buildWrappers/>
</project>

以上

素敵な Jenkins ライフをお送り下さいmm