assetprops.go 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. package kubecost
  2. import (
  3. "fmt"
  4. "strings"
  5. )
  6. // AssetProperty is a kind of property belonging to an Asset
  7. type AssetProperty string
  8. const (
  9. // AssetNilProp is the zero-value of AssetProperty
  10. AssetNilProp AssetProperty = ""
  11. // AssetAccountProp describes the account of the Asset
  12. AssetAccountProp AssetProperty = "account"
  13. // AssetCategoryProp describes the category of the Asset
  14. AssetCategoryProp AssetProperty = "category"
  15. // AssetClusterProp describes the cluster of the Asset
  16. AssetClusterProp AssetProperty = "cluster"
  17. // AssetNameProp describes the name of the Asset
  18. AssetNameProp AssetProperty = "name"
  19. // AssetNodeProp describes the node of the Asset
  20. AssetNodeProp AssetProperty = "node"
  21. // AssetProjectProp describes the project of the Asset
  22. AssetProjectProp AssetProperty = "project"
  23. // AssetProviderProp describes the provider of the Asset
  24. AssetProviderProp AssetProperty = "provider"
  25. // AssetProviderIDProp describes the providerID of the Asset
  26. AssetProviderIDProp AssetProperty = "providerID"
  27. // AssetServiceProp describes the service of the Asset
  28. AssetServiceProp AssetProperty = "service"
  29. // AssetTypeProp describes the type of the Asset
  30. AssetTypeProp AssetProperty = "type"
  31. )
  32. // ParseAssetProperty attempts to parse a string into an AssetProperty
  33. func ParseAssetProperty(text string) (AssetProperty, error) {
  34. switch strings.TrimSpace(strings.ToLower(text)) {
  35. case "account":
  36. return AssetAccountProp, nil
  37. case "category":
  38. return AssetCategoryProp, nil
  39. case "cluster":
  40. return AssetClusterProp, nil
  41. case "name":
  42. return AssetNameProp, nil
  43. case "project":
  44. return AssetProjectProp, nil
  45. case "provider":
  46. return AssetProviderProp, nil
  47. case "providerid":
  48. return AssetProviderIDProp, nil
  49. case "service":
  50. return AssetServiceProp, nil
  51. case "type":
  52. return AssetTypeProp, nil
  53. }
  54. return AssetNilProp, fmt.Errorf("invalid asset property: %s", text)
  55. }
  56. // Category options
  57. // ComputeCategory signifies the Compute Category
  58. const ComputeCategory = "Compute"
  59. // StorageCategory signifies the Storage Category
  60. const StorageCategory = "Storage"
  61. // NetworkCategory signifies the Network Category
  62. const NetworkCategory = "Network"
  63. // ManagementCategory signifies the Management Category
  64. const ManagementCategory = "Management"
  65. // SharedCategory signifies an unassigned Category
  66. const SharedCategory = "Shared"
  67. // OtherCategory signifies an unassigned Category
  68. const OtherCategory = "Other"
  69. // Provider options
  70. // AWSProvider describes the provider AWS
  71. const AWSProvider = "AWS"
  72. // GCPProvider describes the provider GCP
  73. const GCPProvider = "GCP"
  74. // AzureProvider describes the provider Azure
  75. const AzureProvider = "Azure"
  76. // CSVProvider describes the provider a CSV
  77. const CSVProvider = "CSV"
  78. // ScalewayProvider describes the provider Scaleway
  79. const ScalewayProvider = "Scaleway"
  80. // NilProvider describes unknown provider
  81. const NilProvider = "-"
  82. // Service options
  83. const KubernetesService = "Kubernetes"
  84. // ParseProvider attempts to parse and return a known provider, given a string
  85. func ParseProvider(str string) string {
  86. switch strings.ToLower(strings.TrimSpace(str)) {
  87. case "aws", "eks", "amazon":
  88. return AWSProvider
  89. case "gcp", "gke", "google":
  90. return GCPProvider
  91. case "azure":
  92. return AzureProvider
  93. case "scaleway", "scw", "kapsule":
  94. return ScalewayProvider
  95. default:
  96. return NilProvider
  97. }
  98. }
  99. // AssetProperties describes all properties assigned to an Asset.
  100. type AssetProperties struct {
  101. Category string `json:"category,omitempty"`
  102. Provider string `json:"provider,omitempty"`
  103. Account string `json:"account,omitempty"`
  104. Project string `json:"project,omitempty"`
  105. Service string `json:"service,omitempty"`
  106. Cluster string `json:"cluster,omitempty"`
  107. Name string `json:"name,omitempty"`
  108. ProviderID string `json:"providerID,omitempty"`
  109. }
  110. // Clone returns a cloned instance of the given AssetProperties
  111. func (ap *AssetProperties) Clone() *AssetProperties {
  112. if ap == nil {
  113. return nil
  114. }
  115. clone := &AssetProperties{}
  116. clone.Category = ap.Category
  117. clone.Provider = ap.Provider
  118. clone.Account = ap.Account
  119. clone.Project = ap.Project
  120. clone.Service = ap.Service
  121. clone.Cluster = ap.Cluster
  122. clone.Name = ap.Name
  123. clone.ProviderID = ap.ProviderID
  124. return clone
  125. }
  126. // Equal returns true only if both AssetProperties are non-nil exact matches
  127. func (ap *AssetProperties) Equal(that *AssetProperties) bool {
  128. if ap == nil || that == nil {
  129. return false
  130. }
  131. if ap.Category != that.Category {
  132. return false
  133. }
  134. if ap.Provider != that.Provider {
  135. return false
  136. }
  137. if ap.Account != that.Account {
  138. return false
  139. }
  140. if ap.Project != that.Project {
  141. return false
  142. }
  143. if ap.Service != that.Service {
  144. return false
  145. }
  146. if ap.Cluster != that.Cluster {
  147. return false
  148. }
  149. if ap.Name != that.Name {
  150. return false
  151. }
  152. if ap.ProviderID != that.ProviderID {
  153. return false
  154. }
  155. return true
  156. }
  157. // Keys returns the list of string values used to key the Asset based on the
  158. // list of properties provided.
  159. func (ap *AssetProperties) Keys(props []AssetProperty) []string {
  160. keys := []string{}
  161. if ap == nil {
  162. return keys
  163. }
  164. if (props == nil || hasProp(props, AssetCategoryProp)) && ap.Category != "" {
  165. keys = append(keys, ap.Category)
  166. }
  167. if (props == nil || hasProp(props, AssetProviderProp)) && ap.Provider != "" {
  168. keys = append(keys, ap.Provider)
  169. }
  170. if (props == nil || hasProp(props, AssetAccountProp)) && ap.Account != "" {
  171. keys = append(keys, ap.Account)
  172. }
  173. if (props == nil || hasProp(props, AssetProjectProp)) && ap.Project != "" {
  174. keys = append(keys, ap.Project)
  175. }
  176. if (props == nil || hasProp(props, AssetServiceProp)) && ap.Service != "" {
  177. keys = append(keys, ap.Service)
  178. }
  179. if (props == nil || hasProp(props, AssetClusterProp)) && ap.Cluster != "" {
  180. keys = append(keys, ap.Cluster)
  181. }
  182. if (props == nil || hasProp(props, AssetNameProp)) && ap.Name != "" {
  183. keys = append(keys, ap.Name)
  184. }
  185. if (props == nil || hasProp(props, AssetProviderIDProp)) && ap.ProviderID != "" {
  186. keys = append(keys, ap.ProviderID)
  187. }
  188. return keys
  189. }
  190. // Merge retains only the properties shared with the given AssetProperties
  191. func (ap *AssetProperties) Merge(that *AssetProperties) *AssetProperties {
  192. if ap == nil || that == nil {
  193. return nil
  194. }
  195. result := &AssetProperties{}
  196. if ap.Category == that.Category {
  197. result.Category = ap.Category
  198. }
  199. if ap.Provider == that.Provider {
  200. result.Provider = ap.Provider
  201. }
  202. if ap.Account == that.Account {
  203. result.Account = ap.Account
  204. }
  205. if ap.Project == that.Project {
  206. result.Project = ap.Project
  207. }
  208. if ap.Service == that.Service {
  209. result.Service = ap.Service
  210. }
  211. if ap.Cluster == that.Cluster {
  212. result.Cluster = ap.Cluster
  213. }
  214. if ap.Name == that.Name {
  215. result.Name = ap.Name
  216. }
  217. if ap.ProviderID == that.ProviderID {
  218. result.ProviderID = ap.ProviderID
  219. }
  220. return result
  221. }
  222. // String represents the properties as a string
  223. func (ap *AssetProperties) String() string {
  224. if ap == nil {
  225. return "<nil>"
  226. }
  227. strs := []string{}
  228. if ap.Category != "" {
  229. strs = append(strs, "Category:"+ap.Category)
  230. }
  231. if ap.Provider != "" {
  232. strs = append(strs, "Provider:"+ap.Provider)
  233. }
  234. if ap.Account != "" {
  235. strs = append(strs, "Account:"+ap.Account)
  236. }
  237. if ap.Project != "" {
  238. strs = append(strs, "Project:"+ap.Project)
  239. }
  240. if ap.Service != "" {
  241. strs = append(strs, "Service:"+ap.Service)
  242. }
  243. if ap.Cluster != "" {
  244. strs = append(strs, "Cluster:"+ap.Cluster)
  245. }
  246. if ap.Name != "" {
  247. strs = append(strs, "Name:"+ap.Name)
  248. }
  249. if ap.ProviderID != "" {
  250. strs = append(strs, "ProviderID:"+ap.ProviderID)
  251. }
  252. return strings.Join(strs, ",")
  253. }
  254. func hasProp(props []AssetProperty, prop AssetProperty) bool {
  255. for _, p := range props {
  256. if p == prop {
  257. return true
  258. }
  259. }
  260. return false
  261. }