Terraform 开发指南
摘要:?本文主要向大家展示如何為阿里云 Terraform Provider 貢獻自己的力量,幫助開發(fā)者和志同道合的朋友盡快加入到開源生態(tài)的建設中來。 本文面向所有的對Terraform熟悉和感興趣的朋友,如果您還不了解Terraform,快快戳這里。
本文主要向大家展示如何為阿里云 Terraform Provider?貢獻自己的力量,幫助開發(fā)者和志同道合的朋友盡快加入到開源生態(tài)的建設中來。
本文面向所有的對Terraform熟悉和感興趣的朋友,如果您還不了解Terraform,快快戳這里。
本文會從環(huán)境搭建和開發(fā)規(guī)范兩個方面向大家展示如何開放 terraform provider。
環(huán)境搭建
安裝 Golang
本地安裝go >1.10.0 詳見:https://golang.org/dl/
安裝 Terraform
本地安裝 Terraform > 0.11, 詳見:?https://www.terraform.io/intro/getting-started/install.html
安裝 Terraform Provider
fork 并下載 repo:?https://github.com/alibaba/terraform-provider
cd $GOPATH mkdir -p src/github.com/alibaba cd $GOPATH/src/github.com/alibaba git clone git clone git@github.com:<your-git-id>/terraform-provider.git利用 glide 安裝依賴(how to install glide)
# switch to project cd $GOPATH/src/github.com/alibaba/terraform-provider# get all dependencies and install modules glide up設置環(huán)境變量,省去每次測試時輸入AK的要求
# set the creds export ALICLOUD_ACCESS_KEY="***" export ALICLOUD_SECRET_KEY="***"Resource 開發(fā)
Resource 開發(fā)是根據阿里云的OpenAPI在terraform provider中實現對阿里云產品和資源的插件。
規(guī)劃和設計
每個Resource的實現不是根據阿里云幫助文檔對OpenAPI的簡單調用,要對產品的設計,功能以及使用有較深的理解,通常遵循如下設計原則:
每個resource只管理自身的功能,與其他resource引用或者關聯交由關系性資源來完成,如ECS instance只管理實例自身的功能,對于掛哪個數據盤,分配哪個EIP交由attachment資源來完成
對于資源與資源之間的關系,需要單獨定義一個邏輯resource,來完成資源與資源之間的關聯,如磁盤掛載,eip的掛載,ess與ecs的關聯等
參數要盡可能簡潔,不要有冗余的參數,以RDS instance為例,對于參數zoneId,VpcId以及VSwitchId而言,只需要定義zoneId和VpcId就是冗余參數,因為在調用具體API之前,可以通過vswitchId來獲取這兩個參數,但某些特殊的場景除外,比如RDS支持Multiple zone,所以zonId也需要保留。如果可以設置Default,最好顯示設置。
每個參數字段要具有清晰的語義,幫助用戶更好的理解。對于一些公共的,統(tǒng)一的參數,如可用區(qū),slb ID,最好跟其他資源保持一致:availability_zone,?load_balancer_id.
參數校驗
有些參數需要做一些簡單的校驗,提前提醒客戶使用正確的可選值。除此之外,對于某些參數,要做diff判斷,以自動屏蔽某些不起作用的參數,如:對于ECS而言,選擇PostPaid,意味著所有與PrePaid相關的參數?period,period_unit,renewal_status,auto_renew_period都將失效,具體表現為在執(zhí)行terraform plan的時候,這些參數不會做diff比較。
基本實現
每個Resource需要實現Create,Read,Update,Delete,Import五個功能:
-
Create
- 調用產品創(chuàng)建API,實現對某個資源的創(chuàng)建,并將resource id 寫入到state文件中
- 如果資源沒有ID,比如安全組規(guī)則,那么resource要自己按照一定的規(guī)則自行實現一個ID,對terraform而言,該ID是resource的唯一標識,后續(xù)對resource的所有操作都需要依賴于該ID進行
- Create 的實現邏輯要盡可能簡單,以成功創(chuàng)建資源為目標,太多的復雜邏輯會降低資源創(chuàng)建的成功率
- 復雜的功能實現可交由 Update 來完成
- Create之后通常調用Update方法來完成更多功能的實現
-
Update
- 調用產品的Update或Modify API,實現對resource更多功能的支持以及對已有屬性的修改
- Update之前要打開Partial?d.Partial(true),并在每步修改后進行時時更新,如d.SetPartial("bandwidth"),以保證后面的每一步成功的更改都能被及時的寫入到state 文件中。
- Update 之后,調用 Read 方法,實現對resource 所有屬性的展示。
-
Read
- 調用 Describe 或者 List API,實現對已有資源的查詢和寫入state
- 如果找不到指定的資源,要將resource ID標記為“”,以告訴terraform,當前這個資源已經不存在了。
-
Delete
- 調用Delete API實現對指定資源的刪除和釋放
- 為了保證resource成功釋放,需要加入retry策略來避免因資源依賴或者異步操作而引起的刪除失敗問題
- 通常,resource釋放后要再次調用查詢API來完成刪除操作的驗證
-
Import
- 調用查詢API實現對已有資源的導入
- 通常只需要方法申明,無需多余的實現邏輯,它會借助Read方法來完成對資源的查詢和導入
基本工作原理
執(zhí)行terraform 命令,完成對資源的管理,主要命令包含以下幾個:
實現對資源的預覽。該命令會調用對應資源的Read?方法來獲取模板中定義的資源。如果資源尚未創(chuàng)建,及當前目錄下的state文件為空,直接展示即將創(chuàng)建的資源,否則展示要變更的資源
terrform apply
實現對資源的創(chuàng)建和更新。新資源調用Create,已有資源調用Update完成對資源的修改。
terraform destroy
調用Destroy完成對資源的銷毀。
調用Read方法完成對已有資源的導入,將已有資源加入到terraform的管理序列中來。但要注意,由于已有資源不一定是通過terraform創(chuàng)建的,所有導入成功后,記得運行terraform plan進行對比,手動補齊模板。
注意事項
Data Source 開發(fā)
Data Source 開發(fā)是調用阿里云資源的查詢API完成對特定資源的查詢和展示。
規(guī)劃和設計
每個Data Source的實現要根據API的字段和資源屬性,為用戶提供更好的查詢體驗,最好可以支持模糊查詢。參數設計原則除了與Resource設計原則類似外,還應該提供一個參數output_file來將查詢到的結果輸出到文件中,供用戶參考。
基本實現
每個Data Source只需實現Read方法,該方法用來查詢并過濾符合條件的所有的resource,然后將過濾的結果以列表的方式展示出來。在具體實現過程中,需要注意以下幾點:
測試
在完成模塊開發(fā)后,要對每個resource和data source的功能進行測試,測試的方法是編寫對應的測試用例。
測試用例的編寫要遵循以下幾個原則:
如何運行測試用例?
以ECS instance 舉例,運行如下的測試命令,可以實現對目錄alicloud下所有以TestAccAlicloudInstance為前綴的測試用例的運行:
其中,timeout?表示這個測試用例運行的超時時長。
如果想要精確到具體的測試用例,補全測試用例的名稱即可。
文檔
文檔是用戶使用provider的基礎,文檔的編寫非常重要,需遵循如下幾個原則:
樣例
為了更好的幫助用戶使用新增的resource,在完成以上工作后,需要為當前的這個resource或者當前這類resource增加一個example,來指導用戶編寫對應的模板。該樣例是一個真實的可運行的模板,通常包含以下四部分:
代碼提交
完成了以上功能的實現和代碼的編寫后,接下來最關鍵的就是代碼的提交,我們的代碼最好優(yōu)先提交到dev分支,具體的步驟分為以下幾步:
Commit
為了避免出現代碼的錯亂,降低review的復雜度,Commit要細化,每一功能點或者一次的修改(不論改動有多小)對應一個Commit。為了防止功能和代碼的相互沖突,每個功能點對應一個branch。
Rebase
提交代碼前一定要Rebase,具體操作步驟如下:
Rebase之前,首先需要配置你的Remote,假定你origin?指向了你的fork:
接著,將主倉庫配置為你的remote,如起名為“alicloud”
$ git remote add alicloud https://github.com/alibaba/terraform-provider.git$ git remote -vorigin git@github.com:YOUR_GITHUB_USERNAME/terraform-provider.git (fetch)origin git@github.com:YOUR_GITHUB_USERNAME/terraform-provider.git (push)alicloud https://github.com/alibaba/terraform-provider.git (fetch)alicloud https://github.com/alibaba/terraform-provider.git (push)檢查當前倉庫的狀態(tài)
$ git statusOn branch YOUR_BRANCHYour branch is up-to-date with 'origin/YOUR_BRANCH'.nothing to commit, working tree clean完成commit和remote配置后,即可進行rebase操作:
如果有沖突,解決沖突后繼續(xù) rebase,直到所有沖突都解決,之后再次檢查狀態(tài):
$ git statusOn branch YOUR_BRANCHYour branch and 'origin/YOUR_BRANCH' have diverged,and have 4 and 1 different commits each, respectively.(use "git pull" to merge the remote branch into yours)nothing to commit, working tree clean完成rebase操作后,上傳代碼:
如遇到提交失敗,可使用-f?或者--force?來強制提交
Submitting Your Pull Request
完成代碼上傳后,在Github控制臺將你的代碼提交到主倉庫的dev分支,并對PR做一個簡單的描述和介紹。
如果代碼有問題,在Review結束后,需要對已提交的代碼做修改,首先將上次提交進行回退:
之后,stash并利用rebase下載最新的代碼,以避免不必要的沖突:
$ git stashSaved working directory and index state WIP on YOUR_BRANH: xxxxxHEAD is now at xxxxx# rebase 下載最新代碼$ git pull --rebase alicloud devrebase順利執(zhí)行之后,恢復stash代碼:
$ git stash popOn branch YOUR_BRANCHChanges not staged for commit:xxxxx根據review意見,繼續(xù)修改代碼,之后再次進行代碼commit,rebase和push即可。
寫在最后
本文主要講述了如何為阿里云的Terraform-Provider貢獻代碼的一些流程和注意事項,歡迎大家積極加入到Terraform Provider的建設中來,謝謝大家。
原文鏈接
本文為云棲社區(qū)原創(chuàng)內容,未經允許不得轉載
總結
以上是生活随笔為你收集整理的Terraform 开发指南的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 阿里敏捷教练何勉:论精益思想及精益产品开
- 下一篇: Apache RocketMQ 正式开源