[英]Pulumi Outputs - create an external config file
我正在 GCP 中使用 Cloudrun,并想用 API Gateway 总结创建的 API。 这需要创建一个包含 Google 为 Cloudrun 服务生成的 URL 的Swagger/OpenAPI v2文档。
如何将这些从 Pulumi 输出获取到 swagger 文件中以作为 API 配置上传?
我最初希望使用 Moustache。 但是现在我正在尝试使用原始 JSON,但仍然没有成功。 我试过apply()
和interpolate
但总是[object Object]
从来没有部署服务的 url。
"x-google-backend": {
"address": {
"[object Object]":null
},
"path_translation":"APPEND_PATH_TO_ADDRESS"
}
我错过了什么?
是否可以直接使用小胡子进行此操作,而无需使用反序列化的 Swagger?
重新创建的代码:
一个基本的 Swagger 文件my-spec.yaml
swagger: '2.0'
info:
title: Demo for URL Replacement
version: 0.0.1
schemes:
- https
paths:
/users:
post:
summary: Registers a new user to the service
operationId: createUser
x-google-backend:
address: {{{apiUsersUrl}}} # Output URL from CloudRun, in moustache format
path_translation: APPEND_PATH_TO_ADDRESS
responses:
201:
description: Success
security:
- api_key: []
securityDefinitions:
api_key:
type: apiKey
name: x-api-key
in: header
我的文件来编写新的 API 配置。
import * as pulumi from '@pulumi/pulumi';
import * as yaml from 'js-yaml';
import * as fs from 'fs';
import { Spec } from '../types/Swagger';
export function buildApiSpecJS(usersUrl: pulumi.Output<string>) {
const specFile = fs.readFileSync(`${__dirname}/my-spec.yaml`, 'utf8');
const specTemplate= yaml.load(specFile) as Spec;
usersUrl.apply((url) => {
let pathName: keyof typeof specTemplate.paths;
// eslint-disable-next-line guard-for-in
for (pathName in specTemplate.paths) {
const path = specTemplate.paths[pathName];
let operation: keyof typeof path;
for (operation in path) {
if (path[operation] !== '$ref') {
const address: string = path[operation]['x-google-backend']?.address;
if (address === '{{{apiUsersUrl}}}') {
path[operation]['x-google-backend'].address = pulumi.interpolate`${url}`;
}
}
}
}
fs.writeFileSync(`${__dirname}/testfile.json`, JSON.stringify(specTemplate));
});
}
// Changes:
// - Operation is edited to add the Google Backend
export interface GoogleBackend {
address: string;
jwt_audience?: string;
disable_auth?: boolean;
path_translation?: string; // [ APPEND_PATH_TO_ADDRESS | CONSTANT_ADDRESS ]
deadline?: string;
protocol?: string; // [ http/1.1 | h2 ]
};
//
///// .... Copied Types ....
//
// ----------------------------- Operation -----------------------------------
export interface Operation {
responses: { [responseName: string]: Response | Reference };
summary?: string | undefined;
description?: string | undefined;
externalDocs?: ExternalDocs | undefined;
operationId?: string | undefined;
produces?: string[] | undefined;
consumes?: string[] | undefined;
parameters?: Array<Parameter | Reference> | undefined;
schemes?: string[] | undefined;
deprecated?: boolean | undefined;
security?: Array<{ [securityDefinitionName: string]: string[] }> | undefined;
tags?: string[] | undefined;
'x-google-backend': GoogleBackend | undefined; // Added
}
//
///// Copied Types continue....
//
我找到的解决方案是 DomainMapping 和 DNS。 我使用 DomainMapping 在每个环境中为 Cloud Run 服务创建一个可预测的名称。 例如api-users.dev.example.com
。
然后,因为我提前知道该名称,所以我可以将它用于 API 规范中的 Mustache 替换。
我用以下代码解决了这个问题 - 我有一个主模板文件,它被复制到一个特定于堆栈的 OpenAPI .yaml 文件中。
import * as pulumi from '@pulumi/pulumi';
import * as gcp from '@pulumi/gcp';
import * as fs from 'fs';
import { helloWorldUrl } from '../cloud-run/hello-world';
import { Output } from '@pulumi/pulumi/output';
import * as Mustache from 'mustache';
const config = new pulumi.Config();
const region = config.get('region');
const google_beta = new gcp.Provider('provider', {
project: 'temp-22223'
});
// overwrite file
(async () => {
try {
helloWorldUrl.apply(url => {
let gatewayOpenAPI = fs.readFileSync('./api-gateway/open-api/gateway.yaml').toString();
gatewayOpenAPI = Mustache.render(gatewayOpenAPI, { helloWorldUrl: url });
fs.writeFileSync(`./api-gateway/open-api/gateway-${pulumi.getStack()}.yaml`, gatewayOpenAPI);
});
} catch (e) {
console.error(e);
}
})();
// always create new config
const apiCfgApi = new gcp.apigateway.Api('api', { apiId: `api-cfg${new Date().getTime()}` },
{
provider: google_beta
});
const gatewayOpenAPI = fs.readFileSync(`./api-gateway/open-api/gateway-${pulumi.getStack()}.yaml`).toString('base64');
const apiCfgApiConfig = new gcp.apigateway.ApiConfig('apiCfg', {
api: apiCfgApi.apiId,
apiConfigId: 'cfg',
project: 'temp-22223',
openapiDocuments: [{
document: {
path: 'gateway.yaml',
contents: gatewayOpenAPI
},
}],
},
{
provider: google_beta,
});
const apiGwGateway = new gcp.apigateway.Gateway("apiGw", {
apiConfig: apiCfgApiConfig.id,
gatewayId: "api-gw",
region: region
},
{
provider: google_beta,
});
export let gatewayUrl = apiGwGateway.defaultHostname;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.