Visual studio API网关的SAM模板在Visual Studio中有错误(作为无服务器应用程序解决方案的一部分)

Visual studio API网关的SAM模板在Visual Studio中有错误(作为无服务器应用程序解决方案的一部分),visual-studio,amazon-cloudformation,serverless-application-model,Visual Studio,Amazon Cloudformation,Serverless Application Model,我正在尝试在VisualStudio中创建SAM模板(serverless.template),以发布我的API网关。在模板验证过程中(在Visual Studio中)产生了几个错误,我无法解决这些错误。发布时,堆栈会部署,但没有创建使用计划或api密钥(或者说,它们是创建的,但在控制台中不可见,如果您尝试通过Cloudformation>Resources查看它们,它们将显示为“无效引用”,并且它们根本不会显示在api网关控制台中) 错误是: ServerLessRestapidDeploym

我正在尝试在VisualStudio中创建SAM模板(serverless.template),以发布我的API网关。在模板验证过程中(在Visual Studio中)产生了几个错误,我无法解决这些错误。发布时,堆栈会部署,但没有创建使用计划或api密钥(或者说,它们是创建的,但在控制台中不可见,如果您尝试通过Cloudformation>Resources查看它们,它们将显示为“无效引用”,并且它们根本不会显示在api网关控制台中)

错误是:

ServerLessRestapidDeployment26AAD1646F是未知引用

    "ServerlessRestApiProdStage": {
        "Type": "AWS::ApiGateway::Stage",
        "Properties": {
            "DeploymentId": {
                "Ref": "ServerlessRestApiDeployment26aad1646f"
            },
            "RestApiId": {
                "Ref": "ServerlessRestApi"
            },
            "StageName": "Prod"
        }
    },
    "APIGatewayHeartInHandKey": {
        "Type": "AWS::ApiGateway::ApiKey",
        "DependsOn": [
            "ServerlessRestApi",
            "ServerlessRestApiProdStage"
        ],
        "Properties": {
            "Name": "HeartInHandApiKey",
            "Description": "Api Key for Heart In Hand",
            "Enabled": true,
            "GenerateDistinctId": true,
            "StageKeys": [
                {
                    "RestApiId": {
                        "Ref": "ServerlessRestApi"
                    },
                    "StageName": {
                        "Ref": "ServerlessRestApiProdStage"
                    }
                }
            ]
        }
    },

ServerlessRestApiProdStage是此引用的无效类型

    "ServerlessRestApiProdStage": {
        "Type": "AWS::ApiGateway::Stage",
        "Properties": {
            "DeploymentId": {
                "Ref": "ServerlessRestApiDeployment26aad1646f"
            },
            "RestApiId": {
                "Ref": "ServerlessRestApi"
            },
            "StageName": "Prod"
        }
    },
    "APIGatewayHeartInHandKey": {
        "Type": "AWS::ApiGateway::ApiKey",
        "DependsOn": [
            "ServerlessRestApi",
            "ServerlessRestApiProdStage"
        ],
        "Properties": {
            "Name": "HeartInHandApiKey",
            "Description": "Api Key for Heart In Hand",
            "Enabled": true,
            "GenerateDistinctId": true,
            "StageKeys": [
                {
                    "RestApiId": {
                        "Ref": "ServerlessRestApi"
                    },
                    "StageName": {
                        "Ref": "ServerlessRestApiProdStage"
                    }
                }
            ]
        }
    },
完整的SAM模板如下所示

