athenaconfiguration_test.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671
  1. package aws
  2. import (
  3. "fmt"
  4. "testing"
  5. "github.com/opencost/opencost/core/pkg/log"
  6. "github.com/opencost/opencost/core/pkg/util/json"
  7. "github.com/opencost/opencost/pkg/cloud"
  8. )
  9. func TestAthenaConfiguration_Validate(t *testing.T) {
  10. testCases := map[string]struct {
  11. config AthenaConfiguration
  12. expected error
  13. }{
  14. "valid config access key": {
  15. config: AthenaConfiguration{
  16. Bucket: "bucket",
  17. Region: "region",
  18. Database: "database",
  19. Catalog: "catalog",
  20. Table: "table",
  21. Workgroup: "workgroup",
  22. Account: "account",
  23. Authorizer: &AccessKey{
  24. ID: "id",
  25. Secret: "secret",
  26. },
  27. },
  28. expected: nil,
  29. },
  30. "valid config service account": {
  31. config: AthenaConfiguration{
  32. Bucket: "bucket",
  33. Region: "region",
  34. Database: "database",
  35. Catalog: "catalog",
  36. Table: "table",
  37. Workgroup: "workgroup",
  38. Account: "account",
  39. Authorizer: &ServiceAccount{},
  40. },
  41. expected: nil,
  42. },
  43. "valid missing catalog": {
  44. config: AthenaConfiguration{
  45. Bucket: "bucket",
  46. Region: "region",
  47. Database: "database",
  48. Table: "table",
  49. Workgroup: "workgroup",
  50. Account: "account",
  51. Authorizer: &ServiceAccount{},
  52. },
  53. expected: nil,
  54. },
  55. "access key invalid": {
  56. config: AthenaConfiguration{
  57. Bucket: "bucket",
  58. Region: "region",
  59. Database: "database",
  60. Catalog: "catalog",
  61. Table: "table",
  62. Workgroup: "workgroup",
  63. Account: "account",
  64. Authorizer: &AccessKey{
  65. ID: "id",
  66. },
  67. },
  68. expected: fmt.Errorf("AthenaConfiguration: AccessKey: missing Secret"),
  69. },
  70. "missing Authorizer": {
  71. config: AthenaConfiguration{
  72. Bucket: "bucket",
  73. Region: "region",
  74. Database: "database",
  75. Catalog: "catalog",
  76. Table: "table",
  77. Workgroup: "workgroup",
  78. Account: "account",
  79. Authorizer: nil,
  80. },
  81. expected: fmt.Errorf("AthenaConfiguration: missing Authorizer"),
  82. },
  83. "missing bucket": {
  84. config: AthenaConfiguration{
  85. Bucket: "",
  86. Region: "region",
  87. Database: "database",
  88. Catalog: "catalog",
  89. Table: "table",
  90. Workgroup: "workgroup",
  91. Account: "account",
  92. Authorizer: &ServiceAccount{},
  93. },
  94. expected: fmt.Errorf("AthenaConfiguration: missing bucket"),
  95. },
  96. "missing region": {
  97. config: AthenaConfiguration{
  98. Bucket: "bucket",
  99. Region: "",
  100. Database: "database",
  101. Catalog: "catalog",
  102. Table: "table",
  103. Workgroup: "workgroup",
  104. Account: "account",
  105. Authorizer: &ServiceAccount{},
  106. },
  107. expected: fmt.Errorf("AthenaConfiguration: missing region"),
  108. },
  109. "missing database": {
  110. config: AthenaConfiguration{
  111. Bucket: "bucket",
  112. Region: "region",
  113. Database: "",
  114. Catalog: "catalog",
  115. Table: "table",
  116. Workgroup: "workgroup",
  117. Account: "account",
  118. Authorizer: &ServiceAccount{},
  119. },
  120. expected: fmt.Errorf("AthenaConfiguration: missing database"),
  121. },
  122. "missing table": {
  123. config: AthenaConfiguration{
  124. Bucket: "bucket",
  125. Region: "region",
  126. Database: "database",
  127. Table: "",
  128. Catalog: "catalog",
  129. Workgroup: "workgroup",
  130. Account: "account",
  131. Authorizer: &ServiceAccount{},
  132. },
  133. expected: fmt.Errorf("AthenaConfiguration: missing table"),
  134. },
  135. "missing workgroup": {
  136. config: AthenaConfiguration{
  137. Bucket: "bucket",
  138. Region: "region",
  139. Database: "database",
  140. Catalog: "catalog",
  141. Table: "table",
  142. Workgroup: "",
  143. Account: "account",
  144. Authorizer: &ServiceAccount{},
  145. },
  146. expected: nil,
  147. },
  148. "missing account": {
  149. config: AthenaConfiguration{
  150. Bucket: "bucket",
  151. Region: "region",
  152. Database: "database",
  153. Catalog: "catalog",
  154. Table: "table",
  155. Workgroup: "workgroup",
  156. Account: "",
  157. Authorizer: &ServiceAccount{},
  158. },
  159. expected: fmt.Errorf("AthenaConfiguration: missing account"),
  160. },
  161. }
  162. for name, testCase := range testCases {
  163. t.Run(name, func(t *testing.T) {
  164. actual := testCase.config.Validate()
  165. actualString := "nil"
  166. if actual != nil {
  167. actualString = actual.Error()
  168. }
  169. expectedString := "nil"
  170. if testCase.expected != nil {
  171. expectedString = testCase.expected.Error()
  172. }
  173. if actualString != expectedString {
  174. t.Errorf("errors do not match: Actual: '%s', Expected: '%s", actualString, expectedString)
  175. }
  176. })
  177. }
  178. }
  179. func TestAthenaConfiguration_Equals(t *testing.T) {
  180. testCases := map[string]struct {
  181. left AthenaConfiguration
  182. right cloud.Config
  183. expected bool
  184. }{
  185. "matching config": {
  186. left: AthenaConfiguration{
  187. Bucket: "bucket",
  188. Region: "region",
  189. Database: "database",
  190. Catalog: "catalog",
  191. Table: "table",
  192. Workgroup: "workgroup",
  193. Account: "account",
  194. Authorizer: &AccessKey{
  195. ID: "id",
  196. Secret: "secret",
  197. },
  198. },
  199. right: &AthenaConfiguration{
  200. Bucket: "bucket",
  201. Region: "region",
  202. Database: "database",
  203. Catalog: "catalog",
  204. Table: "table",
  205. Workgroup: "workgroup",
  206. Account: "account",
  207. Authorizer: &AccessKey{
  208. ID: "id",
  209. Secret: "secret",
  210. },
  211. },
  212. expected: true,
  213. },
  214. "different Authorizer": {
  215. left: AthenaConfiguration{
  216. Bucket: "bucket",
  217. Region: "region",
  218. Database: "database",
  219. Catalog: "catalog",
  220. Table: "table",
  221. Workgroup: "workgroup",
  222. Account: "account",
  223. Authorizer: &AccessKey{
  224. ID: "id",
  225. Secret: "secret",
  226. },
  227. },
  228. right: &AthenaConfiguration{
  229. Bucket: "bucket",
  230. Region: "region",
  231. Database: "database",
  232. Catalog: "catalog",
  233. Table: "table",
  234. Workgroup: "workgroup",
  235. Account: "account",
  236. Authorizer: &ServiceAccount{},
  237. },
  238. expected: false,
  239. },
  240. "missing both Authorizer": {
  241. left: AthenaConfiguration{
  242. Bucket: "bucket",
  243. Region: "region",
  244. Database: "database",
  245. Catalog: "catalog",
  246. Table: "table",
  247. Workgroup: "workgroup",
  248. Account: "account",
  249. Authorizer: nil,
  250. },
  251. right: &AthenaConfiguration{
  252. Bucket: "bucket",
  253. Region: "region",
  254. Database: "database",
  255. Catalog: "catalog",
  256. Table: "table",
  257. Workgroup: "workgroup",
  258. Account: "account",
  259. Authorizer: nil,
  260. },
  261. expected: true,
  262. },
  263. "missing left Authorizer": {
  264. left: AthenaConfiguration{
  265. Bucket: "bucket",
  266. Region: "region",
  267. Database: "database",
  268. Catalog: "catalog",
  269. Table: "table",
  270. Workgroup: "workgroup",
  271. Account: "account",
  272. Authorizer: nil,
  273. },
  274. right: &AthenaConfiguration{
  275. Bucket: "bucket",
  276. Region: "region",
  277. Database: "database",
  278. Catalog: "catalog",
  279. Table: "table",
  280. Workgroup: "workgroup",
  281. Account: "account",
  282. Authorizer: &ServiceAccount{},
  283. },
  284. expected: false,
  285. },
  286. "missing right Authorizer": {
  287. left: AthenaConfiguration{
  288. Bucket: "bucket",
  289. Region: "region",
  290. Database: "database",
  291. Catalog: "catalog",
  292. Table: "table",
  293. Workgroup: "workgroup",
  294. Account: "account",
  295. Authorizer: &AccessKey{
  296. ID: "id",
  297. Secret: "secret",
  298. },
  299. },
  300. right: &AthenaConfiguration{
  301. Bucket: "bucket",
  302. Region: "region",
  303. Database: "database",
  304. Catalog: "catalog",
  305. Table: "table",
  306. Workgroup: "workgroup",
  307. Account: "account",
  308. Authorizer: nil,
  309. },
  310. expected: false,
  311. },
  312. "different bucket": {
  313. left: AthenaConfiguration{
  314. Bucket: "bucket",
  315. Region: "region",
  316. Database: "database",
  317. Catalog: "catalog",
  318. Table: "table",
  319. Workgroup: "workgroup",
  320. Account: "account",
  321. Authorizer: &AccessKey{
  322. ID: "id",
  323. Secret: "secret",
  324. },
  325. },
  326. right: &AthenaConfiguration{
  327. Bucket: "bucket2",
  328. Region: "region",
  329. Database: "database",
  330. Catalog: "catalog",
  331. Table: "table",
  332. Workgroup: "workgroup",
  333. Account: "account",
  334. Authorizer: &AccessKey{
  335. ID: "id",
  336. Secret: "secret",
  337. },
  338. },
  339. expected: false,
  340. },
  341. "different region": {
  342. left: AthenaConfiguration{
  343. Bucket: "bucket",
  344. Region: "region",
  345. Database: "database",
  346. Catalog: "catalog",
  347. Table: "table",
  348. Workgroup: "workgroup",
  349. Account: "account",
  350. Authorizer: &AccessKey{
  351. ID: "id",
  352. Secret: "secret",
  353. },
  354. },
  355. right: &AthenaConfiguration{
  356. Bucket: "bucket",
  357. Region: "region2",
  358. Database: "database",
  359. Catalog: "catalog",
  360. Table: "table",
  361. Workgroup: "workgroup",
  362. Account: "account",
  363. Authorizer: &AccessKey{
  364. ID: "id",
  365. Secret: "secret",
  366. },
  367. },
  368. expected: false,
  369. },
  370. "different database": {
  371. left: AthenaConfiguration{
  372. Bucket: "bucket",
  373. Region: "region",
  374. Database: "database",
  375. Catalog: "catalog",
  376. Table: "table",
  377. Workgroup: "workgroup",
  378. Account: "account",
  379. Authorizer: &AccessKey{
  380. ID: "id",
  381. Secret: "secret",
  382. },
  383. },
  384. right: &AthenaConfiguration{
  385. Bucket: "bucket",
  386. Region: "region",
  387. Database: "database2",
  388. Catalog: "catalog",
  389. Table: "table",
  390. Workgroup: "workgroup",
  391. Account: "account",
  392. Authorizer: &AccessKey{
  393. ID: "id",
  394. Secret: "secret",
  395. },
  396. },
  397. expected: false,
  398. },
  399. "different table": {
  400. left: AthenaConfiguration{
  401. Bucket: "bucket",
  402. Region: "region",
  403. Database: "database",
  404. Catalog: "catalog",
  405. Table: "table",
  406. Workgroup: "workgroup",
  407. Account: "account",
  408. Authorizer: &AccessKey{
  409. ID: "id",
  410. Secret: "secret",
  411. },
  412. },
  413. right: &AthenaConfiguration{
  414. Bucket: "bucket",
  415. Region: "region",
  416. Database: "database",
  417. Catalog: "catalog",
  418. Table: "table2",
  419. Workgroup: "workgroup",
  420. Account: "account",
  421. Authorizer: &AccessKey{
  422. ID: "id",
  423. Secret: "secret",
  424. },
  425. },
  426. expected: false,
  427. },
  428. "different catalog": {
  429. left: AthenaConfiguration{
  430. Bucket: "bucket",
  431. Region: "region",
  432. Database: "database",
  433. Catalog: "catalog",
  434. Table: "table",
  435. Workgroup: "workgroup",
  436. Account: "account",
  437. Authorizer: &AccessKey{
  438. ID: "id",
  439. Secret: "secret",
  440. },
  441. },
  442. right: &AthenaConfiguration{
  443. Bucket: "bucket",
  444. Region: "region",
  445. Database: "database",
  446. Catalog: "catalog2",
  447. Table: "table",
  448. Workgroup: "workgroup",
  449. Account: "account",
  450. Authorizer: &AccessKey{
  451. ID: "id",
  452. Secret: "secret",
  453. },
  454. },
  455. expected: false,
  456. },
  457. "different workgroup": {
  458. left: AthenaConfiguration{
  459. Bucket: "bucket",
  460. Region: "region",
  461. Database: "database",
  462. Catalog: "catalog",
  463. Table: "table",
  464. Workgroup: "workgroup",
  465. Account: "account",
  466. Authorizer: &AccessKey{
  467. ID: "id",
  468. Secret: "secret",
  469. },
  470. },
  471. right: &AthenaConfiguration{
  472. Bucket: "bucket",
  473. Region: "region",
  474. Database: "database",
  475. Catalog: "catalog",
  476. Table: "table",
  477. Workgroup: "workgroup2",
  478. Account: "account",
  479. Authorizer: &AccessKey{
  480. ID: "id",
  481. Secret: "secret",
  482. },
  483. },
  484. expected: false,
  485. },
  486. "different account": {
  487. left: AthenaConfiguration{
  488. Bucket: "bucket",
  489. Region: "region",
  490. Database: "database",
  491. Table: "table",
  492. Workgroup: "workgroup",
  493. Account: "account",
  494. Authorizer: &AccessKey{
  495. ID: "id",
  496. Secret: "secret",
  497. },
  498. },
  499. right: &AthenaConfiguration{
  500. Bucket: "bucket",
  501. Region: "region",
  502. Database: "database",
  503. Table: "table",
  504. Workgroup: "workgroup",
  505. Account: "account2",
  506. Authorizer: &AccessKey{
  507. ID: "id",
  508. Secret: "secret",
  509. },
  510. },
  511. expected: false,
  512. },
  513. "different config": {
  514. left: AthenaConfiguration{
  515. Bucket: "bucket",
  516. Region: "region",
  517. Database: "database",
  518. Table: "table",
  519. Workgroup: "workgroup",
  520. Account: "account",
  521. Authorizer: &AccessKey{
  522. ID: "id",
  523. Secret: "secret",
  524. },
  525. },
  526. right: &AccessKey{
  527. ID: "id",
  528. Secret: "secret",
  529. },
  530. expected: false,
  531. },
  532. }
  533. for name, testCase := range testCases {
  534. t.Run(name, func(t *testing.T) {
  535. actual := testCase.left.Equals(testCase.right)
  536. if actual != testCase.expected {
  537. t.Errorf("incorrect result: Actual: '%t', Expected: '%t", actual, testCase.expected)
  538. }
  539. })
  540. }
  541. }
  542. func TestAthenaConfiguration_JSON(t *testing.T) {
  543. testCases := map[string]struct {
  544. config AthenaConfiguration
  545. }{
  546. "Empty Config": {
  547. config: AthenaConfiguration{},
  548. },
  549. "AccessKey": {
  550. config: AthenaConfiguration{
  551. Bucket: "bucket",
  552. Region: "region",
  553. Database: "database",
  554. Catalog: "catalog",
  555. Table: "table",
  556. Workgroup: "workgroup",
  557. Account: "account",
  558. Authorizer: &AccessKey{
  559. ID: "id",
  560. Secret: "secret",
  561. },
  562. },
  563. },
  564. "ServiceAccount": {
  565. config: AthenaConfiguration{
  566. Bucket: "bucket",
  567. Region: "region",
  568. Database: "database",
  569. Catalog: "catalog",
  570. Table: "table",
  571. Workgroup: "workgroup",
  572. Account: "account",
  573. Authorizer: &ServiceAccount{},
  574. },
  575. },
  576. "AssumeRole with AccessKey": {
  577. config: AthenaConfiguration{
  578. Bucket: "bucket",
  579. Region: "region",
  580. Database: "database",
  581. Catalog: "catalog",
  582. Table: "table",
  583. Workgroup: "workgroup",
  584. Account: "account",
  585. Authorizer: &AssumeRole{
  586. Authorizer: &AccessKey{
  587. ID: "id",
  588. Secret: "secret",
  589. },
  590. RoleARN: "12345",
  591. },
  592. },
  593. },
  594. "AssumeRole with ServiceAccount": {
  595. config: AthenaConfiguration{
  596. Bucket: "bucket",
  597. Region: "region",
  598. Database: "database",
  599. Catalog: "catalog",
  600. Table: "table",
  601. Workgroup: "workgroup",
  602. Account: "account",
  603. Authorizer: &AssumeRole{
  604. Authorizer: &ServiceAccount{},
  605. RoleARN: "12345",
  606. },
  607. },
  608. },
  609. "RoleArnNil": {
  610. config: AthenaConfiguration{
  611. Bucket: "bucket",
  612. Region: "region",
  613. Database: "database",
  614. Catalog: "catalog",
  615. Table: "table",
  616. Workgroup: "workgroup",
  617. Account: "account",
  618. Authorizer: &AssumeRole{
  619. Authorizer: nil,
  620. RoleARN: "12345",
  621. },
  622. },
  623. },
  624. "AssumeRole with AssumeRole with ServiceAccount": {
  625. config: AthenaConfiguration{
  626. Bucket: "bucket",
  627. Region: "region",
  628. Database: "database",
  629. Catalog: "catalog",
  630. Table: "table",
  631. Workgroup: "workgroup",
  632. Account: "account",
  633. Authorizer: &AssumeRole{
  634. Authorizer: &AssumeRole{
  635. RoleARN: "12345",
  636. Authorizer: &ServiceAccount{},
  637. },
  638. RoleARN: "12345",
  639. },
  640. },
  641. },
  642. }
  643. for name, testCase := range testCases {
  644. t.Run(name, func(t *testing.T) {
  645. // test JSON Marshalling
  646. configJSON, err := json.Marshal(testCase.config)
  647. if err != nil {
  648. t.Errorf("failed to marshal configuration: %s", err.Error())
  649. }
  650. log.Info(string(configJSON))
  651. unmarshalledConfig := &AthenaConfiguration{}
  652. err = json.Unmarshal(configJSON, unmarshalledConfig)
  653. if err != nil {
  654. t.Errorf("failed to unmarshal configuration: %s", err.Error())
  655. }
  656. if !testCase.config.Equals(unmarshalledConfig) {
  657. t.Error("config does not equal unmarshalled config")
  658. }
  659. })
  660. }
  661. }