allocationprops.go 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. package kubecost
  2. import (
  3. "fmt"
  4. "sort"
  5. "strings"
  6. )
  7. const (
  8. AllocationNilProp string = ""
  9. AllocationClusterProp string = "cluster"
  10. AllocationNodeProp string = "node"
  11. AllocationContainerProp string = "container"
  12. AllocationControllerProp string = "controller"
  13. AllocationControllerKindProp string = "controllerKind"
  14. AllocationNamespaceProp string = "namespace"
  15. AllocationPodProp string = "pod"
  16. AllocationProviderIDProp string = "providerID"
  17. AllocationServiceProp string = "service"
  18. AllocationLabelProp string = "label"
  19. AllocationAnnotationProp string = "annotation"
  20. AllocationDeploymentProp string = "deployment"
  21. AllocationStatefulSetProp string = "statefulset"
  22. AllocationDaemonSetProp string = "daemonset"
  23. AllocationJobProp string = "job"
  24. )
  25. func ParseProperty(text string) (string, error) {
  26. switch strings.TrimSpace(strings.ToLower(text)) {
  27. case "cluster":
  28. return AllocationClusterProp, nil
  29. case "node":
  30. return AllocationNodeProp, nil
  31. case "container":
  32. return AllocationContainerProp, nil
  33. case "controller":
  34. return AllocationControllerProp, nil
  35. case "controllerkind":
  36. return AllocationControllerKindProp, nil
  37. case "namespace":
  38. return AllocationNamespaceProp, nil
  39. case "pod":
  40. return AllocationPodProp, nil
  41. case "providerid":
  42. return AllocationProviderIDProp, nil
  43. case "service":
  44. return AllocationServiceProp, nil
  45. case "label":
  46. return AllocationLabelProp, nil
  47. case "annotation":
  48. return AllocationAnnotationProp, nil
  49. case "deployment":
  50. return AllocationDeploymentProp, nil
  51. case "daemonset":
  52. return AllocationDaemonSetProp, nil
  53. case "statefulset":
  54. return AllocationStatefulSetProp, nil
  55. case "job":
  56. return AllocationJobProp, nil
  57. }
  58. return AllocationNilProp, fmt.Errorf("invalid allocation property: %s", text)
  59. }
  60. // AllocationProperties describes a set of Kubernetes objects.
  61. type AllocationProperties struct {
  62. Cluster string `json:"cluster,omitempty"`
  63. Node string `json:"node,omitempty"`
  64. Container string `json:"container,omitempty"`
  65. Controller string `json:"controller,omitempty"`
  66. ControllerKind string `json:"controllerKind,omitempty"`
  67. Namespace string `json:"namespace,omitempty"`
  68. Pod string `json:"pod,omitempty"`
  69. Services []string `json:"services,omitempty"`
  70. ProviderID string `json:"providerID,omitempty"`
  71. Labels AllocationLabels `json:"allocationLabels,omitempty"`
  72. Annotations AllocationAnnotations `json:"allocationAnnotations,omitempty"`
  73. }
  74. // AllocationLabels is a schema-free mapping of key/value pairs that can be
  75. // attributed to an Allocation
  76. type AllocationLabels map[string]string
  77. // AllocationAnnotations is a schema-free mapping of key/value pairs that can be
  78. // attributed to an Allocation
  79. type AllocationAnnotations map[string]string
  80. func (p *AllocationProperties) Clone() *AllocationProperties {
  81. if p == nil {
  82. return nil
  83. }
  84. clone := &AllocationProperties{}
  85. clone.Cluster = p.Cluster
  86. clone.Node = p.Node
  87. clone.Container = p.Container
  88. clone.Controller = p.Controller
  89. clone.ControllerKind = p.ControllerKind
  90. clone.Namespace = p.Namespace
  91. clone.Pod = p.Pod
  92. clone.ProviderID = p.ProviderID
  93. var services []string
  94. for _, s := range p.Services {
  95. services = append(services, s)
  96. }
  97. clone.Services = services
  98. labels := make(map[string]string)
  99. for k, v := range p.Labels {
  100. labels[k] = v
  101. }
  102. clone.Labels = labels
  103. annotations := make(map[string]string)
  104. for k, v := range p.Annotations {
  105. annotations[k] = v
  106. }
  107. clone.Annotations = annotations
  108. return clone
  109. }
  110. func (p *AllocationProperties) Equal(that *AllocationProperties) bool {
  111. if p == nil || that == nil {
  112. return false
  113. }
  114. if p.Cluster != that.Cluster {
  115. return false
  116. }
  117. if p.Node != that.Node {
  118. return false
  119. }
  120. if p.Container != that.Container {
  121. return false
  122. }
  123. if p.Controller != that.Controller {
  124. return false
  125. }
  126. if p.ControllerKind != that.ControllerKind {
  127. return false
  128. }
  129. if p.Namespace != that.Namespace {
  130. return false
  131. }
  132. if p.Pod != that.Pod {
  133. return false
  134. }
  135. if p.ProviderID != that.ProviderID {
  136. return false
  137. }
  138. pLabels := p.Labels
  139. thatLabels := that.Labels
  140. if len(pLabels) == len(thatLabels) {
  141. for k, pv := range pLabels {
  142. tv, ok := thatLabels[k]
  143. if !ok || tv != pv {
  144. return false
  145. }
  146. }
  147. } else {
  148. return false
  149. }
  150. pAnnotations := p.Annotations
  151. thatAnnotations := that.Annotations
  152. if len(pAnnotations) == len(thatAnnotations) {
  153. for k, pv := range pAnnotations {
  154. tv, ok := thatAnnotations[k]
  155. if !ok || tv != pv {
  156. return false
  157. }
  158. }
  159. } else {
  160. return false
  161. }
  162. pServices := p.Services
  163. thatServices := that.Services
  164. if len(pServices) == len(thatServices) {
  165. sort.Strings(pServices)
  166. sort.Strings(thatServices)
  167. for i, pv := range pServices {
  168. tv := thatServices[i]
  169. if tv != pv {
  170. return false
  171. }
  172. }
  173. } else {
  174. return false
  175. }
  176. return true
  177. }
  178. // Intersection returns an *AllocationProperties which contains all matching fields between the calling and parameter AllocationProperties
  179. // nillable slices and maps are left as nil
  180. func (p *AllocationProperties) Intersection(that *AllocationProperties) *AllocationProperties {
  181. if p == nil || that == nil {
  182. return nil
  183. }
  184. intersectionProps := &AllocationProperties{}
  185. if p.Cluster == that.Cluster {
  186. intersectionProps.Cluster = p.Cluster
  187. }
  188. if p.Node == that.Node {
  189. intersectionProps.Node = p.Node
  190. }
  191. if p.Container == that.Container {
  192. intersectionProps.Container = p.Container
  193. }
  194. if p.Controller == that.Controller {
  195. intersectionProps.Controller = p.Controller
  196. }
  197. if p.ControllerKind == that.ControllerKind {
  198. intersectionProps.ControllerKind = p.ControllerKind
  199. }
  200. if p.Namespace == that.Namespace {
  201. intersectionProps.Namespace = p.Namespace
  202. }
  203. if p.Pod == that.Pod {
  204. intersectionProps.Pod = p.Pod
  205. }
  206. if p.ProviderID == that.ProviderID {
  207. intersectionProps.ProviderID = p.ProviderID
  208. }
  209. return intersectionProps
  210. }
  211. func (p *AllocationProperties) String() string {
  212. if p == nil {
  213. return "<nil>"
  214. }
  215. strs := []string{}
  216. if p.Cluster != "" {
  217. strs = append(strs, "Cluster:"+p.Cluster)
  218. }
  219. if p.Node != "" {
  220. strs = append(strs, "Node:"+p.Node)
  221. }
  222. if p.Container != "" {
  223. strs = append(strs, "Container:"+p.Container)
  224. }
  225. if p.Controller != "" {
  226. strs = append(strs, "Controller:"+p.Controller)
  227. }
  228. if p.ControllerKind != "" {
  229. strs = append(strs, "ControllerKind:"+p.ControllerKind)
  230. }
  231. if p.Namespace != "" {
  232. strs = append(strs, "Namespace:"+p.Namespace)
  233. }
  234. if p.Pod != "" {
  235. strs = append(strs, "Pod:"+p.Pod)
  236. }
  237. if p.ProviderID != "" {
  238. strs = append(strs, "ProviderID:"+p.ProviderID)
  239. }
  240. if len(p.Services) > 0 {
  241. strs = append(strs, "Services:"+strings.Join(p.Services, ";"))
  242. }
  243. var labelStrs []string
  244. for k, prop := range p.Labels {
  245. labelStrs = append(labelStrs, fmt.Sprintf("%s:%s", k, prop))
  246. }
  247. strs = append(strs, fmt.Sprintf("Labels:{%s}", strings.Join(strs, ",")))
  248. var AnnotationStrs []string
  249. for k, prop := range p.Annotations {
  250. AnnotationStrs = append(AnnotationStrs, fmt.Sprintf("%s:%s", k, prop))
  251. }
  252. strs = append(strs, fmt.Sprintf("Annotations:{%s}", strings.Join(strs, ",")))
  253. return fmt.Sprintf("{%s}", strings.Join(strs, "; "))
  254. }