controller_test.go 36 KB

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