customcostresponse.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. package model
  2. import "github.com/opencost/opencost/core/pkg/opencost"
  3. // see design at https://link.excalidraw.com/l/ABLQ24dkKai/CBEQtjH6Mr
  4. // for additional details on how these objects work in the context of
  5. // opencost's plugin system
  6. type CustomCostResponse struct {
  7. // provides metadata on the Custom CostResponse
  8. // deliberately left unstructured
  9. Metadata map[string]string
  10. // declared by plugin
  11. // eg snowflake == "data management",
  12. // datadog == "observability" etc
  13. // intended for top level agg
  14. Costsource string
  15. // the name of the custom cost source
  16. // e.g., "datadog"
  17. Domain string
  18. // the version of the Custom Cost response
  19. // is set by the plugin, will vary between
  20. // different plugins
  21. Version string
  22. // FOCUS billing currency
  23. Currency string
  24. // the window of the returned objects
  25. Window opencost.Window
  26. // array of CustomCosts
  27. Costs []*CustomCost
  28. // any errors in processing
  29. Errors []error
  30. }
  31. // designed to provide a superset of the FOCUS spec
  32. // https://github.com/FinOps-Open-Cost-and-Usage-Spec/FOCUS_Spec/releases/latest/download/spec.pdf
  33. type CustomCost struct {
  34. // provides metadata on the Custom CostResponse
  35. // deliberately left unstructured
  36. Metadata map[string]string
  37. // the region that the resource was incurred
  38. // corresponds to 'availability zone' of FOCUS
  39. Zone string
  40. // FOCUS billed Cost
  41. BilledCost float32
  42. // FOCUS billing account name
  43. AccountName string
  44. // FOCUS charge category
  45. ChargeCategory string
  46. // FOCUS charge description
  47. Description string
  48. // FOCUS List Cost
  49. ListCost float32
  50. // FOCUS List Unit Price
  51. ListUnitPrice float32
  52. // FOCUS Resource Name
  53. ResourceName string
  54. // FOCUS Resource type
  55. // if not set, assumed to be domain
  56. ResourceType string
  57. // ID of the individual cost. should be globally
  58. // unique. Assigned by plugin on read
  59. Id string
  60. // the provider's ID for the cost, if
  61. // available
  62. // FOCUS resource ID
  63. ProviderId string
  64. // the window of the returned specific
  65. // custom cost
  66. // equivalent to charge period start/end of FOCUS
  67. Window *opencost.Window
  68. // Returns key/value sets of labels
  69. // equivalent to Tags in focus spec
  70. Labels map[string]string
  71. // FOCUS usage quantity
  72. UsageQty float32
  73. // FOCUS usage Unit
  74. UsageUnit string
  75. // Optional struct to implement other focus
  76. // spec attributes
  77. ExtendedAttributes *ExtendedCustomCostAttributes
  78. }
  79. // These parts of the FOCUS spec are not expected
  80. // to be implemented by every plugin
  81. // however, if these bits of information are available,
  82. // they should be provided
  83. type ExtendedCustomCostAttributes struct {
  84. // FOCUS billing period start/end
  85. BillingPeriod *opencost.Window
  86. // FOCUS Billing Account ID
  87. AccountID string
  88. // FOCUS Charge Frequency
  89. ChargeFrequency string
  90. // FOCUS Charge Subcategory
  91. Subcategory string
  92. // FOCUS Commitment Discount Category
  93. CommitmentDiscountCategory string
  94. // FOCUS Commitment Discount ID
  95. CommitmentDiscountID string
  96. // FOCUS Commitment Discount Name
  97. CommitmentDiscountName string
  98. // FOCUS Commitment Discount Type
  99. CommitmentDiscountType string
  100. // FOCUS Effective Cost
  101. EffectiveCost float32
  102. // FOCUS Invoice Issuer
  103. InvoiceIssuer string
  104. // FOCUS Provider
  105. // if unset, assumed to be domain
  106. Provider string
  107. // FOCUS Publisher
  108. // if unset, assumed to be domain
  109. Publisher string
  110. // FOCUS Service Category
  111. // if unset, assumed to be cost source
  112. ServiceCategory string
  113. // FOCUS Service Name
  114. // if unset, assumed to be cost source
  115. ServiceName string
  116. // FOCUS SKU ID
  117. SkuID string
  118. // FOCUS SKU Price ID
  119. SkuPriceID string
  120. // FOCUS Sub Account ID
  121. SubAccountID string
  122. // FOCUS Sub Account Name
  123. SubAccountName string
  124. // FOCUS Pricing Quantity
  125. PricingQuantity float32
  126. // FOCUS Pricing Unit
  127. PricingUnit string
  128. // FOCUS Pricing Category
  129. PricingCategory string
  130. }
  131. func (c *CustomCostResponse) Clone() CustomCostResponse {
  132. win := c.GetWindow().Clone()
  133. costClones := []*CustomCost{}
  134. for _, cost := range c.GetCosts() {
  135. clone := cost.Clone()
  136. costClones = append(costClones, &clone)
  137. }
  138. errClones := []error{}
  139. for _, err := range c.GetErrors() {
  140. errClones = append(errClones, err)
  141. }
  142. return CustomCostResponse{
  143. Metadata: cloneMap(c.GetMetadata()),
  144. Costsource: c.GetCostSource(),
  145. Domain: c.GetDomain(),
  146. Version: c.GetVersion(),
  147. Currency: c.GetCurrency(),
  148. Window: win,
  149. Costs: costClones,
  150. Errors: errClones,
  151. }
  152. }
  153. func cloneMap(input map[string]string) map[string]string {
  154. if input == nil {
  155. return nil
  156. }
  157. result := map[string]string{}
  158. for key, val := range input {
  159. result[key] = val
  160. }
  161. return result
  162. }
  163. func (c *CustomCost) Clone() CustomCost {
  164. win := c.GetWindow().Clone()
  165. var ext ExtendedCustomCostAttributes
  166. if c.GetExtendedAttributes() != nil {
  167. ext = c.GetExtendedAttributes().Clone()
  168. }
  169. return CustomCost{
  170. Metadata: cloneMap(c.GetMetadata()),
  171. Zone: c.GetCostIncurredZone(),
  172. BilledCost: c.GetBilledCost(),
  173. AccountName: c.GetAccountName(),
  174. ChargeCategory: c.GetChargeCategory(),
  175. Description: c.GetDescription(),
  176. ListCost: c.GetListCost(),
  177. ListUnitPrice: c.GetListUnitPrice(),
  178. ResourceName: c.GetResourceName(),
  179. ResourceType: c.GetResourceType(),
  180. Id: c.GetID(),
  181. ProviderId: c.GetProviderID(),
  182. Window: &win,
  183. Labels: cloneMap(c.GetLabels()),
  184. UsageQty: c.GetUsageQuantity(),
  185. UsageUnit: c.GetUsageUnit(),
  186. ExtendedAttributes: &ext,
  187. }
  188. }
  189. func (e *ExtendedCustomCostAttributes) Clone() ExtendedCustomCostAttributes {
  190. win := e.BillingPeriod.Clone()
  191. return ExtendedCustomCostAttributes{
  192. BillingPeriod: &win,
  193. AccountID: e.GetAccountID(),
  194. ChargeFrequency: e.GetChargeFrequency(),
  195. Subcategory: e.GetSubcategory(),
  196. CommitmentDiscountCategory: e.GetCommitmentDiscountCategory(),
  197. CommitmentDiscountID: e.GetCommitmentDiscountID(),
  198. CommitmentDiscountName: e.GetCommitmentDiscountName(),
  199. CommitmentDiscountType: e.GetCommitmentDiscountType(),
  200. EffectiveCost: e.GetEffectiveCost(),
  201. InvoiceIssuer: e.GetInvoiceIssuer(),
  202. Provider: e.GetProvider(),
  203. Publisher: e.GetPublisher(),
  204. ServiceCategory: e.GetServiceCategory(),
  205. ServiceName: e.GetServiceName(),
  206. SkuID: e.GetSKUID(),
  207. SkuPriceID: e.GetSKUPriceID(),
  208. SubAccountID: e.GetSubAccountID(),
  209. SubAccountName: e.GetSubAccountName(),
  210. PricingQuantity: e.GetPricingQuantity(),
  211. PricingUnit: e.GetPricingUnit(),
  212. PricingCategory: e.GetPricingCategory(),
  213. }
  214. }
  215. func (e *ExtendedCustomCostAttributes) GetBillingPeriod() *opencost.Window {
  216. return e.BillingPeriod
  217. }
  218. func (e *ExtendedCustomCostAttributes) GetAccountID() string {
  219. return e.AccountID
  220. }
  221. func (e *ExtendedCustomCostAttributes) GetChargeFrequency() string {
  222. return e.ChargeFrequency
  223. }
  224. func (e *ExtendedCustomCostAttributes) GetSubcategory() string {
  225. return e.Subcategory
  226. }
  227. func (e *ExtendedCustomCostAttributes) GetCommitmentDiscountCategory() string {
  228. return e.CommitmentDiscountCategory
  229. }
  230. func (e *ExtendedCustomCostAttributes) GetCommitmentDiscountID() string {
  231. return e.CommitmentDiscountID
  232. }
  233. func (e *ExtendedCustomCostAttributes) GetCommitmentDiscountName() string {
  234. return e.CommitmentDiscountName
  235. }
  236. func (e *ExtendedCustomCostAttributes) GetCommitmentDiscountType() string {
  237. return e.CommitmentDiscountType
  238. }
  239. func (e *ExtendedCustomCostAttributes) GetEffectiveCost() float32 {
  240. return e.EffectiveCost
  241. }
  242. func (e *ExtendedCustomCostAttributes) GetInvoiceIssuer() string {
  243. return e.InvoiceIssuer
  244. }
  245. func (e *ExtendedCustomCostAttributes) GetProvider() string {
  246. return e.Provider
  247. }
  248. func (e *ExtendedCustomCostAttributes) GetPublisher() string {
  249. return e.Publisher
  250. }
  251. func (e *ExtendedCustomCostAttributes) GetServiceCategory() string {
  252. return e.ServiceCategory
  253. }
  254. func (e *ExtendedCustomCostAttributes) GetServiceName() string {
  255. return e.ServiceName
  256. }
  257. func (e *ExtendedCustomCostAttributes) GetSKUID() string {
  258. return e.SkuID
  259. }
  260. func (e *ExtendedCustomCostAttributes) GetSKUPriceID() string {
  261. return e.SkuPriceID
  262. }
  263. func (e *ExtendedCustomCostAttributes) GetSubAccountID() string {
  264. return e.SubAccountID
  265. }
  266. func (e *ExtendedCustomCostAttributes) GetSubAccountName() string {
  267. return e.SubAccountName
  268. }
  269. func (e *ExtendedCustomCostAttributes) GetPricingQuantity() float32 {
  270. return e.PricingQuantity
  271. }
  272. func (e *ExtendedCustomCostAttributes) GetPricingUnit() string {
  273. return e.PricingUnit
  274. }
  275. func (e *ExtendedCustomCostAttributes) GetPricingCategory() string {
  276. return e.PricingCategory
  277. }
  278. func (d *CustomCost) GetMetadata() map[string]string {
  279. return d.Metadata
  280. }
  281. func (d *CustomCost) GetCostIncurredZone() string {
  282. return d.Zone
  283. }
  284. func (d *CustomCost) GetBilledCost() float32 {
  285. return d.BilledCost
  286. }
  287. func (d *CustomCost) GetAccountName() string {
  288. return d.AccountName
  289. }
  290. func (d *CustomCost) GetChargeCategory() string {
  291. return d.ChargeCategory
  292. }
  293. func (d *CustomCost) GetDescription() string {
  294. return d.Description
  295. }
  296. func (d *CustomCost) GetListCost() float32 {
  297. return d.ListCost
  298. }
  299. func (d *CustomCost) GetListUnitPrice() float32 {
  300. return d.ListUnitPrice
  301. }
  302. func (d *CustomCost) GetResourceName() string {
  303. return d.ResourceName
  304. }
  305. func (d *CustomCost) GetID() string {
  306. return d.Id
  307. }
  308. func (d *CustomCost) GetProviderID() string {
  309. return d.ProviderId
  310. }
  311. func (d *CustomCost) GetWindow() *opencost.Window {
  312. return d.Window
  313. }
  314. func (d *CustomCost) GetLabels() map[string]string {
  315. return d.Labels
  316. }
  317. func (d *CustomCost) GetUsageQuantity() float32 {
  318. return d.UsageQty
  319. }
  320. func (d *CustomCost) GetUsageUnit() string {
  321. return d.UsageUnit
  322. }
  323. func (d *CustomCost) GetExtendedAttributes() *ExtendedCustomCostAttributes {
  324. return d.ExtendedAttributes
  325. }
  326. func (d *CustomCost) GetResourceType() string {
  327. return d.ResourceType
  328. }
  329. func (d *CustomCostResponse) GetMetadata() map[string]string {
  330. return d.Metadata
  331. }
  332. func (d *CustomCostResponse) GetCostSource() string {
  333. return d.Costsource
  334. }
  335. func (d *CustomCostResponse) GetDomain() string {
  336. return d.Domain
  337. }
  338. func (d *CustomCostResponse) GetVersion() string {
  339. return d.Version
  340. }
  341. func (d *CustomCostResponse) GetCurrency() string {
  342. return d.Currency
  343. }
  344. func (d *CustomCostResponse) GetWindow() opencost.Window {
  345. return d.Window
  346. }
  347. func (d *CustomCostResponse) GetCosts() []*CustomCost {
  348. return d.Costs
  349. }
  350. func (d *CustomCostResponse) GetErrors() []error {
  351. return d.Errors
  352. }