ecr.go 4.3 KB

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