Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add SAM Global support #376

Merged
merged 23 commits into from
Jun 20, 2021
Merged

Add SAM Global support #376

merged 23 commits into from
Jun 20, 2021

Conversation

bryceitoc9
Copy link
Contributor

@bryceitoc9 bryceitoc9 commented May 28, 2021

BREAKING CHANGE: Improved implementation of Globals (in SAM tempates)

This PR introduces a new implementation for both defining SAM templates with Global values, as well as parsing templates containing them.

Note: Globals only apply to SAM templates - if you are using regular CloudFormation templates this breaking change should not impact you. The only impact you might see is if you are creating cloudFormation.Template structs manually rather than using the cloudformation.NewTemplate() constructor. As part of this change, a new field (Globals) was added to the Template{} struct. If you are not using the constructor, your compiler will probably complain that this field is missing from the struct instantiation in your code.

For more information about what Globals are in SAM templates, see this link:
https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-specification-template-anatomy-globals.html

In previous versions of Goformation (before v5), goformation was able to parse SAM templates that contained a Globals section, however the implementation just overwrote the resource properties in the template, with the global values at parse time.

This meant that:

  • It was not possible to compose a template in Go that had a Globals section.
  • The JSON Schema generated by this repo, had no concept of Globals.

This new implementation DOES NOT does not overwrite the values in the template, like the previous implementation did. It replaces the old implementation completely, and exposes Globals as a series of structs that are marshalled/unmarshalled to/from JSON/YAML.

This allows you to compose a template:

template := cloudformation.NewTemplate()

template.Globals["Function"] = &global.Function{
    Timeout: 1800,
}

As well as parse a JSON/YAML template, and inspect the global properties:

template, err := goformation.Open("../some-template-with-globals.yml")
if err != nil {
    fmt.Printf("failed to open template: %s\n", err)
    os.Exit(1)
} 

fmt.Printf(template.Globals["Function"])

// You can view the global as above, however it's type is downcast to a basic interface helper
// If you want to inspect properties specific to the global type (e.g. the timeout for a Lambda function)
// then use the following helper methods to get the various global types from the template:

globalAPI, _:= template.GetServerlessGlobalApi()
globalFunction, _ := template.GetServerlessGlobalFunction()
globalHttpApi, _ := template.GetServerlessGlobalHttpApi()
globalSimpleTable, _ := template.GetServerlessGlobalSimpleTable()

fmt.Printf("Global Function Timeout: %d\n", globalFunction.Timeout)

Issue #, if available: Fixes issues #199 and #305

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

Copy link
Contributor

@PaulMaddox PaulMaddox left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a really impressive PR, more so considering it's your first time with Go (and this library). It took me a little while to grok the way you've implemented the Globals functionality, however after reading through I understand why you needed to create a new separate Globals resource type etc. Great work.

As per some of the review comments I've left, I think this needs a (relatively small) bit of work on the Go resource generation/parsing before we can merge it.

