今天的主題是介紹如何參考其他專案中 Stack 的資料,假設我們有兩個 Pulumi 專案如下:專案 B 的 stack 會需要參考到專案 A 相同名稱 stack 所建立的 VPC 資料。
跨 Pulumi 專案的 Output 使用這種需求,可以透過 StackReference
來達成。StackReference
的使用方式很簡單,只要使用要參考的專案的 Organization name、Project Name、Stack Name 資訊,即可參考另一個專案的 Output 資訊。
例如以下程式碼,會參考 pulumi-infra
專案相同 Stack 名稱的資訊。這邊我使用 pulumi.getOrganization()
取得目前 Project 所使用的 Pulumi Cloud 的組織名稱、pulumi.getStack()
取得目前執行的 Stack 名稱。
Note: 這邊預設所使用的 Backend 都是 Pulumi Cloud,如果是使用 Object Storage 或是本地檔案系統的話,組織名稱需要固定填寫
org
。
const currentOrg = pulumi.getOrganization();
const currentStack = pulumi.getStack();
const stackRef = new pulumi.StackReference(`${currentOrg}/pulumi-infra/${currentStack}`);
current_org = pulumi.get_organization()
current_stack = pulumi.get_stack()
infra_stack = pulumi.StackReference(f"{current_org}/pulumi-infra/{current_stack}")
如果想要使用其他名稱做為 StackReference 的名字的話,可以將要參考的專案路徑設定在參數中。例如以下程式碼可以達到同樣的效果:
const currentOrg = pulumi.getOrganization();
const currentStack = pulumi.getStack();
const stackRef = new pulumi.StackReference('infra_stack', {
name: `${currentOrg}/pulumi-infra/${currentStack}`
});
其實 StackReference
也是一種 Pulumi 中的 Resource。在顯示所有 Resource 時,可以看到 StackReference 也是一個 Resource。
Current stack resources (16):
TYPE NAME
pulumi:pulumi:Stack aws-vpc-ts-dev
├─ pulumi-practice:vpc:Vpc project-vpc
├─ pulumi:pulumi:StackReference xxx/pulumi-infra/dev
├─ pulumi:providers:pulumi default
└─ pulumi:providers:aws default_5_42_0
那又為何我們在使用 StackReference
時不需要指定 args 的參數,只要在 name 上指定要參考的 stack 位置就可以了呢?這其實是建立 StackReference
資源時,如果沒有拿到 args.name 的話,就會預設使用 Resource name 做為要參考的 Stack 名稱。
constructor(name, args, opts) {
args = args || {};
const stackReferenceName = args.name || name;
...
}
Note: Pulumi 中不支援跨 Backend 參考。意思是所有專案都必須使用同一個 Backend。如果是使用 S3 等 Object Storage,也必須在同一個 Bucket 之中。
StackReference 提供了以下的 Method 可用來存取 Stack 中的 Output 值:
public getOutput(name: Input<string>): Output<any>;
public getOutputValue(name: string): Promise<any>;
public requireOutput(name: Input<string>): Output<any>;
public requireOutputValue(name: string): Promise<any>;
這四個 method 主要可以分為兩組:
Input<string>
,取得 Output
型別的資料。string
,取得 Promise 型別的資料。get 與 require 的差別就與 Config 的 get 與 require 相同,get 可能會拿不到資料,而回傳 undefined;require 會確保資料存在,不存在就會拋出 Exception。
Note: Python 只有 getOutput 與 requireOutput
如果沒有特別需求的話,可以直接使用 getOutput 的方法取得其他 Stack 的 Output。
但 Output 處理起來有時候會比較麻煩,且 Output 值不能做為 Resource 的 name,官方也不建議在 Output.apply 內建立 Resource。這時就可以用 getOutputValue 取得資料,因為 getOutputValue 會回傳 Promise,可以直接使用 await 的方式取得 Promise 的值。這個方法就類似使用 aws.getAvailabilityZones
取得可用區一樣,一樣是回傳 Promise。
以下為使用兩種不同方式取得 pulumi-infra 專案 dev Stack 中的 VpcId 的方法:
// 取得另一個 Stack 中的 vpcId,型別為 Output<string>
const vpcIdOutput: pulumi.Output<string> = stackRef.getOutput("vpcId") as pulumi.Output<string>;
// 取得另一個 Stack 中的 vpcId,型別為 string
const vpcIdValue: string = await stackRef.getOutputValue("vpcId") as string;
// 取得另一個 Stack 中的 vpcId,型別為 Output[str]
vpc_id: pulumi.Output[str] = infra_stack.get_output('vpcId')
在 Pulumi 中,參考其他專案中的 Stack 應該是很常見的需求。不過目前的限制還是比較多。
因為 Pulumi 一開始開發就只支援 Pulumi Cloud,後期才開始支援不同的 Storage 做為 Backend。雖然個人使用 Pulumi Cloud 是完全免費的,但如果是企業使用就可能需要付費了。