push_image_driver.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. package preview
  2. import (
  3. "context"
  4. "fmt"
  5. "os"
  6. "github.com/mitchellh/mapstructure"
  7. "github.com/porter-dev/porter/api/types"
  8. "github.com/porter-dev/porter/cli/cmd/config"
  9. "github.com/porter-dev/porter/cli/cmd/deploy"
  10. "github.com/porter-dev/porter/cli/cmd/docker"
  11. "github.com/porter-dev/porter/internal/integrations/preview"
  12. "github.com/porter-dev/switchboard/pkg/drivers"
  13. "github.com/porter-dev/switchboard/pkg/models"
  14. )
  15. type PushDriver struct {
  16. target *preview.Target
  17. config *preview.PushDriverConfig
  18. lookupTable *map[string]drivers.Driver
  19. output map[string]interface{}
  20. }
  21. func NewPushDriver(resource *models.Resource, opts *drivers.SharedDriverOpts) (drivers.Driver, error) {
  22. driver := &PushDriver{
  23. lookupTable: opts.DriverLookupTable,
  24. output: make(map[string]interface{}),
  25. }
  26. target, err := GetTarget(resource.Name, resource.Target)
  27. if err != nil {
  28. return nil, err
  29. }
  30. driver.target = target
  31. return driver, nil
  32. }
  33. func (d *PushDriver) ShouldApply(resource *models.Resource) bool {
  34. return true
  35. }
  36. func (d *PushDriver) Apply(resource *models.Resource) (*models.Resource, error) {
  37. pushDriverConfig, err := d.getConfig(resource)
  38. if err != nil {
  39. return nil, err
  40. }
  41. d.config = pushDriverConfig
  42. if d.config.Push.UsePackCache {
  43. d.output["image"] = d.config.Push.Image
  44. return resource, nil
  45. }
  46. client := config.GetAPIClient()
  47. agent, err := docker.NewAgentWithAuthGetter(client, d.target.Project)
  48. if err != nil {
  49. return nil, err
  50. }
  51. _, err = client.GetRelease(
  52. context.Background(),
  53. d.target.Project,
  54. d.target.Cluster,
  55. d.target.Namespace,
  56. d.target.AppName,
  57. )
  58. shouldCreate := err != nil
  59. if shouldCreate {
  60. regList, err := client.ListRegistries(context.Background(), d.target.Project)
  61. if err != nil {
  62. return nil, err
  63. }
  64. var registryURL string
  65. if len(*regList) == 0 {
  66. return nil, fmt.Errorf("no registry found")
  67. } else {
  68. registryURL = (*regList)[0].URL
  69. }
  70. var repoSuffix string
  71. if repoName := os.Getenv("PORTER_REPO_NAME"); repoName != "" {
  72. if repoOwner := os.Getenv("PORTER_REPO_OWNER"); repoOwner != "" {
  73. repoSuffix = sanitizedRepoSuffix(repoOwner, repoName)
  74. }
  75. }
  76. sharedOpts := &deploy.SharedOpts{
  77. ProjectID: d.target.Project,
  78. ClusterID: d.target.Cluster,
  79. Namespace: d.target.Namespace,
  80. }
  81. createAgent := &deploy.CreateAgent{
  82. Client: client,
  83. CreateOpts: &deploy.CreateOpts{
  84. SharedOpts: sharedOpts,
  85. ReleaseName: d.target.AppName,
  86. RegistryURL: registryURL,
  87. RepoSuffix: repoSuffix,
  88. },
  89. }
  90. regID, imageURL, err := createAgent.GetImageRepoURL(d.target.AppName, sharedOpts.Namespace)
  91. if err != nil {
  92. return nil, err
  93. }
  94. err = client.CreateRepository(
  95. context.Background(),
  96. sharedOpts.ProjectID,
  97. regID,
  98. &types.CreateRegistryRepositoryRequest{
  99. ImageRepoURI: imageURL,
  100. },
  101. )
  102. if err != nil {
  103. return nil, err
  104. }
  105. }
  106. err = agent.PushImage(d.config.Push.Image)
  107. if err != nil {
  108. return nil, err
  109. }
  110. d.output["image"] = d.config.Push.Image
  111. return resource, nil
  112. }
  113. func (d *PushDriver) Output() (map[string]interface{}, error) {
  114. return d.output, nil
  115. }
  116. func (d *PushDriver) getConfig(resource *models.Resource) (*preview.PushDriverConfig, error) {
  117. populatedConf, err := drivers.ConstructConfig(&drivers.ConstructConfigOpts{
  118. RawConf: resource.Config,
  119. LookupTable: *d.lookupTable,
  120. Dependencies: resource.Dependencies,
  121. })
  122. if err != nil {
  123. return nil, err
  124. }
  125. config := &preview.PushDriverConfig{}
  126. err = mapstructure.Decode(populatedConf, config)
  127. if err != nil {
  128. return nil, err
  129. }
  130. return config, nil
  131. }