spinnaker 的模板是通过 spin 命令行去创建的,spin 是 spinnaker 的套件,可以使用 spin 获取到存在的pipeline与 template,还可以创建一个新的模板或者替换就得;cli获取到的数据是 json 类型

配置spin

bash
1
2
3
4
5
6
7
mkdir ~/spin
# Inside the dir, setup ‘config’ file using the sample
# https://github.com/spinnaker/spin/blob/master/config/example.yaml
#Sample ~/.spin/config
gate:
   endpoint: http://demospin.net:9000/gateauth:
    enabled: false

spin 配置文件

spin 默认从 ~/spin/config 读取配置,可以通过 –config 指定 spin 的配置文件。下面是一个官方给的一个 spin config 的 example,在配置时只需要选择一个认证方式即可 iap/x.509/oauth2 这个选择的是 oauth2

json
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# NOTE: Copy this file to ~/.spin/config

gate:
  endpoint: https://my-spinnaker-gate:8084
  retryTimeout: 300
auth:
  enabled: true
  x509:
    # See https://www.spinnaker.io/setup/security/ssl/ and
    # https://www.spinnaker.io/setup/security/authentication/x509/ for guides on creating
    # the key and cert files.
    certPath: "~/.spin/certpath"
    keyPath: "~/.spin/keypath" # This should point to an _unencrypted_ keyfile.

    # Pipe to start a multi-line string. This is necessary to import the b64 cert/key value.
    cert: |
      -----BEGIN CERTIFICATE-----
      BLAHBLAHBLAHBLAHBLAHBLAH==
      -----END RSA PRIVATE KEY-----
    # Pipe to start a multi-line string. This is necessary to import the b64 cert/key value.
    key: |
      -----BEGIN RSA PRIVATE KEY-----
      BLAHBLAHBLAHBLAHBLAHBLAH==
      -----END RSA PRIVATE KEY-----

  oauth2:
    # The following is an example for Google's OAuth2 endpoints.
    # The values for these are specific to your OAuth2 provider.
    authUrl: https://accounts.google.com/o/oauth2/auth
    tokenUrl: https://accounts.google.com/o/oauth2/token

    # See https://spinnaker.io/setup/security/authentication/oauth/#oauth-20-providers
    # for examples acquiring clientId/clientSecret.
    clientId:
    clientSecret:
    scopes:
      - scope1
      - scope2

    # To set a cached token, follow the following format:
    # note that these yaml keys must match the golang struct tags exactly because of yaml.UnmarshalStrict
    cachedToken:
      access_token: <token>
      token_type: bearer
      refresh_token: <token>

这里使用了 oauth2,下面是一个完整的配置示例

