sdk.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. package amazon
  2. import (
  3. "context"
  4. "fmt"
  5. "github.com/aws/aws-sdk-go/aws"
  6. "github.com/aws/aws-sdk-go/aws/session"
  7. "github.com/aws/aws-sdk-go/service/cloudformation"
  8. "github.com/aws/aws-sdk-go/service/cloudformation/cloudformationiface"
  9. "github.com/aws/aws-sdk-go/service/cloudwatchlogs"
  10. "github.com/aws/aws-sdk-go/service/cloudwatchlogs/cloudwatchlogsiface"
  11. "github.com/aws/aws-sdk-go/service/ec2"
  12. "github.com/aws/aws-sdk-go/service/ec2/ec2iface"
  13. "github.com/aws/aws-sdk-go/service/ecs"
  14. "github.com/aws/aws-sdk-go/service/ecs/ecsiface"
  15. "github.com/aws/aws-sdk-go/service/elbv2"
  16. "github.com/aws/aws-sdk-go/service/elbv2/elbv2iface"
  17. "github.com/aws/aws-sdk-go/service/iam"
  18. "github.com/aws/aws-sdk-go/service/iam/iamiface"
  19. cf "github.com/awslabs/goformation/v4/cloudformation"
  20. "github.com/sirupsen/logrus"
  21. )
  22. type sdk struct {
  23. sess *session.Session
  24. ECS ecsiface.ECSAPI
  25. EC2 ec2iface.EC2API
  26. ELB elbv2iface.ELBV2API
  27. CW cloudwatchlogsiface.CloudWatchLogsAPI
  28. IAM iamiface.IAMAPI
  29. CF cloudformationiface.CloudFormationAPI
  30. }
  31. func NewAPI(sess *session.Session) API {
  32. return sdk{
  33. ECS: ecs.New(sess),
  34. EC2: ec2.New(sess),
  35. ELB: elbv2.New(sess),
  36. CW: cloudwatchlogs.New(sess),
  37. IAM: iam.New(sess),
  38. CF: cloudformation.New(sess),
  39. }
  40. }
  41. func (s sdk) ClusterExists(ctx context.Context, name string) (bool, error) {
  42. logrus.Debug("Check if cluster was already created: ", name)
  43. clusters, err := s.ECS.DescribeClustersWithContext(aws.Context(ctx), &ecs.DescribeClustersInput{
  44. Clusters: []*string{aws.String(name)},
  45. })
  46. if err != nil {
  47. return false, err
  48. }
  49. return len(clusters.Clusters) > 0, nil
  50. }
  51. func (s sdk) CreateCluster(ctx context.Context, name string) (string, error) {
  52. logrus.Debug("Create cluster ", name)
  53. response, err := s.ECS.CreateClusterWithContext(aws.Context(ctx), &ecs.CreateClusterInput{ClusterName: aws.String(name)})
  54. if err != nil {
  55. return "", err
  56. }
  57. return *response.Cluster.Status, nil
  58. }
  59. func (s sdk) DeleteCluster(ctx context.Context, name string) error {
  60. logrus.Debug("Delete cluster ", name)
  61. response, err := s.ECS.DeleteClusterWithContext(aws.Context(ctx), &ecs.DeleteClusterInput{Cluster: aws.String(name)})
  62. if err != nil {
  63. return err
  64. }
  65. if *response.Cluster.Status == "INACTIVE" {
  66. return nil
  67. }
  68. return fmt.Errorf("Failed to delete cluster, status: %s" + *response.Cluster.Status)
  69. }
  70. func (s sdk) GetDefaultVPC(ctx context.Context) (string, error) {
  71. logrus.Debug("Retrieve default VPC")
  72. vpcs, err := s.EC2.DescribeVpcsWithContext(aws.Context(ctx), &ec2.DescribeVpcsInput{
  73. Filters: []*ec2.Filter{
  74. {
  75. Name: aws.String("isDefault"),
  76. Values: []*string{aws.String("true")},
  77. },
  78. },
  79. })
  80. if err != nil {
  81. return "", err
  82. }
  83. if len(vpcs.Vpcs) == 0 {
  84. return "", fmt.Errorf("account has not default VPC")
  85. }
  86. return *vpcs.Vpcs[0].VpcId, nil
  87. }
  88. func (s sdk) GetSubNets(ctx context.Context, vpcID string) ([]string, error) {
  89. logrus.Debug("Retrieve SubNets")
  90. subnets, err := s.EC2.DescribeSubnetsWithContext(aws.Context(ctx), &ec2.DescribeSubnetsInput{
  91. DryRun: nil,
  92. Filters: []*ec2.Filter{
  93. {
  94. Name: aws.String("vpc-id"),
  95. Values: []*string{aws.String(vpcID)},
  96. },
  97. {
  98. Name: aws.String("default-for-az"),
  99. Values: []*string{aws.String("true")},
  100. },
  101. },
  102. })
  103. if err != nil {
  104. return nil, err
  105. }
  106. ids := []string{}
  107. for _, subnet := range subnets.Subnets {
  108. ids = append(ids, *subnet.SubnetId)
  109. }
  110. return ids, nil
  111. }
  112. func (s sdk) ListRolesForPolicy(ctx context.Context, policy string) ([]string, error) {
  113. entities, err := s.IAM.ListEntitiesForPolicyWithContext(aws.Context(ctx), &iam.ListEntitiesForPolicyInput{
  114. EntityFilter: aws.String("Role"),
  115. PolicyArn: aws.String(policy),
  116. })
  117. if err != nil {
  118. return nil, err
  119. }
  120. roles := []string{}
  121. for _, e := range entities.PolicyRoles {
  122. roles = append(roles, *e.RoleName)
  123. }
  124. return roles, nil
  125. }
  126. func (s sdk) GetRoleArn(ctx context.Context, name string) (string, error) {
  127. role, err := s.IAM.GetRoleWithContext(aws.Context(ctx), &iam.GetRoleInput{
  128. RoleName: aws.String(name),
  129. })
  130. if err != nil {
  131. return "", err
  132. }
  133. return *role.Role.Arn, nil
  134. }
  135. func (s sdk) StackExists(ctx context.Context, name string) (bool, error) {
  136. stacks, err := s.CF.DescribeStacksWithContext(aws.Context(ctx), &cloudformation.DescribeStacksInput{
  137. StackName: aws.String(name),
  138. })
  139. if err != nil {
  140. // FIXME doesn't work as expected
  141. return false, nil
  142. }
  143. return len(stacks.Stacks) > 0, nil
  144. }
  145. func (s sdk) CreateStack(ctx context.Context, name string, template *cf.Template) error {
  146. logrus.Debug("Create CloudFormation stack")
  147. json, err := template.JSON()
  148. if err != nil {
  149. return err
  150. }
  151. _, err = s.CF.CreateStackWithContext(aws.Context(ctx), &cloudformation.CreateStackInput{
  152. OnFailure: aws.String("DELETE"),
  153. StackName: aws.String(name),
  154. TemplateBody: aws.String(string(json)),
  155. TimeoutInMinutes: aws.Int64(10),
  156. })
  157. return err
  158. }
  159. func (s sdk) DescribeStackEvents(ctx context.Context, name string) error {
  160. // Fixme implement Paginator on Events and return as a chan(events)
  161. _, err := s.CF.DescribeStackEventsWithContext(aws.Context(ctx), &cloudformation.DescribeStackEventsInput{
  162. StackName: aws.String(name),
  163. })
  164. return err
  165. }
  166. func (s sdk) DeleteStack(ctx context.Context, name string) error {
  167. logrus.Debug("Delete CloudFormation stack")
  168. _, err := s.CF.DeleteStackWithContext(aws.Context(ctx), &cloudformation.DeleteStackInput{
  169. StackName: aws.String(name),
  170. })
  171. return err
  172. }