使用Golang開發(fā)OpenStack服務(wù)的CLI
由于我們需要編寫自己服務(wù)的客戶端,之前參考過magnum的python客戶端,編寫過一個(gè),整體感受就是: 一件簡(jiǎn)單的事兒,被他封裝的很復(fù)雜,而且還有一個(gè)關(guān)鍵痛點(diǎn),部署問題:?1.依賴python環(huán)境 2. 蹩腳的二進(jìn)制打包方式。因此,作為一個(gè)產(chǎn)品的CLI,以二進(jìn)制方式交付會(huì)帶來諸多方便,比如cloud foundry也用golang重寫了他的客戶端部分。
Cobra簡(jiǎn)介
在博客的開篇寫過一篇cobra的博客:?如何使用golang編寫漂亮的命令行工具, 很多流行的CLI都基于這個(gè)庫(kù)開發(fā),比如kubectl, etcdctl, docker等, 基本的概念和用法請(qǐng)參考之前的博客。
基于RESTful的CLI
打造的這個(gè)CLI是RESTful的客戶端, 在RESTful里面以資源(Resource)為核心,因此客戶端也需要以資源的形式表現(xiàn), 比如Docker的 Management Commands:

該資源允許的操作:

因此, 輪廓上我們需要打造這樣一種風(fēng)格的RESTful CLI
OpenStack服務(wù) CLI
我們的OpenStack服務(wù)是自己開發(fā)的, 開發(fā)出來的CLI風(fēng)格想要和Openstack社區(qū)風(fēng)格一致(長(zhǎng)相相近), 這東西社區(qū)是沒有Golang版本的(有的話給我留言, 我真沒找到), 因此整個(gè)架子需要自己構(gòu)建, 由于cobra架子比較成熟, 如果只用官方的Flag庫(kù)來做的話,會(huì)有很多重復(fù)工作, 因此使用cobra為基礎(chǔ)來進(jìn)行構(gòu)建。
要做成和Openstack風(fēng)格類似的CLI, 在cobra的基礎(chǔ)上我們需要加入2個(gè)組件:
keystone認(rèn)證: 對(duì)每一個(gè)資源的訪問必須通過keystone認(rèn)證才能訪問, 因此認(rèn)證部分是全局的。表格輸出: OpenstackCLI把資源以Table的方式輸出, 這個(gè)也需要單獨(dú)實(shí)現(xiàn)。
搭建CLI架子
初始化app, 添加resourceA和resourceB

訪問每一個(gè)resource都需要經(jīng)過keystone的認(rèn)證,因此認(rèn)證屬于一個(gè)全局都要執(zhí)行的邏輯, 必須放在最前面,這里Cobra提供的一組Hook可以解決這個(gè)問題
帶錯(cuò)誤處理的Hook
當(dāng)處理過程中如果產(chǎn)生了error可以直接return出來, 從而中斷命令的繼續(xù)執(zhí)行, 因此認(rèn)證部分我們需要這種帶錯(cuò)誤處理的Hook, 因?yàn)檎J(rèn)證失敗需要中斷請(qǐng)求,
其次,cobra 在命令函數(shù)的執(zhí)行前后分別設(shè)置了2組Hook, 執(zhí)行的順序如下:
PersistentPreRunE: 無論函數(shù) 執(zhí)不執(zhí)行 該函數(shù)都會(huì)運(yùn)行
PreRunE: 在函數(shù)執(zhí)行前執(zhí)行
RunE: 執(zhí)行函數(shù)
PostRunE: 函數(shù)執(zhí)行后執(zhí)行
PersistentPostRunE: 無論函數(shù) 執(zhí)不執(zhí)行 該函數(shù)都會(huì)執(zhí)行
利用cobra提供的PersistentPreRunE來實(shí)現(xiàn)驗(yàn)證功能

auth函數(shù)實(shí)現(xiàn)認(rèn)證并不難, 關(guān)鍵是auth過后的token 如何傳遞給后面的子命令使用, 參考etcdctl和docker部分都使用上下文來實(shí)現(xiàn)這個(gè)需求, cobra里面也沒有地方給我存上下文, 因此需要專門用一個(gè)模塊來保持 全局的上下文, 因此需要手動(dòng)實(shí)現(xiàn)一個(gè)common包。

最后在common包里面添加2個(gè)子包: keystone, printTable, keystone 用于實(shí)現(xiàn)與keystone認(rèn)證的過程, printTable用于打印最后結(jié)果的表格,具體詳情請(qǐng)看源碼。
添加資源
為每一個(gè)資源添加5個(gè)基礎(chǔ)的操作:get, list, create, delete, update。另起一個(gè)resourceA的包,實(shí)現(xiàn)這些方法,添加到子命令即可, 比如:

大概效果如下

使用效果
和使用openstack一樣,你需要有一個(gè)admin_openrc 用于導(dǎo)入環(huán)境變量

比如