git-gsubがライフチェンジングだったのでgit-gsub-filesを作った

Gitで何かの仕方を検索していて、いまさらながら git-gsub を知りました。

fujimura.hatenablog.com

gemとして公開されており、カジュアルにインストールできてめちゃくちゃ便利です。

となると気になるのが git-rename 。おそらく想像するにファイル名の便利置換コマンド。ファイル名の置換もよくあるので、こちらも是非使いたいなと思いました。

が、gemとして公開されていなかったので、git-gsub を参考に git-gsub-files を作ってみました。

github.com

簡単にいうと、Gitで管理されているファイルのリネーム( mv )を gsub ライクにするためのGitサブコマンドです。

インストール

$ git install git-gsub-files

使い方

Gitの管理下のファイルに対して、ファイル名をgsubライクに置換して mv します。 置換対象はファイル名だけでディレクトリ名には影響しません。

$ git gsub-files READ WRITE
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)

deleted:    README.md

Untracked files:
(use "git add <file>..." to include in what will be committed)

WRITEME.md

no changes added to commit (use "git add" and/or "git commit -a")

せっかくGitなので、mv ではなくて git mv したいこともあります。そのときは --add オプションを使います。

$ git gsub-files READ WRITE --add
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)

renamed:    README.md -> WRITEME.md

no changes added to commit (use "git add" and/or "git commit -a")

と、ここまで作って本家が公開されていました。。。

想像していた動きとは少し違っていたので、まあgit-gsub-filesを作った意味はあったかもです。

Thor人間だったのに、Thor使わないでコマンド作ったり、Rspecの書き方を git-gsub のテストを見ながら学んだり、俺得でした。

最後に

git-gsubという便利コマンドを公開してくださった fujimura さんありがとうございます!

最近のawspec活動 その2

v0.27.1になりました


Evolution of awspec (Gource Visualization)

リソースタイプを増やした

現在23個になっています。もう少し増やしたい。けどユースケースを考えながら追加するので、なかなか増えない。。。

AWS Advent Calendar 2015に参加した

qiita.com

awspec generate という便利コマンドの実践的紹介です。

Fukuoka.rbの成果をリリースした

具体的な成果

実際に何を追加したかというと、aws-sdk-rubyAws::Resources::Resource を継承している Aws::EC2::Instance などを its() {} などで呼び出せるようにしました。

これが追加されたことで、aws-sdk-ruby を知っていれば、awspecでマッチャーが作られていないような細かい箇所についてのテストが書けるようになります。

例えばこんな感じで、

describe s3_bucket('my-bucket') do
  its('acl.owner.display_name') { should eq 'my-bucket-owner' }
end

describe vpc('my-vpc') do
  its('instances.count') { should eq 3 }
end

ただ、そのままだと

describe vpc('my-vpc') do
  its('instances.batch_terminate!') { should eq '' }
end

とかで、「テスティングフレームワークなのに、なぜか対象リソースを潰してしまう」という狂気が実行できてしまうので、 Awspec::ResourceReaderAws::Resources::Resource なオブジェクトをラップして雑なブラックリストで判定しています。(まだ抜けはありそう)

最初はホワイトリストを検討したのですが、あまりに列挙すべきメソッドが多く、また規則性がなかったので、 @udzura さんと話して、「(まあ)ブラックリストで」という感じで実装しています。

このアドバンスドな機能は、こちら の "Advanced use" の項目があるリソースタイプで利用可能です。

ロゴを作った

f:id:k1LoW:20151217231631p:plain

自分で描いたらこんな感じになりました。

今後

実務でもどんどん投入されているので、地道に開発継続していきます。

Fukuoka.rbでエクストリームフィッシュボールをして、エクストリームな体験をした #fukuokarb

成果です。

github.com

ひょんなことから @udzuraさんとペアプロをする機会を得たのですが、成果は出るわ勉強になるわで最高体験でした。教えてもらうことが久しぶりで新鮮過ぎて

な感じでした。

awspecに追加された強力な実装についてはまたいつか紹介するとして、とりあえずいろいろメモを記録。

あ、

メタプロRuby早く読んだほうがいい」と10回以上言われました。

まずは実装の方針について検討・共有

いきなりソースコードに向かうと思ったらそうではなかったです。

2時間のうち、1時間くらいは設計の話だったような気がします。SDKのドキュメントと、awspecのソースを表示しつつ、方針を決めました。

で、決まった今回の実装方針はこちら。

f:id:k1LoW:20151211185231p:plain

とてもわかりやすい!

特に緑でウニョウニョしている部分( ResponceReader )が今回の実装のポイントです!(本人たちは議論しながらなのでばっちり)

respond_to がわからないなんてちょっと。。。」