json
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
auth:
  enabled: true
  ignoreCertErrors: false
  ignoreRedirects: false
  oauth2:
    authUrl: http://{your spinnaker web address}/realms/test/protocol/openid-connect/auth
    cachedToken:
      access_token: eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI3VU0wRUtWRGYwMzJaSFh5MjVDeXhTSGM2b3AySUpod3B0VkhsQnZZSXVvIn0.eyJleHAiOjE2OTAzNTMzNTYsImlhdCI6MTY5MDM1MzA1NiwianRpIjoiOTAzN2ZhNDItYzc1ZC00ODY3LThhZDYtZDkxYWY0ZTRhZTAyIiwiaXNzIjoiaHR0cDovL3NlaXlhLXNzby5ic3Nydi5jb20vcmVhbG1zL3Rlc3QiLCJzdWIiOiJjODgzOGY0Ni1iZWNhLTRmODctYWNjMC0yMTEzYWM2Y2E0NzAiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJzZWl5YS1zcGluLXRlc3QiLCJzZXNzaW9uX3N0YXRlIjoiNzNkNjQ2MGUtY2E0OC00YTYwLWE2MWUtZTUzMTBjNTZmMmQzIiwiYWNyIjoiMSIsImFsbG93ZWQtb3JpZ2lucyI6WyJodHRwOi8vc2VpeWEtc3Bpbi1hcGkuYnNzcnYuY29tIiwiaHR0cDovL3NlaXlhLXNwaW4td2ViLmJzc3J2LmNvbSJdLCJzY29wZSI6Im9wZW5pZCBlbWFpbCBwcm9maWxlIiwic2lkIjoiNzNkNjQ2MGUtY2E0OC00YTYwLWE2MWUtZTUzMTBjNTZmMmQzIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJuYW1lIjoic2VpeWEgc2VpeWEiLCJncm91cHMiOltdLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJ0ZXN0IiwiZ2l2ZW5fbmFtZSI6InNlaXlhIiwiZmFtaWx5X25hbWUiOiJzZWl5YSIsImVtYWlsIjoic2VpeWFAYnNzcnYuY29tIn0.HCr2D0LpRq0nM4_JGoSjl3gmuQZZf-SAyNN01gQj1mIJoTjR2qFd_GuCy3UMgdNCacnEApR-tLmu_7vgti4GDmvv0Fgxl2k2QF8YrDyX89QB2M-72EcqWrHeOSCjeWTagF-ewh_ENfhWPle9iUszM8XLt-rOLr9Rf4RpBRDDMh25MyVKFfy6sezKk9x0oN9IA0MoUWXsdL5nbewu_KCXmF-Jh7raoxXadWs3N9SmWa5RC6FsYFsZEhbJ5vou-EEHzdsBlWwKj_skd7IuPalRAd3MzHqr9HMcZmyzAxC349ozipOGo5vY258wHs8cOQnasJSWYqQani0xNoE3-1L5PA
      expiry: "0001-01-01T00:00:00Z"
      refresh_token: eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI3YmI2NmI3OC1lYzQ0LTQ2YzEtYTMxYy1kNGJkZTZkMjI2ZjEifQ.eyJleHAiOjE2OTAzNTQ4NTYsImlhdCI6MTY5MDM1MzA1NiwianRpIjoiZjM0Y2JkMDUtNWFiZC00ODNjLTkyOTEtODZlZTIxNGJkNTkwIiwiaXNzIjoiaHR0cDovL3NlaXlhLXNzby5ic3Nydi5jb20vcmVhbG1zL3Rlc3QiLCJhdWQiOiJodHRwOi8vc2VpeWEtc3NvLmJzc3J2LmNvbS9yZWFsbXMvdGVzdCIsInN1YiI6ImM4ODM4ZjQ2LWJlY2EtNGY4Ny1hY2MwLTIxMTNhYzZjYTQ3MCIsInR5cCI6IlJlZnJlc2giLCJhenAiOiJzZWl5YS1zcGluLXRlc3QiLCJzZXNzaW9uX3N0YXRlIjoiNzNkNjQ2MGUtY2E0OC00YTYwLWE2MWUtZTUzMTBjNTZmMmQzIiwic2NvcGUiOiJvcGVuaWQgZW1haWwgcHJvZmlsZSIsInNpZCI6IjczZDY0NjBlLWNhNDgtNGE2MC1hNjFlLWU1MzEwYzU2ZjJkMyJ9.bWN0Zencpbwj3fc4SSbc6ApMmx9OBBtevpDFG0974-4
      token_type: bearer
    clientId: "{your spinnaker client id}"
    clientSecret: 61VpMJND1V3A4OXp1afZSidaxIG5hvgt
    scopes:
    - openid
    - email
    - profile
    tokenUrl: http://{your spinnaker web address}/realms/test/protocol/openid-connect/token
gate:
  endpoint: http://{your spinnaker web address}
  retryTimeout: 300

Token 是有时效性的,默认情况下生成的token只有 300 秒

token的获取

当提示下面错误时,表示 token 已过期

bash
1
2
3
Caching oauth2 token.
Could not reach Gate, please ensure it is running. Failing.
Get "http://{your spinnaker web address}/realms/test/protocol/openid-connect/auth?client_id=spin-test&redirect_uri=http://{your spinnaker web address}/login&response_type=code&scope=profile%20email%20role&state=sh5ZiP": stopped after 10 redirects

