今天要實作做的是自訂資源的 out
部分。不過實際上這次的範例並不會有任何反應,因為我們在前面 API 設計上並沒有做特別的處理。
初始化的部分基本上都是相同的,不過 out
的部分從 STDIN
接收到的參數卻會有一點不同。
require "net/http"
require "json"
input = JSON.parse(STDIN.gets)
source = input["source"] || {}
params = input["params"] || {}
version = "%.1f" % params["version"] || "0.0"
在這邊我們不會收到 version
參數,因為上傳資源並不需要知道版本,而是由伺服器接收之後回傳一個版本資訊。
另一方面,我們需要上傳的話可能會需要一些額外的參數,所以我們可以透過 params
來帶入一些額外的設定參數。
在這個範例,我們可以透過
params
設定要更新的版本。
接下來一樣是建立一個 HTTP 的請求去呼叫我們的伺服器,不過需要調整一下請求的方式。
major, minior = version.split(".")
uri = URI(source["uri"])
query = URI.encode_www_form({major: major, minior: minior})
path = "/v1/version?" << query
res = Net::HTTP.new(uri.host, uri.port).send_request("PUT", path)
response = JSON.parse(res.body)
根據我們的 API 設計,會用 PUT /v1/version
帶入 major
和 minior
兩個參數傳入來決定要對哪個版本做 touch
(修改最後修改時間)的動作。
取得回傳的時間後,我們需要傳回目前所更新的版本讓 Concourse 可以做出對應的動作。而另一方面,和 in
一樣也可以回傳一些 Metadata 讓使用者知道這次上傳的動作有哪些額外的訊息。
updated_at = response["updated_at"] || false
result = {
"version" => {"version": version },
"metadata" => []
}
if updated_at
result["metadata"] << { "name" => "updated_at", "value" => updated_at.to_s }
else
result["metadata"]<< { "name" => "error", "value" => "No valid version matched!" }
end
STDOUT.puts result.to_json
這邊我們可以將伺服器回傳的更新時間放進 Metadat 中,假設伺服器無法取得時間資訊的話,則回傳一個錯誤訊息。
不過這邊大多數時候都會被 Concourse 快取住,所以在配置版本資訊時可以考慮用 Timestamp 的方式強制觸發。
最後,稍微更新一下我們的 Pipeline 設定檔,加入 put
動作就可以觸發對應的事件。
- put: monster-db
params:
version: 2.0
到此為止,我們已經掌握了自訂資源的基本技巧,下一篇會討論一下如何改進以及可以怎麼應用。