ecr.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. package connect
  2. import (
  3. "context"
  4. "fmt"
  5. "strings"
  6. "time"
  7. "github.com/aws/aws-sdk-go/service/ecr"
  8. "github.com/fatih/color"
  9. "github.com/porter-dev/porter/cli/cmd/api"
  10. "github.com/porter-dev/porter/cli/cmd/utils"
  11. "github.com/porter-dev/porter/internal/models/integrations"
  12. "github.com/porter-dev/porter/cli/cmd/providers/aws"
  13. awsLocal "github.com/porter-dev/porter/cli/cmd/providers/aws/local"
  14. )
  15. // ECR creates an ECR integration
  16. func ECR(
  17. client *api.Client,
  18. projectID uint,
  19. ) (uint, error) {
  20. // if project ID is 0, ask the user to set the project ID or create a project
  21. if projectID == 0 {
  22. return 0, fmt.Errorf("no project set, please run porter project set [id]")
  23. }
  24. // query for the region
  25. region, err := utils.PromptPlaintext(fmt.Sprintf(`Please provide the AWS region where the ECR instance is located.
  26. AWS Region: `))
  27. if err != nil {
  28. return 0, err
  29. }
  30. userResp, err := utils.PromptPlaintext(
  31. fmt.Sprintf(`Porter can set up an IAM user in your AWS account to connect to this ECR instance automatically.
  32. Would you like to proceed? %s `,
  33. color.New(color.FgCyan).Sprintf("[y/n]"),
  34. ),
  35. )
  36. if err != nil {
  37. return 0, err
  38. }
  39. if userResp := strings.ToLower(userResp); userResp == "y" || userResp == "yes" {
  40. agent := awsLocal.NewDefaultAgent()
  41. creds, err := agent.CreateIAMECRUser(region)
  42. if err != nil {
  43. color.New(color.FgRed).Printf("Automatic creation failed, manual input required. Error was: %v\n", err)
  44. return ecrManual(client, projectID, region)
  45. }
  46. waitForAuthorizationToken(region, creds)
  47. integration, err := client.CreateAWSIntegration(
  48. context.Background(),
  49. projectID,
  50. &api.CreateAWSIntegrationRequest{
  51. AWSAccessKeyID: creds.AWSAccessKeyID,
  52. AWSSecretAccessKey: creds.AWSSecretAccessKey,
  53. AWSRegion: region,
  54. },
  55. )
  56. if err != nil {
  57. return 0, err
  58. }
  59. color.New(color.FgGreen).Printf("created aws integration with id %d\n", integration.ID)
  60. return linkRegistry(client, projectID, integration.ID)
  61. }
  62. return ecrManual(client, projectID, region)
  63. }
  64. func ecrManual(
  65. client *api.Client,
  66. projectID uint,
  67. region string,
  68. ) (uint, error) {
  69. // if project ID is 0, ask the user to set the project ID or create a project
  70. if projectID == 0 {
  71. return 0, fmt.Errorf("no project set, please run porter project set [id]")
  72. }
  73. // query for the access key id
  74. accessKeyID, err := utils.PromptPlaintext(fmt.Sprintf(`AWS Access Key ID: `))
  75. if err != nil {
  76. return 0, err
  77. }
  78. // query for the secret access key
  79. secretKey, err := utils.PromptPlaintext(fmt.Sprintf(`AWS Secret Access Key: `))
  80. if err != nil {
  81. return 0, err
  82. }
  83. // create the aws integration
  84. integration, err := client.CreateAWSIntegration(
  85. context.Background(),
  86. projectID,
  87. &api.CreateAWSIntegrationRequest{
  88. AWSAccessKeyID: accessKeyID,
  89. AWSSecretAccessKey: secretKey,
  90. AWSRegion: region,
  91. },
  92. )
  93. if err != nil {
  94. return 0, err
  95. }
  96. color.New(color.FgGreen).Printf("created aws integration with id %d\n", integration.ID)
  97. return linkRegistry(client, projectID, integration.ID)
  98. }
  99. func linkRegistry(client *api.Client, projectID uint, intID uint) (uint, error) {
  100. // create the registry
  101. // query for registry name
  102. regName, err := utils.PromptPlaintext(fmt.Sprintf(`Give this registry a name: `))
  103. if err != nil {
  104. return 0, err
  105. }
  106. reg, err := client.CreateECR(
  107. context.Background(),
  108. projectID,
  109. &api.CreateECRRequest{
  110. Name: regName,
  111. AWSIntegrationID: intID,
  112. },
  113. )
  114. if err != nil {
  115. return 0, err
  116. }
  117. color.New(color.FgGreen).Printf("created registry with id %d and name %s\n", reg.ID, reg.Name)
  118. return reg.ID, nil
  119. }
  120. func waitForAuthorizationToken(region string, creds *aws.PorterAWSCredentials) error {
  121. awsInt := &integrations.AWSIntegration{
  122. AWSRegion: region,
  123. AWSAccessKeyID: []byte(creds.AWSAccessKeyID),
  124. AWSSecretAccessKey: []byte(creds.AWSSecretAccessKey),
  125. }
  126. sess, err := awsInt.GetSession()
  127. if err != nil {
  128. return err
  129. }
  130. ecrSvc := ecr.New(sess)
  131. for i := 0; i < 30; i++ {
  132. _, err := ecrSvc.GetAuthorizationToken(&ecr.GetAuthorizationTokenInput{})
  133. if err == nil {
  134. return nil
  135. }
  136. time.Sleep(2 * time.Second)
  137. }
  138. return fmt.Errorf("could not get ECR authorization token, please check credentials")
  139. }