ecr.go 4.2 KB

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