respond_to がぱっとでてきませんでした。これがレベル低いのかどうかすらわからないレベル。ちょっと能力差がありすぎました。 (ちなみに使っていました。。。)

Rubyに馴染んでいないのがまるわかり。

「メモ化してください」「え?」

def resource
  @resource ||= Awspec::ResourceReader.new(Aws::S3::Bucket.new(@id))
end

||= の部分ですね。まず「メモ化」の言葉の意味が出てこなかった(そういう言葉があるのは知っていた)です。

その後、説明をしてもらうとすんなり理解。シングルトンとの違いもすっきり。

テストは実装方針にしたがって順番に

今回は最終的に

describe s3_bucket('my-bucket') do
  its('acl.owner.display_name') { should eq 'my-bucket-owner' }
end

のテストが通れば完成なので、自分はついつい上のテストが通ることを急ぎがちなのですが、 @udzuraさんはしっかりと、「順を追って」「まずは」といいながら

describe s3_bucket('my-bucket') do
  its(:real_resource) { should be_an_instance_of(Awspec::ResourceReader) } # まずは直接アクセスしてインスタンスを確認
  its('real_resource.name') { should eq 'my-bucket' } # アトリビュートがStringの場合
  its('real_resource.acl') { should be_an_instance_of(Awspec::ResourceReader) } # アトリビュートがAws::Resources::Resourceの場合
  it 'should be a Exception when black list method is called' do # ブラックリストなメソッドを呼んだ場合
    expect { subject.delete }.to raise_error(
      Awspec::BlackListForwardable::CalledMethodInBlackList,
      'Method call :delete is black-listed'
    )
  end
  its(:acl) { should be_an_kind_of(Awspec::ResourceReader) } # 最終形態でのアクセス方法でインスタンスを確認
end

と、実装を進めながら順にテストを追加していきました。

今回は特に基盤となる部分の機能追加でもあるので、「あーね!あーね!」と言いながら関心していたら「博多..」と言われました。

正しい値を知るために、テストREDの結果を利用する

自分はstubの値を知っているので、

describe s3_bucket('my-bucket') do
  its('acl.owner.display_name') { should eq 'my-bucket-owner' }
end

とすぐ書いてしまうのですが、そこをあえて

describe s3_bucket('my-bucket') do
  its('acl.owner.display_name') { should eq '' }
end

と書いて、一旦テスト結果をREDにし、さらにテスト結果から my-bucket-owner というstubの値を知るということをしていました。

というかテストを書くとき、必ず結果をREDにするところからスタートしているのが、慣れているなーと思いました。 (ちょっとだけTDD?)

bin/console bin/setup と exe/ ディレクトリ とpry

@udzura さんに「あれ?」と言われて知った事実。

github.com

ちなみに bundle gem で生成されたのは覚えているのですが「なんだこれ、知らんわ」と消していました。。。

あと「pryがないなんて耐えられないんで。。。」とpryが追加されました。

対話インターフェースで確認する習慣がないです。。。どうやったらそういう習慣になるんだろう。

こちら修正しました

感想

  • 教えてもらうのがめちゃくちゃ楽しい。最高体験。
  • Ruby力足りない。でもそれが楽しい。最高体験。
  • 他の人のコーディングを見るだけで勉強になる。最高体験。
  • Emacs。最高。

また、是非やりたいです!

そんな豪華な体験ができる勉強会がFukuoka.rbです。みんなも来たほうが良いと思いました。

以上成果報告でした!

Fukuoka.rbでawspecを対象にペアプロをしてもらえることになったので、やりたいことを書いておく #fukuokarb

SlackのチャンネルでRubyの質問(というか悩みを相談)をしていたら、緊張ヤバいことにありがたいことに今日のFukuoka.rbで @udzura さんとペアプロをすることになりました。

もともとは自分の疑問をSlackチャンネルでうまく伝えられなかったことが発端だったので、先にやりたいことを書いておこうと思います。日本語がダメで伝わらないかもしれませんが。。。

やりたいことその1: awspec でテストできる範囲を劇的に増やしたい

もともとのアイデアはこちら↓

awspecでテストできる内容はaws-sdk-rubyを素で使ったテストよりも(当然)少ないです。

しかし、↑のアイデアをうまく実装できれば、awspec(のits() {} )で、(aws-sdk-rubyを理解していれば)かなり柔軟に多くの範囲のテストができるようになります。しかも、awspecの見た目のシンプルさはそのまま。

ところが、↑を単純に実装すると、

となるので、うまく解決して実装したいです。

やりたいことその2: リファクタリングをして lib/awpec/helper/finder/ の中をすっきりしたい

awspec/lib/awspec/helper/finder at master · k1LoW/awspec · GitHub

こんなものなのかどうかわからず。。。

やりたいことその3: 何かナレッジを

得られるようにがんばります!

緊張ヤバい…init.el整理したい…

