GitOps for k8s
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

types.go 8.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. package v1beta1
  2. import (
  3. "fmt"
  4. "strings"
  5. "github.com/ghodss/yaml"
  6. v1 "k8s.io/api/core/v1"
  7. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  8. "k8s.io/helm/pkg/chartutil"
  9. "github.com/fluxcd/flux/resource"
  10. )
  11. // +genclient
  12. // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
  13. // HelmRelease represents custom resource associated with a Helm Chart
  14. type HelmRelease struct {
  15. metav1.TypeMeta `json:",inline"`
  16. metav1.ObjectMeta `json:"metadata"`
  17. Spec HelmReleaseSpec `json:"spec"`
  18. Status HelmReleaseStatus `json:"status"`
  19. }
  20. // ResourceID returns an ID made from the identifying parts of the
  21. // resource, as a convenience for Flux, which uses them
  22. // everywhere.
  23. func (hr HelmRelease) ResourceID() resource.ID {
  24. return resource.MakeID(hr.Namespace, "HelmRelease", hr.Name)
  25. }
  26. // ReleaseName returns the configured release name, or constructs and
  27. // returns one based on the namespace and name of the HelmRelease.
  28. // When the HelmRelease's metadata.namespace and spec.targetNamespace
  29. // differ, both are used in the generated name.
  30. // This name is used for naming and operating on the release in Helm.
  31. func (hr HelmRelease) ReleaseName() string {
  32. if hr.Spec.ReleaseName == "" {
  33. namespace := hr.GetDefaultedNamespace()
  34. targetNamespace := hr.GetTargetNamespace()
  35. if namespace != targetNamespace {
  36. // prefix the releaseName with the administering HelmRelease namespace as well
  37. return fmt.Sprintf("%s-%s-%s", namespace, targetNamespace, hr.Name)
  38. }
  39. return fmt.Sprintf("%s-%s", targetNamespace, hr.Name)
  40. }
  41. return hr.Spec.ReleaseName
  42. }
  43. // GetDefaultedNamespace returns the HelmRelease's namespace
  44. // defaulting to the "default" if not set.
  45. func (hr HelmRelease) GetDefaultedNamespace() string {
  46. if hr.GetNamespace() == "" {
  47. return "default"
  48. }
  49. return hr.Namespace
  50. }
  51. // GetTargetNamespace returns the configured release targetNamespace
  52. // defaulting to the namespace of the HelmRelease if not set.
  53. func (hr HelmRelease) GetTargetNamespace() string {
  54. if hr.Spec.TargetNamespace == "" {
  55. return hr.GetDefaultedNamespace()
  56. }
  57. return hr.Spec.TargetNamespace
  58. }
  59. // ValuesFromSource represents a source of values.
  60. // Only one of its fields may be set.
  61. type ValuesFromSource struct {
  62. // Selects a key of a ConfigMap.
  63. // +optional
  64. ConfigMapKeyRef *v1.ConfigMapKeySelector `json:"configMapKeyRef,omitempty"`
  65. // Selects a key of a Secret.
  66. // +optional
  67. SecretKeyRef *v1.SecretKeySelector `json:"secretKeyRef,omitempty"`
  68. // Selects an URL.
  69. // +optional
  70. ExternalSourceRef *ExternalSourceSelector `json:"externalSourceRef,omitempty"`
  71. // Selects a file from git source helm chart.
  72. // +optional
  73. ChartFileRef *ChartFileSelector `json:"chartFileRef,omitempty"`
  74. }
  75. type ChartFileSelector struct {
  76. Path string `json:"path"`
  77. // Do not fail if chart file could not be retrieved
  78. // +optional
  79. Optional *bool `json:"optional,omitempty"`
  80. }
  81. type ExternalSourceSelector struct {
  82. URL string `json:"url"`
  83. // Do not fail if external source could not be retrieved
  84. // +optional
  85. Optional *bool `json:"optional,omitempty"`
  86. }
  87. type ChartSource struct {
  88. // one of the following...
  89. // +optional
  90. *GitChartSource
  91. // +optional
  92. *RepoChartSource
  93. }
  94. type GitChartSource struct {
  95. GitURL string `json:"git"`
  96. Ref string `json:"ref"`
  97. Path string `json:"path"`
  98. // Do not run 'dep' update (assume requirements.yaml is already fulfilled)
  99. // +optional
  100. SkipDepUpdate bool `json:"skipDepUpdate,omitempty"`
  101. }
  102. // DefaultGitRef is the ref assumed if the Ref field is not given in
  103. // a GitChartSource
  104. const DefaultGitRef = "master"
  105. func (s GitChartSource) RefOrDefault() string {
  106. if s.Ref == "" {
  107. return DefaultGitRef
  108. }
  109. return s.Ref
  110. }
  111. type RepoChartSource struct {
  112. RepoURL string `json:"repository"`
  113. Name string `json:"name"`
  114. Version string `json:"version"`
  115. // An authentication secret for accessing the chart repo
  116. // +optional
  117. ChartPullSecret *v1.LocalObjectReference `json:"chartPullSecret,omitempty"`
  118. }
  119. // CleanRepoURL returns the RepoURL but ensures it ends with a trailing slash
  120. func (s RepoChartSource) CleanRepoURL() string {
  121. cleanURL := strings.TrimRight(s.RepoURL, "/")
  122. return cleanURL + "/"
  123. }
  124. type Rollback struct {
  125. Enable bool `json:"enable,omitempty"`
  126. Force bool `json:"force,omitempty"`
  127. Recreate bool `json:"recreate,omitempty"`
  128. DisableHooks bool `json:"disableHooks,omitempty"`
  129. Timeout *int64 `json:"timeout,omitempty"`
  130. Wait bool `json:"wait,omitempty"`
  131. }
  132. func (r Rollback) GetTimeout() int64 {
  133. if r.Timeout == nil {
  134. return 300
  135. }
  136. return *r.Timeout
  137. }
  138. // HelmReleaseSpec is the spec for a HelmRelease resource
  139. type HelmReleaseSpec struct {
  140. ChartSource `json:"chart"`
  141. ReleaseName string `json:"releaseName,omitempty"`
  142. ValueFileSecrets []v1.LocalObjectReference `json:"valueFileSecrets,omitempty"`
  143. ValuesFrom []ValuesFromSource `json:"valuesFrom,omitempty"`
  144. HelmValues `json:",inline"`
  145. // Override the target namespace, defaults to metadata.namespace
  146. // +optional
  147. TargetNamespace string `json:"targetNamespace,omitempty"`
  148. // Install or upgrade timeout in seconds
  149. // +optional
  150. Timeout *int64 `json:"timeout,omitempty"`
  151. // Reset values on helm upgrade
  152. // +optional
  153. ResetValues bool `json:"resetValues,omitempty"`
  154. // Force resource update through delete/recreate, allows recovery from a failed state
  155. // +optional
  156. ForceUpgrade bool `json:"forceUpgrade,omitempty"`
  157. // Enable rollback and configure options
  158. // +optional
  159. Rollback Rollback `json:"rollback,omitempty"`
  160. }
  161. // GetTimeout returns the install or upgrade timeout (defaults to 300s)
  162. func (r HelmRelease) GetTimeout() int64 {
  163. if r.Spec.Timeout == nil {
  164. return 300
  165. }
  166. return *r.Spec.Timeout
  167. }
  168. // GetValuesFromSources maintains backwards compatibility with
  169. // ValueFileSecrets by merging them into the ValuesFrom array.
  170. func (r HelmRelease) GetValuesFromSources() []ValuesFromSource {
  171. valuesFrom := r.Spec.ValuesFrom
  172. // Maintain backwards compatibility with ValueFileSecrets
  173. if r.Spec.ValueFileSecrets != nil {
  174. var secretKeyRefs []ValuesFromSource
  175. for _, ref := range r.Spec.ValueFileSecrets {
  176. s := &v1.SecretKeySelector{LocalObjectReference: ref}
  177. secretKeyRefs = append(secretKeyRefs, ValuesFromSource{SecretKeyRef: s})
  178. }
  179. valuesFrom = append(secretKeyRefs, valuesFrom...)
  180. }
  181. return valuesFrom
  182. }
  183. type HelmReleaseStatus struct {
  184. // ReleaseName is the name as either supplied or generated.
  185. // +optional
  186. ReleaseName string `json:"releaseName"`
  187. // ReleaseStatus is the status as given by Helm for the release
  188. // managed by this resource.
  189. ReleaseStatus string `json:"releaseStatus"`
  190. // ObservedGeneration is the most recent generation observed by
  191. // the controller.
  192. ObservedGeneration int64 `json:"observedGeneration"`
  193. // ValuesChecksum holds the SHA256 checksum of the last applied
  194. // values.
  195. ValuesChecksum string `json:"valuesChecksum"`
  196. // Revision would define what Git hash or Chart version has currently
  197. // been deployed.
  198. // +optional
  199. Revision string `json:"revision,omitempty"`
  200. // Conditions contains observations of the resource's state, e.g.,
  201. // has the chart which it refers to been fetched.
  202. // +optional
  203. // +patchMergeKey=type
  204. // +patchStrategy=merge
  205. Conditions []HelmReleaseCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
  206. }
  207. type HelmReleaseCondition struct {
  208. Type HelmReleaseConditionType `json:"type"`
  209. Status v1.ConditionStatus `json:"status"`
  210. // +optional
  211. LastUpdateTime metav1.Time `json:"lastUpdateTime,omitempty"`
  212. // +optional
  213. LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"`
  214. // +optional
  215. Reason string `json:"reason,omitempty"`
  216. // +optional
  217. Message string `json:"message,omitempty"`
  218. }
  219. type HelmReleaseConditionType string
  220. const (
  221. // ChartFetched means the chart to which the HelmRelease refers
  222. // has been fetched successfully
  223. HelmReleaseChartFetched HelmReleaseConditionType = "ChartFetched"
  224. // Released means the chart release, as specified in this
  225. // HelmRelease, has been processed by Helm.
  226. HelmReleaseReleased HelmReleaseConditionType = "Released"
  227. // RolledBack means the chart to which the HelmRelease refers
  228. // has been rolled back
  229. HelmReleaseRolledBack HelmReleaseConditionType = "RolledBack"
  230. )
  231. // FluxHelmValues embeds chartutil.Values so we can implement deepcopy on map[string]interface{}
  232. // +k8s:deepcopy-gen=false
  233. type HelmValues struct {
  234. chartutil.Values `json:"values,omitempty"`
  235. }
  236. // DeepCopyInto implements deepcopy-gen method for use in generated code
  237. func (in *HelmValues) DeepCopyInto(out *HelmValues) {
  238. if in == nil {
  239. return
  240. }
  241. b, err := yaml.Marshal(in.Values)
  242. if err != nil {
  243. return
  244. }
  245. var values chartutil.Values
  246. err = yaml.Unmarshal(b, &values)
  247. if err != nil {
  248. return
  249. }
  250. out.Values = values
  251. }
  252. // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
  253. // HelmReleaseList is a list of HelmRelease resources
  254. type HelmReleaseList struct {
  255. metav1.TypeMeta `json:",inline"`
  256. metav1.ListMeta `json:"metadata"`
  257. Items []HelmRelease `json:"items"`
  258. }