qontract-reconcile 0.10.1rc613__py3-none-any.whl → 0.10.1rc614__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,6 +3,7 @@ from unittest.mock import patch
3
3
 
4
4
  import pytest
5
5
  from pydantic import ValidationError
6
+ from pytest_mock import MockerFixture
6
7
 
7
8
  import reconcile.ocm_clusters as occ
8
9
  import reconcile.utils.ocm as ocmmod
@@ -17,6 +18,7 @@ from reconcile.ocm.types import (
17
18
  OSDClusterSpec,
18
19
  ROSAClusterSpec,
19
20
  )
21
+ from reconcile.test.fixtures import Fixtures
20
22
  from reconcile.utils.mr.clusters_updates import CreateClustersUpdates
21
23
  from reconcile.utils.ocm import (
22
24
  OCM,
@@ -24,9 +26,16 @@ from reconcile.utils.ocm import (
24
26
  SPEC_ATTR_SERVER_URL,
25
27
  OCMMap,
26
28
  ocm,
29
+ products,
27
30
  )
28
-
29
- from .fixtures import Fixtures
31
+ from reconcile.utils.ocm.products import (
32
+ OCM_PRODUCT_OSD,
33
+ OCM_PRODUCT_ROSA,
34
+ OCMProductOsd,
35
+ OCMProductPortfolio,
36
+ OCMProductRosa,
37
+ )
38
+ from reconcile.utils.ocm_base_client import OCMBaseClient
30
39
 
31
40
  fxt = Fixtures("clusters")
32
41
 
@@ -333,20 +342,16 @@ def ocmmap_mock(ocm_osd_cluster_spec, ocm_mock):
333
342
 
334
343
 
335
344
  @pytest.fixture
336
- def ocm_secrets_reader():
337
- with patch("reconcile.utils.ocm.ocm.SecretReader", autospec=True) as sr:
338
- yield sr
339
-
340
-
341
- @pytest.fixture
342
- def ocm_mock(ocm_secrets_reader):
343
- with patch.object(OCM, "_post") as _post:
344
- with patch.object(OCM, "_patch", autospec=True) as _patch:
345
- with patch.object(OCM, "whoami", autospec=True):
346
- with patch.object(ocm, "init_ocm_base_client"):
347
- with patch.object(OCM, "get_provision_shard", autospec=True) as gps:
348
- gps.return_value = {"id": "provision_shard_id"}
349
- yield _post, _patch
345
+ def ocm_mock(mocker: MockerFixture):
346
+ with patch.object(OCM, "whoami", autospec=True):
347
+ with patch.object(ocm, "init_ocm_base_client") as ioc:
348
+ ocm_api_mock = mocker.Mock(OCMBaseClient)
349
+ ioc.return_value = ocm_api_mock
350
+ yield ocm_api_mock.post, ocm_api_mock.patch
351
+ # todo check if we need this realy!!!
352
+ # with patch.object(OCM, "get_product_impl", autospec=True) as gpi:
353
+ # gpi.return_value = osd_product
354
+ # yield _post, _patch
350
355
 
351
356
 
352
357
  @pytest.fixture
@@ -362,6 +367,53 @@ def get_json_mock():
362
367
  yield get_json
363
368
 
364
369
 
370
+ @pytest.fixture
371
+ def osd_product() -> typing.Generator[OCMProductOsd, None, None]:
372
+ with patch.object(products, "get_provisioning_shard_id") as g:
373
+ g.return_value = "provision_shard_id"
374
+ yield OCMProductOsd()
375
+
376
+
377
+ @pytest.fixture
378
+ def rosa_product() -> typing.Generator[OCMProductRosa, None, None]:
379
+ with patch.object(products, "get_provisioning_shard_id") as g:
380
+ g.return_value = "provision_shard_id"
381
+ yield OCMProductRosa()
382
+
383
+
384
+ @pytest.fixture
385
+ def product_portfolio(
386
+ osd_product: OCMProductOsd, rosa_product: OCMProductRosa
387
+ ) -> OCMProductPortfolio:
388
+ return OCMProductPortfolio(
389
+ products={
390
+ OCM_PRODUCT_OSD: osd_product,
391
+ OCM_PRODUCT_ROSA: rosa_product,
392
+ }
393
+ )
394
+
395
+
396
+ @pytest.fixture
397
+ def integration(
398
+ product_portfolio: OCMProductPortfolio,
399
+ ) -> typing.Generator[occ.OcmClusters, None, None]:
400
+ integration = occ.OcmClusters(
401
+ params=occ.OcmClustersParams(
402
+ job_controller_cluster="cluster",
403
+ job_controller_namespace="namespace",
404
+ rosa_job_image="image",
405
+ rosa_job_service_account="service_account",
406
+ rosa_role="role",
407
+ gitlab_project_id=None,
408
+ thread_pool_size=1,
409
+ )
410
+ )
411
+ with patch.object(
412
+ integration, "assemble_product_portfolio", return_value=product_portfolio
413
+ ):
414
+ yield integration
415
+
416
+
365
417
  def test_ocm_spec_population_rosa(rosa_cluster_fxt):
366
418
  n = OCMSpec(**rosa_cluster_fxt)
367
419
  assert isinstance(n.spec, ROSAClusterSpec)
@@ -386,49 +438,49 @@ def test_ocm_spec_population_osd_with_extra(osd_cluster_fxt):
386
438
 
387
439
 
388
440
  def test_get_ocm_cluster_update_spec_no_changes(
389
- ocm_mock, ocm_osd_cluster_spec: OCMSpec
441
+ osd_product: OCMProductOsd, ocm_osd_cluster_spec: OCMSpec
390
442
  ):
391
443
  current_spec = ocm_osd_cluster_spec
392
444
  desired_spec = ocm_osd_cluster_spec
393
445
  upd, err = occ.get_cluster_ocm_update_spec(
394
- ocm_mock, "cluster1", current_spec, desired_spec
446
+ osd_product, "cluster1", current_spec, desired_spec
395
447
  )
396
448
  assert (upd, err) == ({}, False)
397
449
 
398
450
 
399
451
  def test_get_ocm_cluster_update_spec_network_banned(
400
- ocm_mock, ocm_osd_cluster_spec: OCMSpec
452
+ osd_product: OCMProductOsd, ocm_osd_cluster_spec: OCMSpec
401
453
  ):
402
454
  current_spec = ocm_osd_cluster_spec
403
455
  desired_spec = current_spec.copy(deep=True)
404
456
  desired_spec.network.vpc = "0.0.0.0/0"
405
457
  _, err = occ.get_cluster_ocm_update_spec(
406
- ocm_mock, "cluster1", current_spec, desired_spec
458
+ osd_product, "cluster1", current_spec, desired_spec
407
459
  )
408
460
  assert err is True
409
461
 
410
462
 
411
463
  @typing.no_type_check
412
464
  def test_get_ocm_cluster_update_spec_allowed_change(
413
- ocm_mock, ocm_osd_cluster_spec: OCMSpec
465
+ osd_product: OCMProductOsd, ocm_osd_cluster_spec: OCMSpec
414
466
  ):
415
467
  current_spec = ocm_osd_cluster_spec
416
468
  desired_spec = current_spec.copy(deep=True)
417
469
  desired_spec.spec.storage = 2000
418
470
  upd, err = occ.get_cluster_ocm_update_spec(
419
- ocm_mock, "cluster1", current_spec, desired_spec
471
+ osd_product, "cluster1", current_spec, desired_spec
420
472
  )
421
473
  assert (upd, err) == ({ocmmod.SPEC_ATTR_STORAGE: 2000}, False)
422
474
 
423
475
 
424
476
  def test_get_ocm_cluster_update_spec_not_allowed_change(
425
- ocm_mock, ocm_osd_cluster_spec: OCMSpec
477
+ osd_product: OCMProductOsd, ocm_osd_cluster_spec: OCMSpec
426
478
  ):
427
479
  current_spec = ocm_osd_cluster_spec
428
480
  desired_spec = current_spec.copy(deep=True)
429
481
  desired_spec.spec.multi_az = not desired_spec.spec.multi_az
430
482
  upd, err = occ.get_cluster_ocm_update_spec(
431
- ocm_mock, "cluster1", current_spec, desired_spec
483
+ osd_product, "cluster1", current_spec, desired_spec
432
484
  )
433
485
  assert (upd, err) == (
434
486
  {ocmmod.SPEC_ATTR_MULTI_AZ: desired_spec.spec.multi_az},
@@ -437,7 +489,7 @@ def test_get_ocm_cluster_update_spec_not_allowed_change(
437
489
 
438
490
 
439
491
  def test_get_ocm_cluster_update_spec_disable_uwm(
440
- ocm_mock, ocm_osd_cluster_spec: OCMSpec
492
+ osd_product: OCMProductOsd, ocm_osd_cluster_spec: OCMSpec
441
493
  ):
442
494
  current_spec = ocm_osd_cluster_spec
443
495
  desired_spec = current_spec.copy(deep=True)
@@ -445,7 +497,7 @@ def test_get_ocm_cluster_update_spec_disable_uwm(
445
497
  not desired_spec.spec.disable_user_workload_monitoring
446
498
  )
447
499
  upd, err = occ.get_cluster_ocm_update_spec(
448
- ocm_mock, "cluster1", current_spec, desired_spec
500
+ osd_product, "cluster1", current_spec, desired_spec
449
501
  )
450
502
  assert (upd, err) == (
451
503
  {
@@ -455,9 +507,15 @@ def test_get_ocm_cluster_update_spec_disable_uwm(
455
507
  )
456
508
 
457
509
 
458
- def test_noop_dry_run(queries_mock, ocmmap_mock, ocm_mock, cluster_updates_mr_mock):
510
+ def test_noop_dry_run(
511
+ integration: occ.OcmClusters,
512
+ queries_mock,
513
+ ocmmap_mock,
514
+ ocm_mock,
515
+ cluster_updates_mr_mock,
516
+ ) -> None:
459
517
  with pytest.raises(SystemExit):
460
- occ.run(False)
518
+ integration.run(False)
461
519
  # If get has not been called means no action has been performed
462
520
  _post, _patch = ocm_mock
463
521
  assert _post.call_count == 0
@@ -466,13 +524,14 @@ def test_noop_dry_run(queries_mock, ocmmap_mock, ocm_mock, cluster_updates_mr_mo
466
524
 
467
525
 
468
526
  def test_changed_id(
527
+ integration: occ.OcmClusters,
469
528
  get_json_mock,
470
529
  queries_mock,
471
530
  ocm_mock,
472
531
  ocm_osd_cluster_raw_spec,
473
532
  ocm_osd_cluster_ai_spec,
474
533
  cluster_updates_mr_mock,
475
- ):
534
+ ) -> None:
476
535
  # App Interface attributes are only considered if are null or blank
477
536
  # Won't be better to update them if have changed?
478
537
  ocm_osd_cluster_ai_spec["spec"]["id"] = ""
@@ -480,7 +539,7 @@ def test_changed_id(
480
539
  get_json_mock.return_value = {"items": [ocm_osd_cluster_raw_spec]}
481
540
 
482
541
  with pytest.raises(SystemExit):
483
- occ.run(dry_run=False)
542
+ integration.run(dry_run=False)
484
543
  _post, _patch = ocm_mock
485
544
  assert _post.call_count == 0
486
545
  assert _patch.call_count == 0
@@ -488,6 +547,7 @@ def test_changed_id(
488
547
 
489
548
 
490
549
  def test_ocm_osd_create_cluster(
550
+ integration: occ.OcmClusters,
491
551
  get_json_mock,
492
552
  queries_mock,
493
553
  ocm_mock,
@@ -499,7 +559,7 @@ def test_ocm_osd_create_cluster(
499
559
  queries_mock[1].return_value = [ocm_osd_cluster_ai_spec]
500
560
 
501
561
  with pytest.raises(SystemExit) as sys_exit:
502
- occ.run(dry_run=False)
562
+ integration.run(dry_run=False)
503
563
 
504
564
  assert sys_exit.value.code == 0
505
565
  _post, _patch = ocm_mock
@@ -513,6 +573,7 @@ def test_ocm_osd_create_cluster(
513
573
 
514
574
 
515
575
  def test_ocm_osd_create_cluster_without_machine_pools(
576
+ integration: occ.OcmClusters,
516
577
  get_json_mock,
517
578
  queries_mock,
518
579
  ocm_mock,
@@ -525,7 +586,7 @@ def test_ocm_osd_create_cluster_without_machine_pools(
525
586
  queries_mock[1].return_value = [bad_spec]
526
587
 
527
588
  with pytest.raises(SystemExit) as sys_exit:
528
- occ.run(dry_run=False)
589
+ integration.run(dry_run=False)
529
590
 
530
591
  assert sys_exit.value.code == 1
531
592
  _post, _patch = ocm_mock
@@ -535,6 +596,7 @@ def test_ocm_osd_create_cluster_without_machine_pools(
535
596
 
536
597
 
537
598
  def test_ocm_rosa_create_cluster(
599
+ integration: occ.OcmClusters,
538
600
  get_json_mock,
539
601
  queries_mock,
540
602
  ocm_mock,
@@ -545,9 +607,11 @@ def test_ocm_rosa_create_cluster(
545
607
  get_json_mock.return_value = {"items": []}
546
608
  queries_mock[1].return_value = [ocm_rosa_cluster_ai_spec]
547
609
 
548
- with patch("reconcile.utils.ocm.random.choices", return_value=["c", "n", "z", "y"]):
610
+ with patch(
611
+ "reconcile.utils.ocm.products.random.choices", return_value=["c", "n", "z", "y"]
612
+ ):
549
613
  with pytest.raises(SystemExit) as sys_exit:
550
- occ.run(dry_run=False)
614
+ integration.run(dry_run=False)
551
615
 
552
616
  assert sys_exit.value.code == 0
553
617
  _post, _patch = ocm_mock
@@ -561,6 +625,7 @@ def test_ocm_rosa_create_cluster(
561
625
 
562
626
 
563
627
  def test_ocm_rosa_create_cluster_without_machine_pools(
628
+ integration: occ.OcmClusters,
564
629
  get_json_mock,
565
630
  queries_mock,
566
631
  ocm_mock,
@@ -572,9 +637,11 @@ def test_ocm_rosa_create_cluster_without_machine_pools(
572
637
  bad_spec = ocm_rosa_cluster_ai_spec | {"machinePools": []}
573
638
  queries_mock[1].return_value = [bad_spec]
574
639
 
575
- with patch("reconcile.utils.ocm.random.choices", return_value=["c", "n", "z", "y"]):
640
+ with patch(
641
+ "reconcile.utils.ocm.products.random.choices", return_value=["c", "n", "z", "y"]
642
+ ):
576
643
  with pytest.raises(SystemExit) as sys_exit:
577
- occ.run(dry_run=False)
644
+ integration.run(dry_run=False)
578
645
 
579
646
  assert sys_exit.value.code == 1
580
647
  _post, _patch = ocm_mock
@@ -584,6 +651,7 @@ def test_ocm_rosa_create_cluster_without_machine_pools(
584
651
 
585
652
 
586
653
  def test_ocm_rosa_update_cluster(
654
+ integration: occ.OcmClusters,
587
655
  get_json_mock,
588
656
  queries_mock,
589
657
  ocm_mock,
@@ -595,7 +663,7 @@ def test_ocm_rosa_update_cluster(
595
663
  get_json_mock.return_value = {"items": [ocm_rosa_cluster_raw_spec]}
596
664
  queries_mock[1].return_value = [ocm_rosa_cluster_ai_spec]
597
665
  with pytest.raises(SystemExit):
598
- occ.run(dry_run=False)
666
+ integration.run(dry_run=False)
599
667
  _post, _patch = ocm_mock
600
668
  assert _post.call_count == 0
601
669
  assert _patch.call_count == 1
@@ -603,6 +671,7 @@ def test_ocm_rosa_update_cluster(
603
671
 
604
672
 
605
673
  def test_ocm_rosa_update_cluster_dont_update_ocm_on_oidc_drift(
674
+ integration: occ.OcmClusters,
606
675
  get_json_mock,
607
676
  queries_mock,
608
677
  ocm_mock,
@@ -614,7 +683,7 @@ def test_ocm_rosa_update_cluster_dont_update_ocm_on_oidc_drift(
614
683
  get_json_mock.return_value = {"items": [ocm_rosa_cluster_raw_spec]}
615
684
  queries_mock[1].return_value = [ocm_rosa_cluster_ai_spec]
616
685
  with pytest.raises(SystemExit):
617
- occ.run(dry_run=False)
686
+ integration.run(dry_run=False)
618
687
  _post, _patch = ocm_mock
619
688
  assert _post.call_count == 0
620
689
  assert _patch.call_count == 0
@@ -622,6 +691,7 @@ def test_ocm_rosa_update_cluster_dont_update_ocm_on_oidc_drift(
622
691
 
623
692
 
624
693
  def test_ocm_rosa_update_cluster_with_machine_pools_change(
694
+ integration: occ.OcmClusters,
625
695
  get_json_mock,
626
696
  queries_mock,
627
697
  ocm_mock,
@@ -642,7 +712,7 @@ def test_ocm_rosa_update_cluster_with_machine_pools_change(
642
712
  queries_mock[1].return_value = [new_spec]
643
713
 
644
714
  with pytest.raises(SystemExit):
645
- occ.run(dry_run=False)
715
+ integration.run(dry_run=False)
646
716
 
647
717
  _post, _patch = ocm_mock
648
718
  _post.assert_not_called()
@@ -651,6 +721,7 @@ def test_ocm_rosa_update_cluster_with_machine_pools_change(
651
721
 
652
722
 
653
723
  def test_ocm_osd_update_cluster(
724
+ integration: occ.OcmClusters,
654
725
  get_json_mock,
655
726
  queries_mock,
656
727
  ocm_mock,
@@ -662,7 +733,7 @@ def test_ocm_osd_update_cluster(
662
733
  get_json_mock.return_value = {"items": [ocm_osd_cluster_raw_spec]}
663
734
  queries_mock[1].return_value = [ocm_osd_cluster_ai_spec]
664
735
  with pytest.raises(SystemExit):
665
- occ.run(dry_run=False)
736
+ integration.run(dry_run=False)
666
737
  _post, _patch = ocm_mock
667
738
  assert _post.call_count == 0
668
739
  assert _patch.call_count == 1
@@ -670,6 +741,7 @@ def test_ocm_osd_update_cluster(
670
741
 
671
742
 
672
743
  def test_ocm_osd_update_cluster_with_machine_pools_change(
744
+ integration: occ.OcmClusters,
673
745
  get_json_mock,
674
746
  queries_mock,
675
747
  ocm_mock,
@@ -690,7 +762,7 @@ def test_ocm_osd_update_cluster_with_machine_pools_change(
690
762
  queries_mock[1].return_value = [new_spec]
691
763
 
692
764
  with pytest.raises(SystemExit):
693
- occ.run(dry_run=False)
765
+ integration.run(dry_run=False)
694
766
 
695
767
  _post, _patch = ocm_mock
696
768
  _post.assert_not_called()
@@ -699,6 +771,7 @@ def test_ocm_osd_update_cluster_with_machine_pools_change(
699
771
 
700
772
 
701
773
  def test_ocm_returns_a_rosa_cluster(
774
+ integration: occ.OcmClusters,
702
775
  get_json_mock,
703
776
  queries_mock,
704
777
  ocm_mock,
@@ -712,7 +785,7 @@ def test_ocm_returns_a_rosa_cluster(
712
785
  }
713
786
  queries_mock[1].return_value = [ocm_osd_cluster_ai_spec]
714
787
  with pytest.raises(SystemExit):
715
- occ.run(dry_run=False)
788
+ integration.run(dry_run=False)
716
789
  _post, _patch = ocm_mock
717
790
  assert _post.call_count == 0
718
791
  assert _patch.call_count == 0
@@ -720,6 +793,7 @@ def test_ocm_returns_a_rosa_cluster(
720
793
 
721
794
 
722
795
  def test_changed_ocm_spec_disable_uwm(
796
+ integration: occ.OcmClusters,
723
797
  get_json_mock,
724
798
  queries_mock,
725
799
  ocm_mock,
@@ -735,7 +809,7 @@ def test_changed_ocm_spec_disable_uwm(
735
809
  queries_mock[1].return_value = [ocm_osd_cluster_ai_spec]
736
810
 
737
811
  with pytest.raises(SystemExit):
738
- occ.run(dry_run=False)
812
+ integration.run(dry_run=False)
739
813
 
740
814
  _post, _patch = ocm_mock
741
815
  assert _patch.call_count == 1
@@ -744,6 +818,7 @@ def test_changed_ocm_spec_disable_uwm(
744
818
 
745
819
 
746
820
  def test_console_url_changes_ai(
821
+ integration: occ.OcmClusters,
747
822
  get_json_mock,
748
823
  queries_mock,
749
824
  ocm_mock,
@@ -757,7 +832,7 @@ def test_console_url_changes_ai(
757
832
  queries_mock[1].return_value = [ocm_osd_cluster_ai_spec]
758
833
 
759
834
  with pytest.raises(SystemExit):
760
- occ.run(dry_run=False)
835
+ integration.run(dry_run=False)
761
836
 
762
837
  _post, _patch = ocm_mock
763
838
  assert _patch.call_count == 0
@@ -2,13 +2,9 @@ import json
2
2
 
3
3
  import pytest
4
4
 
5
+ from reconcile.ocm.types import OCMClusterNetwork, OCMSpec, OSDClusterSpec
5
6
  from reconcile.ocm_upgrade_scheduler_org_updater import render_policy
6
7
  from reconcile.utils.jinja2.utils import Jinja2TemplateError
7
- from reconcile.utils.ocm import (
8
- OCMClusterNetwork,
9
- OCMSpec,
10
- OSDClusterSpec,
11
- )
12
8
 
13
9
 
14
10
  @pytest.fixture
@@ -89,7 +89,7 @@ class K8sJobController:
89
89
 
90
90
  @property
91
91
  def cache(self) -> dict[str, OpenshiftResource]:
92
- if not self._cache:
92
+ if self._cache is None:
93
93
  return self.update_cache()
94
94
  return self._cache
95
95
 
@@ -1 +1,30 @@
1
1
  from reconcile.utils.ocm.ocm import * # noqa: F401,F403
2
+ from reconcile.utils.ocm.products import ( # noqa: F401,F403
3
+ BYTES_IN_GIGABYTE,
4
+ CS_API_BASE,
5
+ DEFAULT_OCM_MACHINE_POOL_ID,
6
+ OCM_PRODUCT_HYPERSHIFT,
7
+ OCM_PRODUCT_OSD,
8
+ OCM_PRODUCT_ROSA,
9
+ SPEC_ATTR_ACCOUNT,
10
+ SPEC_ATTR_AVAILABILITY_ZONES,
11
+ SPEC_ATTR_CHANNEL,
12
+ SPEC_ATTR_CONSOLE_URL,
13
+ SPEC_ATTR_DISABLE_UWM,
14
+ SPEC_ATTR_ELBFQDN,
15
+ SPEC_ATTR_EXTERNAL_ID,
16
+ SPEC_ATTR_HYPERSHIFT,
17
+ SPEC_ATTR_ID,
18
+ SPEC_ATTR_INITIAL_VERSION,
19
+ SPEC_ATTR_LOAD_BALANCERS,
20
+ SPEC_ATTR_MULTI_AZ,
21
+ SPEC_ATTR_NETWORK,
22
+ SPEC_ATTR_OIDC_ENDPONT_URL,
23
+ SPEC_ATTR_PATH,
24
+ SPEC_ATTR_PRIVATE,
25
+ SPEC_ATTR_PROVISION_SHARD_ID,
26
+ SPEC_ATTR_SERVER_URL,
27
+ SPEC_ATTR_STORAGE,
28
+ SPEC_ATTR_SUBNET_IDS,
29
+ SPEC_ATTR_VERSION,
30
+ )
@@ -233,3 +233,10 @@ def get_version(ocm_api: OCMBaseClient, version: str) -> dict[str, Any]:
233
233
 
234
234
  item = ocm_api.get(api)
235
235
  return {k: v for k, v in item.items() if k in VERSION_DESIRED_KEYS}
236
+
237
+
238
+ def get_provisioning_shard_id(ocm_api: OCMBaseClient, cluster_id: str) -> str:
239
+ api = f"/api/clusters_mgmt/v1/clusters/{cluster_id}/provision_shard"
240
+
241
+ item = ocm_api.get(api)
242
+ return item["id"]