{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Description": "Custom::ApiGatewayResourceTree sample template",
  "Parameters": {
    "aaToggleConditionalRoute": {
      "Type": "String",
      "Description": "Use this to demonstrate UPDATE functionality.",
      "Default": "TOGGLE_ON",
      "AllowedValues": [
        "TOGGLE_ON",
        "TOGGLE_OFF"
      ]
    },
    "ResourceTreeCustomResourceLambdaName": {
      "Type": "String",
      "Default": "cfn-api-gateway-resource-tree-0-3-0",
      "Description": "The name of the ApiGatewayResourceTree Lambda you deployed to test this stack."
    },
    "RestApiCustomResourceLambdaName": {
      "Type": "String",
      "Default": "cfn-api-gateway-restapi-0-6-0",
      "Description": "The name of the ApiGatewayRestApi Lambda you deployed to test this stack."
    },
    "RestApiName": {
      "Type": "String",
      "Description": "Name for the API (required). Must be unique across your account for this Region.",
      "Default": "MyRestApiForResourceTree"
    },
    "RestApiDescription": {
      "Type": "String",
      "Description": "Description for the API (optional)."
    },
    "RestApiBaseApiId": {
      "Type": "String",
      "Description": "API ID (not name, not ARN) from which to clone the base for the new API (optional). WARNING: Changing this value requires full replacement."
    },
    "MethodCustomResourceLambdaName": {
      "Type": "String",
      "Default": "cfn-api-gateway-method-0-3-0",
      "Description": "The name of the ApiGatewayMethod Lambda you deployed to test this stack."
    },
    "MethodAuthorizationType": {
      "Type": "String",
      "Default": "NONE",
      "Description": "Whether or not to require IAM authorization to invoke the method.",
      "AllowedValues": [
        "NONE",
        "AWS_IAM"
      ]
    },
    "MethodHttpMethod": {
      "Type": "String",
      "Default": "GET",
      "Description": "The HTTP method your deployed Method should use.",
      "AllowedValues": [
        "DELETE",
        "GET",
        "HEAD",
        "OPTIONS",
        "PATCH",
        "POST",
        "PUT"
      ]
    },
    "MyMethodMainStatusCode": {
      "Type": "String",
      "AllowedPattern": "^\\d{3}$",
      "Default": "200",
      "Description": "The HTTP status code for the method we are trying out here."
    },
    "DoesMethodRequireApiKey": {
      "Type": "String",
      "Default": "NO",
      "Description": "Whether or not to require use of an API Key on the created method.",
      "AllowedValues": [
        "NO",
        "YES"
      ]
    },
    "MethodResponseCustomResourceLambdaName": {
      "Type": "String",
      "Default": "cfn-api-gateway-method-response-0-2-0",
      "Description": "The name of the ApiGatewayMethodResponse Lambda you deployed to test this stack."
    },
    "IntegrationCustomResourceLambdaName": {
      "Type": "String",
      "Default": "cfn-api-gateway-integration-0-2-0",
      "Description": "The name of the ApiGatewayIntegration Lambda you deployed to test this stack."
    },
    "IntegrationResponseCustomResourceLambdaName": {
      "Type": "String",
      "Default": "cfn-api-gateway-integration-response-0-2-1",
      "Description": "The name of the ApiGatewayIntegrationResponse Lambda you deployed to test this stack."
    },
    "DeploymentCustomResourceLambdaName": {
     "Type": "String",
      "Default": "cfn-api-gateway-deployment-0-3-0",
      "Description": "The name of the ApiGatewayDeployment Lambda you deployed to test this stack."
    },
    "DeploymentStageName": {
      "Type": "String",
      "Description": "The name of the API stage you would like to deploy",
      "AllowedPattern": "^\\w+$",
      "Default": "tree_demo"
    },
    "DeploymentStageDescription": {
      "Type": "String",
      "Description": "Description for the API Deployment Stage (optional)."
    },
    "DeploymentDescription": {
      "Type": "String",
      "Description": "Description for the API Deployment (optional)."
    },
    "EnableDeploymentCacheCluster": {
      "Type": "String",
      "AllowedValues": [
        "Yes",
        "No"
      ],
      "Default": "No",
      "Description": "Whether or not to use a cache layer on top of the API Deployment."
    },
    "DeploymentCacheClusterSizeInGigabytes": {
      "Type": "String",
      "AllowedValues": [
        "",
        "0.5",
        "1.6",
        "6.1",
        "13.5",
        "28.4",
        "58.2",
        "118",
        "237"
      ],
      "Default": ""
    },
    "DeploymentStageVariableFooValue": {
      "Type": "String",
      "Description": "Try different values to test",
      "AllowedPattern": "^[\\^\\-._:\/?&=,\\w]+",
      "Default": "Bar"
    }
  },
  "Conditions": {
    "ShouldToggleOn": {
      "Fn::Equals": [
        "TOGGLE_ON",
        {
          "Ref": "aaToggleConditionalRoute"
        }
      ]
    },
    "NoApiDescription": {
      "Fn::Equals": [
        "",
        {
          "Ref": "RestApiDescription"
        }
      ]
    },
    "NoApiBaseApiId": {
      "Fn::Equals": [
        "",
        {
          "Ref": "RestApiBaseApiId"
        }
      ]
    },
    "MethodRequiresApiKey": {
      "Fn::Equals": [
        "YES",
        {
          "Ref": "DoesMethodRequireApiKey"
        }
      ]
    },
    "NoDeploymentStageDescription": {
      "Fn::Equals": [
        "",
        {
          "Ref": "DeploymentStageDescription"
        }
      ]
    },
    "NoDeploymentDescription": {
      "Fn::Equals": [
        "",
        {
          "Ref": "DeploymentDescription"
        }
      ]
    },
    "ShouldDeployCacheCluster": {
      "Fn::And": [
        {
          "Fn::Equals": [
            "Yes",
            {
              "Ref": "EnableDeploymentCacheCluster"
            }
          ]
        },
        {
          "Fn::Not": [
            {
              "Fn::Equals": [
                "",
                {
                  "Ref": "DeploymentCacheClusterSizeInGigabytes"
                }
              ]
            }
          ]
        }
      ]
    },
    "ShouldOmitStageVariables": {
      "Fn::Equals": [
        "",
        {
          "Ref": "DeploymentStageVariableFooValue"
        }
      ]
    }
  },
  "Resources": {
    "MyRestApi": {
      "Type": "Custom::ApiGatewayRestApi",   
      "Properties": {
        "ServiceToken": {
          "Fn::Join": [
            ":",
            [
              "arn",
              "aws",
              "lambda",
              {
                "Ref": "AWS::Region"
              },
              {
                "Ref": "AWS::AccountId"
              },
              "function",
              {
                "Ref": "RestApiCustomResourceLambdaName"
              }
            ]
          ]
        },
        "Name": {
          "Ref": "RestApiName"
        },
        "Description": {
          "Fn::If": [
            "NoApiDescription",
            {
              "Ref": "AWS::NoValue"
            },
            {
              "Ref": "RestApiDescription"
            }
          ]
        },
        "BaseApiId": {
          "Fn::If": [
            "NoApiBaseApiId",
            {
              "Ref": "AWS::NoValue"
            },
            {
              "Ref": "RestApiBaseApiId"
            }
          ]
        }
      }
    },
    "MyResourceTree": {
      "DependsOn": [
        "MyRestApi"
      ],
      "Type": "Custom::ApiGatewayResourceTree",
      "Properties": {
        "ServiceToken": {
          "Fn::Join": [
            ":",
            [
              "arn",
              "aws",
              "lambda",
              {
                "Ref": "AWS::Region"
              },
              {
                "Ref": "AWS::AccountId"
              },
              "function",
              {
                "Ref": "ResourceTreeCustomResourceLambdaName"
              }
            ]
          ]
        },
        "ParentId": {
          "Fn::GetAtt": [
            "MyRestApi",
            "RootResourceId"
          ]
        },
        "RestApiId": {
          "Ref": "MyRestApi"
        },
        "ChildResources": [
          {
            "PathPart": "childless"
          },
          {
            "PathPart": "toggle_my_child",
            "ChildResources": {
              "Fn::If": [
                "ShouldToggleOn",
                [
                  {
                    "PathPart": "toggleable"
                  }
                ],
                {
                  "Ref": "AWS::NoValue"
                }
              ]
            }
          },
          {
            "PathPart": "methodless",
            "ChildResources": [
              {
                "PathPart": "with"
              },
              {
                "PathPart": "many"
              },
              {
                "PathPart": "child"
              },
              {
                "PathPart": "resources"
              }
            ]
          },
          {
            "PathPart": "foo",
            "ChildResources": [
              {
                "PathPart": "{id}",
                "ChildResources": [
                  {
                    "PathPart": "baz"
                  }
                ]
              }
            ]
          }
        ]
      }
    },
    "MyMethod": {
      "DependsOn": [
        "MyRestApi",
        "MyResourceTree"
      ],
      "Type": "Custom::ApiGatewayMethod",
      "Properties": {
        "ServiceToken": {
          "Fn::Join": [
            ":",
            [
              "arn",
              "aws",
              "lambda",
              {
                "Ref": "AWS::Region"
              },
              {
                "Ref": "AWS::AccountId"
              },
              "function",
              {
                "Ref": "MethodCustomResourceLambdaName"
              }
            ]
          ]
        },
        "ApiKeyRequired": {
          "Fn::If": [
            "MethodRequiresApiKey",
            true,
            false
          ]
        },
        "AuthorizationType": {
          "Ref": "MethodAuthorizationType"
        },
        "HttpMethod": {
          "Ref": "MethodHttpMethod"
        },
        "ResourceId": {
          "Fn::GetAtt": [
            "MyResourceTree",
            "/foo/{id}/baz"
          ]
        },
        "RestApiId": {
          "Ref": "MyRestApi"
        },
        "RequestModels": {
          "application/json": "Empty"
        },
        "RequestParameters": {
          "method.request.querystring.MapMe": true
        }
      }
    },
    "MyMethodResponseOk": {
      "DependsOn": [
        "MyRestApi",
        "MyResourceTree",
        "MyMethod"
      ],
      "Type": "Custom::ApiGatewayMethodResponse",
      "Properties": {
        "ServiceToken": {
          "Fn::Join": [
            ":",
            [
              "arn",
              "aws",
              "lambda",
              {
                "Ref": "AWS::Region"
              },
              {
                "Ref": "AWS::AccountId"
              },
              "function",
              {
                "Ref": "MethodResponseCustomResourceLambdaName"
              }
            ]
          ]
        },
        "StatusCode": {
          "Ref": "MyMethodMainStatusCode"
        },
        "HttpMethod": {
          "Ref": "MethodHttpMethod"
        },
        "ResourceId": {
          "Fn::GetAtt": [
            "MyResourceTree",
            "/foo/{id}/baz"
          ]
        },
        "RestApiId": {
          "Ref": "MyRestApi"
        },
        "ResponseModels": {
          "application/json": "Empty"
        },
        "ResponseParameters": {
          "method.response.header.Access-Control-Allow-Origin": true,
          "method.response.header.Access-Control-Allow-Methods": true
        }
      }
    },
    "MyIntegration": {
      "DependsOn": [
        "MyRestApi",
        "MyResourceTree",
        "MyMethod",
        "MyMethodResponseOk",
        "IntegrationLambda",
        "IntegrationCredentialsRole"
      ],
      "Type": "Custom::ApiGatewayIntegration",
      "Properties": {
        "ServiceToken": {
          "Fn::Join": [
            ":",
            [
              "arn",
              "aws",
              "lambda",
              {
                "Ref": "AWS::Region"
              },
              {
                "Ref": "AWS::AccountId"
              },
              "function",
              {
                "Ref": "IntegrationCustomResourceLambdaName"
              }
            ]
          ]
        },
        "Type": "AWS",
        "HttpMethod": {
          "Ref": "MethodHttpMethod"
        },
        "IntegrationHttpMethod": "POST",
        "ResourceId": {
          "Fn::GetAtt": [
            "MyResourceTree",
            "/foo/{id}/baz"
          ]
        },
        "RestApiId": {
          "Ref": "MyRestApi"
        },
        "Uri": {
          "Fn::Join": [
            "",
            [
              "arn:aws:apigateway:",
              {
                "Ref": "AWS::Region"
              },
              ":lambda:path/2015-03-31/functions/",
              {
                "Fn::GetAtt": [
                  "IntegrationLambda",
                  "Arn"
                ]
              },
              "/invocations"
            ]
          ]
        },
        "Credentials": {
          "Fn::GetAtt": [
            "IntegrationCredentialsRole",
            "Arn"
          ]
        },
        "RequestTemplates": {
          "application/json": {
            "Fn::Join": [
              "\n",
              [
                "{",
                "  \"hello\": \"world\",",
                "  \"MapMeFromHeader\": \"$input.params().querystring.get('MapMe')\"",
                "}"
              ]
            ]
          }
        },
        "RequestParameters": {
          "integration.request.querystring.MapMe": "method.request.querystring.MapMe"
        }
      }
    },
    "IntegrationLambda": {
      "DependsOn": [
        "IntegrationLambdaExecutionRole"
      ],
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "ZipFile": {
            "Fn::Join": [
              "\n",
              [
                "exports.handler = function(event, context) {",
                "  console.log('The debugging Lambda was called.');",
                "  console.log('Event: %j', event);",
                "  console.log('Context: %j', context);",
                "  event.addedProperty = 'addedValue';",
                "  context.succeed(event);",
                "};"
              ]
            ]
          }
        },
        "Description": "Lambda to integrate test asset with.",
        "Handler": "index.handler",
        "MemorySize": 128,
        "Role": {
          "Fn::GetAtt": [
            "IntegrationLambdaExecutionRole",
            "Arn"
          ]
        },
        "Runtime": "nodejs",
        "Timeout": 300
      }
    },
    "IntegrationCredentialsRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version" : "2012-10-17",
          "Statement": [ 
            {
              "Effect": "Allow",
              "Principal": {
                "Service": [
                  "apigateway.amazonaws.com"
                ]
              },
              "Action": [
                "sts:AssumeRole"
              ]
            }
          ]
        },
        "Path": "/",
        "Policies": [
          {
            "PolicyName": {
              "Fn::Join": [
                "",
                [
                  "IntegrationCredentialsRole",
                  {
                    "Ref": "AWS::StackName"
                  }
                ]
              ]
            },
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": "lambda:InvokeFunction",
                  "Resource": "*"
                }
              ]
            }
          }
        ]
      }
    },
    "IntegrationLambdaExecutionRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version" : "2012-10-17",
          "Statement": [ 
            {
              "Effect": "Allow",
              "Principal": {
                "Service": [
                  "lambda.amazonaws.com"
                ]
              },
              "Action": [
                "sts:AssumeRole"
              ]
            }
          ]
        },
        "Path": "/",
        "Policies": [
          {
            "PolicyName": {
              "Fn::Join": [
                "",
                [
                  "IntegrationLambdaExecutionRole",
                  {
                    "Ref": "AWS::StackName"
                  }
                ]
              ]
            },
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Effect": "Allow",
                  "Resource": "arn:aws:logs:*:*:*"
                }
              ]
            }
          }
        ]
      }
    },
    "MyIntegrationResponse": {
      "DependsOn": [
        "MyRestApi",
        "MyResourceTree",
        "MyMethod",
        "MyMethodResponseOk",
        "MyIntegration"
      ],
      "Type": "Custom::ApiGatewayIntegrationResponse",
      "Properties": {
        "ServiceToken": {
          "Fn::Join": [
            ":",
            [
              "arn",
              "aws",
              "lambda",
              {
                "Ref": "AWS::Region"
              },
              {
                "Ref": "AWS::AccountId"
              },
              "function",
              {
                "Ref": "IntegrationResponseCustomResourceLambdaName"
              }
            ]
          ]
        },
        "StatusCode": {
          "Ref": "MyMethodMainStatusCode"
        },
        "RestApiId": {
          "Ref": "MyRestApi"
        },
        "HttpMethod": {
          "Ref": "MethodHttpMethod"
        },
        "ResourceId": {
          "Fn::GetAtt": [
            "MyResourceTree",
            "/foo/{id}/baz"
          ]
        },
        "SelectionPattern": ".*",
        "ResponseTemplates": {
          "application/json": {
            "Fn::Join": [
              "\n",
              [
                "{",
                "  \"hoistedResponse\": $input.json('$')",
                "}"
              ]
            ]
          }
        },
        "ResponseParameters": {
          "method.response.header.Access-Control-Allow-Origin": "'*'",
          "method.response.header.Access-Control-Allow-Methods": {
            "Fn::Join": [
              "",
              [
                "",
                "'",
                {
                  "Ref": "MethodHttpMethod"
                },
                ", OPTIONS",
                "'"
              ]
            ]
          }
        }
      }
    },
    "MyApiDeployment": {
      "DependsOn": [
        "MyRestApi",
        "MyResourceTree",
        "MyMethod",
        "MyMethodResponseOk",
        "MyIntegration",
        "MyIntegrationResponse"
      ],
      "Type": "Custom::ApiGatewayDeployment",
      "Properties": {
        "ServiceToken": {
          "Fn::Join": [
            ":",
            [
              "arn",
              "aws",
              "lambda",
              {
                "Ref": "AWS::Region"
              },
              {
                "Ref": "AWS::AccountId"
              },
              "function",
              {
                "Ref": "DeploymentCustomResourceLambdaName"
              }
            ]
          ]
        },
        "RestApiId": {
          "Ref": "MyRestApi"
        },
        "StageName": {
          "Ref": "DeploymentStageName"
        },
        "StageDescription": {
          "Fn::If": [
            "NoDeploymentStageDescription",
            {
              "Ref": "AWS::NoValue"
            },
            {
              "Ref": "DeploymentStageDescription"
            }
          ]
        },
        "Description": {
          "Fn::If": [
            "NoDeploymentDescription",
            {
              "Ref": "AWS::NoValue"
            },
            {
              "Ref": "DeploymentDescription"
            }
          ]
        },
        "CacheClusterEnabled": {
          "Fn::If": [
            "ShouldDeployCacheCluster",
            true,
            false
          ]
        },
        "CacheClusterSize": {
          "Fn::If": [
            "ShouldDeployCacheCluster",
            {
              "Ref": "DeploymentCacheClusterSizeInGigabytes"
            },
            {
              "Ref": "AWS::NoValue"
            }
          ]
        },
        "Variables": {
          "Foo": {
            "Fn::If": [
              "ShouldOmitStageVariables",
              {
                "Ref": "AWS::NoValue"
              },
              {
                "Ref": "DeploymentStageVariableFooValue"
              }
            ]
          }
        }
      }
    }
  },
  "Outputs": {
    "aSampleResourceTreeEndpoint": {
      "Description": "A nested resource created by the tree.",
      "Value": {
        "Fn::Join": [
          "",
          [
            "https://",
            {
              "Ref": "MyRestApi"
            },
            ".execute-api.",
            {
              "Ref": "AWS::Region"
            },
            ".amazonaws.com/",
            {
              "Ref": "DeploymentStageName"
            },
            "/foo/12345/baz?MapMe=AnotherValue"
          ]
        ]
      }
    },
    "MyApiDeploymentEndpoint": {
      "Description": "The root URL of the API we just deployed",
      "Value": {
        "Fn::Join": [
          "",
          [
            "https://",
            {
              "Ref": "MyRestApi"
            },
            ".execute-api.",
            {
              "Ref": "AWS::Region"
            },
            ".amazonaws.com/",
            {
              "Ref": "DeploymentStageName"
            },
            "/"
          ]
        ]
      }
    },
    "MyRestApiId": {
      "Description": "The unique ID value across your entire account for the created API.",
      "Value": {
        "Ref": "MyRestApi"
      }
    },
    "MyRestApiRootResource": {
      "Description": "The 10 char alphanum ID of the / resource for MyRestApi",
      "Value": {
        "Fn::GetAtt": [
          "MyRestApi",
          "RootResourceId"
        ]
      }
    },
    "aSampleMethodConsoleUrl": {
      "Description": "The AWS Console URL for inspecting the created method.",
      "Value": {
        "Fn::Join": [
          "",
          [
            "https://console.aws.amazon.com/apigateway/home?region=",
            {
              "Ref": "AWS::Region"
            },
            "#/restapis/",
            {
              "Ref": "MyRestApi"
            },
            "/resources/",
            {
              "Fn::GetAtt": [
                "MyResourceTree",
                "/foo/{id}/baz"
              ]
            },
            "/methods/",
            {
              "Ref": "MethodHttpMethod"
            }
          ]
        ]
      }
    },
    "MyApiDeploymentId": {
      "Description": "The unique ID for the Api Gateway Deployment of MyRestApi",
      "Value": {
        "Ref": "MyApiDeployment"
      }
    }
  }
}
