qontract-reconcile 0.10.1rc765__py3-none-any.whl → 0.10.1rc766__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.1rc765
3
+ Version: 0.10.1rc766
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
@@ -308,7 +308,7 @@ reconcile/gql_definitions/jira_permissions_validator/jira_boards_for_permissions
308
308
  reconcile/gql_definitions/jumphosts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
309
309
  reconcile/gql_definitions/jumphosts/jumphosts.py,sha256=gN595lx7K1XsB2AfxDQ911TBVBbCoxibVeujnsGue_Q,2371
310
310
  reconcile/gql_definitions/ldap_groups/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
311
- reconcile/gql_definitions/ldap_groups/roles.py,sha256=RVTDgMExKb2BGq4dVeBYm5p7HMJlbjme-YkUWh8ikkA,2612
311
+ reconcile/gql_definitions/ldap_groups/roles.py,sha256=goGDnkBBFy0mdLsXqL9qlSLPCFd9rwiD1rrsIH-6nZQ,2888
312
312
  reconcile/gql_definitions/ldap_groups/settings.py,sha256=KR6eKqXQWVYZAUEdatL1RCARaTOWl9X-QmxEMVjVNDE,2227
313
313
  reconcile/gql_definitions/membershipsources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
314
314
  reconcile/gql_definitions/membershipsources/roles.py,sha256=d3nv3GLsj_eKgwB1glsiK6smpC4i16WO3dU5rIdRg94,3678
@@ -377,7 +377,7 @@ reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator_peered_c
377
377
  reconcile/jenkins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
378
378
  reconcile/jenkins/types.py,sha256=0UlyJxv3KY1WXHkfI_ghUI6FAwRJTL4EwvLg-62tNcg,3001
379
379
  reconcile/ldap_groups/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
380
- reconcile/ldap_groups/integration.py,sha256=iVfR7bRz8up_bf5Q4aVZHuVoUT6U_aHHkcgY4S9RwqA,10113
380
+ reconcile/ldap_groups/integration.py,sha256=Jj4jWp1aypkoweVNQj7QzMtFKQIWeaunLtXZ8KyKOHE,10670
381
381
  reconcile/ocm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
382
382
  reconcile/ocm/types.py,sha256=ibJYvzfAZyyMFkcF1bP8u3rkXciYJRplt_7Z1pKHFh0,2484
383
383
  reconcile/ocm_internal_notifications/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -692,7 +692,7 @@ reconcile/utils/glitchtip/client.py,sha256=KHUNjN8r2J67RxROIpjzs5cKsqbwjzsM_I1TA
692
692
  reconcile/utils/glitchtip/models.py,sha256=_oqZXNkyRTsAnx6tF4WUURSBj0cc9UNS4okOQYfAfB4,6435
693
693
  reconcile/utils/internal_groups/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
694
694
  reconcile/utils/internal_groups/client.py,sha256=abREA8RwXKybXFjCK8CAcCr-iUp2r0tAbIEJ-c-PXws,4538
695
- reconcile/utils/internal_groups/models.py,sha256=jlkH_hyyyuwS0J1IpuS7W1AyQSKQ2QpHelXoH36edbE,2316
695
+ reconcile/utils/internal_groups/models.py,sha256=GSkF6fVcdbl774q51ZFUmNfSJPta03OcV67MgsuBR2E,2326
696
696
  reconcile/utils/jinja2/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
697
697
  reconcile/utils/jinja2/extensions.py,sha256=zV_x8MhSHAynKhFnG3fULXrwsm5fUG_88IygZHSnN0o,1284
698
698
  reconcile/utils/jinja2/filters.py,sha256=_kJjdMsY3lGS5PUn4NnpXUQDNrL1IwiKsB-0MhTMGYM,4521
@@ -782,8 +782,8 @@ tools/test/test_app_interface_metrics_exporter.py,sha256=SX7qL3D1SIRKFo95FoQztvf
782
782
  tools/test/test_qontract_cli.py,sha256=w2l4BHB09k1d-BGJ1jBUNCqDv7zkqYrMHojQXg-21kQ,4155
783
783
  tools/test/test_sd_app_sre_alert_report.py,sha256=v363r9zM7__0kR5K6mvJoGFcM9BvE33fWAayrqkpojA,2116
