qontract-reconcile 0.10.1rc803__py3-none-any.whl → 0.10.1rc805__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: qontract-reconcile
3
- Version: 0.10.1rc803
3
+ Version: 0.10.1rc805
4
4
  Summary: Collection of tools to reconcile services with their desired state as defined in the app-interface DB.
5
5
  Home-page: https://github.com/app-sre/qontract-reconcile
6
6
  Author: Red Hat App-SRE Team
@@ -104,7 +104,7 @@ reconcile/sendgrid_teammates.py,sha256=oO8QbLb4s1o8A6CGiCagN9CmS05BSS_WLztuY0Ym9
104
104
  reconcile/service_dependencies.py,sha256=PMKP9vc6oL-78rzyF_RE8DzLSQMSqN8vCqt9sWpBLAM,4470
105
105
  reconcile/signalfx_endpoint_monitoring.py,sha256=D1m8iq0EAKie0OD59FOcVCtpWWZ7xlo6lwBS9urwMIk,2894
106
106
  reconcile/slack_base.py,sha256=K3fSYx46G1djoPb07_C9j6ChhMCt5LgV5l6v2TFkNZk,3479
107
- reconcile/slack_usergroups.py,sha256=6G-KjcqacqqhJDsl-KMC-t5M9oexUpSSUc1yGyt2zvY,27120
107
+ reconcile/slack_usergroups.py,sha256=sp1QSPRUgTj3-hXpAWx1qOeR6okmVmlHcTUvUMTOLDI,27855
108
108
  reconcile/sql_query.py,sha256=FAQI9EIHsokZBbGwvGU4vnjg1fHemxpYQE20UtCB1qo,25941
109
109
  reconcile/status.py,sha256=cY4IJFXemhxptRJqR4qaaOWqei9e4jgLXuVSGajMsjg,544
110
110
  reconcile/status_board.py,sha256=nA74_133jukxVShjPKJpkXOA3vggDTTEhYTegoXbN1M,8632
@@ -371,7 +371,7 @@ reconcile/gql_definitions/terraform_repo/__init__.py,sha256=47DEQpj8HBSa-_TImW-5
371
371
  reconcile/gql_definitions/terraform_repo/terraform_repo.py,sha256=_rdq3efy5Q3QFpI-vcs3-wacsXo_1fu1kVix_E83h5Q,3599
372
372
  reconcile/gql_definitions/terraform_resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
373
373
  reconcile/gql_definitions/terraform_resources/database_access_manager.py,sha256=yv0_YC-LmhaKD_gyGG3le1w5BtypBjlsO894-Zgdg4U,4813
374
- reconcile/gql_definitions/terraform_resources/terraform_resources_namespaces.py,sha256=ElJTVH2cwNqJiLFl3Zi5zt9y7dN0yLmdtmwZC5X7ir0,42189
374
+ reconcile/gql_definitions/terraform_resources/terraform_resources_namespaces.py,sha256=bY53hFt1Ki0oqjP03OX4nT80zdD29YwvnlKW3Df7zs8,42401
375
375
  reconcile/gql_definitions/terraform_tgw_attachments/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
376
376
  reconcile/gql_definitions/terraform_tgw_attachments/aws_accounts.py,sha256=GjCuLHOgm3eHbkpK7Q2i7l6tori5Y62uFlz3M89BYtA,2602
377
377
  reconcile/gql_definitions/vault_instances/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -522,7 +522,7 @@ reconcile/test/test_saasherder.py,sha256=hSZk34aZFq-wspT-kJmFuHjh8ztSr7IzGc5QdRV
522
522
  reconcile/test/test_saasherder_allowed_secret_paths.py,sha256=5NHQwNJO66at6HiyMZ5sVRTQDwxdvlOQo0KmkBWCw5Q,4853
523
523
  reconcile/test/test_secret_reader.py,sha256=kz7nzcPjvA08cytnvcA_PMA98AEyqJWsESkYeRn5xCk,4994
524
524
  reconcile/test/test_slack_base.py,sha256=gpbWOLNxMMX6fyAbs1JakhLTnwfedb3f7WpUae4tQZE,5060
