ecr.go 4.2 KB

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