784
784
  tools/test/test_sre_checkpoints.py,sha256=SKqPPTl9ua0RFdSSofnoQX-JZE6dFLO3LRhfQzqtfh8,2607
785
- qontract_reconcile-0.10.1rc765.dist-info/METADATA,sha256=jvfPojPDE35EHICj36iXRI8v0jcPR9pHsqy5dacJiVE,2382
786
- qontract_reconcile-0.10.1rc765.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
787
- qontract_reconcile-0.10.1rc765.dist-info/entry_points.txt,sha256=rIxI5zWtHNlfpDeq1a7pZXAPoqf7HG32KMTN3MeWK_8,429
788
- qontract_reconcile-0.10.1rc765.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
789
- qontract_reconcile-0.10.1rc765.dist-info/RECORD,,
785
+ qontract_reconcile-0.10.1rc766.dist-info/METADATA,sha256=tFpqi2YNRp9SyjmZicHUP7W6onmCER5zHM7Y-fD6qa0,2382
786
+ qontract_reconcile-0.10.1rc766.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
787
+ qontract_reconcile-0.10.1rc766.dist-info/entry_points.txt,sha256=rIxI5zWtHNlfpDeq1a7pZXAPoqf7HG32KMTN3MeWK_8,429
788
+ qontract_reconcile-0.10.1rc766.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
789
+ qontract_reconcile-0.10.1rc766.dist-info/RECORD,,
@@ -33,7 +33,11 @@ fragment AWSAccountSSO on AWSAccount_v1 {
33
33
  query LdapGroupsRolesQuery {
34
34
  roles: roles_v1 {
35
35
  name
36
- ldapGroup
36
+ ldapGroup {
37
+ name
38
+ notes
39
+ membersAreOwners
40
+ }
37
41
  users {
38
42
  org_username
39
43
  }
@@ -58,6 +62,12 @@ class ConfiguredBaseModel(BaseModel):
58
62
  extra=Extra.forbid
59
63
 
60
64
 
65
+ class LdapGroupV1(ConfiguredBaseModel):
66
+ name: str = Field(..., alias="name")
67
+ notes: Optional[str] = Field(..., alias="notes")
68
+ members_are_owners: Optional[bool] = Field(..., alias="membersAreOwners")
69
+
70
+
61
71
  class UserV1(ConfiguredBaseModel):
62
72
  org_username: str = Field(..., alias="org_username")
63
73
 
@@ -72,7 +82,7 @@ class AWSGroupV1(ConfiguredBaseModel):
72
82
 
73
83
  class RoleV1(ConfiguredBaseModel):
74
84
  name: str = Field(..., alias="name")
75
- ldap_group: Optional[str] = Field(..., alias="ldapGroup")
85
+ ldap_group: Optional[LdapGroupV1] = Field(..., alias="ldapGroup")
76
86
  users: list[UserV1] = Field(..., alias="users")
77
87
  user_policies: Optional[list[AWSUserPolicyV1]] = Field(..., alias="user_policies")
78
88
  aws_groups: Optional[list[AWSGroupV1]] = Field(..., alias="aws_groups")
@@ -93,12 +93,12 @@ class LdapGroupsIntegration(QontractReconcileIntegration[LdapGroupsIntegrationPa
93
93
  desired_groups_for_roles = self.get_desired_groups_for_roles(
94
94
  roles,
95
95
  contact_list=self.settings.contact_list,
96
- owners=[owner],
96
+ default_owners=[owner],
97
97
  )
98
98
  desired_groups_for_aws_roles = self.get_desired_groups_for_aws_roles(
99
99
  roles,
100
100
  contact_list=self.settings.contact_list,
101
- owners=[owner],
101
+ default_owners=[owner],
102
102
  )
103
103
  desired_groups = desired_groups_for_roles + desired_groups_for_aws_roles
104
104
 
@@ -147,7 +147,7 @@ class LdapGroupsIntegration(QontractReconcileIntegration[LdapGroupsIntegrationPa
147
147
  data = roles_query(query_func, variables={})
148
148
  roles = [role for role in data.roles or []]
149
149
  if duplicates := find_duplicates(
150
- role.ldap_group for role in roles if role.ldap_group
150
+ role.ldap_group.name for role in roles if role.ldap_group
151
151
  ):
152
152
  for dup in duplicates:
153
153
  logging.error(f"{dup} is already in use by another role.")
@@ -155,30 +155,39 @@ class LdapGroupsIntegration(QontractReconcileIntegration[LdapGroupsIntegrationPa
155
155
  return roles
156
156
 
157
157
  def get_desired_groups_for_roles(
158
- self, roles: Iterable[RoleV1], owners: Iterable[Entity], contact_list: str
158
+ self,
159
+ roles: Iterable[RoleV1],
160
+ default_owners: list[Entity],
161
+ contact_list: str,
159
162
  ) -> list[Group]:
160
163
  """Return the desired rover groups for the given roles."""
161
- return [
162
- Group(
163
- name=role.ldap_group,
164
- description="Persisted App-Interface role. Managed by qontract-reconcile",
165
- display_name=f"{role.ldap_group} (App-Interface))",
166
- members=[
167
- Entity(type=EntityType.USER, id=user.org_username)
168
- for user in role.users
169
- ],
170
- # only owners can modify the group (e.g. add/remove members)
171
- owners=owners,
172
- contact_list=contact_list,
164
+ groups = []
165
+ for role in roles:
166
+ if not role.ldap_group:
167
+ continue
168
+ members = [
169
+ Entity(type=EntityType.USER, id=user.org_username)
170
+ for user in role.users
171
+ ]
172
+ groups.append(
173
+ Group(
174
+ name=role.ldap_group.name,
175
+ description="Persisted App-Interface role. Managed by qontract-reconcile",
176
+ notes=role.ldap_group.notes,
177
+ display_name=f"{role.ldap_group.name} (App-Interface))",
178
+ members=members,
179
+ owners=default_owners
180
+ if not role.ldap_group.members_are_owners
181
+ else default_owners + members,
182
+ contact_list=contact_list,
183
+ )
173
184
  )
174
- for role in roles
175
- if role.ldap_group
176
- ]
185
+ return groups
177
186
 
178
187
  def get_desired_groups_for_aws_roles(
179
188
  self,
180
189
  roles: Iterable[RoleV1],
181
- owners: list[Entity],
190
+ default_owners: Iterable[Entity],
182
191
  contact_list: str,
183
192
  ) -> list[Group]:
184
193
  """Return the desired rover groups for all AWS roles."""
@@ -205,7 +214,7 @@ class LdapGroupsIntegration(QontractReconcileIntegration[LdapGroupsIntegrationPa
205
214
  for user in role.users
206
215
  ],
207
216
  # only owners can modify the group (e.g. add/remove members)
208
- owners=owners,
217
+ owners=default_owners,
209
218
  contact_list=contact_list,
210
219
  )
211
220
  )
@@ -246,7 +255,9 @@ class LdapGroupsIntegration(QontractReconcileIntegration[LdapGroupsIntegrationPa
246
255
  logging.info([
247
256
  "create_ldap_group",
248
257
  group_to_add.name,
249
- f"users={', '.join(u.id for u in group_to_add.members)}",
258
+ f"members={', '.join(u.id for u in group_to_add.members)}",
259
+ f"owners={', '.join(u.id for u in group_to_add.owners)}",
260
+ f"notes={group_to_add.notes}",
250
261
  ])
251
262
  if not dry_run:
252
263
  internal_groups_client.create_group(group_to_add)
@@ -266,7 +277,9 @@ class LdapGroupsIntegration(QontractReconcileIntegration[LdapGroupsIntegrationPa
266
277
  logging.info([
267
278
  "update_ldap_group",
268
279
  group_to_update.name,
269
- f"users={', '.join(u.id for u in group_to_update.members)}",
280
+ f"members={', '.join(u.id for u in group_to_update.members)}",
281
+ f"owners={', '.join(u.id for u in group_to_update.owners)}",
282
+ f"notes={group_to_update.notes}",
270
283
  ])
271
284
  if not dry_run:
272
285
  internal_groups_client.update_group(group_to_update)
@@ -54,7 +54,7 @@ class Group(BaseModel):
54
54
  self.description == other.description
55
55
  and self.member_approval_type == other.member_approval_type
56
56
  and self.contact_list == other.contact_list
57
- and self.owners == other.owners
57
+ and set(self.owners) == set(other.owners)
58
58
  and self.display_name == other.display_name
59
59
  and self.notes == other.notes
60
60
  and set(self.members) == set(other.members)