525
- reconcile/test/test_slack_usergroups.py,sha256=wmS7xgl4U1jx4gu8qIDlljkhZxb_y8F6tR4UteyrlZE,24899
525
+ reconcile/test/test_slack_usergroups.py,sha256=Yj7SetVzdVsl0mzPakVil3Fb_4R_3r9lC32gnw_CwiA,24899
526
526
  reconcile/test/test_sql_query.py,sha256=rC-lf1_isT9i2ZIV9W0hkUkLi2oBIjZMRMhk-6mV-34,11029
527
527
  reconcile/test/test_status_board.py,sha256=go3YSWo03OLIdK95SuiDJa1Nqk-eN_9QtS7dfmu9__8,7875
528
528
  reconcile/test/test_terraform_aws_route53.py,sha256=xHggb8K1P76OyCfFcogbkmyKle-NlUylcbDnuv3IqvY,771
@@ -619,7 +619,7 @@ reconcile/utils/exceptions.py,sha256=DwfnWUpVOotpP79RWZ2pycmG6nKCL00RBIeZLYkQPW4
619
619
  reconcile/utils/expiration.py,sha256=BXwKE50sNIV-Lszke97fxitNkLxYszoOLW1LBgp_yqg,1246
620
620
  reconcile/utils/extended_early_exit.py,sha256=QSktrmfw37zSRMNk930tDbQsVeKxaPPPD43e79DGwZw,6754
621
621
  reconcile/utils/external_resource_spec.py,sha256=IRY8MCsyWKzt-Qj_hXiFKgkCvZu6VVyj6IYtqEb05BA,6618
622
- reconcile/utils/external_resources.py,sha256=a2CkJ3KLociYBnc_9F2VWfZGWMhzDl6fDNhwo2U-MWU,7501
622
+ reconcile/utils/external_resources.py,sha256=ZnBjQlMpiuCX0Ivm77eIMB4Um_RuAsoMtc8IyuvIxI4,7590
623
623
  reconcile/utils/filtering.py,sha256=zZnHH0u0SaTDyzuFXZ_mREURGLvjEqQIQy4z-7QBVlc,419
624
624
  reconcile/utils/git.py,sha256=BdxXFgQ1XOZpS-4qb3qMsKTCFDG8MlE26rv1jAhvCkM,1560
625
625
  reconcile/utils/git_secrets.py,sha256=0wGNL5mvDtVPRuu3vEQgld1Am64gIDJHtmu1_ZKxMAI,1973
@@ -797,8 +797,8 @@ tools/test/test_app_interface_metrics_exporter.py,sha256=SX7qL3D1SIRKFo95FoQztvf
797
797
  tools/test/test_qontract_cli.py,sha256=_D61RFGAN5x44CY1tYbouhlGXXABwYfxKSWSQx3Jrss,4941
798
798
  tools/test/test_sd_app_sre_alert_report.py,sha256=v363r9zM7__0kR5K6mvJoGFcM9BvE33fWAayrqkpojA,2116
799
799
  tools/test/test_sre_checkpoints.py,sha256=SKqPPTl9ua0RFdSSofnoQX-JZE6dFLO3LRhfQzqtfh8,2607
800
- qontract_reconcile-0.10.1rc803.dist-info/METADATA,sha256=NTfgWm43JS7pKaeQtl4uuf73kEQxGqfhtxg1alCle_E,2314
801
- qontract_reconcile-0.10.1rc803.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
802
- qontract_reconcile-0.10.1rc803.dist-info/entry_points.txt,sha256=rIxI5zWtHNlfpDeq1a7pZXAPoqf7HG32KMTN3MeWK_8,429
803
- qontract_reconcile-0.10.1rc803.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
804
- qontract_reconcile-0.10.1rc803.dist-info/RECORD,,
800
+ qontract_reconcile-0.10.1rc805.dist-info/METADATA,sha256=hQqEKCmIWG-75Lp4rO5VuV1Utx4ciyWOVz3hcotymnM,2314
801
+ qontract_reconcile-0.10.1rc805.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
802
+ qontract_reconcile-0.10.1rc805.dist-info/entry_points.txt,sha256=rIxI5zWtHNlfpDeq1a7pZXAPoqf7HG32KMTN3MeWK_8,429
803
+ qontract_reconcile-0.10.1rc805.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
804
+ qontract_reconcile-0.10.1rc805.dist-info/RECORD,,
@@ -105,6 +105,7 @@ query TerraformResourcesNamespaces {
105
105
  data_classification {
106
106
  loss_impact
107
107
  }
108
+ managed_by_erv2
108
109
  }
