星期六, 11月 18, 2017

Intranet jail break

我們常開發了一些網站應用程式,部署在個人開發環境、內網測試環境與客戶測試環境,因為各有各的用途與限制,三者缺一不可,但又瑣碎費時。
  • 個人開發環境:通常與開發工具結合,不太需要擔心如何部署,但配備要夠(資料庫不一定是隨便一部電腦就跑得動吧?)。
  • 內網測試環境:為了整合測試,或給 SA 驗收確認,可以搭配 Jenkins 持續部署。
  • 客戶測試環境:為了給客戶 Prototyping,請工程師帶個人開發環境(筆電)秀給客戶看?或請客戶提供機器讓我們去裝一套?或請公司的 MIS 把內網開給客戶?
現在有個神器 ngrok 能幫忙,原理應該是與分享檔案的 JustBeamIt 類似,只要是內網測試環境,我們自己就能把內網開給客戶。下載解壓之後,只有一個執行檔,請在內網執行環境的主機上開終端機/命令提示字元,執行類似如下的指令:
  • ./ngrok http 80
就會把本機的 http port 80 公開在 Internet 上,網址是隨時産生的。這時再把網址傳給客戶,我們這些廢宅工程師就免出門吹風了。

星期三, 10月 25, 2017

VirtualBox VT-x

對於這個選項放在每個 Guest VM 上,一直以來引人誤解為「只要勾選就能讓 Guest VM 相當於 BIOS 設定啟用 VT-x」,其實只是代表「Host 在啟動 Guest 時能用到 VT-x」,這篇有比較詳細的討論。
如果想讓 Guest VM 支援 VT-x,專業術語叫 nested virtualization,大家已對 VirtualBox 喊話很久了。

星期四, 10月 19, 2017

Confirm your Jenkins Deploy

以我大多接觸的都是 Web Application 而言,可概分
  • 淺層-網路通暢
  • 中層-版本正確
  • 深層-功能正確
淺層在 Jenkins 有個好用的 Http Request Plugin,只要輸入任一頁的 URL,這個外掛就可以試著要求,並檢查回傳的 Http Status Code 是否在預期內,通常是 2xx 或 3xx。
最近有個特例是要檢查部署的結果,但對面並不接受 http(s) 協定,在 Linux 上的 Jenkins Slave 可以用 nc -vz <IP> <Port>。
中層的話,如果部署的 Web Application 除了服務人,也服務機器(Web API),建議就考慮增加一個供外界查詢版本的 Web API,Jenkins 可透過核對 curl <Web API> 確認部署的狀況;如果是只服務人又不想改得多,可以挑一個靜態網頁的角落放版號,用 Selenium BDD 簡單的腳本確認。
深層的話,要準備 Selenium BDD 比較複雜的腳本,錄製工具似乎有些變化,所幸直接用 Node.js 來寫也不太困難。

[2017/10/23 補充]
有些 Linux 版本上 nc 似乎相容性不是很好,可用 nmap <IP> -p<Port> | grep open 試試能否取代?

星期二, 10月 17, 2017

Samba cannot communicate with Windows WINS servers

不敢令人相信的標題!出自於此。
當 Windows 與 Linux 混處於同個網段上,Linux 想識別那些 WINS server 掌管的 NetBIOS 機器名稱,竟然不是我一直肖想的架個 Samba 就好?目前只知一種解法(在安裝 Samba 之後):
  • nmblookup -U <WINS_ip> -R <NetBIOS_name>

星期四, 9月 07, 2017

update configuration in jar / war

jar / war 能帶著 configuration 一起其實是把雙面刃:好處是開發人員能提供一種「預設組態」期待在任何環境都可運作;壞處則是非改不可又不會改的時候變成累贅。這時我們就可以思考如何因應這些情境:
  1. 組態內容預期在任何環境都適用
  2. 組態內容必須為各環境調整
    1. 開發人員為各環境提供不同的 jar / war 包含各自的組態內容
    2. 部署人員為單一的 jar / war 修改組態以適應其環境
首先看 2-1 情境:開發人員可以在 Jenkins 封裝 jar / war 之前用一個 Ant Task 讀環境變數,並將結果取代掉該改的地方,例如在 cas/src/main/resources/application.properties 有一行內容如下:
  • cas.server.name=https://acme.com
但這行右邊的內容每次都不一樣,可先修正為:
  • cas.server.name=https://@hostName@
當然只有這樣並不夠,必須搭配 build.xml,內容如下:
  • <?xml version="1.0" encoding="UTF-8"?>
  • <project default="replaceToken">
    • <property environment="env" />
    • <target name="replaceToken">
      • <replace file="cas/src/main/resources/application.properties" token="@hostName%" value="@{env.hostName}" />
    • </target>
  • </project>
另外,在 Jenkins Build 段落必須在編譯封裝 jar / war(假設是用 Gradle)之前安排:
  • Build
    • Inject environment variables
      • Properties Content
        • hostName=acme.com
    • Invoke ant
    • Invoke Gradle script
當然,實際上要再進一步整合到純粹用 Ant 或 Gradle,不再混搭會更好。

再來是情境 2-2「一個 jar / war 到處使用」,藉由很基本的 JDK 工具即可:
  • mkdir working
  • cd working
  • mv ~/Downloads/cas-1.0.0-SNAPSHOT.war .
  • jar xf cas-1.0.0-SNAPSHOT.war WEB-INF/classes/application.properties
  • vi WEB-INF/classes/application.properties(改成適合環境的內容)
  • jar uf cas-1.0.0-SNAPSHOT.war WEB-INF/classes/*
  • mv cas-1.0.0-SNAPSHOT.war ~/Downloads
  • cd ..
  • rm -rf working
有的環境只有 JRE 但沒有 JDK,需要為此下載安裝嗎?別急,找找有沒有 zip / unzip 也可當做替代品:
  • unzip cas-1.0.0-SNAPSHOT.war WEB-INF/classes/application.properties
  • zip -u cas-1.0.0-SNAPSHOT.war WEB-INF/classes/*

星期一, 9月 04, 2017

星期五, 9月 01, 2017

Maven install reference

在舊版(3.0.5)mvn install 遇到以下問題:

  • [ERROR] ...
  • The following artifacts could not be resolved:
    • com.dummy:packageA:jar:1.0.0-SNAPSHOT,
    • com.dummy:packageB:jar:1.0.0-SNAPSHOT
    • ...
  • Could not find artifact ... in snapshots (http://your.artifact.com/libs-snapshot)

如果我們明明在本地端 Maven Repositories 能找到那些 JAR,但以上的指令固執地只找遠端,可以這麼修正:

  • rm ~/.m2/repository/com/dummy/packageA/1.0.0-SNAPSHOT/_maven.repositories
  • rm ~/.m2/repository/com/dummy/packageB/1.0.0-SNAPSHOT/_maven.repositories