boaconfiguration_test.go 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. package alibaba
  2. import (
  3. "fmt"
  4. "testing"
  5. "github.com/opencost/opencost/core/pkg/log"
  6. "github.com/opencost/opencost/core/pkg/opencost"
  7. "github.com/opencost/opencost/core/pkg/util/json"
  8. "github.com/opencost/opencost/pkg/cloud"
  9. )
  10. func TestBoaConfiguration_Validate(t *testing.T) {
  11. testCases := map[string]struct {
  12. config BOAConfiguration
  13. expected error
  14. }{
  15. "valid config Azure AccessKey": {
  16. config: BOAConfiguration{
  17. Account: "Account Number",
  18. Region: "Region",
  19. Authorizer: &AccessKey{
  20. AccessKeyID: "accessKeyID",
  21. AccessKeySecret: "accessKeySecret",
  22. },
  23. },
  24. expected: nil,
  25. },
  26. "access key invalid": {
  27. config: BOAConfiguration{
  28. Account: "Account Number",
  29. Region: "Region",
  30. Authorizer: &AccessKey{
  31. AccessKeySecret: "accessKeySecret",
  32. },
  33. },
  34. expected: fmt.Errorf("AccessKey: missing Access key ID"),
  35. },
  36. "access secret invalid": {
  37. config: BOAConfiguration{
  38. Account: "Account Number",
  39. Region: "Region",
  40. Authorizer: &AccessKey{
  41. AccessKeyID: "accessKeyId",
  42. },
  43. },
  44. expected: fmt.Errorf("AccessKey: missing Access Key secret"),
  45. },
  46. "missing authorizer": {
  47. config: BOAConfiguration{
  48. Account: "Account Number",
  49. Region: "Region",
  50. Authorizer: nil,
  51. },
  52. expected: fmt.Errorf("BOAConfiguration: missing authorizer"),
  53. },
  54. "missing Account": {
  55. config: BOAConfiguration{
  56. Account: "",
  57. Region: "Region",
  58. Authorizer: &AccessKey{
  59. AccessKeyID: "accessKeyID",
  60. AccessKeySecret: "accessKeySecret",
  61. },
  62. },
  63. expected: fmt.Errorf("BOAConfiguration: missing account"),
  64. },
  65. "missing Region": {
  66. config: BOAConfiguration{
  67. Account: "Account",
  68. Authorizer: &AccessKey{
  69. AccessKeyID: "accessKeyID",
  70. AccessKeySecret: "accessKeySecret",
  71. },
  72. },
  73. expected: fmt.Errorf("BOAConfiguration: missing region"),
  74. },
  75. }
  76. for name, testCase := range testCases {
  77. t.Run(name, func(t *testing.T) {
  78. actual := testCase.config.Validate()
  79. actualString := "nil"
  80. if actual != nil {
  81. actualString = actual.Error()
  82. }
  83. expectedString := "nil"
  84. if testCase.expected != nil {
  85. expectedString = testCase.expected.Error()
  86. }
  87. if actualString != expectedString {
  88. t.Errorf("errors do not match: Actual: '%s', Expected: '%s", actualString, expectedString)
  89. }
  90. })
  91. }
  92. }
  93. func TestBOAConfiguration_Equals(t *testing.T) {
  94. testCases := map[string]struct {
  95. left BOAConfiguration
  96. right cloud.Config
  97. expected bool
  98. }{
  99. "matching config": {
  100. left: BOAConfiguration{
  101. Region: "region",
  102. Account: "account",
  103. Authorizer: &AccessKey{
  104. AccessKeyID: "id",
  105. AccessKeySecret: "secret",
  106. },
  107. },
  108. right: &BOAConfiguration{
  109. Region: "region",
  110. Account: "account",
  111. Authorizer: &AccessKey{
  112. AccessKeyID: "id",
  113. AccessKeySecret: "secret",
  114. },
  115. },
  116. expected: true,
  117. },
  118. "different Authorizer": {
  119. left: BOAConfiguration{
  120. Region: "region",
  121. Account: "account",
  122. Authorizer: &AccessKey{
  123. AccessKeyID: "id",
  124. AccessKeySecret: "secret",
  125. },
  126. },
  127. right: &BOAConfiguration{
  128. Region: "region",
  129. Account: "account",
  130. Authorizer: &AccessKey{
  131. AccessKeyID: "id2",
  132. AccessKeySecret: "secret2",
  133. },
  134. },
  135. expected: false,
  136. },
  137. "missing both Authorizer": {
  138. left: BOAConfiguration{
  139. Region: "region",
  140. Account: "account",
  141. Authorizer: nil,
  142. },
  143. right: &BOAConfiguration{
  144. Region: "region",
  145. Account: "account",
  146. Authorizer: nil,
  147. },
  148. expected: true,
  149. },
  150. "missing left Authorizer": {
  151. left: BOAConfiguration{
  152. Region: "region",
  153. Account: "account",
  154. Authorizer: nil,
  155. },
  156. right: &BOAConfiguration{
  157. Region: "region",
  158. Account: "account",
  159. Authorizer: &AccessKey{
  160. AccessKeyID: "id",
  161. AccessKeySecret: "secret",
  162. },
  163. },
  164. expected: false,
  165. },
  166. "missing right Authorizer": {
  167. left: BOAConfiguration{
  168. Region: "region",
  169. Account: "account",
  170. Authorizer: &AccessKey{
  171. AccessKeyID: "id",
  172. AccessKeySecret: "secret",
  173. },
  174. },
  175. right: &BOAConfiguration{
  176. Region: "region",
  177. Account: "account",
  178. Authorizer: nil,
  179. },
  180. expected: false,
  181. },
  182. "different region": {
  183. left: BOAConfiguration{
  184. Region: "region",
  185. Account: "account",
  186. Authorizer: &AccessKey{
  187. AccessKeyID: "id",
  188. AccessKeySecret: "secret",
  189. },
  190. },
  191. right: &BOAConfiguration{
  192. Region: "region2",
  193. Account: "account",
  194. Authorizer: &AccessKey{
  195. AccessKeyID: "id",
  196. AccessKeySecret: "secret",
  197. },
  198. },
  199. expected: false,
  200. },
  201. "different account": {
  202. left: BOAConfiguration{
  203. Region: "region",
  204. Account: "account",
  205. Authorizer: &AccessKey{
  206. AccessKeyID: "id",
  207. AccessKeySecret: "secret",
  208. },
  209. },
  210. right: &BOAConfiguration{
  211. Region: "region",
  212. Account: "account2",
  213. Authorizer: &AccessKey{
  214. AccessKeyID: "id",
  215. AccessKeySecret: "secret",
  216. },
  217. },
  218. expected: false,
  219. },
  220. "different config": {
  221. left: BOAConfiguration{
  222. Region: "region",
  223. Account: "account",
  224. Authorizer: &AccessKey{
  225. AccessKeyID: "id",
  226. AccessKeySecret: "secret",
  227. },
  228. },
  229. right: &AccessKey{
  230. AccessKeyID: "id",
  231. AccessKeySecret: "secret",
  232. },
  233. expected: false,
  234. },
  235. }
  236. for name, testCase := range testCases {
  237. t.Run(name, func(t *testing.T) {
  238. actual := testCase.left.Equals(testCase.right)
  239. if actual != testCase.expected {
  240. t.Errorf("incorrect result: Actual: '%t', Expected: '%t", actual, testCase.expected)
  241. }
  242. })
  243. }
  244. }
  245. func TestBOAConfiguration_JSON(t *testing.T) {
  246. testCases := map[string]struct {
  247. config BOAConfiguration
  248. }{
  249. "Empty Config": {
  250. config: BOAConfiguration{},
  251. },
  252. "AccessKey": {
  253. config: BOAConfiguration{
  254. Region: "region",
  255. Account: "account",
  256. Authorizer: &AccessKey{
  257. AccessKeyID: "id",
  258. AccessKeySecret: "secret",
  259. },
  260. },
  261. },
  262. }
  263. for name, testCase := range testCases {
  264. t.Run(name, func(t *testing.T) {
  265. // test JSON Marshalling
  266. configJSON, err := json.Marshal(testCase.config)
  267. if err != nil {
  268. t.Errorf("failed to marshal configuration: %s", err.Error())
  269. }
  270. log.Info(string(configJSON))
  271. unmarshalledConfig := &BOAConfiguration{}
  272. err = json.Unmarshal(configJSON, unmarshalledConfig)
  273. if err != nil {
  274. t.Errorf("failed to unmarshal configuration: %s", err.Error())
  275. }
  276. if !testCase.config.Equals(unmarshalledConfig) {
  277. t.Error("config does not equal unmarshalled config")
  278. }
  279. })
  280. }
  281. }
  282. func TestBOAConfiguration_Sanitize(t *testing.T) {
  283. cfg := BOAConfiguration{
  284. Account: "account",
  285. Region: "region",
  286. Authorizer: &AccessKey{
  287. AccessKeyID: "id",
  288. AccessKeySecret: "secret",
  289. },
  290. }
  291. sanitized := cfg.Sanitize()
  292. sanitizedCfg, ok := sanitized.(*BOAConfiguration)
  293. if !ok {
  294. t.Fatal("Sanitize did not return *BOAConfiguration")
  295. }
  296. if sanitizedCfg.Authorizer != nil {
  297. if ak, ok := sanitizedCfg.Authorizer.(*AccessKey); ok {
  298. if ak.AccessKeyID != "id" {
  299. t.Errorf("Sanitize should not change AccessKeyID: got %q, want %q", ak.AccessKeyID, "id")
  300. }
  301. if ak.AccessKeySecret != "REDACTED" {
  302. t.Errorf("Sanitize should redact AccessKeySecret: got %q, want %q", ak.AccessKeySecret, "REDACTED")
  303. }
  304. }
  305. }
  306. }
  307. func TestBOAConfiguration_Key(t *testing.T) {
  308. cfg := BOAConfiguration{
  309. Account: "acc",
  310. Region: "reg",
  311. }
  312. key := cfg.Key()
  313. if key == "" {
  314. t.Error("Key() returned empty string")
  315. }
  316. }
  317. func TestBOAConfiguration_Provider(t *testing.T) {
  318. cfg := BOAConfiguration{}
  319. provider := cfg.Provider()
  320. if provider != opencost.AlibabaProvider {
  321. t.Errorf("Provider() = %v, want %v", provider, opencost.AlibabaProvider)
  322. }
  323. }
  324. func TestBOAConfiguration_UnmarshalJSON_ExtraCases(t *testing.T) {
  325. // Already tested in TestBOAConfiguration_JSON, but let's add a negative test
  326. badJSON := []byte(`{"Region": "r", "Account": "a", "Authorizer": {"Type": "Unknown"}}`)
  327. var cfg BOAConfiguration
  328. err := cfg.UnmarshalJSON(badJSON)
  329. if err == nil {
  330. t.Error("UnmarshalJSON should fail for unknown authorizer type")
  331. }
  332. }
  333. func TestConvertAlibabaInfoToConfig(t *testing.T) {
  334. info := AlibabaInfo{
  335. AlibabaAccountID: "acc",
  336. AlibabaClusterRegion: "reg",
  337. AlibabaServiceKeyName: "id",
  338. AlibabaServiceKeySecret: "secret",
  339. }
  340. cfg := ConvertAlibabaInfoToConfig(info)
  341. boaCfg, ok := cfg.(*BOAConfiguration)
  342. if !ok {
  343. t.Fatal("ConvertAlibabaInfoToConfig did not return *BOAConfiguration")
  344. }
  345. if boaCfg.Account != info.AlibabaAccountID || boaCfg.Region != info.AlibabaClusterRegion {
  346. t.Errorf("ConvertAlibabaInfoToConfig did not copy fields correctly")
  347. }
  348. ak, ok := boaCfg.Authorizer.(*AccessKey)
  349. if !ok || ak.AccessKeyID != info.AlibabaServiceKeyName || ak.AccessKeySecret != info.AlibabaServiceKeySecret {
  350. t.Errorf("ConvertAlibabaInfoToConfig did not set AccessKey correctly")
  351. }
  352. }