allocation_types.go 4.9 KB

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