controller_test.go 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551
  1. package config
  2. import (
  3. "fmt"
  4. "os"
  5. "path/filepath"
  6. "testing"
  7. cloudconfig "github.com/opencost/opencost/pkg/cloud"
  8. "github.com/opencost/opencost/pkg/cloud/aws"
  9. "github.com/opencost/opencost/pkg/cloud/gcp"
  10. )
  11. var configFile = "test.json"
  12. // Baseline valid config
  13. var validAthenaConf = &aws.AthenaConfiguration{
  14. Bucket: "bucket",
  15. Region: "region",
  16. Database: "database",
  17. Table: "table",
  18. Workgroup: "workgroup",
  19. Account: "account",
  20. Authorizer: &aws.ServiceAccount{},
  21. CURVersion: "2.0",
  22. }
  23. // Config with the same key as the baseline but is not equal to it because of the change in the non-keyed property Workgroup
  24. var validAthenaConfModifiedProperty = &aws.AthenaConfiguration{
  25. Bucket: "bucket",
  26. Region: "region",
  27. Database: "database",
  28. Table: "table",
  29. Workgroup: "workgroup1",
  30. Account: "account",
  31. Authorizer: &aws.ServiceAccount{},
  32. CURVersion: "2.0",
  33. }
  34. // Config with the same key as baseline but is invalid due to missing Authorizer
  35. var invalidAthenaConf = &aws.AthenaConfiguration{
  36. Bucket: "bucket",
  37. Region: "region",
  38. Database: "database",
  39. Table: "table",
  40. Workgroup: "workgroup",
  41. Account: "account",
  42. Authorizer: nil,
  43. CURVersion: "2.0",
  44. }
  45. // A valid config with a different key from the baseline
  46. var validBigQueryConf = &gcp.BigQueryConfiguration{
  47. ProjectID: "projectID",
  48. Dataset: "dataset",
  49. Table: "table",
  50. Authorizer: &gcp.WorkloadIdentity{},
  51. }
  52. func TestIntegrationController_pullWatchers(t *testing.T) {
  53. testCases := map[string]struct {
  54. initialStatuses []*Status
  55. configWatchers map[ConfigSource]cloudconfig.KeyedConfigWatcher
  56. expectedStatuses []*Status
  57. }{
  58. // Helm Source
  59. "Helm Source init": {
  60. initialStatuses: []*Status{},
  61. configWatchers: map[ConfigSource]cloudconfig.KeyedConfigWatcher{
  62. HelmSource: &MockKeyedConfigWatcher{
  63. Integrations: []cloudconfig.KeyedConfig{
  64. validAthenaConf,
  65. },
  66. },
  67. },
  68. expectedStatuses: []*Status{
  69. {
  70. Source: HelmSource,
  71. Key: validAthenaConf.Key(),
  72. Active: true,
  73. Valid: true,
  74. ConfigType: AthenaConfigType,
  75. Config: validAthenaConf,
  76. },
  77. },
  78. },
  79. "Helm Source No Change": {
  80. initialStatuses: []*Status{
  81. {
  82. Source: HelmSource,
  83. Key: validAthenaConf.Key(),
  84. Active: true,
  85. Valid: true,
  86. ConfigType: AthenaConfigType,
  87. Config: validAthenaConf,
  88. },
  89. },
  90. configWatchers: map[ConfigSource]cloudconfig.KeyedConfigWatcher{
  91. HelmSource: &MockKeyedConfigWatcher{
  92. Integrations: []cloudconfig.KeyedConfig{
  93. validAthenaConf,
  94. },
  95. },
  96. },
  97. expectedStatuses: []*Status{
  98. {
  99. Source: HelmSource,
  100. Key: validAthenaConf.Key(),
  101. Active: true,
  102. Valid: true,
  103. ConfigType: AthenaConfigType,
  104. Config: validAthenaConf,
  105. },
  106. },
  107. },
  108. "Helm Source Update Config": {
  109. initialStatuses: []*Status{
  110. {
  111. Source: HelmSource,
  112. Key: validAthenaConfModifiedProperty.Key(),
  113. Active: true,
  114. Valid: true,
  115. ConfigType: AthenaConfigType,
  116. Config: validAthenaConfModifiedProperty,
  117. },
  118. },
  119. configWatchers: map[ConfigSource]cloudconfig.KeyedConfigWatcher{
  120. HelmSource: &MockKeyedConfigWatcher{
  121. Integrations: []cloudconfig.KeyedConfig{
  122. validAthenaConf,
  123. },
  124. },
  125. },
  126. expectedStatuses: []*Status{
  127. {
  128. Source: HelmSource,
  129. Key: validAthenaConf.Key(),
  130. Active: true,
  131. Valid: true,
  132. ConfigType: AthenaConfigType,
  133. Config: validAthenaConf,
  134. },
  135. },
  136. },
  137. "Helm Source Update Config Invalid": {
  138. initialStatuses: []*Status{
  139. {
  140. Source: HelmSource,
  141. Key: validAthenaConf.Key(),
  142. Active: true,
  143. Valid: true,
  144. ConfigType: AthenaConfigType,
  145. Config: validAthenaConf,
  146. },
  147. },
  148. configWatchers: map[ConfigSource]cloudconfig.KeyedConfigWatcher{
  149. HelmSource: &MockKeyedConfigWatcher{
  150. Integrations: []cloudconfig.KeyedConfig{
  151. invalidAthenaConf,
  152. },
  153. },
  154. },
  155. expectedStatuses: []*Status{
  156. {
  157. Source: HelmSource,
  158. Key: invalidAthenaConf.Key(),
  159. Active: false,
  160. Valid: false,
  161. ConfigType: AthenaConfigType,
  162. Config: invalidAthenaConf,
  163. },
  164. },
  165. },
  166. "Helm Source New Config": {
  167. initialStatuses: []*Status{
  168. {
  169. Source: HelmSource,
  170. Key: validAthenaConf.Key(),
  171. Active: true,
  172. Valid: true,
  173. ConfigType: AthenaConfigType,
  174. Config: validAthenaConf,
  175. },
  176. },
  177. configWatchers: map[ConfigSource]cloudconfig.KeyedConfigWatcher{
  178. HelmSource: &MockKeyedConfigWatcher{
  179. Integrations: []cloudconfig.KeyedConfig{
  180. validBigQueryConf,
  181. },
  182. },
  183. },
  184. expectedStatuses: []*Status{
  185. {
  186. Source: HelmSource,
  187. Key: validBigQueryConf.Key(),
  188. Active: true,
  189. Valid: true,
  190. ConfigType: AthenaConfigType,
  191. Config: validBigQueryConf,
  192. },
  193. },
  194. },
  195. // Config File
  196. "Config File Source init": {
  197. initialStatuses: []*Status{},
  198. configWatchers: map[ConfigSource]cloudconfig.KeyedConfigWatcher{
  199. ConfigFileSource: &MockKeyedConfigWatcher{
  200. Integrations: []cloudconfig.KeyedConfig{
  201. validAthenaConf,
  202. },
  203. },
  204. },
  205. expectedStatuses: []*Status{
  206. {
  207. Source: ConfigFileSource,
  208. Key: validAthenaConf.Key(),
  209. Active: true,
  210. Valid: true,
  211. ConfigType: AthenaConfigType,
  212. Config: validAthenaConf,
  213. },
  214. },
  215. },
  216. "Config File No Change": {
  217. initialStatuses: []*Status{
  218. {
  219. Source: ConfigFileSource,
  220. Key: validAthenaConf.Key(),
  221. Active: true,
  222. Valid: true,
  223. ConfigType: AthenaConfigType,
  224. Config: validAthenaConf,
  225. },
  226. },
  227. configWatchers: map[ConfigSource]cloudconfig.KeyedConfigWatcher{
  228. ConfigFileSource: &MockKeyedConfigWatcher{
  229. Integrations: []cloudconfig.KeyedConfig{
  230. validAthenaConf,
  231. },
  232. },
  233. },
  234. expectedStatuses: []*Status{
  235. {
  236. Source: ConfigFileSource,
  237. Key: validAthenaConf.Key(),
  238. Active: true,
  239. Valid: true,
  240. ConfigType: AthenaConfigType,
  241. Config: validAthenaConf,
  242. },
  243. },
  244. },
  245. "Config File Update Config": {
  246. initialStatuses: []*Status{
  247. {
  248. Source: ConfigFileSource,
  249. Key: validAthenaConf.Key(),
  250. Active: true,
  251. Valid: true,
  252. ConfigType: AthenaConfigType,
  253. Config: validAthenaConf,
  254. },
  255. },
  256. configWatchers: map[ConfigSource]cloudconfig.KeyedConfigWatcher{
  257. ConfigFileSource: &MockKeyedConfigWatcher{
  258. Integrations: []cloudconfig.KeyedConfig{
  259. validAthenaConf,
  260. },
  261. },
  262. },
  263. expectedStatuses: []*Status{
  264. {
  265. Source: ConfigFileSource,
  266. Key: validAthenaConf.Key(),
  267. Active: true,
  268. Valid: true,
  269. ConfigType: AthenaConfigType,
  270. Config: validAthenaConf,
  271. },
  272. },
  273. },
  274. "Config File Update Config Invalid": {
  275. initialStatuses: []*Status{
  276. {
  277. Source: ConfigFileSource,
  278. Key: validAthenaConf.Key(),
  279. Active: true,
  280. Valid: true,
  281. ConfigType: AthenaConfigType,
  282. Config: validAthenaConf,
  283. },
  284. },
  285. configWatchers: map[ConfigSource]cloudconfig.KeyedConfigWatcher{
  286. ConfigFileSource: &MockKeyedConfigWatcher{
  287. Integrations: []cloudconfig.KeyedConfig{
  288. invalidAthenaConf,
  289. },
  290. },
  291. },
  292. expectedStatuses: []*Status{
  293. {
  294. Source: ConfigFileSource,
  295. Key: invalidAthenaConf.Key(),
  296. Active: false,
  297. Valid: false,
  298. ConfigType: AthenaConfigType,
  299. Config: invalidAthenaConf,
  300. },
  301. },
  302. },
  303. "Config File New Config": {
  304. initialStatuses: []*Status{
  305. {
  306. Source: ConfigFileSource,
  307. Key: validAthenaConf.Key(),
  308. Active: true,
  309. Valid: true,
  310. ConfigType: AthenaConfigType,
  311. Config: validAthenaConf,
  312. },
  313. },
  314. configWatchers: map[ConfigSource]cloudconfig.KeyedConfigWatcher{
  315. ConfigFileSource: &MockKeyedConfigWatcher{
  316. Integrations: []cloudconfig.KeyedConfig{
  317. validBigQueryConf,
  318. },
  319. },
  320. },
  321. expectedStatuses: []*Status{
  322. {
  323. Source: ConfigFileSource,
  324. Key: validBigQueryConf.Key(),
  325. Active: true,
  326. Valid: true,
  327. ConfigType: BigQueryConfigType,
  328. Config: validBigQueryConf,
  329. },
  330. },
  331. },
  332. // Multi Cloud
  333. "Multi Cloud Source init": {
  334. initialStatuses: []*Status{},
  335. configWatchers: map[ConfigSource]cloudconfig.KeyedConfigWatcher{
  336. MultiCloudSource: &MockKeyedConfigWatcher{
  337. Integrations: []cloudconfig.KeyedConfig{
  338. validAthenaConf,
  339. },
  340. },
  341. },
  342. expectedStatuses: []*Status{
  343. {
  344. Source: MultiCloudSource,
  345. Key: validAthenaConf.Key(),
  346. Active: true,
  347. Valid: true,
  348. ConfigType: AthenaConfigType,
  349. Config: validAthenaConf,
  350. },
  351. },
  352. },
  353. "Multi Cloud No Change": {
  354. initialStatuses: []*Status{
  355. {
  356. Source: MultiCloudSource,
  357. Key: validAthenaConf.Key(),
  358. Active: true,
  359. Valid: true,
  360. ConfigType: AthenaConfigType,
  361. Config: validAthenaConf,
  362. },
  363. },
  364. configWatchers: map[ConfigSource]cloudconfig.KeyedConfigWatcher{
  365. MultiCloudSource: &MockKeyedConfigWatcher{
  366. Integrations: []cloudconfig.KeyedConfig{
  367. validAthenaConf,
  368. },
  369. },
  370. },
  371. expectedStatuses: []*Status{
  372. {
  373. Source: MultiCloudSource,
  374. Key: validAthenaConf.Key(),
  375. Active: true,
  376. Valid: true,
  377. ConfigType: AthenaConfigType,
  378. Config: validAthenaConf,
  379. },
  380. },
  381. },
  382. "Multi Cloud Update Config": {
  383. initialStatuses: []*Status{
  384. {
  385. Source: MultiCloudSource,
  386. Key: validAthenaConf.Key(),
  387. Active: true,
  388. Valid: true,
  389. ConfigType: AthenaConfigType,
  390. Config: validAthenaConf,
  391. },
  392. },
  393. configWatchers: map[ConfigSource]cloudconfig.KeyedConfigWatcher{
  394. MultiCloudSource: &MockKeyedConfigWatcher{
  395. Integrations: []cloudconfig.KeyedConfig{
  396. validAthenaConfModifiedProperty,
  397. },
  398. },
  399. },
  400. expectedStatuses: []*Status{
  401. {
  402. Source: MultiCloudSource,
  403. Key: validAthenaConfModifiedProperty.Key(),
  404. Active: true,
  405. Valid: true,
  406. ConfigType: AthenaConfigType,
  407. Config: validAthenaConfModifiedProperty,
  408. },
  409. },
  410. },
  411. "Multi Cloud Update Config Invalid": {
  412. initialStatuses: []*Status{
  413. {
  414. Source: MultiCloudSource,
  415. Key: validAthenaConf.Key(),
  416. Active: true,
  417. Valid: true,
  418. ConfigType: AthenaConfigType,
  419. Config: validAthenaConf,
  420. },
  421. },
  422. configWatchers: map[ConfigSource]cloudconfig.KeyedConfigWatcher{
  423. MultiCloudSource: &MockKeyedConfigWatcher{
  424. Integrations: []cloudconfig.KeyedConfig{
  425. invalidAthenaConf,
  426. },
  427. },
  428. },
  429. expectedStatuses: []*Status{
  430. {
  431. Source: MultiCloudSource,
  432. Key: invalidAthenaConf.Key(),
  433. Active: false,
  434. Valid: false,
  435. ConfigType: AthenaConfigType,
  436. Config: invalidAthenaConf,
  437. },
  438. },
  439. },
  440. "Multi Cloud New Config": {
  441. initialStatuses: []*Status{
  442. {
  443. Source: MultiCloudSource,
  444. Key: validAthenaConf.Key(),
  445. Active: true,
  446. Valid: true,
  447. ConfigType: AthenaConfigType,
  448. Config: validAthenaConf,
  449. },
  450. },
  451. configWatchers: map[ConfigSource]cloudconfig.KeyedConfigWatcher{
  452. MultiCloudSource: &MockKeyedConfigWatcher{
  453. Integrations: []cloudconfig.KeyedConfig{
  454. validBigQueryConf,
  455. },
  456. },
  457. },
  458. expectedStatuses: []*Status{
  459. {
  460. Source: MultiCloudSource,
  461. Key: validBigQueryConf.Key(),
  462. Active: true,
  463. Valid: true,
  464. ConfigType: BigQueryConfigType,
  465. Config: validBigQueryConf,
  466. },
  467. },
  468. },
  469. "Multi Cloud Delete All": {
  470. initialStatuses: []*Status{
  471. {
  472. Source: MultiCloudSource,
  473. Key: validAthenaConf.Key(),
  474. Active: true,
  475. Valid: true,
  476. ConfigType: AthenaConfigType,
  477. Config: validAthenaConf,
  478. },
  479. },
  480. configWatchers: map[ConfigSource]cloudconfig.KeyedConfigWatcher{
  481. MultiCloudSource: &MockKeyedConfigWatcher{},
  482. },
  483. expectedStatuses: []*Status{},
  484. },
  485. // Watch Interaction
  486. "New Helm, Existing Config File": {
  487. initialStatuses: []*Status{
  488. {
  489. Source: ConfigFileSource,
  490. Key: validAthenaConf.Key(),
  491. Active: true,
  492. Valid: true,
  493. ConfigType: AthenaConfigType,
  494. Config: validAthenaConf,
  495. },
  496. },
  497. configWatchers: map[ConfigSource]cloudconfig.KeyedConfigWatcher{
  498. ConfigFileSource: &MockKeyedConfigWatcher{
  499. Integrations: []cloudconfig.KeyedConfig{
  500. validAthenaConf,
  501. },
  502. },
  503. HelmSource: &MockKeyedConfigWatcher{
  504. Integrations: []cloudconfig.KeyedConfig{
  505. validBigQueryConf,
  506. },
  507. },
  508. },
  509. expectedStatuses: []*Status{
  510. {
  511. Source: ConfigFileSource,
  512. Key: validAthenaConf.Key(),
  513. Active: false,
  514. Valid: true,
  515. ConfigType: AthenaConfigType,
  516. Config: validAthenaConf,
  517. },
  518. {
  519. Source: HelmSource,
  520. Key: validBigQueryConf.Key(),
  521. Active: true,
  522. Valid: true,
  523. ConfigType: BigQueryConfigType,
  524. Config: validBigQueryConf,
  525. },
  526. },
  527. },
  528. "Update Helm, Existing Config File": {
  529. initialStatuses: []*Status{
  530. {
  531. Source: HelmSource,
  532. Key: validAthenaConf.Key(),
  533. Active: false,
  534. Valid: true,
  535. ConfigType: AthenaConfigType,
  536. Config: validAthenaConf,
  537. },
  538. {
  539. Source: ConfigFileSource,
  540. Key: validBigQueryConf.Key(),
  541. Active: true,
  542. Valid: true,
  543. ConfigType: BigQueryConfigType,
  544. Config: validBigQueryConf,
  545. },
  546. },
  547. configWatchers: map[ConfigSource]cloudconfig.KeyedConfigWatcher{
  548. ConfigFileSource: &MockKeyedConfigWatcher{
  549. Integrations: []cloudconfig.KeyedConfig{
  550. validBigQueryConf,
  551. },
  552. },
  553. HelmSource: &MockKeyedConfigWatcher{
  554. Integrations: []cloudconfig.KeyedConfig{
  555. validAthenaConfModifiedProperty,
  556. },
  557. },
  558. },
  559. expectedStatuses: []*Status{
  560. {
  561. Source: HelmSource,
  562. Key: validAthenaConfModifiedProperty.Key(),
  563. Active: true,
  564. Valid: true,
  565. ConfigType: AthenaConfigType,
  566. Config: validAthenaConfModifiedProperty,
  567. },
  568. {
  569. Source: ConfigFileSource,
  570. Key: validBigQueryConf.Key(),
  571. Active: false,
  572. Valid: true,
  573. ConfigType: BigQueryConfigType,
  574. Config: validBigQueryConf,
  575. },
  576. },
  577. },
  578. "New Helm Invalid, Existing Config File": {
  579. initialStatuses: []*Status{
  580. {
  581. Source: ConfigFileSource,
  582. Key: validBigQueryConf.Key(),
  583. Active: true,
  584. Valid: true,
  585. ConfigType: BigQueryConfigType,
  586. Config: validBigQueryConf,
  587. },
  588. },
  589. configWatchers: map[ConfigSource]cloudconfig.KeyedConfigWatcher{
  590. ConfigFileSource: &MockKeyedConfigWatcher{
  591. Integrations: []cloudconfig.KeyedConfig{
  592. validBigQueryConf,
  593. },
  594. },
  595. HelmSource: &MockKeyedConfigWatcher{
  596. Integrations: []cloudconfig.KeyedConfig{
  597. invalidAthenaConf,
  598. },
  599. },
  600. },
  601. expectedStatuses: []*Status{
  602. {
  603. Source: ConfigFileSource,
  604. Key: validBigQueryConf.Key(),
  605. Active: true,
  606. Valid: true,
  607. ConfigType: BigQueryConfigType,
  608. Config: validBigQueryConf,
  609. },
  610. {
  611. Source: HelmSource,
  612. Key: invalidAthenaConf.Key(),
  613. Active: false,
  614. Valid: false,
  615. ConfigType: AthenaConfigType,
  616. Config: invalidAthenaConf,
  617. },
  618. },
  619. },
  620. "Update Helm Invalid, Existing Config File": {
  621. initialStatuses: []*Status{
  622. {
  623. Source: ConfigFileSource,
  624. Key: validBigQueryConf.Key(),
  625. Active: true,
  626. Valid: true,
  627. ConfigType: BigQueryConfigType,
  628. Config: validBigQueryConf,
  629. },
  630. {
  631. Source: HelmSource,
  632. Key: validAthenaConf.Key(),
  633. Active: false,
  634. Valid: true,
  635. ConfigType: AthenaConfigType,
  636. Config: validAthenaConf,
  637. },
  638. },
  639. configWatchers: map[ConfigSource]cloudconfig.KeyedConfigWatcher{
  640. ConfigFileSource: &MockKeyedConfigWatcher{
  641. Integrations: []cloudconfig.KeyedConfig{
  642. validBigQueryConf,
  643. },
  644. },
  645. HelmSource: &MockKeyedConfigWatcher{
  646. Integrations: []cloudconfig.KeyedConfig{
  647. invalidAthenaConf,
  648. },
  649. },
  650. },
  651. expectedStatuses: []*Status{
  652. {
  653. Source: ConfigFileSource,
  654. Key: validBigQueryConf.Key(),
  655. Active: true,
  656. Valid: true,
  657. ConfigType: BigQueryConfigType,
  658. Config: validBigQueryConf,
  659. },
  660. {
  661. Source: HelmSource,
  662. Key: invalidAthenaConf.Key(),
  663. Active: false,
  664. Valid: false,
  665. ConfigType: AthenaConfigType,
  666. Config: invalidAthenaConf,
  667. },
  668. },
  669. },
  670. "New Config File, Existing Helm": {
  671. initialStatuses: []*Status{
  672. {
  673. Source: HelmSource,
  674. Key: validAthenaConf.Key(),
  675. Active: true,
  676. Valid: true,
  677. ConfigType: AthenaConfigType,
  678. Config: validAthenaConf,
  679. },
  680. },
  681. configWatchers: map[ConfigSource]cloudconfig.KeyedConfigWatcher{
  682. HelmSource: &MockKeyedConfigWatcher{
  683. Integrations: []cloudconfig.KeyedConfig{
  684. validAthenaConf,
  685. },
  686. },
  687. ConfigFileSource: &MockKeyedConfigWatcher{
  688. Integrations: []cloudconfig.KeyedConfig{
  689. validBigQueryConf,
  690. },
  691. },
  692. },
  693. expectedStatuses: []*Status{
  694. {
  695. Source: HelmSource,
  696. Key: validAthenaConf.Key(),
  697. Active: false,
  698. Valid: true,
  699. ConfigType: AthenaConfigType,
  700. Config: validAthenaConf,
  701. },
  702. {
  703. Source: ConfigFileSource,
  704. Key: validBigQueryConf.Key(),
  705. Active: true,
  706. Valid: true,
  707. ConfigType: BigQueryConfigType,
  708. Config: validBigQueryConf,
  709. },
  710. },
  711. },
  712. "Update Config File, Existing Helm": {
  713. initialStatuses: []*Status{
  714. {
  715. Source: HelmSource,
  716. Key: validBigQueryConf.Key(),
  717. Active: true,
  718. Valid: true,
  719. ConfigType: BigQueryConfigType,
  720. Config: validBigQueryConf,
  721. },
  722. },
  723. configWatchers: map[ConfigSource]cloudconfig.KeyedConfigWatcher{
  724. HelmSource: &MockKeyedConfigWatcher{
  725. Integrations: []cloudconfig.KeyedConfig{},
  726. },
  727. ConfigFileSource: &MockKeyedConfigWatcher{
  728. Integrations: []cloudconfig.KeyedConfig{
  729. validAthenaConfModifiedProperty,
  730. },
  731. },
  732. },
  733. expectedStatuses: []*Status{
  734. {
  735. Source: ConfigFileSource,
  736. Key: validAthenaConfModifiedProperty.Key(),
  737. Active: true,
  738. Valid: true,
  739. ConfigType: AthenaConfigType,
  740. Config: validAthenaConfModifiedProperty,
  741. },
  742. },
  743. },
  744. "New Config File Invalid, Existing Helm": {
  745. initialStatuses: []*Status{
  746. {
  747. Source: HelmSource,
  748. Key: validBigQueryConf.Key(),
  749. Active: true,
  750. Valid: true,
  751. ConfigType: BigQueryConfigType,
  752. Config: validBigQueryConf,
  753. },
  754. },
  755. configWatchers: map[ConfigSource]cloudconfig.KeyedConfigWatcher{
  756. HelmSource: &MockKeyedConfigWatcher{
  757. Integrations: []cloudconfig.KeyedConfig{
  758. validBigQueryConf,
  759. },
  760. },
  761. ConfigFileSource: &MockKeyedConfigWatcher{
  762. Integrations: []cloudconfig.KeyedConfig{
  763. invalidAthenaConf,
  764. },
  765. },
  766. },
  767. expectedStatuses: []*Status{
  768. {
  769. Source: HelmSource,
  770. Key: validBigQueryConf.Key(),
  771. Active: true,
  772. Valid: true,
  773. ConfigType: BigQueryConfigType,
  774. Config: validBigQueryConf,
  775. },
  776. {
  777. Source: ConfigFileSource,
  778. Key: invalidAthenaConf.Key(),
  779. Active: false,
  780. Valid: false,
  781. ConfigType: AthenaConfigType,
  782. Config: invalidAthenaConf,
  783. },
  784. },
  785. },
  786. "Update Config File Invalid, Existing Helm": {
  787. initialStatuses: []*Status{
  788. {
  789. Source: HelmSource,
  790. Key: validBigQueryConf.Key(),
  791. Active: true,
  792. Valid: true,
  793. ConfigType: BigQueryConfigType,
  794. Config: validBigQueryConf,
  795. },
  796. {
  797. Source: ConfigFileSource,
  798. Key: validAthenaConf.Key(),
  799. Active: false,
  800. Valid: true,
  801. ConfigType: AthenaConfigType,
  802. Config: validAthenaConf,
  803. },
  804. },
  805. configWatchers: map[ConfigSource]cloudconfig.KeyedConfigWatcher{
  806. HelmSource: &MockKeyedConfigWatcher{
  807. Integrations: []cloudconfig.KeyedConfig{
  808. validBigQueryConf,
  809. },
  810. },
  811. ConfigFileSource: &MockKeyedConfigWatcher{
  812. Integrations: []cloudconfig.KeyedConfig{
  813. invalidAthenaConf,
  814. },
  815. },
  816. },
  817. expectedStatuses: []*Status{
  818. {
  819. Source: HelmSource,
  820. Key: validBigQueryConf.Key(),
  821. Active: true,
  822. Valid: true,
  823. ConfigType: BigQueryConfigType,
  824. Config: validBigQueryConf,
  825. },
  826. {
  827. Source: ConfigFileSource,
  828. Key: invalidAthenaConf.Key(),
  829. Active: false,
  830. Valid: false,
  831. ConfigType: AthenaConfigType,
  832. Config: invalidAthenaConf,
  833. },
  834. },
  835. },
  836. }
  837. for name, tc := range testCases {
  838. t.Run(name, func(t *testing.T) {
  839. // Test set up and validation
  840. initialStatuses, err := buildStatuses(tc.initialStatuses)
  841. if err != nil {
  842. t.Errorf("initial statuses: %s", err.Error())
  843. }
  844. expectedStatuses, err := buildStatuses(tc.expectedStatuses)
  845. if err != nil {
  846. t.Errorf("initial statuses: %s", err.Error())
  847. }
  848. tempDir := os.TempDir()
  849. path := filepath.Join(tempDir, configFile)
  850. defer os.Remove(path)
  851. storage := &FileControllerStorage{
  852. path: path,
  853. }
  854. // Initialize controller
  855. icd := &Controller{
  856. storage: storage,
  857. watchers: tc.configWatchers,
  858. }
  859. err = icd.storage.save(initialStatuses)
  860. if err != nil {
  861. t.Errorf("failed to save initial statuses: %s", err.Error())
  862. }
  863. // Functionality being tested
  864. icd.pullWatchers()
  865. // Test Result
  866. status, err := icd.storage.load()
  867. if err != nil {
  868. t.Errorf("failed to load status file: %s", err.Error())
  869. }
  870. err = checkStatuses(status, expectedStatuses)
  871. if err != nil {
  872. t.Errorf("statuses equality check failed: %s", err.Error())
  873. }
  874. })
  875. }
  876. }
  877. func TestIntegrationController_CreateConfig(t *testing.T) {
  878. testCases := map[string]struct {
  879. initial []*Status
  880. expected []*Status
  881. input cloudconfig.KeyedConfig
  882. expectErr bool
  883. }{
  884. "Invalid Config": {
  885. initial: nil,
  886. expected: nil,
  887. input: invalidAthenaConf,
  888. expectErr: true,
  889. },
  890. "config exists from this source": {
  891. initial: []*Status{
  892. makeStatus(validAthenaConf, true, ConfigControllerSource),
  893. },
  894. expected: []*Status{
  895. makeStatus(validAthenaConf, true, ConfigControllerSource),
  896. },
  897. input: validAthenaConf,
  898. expectErr: true,
  899. },
  900. "config exists from this source altered": {
  901. initial: []*Status{
  902. makeStatus(validAthenaConf, true, ConfigControllerSource),
  903. },
  904. expected: []*Status{
  905. makeStatus(validAthenaConf, true, ConfigControllerSource),
  906. },
  907. input: validAthenaConfModifiedProperty,
  908. expectErr: true,
  909. },
  910. "config exists from other source enabled": {
  911. initial: []*Status{
  912. makeStatus(validAthenaConf, true, MultiCloudSource),
  913. },
  914. expected: []*Status{
  915. makeStatus(validAthenaConf, false, MultiCloudSource),
  916. makeStatus(validAthenaConf, true, ConfigControllerSource),
  917. },
  918. input: validAthenaConf,
  919. expectErr: false,
  920. },
  921. "config exists from other source disabled": {
  922. initial: []*Status{
  923. makeStatus(validAthenaConf, false, MultiCloudSource),
  924. },
  925. expected: []*Status{
  926. makeStatus(validAthenaConf, false, MultiCloudSource),
  927. makeStatus(validAthenaConf, true, ConfigControllerSource),
  928. },
  929. input: validAthenaConf,
  930. expectErr: false,
  931. },
  932. "config into empty": {
  933. initial: []*Status{},
  934. expected: []*Status{
  935. makeStatus(validAthenaConf, true, ConfigControllerSource),
  936. },
  937. input: validAthenaConf,
  938. expectErr: false,
  939. },
  940. }
  941. for name, tc := range testCases {
  942. t.Run(name, func(t *testing.T) {
  943. // Test set up and validation
  944. initialStatuses, err := buildStatuses(tc.initial)
  945. if err != nil {
  946. t.Errorf("initial statuses: %s", err.Error())
  947. }
  948. expectedStatuses, err := buildStatuses(tc.expected)
  949. if err != nil {
  950. t.Errorf("initial statuses: %s", err.Error())
  951. }
  952. tempDir := os.TempDir()
  953. path := filepath.Join(tempDir, configFile)
  954. defer os.Remove(path)
  955. storage := &FileControllerStorage{
  956. path: path,
  957. }
  958. // Initialize controller
  959. icd := &Controller{
  960. storage: storage,
  961. }
  962. err = icd.storage.save(initialStatuses)
  963. if err != nil {
  964. t.Errorf("failed to save initial statuses: %s", err.Error())
  965. }
  966. // Functionality being tested
  967. err = icd.CreateConfig(tc.input)
  968. // Test Result
  969. if err != nil && !tc.expectErr {
  970. t.Errorf("unexpected error when creating config: %s", err.Error())
  971. }
  972. if err == nil && tc.expectErr {
  973. t.Errorf("no error where expect")
  974. }
  975. status, err := icd.storage.load()
  976. if err != nil {
  977. t.Errorf("failed to load status file: %s", err.Error())
  978. }
  979. err = checkStatuses(status, expectedStatuses)
  980. if err != nil {
  981. t.Errorf("statuses equality check failed: %s", err.Error())
  982. }
  983. })
  984. }
  985. }
  986. func TestIntegrationController_UpdateConfig(t *testing.T) {
  987. testCases := map[string]struct {
  988. initial []*Status
  989. expected []*Status
  990. input cloudconfig.KeyedConfig
  991. expectErr bool
  992. }{
  993. "invalid config": {
  994. initial: []*Status{
  995. makeStatus(validAthenaConf, true, ConfigControllerSource),
  996. },
  997. expected: []*Status{
  998. makeStatus(validAthenaConf, true, ConfigControllerSource),
  999. },
  1000. input: invalidAthenaConf,
  1001. expectErr: true,
  1002. },
  1003. "config is not from ConfigControllerSource": {
  1004. initial: []*Status{
  1005. makeStatus(validAthenaConf, true, MultiCloudSource),
  1006. },
  1007. expected: []*Status{
  1008. makeStatus(validAthenaConf, true, MultiCloudSource),
  1009. },
  1010. input: validAthenaConf,
  1011. expectErr: true,
  1012. },
  1013. "config does not exist": {
  1014. initial: []*Status{},
  1015. expected: []*Status{},
  1016. input: validAthenaConf,
  1017. expectErr: true,
  1018. },
  1019. "update existing config with modified properties": {
  1020. initial: []*Status{
  1021. makeStatus(validAthenaConf, true, ConfigControllerSource),
  1022. },
  1023. expected: []*Status{
  1024. makeStatus(validAthenaConfModifiedProperty, true, ConfigControllerSource),
  1025. },
  1026. input: validAthenaConfModifiedProperty,
  1027. expectErr: false,
  1028. },
  1029. "update existing config with same properties": {
  1030. initial: []*Status{
  1031. makeStatus(validAthenaConf, true, ConfigControllerSource),
  1032. },
  1033. expected: []*Status{
  1034. makeStatus(validAthenaConf, true, ConfigControllerSource),
  1035. },
  1036. input: validAthenaConf,
  1037. expectErr: false,
  1038. },
  1039. "update existing config when other source has same key": {
  1040. initial: []*Status{
  1041. makeStatus(validAthenaConf, false, MultiCloudSource),
  1042. makeStatus(validAthenaConf, true, ConfigControllerSource),
  1043. },
  1044. expected: []*Status{
  1045. makeStatus(validAthenaConf, false, MultiCloudSource),
  1046. makeStatus(validAthenaConfModifiedProperty, true, ConfigControllerSource),
  1047. },
  1048. input: validAthenaConfModifiedProperty,
  1049. expectErr: false,
  1050. },
  1051. "update existing config when multiple other configs exist": {
  1052. initial: []*Status{
  1053. makeStatus(validBigQueryConf, true, MultiCloudSource),
  1054. makeStatus(validAthenaConf, true, ConfigControllerSource),
  1055. },
  1056. expected: []*Status{
  1057. makeStatus(validBigQueryConf, true, MultiCloudSource),
  1058. makeStatus(validAthenaConfModifiedProperty, true, ConfigControllerSource),
  1059. },
  1060. input: validAthenaConfModifiedProperty,
  1061. expectErr: false,
  1062. },
  1063. }
  1064. for name, tc := range testCases {
  1065. t.Run(name, func(t *testing.T) {
  1066. // Test set up and validation
  1067. initialStatuses, err := buildStatuses(tc.initial)
  1068. if err != nil {
  1069. t.Errorf("initial statuses: %s", err.Error())
  1070. }
  1071. expectedStatuses, err := buildStatuses(tc.expected)
  1072. if err != nil {
  1073. t.Errorf("expected statuses: %s", err.Error())
  1074. }
  1075. tempDir := os.TempDir()
  1076. path := filepath.Join(tempDir, configFile)
  1077. defer os.Remove(path)
  1078. storage := &FileControllerStorage{
  1079. path: path,
  1080. }
  1081. // Initialize controller
  1082. icd := &Controller{
  1083. storage: storage,
  1084. }
  1085. err = icd.storage.save(initialStatuses)
  1086. if err != nil {
  1087. t.Errorf("failed to save initial statuses: %s", err.Error())
  1088. }
  1089. // Functionality being tested
  1090. err = icd.UpdateConfig(tc.input)
  1091. // Test Result
  1092. if err != nil && !tc.expectErr {
  1093. t.Errorf("unexpected error when updating config: %s", err.Error())
  1094. }
  1095. if err == nil && tc.expectErr {
  1096. t.Errorf("no error where expected")
  1097. }
  1098. status, err := icd.storage.load()
  1099. if err != nil {
  1100. t.Errorf("failed to load status file: %s", err.Error())
  1101. }
  1102. err = checkStatuses(status, expectedStatuses)
  1103. if err != nil {
  1104. t.Errorf("statuses equality check failed: %s", err.Error())
  1105. }
  1106. })
  1107. }
  1108. }
  1109. func TestIntegrationController_EnableConfig(t *testing.T) {
  1110. testCases := map[string]struct {
  1111. initial []*Status
  1112. expected []*Status
  1113. inputKey string
  1114. inputSource string
  1115. expectErr bool
  1116. }{
  1117. "config doesn't exist": {
  1118. initial: []*Status{},
  1119. expected: []*Status{},
  1120. inputKey: validAthenaConf.Key(),
  1121. inputSource: ConfigControllerSource.String(),
  1122. expectErr: true,
  1123. },
  1124. "config is already enabled": {
  1125. initial: []*Status{
  1126. makeStatus(validAthenaConf, true, ConfigControllerSource),
  1127. },
  1128. expected: []*Status{
  1129. makeStatus(validAthenaConf, true, ConfigControllerSource),
  1130. },
  1131. inputKey: validAthenaConf.Key(),
  1132. inputSource: ConfigControllerSource.String(),
  1133. expectErr: true,
  1134. },
  1135. "alternate source": {
  1136. initial: []*Status{
  1137. makeStatus(validAthenaConf, false, MultiCloudSource),
  1138. },
  1139. expected: []*Status{
  1140. makeStatus(validAthenaConf, true, MultiCloudSource),
  1141. },
  1142. inputKey: validAthenaConf.Key(),
  1143. inputSource: MultiCloudSource.String(),
  1144. expectErr: false,
  1145. },
  1146. "enabled disabled single config": {
  1147. initial: []*Status{
  1148. makeStatus(validAthenaConf, false, ConfigControllerSource),
  1149. },
  1150. expected: []*Status{
  1151. makeStatus(validAthenaConf, true, ConfigControllerSource),
  1152. },
  1153. inputKey: validAthenaConf.Key(),
  1154. inputSource: ConfigControllerSource.String(),
  1155. expectErr: false,
  1156. },
  1157. "enable config which is enabled by another source": {
  1158. initial: []*Status{
  1159. makeStatus(validAthenaConf, false, ConfigControllerSource),
  1160. makeStatus(validAthenaConf, true, MultiCloudSource),
  1161. },
  1162. expected: []*Status{
  1163. makeStatus(validAthenaConf, true, ConfigControllerSource),
  1164. makeStatus(validAthenaConf, false, MultiCloudSource),
  1165. },
  1166. inputKey: validAthenaConf.Key(),
  1167. inputSource: ConfigControllerSource.String(),
  1168. expectErr: false,
  1169. },
  1170. }
  1171. for name, tc := range testCases {
  1172. t.Run(name, func(t *testing.T) {
  1173. // Test set up and validation
  1174. initialStatuses, err := buildStatuses(tc.initial)
  1175. if err != nil {
  1176. t.Errorf("initial statuses: %s", err.Error())
  1177. }
  1178. expectedStatuses, err := buildStatuses(tc.expected)
  1179. if err != nil {
  1180. t.Errorf("initial statuses: %s", err.Error())
  1181. }
  1182. tempDir := os.TempDir()
  1183. path := filepath.Join(tempDir, configFile)
  1184. defer os.Remove(path)
  1185. storage := &FileControllerStorage{
  1186. path: path,
  1187. }
  1188. // Initialize controller
  1189. icd := &Controller{
  1190. storage: storage,
  1191. }
  1192. err = icd.storage.save(initialStatuses)
  1193. if err != nil {
  1194. t.Errorf("failed to save initial statuses: %s", err.Error())
  1195. }
  1196. // Functionality being tested
  1197. err = icd.EnableConfig(tc.inputKey, tc.inputSource)
  1198. // Test Result
  1199. if err != nil && !tc.expectErr {
  1200. t.Errorf("unexpected error when enabling config: %s", err.Error())
  1201. }
  1202. if err == nil && tc.expectErr {
  1203. t.Errorf("no error where expect")
  1204. }
  1205. status, err := icd.storage.load()
  1206. if err != nil {
  1207. t.Errorf("failed to load status file: %s", err.Error())
  1208. }
  1209. err = checkStatuses(status, expectedStatuses)
  1210. if err != nil {
  1211. t.Errorf("statuses equality check failed: %s", err.Error())
  1212. }
  1213. })
  1214. }
  1215. }
  1216. func TestIntegrationController_DisableConfig(t *testing.T) {
  1217. testCases := map[string]struct {
  1218. initial []*Status
  1219. expected []*Status
  1220. inputKey string
  1221. inputSource string
  1222. expectErr bool
  1223. }{
  1224. "config doesn't exist": {
  1225. initial: []*Status{},
  1226. expected: []*Status{},
  1227. inputKey: validAthenaConf.Key(),
  1228. inputSource: ConfigControllerSource.String(),
  1229. expectErr: true,
  1230. },
  1231. "config is already disabled": {
  1232. initial: []*Status{
  1233. makeStatus(validAthenaConf, false, ConfigControllerSource),
  1234. makeStatus(validAthenaConf, true, MultiCloudSource),
  1235. },
  1236. expected: []*Status{
  1237. makeStatus(validAthenaConf, false, ConfigControllerSource),
  1238. makeStatus(validAthenaConf, true, MultiCloudSource),
  1239. },
  1240. inputKey: validAthenaConf.Key(),
  1241. inputSource: ConfigControllerSource.String(),
  1242. expectErr: true,
  1243. },
  1244. "disable single config": {
  1245. initial: []*Status{
  1246. makeStatus(validAthenaConf, true, ConfigControllerSource),
  1247. },
  1248. expected: []*Status{
  1249. makeStatus(validAthenaConf, false, ConfigControllerSource),
  1250. },
  1251. inputKey: validAthenaConf.Key(),
  1252. inputSource: ConfigControllerSource.String(),
  1253. expectErr: false,
  1254. },
  1255. "alternate source": {
  1256. initial: []*Status{
  1257. makeStatus(validAthenaConf, true, MultiCloudSource),
  1258. },
  1259. expected: []*Status{
  1260. makeStatus(validAthenaConf, false, MultiCloudSource),
  1261. },
  1262. inputKey: validAthenaConf.Key(),
  1263. inputSource: MultiCloudSource.String(),
  1264. expectErr: false,
  1265. },
  1266. "disable config, matching config from separate source": {
  1267. initial: []*Status{
  1268. makeStatus(validAthenaConf, true, ConfigControllerSource),
  1269. makeStatus(validAthenaConf, false, MultiCloudSource),
  1270. },
  1271. expected: []*Status{
  1272. makeStatus(validAthenaConf, false, ConfigControllerSource),
  1273. makeStatus(validAthenaConf, false, MultiCloudSource),
  1274. },
  1275. inputKey: validAthenaConf.Key(),
  1276. inputSource: ConfigControllerSource.String(),
  1277. expectErr: false,
  1278. },
  1279. }
  1280. for name, tc := range testCases {
  1281. t.Run(name, func(t *testing.T) {
  1282. // Test set up and validation
  1283. initialStatuses, err := buildStatuses(tc.initial)
  1284. if err != nil {
  1285. t.Errorf("initial statuses: %s", err.Error())
  1286. }
  1287. expectedStatuses, err := buildStatuses(tc.expected)
  1288. if err != nil {
  1289. t.Errorf("initial statuses: %s", err.Error())
  1290. }
  1291. tempDir := os.TempDir()
  1292. path := filepath.Join(tempDir, configFile)
  1293. defer os.Remove(path)
  1294. storage := &FileControllerStorage{
  1295. path: path,
  1296. }
  1297. // Initialize controller
  1298. icd := &Controller{
  1299. storage: storage,
  1300. }
  1301. err = icd.storage.save(initialStatuses)
  1302. if err != nil {
  1303. t.Errorf("failed to save initial statuses: %s", err.Error())
  1304. }
  1305. // Functionality being tested
  1306. err = icd.DisableConfig(tc.inputKey, tc.inputSource)
  1307. // Test Result
  1308. if err != nil && !tc.expectErr {
  1309. t.Errorf("unexpected error when disabling config: %s", err.Error())
  1310. }
  1311. if err == nil && tc.expectErr {
  1312. t.Errorf("no error where expect")
  1313. }
  1314. status, err := icd.storage.load()
  1315. if err != nil {
  1316. t.Errorf("failed to load status file: %s", err.Error())
  1317. }
  1318. err = checkStatuses(status, expectedStatuses)
  1319. if err != nil {
  1320. t.Errorf("statuses equality check failed: %s", err.Error())
  1321. }
  1322. })
  1323. }
  1324. }
  1325. func TestIntegrationController_DeleteConfig(t *testing.T) {
  1326. testCases := map[string]struct {
  1327. initial []*Status
  1328. expected []*Status
  1329. inputKey string
  1330. inputSource string
  1331. expectErr bool
  1332. }{
  1333. "config doesn't exist": {
  1334. initial: []*Status{},
  1335. expected: []*Status{},
  1336. inputKey: validAthenaConf.Key(),
  1337. inputSource: ConfigControllerSource.String(),
  1338. expectErr: true,
  1339. },
  1340. "invalid source": {
  1341. initial: []*Status{},
  1342. expected: []*Status{},
  1343. inputKey: validAthenaConf.Key(),
  1344. inputSource: MultiCloudSource.String(),
  1345. expectErr: true,
  1346. },
  1347. "delete single config": {
  1348. initial: []*Status{
  1349. makeStatus(validAthenaConf, true, ConfigControllerSource),
  1350. },
  1351. expected: []*Status{},
  1352. inputKey: validAthenaConf.Key(),
  1353. inputSource: ConfigControllerSource.String(),
  1354. expectErr: false,
  1355. },
  1356. "disable config, matching config from separate source": {
  1357. initial: []*Status{
  1358. makeStatus(validAthenaConf, true, ConfigControllerSource),
  1359. makeStatus(validAthenaConf, false, MultiCloudSource),
  1360. },
  1361. expected: []*Status{
  1362. makeStatus(validAthenaConf, false, MultiCloudSource),
  1363. },
  1364. inputKey: validAthenaConf.Key(),
  1365. inputSource: ConfigControllerSource.String(),
  1366. expectErr: false,
  1367. },
  1368. }
  1369. for name, tc := range testCases {
  1370. t.Run(name, func(t *testing.T) {
  1371. // Test set up and validation
  1372. initialStatuses, err := buildStatuses(tc.initial)
  1373. if err != nil {
  1374. t.Errorf("initial statuses: %s", err.Error())
  1375. }
  1376. expectedStatuses, err := buildStatuses(tc.expected)
  1377. if err != nil {
  1378. t.Errorf("initial statuses: %s", err.Error())
  1379. }
  1380. tempDir := os.TempDir()
  1381. path := filepath.Join(tempDir, configFile)
  1382. defer os.Remove(path)
  1383. storage := &FileControllerStorage{
  1384. path: path,
  1385. }
  1386. // Initialize controller
  1387. icd := &Controller{
  1388. storage: storage,
  1389. }
  1390. err = icd.storage.save(initialStatuses)
  1391. if err != nil {
  1392. t.Errorf("failed to save initial statuses: %s", err.Error())
  1393. }
  1394. // Functionality being tested
  1395. err = icd.DeleteConfig(tc.inputKey, tc.inputSource)
  1396. // Test Result
  1397. if err != nil && !tc.expectErr {
  1398. t.Errorf("unexpected error when deleting config: %s", err.Error())
  1399. }
  1400. if err == nil && tc.expectErr {
  1401. t.Errorf("no error where expect")
  1402. }
  1403. status, err := icd.storage.load()
  1404. if err != nil {
  1405. t.Errorf("failed to load status file: %s", err.Error())
  1406. }
  1407. err = checkStatuses(status, expectedStatuses)
  1408. if err != nil {
  1409. t.Errorf("statuses equality check failed: %s", err.Error())
  1410. }
  1411. })
  1412. }
  1413. }
  1414. func makeStatus(config cloudconfig.KeyedConfig, active bool, source ConfigSource) *Status {
  1415. err := config.Validate()
  1416. valid := err == nil
  1417. configType, err := ConfigTypeFromConfig(config)
  1418. if err != nil {
  1419. panic(fmt.Errorf("config type not recognised: %w", err))
  1420. }
  1421. return &Status{
  1422. Source: source,
  1423. Key: config.Key(),
  1424. Active: active,
  1425. Valid: valid,
  1426. ConfigType: configType,
  1427. Config: config,
  1428. }
  1429. }
  1430. func buildStatuses(statusList []*Status) (Statuses, error) {
  1431. statuses := Statuses{}
  1432. for _, status := range statusList {
  1433. if _, ok := statuses.Get(status.Key, status.Source); ok {
  1434. return nil, fmt.Errorf("invalid test, duplicate status with key: %s source: %s", status.Key, status.Source.String())
  1435. }
  1436. statuses.Insert(status)
  1437. }
  1438. return statuses, nil
  1439. }
  1440. func checkStatuses(actual, expected Statuses) error {
  1441. if len(actual.List()) != len(expected.List()) {
  1442. return fmt.Errorf("integration statueses did not have the correct length actaul: %d, expected: %d", len(actual.List()), len(expected.List()))
  1443. }
  1444. for _, actualStatus := range actual.List() {
  1445. expectedStatus, ok := expected.Get(actualStatus.Key, actualStatus.Source)
  1446. if !ok {
  1447. return fmt.Errorf("expected integration statuses is missing with integration key: %s, source: %s", actualStatus.Key, actualStatus.Source.String())
  1448. }
  1449. // failure here indicates an issue with the configID
  1450. if actualStatus.Key != expectedStatus.Key {
  1451. return fmt.Errorf("integration status does not have the correct Key values actual: %s, expected: %s", actualStatus.Key, expectedStatus.Key)
  1452. }
  1453. // failure here indicates an issue with the configID
  1454. if actualStatus.Key != expectedStatus.Key {
  1455. return fmt.Errorf("integration status does not have the correct Source values actual: %s, expected: %s", actualStatus.Source, expectedStatus.Source)
  1456. }
  1457. if actualStatus.Active != expectedStatus.Active {
  1458. return fmt.Errorf("integration status does not have the correct Active values actual: %v, expected: %v", actualStatus.Active, expectedStatus.Active)
  1459. }
  1460. if actualStatus.Valid != expectedStatus.Valid {
  1461. return fmt.Errorf("integration status does not have the correct Valid values actual: %v, expected: %v", actualStatus.Valid, expectedStatus.Valid)
  1462. }
  1463. if !actualStatus.Config.Equals(expectedStatus.Config) {
  1464. return fmt.Errorf("integration status does not have the correct config values actual: %v, expected: %v", actualStatus.Config, expectedStatus.Config)
  1465. }
  1466. }
  1467. return nil
  1468. }