generate/globals.go Outdated Show resolved Hide resolved
// GetServerlessGlobal{{$resource.StructName}}retrieves the template's Globals.{{$resource.StructName}} items from an AWS SAM template.
// Returns an error if not found.
func (t *Template) GetServerlessGlobal{{$resource.StructName}} () (*global.{{$resource.StructName}}, error) {
globals := *t.Globals
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fails:

  • t.Globals undefined (type *Template has no field or method Globals)
  • It should also probably be t.Globals, not *t.Globals

I think for this PR to be merged, we need to be able to parse a CloudFormation template with globals into Go objects. I know that's not your primary motivation for this PR, but it's what people will expect.

Given the below template:

AWSTemplateFormatVersion: "2010-09-09"
Description: Testing Globals

Globals:
  Function:
    Runtime: nodejs12.x
    Timeout: 180
    Handler: index.handler
    Environment:
      Variables:
        TABLE_NAME: data-table

Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function
    Properties:
      Environment:
        Variables:
          MESSAGE: "Hello From SAM"

I would expect to be able to parse it with goformation.Open(filename), and inspect the global elements like so:

package main

import (
	"log"

	"github.com/awslabs/goformation/v4"
	"github.com/davecgh/go-spew/spew"
)

func main() {

	template, err := goformation.Open("test/globals.yml")
	if err != nil {
		log.Fatalf("There was an error processing the template: %s\n", err)
	}

	gf, err := template.GetServerlessGlobalFunction()
	if err != nil {
		log.Fatalf("No global function set")
	}

	spew.Dump(gf)

}

I've been trying to this how best to implement this. If we add a Globals field to the Template struct, it needs to be able to support any of (and only) the Global resource types, but Go has no sum types. So we'd need to create an interface.

In cloudformation/template.go:

type Template struct {
	AWSTemplateFormatVersion string                 `json:"AWSTemplateFormatVersion,omitempty"`
	Transform                *Transform             `json:"Transform,omitempty"`
	Description              string                 `json:"Description,omitempty"`
	Metadata                 map[string]interface{} `json:"Metadata,omitempty"`
	Parameters               Parameters             `json:"Parameters,omitempty"`
	Mappings                 map[string]interface{} `json:"Mappings,omitempty"`
	Conditions               map[string]interface{} `json:"Conditions,omitempty"`
	Resources                Resources              `json:"Resources,omitempty"`
	Outputs                  Outputs                `json:"Outputs,omitempty"`
	Globals                  Globals                `json:"Globals,omitempty"`
}

type Resource interface {
	AWSCloudFormationType() string
}

type Global interface {
	AWSCloudFormationIsGlobal() bool
}

type Resources map[string]Resource
type Globals map[string]Global

In generate/templates/global.template you'd just need to add the following method at the bottom of all generated Global types, to satisfy the interface:

// AWSCloudFormationIsGlobal is used to compile an interface (cloudformation.Global) for all global resources
func (r *{{.StructName}}) AWSCloudFormationIsGlobal() bool {
    return true
}

note: the method above, like AWSCloudFormationType is prefixed with AWSCloudFormation to prevent conflicts if a CFN property ever has a matching name.

When it comes to unmarshalling the JSON/YAML into the cloudformation/global/* structs, it will a small bit of logic to detect which struct to unmarshal it into. This should be easy enough though, as the Logical ID is a fixed list (Function|Api|HttpApi|SimpleTable).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Committed my changes to template.go. Check to see if that fits the bill? Definitely open to moving stuff around after that.

globals["Function"] = &global.Function{
Timeout: 123,
}
template.Globals = &globals
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this test actually running? I can't see it failing in the PR, but template.Globals field doesn't exist in your PR (I don't see any modifications to cloudformation/template.go).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack, I did edit this file but I thought it was a codegenned file and I didn't commit it. Will take a second look through my local diff...

@bryceitoc9
Copy link
Contributor Author

Looks like there are a couple tests failing since I removed https://github.com/awslabs/goformation/pull/376/files#diff-02e367f7b1ddbe988fc7723f77af36e76a7d0e449c87320aa0b3eada854091d5R91-R92 . Do you think there's still sense in keeping this around? My understanding is that this can parse a template with globals (not write one) and basically just overlay global values into matching resources (instead of letting SAM do the work).

bryceitoc9 and others added 4 commits June 3, 2021 18:26
This allows a nicer API for building templates with globals:

```go
template := cloudformation.NewTemplate{}
template.Globals["Function"] = &global.Function{ ... }
```

While storing a pointer would be slightly more efficient, it would mean
the `template.Globals` could not be assigned directly, and would require
composition of the global.Function first, and then assigning in a
separate step. This is more consistent with the rest of the goformation
API.
Using `cloudformation.NewTemplate()` should create a new empty map of
globals. This will prevent the following error when a user tries:

```go
template := cloudformation.NewTemplate()
template.Globals["Function"] = &global.Function{ ... }
```

`panic: assignment to entry in nil map`
@PaulMaddox
Copy link
Contributor

There's actually more test failures, as cloudformation/global/* was not committed to the repo, so all the tests in globals_test.go were failing to run.

I'm working through the test failures now and will add some more commits to this PR to resolve them.

`json.Unmarshal` does not throw an error by default, if fields are found
in JSON, but not in the struct it's trying to unmarhsal to.

It is possible to create a JSON decoder that is more strict (see https://maori.geek.nz/golang-raise-error-if-unknown-field-in-json-with-exceptions-2b0caddecd1) however this test wouldn't really prove anything useful IMO.
This change removes the previous globals implementation. Previously when
parsing a JSON/YAML template that contained globals, the parser would
automatically overwrite the properties in the parsed resources with the
value from the global defined (essentially what CFN does on the
backend).

With the changes in PR awslabs#376, this is superceded with a new globals
implementation that allows full composition and decomposition of
templates that contain a global section - WITHOUT overwriting the
values.
@PaulMaddox
Copy link
Contributor

PaulMaddox commented Jun 10, 2021

  • Fixed the tests in globals_test.go that never ran due to errors, and added a few to cover JSON->Go and vice-versa.
  • Removed previous globals implementation.

Still to do (but I've run out of time today):

  • Update all import paths to github.com/goformation/v5.
  • Prepare release with a notice of the breaking change(s). I'll need to update the description of this PR, as the CHANGELOG/semantic versioning is generated based on the final squashed commit message and PR description.

In prep for releasing of the new breaking changes around globals
processing.
@PaulMaddox PaulMaddox merged commit d56929b into awslabs:master Jun 20, 2021
github-actions bot pushed a commit that referenced this pull request Jun 20, 2021
# [5.0.0](v4.19.5...v5.0.0) (2021-06-20)

### Features

* **schema:** Improve SAM Global support ([#376](#376)) ([d56929b](d56929b)), closes [#199](#199) [#305](#305)

### BREAKING CHANGES

* **schema:** Improved implementation of Globals (in SAM tempates)

This PR introduces a new implementation for both defining SAM templates with `Global` values, as well as parsing templates containing them.

Note: Globals only apply to SAM templates - if you are using regular CloudFormation templates this breaking change should not impact you. The only impact you might see is if you are creating `cloudFormation.Template` structs manually rather than using the `cloudformation.NewTemplate()` constructor. As part of this change, a new field (`Globals`) was added to the `Template{}` struct. If you are not using the constructor, your compiler will probably complain that this field is missing from the struct instantiation in your code.

For more information about what `Globals` are in SAM templates, see this link:
https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-specification-template-anatomy-globals.html

In previous versions of Goformation (before v5), goformation was able to parse SAM templates that contained a `Globals` section, however the implementation just overwrote the resource properties in the template, with the global values at parse time.

This meant that:

 - It was not possible to compose a template in Go that had a Globals section.
 - The JSON Schema generated by this repo, had no concept of Globals.

 **This new implementation DOES NOT does not overwrite the values in the template, like the previous implementation did**. It replaces the old implementation completely, and exposes Globals as a series of structs that are marshalled/unmarshalled to/from JSON/YAML.

 This allows you to compose a template:

```go
template := cloudformation.NewTemplate()

template.Globals["Function"] = &global.Function{
    Timeout: 1800,
}
```

As well as parse a JSON/YAML template, and inspect the global properties:

```go
template, err := goformation.Open("../some-template-with-globals.yml")
if err != nil {
    fmt.Printf("failed to open template: %s\n", err)
    os.Exit(1)
}

fmt.Printf("%v", template.Globals["Function"])

// You can view the global as above, however it's type is downcast to a basic interface.
// If you want to inspect properties specific to the global type (e.g. the timeout for a Lambda function)
// then use the following helper methods to get the various global types from the template:

globalAPI, _:= template.GetServerlessGlobalApi()
globalFunction, _ := template.GetServerlessGlobalFunction()
globalHttpApi, _ := template.GetServerlessGlobalHttpApi()
globalSimpleTable, _ := template.GetServerlessGlobalSimpleTable()

fmt.Printf("Global Function Timeout: %d\n", globalFunction.Timeout)
```
@github-actions
Copy link
Contributor

🎉 This PR is included in version 5.0.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

github-actions bot pushed a commit to neoandroid/goformation that referenced this pull request Jul 11, 2023
# [2.0.0](v1.0.0...v2.0.0) (2023-07-11)

### Bug Fixes

* **ci:** bump semantic-release-action ([510f9c6](510f9c6))
* **CI:** fix broken GitHub PR integration ([awslabs#185](https://github.com/neoandroid/goformation/issues/185)) ([d42d00a](d42d00a))
* **CI:** only run semantic-release on push-to-master (not on pull requests) ([awslabs#184](https://github.com/neoandroid/goformation/issues/184)) ([c83945a](c83945a))
* **CI:** speed up PR builds by only downloading the cfn spec and regenerating resources on cron schedule (not on every build) ([7ae2a32](7ae2a32))
* **CI:** Update TravisCI configuration based on https://github.com/se… ([awslabs#180](https://github.com/neoandroid/goformation/issues/180)) ([88e1e85](88e1e85))
* **CI:** Update TravisCI configuration for semantic-release to use jobs ([f6c2fee](f6c2fee))
* **generate:** DependsOn should also accept a string ([09908b6](09908b6)), closes [awslabs#407](https://github.com/neoandroid/goformation/issues/407)
* **generate:** remove duplicated line ([a18d04c](a18d04c))
* generation of AppFlow properties without type ([bfcd40f](bfcd40f))
* **generator:** remove unused import ([cf87ba6](cf87ba6))
* **generator:** update the generation making it easier to fix CF schema errors to generate ([awslabs#285](https://github.com/neoandroid/goformation/issues/285)) ([6751e5b](6751e5b))
* **generator:** updated resources that support update/creation policy ([18c08b9](18c08b9))
* **go:** Ran `go mod tidy` ([awslabs#233](https://github.com/neoandroid/goformation/issues/233)) ([7914822](7914822))
* **intrinsics:** change Fn::Sub to allow AWS pseudo parameters ([awslabs#275](https://github.com/neoandroid/goformation/issues/275)) ([5a48c27](5a48c27)), closes [awslabs#274](https://github.com/neoandroid/goformation/issues/274) [awslabs#202](https://github.com/neoandroid/goformation/issues/202)
* **intrinsics:** continue to process children when transforming ([awslabs#599](https://github.com/neoandroid/goformation/issues/599)) ([396f0fe](396f0fe))
* **intrinsics:** Join function to allow to use parameters of type `List<>` ([awslabs#309](https://github.com/neoandroid/goformation/issues/309)) ([6cc1cd3](6cc1cd3))
* **intrinsics:** split function ([286dd4c](286dd4c))
* **intrinsics:** SplitPtr also as string ([86436f5](86436f5))
* **parser:** do not break if a non-intrinsic `Condition` statement is found in a YAML template ([awslabs#169](https://github.com/neoandroid/goformation/issues/169)) ([e4671e3](e4671e3))
* **parser:** fix invalid YAML template error for custom tag marshaler ([awslabs#177](https://github.com/neoandroid/goformation/issues/177)) ([035d438](035d438))
* **parser:** Select the correct AWS CloudFormation resource type based on similarity ([awslabs#183](https://github.com/neoandroid/goformation/issues/183)) ([5749b23](5749b23))
* **parser:** Unmarshalling of resources with polymorphic properties (like S3 events) now works ([awslabs#188](https://github.com/neoandroid/goformation/issues/188)) ([8eff90a](8eff90a))
* **policies:** re-create deleted files ([bdd5860](bdd5860))
* **resource.template:** remove print to standard output when JSON unmarshal in a resource fails ([d64f719](d64f719))
* **resource.template:** remove print to standard output when JSON unmarshal in a resource fails (output of go generate) ([c039ac4](c039ac4))
* **sam:** AWS::Serverless::Function Properties Architectures property should have a primitive type specified ([awslabs#420](https://github.com/neoandroid/goformation/issues/420)) ([3aa91ed](3aa91ed))
* **sam:** DestinationConfig shouldn't contain OnSuccess property ([awslabs#406](https://github.com/neoandroid/goformation/issues/406)) ([6971966](6971966)), closes [awslabs#404](https://github.com/neoandroid/goformation/issues/404)
* **schema, parser:** change Transform json schema to allow multiple macros ([awslabs#268](https://github.com/neoandroid/goformation/issues/268)) ([072fc74](072fc74)), closes [awslabs#267](https://github.com/neoandroid/goformation/issues/267)
* **schema:** Add AddDefaultAuthorizerToCorsPreflight to Serverless Auth ([637150c](637150c))
* **schema:** Add architectures support for sam functions ([awslabs#419](https://github.com/neoandroid/goformation/issues/419)) ([b505b69](b505b69))
* **schema:** Add cdkmetada resource ([awslabs#418](https://github.com/neoandroid/goformation/issues/418)) ([3d1b1f9](3d1b1f9))
* **schema:** Add Change and Update policies to the Unmarshal method ([awslabs#288](https://github.com/neoandroid/goformation/issues/288)) ([989b05f](989b05f))
* **schema:** add DisableExecuteApiEndpoint to Serverless API ([awslabs#538](https://github.com/neoandroid/goformation/issues/538)) ([1ff11e8](1ff11e8))
* **schema:** Add Domain in AWS::Serverless::API schema ([dff256a](dff256a))
* **schema:** Add DynamoDBWritePolicy to sam policy template ([6f08c13](6f08c13))
* **schema:** add FunctionResponseTypes property for kinesis events ([awslabs#539](https://github.com/neoandroid/goformation/issues/539)) ([3cff1ff](3cff1ff))
* **schema:** add HttpApi, HttpApiFunctionAuth, RouteSettings ([awslabs#541](https://github.com/neoandroid/goformation/issues/541)) ([78913ea](78913ea))
* **schema:** Add RequestModel and RequestParameters for AWS::Serverless::Function.EventSource ([e0c2673](e0c2673))
* **schema:** Add S3WritePolicy to sam policy template ([c9f775e](c9f775e))
* **schema:** Add SSMParameterReadPolicy and AWSSecretsManagerGetSecretValuePolicy into AWS::Serverless::Function.SAMPolicyTemplate ([7a85ab9](7a85ab9))
* **schema:** Add Version property into IAMPolicyDocument and fix Statement type ([846268a](846268a))
* **schema:** Allow any type for Parameter AllowedValues ([awslabs#392](https://github.com/neoandroid/goformation/issues/392)) ([ccc7fb0](ccc7fb0))
* **schema:** AWS::CDK::Metadata resource should be automatically generated ([awslabs#421](https://github.com/neoandroid/goformation/issues/421)) ([65569f7](65569f7)), closes [awslabs#418](https://github.com/neoandroid/goformation/issues/418)
* **schema:** AWS::Serverless::Api.MethodSettings should be a list ([a1f340a](a1f340a)), closes [awslabs#242](https://github.com/neoandroid/goformation/issues/242)
* **schema:** AWS::Serverless::Function S3 notification filters ([awslabs#249](https://github.com/neoandroid/goformation/issues/249)) ([a50ef92](a50ef92)), closes [awslabs#74](https://github.com/neoandroid/goformation/issues/74)
* **schema:** AWS::Serverless:Api.Cors ([awslabs#246](https://github.com/neoandroid/goformation/issues/246)) ([62fd56a](62fd56a)), closes [awslabs#244](https://github.com/neoandroid/goformation/issues/244)
* **schema:** CloudFormation Updates ([ca2da2e](ca2da2e))
* **schema:** CloudFormation Updates ([065bf7e](065bf7e))
* **schema:** CloudFormation Updates ([590b489](590b489))
* **schema:** CloudFormation Updates ([998c192](998c192))
* **schema:** CloudFormation Updates ([cdcc602](cdcc602))
* **schema:** CloudFormation Updates ([7e80942](7e80942))
* **schema:** CloudFormation Updates ([7fedc99](7fedc99))
* **schema:** CloudFormation Updates ([83f2d49](83f2d49))
* **schema:** CloudFormation Updates ([bd8a2ac](bd8a2ac))
* **schema:** CloudFormation Updates ([af4f471](af4f471))
* **schema:** CloudFormation Updates ([5d02a2b](5d02a2b))
* **schema:** CloudFormation Updates ([35a4b24](35a4b24))
* **schema:** CloudFormation Updates ([bc360ab](bc360ab))
* **schema:** CloudFormation Updates ([0f4ade8](0f4ade8))
* **schema:** CloudFormation Updates ([0de7ca4](0de7ca4))
* **schema:** CloudFormation Updates ([dcee612](dcee612))
* **schema:** CloudFormation Updates ([7858395](7858395))
* **schema:** CloudFormation Updates ([319d00f](319d00f))
* **schema:** CloudFormation Updates ([8432365](8432365))
* **schema:** CloudFormation Updates ([68156bc](68156bc))
* **schema:** CloudFormation Updates ([d2d083a](d2d083a))
* **schema:** CloudFormation Updates ([9ce0a19](9ce0a19))
* **schema:** CloudFormation Updates ([d59706b](d59706b))
* **schema:** CloudFormation Updates ([801c7f8](801c7f8))
* **schema:** CloudFormation Updates ([e06f6e2](e06f6e2))
* **schema:** CloudFormation Updates ([13095ef](13095ef))
* **schema:** CloudFormation Updates ([c5b4ae3](c5b4ae3))
* **schema:** CloudFormation Updates ([2f3e802](2f3e802))
* **schema:** CloudFormation Updates ([bbbbbed](bbbbbed))
* **schema:** CloudFormation Updates ([awslabs#320](https://github.com/neoandroid/goformation/issues/320)) ([49879b4](49879b4))
* **schema:** CloudFormation Updates ([awslabs#329](https://github.com/neoandroid/goformation/issues/329)) ([4c1362b](4c1362b))
* **schema:** CloudFormation Updates ([awslabs#330](https://github.com/neoandroid/goformation/issues/330)) ([4070319](4070319))
* **schema:** CloudFormation Updates ([awslabs#331](https://github.com/neoandroid/goformation/issues/331)) ([12f9c83](12f9c83))
* **schema:** CloudFormation Updates ([awslabs#333](https://github.com/neoandroid/goformation/issues/333)) ([0fec2c4](0fec2c4))
* **schema:** CloudFormation Updates ([awslabs#341](https://github.com/neoandroid/goformation/issues/341)) ([b65192b](b65192b))
* **schema:** CloudFormation Updates ([awslabs#342](https://github.com/neoandroid/goformation/issues/342)) ([f047bed](f047bed))
* **schema:** CloudFormation Updates ([awslabs#347](https://github.com/neoandroid/goformation/issues/347)) ([d49d514](d49d514))
* **schema:** CloudFormation Updates ([awslabs#348](https://github.com/neoandroid/goformation/issues/348)) ([5dd2417](5dd2417))
* **schema:** CloudFormation Updates ([awslabs#349](https://github.com/neoandroid/goformation/issues/349)) ([a012fde](a012fde))
* **schema:** CloudFormation Updates ([awslabs#351](https://github.com/neoandroid/goformation/issues/351)) ([53556a3](53556a3))
* **schema:** CloudFormation Updates ([awslabs#353](https://github.com/neoandroid/goformation/issues/353)) ([eee9123](eee9123))
* **schema:** CloudFormation Updates ([awslabs#357](https://github.com/neoandroid/goformation/issues/357)) ([4d320a5](4d320a5))
* **schema:** CloudFormation Updates ([awslabs#361](https://github.com/neoandroid/goformation/issues/361)) ([ece24b8](ece24b8))
* **schema:** CloudFormation Updates ([awslabs#367](https://github.com/neoandroid/goformation/issues/367)) ([1a42e5b](1a42e5b))
* **schema:** CloudFormation Updates ([awslabs#371](https://github.com/neoandroid/goformation/issues/371)) ([b4a4521](b4a4521))
* **schema:** CloudFormation Updates ([awslabs#372](https://github.com/neoandroid/goformation/issues/372)) ([95c8bf5](95c8bf5))
* **schema:** CloudFormation Updates ([awslabs#375](https://github.com/neoandroid/goformation/issues/375)) ([5d0d4f2](5d0d4f2))
* **schema:** CloudFormation Updates ([awslabs#381](https://github.com/neoandroid/goformation/issues/381)) ([0714ecf](0714ecf))
* **schema:** CloudFormation Updates ([awslabs#384](https://github.com/neoandroid/goformation/issues/384)) ([823b7a4](823b7a4))
* **schema:** CloudFormation Updates ([awslabs#385](https://github.com/neoandroid/goformation/issues/385)) ([8b5b816](8b5b816))
* **schema:** CloudFormation Updates ([awslabs#387](https://github.com/neoandroid/goformation/issues/387)) ([71f83ce](71f83ce))
* **schema:** CloudFormation Updates ([awslabs#388](https://github.com/neoandroid/goformation/issues/388)) ([ae6ed10](ae6ed10))
* **schema:** CloudFormation Updates ([awslabs#390](https://github.com/neoandroid/goformation/issues/390)) ([ac83603](ac83603))
* **schema:** CloudFormation Updates ([awslabs#393](https://github.com/neoandroid/goformation/issues/393)) ([b005b8c](b005b8c))
* **schema:** CloudFormation Updates ([awslabs#398](https://github.com/neoandroid/goformation/issues/398)) ([c7ebbd3](c7ebbd3))
* **schema:** CloudFormation Updates ([awslabs#400](https://github.com/neoandroid/goformation/issues/400)) ([1606bbe](1606bbe))
* **schema:** CloudFormation Updates ([awslabs#401](https://github.com/neoandroid/goformation/issues/401)) ([fa89e23](fa89e23))
* **schema:** CloudFormation Updates ([awslabs#408](https://github.com/neoandroid/goformation/issues/408)) ([2ffeeac](2ffeeac))
* **schema:** CloudFormation Updates ([awslabs#415](https://github.com/neoandroid/goformation/issues/415)) ([e560a0f](e560a0f))
* **schema:** CloudFormation Updates ([awslabs#422](https://github.com/neoandroid/goformation/issues/422)) ([61378b5](61378b5))
* **schema:** CloudFormation Updates ([awslabs#510](https://github.com/neoandroid/goformation/issues/510)) ([25e2ea4](25e2ea4))
* **schema:** CloudFormation Updates ([awslabs#524](https://github.com/neoandroid/goformation/issues/524)) ([4fbffa5](4fbffa5))
* **schema:** CloudFormation Updates ([awslabs#525](https://github.com/neoandroid/goformation/issues/525)) ([fa6c239](fa6c239))
* **schema:** CloudFormation Updates ([awslabs#530](https://github.com/neoandroid/goformation/issues/530)) ([a65a99f](a65a99f))
* **schema:** CloudFormation Updates ([awslabs#531](https://github.com/neoandroid/goformation/issues/531)) ([83b04c9](83b04c9))
* **schema:** CloudFormation Updates ([awslabs#531](https://github.com/neoandroid/goformation/issues/531)) ([d72e4af](d72e4af))
* **schema:** CloudFormation Updates ([awslabs#532](https://github.com/neoandroid/goformation/issues/532)) ([d94f3f2](d94f3f2))
* **schema:** CloudFormation Updates ([awslabs#536](https://github.com/neoandroid/goformation/issues/536)) ([35fa19d](35fa19d))
* **schema:** CloudFormation Updates ([awslabs#540](https://github.com/neoandroid/goformation/issues/540)) ([9eeb893](9eeb893))
* **schema:** CloudFormation Updates ([awslabs#544](https://github.com/neoandroid/goformation/issues/544)) ([5ab72b1](5ab72b1))
* **schema:** CloudFormation Updates ([awslabs#549](https://github.com/neoandroid/goformation/issues/549)) ([1583466](1583466))
* **schema:** CloudFormation Updates ([awslabs#552](https://github.com/neoandroid/goformation/issues/552)) ([44a6061](44a6061))
* **schema:** CloudFormation Updates ([awslabs#555](https://github.com/neoandroid/goformation/issues/555)) ([d7d9cce](d7d9cce))
* **schema:** CloudFormation Updates ([awslabs#562](https://github.com/neoandroid/goformation/issues/562)) ([307cd37](307cd37))
* **schema:** CloudFormation Updates ([awslabs#566](https://github.com/neoandroid/goformation/issues/566)) ([1612640](1612640))
* **schema:** CloudFormation Updates ([awslabs#568](https://github.com/neoandroid/goformation/issues/568)) ([2db6261](2db6261))
* **schema:** CloudFormation Updates ([awslabs#569](https://github.com/neoandroid/goformation/issues/569)) ([961063c](961063c))
* **schema:** CloudFormation Updates ([awslabs#575](https://github.com/neoandroid/goformation/issues/575)) ([76aab2e](76aab2e))
* **schema:** CloudFormation Updates ([awslabs#581](https://github.com/neoandroid/goformation/issues/581)) ([da7efea](da7efea))
* **schema:** CloudFormation Updates ([awslabs#582](https://github.com/neoandroid/goformation/issues/582)) ([78e986d](78e986d))
* **schema:** CloudFormation Updates ([awslabs#583](https://github.com/neoandroid/goformation/issues/583)) ([e7cc49b](e7cc49b))
* **schema:** CloudFormation Updates ([awslabs#584](https://github.com/neoandroid/goformation/issues/584)) ([f2508fc](f2508fc))
* **schema:** CloudFormation Updates ([awslabs#585](https://github.com/neoandroid/goformation/issues/585)) ([e749f56](e749f56))
* **schema:** CloudFormation Updates ([awslabs#588](https://github.com/neoandroid/goformation/issues/588)) ([d2464f1](d2464f1))
* **schema:** CloudFormation Updates ([awslabs#589](https://github.com/neoandroid/goformation/issues/589)) ([42b235b](42b235b))
* **schema:** CloudFormation Updates ([awslabs#592](https://github.com/neoandroid/goformation/issues/592)) ([7a7167e](7a7167e))
* **schema:** CloudFormation Updates ([awslabs#593](https://github.com/neoandroid/goformation/issues/593)) ([2915807](2915807))
* **schema:** CloudFormation Updates ([awslabs#595](https://github.com/neoandroid/goformation/issues/595)) ([90e89e7](90e89e7))
* **schema:** CloudFormation Updates ([awslabs#598](https://github.com/neoandroid/goformation/issues/598)) ([fa586c8](fa586c8))
* **schema:** CloudFormation Updates ([awslabs#601](https://github.com/neoandroid/goformation/issues/601)) ([cad0a1f](cad0a1f))
* **schema:** CloudFormation Updates ([awslabs#603](https://github.com/neoandroid/goformation/issues/603)) ([5ceb69c](5ceb69c))
* **schema:** CloudFormation Updates ([awslabs#604](https://github.com/neoandroid/goformation/issues/604)) ([8520deb](8520deb))
* **schema:** Fix JSON Schema generation commas for InclusivePrimitiveItemTypes ([28db940](28db940))
* **schema:** fixed incorrect field type for AWS::Serverless::Application.Location ([awslabs#167](https://github.com/neoandroid/goformation/issues/167)) ([3f1817b](3f1817b))
* **schema:** generated schema acording to new rules ([d9dc863](d9dc863))
* **schema:** maps within YAML templates should allow unknown fields/properties ([3b6e359](3b6e359))
* **schema:** Ordered cloudformation/all.go file ([awslabs#238](https://github.com/neoandroid/goformation/issues/238)) ([91254f3](91254f3))
* **schema:** re-generate schema ([58dc56b](58dc56b))
* **schema:** re-generated schema ([eae0a91](eae0a91))
* **schema:** regenerated with latest code ([33f99bf](33f99bf))
* **schema:** S3Location or String support for AWS::Serverless::LayerVersion.ContentUri ([awslabs#339](https://github.com/neoandroid/goformation/issues/339)) ([6e39ebe](6e39ebe)), closes [awslabs#337](https://github.com/neoandroid/goformation/issues/337)
* **schema:** string should be a primitivetype ([5fa746c](5fa746c))
* **schema:** Support Version field in custom resource ([awslabs#391](https://github.com/neoandroid/goformation/issues/391)) ([eef8f36](eef8f36))
* **schema:** version attribute of Function::S3Location in SAM is optional ([awslabs#226](https://github.com/neoandroid/goformation/issues/226)) ([14b754c](14b754c)), closes [/github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#s3](https://github.com//github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md/issues/s3) [awslabs#87](https://github.com/neoandroid/goformation/issues/87)
* **spec:** corrected AWS::Serverless::Api.Auth.Authorizers to be of type JSON rather than string  ([awslabs#164](https://github.com/neoandroid/goformation/issues/164)) ([4cf1bee](4cf1bee))
* **template:** field Export on type Output should be pointer ([awslabs#299](https://github.com/neoandroid/goformation/issues/299)) ([7d5870e](7d5870e)), closes [awslabs#294](https://github.com/neoandroid/goformation/issues/294)

### Code Refactoring

* **generator:** moving resources and policies into their own packages ([awslabs#161](https://github.com/neoandroid/goformation/issues/161)) ([03a0123](03a0123))

* feat!: bump release to v7 ([a30de92](a30de92))
* Fix method conflicts (awslabs#245) ([d0b0a8b](d0b0a8b)), closes [awslabs#245](https://github.com/neoandroid/goformation/issues/245) [awslabs#241](https://github.com/neoandroid/goformation/issues/241) [awslabs#294](https://github.com/neoandroid/goformation/issues/294)
* Group CloudFormation resources by AWS service name (awslabs#234) ([d0749e6](d0749e6)), closes [awslabs#234](https://github.com/neoandroid/goformation/issues/234)

### feature

* **types:** added utils to create pointer types ([4a68a60](4a68a60))

### Features

* Added semantic-release CI setup ([a9b368a](a9b368a))
* Added semantic-release configuration file ([3b25fdb](3b25fdb))
* **CI:** auto-generate AUTHORS.md file ([b37af7b](b37af7b))
* **generate:** allow for optional params ([d9bfdff](d9bfdff))
* **generator:** add support for new sagemaker properties ([bfd39c4](bfd39c4))
* **generator:** remove generation of interface pointers ([315dde3](315dde3))
* **go:** bump to go1.18 minimum ([awslabs#579](https://github.com/neoandroid/goformation/issues/579)) ([9c453fa](9c453fa))
* **go:** drop support for go 1.13 and 1.14 ([05bb704](05bb704))
* **go:** drop support for go 1.15 ([2e45a2b](2e45a2b))
* **if intrinsics:** generalized solution to support more types ([c66e47b](c66e47b))
* **intrinsics:** Add cloudformation.TransformFn() ([awslabs#352](https://github.com/neoandroid/goformation/issues/352)) ([9a1e331](9a1e331))
* **intrinsics:** add intrinsics ptr versions ([ffdc5af](ffdc5af))
* **intrinsics:** Add SubVars to Sub with replacement variables ([awslabs#411](https://github.com/neoandroid/goformation/issues/411)) ([0940790](0940790))
* **intrinsics:** add support for base64 encoded string in instrinsic if function ([awslabs#414](https://github.com/neoandroid/goformation/issues/414)) ([652501b](652501b)), closes [awslabs#412](https://github.com/neoandroid/goformation/issues/412)
* **intrinsics:** add support for FindInMap default ([awslabs#546](https://github.com/neoandroid/goformation/issues/546)) ([5f27b01](5f27b01))
* **intrinsics:** Allow for int in Fn::Equals ([awslabs#346](https://github.com/neoandroid/goformation/issues/346)) ([dd6cd2d](dd6cd2d))
* **intrinsics:** support for nested intrinsics ([awslabs#571](https://github.com/neoandroid/goformation/issues/571)) ([5e9e9c4](5e9e9c4))
* **lib:** Test feature (please ignore) ([1df611a](1df611a))
* **parser:** Add support for Conditions ([awslabs#260](https://github.com/neoandroid/goformation/issues/260)) ([1b00f17](1b00f17))
* **parser:** Default to parsing as YAML unless the filename ends in .json ([awslabs#176](https://github.com/neoandroid/goformation/issues/176)) ([42e7146](42e7146))
* Release v7 ([awslabs#499](https://github.com/neoandroid/goformation/issues/499)) ([28c3768](28c3768))
* remove go1.16 and add go1.19 support ([awslabs#529](https://github.com/neoandroid/goformation/issues/529)) ([583451d](583451d))
* **resources:** Add DependOn, DeletionPolicy and others to CustomResource ([awslabs#350](https://github.com/neoandroid/goformation/issues/350)) ([6712019](6712019))
* **sam:** add missing fields to ScheduledEvents and remove required versions from IAM ([33395af](33395af))
* **sam:** add SAM CognitoEvent EventSource ([awslabs#570](https://github.com/neoandroid/goformation/issues/570)) ([701fb3d](701fb3d))
* **sam:** Add support for `AWS::Serverless::Api.TracingEnabled`, `AWS::Serverless::Function.PermissionsBoundary`, `AWS::Serverless::Function.DynamoEvent.Enabled`, `AWS::Serverless::Function.KinesisEvent.Enabled`, and `AWS::Serverless::Function.SQSEvent.Enabled` ([awslabs#191](https://github.com/neoandroid/goformation/issues/191)) ([38f0187](38f0187))
* **sam:** serverless api model type fix ([awslabs#515](https://github.com/neoandroid/goformation/issues/515)) ([43e87d9](43e87d9))
* **schema:** Add AWS::Serverless::Function.Auth ([awslabs#373](https://github.com/neoandroid/goformation/issues/373)) ([fc2877f](fc2877f))
* **schema:** add CloudFormation parameter type ([awslabs#259](https://github.com/neoandroid/goformation/issues/259)) ([27fe204](27fe204))
* **schema:** Add new DynamoDBEvent options ([awslabs#289](https://github.com/neoandroid/goformation/issues/289)) ([741228d](741228d))
* **schema:** Add OpenApiVersion field to serverless Api ([awslabs#281](https://github.com/neoandroid/goformation/issues/281)) ([bccc71b](bccc71b))
* **schema:** Add support for Template Outputs ([awslabs#291](https://github.com/neoandroid/goformation/issues/291)) ([6875c50](6875c50))
* **schema:** Add the ability to create items using pattern properties rather than normal references ([7b60160](7b60160))
* **schema:** Add UpdateReplacePolicy to the templates and the policies so that it is generated for every resource ([awslabs#272](https://github.com/neoandroid/goformation/issues/272)) ([696c515](696c515))
* **schema:** Added CloudWatch Logs event for SAM ([awslabs#271](https://github.com/neoandroid/goformation/issues/271)) ([fedb013](fedb013))
* **schema:** adding AWS::Serverless::StateMachine and FileSystemConfigs to Function ([awslabs#284](https://github.com/neoandroid/goformation/issues/284)) ([d2d23ca](d2d23ca))
* **schema:** AWS CloudFormation Update (2019-03-15) ([awslabs#189](https://github.com/neoandroid/goformation/issues/189)) ([8b332a4](8b332a4))
* **schema:** AWS CloudFormation Update (2019-10-26) ([awslabs#231](https://github.com/neoandroid/goformation/issues/231)) ([63ca311](63ca311))
* **schema:** AWS CloudFormation Update (2019-10-29) ([awslabs#239](https://github.com/neoandroid/goformation/issues/239)) ([7ff8499](7ff8499))
* **schema:** CFN Updates ([awslabs#287](https://github.com/neoandroid/goformation/issues/287)) ([9778479](9778479))
* **schema:** CloudFormation Updates ([awslabs#383](https://github.com/neoandroid/goformation/issues/383)) ([92fa1e3](92fa1e3))
* **schema:** CloudFormation Updates (2019-12-09) ([awslabs#251](https://github.com/neoandroid/goformation/issues/251)) ([a23ba41](a23ba41))
* **schema:** CloudFormation Updates (2020-01-30) ([awslabs#263](https://github.com/neoandroid/goformation/issues/263)) ([fda2d31](fda2d31))
* **schema:** CloudFormation Updates (2020-02-13) ([awslabs#266](https://github.com/neoandroid/goformation/issues/266)) ([bc75922](bc75922))
* **schema:** CloudFormation Updates (2020-02-22) ([awslabs#269](https://github.com/neoandroid/goformation/issues/269)) ([ffd88a6](ffd88a6))
* **schema:** dummy commit - trigger CI for schema update ([66bc344](66bc344))
* **schema:** Improve cloudformation If to accept structs ([awslabs#368](https://github.com/neoandroid/goformation/issues/368)) ([3c1bcd8](3c1bcd8))
* **schema:** Improve SAM Global support ([awslabs#376](https://github.com/neoandroid/goformation/issues/376)) ([d56929b](d56929b)), closes [awslabs#199](https://github.com/neoandroid/goformation/issues/199) [awslabs#305](https://github.com/neoandroid/goformation/issues/305)
* **schema:** regenerated resources to apply SAM schema fixes from previous PR ([b30c019](b30c019))
* **schema:** Serverless eventbridgeruleevent ([awslabs#279](https://github.com/neoandroid/goformation/issues/279)) ([2a9e572](2a9e572))
* **schema:** serverless http api cors configuration ([a90bb03](a90bb03))
* **schema:** Support condition properties in resources ([b3b7397](b3b7397))
* **schema:** Support custom resource types ([1274ccd](1274ccd))
* **schema:** Support generation of array items that should be combined in one anyOf ([d5e468f](d5e468f))
* switch go-yaml implementation to most recent version ([awslabs#535](https://github.com/neoandroid/goformation/issues/535)) ([0ca6ce2](0ca6ce2))
* **template:** support optional parameters ([awslabs#548](https://github.com/neoandroid/goformation/issues/548)) ([3344301](3344301))

### Performance Improvements

* reduce JSON CloudFormation template size ([f893af7](f893af7))

### BREAKING CHANGES

* Pointers are not used for Lists, Maps and interface{} members.
* **generate:** DependsOn can now parse a single string instead of just a list of strings.
* **types:** use cloudformation.{String,Int,...} as helpers for
creating pointer types.
* **generate:** optional parameters are now marked as a pointer.
* **schema:** Improved implementation of Globals (in SAM tempates)

This PR introduces a new implementation for both defining SAM templates with `Global` values, as well as parsing templates containing them.

Note: Globals only apply to SAM templates - if you are using regular CloudFormation templates this breaking change should not impact you. The only impact you might see is if you are creating `cloudFormation.Template` structs manually rather than using the `cloudformation.NewTemplate()` constructor. As part of this change, a new field (`Globals`) was added to the `Template{}` struct. If you are not using the constructor, your compiler will probably complain that this field is missing from the struct instantiation in your code.

For more information about what `Globals` are in SAM templates, see this link:
https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-specification-template-anatomy-globals.html

In previous versions of Goformation (before v5), goformation was able to parse SAM templates that contained a `Globals` section, however the implementation just overwrote the resource properties in the template, with the global values at parse time.

This meant that:

 - It was not possible to compose a template in Go that had a Globals section.
 - The JSON Schema generated by this repo, had no concept of Globals.

 **This new implementation DOES NOT does not overwrite the values in the template, like the previous implementation did**. It replaces the old implementation completely, and exposes Globals as a series of structs that are marshalled/unmarshalled to/from JSON/YAML.

 This allows you to compose a template:

```go
template := cloudformation.NewTemplate()

template.Globals["Function"] = &global.Function{
    Timeout: 1800,
}
```

As well as parse a JSON/YAML template, and inspect the global properties:

```go
template, err := goformation.Open("../some-template-with-globals.yml")
if err != nil {
    fmt.Printf("failed to open template: %s\n", err)
    os.Exit(1)
}

fmt.Printf("%v", template.Globals["Function"])

// You can view the global as above, however it's type is downcast to a basic interface.
// If you want to inspect properties specific to the global type (e.g. the timeout for a Lambda function)
// then use the following helper methods to get the various global types from the template:

globalAPI, _:= template.GetServerlessGlobalApi()
globalFunction, _ := template.GetServerlessGlobalFunction()
globalHttpApi, _ := template.GetServerlessGlobalHttpApi()
globalSimpleTable, _ := template.GetServerlessGlobalSimpleTable()

fmt.Printf("Global Function Timeout: %d\n", globalFunction.Timeout)
```
* This change refactors the DependsOn, Metadata, CreationPolicy,
UpdatePolicy and DeletionPolicy methods on each resource to a new
name. This is required, as some CloudFormation resources use these
keywords as properties (AWS::AppMesh::Route.GrpcRouteMatch has a
Metadata field for example), which causes a conflict.

`resource.DependsOn()` method is refactored to `resource.AWSCloudFormationDependsOn` field.
`resource.SetDependsOn()` method is refactored to `resource.AWSCloudFormationDependsOn` field.
`resource.Metadata()` method is refactored to `resource.AWSCloudFormationMetadata` field.
`resource.SetMetadata()` method is refactored to `resource.AWSCloudFormationMetadata` field.
`resource.CreationPolicy()` method is refactored to `resource.AWSCloudFormationCreationPolicy` field.
`resource.SetCreationPolicy()` method is refactored to `resource.AWSCloudFormationCreationPolicy` field.
`resource.UpdatePolicy()` method is refactored to `resource.AWSCloudFormationUpdatePolicy` field.
`resource.SetUpdatePolicy()` method is refactored to `resource.AWSCloudFormationUpdatePolicy` field.
`resource.DeletionPolicy()` method is refactored to `resource.AWSCloudFormationDeletionPolicy` field.
`resource.SetDeletionPolicy()` method is refactored to `resource.AWSCloudFormationDeletionPolicy` field.
* this change moves all Cloudformation resources to
packages based on the AWS service name. The main motivation for this is
that building goformation on some platforms (Windows) failed due to too
many files in the old cloudformation/resources package. This new package
style has a nice benefit of slightly nicer to use API, but is a breaking
change and will require refactoring existing codebases to update to v3.

Old usage:

```go
import "github.com/awslabs/goformation/v2/cloudformation/resources"

... snip ...

topic := &resources.AWSSNSTopic{}
```

New usage:

```go
import "github.com/awslabs/goformation/v3/cloudformation/sns"

...snip...

topic := &sns.Topic{}
```

Most tests are still failing at this point and need refactoring.

* fix(schema): Tag handling

Fixed tag handling for new grouped resources style (via new tags.Tag
struct).

* fix(schema): SAM specification

SAM Specification now generates nicely with new grouped resources
format. Also all tests are now passing \o/
* **generator:** this PR refactors the auto-generated CloudFormation resources out of the cloudformation package and into a dedicated package (resources). This helps keep the auto generated files separate from others.

E.g. cloudformation.AWSSnsTopic{} becomes resources.AWSSnsTopic{}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants