agent.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. package helm
  2. import (
  3. "fmt"
  4. "github.com/pkg/errors"
  5. "helm.sh/helm/v3/pkg/action"
  6. "helm.sh/helm/v3/pkg/chart"
  7. "helm.sh/helm/v3/pkg/chart/loader"
  8. "helm.sh/helm/v3/pkg/release"
  9. "k8s.io/helm/pkg/chartutil"
  10. )
  11. // Agent is a Helm agent for performing helm operations
  12. type Agent struct {
  13. ActionConfig *action.Configuration
  14. }
  15. // ListReleases lists releases based on a ListFilter
  16. func (a *Agent) ListReleases(
  17. namespace string,
  18. filter *ListFilter,
  19. ) ([]*release.Release, error) {
  20. cmd := action.NewList(a.ActionConfig)
  21. filter.apply(cmd)
  22. return cmd.Run()
  23. }
  24. // GetRelease returns the info of a release.
  25. func (a *Agent) GetRelease(
  26. name string,
  27. version int,
  28. ) (*release.Release, error) {
  29. // Namespace is already known by the RESTClientGetter.
  30. cmd := action.NewGet(a.ActionConfig)
  31. cmd.Version = version
  32. return cmd.Run(name)
  33. }
  34. // GetReleaseHistory returns a list of charts for a specific release
  35. func (a *Agent) GetReleaseHistory(
  36. name string,
  37. ) ([]*release.Release, error) {
  38. cmd := action.NewHistory(a.ActionConfig)
  39. return cmd.Run(name)
  40. }
  41. // UpgradeRelease upgrades a specific release with new values.yaml
  42. func (a *Agent) UpgradeRelease(
  43. name string,
  44. values string,
  45. ) (*release.Release, error) {
  46. valuesYaml, err := chartutil.ReadValues([]byte(values))
  47. if err != nil {
  48. return nil, fmt.Errorf("Values could not be parsed: %v", err)
  49. }
  50. return a.UpgradeReleaseByValues(name, valuesYaml)
  51. }
  52. // UpgradeReleaseByValues upgrades a release by unmarshaled yaml values
  53. func (a *Agent) UpgradeReleaseByValues(
  54. name string,
  55. values map[string]interface{},
  56. ) (*release.Release, error) {
  57. // grab the latest release
  58. rel, err := a.GetRelease(name, 0)
  59. if err != nil {
  60. return nil, fmt.Errorf("Could not get release to be upgraded: %v", err)
  61. }
  62. ch := rel.Chart
  63. cmd := action.NewUpgrade(a.ActionConfig)
  64. res, err := cmd.Run(name, ch, values)
  65. if err != nil {
  66. return nil, fmt.Errorf("Upgrade failed: %v", err)
  67. }
  68. return res, nil
  69. }
  70. // InstallChart reads the raw values and calls Agent.InstallChartByValues
  71. func (a *Agent) InstallChart(
  72. cp string,
  73. values []byte,
  74. ) (*release.Release, error) {
  75. valuesYaml, err := chartutil.ReadValues(values)
  76. if err != nil {
  77. return nil, fmt.Errorf("Values could not be parsed: %v", err)
  78. }
  79. return a.InstallChartByValues(cp, valuesYaml)
  80. }
  81. // InstallChartByValues installs a new chart by unmarshalled values via
  82. // URL, absolute or relative filepaths.
  83. //
  84. // Equivalent to `helm install [CHART_NAME] [cp]` where cp is one of the following:
  85. // 1) Absolute URL: https://example.com/charts/nginx-1.2.3.tgz
  86. // 2) path to packaged chart ./nginx-1.2.3.tgz
  87. // 3) path to unpacked chart ./nginx
  88. func (a *Agent) InstallChartByValues(
  89. cp string,
  90. values map[string]interface{},
  91. ) (*release.Release, error) {
  92. cmd := action.NewInstall(a.ActionConfig)
  93. // Only supports filepaths for now, URL option WIP.
  94. // Check chart dependencies to make sure all are present in /charts
  95. chartRequested, err := loader.Load(cp)
  96. if err != nil {
  97. return nil, err
  98. }
  99. if err := checkIfInstallable(chartRequested); err != nil {
  100. return nil, err
  101. }
  102. if chartRequested.Metadata.Deprecated {
  103. return nil, fmt.Errorf("This chart is deprecated")
  104. }
  105. if req := chartRequested.Metadata.Dependencies; req != nil {
  106. if err := action.CheckDependencies(chartRequested, req); err != nil {
  107. // TODO: Handle dependency updates.
  108. return nil, err
  109. }
  110. }
  111. return cmd.Run(chartRequested, values)
  112. }
  113. // RollbackRelease rolls a release back to a specified revision/version
  114. func (a *Agent) RollbackRelease(
  115. name string,
  116. version int,
  117. ) error {
  118. cmd := action.NewRollback(a.ActionConfig)
  119. cmd.Version = version
  120. return cmd.Run(name)
  121. }
  122. // ------------------------ Helm agent helper functions ------------------------ //
  123. // checkIfInstallable validates if a chart can be installed
  124. // Application chart type is only installable
  125. func checkIfInstallable(ch *chart.Chart) error {
  126. switch ch.Metadata.Type {
  127. case "", "application":
  128. return nil
  129. }
  130. return errors.Errorf("%s charts are not installable", ch.Metadata.Type)
  131. }