image-20250414205019555

图:获取access_token参数图

上图表示通过 spinnaker api 获取登录 token 的一个参数,这里 API 是 “keycloak” 的 realm,也是 spinnaker 中健全认证 [1] 的一部分。

配置 Pineline

Get the pipeline.

bash
1
2
spin pipeline get --name <pipelineName> --application <appName>
spin pipeline get <pipelineName> -a <appName>

从文件 save 一个 pipeline.

bash
1
spin pipeline get --name <pipelineName> --application <appName> | tee new_template.txt

列出一个 pipeline.

bash
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
$ spin pipeline list -a example_pipeline
Caching oauth2 token.
[
 {
  "application": "example_pipeline",
  "expectedArtifacts": [
   {
    "defaultArtifact": {
     "customKind": true,
     "id": "e37a6a0a-4d93-4977-bc1c-d2931e29156a"
    },
    "displayName": "testdepoloy",
    "id": "a8085035-93a0-45d7-985c-64615d8f200d",
    "matchArtifact": {
     "artifactAccount": "testdepoloy",
     "id": "dc72329f-e894-496f-af96-ce1c528340fc",
     "name": "https://git.com/Example/test/-/raw/master/nginxtest2.yaml",
     "type": "gitlab/file"
    },
    "useDefaultArtifact": false,
    "usePriorArtifact": false
   }
  ],
  "id": "1638c12f-aab6-4c5e-8886-ed52fc4c8bbb",
  "index": 0,
  "keepWaitingPipelines": true,
  "lastModifiedBy": "anonymous",
  "limitConcurrent": true,
  "name": "deploy",
  "spelEvaluator": "v4",
  "stages": [],
  "triggers": [],
  "updateTs": "1690187227000"
 }
]

Create a pipeline

使用的 schema

json
1
"schema": "v2",

声明变量

在 “模板” 中配置的 “variable” 可以作为之实例化时填写的内容到对应的 pipeline 中。

json
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
"variables": [
  {
    "type": "<type>",
    "defaultValue": <defaultValue>,
    "description": "<some description>",
    "name": "<name of this variable>"
  },
  {
    "type": "<type>",
    "defaultValue": <defaultValue>,
    "description": "<some description>",
    "name": "<name of this variable>"
  }
]

在上下文中使用变量 例如 使用 ${templateVariables.${variableName}} , 例如我们在 pipeline 使用一个配置 "waitTime": <time> ,他在参数化的模板中的使用如下

json
1
"waitTime": "${ templateVariables.timeToWait }",

最终一个完整模板为

json
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
{
  "schema": "v2", # Reference to the MPTv2 schema
  "variables": [
    {
      "type": "int",
      "defaultValue": 42,
      "description": "The time a wait stage shall pauseth",
      "name": "timeToWait" # This is the name that's referenced in the SpEL expression later
    }
  ],
  "id": "newSpelTemplate", # Main identifier to reference this template from instance
  "protect": false,
  "metadata": {
    "name": "Variable Wait",
    "description": "A demonstrative Wait Pipeline.",
    "owner": "example@example.com",
    "scopes": ["global"]
  },
  "pipeline": { # A "normal" pipeline definition.
    "lastModifiedBy": "anonymous",
    "updateTs": "0",
    "parameterConfig": [],
    "limitConcurrent": true,
    "keepWaitingPipelines": false,
    "description": "",
    "triggers": [],
    "notifications": [],
    "stages": [
      {
        "waitTime": "${ templateVariables.timeToWait }", # Templated field.
        "name": "My Wait Stage",
        "type": "wait",
        "refId": "wait1",
        "requisiteStageRefIds": []
      }
    ]
  }
}

Save a pipeline

bash
1
spin pipeline-templates save --file my_template.txt

Reference

[1] OAuth 2.0

[2] Create a Pipeline Template