controller_test.go 36 KB

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