首先,要讓自訂資源可以被存取,需要先設定 check
方法,讓自訂資源能夠自動的更新。
我們先開設一個專案,並且放入以下檔案。
今天的主角是 check
這個檔案。
這次使用 Ruby 來處理,所以只需要將這三個檔案放入 Docker Image 並且可以執行即可。
FROM ruby:2.3-alpine
ENV SOURCE_DIR /usr/src/app
ENV RESOURCE_DIR /opt/resource
ADD src $SOURCE_DIR
RUN mkdir -p $RESOURCE_DIR
RUN ln -s $SOURCE_DIR/check $RESOURCE_DIR/check && \
ln -s $SOURCE_DIR/in $RESOURCE_DIR/in && \
ln -s $SOURCE_DIR/out $RESOURCE_DIR/out
RUN chmod +x $RESOURCE_DIR/check && \
chmod +x $RESOURCE_DIR/in && \
chmod +x $RESOURCE_DIR/out
每次執行指令時 Concourse 都會呼叫 /opt/resource
裡面的檔案,我們先使用 ADD
將檔案放進去後,再利用 ln -s
建立捷徑讓檔案可以透過 /opt/resource/check
這個路徑被呼叫到。
接著用 chmod +x
將檔案設定為可執行,這樣一來最基本的運作就沒問題了。
如果是用 C/C++ 這類需要編譯的語言撰寫,可以在生成 Docker Image 的時候進行編譯,這篇文章為了容易開發與測試所以採用直接執行 Ruby 的方式。
這次使用的是 Shell Script 的方式執行,所以要先加入下面這行。
#!/usr/bin/env ruby
這是用來表示這個 Script 是一個 Ruby 程式。
這次會用到兩個套件 json
和 net/http
分別用來解析 JSON 以及連到我們的伺服器進行查詢。
require 'json'
require 'net/http`
input = JSON.parse(STDIN.gets)
Concourse 會透過 STDIN 將一段 JSNO 的資料送進來,我們預期會是這樣。
{
"source" {
"uri": "http://version-server.example.com"
},
"version": {"version": "1.0"}
}
要注意的是 version
會傳入一個 JSON 物件,並且裡面是帶有字串資料的。而這個字串資料是由我們所定義的,像是 git
類型的資源就會傳回 {"ref": "7154fe"}
這樣的資訊作為版本資訊。
source = input["source"]
version = input["version"] || {"version" => "0.0"}
假設是一個新初始化的資源,可能會沒有儲存版本資訊,而傳入 null
進來,所以我們要給一個預設值。
伺服器是用 >=
來比較,所以第一次使用 0.0
當版本,就代表回傳所有可用的版本。
major, minior = version["version"].split(".")
uri = URI(source["uri"] + '/v1/versions')
uri.query = URI.encode_www_form({major: major, minior: minior})
接下來我們先將版本分解為 major
和 minior
兩個部分,然後透過使用者傳入的 uri
來建構 API 查詢的網址。
res = Net::HTTP.get_response(uri)
new_versions = JSON.parse(res.body)
取得類似 http://version-server.example.com/v1/versions?major=0&minior=0
的網址後,我們就可以送出查詢並且解析回傳的資料。
這邊並沒有做任何錯誤處理,實際使用時最好多做處理會比較保險。
我們預期會取得類似像下面這樣的資料。
[
"1.0",
"2.0",
"2.1"
]
output = []
new_versions.each do |v|
output << {"version" => v }
end
基本上和我們預期儲存的格式是相同的,所以將所有取得的新版本都寫入進去。
STDOUT.puts output.to_json
最後將版本資訊輸出即可,在設定好 Pipeline 後就能看到類似像這樣的畫面。
不過工作會是無法執行的,但是可以正確被觸發(2.0 是第一次啟動的版本,而 2.1 是後來新增的版本)
呈現橘色是因為 in
的指令並沒有做任何東西,所以工作被中止。
完整的 check
程式碼如下。
#!/usr/bin/env ruby
require 'net/http'
require 'json'
input = JSON.parse(STDIN.gets)
source = input["source"] || {}
version = input["version"] || { "version" => "0.0" }
major, minior = version["version"].split(".")
uri = URI(source["uri"] + '/v1/versions')
uri.query = URI.encode_www_form({major: major, minior: minior})
res = Net::HTTP.get_response(uri)
new_versions = JSON.parse(res.body)
output = []
new_versions.each do |v|
output << {"version" => v }
end
STDOUT.puts output.to_json
到此為止,已經可以正常地取得新版本,下一篇會介紹 in
指令的實作。