我正在尝试使用terraform部署GCP API网关配置。OpenAPI文档在tf文件中定义,因为我需要为后端url使用变量。
当我在路径(/devices/{deviceID})中使用通配符时,部署会产生一个错误。如果没有通配符(/device),它可以正常工作。
这是带有通配符的资源规范:
resource "google_api_gateway_api_config" "device_management" {
provider = google-beta
project = var.project_id
api = google_api_gateway_api.device_management.api_id
api_config_id_prefix = "${google_api_gateway_api.device_management.api_id}-"
gateway_config {
backend_config {
google_service_account = google_service_account.device_registration.id
}
}
openapi_documents {
document {
path = "${google_api_gateway_api.device_management.api_id}_api_spec.yaml"
contents = base64encode(
jsonencode(
{
swagger : "2.0"
info : {
title : "Device Registration API"
description : "Register devices and get their private keys"
version : "0.0.1"
}
schemes : ["https"]
produces : ["application/json"]
x-google-allow : "configured"
securityDefinitions : {
api_key : {
type : "apiKey"
name : "apiKey"
in : "query"
}
oauth2 : {
authorizationUrl : ""
flow : "implicit"
type : "oauth2"
x-google-issuer : google_service_account.device_registration.email
x-google-jwks_uri : "https://www.googleapis.com/robot/v1/metadata/x509/${google_service_account.device_registration.email}"
x-google-audiences : "device-registration"
}
}
security : [
{ oauth2 : [] }
]
paths : {
"/devices/{deviceID}" : {
post : {
summary : "Register a new device"
operationId : "registerDevice"
x-google-backend : {
address : google_cloudfunctions_function.device_management_register_device.https_trigger_url
}
responses : {
201 : {
description : "Device registered succesfully"
schema : {
type : "string"
}
}
}
}
}
}
}
)
)
}
}
部署时,我得到以下错误:
Error: Error creating ApiConfig: googleapi: Error 400: Cannot convert to service config.
│ 'location: "unknown location"
│ kind: ERROR
│ message: "http: undefined field 'deviceID' on message 'google.protobuf.Empty'."
│
│ location: "unknown location"
│ kind: ERROR
│ message: "http: undefined field 'deviceID' on message 'google.protobuf.Empty'."
│
│ location: "device-registration_api_spec.yaml"
│ message: "apiKey 'apiKey' is ignored. Only apiKey with 'name' as 'key' and 'in' as 'query', or 'name' as 'api_key' and 'in' as 'query', or 'name'as 'x-api-key' and 'in' as 'header' are supported"
│
│ location: "device-registration_api_spec.yaml: Operation 'post' in path '/devices/{deviceID}'"
│ message: "Operation does not require an API key; callers may invoke the method without specifying an associated API-consuming project. To enable API key all the SecurityRequirement Objects (https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#security-requirement-object) inside security definition must reference at least one SecurityDefinition of type : 'apiKey'."
│
│ location: "device-registration_api_spec.yaml: Operation 'get' in path '/devices/{deviceID}/key'"
│ message: "Operation does not require an API key; callers may invoke the method without specifying an associated API-consuming project. To enable API key all the SecurityRequirement Objects (https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#security-requirement-object) inside security definition must reference at least one SecurityDefinition of type : 'apiKey'."
│ '
│ com.google.apps.framework.request.BadRequestException: Cannot convert to service config.
│ 'location: "unknown location"
│ kind: ERROR
│ message: "http: undefined field 'deviceID' on message 'google.protobuf.Empty'."
│
│ location: "unknown location"
│ kind: ERROR
│ message: "http: undefined field 'deviceID' on message 'google.protobuf.Empty'."
│
│ location: "device-registration_api_spec.yaml"
│ message: "apiKey 'apiKey' is ignored. Only apiKey with 'name' as 'key' and 'in' as 'query', or 'name' as 'api_key' and 'in' as 'query', or 'name'as 'x-api-key' and 'in' as 'header' are supported"
│
│ location: "device-registration_api_spec.yaml: Operation 'post' in path '/devices/{deviceID}'"
│ message: "Operation does not require an API key; callers may invoke the method without specifying an associated API-consuming project. To enable API key all the SecurityRequirement Objects (https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#security-requirement-object) inside security definition must reference at least one SecurityDefinition of type : 'apiKey'."
│
│ location: "device-registration_api_spec.yaml: Operation 'get' in path '/devices/{deviceID}/key'"
│ message: "Operation does not require an API key; callers may invoke the method without specifying an associated API-consuming project. To enable API key all the SecurityRequirement Objects (https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#security-requirement-object) inside security definition must reference at least one SecurityDefinition of type : 'apiKey'."
│ '
│
│ with module.iot_backend.google_api_gateway_api_config.device_management,
│ on ../../modules/iot_backend/device_management.tf line 92, in resource "google_api_gateway_api_config" "device_management":
│ 92: resource "google_api_gateway_api_config" "device_management" {
│
╵
如何使用通配符?
根据您的错误日志,您没有在参数部分或块中定义deviceID
。添加deviceID
参数的parameters部分。下面是一个例子:
paths:
/users/{userId}:
get:
summary: Gets a user by ID.
parameters:
- in: path
name: userId
type: integer
required: true
description: Numeric ID of the user to get.
在你的例子中,它应该是这样的:
paths : {
"/devices/{deviceID}" : {
post : {
summary : "Register a new device"
operationId : "registerDevice"
parameters : [
{
in : "path",
name : "deviceID",
type : "string",
required : "true"
}
],
x-google-backend : {
address : google_cloudfunctions_function.device_management_register_device.https_trigger_url
}
responses : {
201 : {
description : "Device registered succesfully"
schema : {
type : "string"
}
}
}
}
}
}
您可以参考这些文档,OpenAPI规范和Swagger,以获取更多信息。