properties.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744
  1. package kubecost
  2. import (
  3. "fmt"
  4. "sort"
  5. "strings"
  6. util "github.com/kubecost/cost-model/pkg/util"
  7. )
  8. type Property string
  9. const (
  10. NilProp Property = ""
  11. ClusterProp Property = "cluster"
  12. NodeProp Property = "node"
  13. ContainerProp Property = "container"
  14. ControllerProp Property = "controller"
  15. ControllerKindProp Property = "controllerKind"
  16. LabelProp Property = "label"
  17. AnnotationProp Property = "annotation"
  18. NamespaceProp Property = "namespace"
  19. PodProp Property = "pod"
  20. ServiceProp Property = "service"
  21. )
  22. var availableProperties []Property = []Property{
  23. NilProp,
  24. ClusterProp,
  25. NodeProp,
  26. ContainerProp,
  27. ControllerProp,
  28. ControllerKindProp,
  29. LabelProp,
  30. AnnotationProp,
  31. NamespaceProp,
  32. PodProp,
  33. ServiceProp,
  34. }
  35. func ParseProperty(prop string) Property {
  36. for _, property := range availableProperties {
  37. if strings.ToLower(string(property)) == strings.ToLower(prop) {
  38. return property
  39. }
  40. }
  41. return NilProp
  42. }
  43. func (p Property) String() string {
  44. return string(p)
  45. }
  46. type PropertyValue struct {
  47. Property Property
  48. Value interface{}
  49. }
  50. // Properties describes a set of Kubernetes objects.
  51. type Properties map[Property]interface{}
  52. // TODO niko/etl make sure Services deep copy works correctly
  53. func (p *Properties) Clone() Properties {
  54. if p == nil {
  55. return nil
  56. }
  57. clone := Properties{}
  58. for k, v := range *p {
  59. clone[k] = v
  60. }
  61. return clone
  62. }
  63. func (p *Properties) Equal(that *Properties) bool {
  64. if p == nil || that == nil {
  65. return false
  66. }
  67. if p.Length() != that.Length() {
  68. return false
  69. }
  70. pCluster, _ := p.GetCluster()
  71. thatCluster, _ := that.GetCluster()
  72. if pCluster != thatCluster {
  73. return false
  74. }
  75. pNode, _ := p.GetNode()
  76. thatNode, _ := that.GetNode()
  77. if pNode != thatNode {
  78. return false
  79. }
  80. pContainer, _ := p.GetContainer()
  81. thatContainer, _ := that.GetContainer()
  82. if pContainer != thatContainer {
  83. return false
  84. }
  85. pController, _ := p.GetController()
  86. thatController, _ := that.GetController()
  87. if pController != thatController {
  88. return false
  89. }
  90. pControllerKind, _ := p.GetControllerKind()
  91. thatControllerKind, _ := that.GetControllerKind()
  92. if pControllerKind != thatControllerKind {
  93. return false
  94. }
  95. pNamespace, _ := p.GetNamespace()
  96. thatNamespace, _ := that.GetNamespace()
  97. if pNamespace != thatNamespace {
  98. return false
  99. }
  100. pPod, _ := p.GetPod()
  101. thatPod, _ := that.GetPod()
  102. if pPod != thatPod {
  103. return false
  104. }
  105. pLabels, _ := p.GetLabels()
  106. thatLabels, _ := that.GetLabels()
  107. if len(pLabels) != len(thatLabels) {
  108. for k, pv := range pLabels {
  109. tv, ok := thatLabels[k]
  110. if !ok || tv != pv {
  111. return false
  112. }
  113. }
  114. return false
  115. }
  116. pAnnotations, _ := p.GetAnnotations()
  117. thatAnnotations, _ := that.GetAnnotations()
  118. if len(pAnnotations) != len(thatAnnotations) {
  119. for k, pv := range pAnnotations {
  120. tv, ok := thatAnnotations[k]
  121. if !ok || tv != pv {
  122. return false
  123. }
  124. }
  125. return false
  126. }
  127. pServices, _ := p.GetServices()
  128. thatServices, _ := that.GetServices()
  129. if len(pServices) != len(thatServices) {
  130. sort.Strings(pServices)
  131. sort.Strings(thatServices)
  132. for i, pv := range pServices {
  133. tv := thatServices[i]
  134. if tv != pv {
  135. return false
  136. }
  137. }
  138. return false
  139. }
  140. return true
  141. }
  142. func (p *Properties) Intersection(that Properties) Properties {
  143. spec := &Properties{}
  144. sCluster, sErr := p.GetCluster()
  145. tCluster, tErr := that.GetCluster()
  146. if sErr == nil && tErr == nil && sCluster == tCluster {
  147. spec.SetCluster(sCluster)
  148. }
  149. sNode, sErr := p.GetNode()
  150. tNode, tErr := that.GetNode()
  151. if sErr == nil && tErr == nil && sNode == tNode {
  152. spec.SetNode(sNode)
  153. }
  154. sContainer, sErr := p.GetContainer()
  155. tContainer, tErr := that.GetContainer()
  156. if sErr == nil && tErr == nil && sContainer == tContainer {
  157. spec.SetContainer(sContainer)
  158. }
  159. sController, sErr := p.GetController()
  160. tController, tErr := that.GetController()
  161. if sErr == nil && tErr == nil && sController == tController {
  162. spec.SetController(sController)
  163. }
  164. sControllerKind, sErr := p.GetControllerKind()
  165. tControllerKind, tErr := that.GetControllerKind()
  166. if sErr == nil && tErr == nil && sControllerKind == tControllerKind {
  167. spec.SetControllerKind(sControllerKind)
  168. }
  169. sNamespace, sErr := p.GetNamespace()
  170. tNamespace, tErr := that.GetNamespace()
  171. if sErr == nil && tErr == nil && sNamespace == tNamespace {
  172. spec.SetNamespace(sNamespace)
  173. }
  174. sPod, sErr := p.GetPod()
  175. tPod, tErr := that.GetPod()
  176. if sErr == nil && tErr == nil && sPod == tPod {
  177. spec.SetPod(sPod)
  178. }
  179. // TODO niko/etl intersection of services and labels and annotations
  180. return *spec
  181. }
  182. // Length returns the number of Properties
  183. func (p *Properties) Length() int {
  184. if p == nil {
  185. return 0
  186. }
  187. return len(*p)
  188. }
  189. func (p *Properties) Matches(that Properties) bool {
  190. // The only Properties that a nil Properties matches is an empty one
  191. if p == nil {
  192. return that.Length() == 0
  193. }
  194. // Matching on cluster, namespace, controller, controller kind, pod,
  195. // and container are simple string equality comparisons. By default,
  196. // we assume a match. For each Property given to match, we say that the
  197. // match fails if we don't have that Property, or if we have it but the
  198. // strings are not equal.
  199. if thatCluster, thatErr := that.GetCluster(); thatErr == nil {
  200. if thisCluster, thisErr := p.GetCluster(); thisErr != nil || thisCluster != thatCluster {
  201. return false
  202. }
  203. }
  204. if thatNode, thatErr := that.GetNode(); thatErr == nil {
  205. if thisNode, thisErr := p.GetNode(); thisErr != nil || thisNode != thatNode {
  206. return false
  207. }
  208. }
  209. if thatNamespace, thatErr := that.GetNamespace(); thatErr == nil {
  210. if thisNamespace, thisErr := p.GetNamespace(); thisErr != nil || thisNamespace != thatNamespace {
  211. return false
  212. }
  213. }
  214. if thatController, thatErr := that.GetController(); thatErr == nil {
  215. if thisController, thisErr := p.GetController(); thisErr != nil || thisController != thatController {
  216. return false
  217. }
  218. }
  219. if thatControllerKind, thatErr := that.GetControllerKind(); thatErr == nil {
  220. if thisControllerKind, thisErr := p.GetControllerKind(); thisErr != nil || thisControllerKind != thatControllerKind {
  221. return false
  222. }
  223. }
  224. if thatPod, thatErr := that.GetPod(); thatErr == nil {
  225. if thisPod, thisErr := p.GetPod(); thisErr != nil || thisPod != thatPod {
  226. return false
  227. }
  228. }
  229. if thatContainer, thatErr := that.GetContainer(); thatErr == nil {
  230. if thisContainer, thisErr := p.GetContainer(); thisErr != nil || thisContainer != thatContainer {
  231. return false
  232. }
  233. }
  234. // Matching on Services only occurs if a non-zero length slice of strings
  235. // is given. The comparison fails if there exists a string to match that is
  236. // not present in our slice of services.
  237. if thatServices, thatErr := that.GetServices(); thatErr == nil && len(thatServices) > 0 {
  238. thisServices, thisErr := p.GetServices()
  239. if thisErr != nil {
  240. return false
  241. }
  242. for _, service := range thatServices {
  243. match := false
  244. for _, s := range thisServices {
  245. if s == service {
  246. match = true
  247. break
  248. }
  249. }
  250. if !match {
  251. return false
  252. }
  253. }
  254. }
  255. // Matching on Labels only occurs if a non-zero length map of strings is
  256. // given. The comparison fails if there exists a key/value pair to match
  257. // that is not present in our set of labels.
  258. if thatServices, thatErr := that.GetServices(); thatErr == nil && len(thatServices) > 0 {
  259. thisServices, thisErr := p.GetServices()
  260. if thisErr != nil {
  261. return false
  262. }
  263. for _, service := range thatServices {
  264. match := false
  265. for _, s := range thisServices {
  266. if s == service {
  267. match = true
  268. break
  269. }
  270. }
  271. if !match {
  272. return false
  273. }
  274. }
  275. }
  276. return true
  277. }
  278. func (p *Properties) String() string {
  279. if p == nil {
  280. return "<nil>"
  281. }
  282. strs := []string{}
  283. for key, prop := range *p {
  284. strs = append(strs, fmt.Sprintf("%s:%s", key, prop))
  285. }
  286. return fmt.Sprintf("{%s}", strings.Join(strs, "; "))
  287. }
  288. func (p *Properties) Get(prop Property) (string, error) {
  289. if raw, ok := (*p)[prop]; ok {
  290. if result, ok := raw.(string); ok {
  291. return result, nil
  292. }
  293. return "", fmt.Errorf("%s is not a string", prop)
  294. }
  295. return "", fmt.Errorf("%s not set", prop)
  296. }
  297. func (p *Properties) Has(prop Property) bool {
  298. _, ok := (*p)[prop]
  299. return ok
  300. }
  301. func (p *Properties) Set(prop Property, value string) {
  302. (*p)[prop] = value
  303. }
  304. func (p *Properties) GetCluster() (string, error) {
  305. if raw, ok := (*p)[ClusterProp]; ok {
  306. if cluster, ok := raw.(string); ok {
  307. return cluster, nil
  308. }
  309. return "", fmt.Errorf("ClusterProp is not a string")
  310. }
  311. return "", fmt.Errorf("ClusterProp not set")
  312. }
  313. func (p *Properties) HasCluster() bool {
  314. _, ok := (*p)[ClusterProp]
  315. return ok
  316. }
  317. func (p *Properties) SetCluster(cluster string) {
  318. (*p)[ClusterProp] = cluster
  319. }
  320. func (p *Properties) GetNode() (string, error) {
  321. if raw, ok := (*p)[NodeProp]; ok {
  322. if node, ok := raw.(string); ok {
  323. return node, nil
  324. }
  325. return "", fmt.Errorf("NodeProp is not a string")
  326. }
  327. return "", fmt.Errorf("NodeProp not set")
  328. }
  329. func (p *Properties) HasNode() bool {
  330. _, ok := (*p)[NodeProp]
  331. return ok
  332. }
  333. func (p *Properties) SetNode(node string) {
  334. (*p)[NodeProp] = node
  335. }
  336. func (p *Properties) GetContainer() (string, error) {
  337. if raw, ok := (*p)[ContainerProp]; ok {
  338. if container, ok := raw.(string); ok {
  339. return container, nil
  340. }
  341. return "", fmt.Errorf("ContainerProp is not a string")
  342. }
  343. return "", fmt.Errorf("ContainerProp not set")
  344. }
  345. func (p *Properties) HasContainer() bool {
  346. _, ok := (*p)[ContainerProp]
  347. return ok
  348. }
  349. func (p *Properties) SetContainer(container string) {
  350. (*p)[ContainerProp] = container
  351. }
  352. func (p *Properties) GetController() (string, error) {
  353. if raw, ok := (*p)[ControllerProp]; ok {
  354. if controller, ok := raw.(string); ok {
  355. return controller, nil
  356. }
  357. return "", fmt.Errorf("ControllerProp is not a string")
  358. }
  359. return "", fmt.Errorf("ControllerProp not set")
  360. }
  361. func (p *Properties) HasController() bool {
  362. _, ok := (*p)[ControllerProp]
  363. return ok
  364. }
  365. func (p *Properties) SetController(controller string) {
  366. (*p)[ControllerProp] = controller
  367. }
  368. func (p *Properties) GetControllerKind() (string, error) {
  369. if raw, ok := (*p)[ControllerKindProp]; ok {
  370. if controllerKind, ok := raw.(string); ok {
  371. return controllerKind, nil
  372. }
  373. return "", fmt.Errorf("ControllerKindProp is not a string")
  374. }
  375. return "", fmt.Errorf("ControllerKindProp not set")
  376. }
  377. func (p *Properties) HasControllerKind() bool {
  378. _, ok := (*p)[ControllerKindProp]
  379. return ok
  380. }
  381. func (p *Properties) SetControllerKind(controllerKind string) {
  382. (*p)[ControllerKindProp] = controllerKind
  383. }
  384. func (p *Properties) GetLabels() (map[string]string, error) {
  385. if raw, ok := (*p)[LabelProp]; ok {
  386. if labels, ok := raw.(map[string]string); ok {
  387. return labels, nil
  388. }
  389. return map[string]string{}, fmt.Errorf("LabelProp is not a map[string]string")
  390. }
  391. return map[string]string{}, fmt.Errorf("LabelProp not set")
  392. }
  393. func (p *Properties) HasLabel() bool {
  394. _, ok := (*p)[LabelProp]
  395. return ok
  396. }
  397. func (p *Properties) SetLabels(labels map[string]string) {
  398. (*p)[LabelProp] = labels
  399. }
  400. func (p *Properties) GetAnnotations() (map[string]string, error) {
  401. if raw, ok := (*p)[AnnotationProp]; ok {
  402. if annotations, ok := raw.(map[string]string); ok {
  403. return annotations, nil
  404. }
  405. return map[string]string{}, fmt.Errorf("AnnotationProp is not a map[string]string")
  406. }
  407. return map[string]string{}, fmt.Errorf("AnnotationProp not set")
  408. }
  409. func (p *Properties) HasAnnotations() bool {
  410. _, ok := (*p)[AnnotationProp]
  411. return ok
  412. }
  413. func (p *Properties) SetAnnotations(annotations map[string]string) {
  414. (*p)[AnnotationProp] = annotations
  415. }
  416. func (p *Properties) GetNamespace() (string, error) {
  417. if raw, ok := (*p)[NamespaceProp]; ok {
  418. if namespace, ok := raw.(string); ok {
  419. return namespace, nil
  420. }
  421. return "", fmt.Errorf("NamespaceProp is not a string")
  422. }
  423. return "", fmt.Errorf("NamespaceProp not set")
  424. }
  425. func (p *Properties) HasNamespace() bool {
  426. _, ok := (*p)[NamespaceProp]
  427. return ok
  428. }
  429. func (p *Properties) SetNamespace(namespace string) {
  430. (*p)[NamespaceProp] = namespace
  431. }
  432. func (p *Properties) GetPod() (string, error) {
  433. if raw, ok := (*p)[PodProp]; ok {
  434. if pod, ok := raw.(string); ok {
  435. return pod, nil
  436. }
  437. return "", fmt.Errorf("PodProp is not a string")
  438. }
  439. return "", fmt.Errorf("PodProp not set")
  440. }
  441. func (p *Properties) HasPod() bool {
  442. _, ok := (*p)[PodProp]
  443. return ok
  444. }
  445. func (p *Properties) SetPod(pod string) {
  446. (*p)[PodProp] = pod
  447. }
  448. func (p *Properties) GetServices() ([]string, error) {
  449. if raw, ok := (*p)[ServiceProp]; ok {
  450. if services, ok := raw.([]string); ok {
  451. return services, nil
  452. }
  453. return []string{}, fmt.Errorf("ServiceProp is not a string")
  454. }
  455. return []string{}, fmt.Errorf("ServiceProp not set")
  456. }
  457. func (p *Properties) HasService() bool {
  458. _, ok := (*p)[ServiceProp]
  459. return ok
  460. }
  461. func (p *Properties) SetServices(services []string) {
  462. (*p)[ServiceProp] = services
  463. }
  464. func (p *Properties) MarshalBinary() (data []byte, err error) {
  465. buff := util.NewBuffer()
  466. buff.WriteUInt8(CodecVersion) // version
  467. // ClusterProp
  468. cluster, err := p.GetCluster()
  469. if err != nil {
  470. buff.WriteUInt8(uint8(0)) // write nil byte
  471. } else {
  472. buff.WriteUInt8(uint8(1)) // write non-nil byte
  473. buff.WriteString(cluster) // write string
  474. }
  475. // NodeProp
  476. node, err := p.GetNode()
  477. if err != nil {
  478. buff.WriteUInt8(uint8(0)) // write nil byte
  479. } else {
  480. buff.WriteUInt8(uint8(1)) // write non-nil byte
  481. buff.WriteString(node) // write string
  482. }
  483. // ContainerProp
  484. container, err := p.GetContainer()
  485. if err != nil {
  486. buff.WriteUInt8(uint8(0)) // write nil byte
  487. } else {
  488. buff.WriteUInt8(uint8(1)) // write non-nil byte
  489. buff.WriteString(container) // write string
  490. }
  491. // ControllerProp
  492. controller, err := p.GetController()
  493. if err != nil {
  494. buff.WriteUInt8(uint8(0)) // write nil byte
  495. } else {
  496. buff.WriteUInt8(uint8(1)) // write non-nil byte
  497. buff.WriteString(controller) // write string
  498. }
  499. // ControllerKindProp
  500. controllerKind, err := p.GetControllerKind()
  501. if err != nil {
  502. buff.WriteUInt8(uint8(0)) // write nil byte
  503. } else {
  504. buff.WriteUInt8(uint8(1)) // write non-nil byte
  505. buff.WriteString(controllerKind) // write string
  506. }
  507. // NamespaceProp
  508. namespace, err := p.GetNamespace()
  509. if err != nil {
  510. buff.WriteUInt8(uint8(0)) // write nil byte
  511. } else {
  512. buff.WriteUInt8(uint8(1)) // write non-nil byte
  513. buff.WriteString(namespace) // write string
  514. }
  515. // PodProp
  516. pod, err := p.GetPod()
  517. if err != nil {
  518. buff.WriteUInt8(uint8(0)) // write nil byte
  519. } else {
  520. buff.WriteUInt8(uint8(1)) // write non-nil byte
  521. buff.WriteString(pod) // write string
  522. }
  523. // LabelProp
  524. labels, err := p.GetLabels()
  525. if err != nil {
  526. buff.WriteUInt8(uint8(0)) // write nil byte
  527. } else {
  528. buff.WriteUInt8(uint8(1)) // write non-nil byte
  529. buff.WriteInt(len(labels)) // map length
  530. for k, v := range labels {
  531. buff.WriteString(k) // write string
  532. buff.WriteString(v) // write string
  533. }
  534. }
  535. // AnnotationProp
  536. annotations, err := p.GetAnnotations()
  537. if err != nil {
  538. buff.WriteUInt8(uint8(0)) // write nil byte
  539. } else {
  540. buff.WriteUInt8(uint8(1)) // write non-nil byte
  541. buff.WriteInt(len(annotations)) // map length
  542. for k, v := range annotations {
  543. buff.WriteString(k) // write string
  544. buff.WriteString(v) // write string
  545. }
  546. }
  547. // ServiceProp
  548. services, err := p.GetServices()
  549. if err != nil {
  550. buff.WriteUInt8(uint8(0)) // write nil byte
  551. } else {
  552. buff.WriteUInt8(uint8(1)) // write non-nil byte
  553. buff.WriteInt(len(services)) // slice length
  554. for _, v := range services {
  555. buff.WriteString(v) // write string
  556. }
  557. }
  558. return buff.Bytes(), nil
  559. }
  560. func (p *Properties) UnmarshalBinary(data []byte) error {
  561. buff := util.NewBufferFromBytes(data)
  562. v := buff.ReadUInt8() // version
  563. if v != CodecVersion {
  564. return fmt.Errorf("Invalid Version. Expected %d, got %d", CodecVersion, v)
  565. }
  566. *p = Properties{}
  567. // ClusterProp
  568. if buff.ReadUInt8() == 1 { // read nil byte
  569. cluster := buff.ReadString() // read string
  570. p.SetCluster(cluster)
  571. }
  572. // NodeProp
  573. if buff.ReadUInt8() == 1 { // read nil byte
  574. node := buff.ReadString() // read string
  575. p.SetNode(node)
  576. }
  577. // ContainerProp
  578. if buff.ReadUInt8() == 1 { // read nil byte
  579. container := buff.ReadString() // read string
  580. p.SetContainer(container)
  581. }
  582. // ControllerProp
  583. if buff.ReadUInt8() == 1 { // read nil byte
  584. controller := buff.ReadString() // read string
  585. p.SetController(controller)
  586. }
  587. // ControllerKindProp
  588. if buff.ReadUInt8() == 1 { // read nil byte
  589. controllerKind := buff.ReadString() // read string
  590. p.SetControllerKind(controllerKind)
  591. }
  592. // NamespaceProp
  593. if buff.ReadUInt8() == 1 { // read nil byte
  594. namespace := buff.ReadString() // read string
  595. p.SetNamespace(namespace)
  596. }
  597. // PodProp
  598. if buff.ReadUInt8() == 1 { // read nil byte
  599. pod := buff.ReadString() // read string
  600. p.SetPod(pod)
  601. }
  602. // LabelProp
  603. if buff.ReadUInt8() == 1 { // read nil byte
  604. labels := map[string]string{}
  605. length := buff.ReadInt() // read map len
  606. for idx := 0; idx < length; idx++ {
  607. key := buff.ReadString()
  608. val := buff.ReadString()
  609. labels[key] = val
  610. }
  611. p.SetLabels(labels)
  612. }
  613. // AnnotationProp
  614. if buff.ReadUInt8() == 1 { // read nil byte
  615. annotations := map[string]string{}
  616. length := buff.ReadInt() // read map len
  617. for idx := 0; idx < length; idx++ {
  618. key := buff.ReadString()
  619. val := buff.ReadString()
  620. annotations[key] = val
  621. }
  622. p.SetAnnotations(annotations)
  623. }
  624. // ServiceProp
  625. if buff.ReadUInt8() == 1 { // read nil byte
  626. services := []string{}
  627. length := buff.ReadInt() // read map len
  628. for idx := 0; idx < length; idx++ {
  629. val := buff.ReadString()
  630. services = append(services, val)
  631. }
  632. p.SetServices(services)
  633. }
  634. return nil
  635. }