configurations.go 6.9 KB

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