Comments

這篇將會記述一些我自己整合 Jenkins CI 和 Docker 的思路、想法、要點以及備忘。不會有 step by step 的教學,若有此類需求請參考最後附錄。

Why Docker?

Jenkins 跑的好好的,為什麼要摻 Docker 呢?原本我們 Rails Rspec 跑的其實也不錯,但受限於 database 以及 elasticsearch, redis 等 services,無法同時跑多個 worker, 再加上未來若有平行化測試以及多個專案 / 不同 db 版本等等的需求,引入 docker 可以完美解決這些問題。

Concept

使用 Docker 的好處就是原本的 shell script 幾乎都不用改即可繼續使用,引入的門檻降到極低。

基本概念是建立一個可以跑 Rails app 起來的環境,然後把整個 CI 的 workspace 丟進去跑測試,其他的步驟都一模一樣。

在建立環境這邊基本上有兩個選擇,一種是全部包成一個 image, 就用這個 container 來跑測試。另一種是每個需要的 service 都是一個各自的 container, 彼此之間透過 Docker Container Linking 來通訊,例如 postgresql 自己一個、elasticsearch 自己一個、rails 自己一個這樣。

不過由於跑測試都是用過即丟,這次我直接採用最簡單的包一大包的策略來進行,減少複雜度。

Read on →
Comments

隨著 AWS Elastic Beanstalk 支援 Docker, Google Computer Engine 也宣布支援 Docker,以及 Google 最近發表的一些 container 工具例如 cAdvisor 這套分析 container 資源和效能的軟體,也同時支援 Google 自己的 lmctfy 和 Docker 來看,Docker 真的是越來越普及了。這個月 Docker 更釋出了 1.0 版 標誌著 Docker 已經 production-ready 了。

關於 Docker 的概念這邊不多加著墨,可以直接上 Docker 官網 閱讀。第一次接觸的朋友可以花十分鐘玩一下 Try Docker。這邊先簡單筆記一些名詞解說和常用的指令。

Read on →
Comments

筆記一下在 Virtualbox 中安裝 OSX 10.9.3 的方式,裝一個乾淨的 Mac vm image 作為測試環境或者 CI 編譯用的 VM 來說相當實用。

以下說明略過 Virtualbox 安裝以及使用的部分,請自行參考 Virtualbox 說明文件。以下步驟在 Virtualbox 4.3.12 測試成功。

  1. 從 AppStore 下載 OSX 安裝檔,不需要進行安裝。

  2. $ gem install iesd

  3. $ iesd -i /Applications/Install\ OS\ X\ Mavericks.app -o Mavericks.dmg -t BaseSyste 這個步驟做完在家目錄會多一個 Mavericks.dmg 檔案

  4. 建立一個新的 Virtualbox 虛擬機器,選 OSX Mavericks 建立好以後先不要開機,進入設定 > 系統 > 晶片組選 PIIX3 然後確定 EFI 有打勾。

  5. $ VBoxManage modifyvm <vmname> –cpuidset 1 000206a7 02100800 1fbae3bf bfebfbff vmname 請帶入你設定的虛擬機器名稱 (可使用指令 VBoxManage list vms 查看)

  6. 啟動虛擬機,會要求啟動磁碟,選剛剛的 Mavericks.dmg 經過一段開機時間後就會進入安裝畫面,依照正常程序安裝。

Ref: How to install OS X on VirtualBox

Comments

在 Puppet 中一些設定大多都是透過 hiera 來取得。 Hiera 最常見,也是預設的 backend 是 YAML 檔。不過有些機敏資訊諸如 API key 或密碼等等,總是不想直接毫無保護的存進 git repository 中,以往我的作法是使用 Hiera-gpg 來加密 YAML 檔,不過一來 gpg 頗為麻煩,二來他是整個檔案都加密,但有時我們只需要修改一些無傷大雅的設定,比如 cluster number 之類的,為此再抽一個加密的檔案專門放這些重要資訊,又破壞了原本的設計。

這次改用了 Hiera-eyaml 這個 plugin,他有許多特色和功能,最大的特點當然是他支援片段加密,也就是一個 YAML 檔,只有需要加密的地方再加密即可。我們的檔案可能就會長成這樣:

1
2
3
4
5
6
7
8
9
10
---
account: hSATAC

password: >
    ENC[PKCS7,Y22exl+OvjDe+drmik2XEeD3VQtl1uZJXFFF2NnrMXDWx0csyqLB/2NOWefv
    NBTZfOlPvMlAesyr4bUY4I5XeVbVk38XKxeriH69EFAD4CahIZlC8lkE/uDh
    jJGQfh052eonkungHIcuGKY/5sEbbZl/qufjAtp/ufor15VBJtsXt17tXP4y
    l5ZP119Fwq8xiREGOL0lVvFYJz2hZc1ppPCNG5lwuLnTekXN/OazNYpf4CMd
    /HjZFXwcXRtTlzewJLc+/gox2IfByQRhsI/AgogRfYQKocZgFb/DOZoXR7wm
    IZGeunzwhqfmEtGiqpvJJQ5wVRdzJVpTnANBA5qxeA==]
