qontract-reconcile 0.10.2.dev184__py3-none-any.whl → 0.10.2.dev185__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.
- {qontract_reconcile-0.10.2.dev184.dist-info → qontract_reconcile-0.10.2.dev185.dist-info}/METADATA +1 -1
- {qontract_reconcile-0.10.2.dev184.dist-info → qontract_reconcile-0.10.2.dev185.dist-info}/RECORD +7 -7
- reconcile/automated_actions/config/integration.py +85 -65
- reconcile/gql_definitions/automated_actions/instance.py +47 -38
- reconcile/gql_definitions/introspection.json +634 -270
- {qontract_reconcile-0.10.2.dev184.dist-info → qontract_reconcile-0.10.2.dev185.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.2.dev184.dist-info → qontract_reconcile-0.10.2.dev185.dist-info}/entry_points.txt +0 -0
{qontract_reconcile-0.10.2.dev184.dist-info → qontract_reconcile-0.10.2.dev185.dist-info}/METADATA
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: qontract-reconcile
|
3
|
-
Version: 0.10.2.
|
3
|
+
Version: 0.10.2.dev185
|
4
4
|
Summary: Collection of tools to reconcile services with their desired state as defined in the app-interface DB.
|
5
5
|
Project-URL: homepage, https://github.com/app-sre/qontract-reconcile
|
6
6
|
Project-URL: repository, https://github.com/app-sre/qontract-reconcile
|
{qontract_reconcile-0.10.2.dev184.dist-info → qontract_reconcile-0.10.2.dev185.dist-info}/RECORD
RENAMED
@@ -141,7 +141,7 @@ reconcile/aus/version_gates/ocp_gate_handler.py,sha256=RW1ppDaCZXVegV9AzzqYXxDUu
|
|
141
141
|
reconcile/aus/version_gates/sts_version_gate_handler.py,sha256=swwwz0YyvrEBf_InqrRRBCt2QzHYNvvq8jz9aYwElh4,3663
|
142
142
|
reconcile/automated_actions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
143
143
|
reconcile/automated_actions/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
144
|
-
reconcile/automated_actions/config/integration.py,sha256=
|
144
|
+
reconcile/automated_actions/config/integration.py,sha256=gDNUKxs8m_4GWH0GnW9QXubtsBF6idc0kHxo05hdj0U,11633
|
145
145
|
reconcile/aws_account_manager/README.md,sha256=_XFM3GZNHUzv--e_navqJuaUWpjC6QrHfulreHynFf0,262
|
146
146
|
reconcile/aws_account_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
147
147
|
reconcile/aws_account_manager/integration.py,sha256=XTamC824imAezzVoQhhwdMOawNcPCOghR_y7i_8bpJI,15343
|
@@ -227,7 +227,7 @@ reconcile/glitchtip_project_alerts/integration.py,sha256=BgMx-NyV9mTuv7Sotb2OioC
|
|
227
227
|
reconcile/glitchtip_project_dsn/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
228
228
|
reconcile/glitchtip_project_dsn/integration.py,sha256=2iugub-kHYkHNK33n0v9_TeWonuxCPah_VkoTPvaajE,8077
|
229
229
|
reconcile/gql_definitions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
230
|
-
reconcile/gql_definitions/introspection.json,sha256=
|
230
|
+
reconcile/gql_definitions/introspection.json,sha256=MT1HCR90ZahZxjrgaBEp34JNhjaEiDRblQK-qfSrfF0,2316277
|
231
231
|
reconcile/gql_definitions/acs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
232
232
|
reconcile/gql_definitions/acs/acs_instances.py,sha256=L91WW9LbhJbBSrECqShQpFtjoBOsmNIYLRpMbx1io5o,2181
|
233
233
|
reconcile/gql_definitions/acs/acs_policies.py,sha256=9IFpGAcrZ8nTFC05q3-12nwkNOEkquHB2-XbVq5_jy4,7219
|
@@ -241,7 +241,7 @@ reconcile/gql_definitions/app_sre_tekton_access_revalidation/__init__.py,sha256=
|
|
241
241
|
reconcile/gql_definitions/app_sre_tekton_access_revalidation/roles.py,sha256=8Y4NsS5T7tumDWxY5MuoV50MK2i-DsLYSpCRjb7KaLE,2353
|
242
242
|
reconcile/gql_definitions/app_sre_tekton_access_revalidation/users.py,sha256=XdVxBxiyTR6Cy939EHNw__0k7iWrZWlhrgS5DakST0I,2504
|
243
243
|
reconcile/gql_definitions/automated_actions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
244
|
-
reconcile/gql_definitions/automated_actions/instance.py,sha256=
|
244
|
+
reconcile/gql_definitions/automated_actions/instance.py,sha256=73vRFDvrD9t2cY1Y8jmjfVPNJ_osPrI8fHTAQz0CGv4,6105
|
245
245
|
reconcile/gql_definitions/aws_account_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
246
246
|
reconcile/gql_definitions/aws_account_manager/aws_accounts.py,sha256=vF51KrY2gwX0J9vESiaRMPQqdAMEtz9f_tBq52bInp0,5148
|
247
247
|
reconcile/gql_definitions/aws_ami_cleanup/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -807,7 +807,7 @@ tools/saas_promotion_state/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJ
|
|
807
807
|
tools/saas_promotion_state/saas_promotion_state.py,sha256=UfwwRLS5Ya4_Nh1w5n1dvoYtchQvYE9yj1VANt2IKqI,3925
|
808
808
|
tools/sre_checkpoints/__init__.py,sha256=CDaDaywJnmRCLyl_NCcvxi-Zc0hTi_3OdwKiFOyS39I,145
|
809
809
|
tools/sre_checkpoints/util.py,sha256=zEDbGr18ZeHNQwW8pUsr2JRjuXIPz--WAGJxZo9sv_Y,894
|
810
|
-
qontract_reconcile-0.10.2.
|
811
|
-
qontract_reconcile-0.10.2.
|
812
|
-
qontract_reconcile-0.10.2.
|
813
|
-
qontract_reconcile-0.10.2.
|
810
|
+
qontract_reconcile-0.10.2.dev185.dist-info/METADATA,sha256=-GBtujthD8qi9Bdj1oIRUOc5iAeTf-Xa5Lp5jpTyTPE,24627
|
811
|
+
qontract_reconcile-0.10.2.dev185.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
812
|
+
qontract_reconcile-0.10.2.dev185.dist-info/entry_points.txt,sha256=5i9l54La3vQrDLAdwDKQWC0iG4sV9RRfOb1BpvzOWLc,698
|
813
|
+
qontract_reconcile-0.10.2.dev185.dist-info/RECORD,,
|
@@ -16,10 +16,11 @@ from pydantic import BaseModel
|
|
16
16
|
|
17
17
|
import reconcile.openshift_base as ob
|
18
18
|
from reconcile.gql_definitions.automated_actions.instance import (
|
19
|
-
|
20
|
-
|
19
|
+
AutomatedActionActionListV1,
|
20
|
+
AutomatedActionOpenshiftWorkloadRestartArgumentV1,
|
21
|
+
AutomatedActionOpenshiftWorkloadRestartV1,
|
21
22
|
AutomatedActionsInstanceV1,
|
22
|
-
|
23
|
+
AutomatedActionV1,
|
23
24
|
)
|
24
25
|
from reconcile.gql_definitions.automated_actions.instance import query as instance_query
|
25
26
|
from reconcile.utils import expiration, gql
|
@@ -35,7 +36,7 @@ from reconcile.utils.runtime.integration import (
|
|
35
36
|
from reconcile.utils.semver_helper import make_semver
|
36
37
|
|
37
38
|
QONTRACT_INTEGRATION = "automated-actions-config"
|
38
|
-
QONTRACT_INTEGRATION_VERSION = make_semver(0, 1,
|
39
|
+
QONTRACT_INTEGRATION_VERSION = make_semver(0, 1, 1)
|
39
40
|
|
40
41
|
|
41
42
|
class AutomatedActionsConfigIntegrationParams(PydanticRunParams):
|
@@ -51,7 +52,6 @@ class AutomatedActionsUser(BaseModel):
|
|
51
52
|
|
52
53
|
|
53
54
|
class AutomatedActionsPolicy(BaseModel):
|
54
|
-
sub: str
|
55
55
|
obj: str
|
56
56
|
max_ops: int
|
57
57
|
params: dict[str, str] = {}
|
@@ -89,89 +89,109 @@ class AutomatedActionsConfigIntegration(
|
|
89
89
|
for instance in data.automated_actions_instances_v1 or []:
|
90
90
|
if instance.deployment.delete:
|
91
91
|
continue
|
92
|
-
instance.
|
93
|
-
self.filter_permissions(instance.permissions or [])
|
94
|
-
)
|
92
|
+
instance.actions = list(self.filter_actions(instance.actions or []))
|
95
93
|
yield instance
|
96
94
|
|
97
|
-
def is_enabled(
|
95
|
+
def is_enabled(
|
96
|
+
self, argument: AutomatedActionOpenshiftWorkloadRestartArgumentV1
|
97
|
+
) -> bool:
|
98
98
|
"""Check if the integration is enabled for the given argument namespace."""
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
)
|
104
|
-
return True
|
99
|
+
return (
|
100
|
+
integration_is_enabled("automated-actions", argument.namespace.cluster)
|
101
|
+
and not argument.namespace.delete
|
102
|
+
)
|
105
103
|
|
106
|
-
def
|
107
|
-
self,
|
108
|
-
) -> Generator[
|
104
|
+
def filter_actions(
|
105
|
+
self, actions: Iterable[AutomatedActionV1]
|
106
|
+
) -> Generator[AutomatedActionV1, None, None]:
|
109
107
|
"""Filter out expired roles and arguments (cluster.namespace) with disabled integrations."""
|
110
|
-
for
|
111
|
-
|
112
|
-
|
113
|
-
|
108
|
+
for action in actions:
|
109
|
+
match action:
|
110
|
+
case AutomatedActionOpenshiftWorkloadRestartV1():
|
111
|
+
# automated actions disabled for the cluster?
|
112
|
+
action.openshift_workload_restart_arguments = [
|
113
|
+
arg
|
114
|
+
for arg in action.openshift_workload_restart_arguments or []
|
115
|
+
if self.is_enabled(arg)
|
116
|
+
]
|
117
|
+
|
118
|
+
# Remove expired roles
|
119
|
+
for permission in action.permissions or []:
|
120
|
+
permission.roles = expiration.filter(permission.roles)
|
121
|
+
|
122
|
+
# Remove permissions without roles
|
123
|
+
action.permissions = [
|
124
|
+
permission
|
125
|
+
for permission in action.permissions or []
|
126
|
+
if permission.roles
|
114
127
|
]
|
115
|
-
|
116
|
-
|
117
|
-
if not permission.roles:
|
128
|
+
|
129
|
+
if not action.permissions:
|
118
130
|
continue
|
119
|
-
|
131
|
+
|
132
|
+
yield action
|
120
133
|
|
121
134
|
def compile_users(
|
122
|
-
self,
|
135
|
+
self, actions: Iterable[AutomatedActionV1]
|
123
136
|
) -> list[AutomatedActionsUser]:
|
124
|
-
"""Compile all automated actions
|
137
|
+
"""Compile a list of all automated actions users with their role relations."""
|
125
138
|
users: dict[str, AutomatedActionsUser] = {}
|
126
|
-
for
|
127
|
-
for
|
128
|
-
for
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
139
|
+
for action in actions:
|
140
|
+
for permission in action.permissions or []:
|
141
|
+
for role in permission.roles or []:
|
142
|
+
for user in (role.users or []) + (role.bots or []):
|
143
|
+
if not user.org_username:
|
144
|
+
continue
|
145
|
+
aa_user = users.setdefault(
|
146
|
+
user.org_username,
|
147
|
+
AutomatedActionsUser(username=user.org_username, roles=[]),
|
148
|
+
)
|
149
|
+
aa_user.roles.add(role.name)
|
136
150
|
|
137
151
|
return list(users.values())
|
138
152
|
|
139
153
|
def compile_roles(
|
140
|
-
self,
|
154
|
+
self, actions: Iterable[AutomatedActionV1]
|
141
155
|
) -> AutomatedActionRoles:
|
142
156
|
"""Compile all automated actions policies."""
|
143
157
|
roles: AutomatedActionRoles = {}
|
144
158
|
|
145
|
-
for
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
159
|
+
for action in actions:
|
160
|
+
parameters: list[dict[str, str]] = []
|
161
|
+
match action:
|
162
|
+
case AutomatedActionActionListV1():
|
163
|
+
# no special handling needed, just dump the values
|
164
|
+
parameters.extend(
|
165
|
+
arg.dict(exclude_none=True, exclude_defaults=True)
|
166
|
+
for arg in action.action_list_arguments or []
|
167
|
+
)
|
168
|
+
case AutomatedActionOpenshiftWorkloadRestartV1():
|
169
|
+
parameters.extend(
|
170
|
+
{
|
153
171
|
# all parameter values are regexes in the OPA policy
|
154
172
|
# therefore, cluster and namespace must be fixed to the current strings
|
155
173
|
"cluster": f"^{arg.namespace.cluster.name}$",
|
156
174
|
"namespace": f"^{arg.namespace.name}$",
|
157
|
-
"kind": arg.
|
158
|
-
"name": arg.
|
159
|
-
}
|
160
|
-
|
161
|
-
|
162
|
-
|
175
|
+
"kind": arg.kind,
|
176
|
+
"name": arg.name,
|
177
|
+
}
|
178
|
+
for arg in action.openshift_workload_restart_arguments
|
179
|
+
)
|
180
|
+
|
181
|
+
if not parameters:
|
182
|
+
parameters = [{}]
|
183
|
+
|
184
|
+
for permission in action.permissions or []:
|
185
|
+
for role in permission.roles or []:
|
186
|
+
aa_role = roles.setdefault(role.name, [])
|
187
|
+
aa_role.extend(
|
188
|
+
AutomatedActionsPolicy(
|
189
|
+
obj=action.q_type,
|
190
|
+
max_ops=action.max_ops,
|
191
|
+
params=params,
|
163
192
|
)
|
164
|
-
|
165
|
-
aa_role = roles.setdefault(role.name, [])
|
166
|
-
aa_role.extend(
|
167
|
-
AutomatedActionsPolicy(
|
168
|
-
sub=role.name,
|
169
|
-
obj=action.operation_id,
|
170
|
-
max_ops=action.max_ops,
|
171
|
-
params=params,
|
193
|
+
for params in parameters
|
172
194
|
)
|
173
|
-
for params in parameters
|
174
|
-
)
|
175
195
|
return roles
|
176
196
|
|
177
197
|
def build_policy_file(
|
@@ -273,8 +293,8 @@ class AutomatedActionsConfigIntegration(
|
|
273
293
|
ri = ResourceInventory()
|
274
294
|
|
275
295
|
for instance in instances:
|
276
|
-
users = self.compile_users(instance.
|
277
|
-
policies = self.compile_roles(instance.
|
296
|
+
users = self.compile_users(instance.actions or [])
|
297
|
+
policies = self.compile_roles(instance.actions or [])
|
278
298
|
if not users and not policies:
|
279
299
|
logging.info(
|
280
300
|
f"{instance.deployment.cluster.name}/{instance.deployment.name}: No enabled automated actions found. Skipping this instance!"
|
@@ -69,27 +69,23 @@ query AutomatedActionsInstances {
|
|
69
69
|
...OcConnectionCluster
|
70
70
|
}
|
71
71
|
}
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
72
|
+
actions {
|
73
|
+
type
|
74
|
+
permissions {
|
75
|
+
roles {
|
76
|
+
name
|
77
|
+
users {
|
78
|
+
org_username
|
79
|
+
}
|
80
|
+
bots {
|
81
|
+
org_username
|
82
|
+
}
|
83
|
+
expirationDate
|
80
84
|
}
|
81
|
-
expirationDate
|
82
85
|
}
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
retries
|
87
|
-
maxOps
|
88
|
-
}
|
89
|
-
|
90
|
-
arguments {
|
91
|
-
type
|
92
|
-
... on AutomatedActionArgumentOpenshift_v1 {
|
86
|
+
maxOps
|
87
|
+
... on AutomatedActionOpenshiftWorkloadRestart_v1 {
|
88
|
+
openshift_workload_restart_arguments: arguments {
|
93
89
|
namespace {
|
94
90
|
name
|
95
91
|
delete
|
@@ -100,8 +96,14 @@ query AutomatedActionsInstances {
|
|
100
96
|
}
|
101
97
|
}
|
102
98
|
}
|
103
|
-
|
104
|
-
|
99
|
+
kind
|
100
|
+
name
|
101
|
+
}
|
102
|
+
}
|
103
|
+
... on AutomatedActionActionList_v1 {
|
104
|
+
action_list_arguments: arguments {
|
105
|
+
action_user
|
106
|
+
max_age_minutes
|
105
107
|
}
|
106
108
|
}
|
107
109
|
}
|
@@ -138,47 +140,54 @@ class RoleV1(ConfiguredBaseModel):
|
|
138
140
|
expiration_date: Optional[str] = Field(..., alias="expirationDate")
|
139
141
|
|
140
142
|
|
141
|
-
class
|
142
|
-
|
143
|
-
retries: int = Field(..., alias="retries")
|
144
|
-
max_ops: int = Field(..., alias="maxOps")
|
143
|
+
class PermissionAutomatedActionsV1(ConfiguredBaseModel):
|
144
|
+
roles: Optional[list[RoleV1]] = Field(..., alias="roles")
|
145
145
|
|
146
146
|
|
147
|
-
class
|
147
|
+
class AutomatedActionV1(ConfiguredBaseModel):
|
148
148
|
q_type: str = Field(..., alias="type")
|
149
|
+
permissions: Optional[list[PermissionAutomatedActionsV1]] = Field(..., alias="permissions")
|
150
|
+
max_ops: int = Field(..., alias="maxOps")
|
149
151
|
|
150
152
|
|
151
153
|
class DisableClusterAutomationsV1(ConfiguredBaseModel):
|
152
154
|
integrations: Optional[list[str]] = Field(..., alias="integrations")
|
153
155
|
|
154
156
|
|
155
|
-
class
|
157
|
+
class AutomatedActionOpenshiftWorkloadRestartArgumentV1_NamespaceV1_ClusterV1(ConfiguredBaseModel):
|
156
158
|
name: str = Field(..., alias="name")
|
157
159
|
disable: Optional[DisableClusterAutomationsV1] = Field(..., alias="disable")
|
158
160
|
|
159
161
|
|
160
|
-
class
|
162
|
+
class AutomatedActionOpenshiftWorkloadRestartArgumentV1_NamespaceV1(ConfiguredBaseModel):
|
161
163
|
name: str = Field(..., alias="name")
|
162
164
|
delete: Optional[bool] = Field(..., alias="delete")
|
163
|
-
cluster:
|
165
|
+
cluster: AutomatedActionOpenshiftWorkloadRestartArgumentV1_NamespaceV1_ClusterV1 = Field(..., alias="cluster")
|
164
166
|
|
165
167
|
|
166
|
-
class
|
167
|
-
namespace:
|
168
|
-
|
169
|
-
|
168
|
+
class AutomatedActionOpenshiftWorkloadRestartArgumentV1(ConfiguredBaseModel):
|
169
|
+
namespace: AutomatedActionOpenshiftWorkloadRestartArgumentV1_NamespaceV1 = Field(..., alias="namespace")
|
170
|
+
kind: str = Field(..., alias="kind")
|
171
|
+
name: str = Field(..., alias="name")
|
170
172
|
|
171
173
|
|
172
|
-
class
|
173
|
-
|
174
|
-
|
175
|
-
|
174
|
+
class AutomatedActionOpenshiftWorkloadRestartV1(AutomatedActionV1):
|
175
|
+
openshift_workload_restart_arguments: list[AutomatedActionOpenshiftWorkloadRestartArgumentV1] = Field(..., alias="openshift_workload_restart_arguments")
|
176
|
+
|
177
|
+
|
178
|
+
class AutomatedActionActionListArgumentV1(ConfiguredBaseModel):
|
179
|
+
action_user: Optional[str] = Field(..., alias="action_user")
|
180
|
+
max_age_minutes: Optional[int] = Field(..., alias="max_age_minutes")
|
181
|
+
|
182
|
+
|
183
|
+
class AutomatedActionActionListV1(AutomatedActionV1):
|
184
|
+
action_list_arguments: Optional[list[AutomatedActionActionListArgumentV1]] = Field(..., alias="action_list_arguments")
|
176
185
|
|
177
186
|
|
178
187
|
class AutomatedActionsInstanceV1(ConfiguredBaseModel):
|
179
188
|
name: str = Field(..., alias="name")
|
180
189
|
deployment: NamespaceV1 = Field(..., alias="deployment")
|
181
|
-
|
190
|
+
actions: Optional[list[Union[AutomatedActionOpenshiftWorkloadRestartV1, AutomatedActionActionListV1, AutomatedActionV1]]] = Field(..., alias="actions")
|
182
191
|
|
183
192
|
|
184
193
|
class AutomatedActionsInstancesQueryData(ConfiguredBaseModel):
|