cloudformation_test.go 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  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 TestServiceReplicas(t *testing.T) {
  87. template := convertYaml(t, `
  88. version: "3"
  89. services:
  90. test:
  91. image: nginx
  92. deploy:
  93. replicas: 10
  94. `)
  95. s := template.Resources["TestService"].(*ecs.Service)
  96. assert.Check(t, s != nil)
  97. assert.Check(t, s.DesiredCount == 10)
  98. }
  99. func TestLoadBalancerTypeNetwork(t *testing.T) {
  100. template := convertYaml(t, `
  101. version: "3"
  102. services:
  103. test:
  104. image: nginx
  105. ports:
  106. - 80:80
  107. - 88:88
  108. `)
  109. lb := template.Resources["TestLoadBalancer"].(*elasticloadbalancingv2.LoadBalancer)
  110. assert.Check(t, lb != nil)
  111. assert.Check(t, lb.Type == elbv2.LoadBalancerTypeEnumNetwork)
  112. }
  113. func TestServiceMapping(t *testing.T) {
  114. template := convertYaml(t, `
  115. version: "3"
  116. services:
  117. test:
  118. image: "image"
  119. command: "command"
  120. entrypoint: "entrypoint"
  121. environment:
  122. - "FOO=BAR"
  123. cap_add:
  124. - SYS_PTRACE
  125. cap_drop:
  126. - SYSLOG
  127. init: true
  128. user: "user"
  129. working_dir: "working_dir"
  130. `)
  131. def := template.Resources["TestTaskDefinition"].(*ecs.TaskDefinition)
  132. container := def.ContainerDefinitions[0]
  133. assert.Equal(t, container.Image, "image")
  134. assert.Equal(t, container.Command[0], "command")
  135. assert.Equal(t, container.EntryPoint[0], "entrypoint")
  136. assert.Equal(t, get(container.Environment, "FOO"), "BAR")
  137. assert.Check(t, container.LinuxParameters.InitProcessEnabled)
  138. assert.Equal(t, container.LinuxParameters.Capabilities.Add[0], "SYS_PTRACE")
  139. assert.Equal(t, container.LinuxParameters.Capabilities.Drop[0], "SYSLOG")
  140. assert.Equal(t, container.User, "user")
  141. assert.Equal(t, container.WorkingDirectory, "working_dir")
  142. }
  143. func get(l []ecs.TaskDefinition_KeyValuePair, name string) string {
  144. for _, e := range l {
  145. if e.Name == name {
  146. return e.Value
  147. }
  148. }
  149. return ""
  150. }
  151. func TestResourcesHaveProjectTagSet(t *testing.T) {
  152. template := convertYaml(t, `
  153. version: "3"
  154. services:
  155. test:
  156. image: nginx
  157. ports:
  158. - 80:80
  159. - 88:88
  160. `)
  161. for _, r := range template.Resources {
  162. tags := reflect.Indirect(reflect.ValueOf(r)).FieldByName("Tags")
  163. if !tags.IsValid() {
  164. continue
  165. }
  166. for i := 0; i < tags.Len(); i++ {
  167. k := tags.Index(i).FieldByName("Key").String()
  168. v := tags.Index(i).FieldByName("Value").String()
  169. if k == compose.ProjectTag {
  170. assert.Equal(t, v, "Test")
  171. }
  172. }
  173. }
  174. }
  175. func convertResultAsString(t *testing.T, project *types.Project, clusterName string) string {
  176. client, err := NewBackend("", clusterName, "")
  177. assert.NilError(t, err)
  178. result, err := client.Convert(project)
  179. assert.NilError(t, err)
  180. resultAsJSON, err := result.JSON()
  181. assert.NilError(t, err)
  182. return fmt.Sprintf("%s\n", string(resultAsJSON))
  183. }
  184. func load(t *testing.T, paths ...string) *types.Project {
  185. options := cli.ProjectOptions{
  186. Name: t.Name(),
  187. ConfigPaths: paths,
  188. }
  189. project, err := cli.ProjectFromOptions(&options)
  190. assert.NilError(t, err)
  191. return project
  192. }
  193. func convertYaml(t *testing.T, yaml string) *cloudformation.Template {
  194. dict, err := loader.ParseYAML([]byte(yaml))
  195. assert.NilError(t, err)
  196. model, err := loader.Load(types.ConfigDetails{
  197. ConfigFiles: []types.ConfigFile{
  198. {Config: dict},
  199. },
  200. }, func(options *loader.Options) {
  201. options.Name = "Test"
  202. })
  203. assert.NilError(t, err)
  204. template, err := Backend{}.Convert(model)
  205. assert.NilError(t, err)
  206. return template
  207. }