update_config_driver.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. package preview
  2. import (
  3. "context"
  4. "fmt"
  5. "os"
  6. "github.com/cli/cli/git"
  7. "github.com/fatih/color"
  8. "github.com/mitchellh/mapstructure"
  9. api "github.com/porter-dev/porter/api/client"
  10. "github.com/porter-dev/porter/api/types"
  11. "github.com/porter-dev/porter/cli/cmd/config"
  12. "github.com/porter-dev/porter/cli/cmd/deploy"
  13. "github.com/porter-dev/porter/internal/templater/utils"
  14. "github.com/porter-dev/switchboard/pkg/drivers"
  15. "github.com/porter-dev/switchboard/pkg/models"
  16. )
  17. type UpdateConfigDriverConfig struct {
  18. UpdateConfig struct {
  19. Image string
  20. } `mapstructure:"update_config"`
  21. EnvGroups []types.EnvGroupMeta `mapstructure:"env_groups"`
  22. Values map[string]interface{}
  23. }
  24. type UpdateConfigDriver struct {
  25. source *Source
  26. target *Target
  27. config *UpdateConfigDriverConfig
  28. lookupTable *map[string]drivers.Driver
  29. output map[string]interface{}
  30. }
  31. func NewUpdateConfigDriver(resource *models.Resource, opts *drivers.SharedDriverOpts) (drivers.Driver, error) {
  32. driver := &UpdateConfigDriver{
  33. lookupTable: opts.DriverLookupTable,
  34. output: make(map[string]interface{}),
  35. }
  36. source, err := GetSource(resource.Source)
  37. if err != nil {
  38. return nil, err
  39. }
  40. driver.source = source
  41. target, err := GetTarget(resource.Target)
  42. if err != nil {
  43. return nil, err
  44. }
  45. if target.AppName == "" {
  46. return nil, fmt.Errorf("target app_name is missing")
  47. }
  48. driver.target = target
  49. return driver, nil
  50. }
  51. func (d *UpdateConfigDriver) ShouldApply(resource *models.Resource) bool {
  52. return true
  53. }
  54. func (d *UpdateConfigDriver) Apply(resource *models.Resource) (*models.Resource, error) {
  55. updateConfigDriverConfig, err := d.getConfig(resource)
  56. if err != nil {
  57. return nil, err
  58. }
  59. d.config = updateConfigDriverConfig
  60. client := config.GetAPIClient()
  61. _, err = client.GetRelease(
  62. context.Background(),
  63. d.target.Project,
  64. d.target.Cluster,
  65. d.target.Namespace,
  66. d.target.AppName,
  67. )
  68. shouldCreate := err != nil
  69. // FIXME: give tag option in config build, but override if PORTER_TAG is present
  70. tag := os.Getenv("PORTER_TAG")
  71. if tag == "" {
  72. commit, err := git.LastCommit()
  73. if err != nil {
  74. return nil, err
  75. }
  76. tag = commit.Sha[:7]
  77. }
  78. sharedOpts := &deploy.SharedOpts{
  79. ProjectID: d.target.Project,
  80. ClusterID: d.target.Cluster,
  81. OverrideTag: tag,
  82. Namespace: d.target.Namespace,
  83. Method: "registry",
  84. EnvGroups: d.config.EnvGroups,
  85. }
  86. if shouldCreate {
  87. color.New(color.FgYellow).Printf("Could not read release %s/%s (%s): attempting creation\n", d.target.Namespace, d.target.AppName, err.Error())
  88. createAgent := &deploy.CreateAgent{
  89. Client: client,
  90. CreateOpts: &deploy.CreateOpts{
  91. SharedOpts: sharedOpts,
  92. Kind: d.source.Name,
  93. ReleaseName: d.target.AppName,
  94. },
  95. }
  96. _, err := createAgent.CreateFromRegistry(d.config.UpdateConfig.Image, d.config.Values)
  97. if err != nil {
  98. return nil, err
  99. }
  100. } else {
  101. updateAgent, err := deploy.NewDeployAgent(client, d.target.AppName, &deploy.DeployOpts{
  102. SharedOpts: sharedOpts,
  103. Local: false,
  104. })
  105. if err != nil {
  106. return nil, err
  107. }
  108. err = updateAgent.UpdateImageAndValues(d.config.Values)
  109. if err != nil {
  110. return nil, err
  111. }
  112. }
  113. err = d.assignOutput(resource, client)
  114. if err != nil {
  115. return nil, err
  116. }
  117. return resource, nil
  118. }
  119. func (d *UpdateConfigDriver) Output() (map[string]interface{}, error) {
  120. return d.output, nil
  121. }
  122. func (d *UpdateConfigDriver) getConfig(resource *models.Resource) (*UpdateConfigDriverConfig, error) {
  123. populatedConf, err := drivers.ConstructConfig(&drivers.ConstructConfigOpts{
  124. RawConf: resource.Config,
  125. LookupTable: *d.lookupTable,
  126. Dependencies: resource.Dependencies,
  127. })
  128. if err != nil {
  129. return nil, err
  130. }
  131. config := &UpdateConfigDriverConfig{}
  132. err = mapstructure.Decode(populatedConf, config)
  133. if err != nil {
  134. return nil, err
  135. }
  136. return config, nil
  137. }
  138. func (d *UpdateConfigDriver) assignOutput(resource *models.Resource, client *api.Client) error {
  139. release, err := client.GetRelease(
  140. context.Background(),
  141. d.target.Project,
  142. d.target.Cluster,
  143. d.target.Namespace,
  144. d.target.AppName,
  145. )
  146. if err != nil {
  147. return err
  148. }
  149. d.output = utils.CoalesceValues(d.source.SourceValues, release.Config)
  150. return nil
  151. }