Ansibleで複数行を追加する(blockinfile)

lineinfile

Ansibleでファイルに行を追記したり置換したりした場合、lineinfileを使うことが多いと思いますが、複数行追加したい場合だと、ちょっとやりずらいところがあります。

下記のように書くと、テキスト内に指定した行の内容がなければ末尾に追加されるので、それを繰り返すことによって末尾に複数行入れられます。

  tasks:
    - name: 末尾に複数行追加
      lineinfile:
        dest=./test.txt
        line={{ item }}
      with_items:
        - '1行目'
        - '2行目'

これが特定の箇所に入れようとすると面倒になります。
たとえば、insertafterを使って指定した行の後に入れようとして、下記のように書くと、、

  tasks:
    - name: 特定の場所に追加
      lineinfile:
        dest=./test.txt
        insertafter='^# xxxx'
        line={{ item }}
      with_items:
        - '1行目'
        - '2行目'

順番が逆に並ぶことになります。

# xxxxx
2行目
1行目

これは、insertafterにマッチした箇所の後に追加するといったことを単に2回繰り返しているためなので、

# xxxxx
1行目
# xxxxx
2行目
1行目

といった形で入っていくためです。

blockinfile

そもそもlineinfileは複数行を扱うのに向いていないので、複数行を扱えるモジュールのblockinfileを使うと良さそうです。

blockinfileは、extraモジュールに現在はあるように見える(GitHubのリポジトリには存在する)のですが、Ansibleのバージョンが古いとextraにいないので、その場合には ansible-galaxy でインストールします。(1.9.4 では入ってませんでした)

ansible-galaxy install yaegashi.blockinfile

blockinfileを使うと、contentに指定した内容をそのまま入れることができます。(rolesにansible-galaxyでインストールしたblockinfileのロールを指定する必要があります)

- hosts: all
  roles:
    - yaegashi.blockinfile
  tasks:
    - name: 特定の場所に追加
      blockinfile:
        dest: ./test.txt
        insertafter: '^# xxxx'
        content: |
          1行目
          2行目

内容の前後にmarkerで指定した内容が入ります。デフォルトだと下記のような感じです。

# xxxxx
# BEGIN ANSIBLE MANAGED BLOCK
1行目
2行目
# END ANSIBLE MANAGED BLOCK

markerの範囲を一つの内容として扱うので、中身を書き換えるのも結構楽です。 たとえば、先ほどのテキスト内容から、下記を実行すると、

tasks:
  - name: 特定の場所に追加
    blockinfile:
      dest: ./test.txt
      insertafter: '^# xxxx'
      content: |
        #1行目
        2行目

markerの範囲のものを置き換えてくれます。

# xxxxx
# BEGIN ANSIBLE MANAGED BLOCK
#1行目
2行目
# END ANSIBLE MANAGED BLOCK

後から追加した行の内容が変わる可能性があるならば、1行だったとしても、blockinfileを使った方がメンテナンスしやすいだろうなぁと思いました。

Easy Ganttを試してみた

以前見かけて試せてなかった Easy Gantt を試してみました。

Easy Ganntは、Easy Software Ltd. が提供するガントチャートのPluginで、有償版と無償版があります。

Easy Software Ltd. は、Easy Redmine として、いろいろ有用なPluginを有償で提供していて、Redmineのホスティングサービスも行っているようです。

インストール

Easy Ganttの動作環境は、Redmine3以上となっています。

Easy Ganttのサイト(Redmine Gantt Plugin - Easy Redmine)から、「Get Gantt Plugin for free」のリンクを押下して、メールアドレスなどの情報を入力します。

指定したアドレスに、ダウンロード先のリンクが記載したメールが届くので、そこからダウンロードしたプラグインをRedmineのpluginディレクトリに配置します。

unzip EasyGanttFree.zip
mv easy_gantt {RAILS_ROOT}/plugins

あとはRedmineを再起動すればインストール完了です。

設定

ログインしてみると、ヘッダに「Projects Gantt」というリンクが見えるので、クリックしてみると、REST API有効にして!といったメッセージが表示されるので、

f:id:onozaty:20160214170506p:plain

REST APIを有効にします。

f:id:onozaty:20160214170627p:plain

この状態でヘッダのリンクをクリックすると、画面が開きましたが、どうやらFree版だと、全プロジェクトをまたいだガントチャートは使えないようです。

f:id:onozaty:20160214170912p:plain

じゃあ、プロジェクト毎のページのガントチャートを見ようということで、プロジェクトの設定で、使用するモジュールとしてEasy ganttにチェックします。

f:id:onozaty:20160214171444p:plain