{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Transform": "AWS::Serverless-2016-10-31",
    "Description": "API Gateway to access InSite data-store",
    "Resources": {
        "Get": {
            "Type": "AWS::Serverless::Function",
            "Properties": {
                "VpcConfig": {
                    "SecurityGroupIds": [
                        "sg-111a1476"
                    ],
                    "SubnetIds": [
                        "subnet-3029a769",
                        "subnet-5ec0b928"
                    ]
                },
                "Handler": "AWSServerlessInSiteDataGw::AWSServerlessInSiteDataGw.Functions::Get",
                "Runtime": "dotnetcore2.0",
                "CodeUri": "",
                "MemorySize": 256,
                "Timeout": 30,
                "Role": null,
                "Policies": [
                    "AWSLambdaBasicExecutionRole",
                    "AWSLambdaVPCAccessExecutionRole",
                    "AmazonSSMFullAccess"
                ],
                "Events": {
                    "PutResource": {
                        "Type": "Api",
                        "Properties": {
                            "Path": "/",
                            "Method": "GET"
                        }
                    }
                }
            }
        },
        "GetTableBasic": {
            "Type": "AWS::Serverless::Function",
            "Properties": {
                "VpcConfig": {
                    "SecurityGroupIds": [
                        "sg-111a1476"
                    ],
                    "SubnetIds": [
                        "subnet-3029a769",
                        "subnet-5ec0b928"
                    ]
                },
                "Handler": "AWSServerlessInSiteDataGw::AWSServerlessInSiteDataGw.Functions::GetTableBasic",
                "Runtime": "dotnetcore2.0",
                "CodeUri": "",
                "MemorySize": 256,
                "Timeout": 30,
                "Role": null,
                "Policies": [
                    "AWSLambdaBasicExecutionRole",
                    "AWSLambdaVPCAccessExecutionRole",
                    "AmazonSSMFullAccess"
                ],
                "Events": {
                    "PutResource": {
                        "Type": "Api",
                        "Properties": {
                            "Path": "/tables/{tableid}/{columnid}",
                            "Method": "GET"
                        }
                    }
                }
            }
        },
        "GetColumnList": {
            "Type": "AWS::Serverless::Function",
            "Properties": {
                "VpcConfig": {
                    "SecurityGroupIds": [
                        "sg-111a1476"
                    ],
                    "SubnetIds": [
                        "subnet-3029a769",
                        "subnet-5ec0b928"
                    ]
                },
                "Handler": "AWSServerlessInSiteDataGw::AWSServerlessInSiteDataGw.Functions::GetColumnList",
                "Runtime": "dotnetcore2.0",
                "CodeUri": "",
                "MemorySize": 256,
                "Timeout": 30,
                "Role": null,
                "Policies": [
                    "AWSLambdaBasicExecutionRole",
                    "AWSLambdaVPCAccessExecutionRole",
                    "AmazonSSMFullAccess"
                ],
                "Events": {
                    "PutResource": {
                        "Type": "Api",
                        "Properties": {
                            "Path": "/list/columns/{tableid}",
                            "Method": "GET"
                        }
                    }
                }
            }
        },
        "GetTableList": {
            "Type": "AWS::Serverless::Function",
            "Properties": {
                "VpcConfig": {
                    "SecurityGroupIds": [
                        "sg-111a1476"
                    ],
                    "SubnetIds": [
                        "subnet-3029a769",
                        "subnet-5ec0b928"
                    ]
                },
                "Handler": "AWSServerlessInSiteDataGw::AWSServerlessInSiteDataGw.Functions::GetTableList",
                "Runtime": "dotnetcore2.0",
                "CodeUri": "",
                "MemorySize": 256,
                "Timeout": 30,
                "Role": null,
                "Policies": [
                    "AWSLambdaBasicExecutionRole",
                    "AWSLambdaVPCAccessExecutionRole",
                    "AmazonSSMFullAccess"
                ],
                "Events": {
                    "PutResource": {
                        "Type": "Api",
                        "Properties": {
                            "Path": "/list/tables",
                            "Method": "GET"
                        }
                    }
                }
            }
        },
        "PostClickCollectNotification": {
            "Type": "AWS::Serverless::Function",
            "Properties": {
                "VpcConfig": {
                    "SecurityGroupIds": [
                        "sg-111a1476"
                    ],
                    "SubnetIds": [
                        "subnet-3029a769",
                        "subnet-5ec0b928"
                    ]
                },
                "Handler": "AWSServerlessInSiteDataGw::AWSServerlessInSiteDataGw.Functions::PostClickCollectNotification",
                "Runtime": "dotnetcore2.0",
                "CodeUri": "",
                "MemorySize": 256,
                "Timeout": 30,
                "Role": null,
                "Policies": [
                    "AWSLambdaBasicExecutionRole",
                    "AWSLambdaVPCAccessExecutionRole",
                    "AmazonSSMFullAccess"
                ],
                "Events": {
                    "PutResource": {
                        "Type": "Api",
                        "Properties": {
                            "Path": "/datagw/general/webhook/ccnotify",
                            "Method": "POST"
                        }
                    }
                }
            }
        },
        "PostClickCollectStockUpdate": {
            "Type": "AWS::Serverless::Function",
            "Properties": {
                "VpcConfig": {
                    "SecurityGroupIds": [
                        "sg-111a1476"
                    ],
                    "SubnetIds": [
                        "subnet-3029a769",
                        "subnet-5ec0b928"
                    ]
                },
                "Handler": "AWSServerlessInSiteDataGw::AWSServerlessInSiteDataGw.Functions::PostClickCollectStockUpdate",
                "Runtime": "dotnetcore2.0",
                "CodeUri": "",
                "MemorySize": 256,
                "Timeout": 30,
                "Role": null,
                "Policies": [
                    "AWSLambdaBasicExecutionRole",
                    "AWSLambdaVPCAccessExecutionRole",
                    "AmazonSSMFullAccess"
                ],
                "Events": {
                    "PutResource": {
                        "Type": "Api",
                        "Properties": {
                            "Path": "/datagw/general/post/sohupdate",
                            "Method": "POST"
                        }
                    }
                }
            }
        },
        "GetTableResponse": {
            "Type": "AWS::Serverless::Function",
            "Properties": {
                "VpcConfig": {
                    "SecurityGroupIds": [
                        "sg-111a1476"
                    ],
                    "SubnetIds": [
                        "subnet-3029a769",
                        "subnet-5ec0b928"
                    ]
                },
                "Handler": "AWSServerlessInSiteDataGw::AWSServerlessInSiteDataGw.Functions::GetTableResponse",
                "Runtime": "dotnetcore2.0",
                "CodeUri": "",
                "MemorySize": 256,
                "Timeout": 30,
                "Role": null,
                "Policies": [
                    "AWSLambdaBasicExecutionRole",
                    "AWSLambdaVPCAccessExecutionRole",
                    "AmazonSSMFullAccess"
                ],
                "Events": {
                    "PutResource": {
                        "Type": "Api",
                        "Properties": {
                            "Path": "datagw/general/table/get/{tableid}",
                            "Method": "GET"
                        }
                    }
                }
            }
        },
        "ServerlessRestApi": {
            "Type": "AWS::ApiGateway::RestApi",
            "Properties": {
                "Description":"This is a placeholder for the description of this web api",
                "ApiKeySourceType":"HEADER",
                "Body": {
                    "info": {
                        "version": "1.0",
                        "title": {
                            "Ref": "AWS::StackName"
                        }
                    },
                    "paths": {
                        "/list/tables": {
                            "get": {
                                "x-amazon-apigateway-integration": {
                                    "httpMethod": "POST",
                                    "type": "aws_proxy",
                                    "uri": {
                                        "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${GetTableList.Arn}/invocations"
                                    }
                                },
                                "responses": {}
                            }
                        },
                        "/list/columns/{tableid}": {
                            "get": {
                                "x-amazon-apigateway-integration": {
                                    "httpMethod": "POST",
                                    "type": "aws_proxy",
                                    "uri": {
                                        "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${GetColumnList.Arn}/invocations"
                                    }
                                },
                                "responses": {}
                            }
                        },
                        "datagw/general/table/get/{tableid}": {
                            "get": {
                                "x-amazon-apigateway-integration": {
                                    "httpMethod": "POST",
                                    "type": "aws_proxy",
                                    "uri": {
                                        "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${GetTableResponse.Arn}/invocations"
                                    }
                                },
                                "responses": {}
                            }
                        },
                        "/": {
                            "get": {
                                "x-amazon-apigateway-integration": {
                                    "httpMethod": "POST",
                                    "type": "aws_proxy",
                                    "uri": {
                                        "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${Get.Arn}/invocations"
                                    }
                                },
                                "responses": {}
                            }
                        },
                        "/tables/{tableid}/{columnid}": {
                            "get": {
                                "x-amazon-apigateway-integration": {
                                    "httpMethod": "POST",
                                    "type": "aws_proxy",
                                    "uri": {
                                        "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${GetTableBasic.Arn}/invocations"
                                    }
                                },
                                "responses": {}
                            }
                        }
                    },
                    "swagger": "2.0"
                }
            }
        },
        "ServerlessRestApiProdStage": {
            "Type": "AWS::ApiGateway::Stage",
            "Properties": {
                "DeploymentId": {
                    "Ref": "ServerlessRestApiDeployment26aad1646f"
                },
                "RestApiId": {
                    "Ref": "ServerlessRestApi"
                },
                "StageName": "Prod"
            }
        },
        "CustomLambdaExecutionRole": {
            "Type": "AWS::IAM::Role",
            "Properties": {
                "AssumeRolePolicyDocument": {
                    "Version": "2012-10-17",
                    "Statement": [
                        {
                            "Effect": "Allow",
                            "Principal": {
                                "Service": [
                                    "lambda.amazonaws.com"
                                ]
                            },
                            "Action": [
                                "sts:AssumeRole"
                            ]
                        }
                    ]
                },
                "Policies": [
                    {
                        "PolicyName": "lambdaAccessApiKeys",
                        "PolicyDocument": {
                            "Version": "2012-10-17",
                            "Statement": [
                                {
                                    "Effect": "Allow",
                                    "Action": [
                                        "apigateway:GET"
                                    ],
                                    "Resource": {
                                        "Fn::Sub": [
                                            "arn:aws:apigateway:ap-southeast-2::/apikeys/${__keyId__}",
                                            {
                                                "__keyId__": {
                                                    "Ref": "APIGatewayHeartInHandKey"
                                                }
                                            }
                                        ]
                                    }
                                }
                            ]
                        }
                    }
                ]
            }
        },
        "GetApiKeyValueLambdaFunction": {
            "Type": "AWS::Lambda::Function",
            "Properties": {
                "Code": {
                    "ZipFile": {
                        "Fn::Join": [
                            "\n",
                            [
                                "import json",
                                "import boto3",
                                "client = boto3.client('apigateway')",
                                "def lambda_handler(event, context):",
                                "   response = client.get_api_key(",
                                "   apiKey= event['apiKeyId'],",
                                "   includeValue = True",
                                ")",
                                "   return {",
                                "       'statusCode': 200,",
                                "       'body': response['value']}"
                            ]
                        ]
                    }
                },
                "Handler": "index.lambda_handler",
                "Runtime": "python3.6",
                "Timeout": 30,
                "Role": {
                    "Fn::GetAtt": [
                        "CustomLambdaExecutionRole",
                        "Arn"
                    ]
                }
            }
        },
        "APIGatewayUsagePlanInternal": {
            "Type": "AWS::ApiGateway::UsagePlan",
            "Properties": {
                "ApiStages": [
                    {
                        "ApiId": {
                            "Ref": "ServerlessRestApi"
                        },
                        "Stage": {
                            "Ref": "ServerlessRestApiProdStage"
                        }
                    }
                ],
                "Description": "Internal Apps Usage Plan",
                "UsagePlanName": "Insite-datagw-InternalAppPlan"
            }
        },
        "APIGatewayUsagePlanExternal": {
            "Type": "AWS::ApiGateway::UsagePlan",
            "Properties": {
                "ApiStages": [
                    {
                        "ApiId": {
                            "Ref": "ServerlessRestApi"
                        },
                        "Stage": {
                            "Ref": "ServerlessRestApiProdStage"
                        }
                    }
                ],
                "Description": "External Apps Usage Plan",
                "UsagePlanName": "InSite-datagw-ExternalAppPlan"
            }
        },
        "APIGatewayHeartInHandKey": {
            "Type": "AWS::ApiGateway::ApiKey",
            "DependsOn": [
                "ServerlessRestApi",
                "ServerlessRestApiProdStage"
            ],
            "Properties": {
                "Name": "HeartInHandApiKey",
                "Description": "Api Key for Heart In Hand",
                "Enabled": true,
                "GenerateDistinctId": true,
                "StageKeys": [
                    {
                        "RestApiId": {
                            "Ref": "ServerlessRestApi"
                        },
                        "StageName": {
                            "Ref": "ServerlessRestApiProdStage"
                        }
                    }
                ]
            }
        },
        "LinkHeartInHandKey": {
            "Type": "AWS::ApiGateway::UsagePlanKey",
            "Properties": {
                "KeyId": {
                    "Ref": "APIGatewayHeartInHandKey"
                },
                "KeyType": "API_KEY",
                "UsagePlanId": {
                    "Ref": "APIGatewayUsagePlanInternal"
                }
            }
        },
        "APIGatewayPricelineSiteKey": {
            "Type": "AWS::ApiGateway::ApiKey",
            "DependsOn": [
                "ServerlessRestApi",
                "ServerlessRestApiProdStage"
            ],
            "Properties": {
                "Name": "PricelineSiteApiKey",
                "Description": "Api Key for Priceline Website",
                "Enabled": true,
                "GenerateDistinctId": true,
                "StageKeys": [
                    {
                        "RestApiId": {
                            "Ref": "ServerlessRestApi"
                        },
                        "StageName": {
                            "Ref": "ServerlessRestApiProdStage"
                        }
                    }
                ]
            }
        },
        "LinkPricelineSiteKey": {
            "Type": "AWS::ApiGateway::UsagePlanKey",
            "Properties": {
                "KeyId": {
                    "Ref": "APIGatewayPricelineSiteKey"
                },
                "KeyType": "API_KEY",
                "UsagePlanId": {
                    "Ref": "APIGatewayUsagePlanInternal"
                }
            }
        }
    },
    "Outputs": {
        "ApiURL": {
            "Description": "API endpoint URL for Prod environment",
            "Value": {
                "Fn::Sub": "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/"
            }
        }
    }
}

看起来您试图使用SAM的
AWS::Serverless::Api
资源的功能,而不在模板中定义
AWS::Serverless::Api

为了解决您提出的问题,您需要:

删除
ServerlessRestApiProdStage
资源

如果您使用
AWS::Serverless::Api
资源,Sam将为您生成此资源(以及部署资源)

将您的
AWS::ApiGateway::RestApi
资源转换为
AWS::Serverless::Api
资源:

  • 删除
    ApiKeySourceType
    属性,并将
    “x-amazon-apigateway-api-key-source”:“HEADER”、
    添加到swagger中
  • 将类型从
    AWS::ApiGateway::RestApi
    更改为
    AWS::Serverless::Api

嗨,基顿。如果我按照您的建议删除serverlessrestapiprodstage,那么我应该为模板中显示的api键在StageName中输入什么值?