109
110
  ... on NamespaceTerraformResourceS3_v1 {
110
111
  region
@@ -173,6 +174,7 @@ query TerraformResourcesNamespaces {
173
174
  prevent_destroy
174
175
  ignore_changes
175
176
  }
177
+ managed_by_erv2
176
178
  }
177
179
  ... on NamespaceTerraformResourceSQS_v1 {
178
180
  region
@@ -562,6 +564,7 @@ class NamespaceTerraformResourceRDSV1(NamespaceTerraformResourceAWSV1):
562
564
  annotations: Optional[str] = Field(..., alias="annotations")
563
565
  event_notifications: Optional[list[AWSRDSEventNotificationV1]] = Field(..., alias="event_notifications")
564
566
  data_classification: Optional[AWSRDSDataClassificationV1] = Field(..., alias="data_classification")
567
+ managed_by_erv2: Optional[bool] = Field(..., alias="managed_by_erv2")
565
568
 
566
569
 
567
570
  class AWSS3EventNotificationV1(ConfiguredBaseModel):
@@ -645,6 +648,7 @@ class NamespaceTerraformResourceRoleV1(NamespaceTerraformResourceAWSV1):
645
648
  output_resource_name: Optional[str] = Field(..., alias="output_resource_name")
646
649
  annotations: Optional[str] = Field(..., alias="annotations")
647
650
  lifecycle: Optional[NamespaceTerraformResourceLifecycleV1] = Field(..., alias="lifecycle")
651
+ managed_by_erv2: Optional[bool] = Field(..., alias="managed_by_erv2")
648
652
 
649
653
 
650
654
  class KeyValueV1(ConfiguredBaseModel):
@@ -1007,7 +1011,7 @@ class NamespaceTerraformResourceMskV1(NamespaceTerraformResourceAWSV1):
1007
1011
 
1008
1012
 
1009
1013
  class NamespaceTerraformProviderResourceAWSV1(NamespaceExternalResourceV1):
1010
- resources: list[Union[NamespaceTerraformResourceRDSV1, NamespaceTerraformResourceRosaAuthenticatorV1, NamespaceTerraformResourceALBV1, NamespaceTerraformResourceS3V1, NamespaceTerraformResourceASGV1, NamespaceTerraformResourceRoleV1, NamespaceTerraformResourceSNSTopicV1, NamespaceTerraformResourceElastiCacheV1, NamespaceTerraformResourceServiceAccountV1, NamespaceTerraformResourceS3SQSV1, NamespaceTerraformResourceCloudWatchV1, NamespaceTerraformResourceRosaAuthenticatorVPCEV1, NamespaceTerraformResourceS3CloudFrontV1, NamespaceTerraformResourceKMSV1, NamespaceTerraformResourceElasticSearchV1, NamespaceTerraformResourceACMV1, NamespaceTerraformResourceKinesisV1, NamespaceTerraformResourceRoute53ZoneV1, NamespaceTerraformResourceMskV1, NamespaceTerraformResourceSQSV1, NamespaceTerraformResourceDynamoDBV1, NamespaceTerraformResourceECRV1, NamespaceTerraformResourceS3CloudFrontPublicKeyV1, NamespaceTerraformResourceSecretsManagerV1, NamespaceTerraformResourceSecretsManagerServiceAccountV1, NamespaceTerraformResourceAWSV1]] = Field(..., alias="resources")
1014
+ resources: list[Union[NamespaceTerraformResourceRDSV1, NamespaceTerraformResourceRosaAuthenticatorV1, NamespaceTerraformResourceALBV1, NamespaceTerraformResourceS3V1, NamespaceTerraformResourceRoleV1, NamespaceTerraformResourceASGV1, NamespaceTerraformResourceSNSTopicV1, NamespaceTerraformResourceElastiCacheV1, NamespaceTerraformResourceServiceAccountV1, NamespaceTerraformResourceS3SQSV1, NamespaceTerraformResourceCloudWatchV1, NamespaceTerraformResourceRosaAuthenticatorVPCEV1, NamespaceTerraformResourceS3CloudFrontV1, NamespaceTerraformResourceKMSV1, NamespaceTerraformResourceElasticSearchV1, NamespaceTerraformResourceACMV1, NamespaceTerraformResourceKinesisV1, NamespaceTerraformResourceRoute53ZoneV1, NamespaceTerraformResourceMskV1, NamespaceTerraformResourceSQSV1, NamespaceTerraformResourceDynamoDBV1, NamespaceTerraformResourceECRV1, NamespaceTerraformResourceS3CloudFrontPublicKeyV1, NamespaceTerraformResourceSecretsManagerV1, NamespaceTerraformResourceSecretsManagerServiceAccountV1, NamespaceTerraformResourceAWSV1]] = Field(..., alias="resources")
1011
1015
 
1012
1016
 
1013
1017
  class EnvironmentV1(ConfiguredBaseModel):
@@ -109,9 +109,7 @@ class State(BaseModel):
109
109
  workspace: str = ""
110
110
  usergroup: str = ""
111
111
  description: str = ""
112
- users: set[SlackObject] = set()
113
112
  user_names: set[str] = set()
114
- channels: set[SlackObject] = set()
115
113
  channel_names: set[str] = set()
116
114
 
117
115
  def __bool__(self) -> bool:
@@ -208,10 +206,8 @@ def get_current_state(
208
206
  current_state.setdefault(workspace, {})[ug] = State(
209
207
  workspace=workspace,
210
208
  usergroup=ug,
211
- users={SlackObject(pk=pk, name=name) for pk, name in users.items()},
212
- channels={
213
- SlackObject(pk=pk, name=name) for pk, name in channels.items()
214
- },
209
+ user_names={name for _, name in users.items()},
210
+ channel_names={name for _, name in channels.items()},
215
211
  description=description,
216
212
  )
217
213
 
@@ -448,7 +444,7 @@ def get_desired_state(
448
444
  workspace=p.workspace.name,
449
445
  usergroup=usergroup,
450
446
  user_names=user_names,
451
- channel_names=sorted(p.channels or []),
447
+ channel_names=sorted(set(p.channels or [])),
452
448
  description=p.description,
453
449
  )
454
450
  return desired_state
@@ -478,11 +474,11 @@ def get_desired_state_cluster_usergroups(
478
474
  for u in openshift_users_desired_state
479
475
  if u["cluster"] == cluster.name
480
476
  ]
481
- cluster_usernames = set({
477
+ cluster_usernames = {
482
478
  get_slack_username(u)
483
479
  for u in users
484
480
  if include_user_to_cluster_usergroup(u, cluster, desired_cluster_users)
485
- })
481
+ }
486
482
  cluster_user_group = compute_cluster_user_group(cluster.name)
487
483
  for workspace, spec in slack_map.items():
488
484
  if not spec.slack.channel:
@@ -504,7 +500,7 @@ def get_desired_state_cluster_usergroups(
504
500
  workspace=workspace,
505
501
  usergroup=cluster_user_group,
506
502
  user_names=cluster_usernames,
507
- channel_names=set([spec.slack.channel]),
503
+ channel_names={spec.slack.channel},
508
504
  description=f"Users with access to the {cluster.name} cluster",
509
505
  )
510
506
  return desired_state
@@ -545,26 +541,40 @@ def _update_usergroup_users_from_state(
545
541
  ) -> None:
546
542
  """Update the users in a Slack usergroup."""
547
543
  global error_occurred # noqa: PLW0603
548
- if current_ug_state.users == desired_ug_state.users:
544
+ if current_ug_state.user_names == desired_ug_state.user_names:
549
545
  logging.debug(
550
546
  f"No usergroup user changes detected for {desired_ug_state.usergroup}"
551
547
  )
552
548
  return
553
549
 
554
- for user in desired_ug_state.users - current_ug_state.users:
550
+ slack_user_objects = [
551
+ SlackObject(pk=pk, name=name)
552
+ for pk, name in slack_client.get_users_by_names(
553
+ desired_ug_state.user_names
554
+ ).items()
555
+ ]
556
+
557
+ if len(slack_user_objects) != len(desired_ug_state.user_names):
558
+ logging.info(
559
+ f"Following usernames are incorrect for usergroup {desired_ug_state.usergroup} and could not be matched with slack users {desired_ug_state.user_names - set(s.name for s in slack_user_objects)}"
560
+ )
561
+ error_occurred = True
562
+ return
563
+
564
+ for user in desired_ug_state.user_names - current_ug_state.user_names:
555
565
  logging.info([
556
566
  "add_user_to_usergroup",
557
567
  desired_ug_state.workspace,
558
568
  desired_ug_state.usergroup,
559
- user.name,
569
+ user,
560
570
  ])
561
571
 
562
- for user in current_ug_state.users - desired_ug_state.users:
572
+ for user in current_ug_state.user_names - desired_ug_state.user_names:
563
573
  logging.info([
564
574
  "del_user_from_usergroup",
565
575
  desired_ug_state.workspace,
566
576
  desired_ug_state.usergroup,
567
- user.name,
577
+ user,
568
578
  ])
569
579
 
570
580
  if not dry_run:
@@ -577,7 +587,7 @@ def _update_usergroup_users_from_state(
577
587
  return
578
588
  slack_client.update_usergroup_users(
579
589
  id=ugid,
580
- users_list=sorted([user.pk for user in desired_ug_state.users]),
590
+ users_list=sorted([s.pk for s in slack_user_objects]),
581
591
  )
582
592
  except SlackApiError as error:
583
593
  # Prior to adding this, we weren't handling failed updates to user
@@ -597,7 +607,7 @@ def _update_usergroup_from_state(
597
607
  """Update a Slack usergroup."""
598
608
  global error_occurred # noqa: PLW0603
599
609
  if (
600
- current_ug_state.channels == desired_ug_state.channels
610
+ current_ug_state.channel_names == desired_ug_state.channel_names
601
611
  and current_ug_state.description == desired_ug_state.description
602
612
  ):
603
613
  logging.debug(
@@ -605,20 +615,39 @@ def _update_usergroup_from_state(
605
615
  )
606
616
  return
607
617
 
608
- for channel in desired_ug_state.channels - current_ug_state.channels:
618
+ slack_channel_objects = [
619
+ SlackObject(pk=pk, name=name)
620
+ for pk, name in slack_client.get_channels_by_names(
621
+ desired_ug_state.channel_names or []
622
+ ).items()
623
+ ]
624
+
625
+ # This is a hack to filter out the missing channels
626
+ desired_channel_names = {s.name for s in slack_channel_objects}
627
+
628
+ # Commenting this out is not correct, we should be checking the length of slack_channel_objects.
629
+ # However there are a couple of missing channels and filtering these out complies with current behavior.
630
+ # if len(slack_channel_objects) != len(desired_ug_state.channel_names):
631
+ # logging.info(
632
+ # f"Following channel names are incorrect for usergroup {desired_ug_state.usergroup} and could not be matched with slack channels {desired_ug_state.channel_names - set([s.name for s in slack_channel_objects])}"
633
+ # )
634
+ # error_occurred = True
635
+ # return
636
+
637
+ for channel in desired_channel_names - current_ug_state.channel_names:
609
638
  logging.info([
610
639
  "add_channel_to_usergroup",
611
640
  desired_ug_state.workspace,
612
641
  desired_ug_state.usergroup,
613
- channel.name,
642
+ channel,
614
643
  ])
615
644
 
616
- for channel in current_ug_state.channels - desired_ug_state.channels:
645
+ for channel in current_ug_state.channel_names - desired_channel_names:
617
646
  logging.info([
618
647
  "del_channel_from_usergroup",
619
648
  desired_ug_state.workspace,
620
649
  desired_ug_state.usergroup,
621
- channel.name,
650
+ channel,
622
651
  ])
623
652
 
624
653
  if current_ug_state.description != desired_ug_state.description:
@@ -639,9 +668,7 @@ def _update_usergroup_from_state(
639
668
  return
640
669
  slack_client.update_usergroup(
641
670
  id=ugid,
642
- channels_list=sorted([
643
- channel.pk for channel in desired_ug_state.channels
644
- ]),
671
+ channels_list=sorted(s.pk for s in slack_channel_objects),
645
672
  description=desired_ug_state.description,
646
673
  )
647
674
  except SlackApiError as error:
@@ -663,40 +690,24 @@ def act(
663
690
  usergroup, State()
664
691
  )
665
692
 
666
- slack_client = slack_map[workspace].slack
667
-
668
- desired_ug_state.users = {
669
- SlackObject(pk=pk, name=name)
670
- for pk, name in slack_client.get_users_by_names(
671
- sorted(desired_ug_state.user_names)
672
- ).items()
673
- }
674
-
675
- desired_ug_state.channels = {
676
- SlackObject(pk=pk, name=name)
677
- for pk, name in slack_client.get_channels_by_names(
678
- sorted(desired_ug_state.channel_names or [])
679
- ).items()
680
- }
681
-
682
693
  _create_usergroups(
683
694
  current_ug_state,
684
695
  desired_ug_state,
685
- slack_client=slack_client,
696
+ slack_client=slack_map[workspace].slack,
686
697
  dry_run=dry_run,
687
698
  )
688
699
 
689
700
  _update_usergroup_users_from_state(
690
701
  current_ug_state,
691
702
  desired_ug_state,
692
- slack_client=slack_client,
703
+ slack_client=slack_map[workspace].slack,
693
704
  dry_run=dry_run,
694
705
  )
695
706
 
696
707
  _update_usergroup_from_state(
697
708
  current_ug_state,
698
709
  desired_ug_state,
699
- slack_client=slack_client,
710
+ slack_client=slack_map[workspace].slack,
700
711
  dry_run=dry_run,
701
712
  )
702
713
 
@@ -36,7 +36,6 @@ from reconcile.gql_definitions.slack_usergroups.users import (
36
36
  from reconcile.gql_definitions.slack_usergroups.users import ClusterV1 as AccessCluster
37
37
  from reconcile.slack_usergroups import (
38
38
  SlackMap,
39
- SlackObject,
40
39
  SlackState,
41
40
  State,
42
41
  WorkspaceSpec,
@@ -61,9 +60,7 @@ def base_state():
61
60
  workspace="slack-workspace",
62
61
  usergroup="usergroup-1",
63
62
  usergroup_id="USERGA",
64
- users={SlackObject(name="username", pk="USERA")},
65
63
  user_names={"username"},
66
- channels={SlackObject(name="channelname", pk="CHANA")},
67
64
  channel_names={"channelname"},
68
65
  description="Some description",
69
66
  )
@@ -561,9 +558,7 @@ def test_act_dryrun_no_changes_made(
561
558
  current_state = base_state
562
559
  desired_state = copy.deepcopy(base_state)
563
560
 
564
- desired_state["slack-workspace"]["usergroup-1"].users = {
565
- SlackObject(name="foo", pk="bar")
566
- }
561
+ desired_state["slack-workspace"]["usergroup-1"].user_names = {"foo"}
567
562
 
568
563
  act(current_state, desired_state, slack_map, dry_run=True)
569
564
 
@@ -604,6 +599,11 @@ def test_act_update_usergroup_users(
604
599
  current_state = base_state
605
600
  desired_state = copy.deepcopy(base_state)
606
601
 
602
+ desired_state["slack-workspace"]["usergroup-1"].user_names = {
603
+ "someotherusername",
604
+ "anotheruser",
605
+ }
606
+
607
607
  slack_client_mock.get_usergroup_id.return_value = "USERGA"
608
608
  slack_client_mock.get_users_by_names.return_value = {
609
609
  "USERB": "someotherusername",
@@ -614,6 +614,7 @@ def test_act_update_usergroup_users(
614
614
  act(current_state, desired_state, slack_map, dry_run=False)
615
615
 
616
616
  slack_client_mock.update_usergroup.assert_not_called()
617
+ slack_client_mock.update_usergroup_users.assert_called_once()
617
618
  assert slack_client_mock.update_usergroup_users.call_args_list == [
618
619
  call(id="USERGA", users_list=["USERB", "USERC"])
619
620
  ]
@@ -36,6 +36,8 @@ def get_external_resource_specs(
36
36
  external_resources = namespace_info.get("externalResources") or []
37
37
  for e in external_resources:
38
38
  for r in e.get("resources", []):
39
+ if "managed_by_erv2" in r and r["managed_by_erv2"]:
40
+ continue
39
41
  spec = ExternalResourceSpec(
40
42
  provision_provider=e["provider"],
41
43
  provisioner=e["provisioner"],