これでEasy Ganttが開けました。最初はサンプルが表示されていて、「Close this window and load real project data」ってリンクを押すと、実際のデータが表示されます。

f:id:onozaty:20160214223026p:plain

画面に見えている「新しく作成」(チケット/バージョン作成)、「Resource management」、「Critical path」、「Baselines」といった機能は、無償版では使えません。

無償版で行えることは、表示項目の選択、マウス操作による期間、進捗率の変更と、チケットの前後関係設定くらいですが、それでも十分役に立つプラグインだと思いました。

Redmine未読ニュース通知プラグインを試してみた

Redmineのニュースを使って、手軽に周知事項を流せないかなぁと思ったのですが、既読管理ができないため、自分が未読の情報があるのか判断しずらいです。

そこで、既読管理ができるプラグインを探したところ、ちょうど良さそうなものが見つかりました。

インストール

手元の環境(Redmine 3.2)に入れてみましたが、そのままだと入りませんでした。

[root@localhost plugins]# git clone https://github.com/georz/redmine_news_notification.git
[root@localhost plugins]# rake redmine:plugins:migrate RAILS_ENV=production
(in /var/lib/redmine)
/var/lib/redmine/vendor/bundle/ruby/2.2.0/gems/htmlentities-4.3.1/lib/htmlentities/mappings/expanded.rb:465: warning: duplicated key at line 466 ignored: "inodot"
An error occurred while loading the routes definition of redmine_news_notification plugin (/var/lib/redmine/plugins/redmine_news_notification/config/routes.rb): You should not use the `match` method in your router without specifying an HTTP method.
If you want to expose your action to both GET and POST, add `via: [:get, :post]` option.
If you want to expose your action to GET, use `get` in the router:
  Instead of: match "controller#action"
  Do: get "controller#action".

routes.rb でエラーが起きました。
Rails4だとoptionなしのmatchが使えないようですので、明示的にgetを指定するように変えました。

[root@localhost redmine_news_notification]# git diff
diff --git a/config/routes.rb b/config/routes.rb
index efa9320..07ccb56 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,5 +1,5 @@
 # Plugin's routes
 # See: http://guides.rubyonrails.org/routing.html
 Rails.application.routes.draw do
-  match 'news_notifications/:action', :to => 'news_notifications'
+  get 'news_notifications/:action', :to => 'news_notifications'
 end

これで無事インストールができました。

動作

動作としてはシンプルで、未読のニュースがあった場合に、ヘッダ部分に表示されます。

f:id:onozaty:20160207012156p:plain

クリックすると、ニュースの概要が表示されます。

f:id:onozaty:20160207012245p:plain

とてもいい感じです。

なんでメール通知使わないの?

新規ニュースはRedmineのメール通知でも飛ばせます。ただ、Redmineを頻繁に見ながら作業している状況で、メールに通知されるのって、ちょっと遠回りをしている気がしてなりません。
また、メールはそれ以外の情報も大量に流れ込んできて、Redmineの通知が埋もれやすいので、なるべくRedmineの情報はRedmine上で通知が出来ればよいなぁと個人的には思っています。(今回のような仕組みはニュース以外にもあっても良いなぁと思っています)

ちなみにメール通知がベストなのかどうかは、通知が飛ぶ量だったり、メールでどんな情報が流れているのかといったところによっても変わってくるものですので、プロジェクトによって全然異なるかと思います。

CentOS7にIRCサーバ(ngIRCd) をインストールする

CentOS 7 で IRCサーバ立てようとして、今まで使ったことのあった ircd-hybrid を入れようとしたところ、yumのリポジトリから無くなってました。(たしか6の時はあったかと)

ソースから入れるのも面倒なので、他にないのかなぁとさがしていたら、 ngIRCd がありました。

ということで、CentOS7での ngIRCd のインストールメモです。

インストール方法

ngIRCdはEPELリポジトリにて公開されていますので、yumのリポジトリとしてEPELを追加し、ngIRCdをインストールします。

[root@localhost ~]# yum install -y epel-release
[root@localhost ~]# yum install -y ngircd

ngIRCdの設定ファイル(/etc/ngircd.conf)のListenの行をコメントアウトします。(コメントアウトすることで、デフォルトの0.0.0.0となり、すべてのIPアドレスに対してlistenします)

;Listen = 127.0.0.1

あとは、ngIRCdをサービスに登録し、起動するだけです。

[root@localhost ~]# systemctl enable ngircd.service
[root@localhost ~]# systemctl start ngircd.service

適当なチャットクライアント(LimeChatなど)から、該当サーバに対して接続できることが確認できればOKです。(ポートは6667)

