Spinnaker第十節—如何開發一個新環節

前面幾篇比較枯燥的介紹了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

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章