cloudformation_test.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. package backend
  2. import (
  3. "fmt"
  4. "reflect"
  5. "testing"
  6. "github.com/aws/aws-sdk-go/service/elbv2"
  7. "github.com/awslabs/goformation/v4/cloudformation"
  8. "github.com/awslabs/goformation/v4/cloudformation/ec2"
  9. "github.com/awslabs/goformation/v4/cloudformation/ecs"
  10. "github.com/awslabs/goformation/v4/cloudformation/elasticloadbalancingv2"
  11. "github.com/awslabs/goformation/v4/cloudformation/iam"
  12. "github.com/compose-spec/compose-go/cli"
  13. "github.com/compose-spec/compose-go/loader"
  14. "github.com/compose-spec/compose-go/types"
  15. "github.com/docker/ecs-plugin/pkg/compose"
  16. "gotest.tools/v3/assert"
  17. "gotest.tools/v3/golden"
  18. )
  19. func TestSimpleConvert(t *testing.T) {
  20. project := load(t, "testdata/input/simple-single-service.yaml")
  21. result := convertResultAsString(t, project, "TestCluster")
  22. expected := "simple/simple-cloudformation-conversion.golden"
  23. golden.Assert(t, result, expected)
  24. }
  25. func TestSimpleWithOverrides(t *testing.T) {
  26. project := load(t, "testdata/input/simple-single-service.yaml", "testdata/input/simple-single-service-with-overrides.yaml")
  27. result := convertResultAsString(t, project, "TestCluster")
  28. expected := "simple/simple-cloudformation-with-overrides-conversion.golden"
  29. golden.Assert(t, result, expected)
  30. }
  31. func TestRolePolicy(t *testing.T) {
  32. template := convertYaml(t, `
  33. version: "3"
  34. services:
  35. foo:
  36. image: hello_world
  37. x-aws-pull_credentials: "secret"
  38. `)
  39. role := template.Resources["FooTaskExecutionRole"].(*iam.Role)
  40. assert.Check(t, role != nil)
  41. assert.Check(t, role.ManagedPolicyArns[0] == ECSTaskExecutionPolicy)
  42. assert.Check(t, role.ManagedPolicyArns[1] == ECRReadOnlyPolicy)
  43. // We expect an extra policy has been created for x-aws-pull_credentials
  44. assert.Check(t, len(role.Policies) == 1)
  45. policy := role.Policies[0].PolicyDocument.(*PolicyDocument)
  46. expected := []string{"secretsmanager:GetSecretValue", "ssm:GetParameters", "kms:Decrypt"}
  47. assert.DeepEqual(t, expected, policy.Statement[0].Action)
  48. assert.DeepEqual(t, []string{"secret"}, policy.Statement[0].Resource)
  49. }
  50. func TestMapNetworksToSecurityGroups(t *testing.T) {
  51. template := convertYaml(t, `
  52. version: "3"
  53. services:
  54. test:
  55. image: hello_world
  56. networks:
  57. - front-tier
  58. - back-tier
  59. networks:
  60. front-tier:
  61. name: public
  62. back-tier:
  63. internal: true
  64. `)
  65. assert.Check(t, template.Resources["TestPublicNetwork"] != nil)
  66. assert.Check(t, template.Resources["TestBacktierNetwork"] != nil)
  67. assert.Check(t, template.Resources["TestBacktierNetworkIngress"] != nil)
  68. ingress := template.Resources["TestPublicNetworkIngress"].(*ec2.SecurityGroupIngress)
  69. assert.Check(t, ingress != nil)
  70. assert.Check(t, ingress.SourceSecurityGroupId == cloudformation.Ref("TestPublicNetwork"))
  71. }
  72. func TestLoadBalancerTypeApplication(t *testing.T) {
  73. template := convertYaml(t, `
  74. version: "3"
  75. services:
  76. test:
  77. image: nginx
  78. ports:
  79. - 80:80
  80. `)
  81. lb := template.Resources["TestLoadBalancer"].(*elasticloadbalancingv2.LoadBalancer)
  82. assert.Check(t, lb != nil)
  83. assert.Check(t, lb.Type == elbv2.LoadBalancerTypeEnumApplication)
  84. assert.Check(t, len(lb.SecurityGroups) > 0)
  85. }
  86. func TestLoadBalancerTypeNetwork(t *testing.T) {
  87. template := convertYaml(t, `
  88. version: "3"
  89. services:
  90. test:
  91. image: nginx
  92. ports:
  93. - 80:80
  94. - 88:88
  95. `)
  96. lb := template.Resources["TestLoadBalancer"].(*elasticloadbalancingv2.LoadBalancer)
  97. assert.Check(t, lb != nil)
  98. assert.Check(t, lb.Type == elbv2.LoadBalancerTypeEnumNetwork)
  99. }
  100. func TestServiceMapping(t *testing.T) {
  101. template := convertYaml(t, `
  102. version: "3"
  103. services:
  104. test:
  105. image: "image"
  106. command: "command"
  107. entrypoint: "entrypoint"
  108. environment:
  109. - "FOO=BAR"
  110. cap_add:
  111. - SYS_PTRACE
  112. cap_drop:
  113. - SYSLOG
  114. init: true
  115. user: "user"
  116. working_dir: "working_dir"
  117. `)
  118. def := template.Resources["TestTaskDefinition"].(*ecs.TaskDefinition)
  119. container := def.ContainerDefinitions[0]
  120. assert.Equal(t, container.Image, "docker.io/library/image")
  121. assert.Equal(t, container.Command[0], "command")
  122. assert.Equal(t, container.EntryPoint[0], "entrypoint")
  123. assert.Equal(t, get(container.Environment, "FOO"), "BAR")
  124. assert.Check(t, container.LinuxParameters.InitProcessEnabled)
  125. assert.Equal(t, container.LinuxParameters.Capabilities.Add[0], "SYS_PTRACE")
  126. assert.Equal(t, container.LinuxParameters.Capabilities.Drop[0], "SYSLOG")
  127. assert.Equal(t, container.User, "user")
  128. assert.Equal(t, container.WorkingDirectory, "working_dir")
  129. }
  130. func get(l []ecs.TaskDefinition_KeyValuePair, name string) string {
  131. for _, e := range l {
  132. if e.Name == name {
  133. return e.Value
  134. }
  135. }
  136. return ""
  137. }
  138. func TestResourcesHaveProjectTagSet(t *testing.T) {
  139. template := convertYaml(t, `
  140. version: "3"
  141. services:
  142. test:
  143. image: nginx
  144. ports:
  145. - 80:80
  146. - 88:88
  147. `)
  148. for _, r := range template.Resources {
  149. tags := reflect.Indirect(reflect.ValueOf(r)).FieldByName("Tags")
  150. if !tags.IsValid() {
  151. continue
  152. }
  153. for i := 0; i < tags.Len(); i++ {
  154. k := tags.Index(i).FieldByName("Key").String()
  155. v := tags.Index(i).FieldByName("Value").String()
  156. if k == compose.ProjectTag {
  157. assert.Equal(t, v, "Test")
  158. }
  159. }
  160. }
  161. }
  162. func convertResultAsString(t *testing.T, project *types.Project, clusterName string) string {
  163. client, err := NewBackend("", clusterName, "")
  164. assert.NilError(t, err)
  165. result, err := client.Convert(project)
  166. assert.NilError(t, err)
  167. resultAsJSON, err := result.JSON()
  168. assert.NilError(t, err)
  169. return fmt.Sprintf("%s\n", string(resultAsJSON))
  170. }
  171. func load(t *testing.T, paths ...string) *types.Project {
  172. options := cli.ProjectOptions{
  173. Name: t.Name(),
  174. ConfigPaths: paths,
  175. }
  176. project, err := cli.ProjectFromOptions(&options)
  177. assert.NilError(t, err)
  178. return project
  179. }
  180. func convertYaml(t *testing.T, yaml string) *cloudformation.Template {
  181. dict, err := loader.ParseYAML([]byte(yaml))
  182. assert.NilError(t, err)
  183. model, err := loader.Load(types.ConfigDetails{
  184. ConfigFiles: []types.ConfigFile{
  185. {Config: dict},
  186. },
  187. }, func(options *loader.Options) {
  188. options.Name = "Test"
  189. })
  190. assert.NilError(t, err)
  191. template, err := Backend{}.Convert(model)
  192. assert.NilError(t, err)
  193. return template
  194. }