allocation_types.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. package costmodel
  2. import (
  3. "fmt"
  4. "github.com/opencost/opencost/pkg/kubecost"
  5. "time"
  6. )
  7. // pod describes a running pod's start and end time within a Window and
  8. // all the Allocations (i.e. containers) contained within it.
  9. type pod struct {
  10. Window kubecost.Window
  11. Start time.Time
  12. End time.Time
  13. Key podKey
  14. Allocations map[string]*kubecost.Allocation
  15. }
  16. func (p *pod) equal(that *pod) bool {
  17. if p == nil {
  18. return that == nil
  19. }
  20. if !p.Window.Equal(that.Window) {
  21. return false
  22. }
  23. if !p.Start.Equal(that.Start) {
  24. return false
  25. }
  26. if !p.End.Equal(that.End) {
  27. return false
  28. }
  29. if p.Key != that.Key {
  30. return false
  31. }
  32. if p.Key != that.Key {
  33. return false
  34. }
  35. if len(p.Allocations) != len(that.Allocations) {
  36. return false
  37. }
  38. for container, thisAlloc := range p.Allocations {
  39. thatAlloc, ok := that.Allocations[container]
  40. if !ok || !thisAlloc.Equal(thatAlloc) {
  41. return false
  42. }
  43. }
  44. return true
  45. }
  46. // appendContainer adds an entry for the given container name to the pod.
  47. func (p *pod) appendContainer(container string) {
  48. name := fmt.Sprintf("%s/%s/%s/%s", p.Key.Cluster, p.Key.Namespace, p.Key.Pod, container)
  49. alloc := &kubecost.Allocation{
  50. Name: name,
  51. Properties: &kubecost.AllocationProperties{},
  52. Window: p.Window.Clone(),
  53. Start: p.Start,
  54. End: p.End,
  55. }
  56. alloc.Properties.Container = container
  57. alloc.Properties.Pod = p.Key.Pod
  58. alloc.Properties.Namespace = p.Key.Namespace
  59. alloc.Properties.Cluster = p.Key.Cluster
  60. p.Allocations[container] = alloc
  61. }
  62. // pvc describes a PersistentVolumeClaim
  63. // TODO:CLEANUP move to pkg/kubecost?
  64. // TODO:CLEANUP add PersistentVolumeClaims field to type Allocation?
  65. type pvc struct {
  66. Bytes float64 `json:"bytes"`
  67. Name string `json:"name"`
  68. Cluster string `json:"cluster"`
  69. Namespace string `json:"namespace"`
  70. Volume *pv `json:"persistentVolume"`
  71. Mounted bool `json:"mounted"`
  72. Start time.Time `json:"start"`
  73. End time.Time `json:"end"`
  74. }
  75. // Cost computes the cumulative cost of the pvc
  76. func (p *pvc) Cost() float64 {
  77. if p == nil || p.Volume == nil {
  78. return 0.0
  79. }
  80. gib := p.Bytes / 1024 / 1024 / 1024
  81. hrs := p.minutes() / 60.0
  82. return p.Volume.CostPerGiBHour * gib * hrs
  83. }
  84. // Minutes computes the number of minutes over which the pvc is defined
  85. func (p *pvc) minutes() float64 {
  86. if p == nil {
  87. return 0.0
  88. }
  89. return p.End.Sub(p.Start).Minutes()
  90. }
  91. // String returns a string representation of the pvc
  92. func (p *pvc) String() string {
  93. if p == nil {
  94. return "<nil>"
  95. }
  96. return fmt.Sprintf("%s/%s/%s{Bytes:%.2f, Cost:%.6f, Start,End:%s}", p.Cluster, p.Namespace, p.Name, p.Bytes, p.Cost(), kubecost.NewWindow(&p.Start, &p.End))
  97. }
  98. // Key returns the pvcKey for the calling pvc
  99. func (p *pvc) key() pvcKey {
  100. return newPVCKey(p.Cluster, p.Namespace, p.Name)
  101. }
  102. // pv describes a PersistentVolume
  103. type pv struct {
  104. Start time.Time `json:"start"`
  105. End time.Time `json:"end"`
  106. Bytes float64 `json:"bytes"`
  107. CostPerGiBHour float64 `json:"costPerGiBHour"`
  108. Cluster string `json:"cluster"`
  109. Name string `json:"name"`
  110. StorageClass string `json:"storageClass"`
  111. }
  112. func (p *pv) clone() *pv {
  113. if p == nil {
  114. return nil
  115. }
  116. return &pv{
  117. Start: p.Start,
  118. End: p.End,
  119. Bytes: p.Bytes,
  120. CostPerGiBHour: p.CostPerGiBHour,
  121. Cluster: p.Cluster,
  122. Name: p.Name,
  123. StorageClass: p.StorageClass,
  124. }
  125. }
  126. func (p *pv) equal(that *pv) bool {
  127. if p == nil {
  128. return that == nil
  129. }
  130. if !p.Start.Equal(that.Start) {
  131. return false
  132. }
  133. if !p.End.Equal(that.End) {
  134. return false
  135. }
  136. if p.Bytes != that.Bytes {
  137. return false
  138. }
  139. if p.CostPerGiBHour != that.CostPerGiBHour {
  140. return false
  141. }
  142. if p.Cluster != that.Cluster {
  143. return false
  144. }
  145. if p.Name != that.Name {
  146. return false
  147. }
  148. if p.StorageClass != that.StorageClass {
  149. return false
  150. }
  151. return true
  152. }
  153. // String returns a string representation of the pv
  154. func (p *pv) String() string {
  155. if p == nil {
  156. return "<nil>"
  157. }
  158. return fmt.Sprintf("%s/%s{Bytes:%.2f, Cost/GiB*Hr:%.6f, StorageClass:%s}", p.Cluster, p.Name, p.Bytes, p.CostPerGiBHour, p.StorageClass)
  159. }
  160. func (p *pv) minutes() float64 {
  161. if p == nil {
  162. return 0.0
  163. }
  164. return p.End.Sub(p.Start).Minutes()
  165. }
  166. // key returns the pvKey for the calling pvc
  167. func (p *pv) key() pvKey {
  168. return newPVKey(p.Cluster, p.Name)
  169. }
  170. // lbCost describes the start and end time of a Load Balancer along with cost
  171. type lbCost struct {
  172. TotalCost float64
  173. Start time.Time
  174. End time.Time
  175. }
  176. // NodePricing describes the resource costs associated with a given node, as
  177. // well as the source of the information (e.g. prometheus, custom)
  178. type nodePricing struct {
  179. Name string
  180. NodeType string
  181. ProviderID string
  182. Preemptible bool
  183. CostPerCPUHr float64
  184. CostPerRAMGiBHr float64
  185. CostPerGPUHr float64
  186. Discount float64
  187. Source string
  188. }