aws.go 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. package tools
  2. import (
  3. "context"
  4. "fmt"
  5. "io"
  6. "os"
  7. "path/filepath"
  8. "github.com/aws/aws-sdk-go-v2/aws"
  9. "github.com/aws/aws-sdk-go-v2/config"
  10. "github.com/aws/aws-sdk-go-v2/credentials"
  11. "github.com/aws/aws-sdk-go-v2/service/cloudformation"
  12. cftypes "github.com/aws/aws-sdk-go-v2/service/cloudformation/types"
  13. "github.com/aws/aws-sdk-go-v2/service/ec2/types"
  14. "github.com/aws/aws-sdk-go-v2/service/s3"
  15. )
  16. func AWS() *awstool {
  17. ctx := context.TODO()
  18. accessKeyID := os.Getenv("AWS_ACCESS_KEY_ID")
  19. secretAccessKey := os.Getenv("AWS_SECRET_ACCESS_KEY")
  20. sessionToken := os.Getenv("AWS_SESSION_TOKEN")
  21. staticProvider := credentials.NewStaticCredentialsProvider(accessKeyID, secretAccessKey, sessionToken)
  22. cfg, err := config.LoadDefaultConfig(ctx,
  23. config.WithCredentialsProvider(staticProvider),
  24. config.WithRegion(os.Getenv("AWS_REGION")),
  25. )
  26. if err != nil {
  27. log.Write([]byte(fmt.Sprintf("unable to load SDK config, %v", err)))
  28. }
  29. return &awstool{
  30. cfg: cfg,
  31. }
  32. }
  33. type (
  34. awstool struct {
  35. cfg aws.Config
  36. }
  37. awss3 struct {
  38. aws *awstool
  39. }
  40. awsec2 struct {
  41. aws *awstool
  42. }
  43. awscloudformation struct {
  44. aws *awstool
  45. }
  46. awsimagebuilder struct {
  47. aws *awstool
  48. }
  49. awsecs struct {
  50. aws *awstool
  51. }
  52. awseks struct {
  53. aws *awstool
  54. }
  55. )
  56. func (t *awstool) S3() *awss3 { return &awss3{aws: t} }
  57. func (t *awstool) EC2() *awsec2 { return &awsec2{aws: t} }
  58. func (t *awstool) CloudFormation() *awscloudformation { return &awscloudformation{aws: t} }
  59. func (t *awstool) ImageBuilder() *awsimagebuilder { return &awsimagebuilder{aws: t} }
  60. func (t *awstool) ECS() *awsecs { return &awsecs{aws: t} }
  61. func (t *awstool) EKS() *awseks { return &awseks{aws: t} }
  62. func (t *awstool) Filter(filters map[string][]string) []types.Filter {
  63. filter := []types.Filter{}
  64. for k, v := range filters {
  65. filter = append(filter, types.Filter{
  66. Name: aws.String(k),
  67. Values: v,
  68. })
  69. }
  70. return filter
  71. }
  72. func (t *awss3) Put(src, bucket, key string) error {
  73. api := s3.NewFromConfig(t.aws.cfg)
  74. f, err := os.Open(src)
  75. if err != nil {
  76. return err
  77. }
  78. defer f.Close()
  79. _, err = api.PutObject(context.TODO(), &s3.PutObjectInput{
  80. Bucket: aws.String(bucket),
  81. Key: aws.String(key),
  82. Body: f,
  83. })
  84. if err != nil {
  85. return err
  86. }
  87. return nil
  88. }
  89. func (t *awss3) PutDir(path, bucket, s3Prefix string) error {
  90. api := s3.NewFromConfig(t.aws.cfg)
  91. err := filepath.WalkDir(path, func(p string, d os.DirEntry, err error) error {
  92. if !d.IsDir() {
  93. relPath, _ := filepath.Rel(path, p)
  94. s3Key := filepath.ToSlash(filepath.Join(s3Prefix, relPath))
  95. file, err := os.Open(p)
  96. if err == nil {
  97. return err
  98. }
  99. defer file.Close()
  100. api.PutObject(context.TODO(), &s3.PutObjectInput{
  101. Bucket: aws.String(bucket),
  102. Key: aws.String(s3Key),
  103. Body: file,
  104. })
  105. }
  106. return nil
  107. })
  108. if err != nil {
  109. return err
  110. }
  111. return nil
  112. }
  113. func (t *awss3) Get(bucket, key, dst string) error {
  114. api := s3.NewFromConfig(t.aws.cfg)
  115. output, err := api.GetObject(context.TODO(), &s3.GetObjectInput{
  116. Bucket: aws.String(bucket),
  117. Key: aws.String(key),
  118. })
  119. if err != nil {
  120. return err
  121. }
  122. f, err := os.Create(dst)
  123. if err != nil {
  124. return err
  125. }
  126. _, err = io.Copy(f, output.Body)
  127. return err
  128. }
  129. func (t *awss3) Read(bucket, key string) ([]byte, error) {
  130. api := s3.NewFromConfig(t.aws.cfg)
  131. output, err := api.GetObject(context.TODO(), &s3.GetObjectInput{
  132. Bucket: aws.String(bucket),
  133. Key: aws.String(key),
  134. })
  135. if err != nil {
  136. return nil, err
  137. }
  138. return io.ReadAll(output.Body)
  139. }
  140. func (t *awss3) ListObjects(bucket, path string) error { return nil }
  141. func (t *awss3) ListBuckets(prefix string) ([]string, error) {
  142. api := s3.NewFromConfig(t.aws.cfg)
  143. output, err := api.ListBuckets(context.TODO(), &s3.ListBucketsInput{
  144. Prefix: &prefix,
  145. })
  146. if err != nil {
  147. return nil, err
  148. }
  149. buckets := []string{}
  150. for _, bucket := range output.Buckets {
  151. buckets = append(buckets, *bucket.Name)
  152. }
  153. return buckets, nil
  154. }
  155. func (t *awsec2) ListIAMRoles(filter []types.Filter) error { return nil }
  156. func (t *awsec2) FindLatestAMI(filter []types.Filter) error { return nil }
  157. func (t *awsec2) ListSubnets(filter []types.Filter) error { return nil }
  158. func (t *awsec2) ListSecurityGroups(filter []types.Filter) error { return nil }
  159. func (t *awsec2) ListVPCs(filter []types.Filter) error { return nil }
  160. func (t *awsec2) ListKeypairs(filter []types.Filter) error { return nil }
  161. func (t *awsec2) List(filter []types.Filter) error { return nil }
  162. func (t *awsec2) Create() error { return nil }
  163. func (t *awsec2) Stop() error { return nil }
  164. func (t *awsec2) Start() error { return nil }
  165. func (t *awsec2) Terminate() error { return nil }
  166. func (t *awscloudformation) ListStacks(filter []types.Filter) {}
  167. func (t *awscloudformation) CreateStack(stackName, templatePath string, params, tags map[string]string) error {
  168. ctx := context.TODO()
  169. client := cloudformation.NewFromConfig(t.aws.cfg)
  170. templateBody, err := os.ReadFile(templatePath)
  171. if err != nil {
  172. return fmt.Errorf("unable to read template file %s, %v", templatePath, err)
  173. }
  174. aparams := []cftypes.Parameter{}
  175. for k, v := range params {
  176. aparams = append(aparams, cftypes.Parameter{
  177. ParameterKey: aws.String(k),
  178. ParameterValue: aws.String(v),
  179. })
  180. }
  181. atags := []cftypes.Tag{}
  182. for k, v := range tags {
  183. atags = append(atags, cftypes.Tag{
  184. Key: aws.String(k),
  185. Value: aws.String(v),
  186. })
  187. }
  188. input := &cloudformation.CreateStackInput{
  189. StackName: aws.String(stackName),
  190. TemplateBody: aws.String(string(templateBody)),
  191. Parameters: aparams,
  192. Capabilities: []cftypes.Capability{
  193. cftypes.CapabilityCapabilityNamedIam,
  194. },
  195. Tags: atags,
  196. }
  197. result, err := client.CreateStack(ctx, input)
  198. if err != nil {
  199. return fmt.Errorf("failed to create stack %s, %v", stackName, err)
  200. }
  201. log.Write([]byte(fmt.Sprintf("Stack creation initiated. Stack ID: %s\n", aws.ToString(result.StackId))))
  202. return nil
  203. }
  204. func (t *awscloudformation) UpdateStack(stackName, templatePath string, params, tags map[string]string) error {
  205. ctx := context.TODO()
  206. client := cloudformation.NewFromConfig(t.aws.cfg)
  207. templateBody, err := os.ReadFile(templatePath)
  208. if err != nil {
  209. return fmt.Errorf("unable to read template file %s, %v", templatePath, err)
  210. }
  211. aparams := []cftypes.Parameter{}
  212. for k, v := range params {
  213. aparams = append(aparams, cftypes.Parameter{
  214. ParameterKey: aws.String(k),
  215. ParameterValue: aws.String(v),
  216. })
  217. }
  218. atags := []cftypes.Tag{}
  219. for k, v := range tags {
  220. atags = append(atags, cftypes.Tag{
  221. Key: aws.String(k),
  222. Value: aws.String(v),
  223. })
  224. }
  225. input := &cloudformation.UpdateStackInput{
  226. StackName: aws.String(stackName),
  227. TemplateBody: aws.String(string(templateBody)),
  228. Parameters: aparams,
  229. Capabilities: []cftypes.Capability{
  230. cftypes.CapabilityCapabilityNamedIam,
  231. },
  232. Tags: atags,
  233. }
  234. result, err := client.UpdateStack(ctx, input)
  235. if err != nil {
  236. return fmt.Errorf("failed to update stack %s, %v", stackName, err)
  237. }
  238. log.Write([]byte(fmt.Sprintf("Stack update initiated. Stack ID: %s\n", aws.ToString(result.StackId))))
  239. return nil
  240. }
  241. func (t *awscloudformation) DeleteStack(stackName string) error {
  242. ctx := context.TODO()
  243. client := cloudformation.NewFromConfig(t.aws.cfg)
  244. input := &cloudformation.DeleteStackInput{
  245. StackName: aws.String(stackName),
  246. }
  247. _, err := client.DeleteStack(ctx, input)
  248. if err != nil {
  249. return fmt.Errorf("failed to delete stack %s, %v", stackName, err)
  250. }
  251. return nil
  252. }
  253. func (t *awsimagebuilder) Component() error { return nil }
  254. func (t *awsimagebuilder) Recipe() error { return nil }
  255. func (t *awsimagebuilder) Pipeline() error { return nil }
  256. func (t *awsimagebuilder) RunPipeline() error { return nil }
  257. func (t *awsecs) Cluster() error { return nil }
  258. func (t *awsecs) Task() error { return nil }
  259. func (t *awseks) UpgradeCluster() error { return nil }