Read on →
Comments

在寫 Vagrantfile 的時候如果需要用不同的 provider,例如用 virtualbox 和 aws 兩個 provider,但是 provisioner 的內容非常類似,這時候想省掉重複的部分,可以利用 Vagrantfile 本身就是 Ruby 的特性,直接定義一個共用的 lambda,不同的地方再另外設定:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  # Puppet config
  puppet_block = lambda do |puppet|
    puppet.options = "--parser future --verbose --debug" # For debug only
    puppet.manifests_path = "manifests"
    puppet.manifest_file  = "vagrant.pp"
    puppet.module_path    = "modules"
    puppet.hiera_config_path = "hiera.yaml"
  end

  config.vm.provider "virtualbox" do |vb, override|
    override.vm.provision "puppet", &puppet_block
  end

  config.vm.provider :aws do |aws, override|
    override.vm.provision "puppet", &puppet_block
  end

Read on →
Comments

好一陣子沒寫 Puppet, 最近回來研究發現多了不少好用的工具,可以有效加速開發速度。

Vagrant

現在 Vagrant provisioner 直接提供了 Puppet 選項,可以幫你 sync hiera, manifests, modules 進去直接 run,也可以帶入 custom options 或是 facter,在開發 modules 的時候可以不用管其他東西,專心 focus 在 pp 本身。

只要在 Vagrantfile 裡面加入這樣的設定即可:

1
2
3
4
5
6
7
8
9
10
  # Puppet config
  config.vm.provider "virtualbox" do |vb, override|
    override.vm.provision "puppet" do |puppet|
      puppet.options = "--parser future --verbose --debug" # For debug only
      puppet.manifests_path = "manifests"
      puppet.manifest_file  = "vagrant.pp"
      puppet.module_path    = "modules"
      puppet.hiera_config_path = "hiera.yaml"
    end
  end

不過有兩個小地方需要注意:

Read on →
Comments

一開始寫 Puppet 就是 node definition 直接寫寫寫…後來就會開始把重複的 resource, file 等等拆成 modules…。不過當機器越來越多,發現還是有許多重複的地方,例如有好多台 web server, 但是他們有些又有些許的不同…。

Read on →
Comments

在 Rails i18n 裡面可以用 relative path 像 t('.key') 這樣的 shortcut,不過這個 shortcut 吃得是 "#{ controller_path.tr('/', '.') }.#{ action_name }#{ key }"

今天碰到 controller 的 before action 裡面用 relative path 結果 locale yml 編到 before action 的 key,但真正會去 lookup 的是 action_name 而不是 before action 的 method name 所以就爆 missing 了。

萬一這個 before_action 之後多加幾個其他的 action 的話很容易就沒改到 locale yml 而爆錯誤,為了保險起見決定把他們都改成 absolute key path. 不過 controller 檔案非常多,所以要寫一隻程式把所有 before action 裡面有用到 relative path 的 t 撈出來。

一開始的想法是用 regex 速解,不過因為 controller 裡面的 t 還滿多的,然後我又很難判斷 before action method 的 scope,於是念頭一轉就直接改用 Ruby Parser 來做。

直接把 controller 檔案都讀進來,拿 AST 來抓 before actions,再去檢查這些 before action 是否有 call 到 relative keypath 的 t。用起來還滿方便的,效率也不差,一下子就寫完了。

程式碼放在 Github,不過這麼特定目的東西應該是無法重用,放著以後有需要的時候回來看一下。

最後就是…i18n 沒事還是不要用 relative key 比較好…散在 controller, helper, service 裡面到時要搬移 code 或者作 refactor 的時候就麻煩了。動態語言重構不像靜態語言這麼便利啊…。

Functional Reactive Programming

第一次聽到 Functional Reactive Programming(FRP) 是在今年新加坡的 RedDotRubyConf 2013 的最後一個 Session: Functional Reactive Programming in Ruby。那時一直無法理解這個主題,直到大約九月時碰到了 ReactiveCocoa 並開始在公司專案中使用,才對 FRP 開始有些感覺。

Functional Reactive Programming 就是 Functional Programming + Reactive Programming。 Functional Programming 大家應該比較熟悉,那什麼是 Reactive Programming 呢?最常看到的比喻就是像試算表一樣,你可以定義 C1 = A1 + B1 ,之後只要你更改了 A1B1 的值, C1 就會跟著改變。

光看這樣實在還是無法理解到底 FRP 是什麼,以及可以帶來什麼好處。這就是我今年六月剛聽到這個名詞時的感受。直到我開始使用 ReactiveCocoa(RAC)。

Read on →