Hatena::ブログ(Diary)

lambda {|diary| lambda { diary.succ! } }.call(hatena) このページをアンテナに追加 RSSフィード

引っ越しました
 

2013-11-24

[][] drone.io+VagrantRuby 2.0.0のrpmを自動作成するようにしてみた

Amazon Linuxを起動したら、だいたい一番最初にRuby 2.0.0のビルドを始めるのだけれど、まいどまいど同じことをやっているのでrpmを自動作成するようにしてみた。

https://github.com/winebarrel/ruby-2.0.0-rpm


Ruby 2.0.0のspecファイル公開している人がいたので、そこからフォーク

drone.ioの中身はUbuntuなので、VagrantからEC2インスタンスを起動してそこでrpmを作成するようにした。

できあがったrpmはS3にアップロード。


所感

  • sshで少しはまったが動くは動いた。他の用途にも応用できそうな気がする。server specとかPackerとか。
    • vagrant destroyがうまく動かず…。仕方ないので terminate on shutdownを有効にしてビルド完了後にTerminateするようにした
  • build timeout 15分がきつい。Travis CIは何分なんだろう?
  • s3cmdのインストール(from EPEL)でたまに固まる
  • クラシックでもVPCでも特に意識せずvagrant sshは動いた
  • なんだかんだでインスタンスを起動しまくったので無駄に散財した気がする

2013-11-13

[] ruby-jq 0.1.0

libjqが簡単に使えたので、NokogiriっぽいRubyバインディング作りました

https://bitbucket.org/winebarrel/ruby-jq

JSONHTMLほど複雑ではないですが、ネストの深いデータを一発でとってこれるのは便利…かも知れないです。

以下はGitHub APIファイルパスだけ取得するサンプル。「.tree[].path」だけでとってこれます。

#!/usr/bin/env ruby
require 'net/http'
require 'jq'

https = Net::HTTP.new('api.github.com', 443)
https.use_ssl = true
https.verify_mode = OpenSSL::SSL::VERIFY_NONE

res = https.start do |w|
  w.get('/repos/rails/rails/git/trees/master?recursive=1')
end

JQ(res.body).search('.tree[].path') do |value|
  p value
end

jpのHEADのビルドについて

jqのHEADからビルドする場合、autoreconfから始める必要があって、少し手間でした。

Macの場合、とりあえずautomake、autoconf、libtool、bisonをイントールして、bisonにパス通して、「./configure --enable-shared」で共有ライブラリを作れました。makeの途中で、rakeによるドキュメント生成に失敗したりしましたが…。

また、他のマックで同様にビルドしようとしたところ「thread-local storage not supported for this target」のエラー。なので https://github.com/stedolan/jq/blob/master/jv_alloc.c#L14 から 「__thread」 を削除…


使えるかどうかわかりませんが、Macバイナリを添付しておきます。

libjq.tar.gz 直

2013-11-12

[] Cからjqを使う

jqのheadでlibjqが切り出されていたので、main.cを参考にしてCから呼び出してみた。

#include <stdio.h>
#include <string.h>
#include <jq.h>

static void process(jq_state *jq, jv value, int flags) {
  jq_start(jq, value, flags);
  jv result;

  while (jv_is_valid(result = jq_next(jq))) {
    jv dumped = jv_dump_string(result, 0);
    const char *str = jv_string_value(dumped);
    printf("%s\n", str);
  }

  jv_free(result);
}

int main() {
  jq_state *jq;
  int jq_flags = 0;

  jq = jq_init();

  if (jq == NULL) {
    perror("malloc");
    return 1;
  }

  char *program = ".[]";
  int compiled = jq_compile(jq, program);

  if (!compiled) {
    return 1;
  }

  struct jv_parser* parser = jv_parser_new();
  char buf[] = "[{\"FOO\":100},{\"BAR\":200}]";

  jv_parser_set_buf(parser, buf, strlen(buf), 0);

  jv value;

  while (jv_is_valid((value = jv_parser_next(parser)))) {
    process(jq, value, jq_flags);
  }

  if (jv_invalid_has_msg(jv_copy(value))) {
    jv msg = jv_invalid_get_msg(value);
    fprintf(stderr, "parse error: %s\n", jv_string_value(msg));
    jv_free(msg);
  } else {
    jv_free(value);
  }

  jv_parser_free(parser);
  jq_teardown(&jq);

  return 0;
}

~/work$ gcc -ljq test.c -o test
~/work$ ./test
{"FOO":100}
{"BAR":200}
~/work$

コンパイルエラー時にjq_teardownを呼び出さなくてよいのかが、若干気になる。

2013-11-05

[][] Piculet/Kelbimというツールを作りました

Piculet

https://bitbucket.org/winebarrel/piculet

Kelbim

https://bitbucket.org/winebarrel/kelbim


以前作成したRoadworkerと同様に、AWSの設定をRubyDSLで管理します。Piculetはセキュリティグループを、KelbimはELBを対象としています。

Piculetのほうはクラスメソッドさんのブログで紹介していただきました。ありがたいことです。


使い方とか

ホームページを読めばだいたい察しはつくかと思います。既存の設定をRuby DSLエクスポートして、DSLを編集して、AWSに適用して…という感じで運用します。

所謂、冪等性を確保しているので何回実行してもRuby DSLの記述通りにAWSが設定されます(DSLと設定が同じなら何もしません)

ついでに、dry runとか(Kelbimの方は)RSpecでのテストとかできます。


DSLは以下のような感じです。

Piculet
ec2 "vpc-XXXXXXXX" do
  security_group "default" do
    description "default VPC security group"

    ingress do
      permission :tcp, 22..22 do
        ip_ranges(
          "0.0.0.0/0",
        )
      end
      permission :any do
        groups(
          "any_other_group",
          "default"
        )
      end
    end

    egress do
      permission :any do
        ip_ranges(
          "0.0.0.0/0"
        )
      end
    end
  end
end
Kelbim
ec2 "vpc-XXXXXXXXX" do
  load_balancer "my-elb" do
    spec do
      url = URI.parse('http://www.example.com/')
      res = Net::HTTP.start(url.host, url.port) {|http| http.get(url.path) }
      expect(res).to be_a(Net::HTTPOK)
    end

    instances(
      "hastur",
      "cthulhu",
      "nyar",
    )

    listeners do
      listener [:http, 80] => [:http, 80] do
        app_cookie_stickiness "CookieName"=>"20"
      end
...

生い立ちとか

もともと別件でPuppetリポジトリを調べてたらpuppetlabs-dnsを見つけて「Puppet的に管理するのもありかー」*1と思って、でもシンタックスが気に入らなかったので夏頃からちまちま作り始めて、そうしてRoadworkerできたら他のもおんなじように管理すると便利そうだからと作り始めて…という感じです。

あとはIAMも同様に管理すると便利そうですね。誰か作ってください。


それCloudFormationで

CloudFormationはライフサイクルがおおむねテンプレートと一緒になってしまうのがにんともかんとも。そもそも某社ではCloudFormationを使ってないので。あとJSONがいまいちというのもありますね。無理矢理な関数とか。JavaScriptで記述できるようにすればいいのに。

既存の設定をエクスポートできて途中から設定を適用できてdry runがあってプログラマブルに設定を記述できていたら使っていたかもしれないです。


いろいろ


その他

次はCloudFormationのラッパーを書こうかと思ってます。Vagrantの複数台管理がめんどくさそうなので。*2。主に個人用途

だれかIAM管理ツールを作ってください。

*1Chefにも同様のがありますね https://github.com/hw-cookbooks/route53

*2:めんどくさくなかったらごめんなさい