configurations.go 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. package config
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "github.com/opencost/opencost/core/pkg/log"
  6. "github.com/opencost/opencost/pkg/cloud"
  7. "github.com/opencost/opencost/pkg/cloud/alibaba"
  8. "github.com/opencost/opencost/pkg/cloud/aws"
  9. "github.com/opencost/opencost/pkg/cloud/azure"
  10. "github.com/opencost/opencost/pkg/cloud/gcp"
  11. "github.com/opencost/opencost/pkg/cloud/oracle"
  12. )
  13. // MultiCloudConfig struct is used to unmarshal cloud configs for each provider out of cloud-integration file
  14. // Deprecated: v1.104 use Configurations
  15. type MultiCloudConfig struct {
  16. AzureConfigs []azure.AzureStorageConfig `json:"azure"`
  17. GCPConfigs []gcp.BigQueryConfig `json:"gcp"`
  18. AWSConfigs []aws.AwsAthenaInfo `json:"aws"`
  19. AlibabaConfigs []alibaba.AlibabaInfo `json:"alibaba"`
  20. }
  21. func (mcc MultiCloudConfig) loadConfigurations(configs *Configurations) {
  22. // Load AWS configs
  23. for _, awsConfig := range mcc.AWSConfigs {
  24. kc := aws.ConvertAwsAthenaInfoToConfig(awsConfig)
  25. err := configs.Insert(kc)
  26. if err != nil {
  27. log.Errorf("MultiCloudConfig: error converting AWS config %s", err.Error())
  28. }
  29. }
  30. // Load GCP configs
  31. for _, gcpConfig := range mcc.GCPConfigs {
  32. kc := gcp.ConvertBigQueryConfigToConfig(gcpConfig)
  33. err := configs.Insert(kc)
  34. if err != nil {
  35. log.Errorf("MultiCloudConfig: error converting GCP config %s", err.Error())
  36. }
  37. }
  38. // Load Azure configs
  39. for _, azureConfig := range mcc.AzureConfigs {
  40. kc := azure.ConvertAzureStorageConfigToConfig(azureConfig)
  41. err := configs.Insert(kc)
  42. if err != nil {
  43. log.Errorf("MultiCloudConfig: error converting Azure config %s", err.Error())
  44. }
  45. }
  46. // Load Alibaba Cloud Configs
  47. for _, aliCloudConfig := range mcc.AlibabaConfigs {
  48. kc := alibaba.ConvertAlibabaInfoToConfig(aliCloudConfig)
  49. err := configs.Insert(kc)
  50. if err != nil {
  51. log.Errorf("MultiCloudConfig: error converting Alibaba config %s", err.Error())
  52. }
  53. }
  54. }
  55. // Configurations is a general use container for all configuration types
  56. type Configurations struct {
  57. AWS *AWSConfigs `json:"aws,omitempty"`
  58. GCP *GCPConfigs `json:"gcp,omitempty"`
  59. Azure *AzureConfigs `json:"azure,omitempty"`
  60. Alibaba *AlibabaConfigs `json:"alibaba,omitempty"`
  61. OCI *OCIConfigs `json:"oci,omitempty"`
  62. }
  63. // UnmarshalJSON custom json unmarshalling to maintain support for MultiCloudConfig format
  64. func (c *Configurations) UnmarshalJSON(bytes []byte) error {
  65. // This has been tested for backwards compatability, and it works in both config formats.
  66. // It also coincidentally works if you mix-and-match both the old format and the new
  67. // format.
  68. // Create inline type to gain access to default Unmarshalling
  69. type ConfUnmarshaller *Configurations
  70. var conf ConfUnmarshaller = c
  71. err := json.Unmarshal(bytes, conf)
  72. // If unmarshal is successful, return
  73. if err == nil {
  74. return nil
  75. }
  76. // Attempt to unmarshal into old config object
  77. multiConfig := &MultiCloudConfig{}
  78. err = json.Unmarshal(bytes, multiConfig)
  79. if err != nil {
  80. return err
  81. }
  82. multiConfig.loadConfigurations(c)
  83. return nil
  84. }
  85. func (c *Configurations) Equals(that *Configurations) bool {
  86. if c == nil && that == nil {
  87. return true
  88. }
  89. if c == nil || that == nil {
  90. return false
  91. }
  92. if !c.AWS.Equals(that.AWS) {
  93. return false
  94. }
  95. if !c.GCP.Equals(that.GCP) {
  96. return false
  97. }
  98. if !c.Azure.Equals(that.Azure) {
  99. return false
  100. }
  101. if !c.Alibaba.Equals(that.Alibaba) {
  102. return false
  103. }
  104. if !c.OCI.Equals(that.OCI) {
  105. return false
  106. }
  107. return true
  108. }
  109. func (c *Configurations) Insert(keyedConfig cloud.Config) error {
  110. switch keyedConfig.(type) {
  111. case *aws.AthenaConfiguration:
  112. if c.AWS == nil {
  113. c.AWS = &AWSConfigs{}
  114. }
  115. c.AWS.Athena = append(c.AWS.Athena, keyedConfig.(*aws.AthenaConfiguration))
  116. case *aws.S3Configuration:
  117. if c.AWS == nil {
  118. c.AWS = &AWSConfigs{}
  119. }
  120. c.AWS.S3 = append(c.AWS.S3, keyedConfig.(*aws.S3Configuration))
  121. case *gcp.BigQueryConfiguration:
  122. if c.GCP == nil {
  123. c.GCP = &GCPConfigs{}
  124. }
  125. c.GCP.BigQuery = append(c.GCP.BigQuery, keyedConfig.(*gcp.BigQueryConfiguration))
  126. case *azure.StorageConfiguration:
  127. if c.Azure == nil {
  128. c.Azure = &AzureConfigs{}
  129. }
  130. c.Azure.Storage = append(c.Azure.Storage, keyedConfig.(*azure.StorageConfiguration))
  131. case *alibaba.BOAConfiguration:
  132. if c.Alibaba == nil {
  133. c.Alibaba = &AlibabaConfigs{}
  134. }
  135. c.Alibaba.BOA = append(c.Alibaba.BOA, keyedConfig.(*alibaba.BOAConfiguration))
  136. case *oracle.UsageApiConfiguration:
  137. if c.OCI == nil {
  138. c.OCI = &OCIConfigs{}
  139. }
  140. c.OCI.UsageAPI = append(c.OCI.UsageAPI, keyedConfig.(*oracle.UsageApiConfiguration))
  141. default:
  142. return fmt.Errorf("Configurations: Insert: failed to insert config of type: %T", keyedConfig)
  143. }
  144. return nil
  145. }
  146. func (c *Configurations) ToSlice() []cloud.KeyedConfig {
  147. var keyedConfigs []cloud.KeyedConfig
  148. if c.AWS != nil {
  149. for _, athenaConfig := range c.AWS.Athena {
  150. keyedConfigs = append(keyedConfigs, athenaConfig)
  151. }
  152. for _, s3Config := range c.AWS.S3 {
  153. keyedConfigs = append(keyedConfigs, s3Config)
  154. }
  155. }
  156. if c.GCP != nil {
  157. for _, bigQueryConfig := range c.GCP.BigQuery {
  158. keyedConfigs = append(keyedConfigs, bigQueryConfig)
  159. }
  160. }
  161. if c.Azure != nil {
  162. for _, azureStorageConfig := range c.Azure.Storage {
  163. keyedConfigs = append(keyedConfigs, azureStorageConfig)
  164. }
  165. }
  166. if c.Alibaba != nil {
  167. for _, boaConfig := range c.Alibaba.BOA {
  168. keyedConfigs = append(keyedConfigs, boaConfig)
  169. }
  170. }
  171. if c.OCI != nil {
  172. for _, usageConfig := range c.OCI.UsageAPI {
  173. keyedConfigs = append(keyedConfigs, usageConfig)
  174. }
  175. }
  176. return keyedConfigs
  177. }
  178. type AWSConfigs struct {
  179. Athena []*aws.AthenaConfiguration `json:"athena,omitempty"`
  180. S3 []*aws.S3Configuration `json:"s3,omitempty"`
  181. }
  182. func (ac *AWSConfigs) Equals(that *AWSConfigs) bool {
  183. if ac == nil && that == nil {
  184. return true
  185. }
  186. if ac == nil || that == nil {
  187. return false
  188. }
  189. // Check Athena
  190. if len(ac.Athena) != len(that.Athena) {
  191. return false
  192. }
  193. for i, thisAthena := range ac.Athena {
  194. thatAthena := that.Athena[i]
  195. if !thisAthena.Equals(thatAthena) {
  196. return false
  197. }
  198. }
  199. // Check S3
  200. if len(ac.S3) != len(that.S3) {
  201. return false
  202. }
  203. for i, thisS3 := range ac.S3 {
  204. thatS3 := that.S3[i]
  205. if !thisS3.Equals(thatS3) {
  206. return false
  207. }
  208. }
  209. return true
  210. }
  211. type GCPConfigs struct {
  212. BigQuery []*gcp.BigQueryConfiguration `json:"bigQuery,omitempty"`
  213. }
  214. func (gc *GCPConfigs) Equals(that *GCPConfigs) bool {
  215. if gc == nil && that == nil {
  216. return true
  217. }
  218. if gc == nil || that == nil {
  219. return false
  220. }
  221. // Check BigQuery
  222. if len(gc.BigQuery) != len(that.BigQuery) {
  223. return false
  224. }
  225. for i, thisBigQuery := range gc.BigQuery {
  226. thatBigQuery := that.BigQuery[i]
  227. if !thisBigQuery.Equals(thatBigQuery) {
  228. return false
  229. }
  230. }
  231. return true
  232. }
  233. type AzureConfigs struct {
  234. Storage []*azure.StorageConfiguration `json:"storage,omitempty"`
  235. }
  236. func (ac *AzureConfigs) Equals(that *AzureConfigs) bool {
  237. if ac == nil && that == nil {
  238. return true
  239. }
  240. if ac == nil || that == nil {
  241. return false
  242. }
  243. // Check Storage
  244. if len(ac.Storage) != len(that.Storage) {
  245. return false
  246. }
  247. for i, thisStorage := range ac.Storage {
  248. thatStorage := that.Storage[i]
  249. if !thisStorage.Equals(thatStorage) {
  250. return false
  251. }
  252. }
  253. return true
  254. }
  255. type AlibabaConfigs struct {
  256. BOA []*alibaba.BOAConfiguration `json:"boa,omitempty"`
  257. }
  258. func (ac *AlibabaConfigs) Equals(that *AlibabaConfigs) bool {
  259. if ac == nil && that == nil {
  260. return true
  261. }
  262. if ac == nil || that == nil {
  263. return false
  264. }
  265. // Check BOA
  266. if len(ac.BOA) != len(that.BOA) {
  267. return false
  268. }
  269. for i, thisBOA := range ac.BOA {
  270. thatBOA := that.BOA[i]
  271. if !thisBOA.Equals(thatBOA) {
  272. return false
  273. }
  274. }
  275. return true
  276. }
  277. type OCIConfigs struct {
  278. UsageAPI []*oracle.UsageApiConfiguration `json:"usageApi,omitempty"`
  279. }
  280. func (oc *OCIConfigs) Equals(that *OCIConfigs) bool {
  281. if oc == nil && that == nil {
  282. return true
  283. }
  284. if oc == nil || that == nil {
  285. return false
  286. }
  287. // Check Usage API
  288. if len(oc.UsageAPI) != len(that.UsageAPI) {
  289. return false
  290. }
  291. for i, thisUsageAPI := range oc.UsageAPI {
  292. thatUsageAPI := that.UsageAPI[i]
  293. if !thisUsageAPI.Equals(thatUsageAPI) {
  294. return false
  295. }
  296. }
  297. return true
  298. }