前面幾篇比較枯燥的介紹了orca、clouddriver、deck目錄結構和核心代碼,本篇將會作爲這一系列的終篇爲大家分享下如何在spinnaker中開發一個自定義的環節。
需求背景:
Spinnaker對於鏡像自帶了FindImageByTags環節,可以讓我們在pipeline中通過tag爲條件選中想要發佈的鏡像,流轉到後續的deploy環節。但是騰訊雲鏡像不支持tag功能,所以爲了達到同樣的效果我們需要自開發一個findImageByName環節。
開發deck-(angular)
1 core部分:
說明:core解決的是parent級別的環節問題,每個環節都必須從parent中繼承,因爲本次開發的環節是全新環節,parent也沒有,所以需要先修改core
1.1 先從core中添加parent環節:
modules\core\src\pipeline\config\stages\findImageFromName
以及相關的文件findImageFromNameStage.js 和 findImageFromNameStage.module.js
1.2 修改stageConstants (個人覺得可能不是必須的)
modules\core\src\pipeline\config\stages\stageConstants.ts
修改IMAGE_PRODUCING_STAGES部分
1.3 修改pipeline.module註冊
modules\core\src\pipeline\pipeline.module.ts
1.4 修改Deploy環節的前置條件
modules\core\src\pipeline\config\stages\deploy\deployStage.js
因爲deploy環節需要輸入一個鏡像id作爲環節的前置條件,目前已知的有findImageByTag和bake,本次添加的環節也屬於deploy的前置條件,所以此處需要修改。關鍵字"stageBeforeType"
2 tencent部分:
說明:解決的是廠商sub級別的環節問題,只有註冊過的環節纔可以在deck中被看到
2.1 廠商實現core中剩餘部分
modules\tencent\src\pipeline\stages\findImageFromName
以及相關文件:
tencentFindImageFromNameStage.js 自定義註冊
findImageFromNameExecutionDetails.html pipeline中看到的頁面
findImageFromNameStage.html stage的詳細頁面
2.2 添加進廠商配置文件
modules\tencent\src\tencent.module.ts
3 前端效果
到目前位置可以重啓deck,可以看到基本的效果了。
4 核心問題思考
Q1:stage頁面中,初始數據從哪來?
A1:兩層:
第一層:modules\core\src\pipeline\config\stages\stage.module.js中controller('StageConfigCtrl')
第二層:modules\tencent\src\pipeline\stages\findImageFromName\tencentFindImageFromNameStage.js中又設置了一次,基本就是透傳的第一層
第一層沒找到,合理的猜測:pipeline執行後相關的json保留在了redis中,所以此處不需要關心,先忽略。
Q2:stage的表單最終提交到哪裏去?
A2:通過API這個module調用了gateway流入到了orca中,後面重點會去開發orca
開發orca-(java+groovy)
1 先開發公共部分:
1.1 先創建一個對應的stage
FindImageFromNameStage.java,內容很簡單,對task的組裝,因爲task對我們來說也是新的,所以要自己再創建task。
注意:stage一定要實現StageDefinitionBuilder,具體原因後面詳解
1.2 再創建一個對應的task
FindImageFromNameTask.java 需要繼承AbstractCloudProviderAwareTask並根據是否可以重複執行選擇性的實現RetryableTask
跟入AbstractCloudProviderAwareTask中
abstract class AbstractCloudProviderAwareTask implements CloudProviderAware, Task {}
其中CloudProviderAware中都有default的實現,此處可以暫時不管;
Task中TaskResult execute(@Nonnull Stage stage)方法需要實現掉
1.3 擴展Reader和Writer
發現task最終調用的Reader和Writer來做的業務處理,但是現有的接口方法不支持我的業務,所以需要添加方法,進行擴展.
注意擴展時給自己新方法添加default實現,不要影響現有功能。
2 再開發雲廠商部分
雲廠商實現在com\netflix\spinnaker\orca\clouddriver\tasks\providers下
3 核心問題思考
Q:deck中環節如何與orca映射起來的?
A:前文說過stage一定要實現StageDefinitionBuilder,核心代碼在StageDefinitionBuilder中getType方法:
static String getType(Class<? extends StageDefinitionBuilder> clazz) {
String className = clazz.getSimpleName();
return className.substring(0, 1).toLowerCase() + className.substring(1).replaceFirst("StageDefinitionBuilder$", "").replaceFirst("Stage$", "");
}
然後DefaultStageDefinitionBuilderFactory中builderFor方法:
@Override
public @Nonnull StageDefinitionBuilder builderFor(
@Nonnull Stage stage) throws NoSuchStageDefinitionBuilder {
return stageDefinitionBuilders
.stream()
.filter((it) -> it.getType().equals(stage.getType()) || it.getType().equals(stage.getContext().get("alias")))
.findFirst()
.orElseThrow(() -> {
List<String> knownTypes = stageDefinitionBuilders.stream().map(it -> it.getType()).sorted().collect(toList());
return new NoSuchStageDefinitionBuilder(stage.getType(), knownTypes);
});
}
其中stageDefinitionBuilders來在springIoc框架,所有子類或實現類的集合
private final Collection<StageDefinitionBuilder> stageDefinitionBuilders;
總結:只要實現了stageDefinitionBuilders並且按照命名規則定義類名,就會被認爲是後端的一個stage。
開發clouddriver-(groovy)
1 controller層修改
找到orca中reader請求clouddriver的restful對應的controller,根據業務需求選擇原基礎上改造還是重新做一個restful入口
TencentNamedImageLookupController
2 編寫核心業務邏輯
本次涉及到的是鏡像查詢邏輯變更,查詢是直接從cache中獲取的,cache的存儲邏輯在TencentImageCachingAgent,根據需求進行改造,在查找後需要按照orca接收的json格式進行封裝。
FindImageByName環節代碼列表:
Deck:
新增:
modules/core/src/pipeline/config/stages/findImageFromName/findImageFromNameStage.js
modules/core/src/pipeline/config/stages/findImageFromName/findImageFromNameStage.module.js
modules/tencent/src/pipeline/stages/findImageFromName/findImageFromNameStage.html
modules/tencent/src/pipeline/stages/findImageFromName/findImageFromNameExecutionDetails.html
modules/tencent/src/pipeline/stages/findImageFromName/tencentFindImageFromNameStage.js
修改:
modules/core/src/pipeline/config/stages/deploy/deployStage.js
modules/tencent/src/aws.module.ts
modules/core/src/pipeline/config/stages/stageConstants.ts
modules/core/src/pipeline/pipeline.module.ts
Orca:
新增:
com.netflix.spinnaker.orca.clouddriver.pipeline.image.FindImageFromNameStage.java
com.netflix.spinnaker.orca.clouddriver.tasks.image.FindImageFromNameTask.java
com.netflix.spinnaker.orca.clouddriver.tasks.providers.tencent.TencentImageFinder.groovy
修改:
com.netflix.spinnaker.orca.clouddriver.tasks.image.ImageFinder.java
CloudDriver:
新增:
com.netflix.spinnaker.clouddriver.tencent.controllers.TencentNamedImageLookupController.groovy
修改:
com.netflix.spinnaker.clouddriver.tencent.provider.agent.TencentImageCachingAgent.groovy
本文的項目地址:https://github.com/spinnaker-cn