パスワードなどを設定したい場合には、/etc/ngircd.conf を触ることになります。 ircd-hybridの設定ファイルより簡単そうです。

Redmineのチケット一覧を右クリックで表示されるコンテキストメニューを調整する(View customize plugin)

確かにカスタムフィールドが多かったりすると、サブメニューが画面に収まらなくて、とても選択しづらくなります。

なぜこういったことがおこるかというと、コンテキストメニューを表示する際に、選択位置を起点として、

  • 下方向に表示して、画面上で収まれば下方向に表示
  • おさまらなければ、上方向に表示

としているようで、ここで決定した方式をサブメニューにも適用しているため、サブメニューが画面からはみ出す可能性が高くなってしまっています。上へ上へ/下へ下へと伸びててしまうイメージです。

サブメニュー表示の際に、画面から切れない位置に都度調整すればよいのですが、それはそれで実装が面倒なので、CSSで調整することによって切れる可能性を減らせないかと考えてみました。

調整方法

上へ上へと延びてしまうのが切れてしまう要因なので、上方向にコンテキストメニューを表示した際には、サブメニューは下方向にしてみます。

結構良い感じになった気がします。

あと、サブメニューで出す項目数が多いと、どうしても切れてしまいかねないので、サブメニューで表示する項目の高さの上限を設定し、それ以上の場合はスクロールバーを出すようにします。

全てのシチュエーションで切れずに選択可能とはならないかもしれませんが、かなり操作しやすくなったのではと思います。

設定内容

今回の調整を、View customize plugin使って実現してみます。

Path pattern

対象のパスはチケット一覧となります。

/issues$

Code

Type:StyleSheetとして下記を設定します。

/* 上方向に表示している時でも、サブメニューは下方向へ */
#context-menu.reverse-y > ul > li.folder > ul {
    top: 0;
    bottom: auto;
}

/* サブメニューの高さを固定にして、スクロールを出すように */
#context-menu > ul > li.folder > ul {
    max-height: 200px;
    overflow-y: auto;
}

Redmineのカスタムフィールド:ユーザで、自分自身を選択しやすくする(View customize plugin)

担当者のプルダウンだと、「<<自分>>」といった選択肢が先頭に表示されて、自分自身の選択がしやすくなっているのですが、カスタムフィールドで書式をユーザとしたときは、同じくユーザを選択するプルダウンでも、そういった選択肢が出てきません。

f:id:onozaty:20160117021815p:plain

ちょっと不便ですよね!

ということで、担当者と同じような選択ができるように、View customize pluginにて対応してみました。
View customize plugin自体の説明は下記をご参照ください。

設定内容

Path pattern

/issues/

Code

Type:JavaScriptとして下記を設定します。
カスタムフィールドでユーザとなっているものを探し出して、その中に自分のIDがあれば、「<<自分>>」という選択肢を空欄の後に追加しています。

$(function() {
  var userUrl = $("div#loggedas a").attr("href");
  var userId = userUrl.substr(userUrl.lastIndexOf('/') + 1);

  // ユーザ一覧のカスタムフィールドを取得
  $('select.user_cf').each(function() {
    // 自分自身の選択肢を取得
    var meOption = $(this).find('option[value="' + userId + '"]').first();

    // 複製し、空項目の次に名前を変えて挿入
    meOption.clone()
      .removeAttr('selected')
      .insertAfter($(this).find('option[value=""]'))
      .text('<<自分>>');
  });
})

設定後のイメージ

f:id:onozaty:20160117022519p:plain

便利になりました。

XML Explorer - 軽量なXMLビューア

大きなXMLファイルでも問題なく表示できそうなXMLビューアということで、下記を見つけました。

http://download-codeplex.sec.s-msft.com/Download?ProjectName=xmlexplorer&DownloadId=109515

XML Explorer is an extremely fast, lightweight XML file viewer. It can handle extremely large XML files. It has been tested on files as big as 300MB. It allows fast viewing and exploration, copying of formatted XML data, evaluation of XPath expressions, and XSD schema validation.

検索はXPathを使うことになるので、プログラマ向けかもしれませんが、、逆にXPathの検証にも使えるので便利だなぁと思いました。

ただ、DTDの検証に失敗すると、エラーとなってXML自体を表示できないので、DTD宣言しているXMLは要注意です。

f:id:onozaty:20160117013104p:plain

で、ちょっとこれは使いずらいときがあるなぁと思って、OSSなのでソースを見て直して使おうかとおもったところ、最新だと直ってました。

ということで、最新のソース落としてビルドしたものだと、下記のような感じで、エラーではなく警告扱いになります。

f:id:onozaty:20160117013248p:plain

お気に入りのXMLビューアとなりました。