aws-sdk-rubyで `*.example.com` なレコードを取得すると `\052.example.com` になる

某プロジェクトで awspec generate route53 example.com. を実行したのですが、なぜか

describe route53_hosted_zone('example.com.') do
  it { should have_record_set('\052.example.com.').cname('example.com') }
end

なspecが生成されて、「\052???」と調べ始めたのが最初。

端的にいうと、aws-sdk-ruby*.example.com なレコードを、Aws::Route53::Client#list_resource_record_setsで取得すると \052.example.com な文字列になる状況です。

で、@udzura さんと @nagachika さんという豪華布陣にも見てもらいつつ調べた結果が、

AWSAPIのレスポンス自体が\052.example.comになっているかも

という残念なことに。。。

AWS CLIでも

$ aws route53 list-resource-record-sets --hosted-zone-id AB1234CDEFGHIJ --profile xxx

...
{
    "ResourceRecords": [
        {
            "Value": "example.com"
        }
    ],
    "Type": "CNAME",
    "Name": "\\052.example.com.",
    "TTL": 300
 },
...

という。。。

というわけで

対応しました

route53_hosted_zone support `*` and `\052` as wildcard record by k1LoW · Pull Request #76 · k1LoW/awspec · GitHub

Fix wildcard record format when `terraforming r53r` by k1LoW · Pull Request #139 · dtan4/terraforming · GitHub

こちらで直接お礼を言おうと思います

fukuokarb.doorkeeper.jp

TechTouchを久しぶりに開催します

最近、「Fusicよく勉強会やっているよね」というお話をよく聞きます。

Fusic Co.,Ltd. | Doorkeeper

事実さまざまな勉強会や報告会やセミナーが開催されているのですが、実は最近自分が主催しているものがありません。

それには、ひとりでもくもくやって満足したり、社内で読書会があっていい知見になってたり、Fukuoka.rb が面白かったり、といろいろ言い訳じみた理由はあるのですが、なんか悔しいのでTechTouchを久しぶりに開催してみます。

techtouch.doorkeeper.jp

(Fusicのマーケチームの勢いすごい。エンジニアも負けないようにしないと!)

TechTouch is 何

おそらく古くは codecheck.in 時代(多分もう知らない人ばかり。フクオカネタです)まで遡る雑多な勉強会です。地方だと単一のテーマだといろいろ厳しいから始まったような気がしています。(もう覚えていない)

d.hatena.ne.jp

最初は輪講で、それが失敗してテーマを設定したもくもく会になって、それも微妙で、最終的にただのもくもく会になったようです。(忘れてた)

AWS的な何かをさわろうと思います。

今回自分はAWSな感じで、

  • awspecの拡張
  • AWS Lambdaでメール送信とかSSH接続とか
  • Terraform(Terraformかkumogataか迷っているんですよねー)

らへんを触ってみようかな、と。

Fukuoka.rbでできない内容がいいかなと思っています。

あと今回は、社内でやっているSwiftもくもく会もTechTouch内で開催されるらしいです。

なんでもいいのです。ただのもくもく会ですから。

エンジニアが集まるだけで面白い。

というわけで

福岡の皆さんお気軽にどうぞ。

techtouch.doorkeeper.jp(再掲)

awspecがShared Credentialsに対応しました

awspecがShared Credentialsに対応しました。

Release v0.19.0 · k1LoW/awspec · GitHub

Shared Credentialsとは

aws-cliでよく使う ~/.aws/credentials のことです。

Shared Credentialsのprofile対応

もともとawspecで利用しているaws-sdk-rubyはShared Credentialsのdefaultを自動で読むようになっていたのですが、profileごとのShared Credentialsも指定できるようにしました。ついでに ~/.aws/config の設定も読むようにしたので、

$ aws configure --profile myprofile
AWS Access Key ID [None]: 
AWS Secret Access Key [None]: 
Default region name [None]:
Default output format [None]: 

と設定したあとで、

$ export AWS_PROFILE=myprofile; bundle exec rake spec

とか

$ awspec generate ec2 vpc-ab123cde --profile myprofile

とか、わざわざawspec用にsecrets.ymlを作成することなく実行できるようになりました。 (secrets.ymlも今までどおり利用できます)

awspecのテスト事情

awspec自体のテストはaws-sdk-rubyが提供するstubを利用して書いていますが(かなり優秀です!)、実は新しいResource Typeを実装する時などには、自分のAWSアカウントで必要なAWSリソース構成を作成し、実際にAWSにリクエストを投げて確認をしていたりします。

そういったときにsecrets.ymlが面倒だなーと思っていたので、awspecをつかう人はもっと面倒なのでは?と思い、aws-cliと同じように --profile が利用できるようにした次第です。

というわけで、少しだけ便利になりました。awspec。