qontract-reconcile 0.10.2.dev109__py3-none-any.whl → 0.10.2.dev111__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.4
2
2
  Name: qontract-reconcile
3
- Version: 0.10.2.dev109
3
+ Version: 0.10.2.dev111
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
@@ -10,7 +10,7 @@ reconcile/aws_iam_password_reset.py,sha256=q96mwr2KeEQ5bpNniGlgIMZTxiuLSodcYfX-t
10
10
  reconcile/aws_support_cases_sos.py,sha256=hl_9L53yQYRQxKs3IWrd69Cc60XK067g_bJRM9B0udo,2975
11
11
  reconcile/blackbox_exporter_endpoint_monitoring.py,sha256=O1wFp52EyF538c6txaWBs8eMtUIy19gyHZ6VzJ6QXS8,3512
12
12
  reconcile/checkpoint.py,sha256=_JhMxrye5BgkRMxWYuf7Upli6XayPINKSsuo3ynHTRc,5010
13
- reconcile/cli.py,sha256=MRdXMNRMBk0e4kv-ctHyYtDD5kAKnT8j6_wiTlWkrQo,107736
13
+ reconcile/cli.py,sha256=hwqPcZVmazrhzq1esPBk5jNHSzpfr7o9EmuuMqiPxfg,108430
14
14
  reconcile/closedbox_endpoint_monitoring_base.py,sha256=MvGKBqH9PdHWdMjhLuptze-dk0Tifhp3-0SZdI-7Fmo,4862
15
15
  reconcile/cluster_deployment_mapper.py,sha256=5gumAaRCcFXsabUJ1dnuUy9WrP_FEEM5JnOnE8ch9sE,2326
16
16
  reconcile/dashdotdb_base.py,sha256=83ZWIf5JJk3P_D69y2TmXRcQr6ELJGlv10OM0h7fJVs,4767
@@ -139,6 +139,9 @@ reconcile/aus/version_gates/handler.py,sha256=S_isQPYHbG4DERiUEvQBZ6ngiFX3uMmATA
139
139
  reconcile/aus/version_gates/ingress_gate_handler.py,sha256=ZCtyggBzzcb0prtdbMpJsVkj5leYN-vS7srM9vbq9xo,1096
140
140
  reconcile/aus/version_gates/ocp_gate_handler.py,sha256=RW1ppDaCZXVegV9AzzqYXxDUu_Z_7d43Z5h2Pk_piKc,716
141
141
  reconcile/aus/version_gates/sts_version_gate_handler.py,sha256=swwwz0YyvrEBf_InqrRRBCt2QzHYNvvq8jz9aYwElh4,3663
142
+ reconcile/automated_actions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
143
+ reconcile/automated_actions/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
144
+ reconcile/automated_actions/config/integration.py,sha256=cf1VxolcjlGP-xO7IIH5A00Qr4znNJTT7a_sU18ABig,10755
142
145
  reconcile/aws_account_manager/README.md,sha256=_XFM3GZNHUzv--e_navqJuaUWpjC6QrHfulreHynFf0,262
143
146
  reconcile/aws_account_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
144
147
  reconcile/aws_account_manager/integration.py,sha256=WOE_mi45pvJW4TNKh4mCGSViJiElH--T4Wg0CLMYxpY,14988
@@ -224,7 +227,7 @@ reconcile/glitchtip_project_alerts/integration.py,sha256=BgMx-NyV9mTuv7Sotb2OioC
224
227
  reconcile/glitchtip_project_dsn/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
225
228
  reconcile/glitchtip_project_dsn/integration.py,sha256=2iugub-kHYkHNK33n0v9_TeWonuxCPah_VkoTPvaajE,8077
226
229
  reconcile/gql_definitions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
227
- reconcile/gql_definitions/introspection.json,sha256=rgLJjGZJ-r-f_d74-1HNqf2X1EwNUjtB8gwbuMSfZEI,2249822
230
+ reconcile/gql_definitions/introspection.json,sha256=Qzf2HgsfNMLNW7EBIpdB4MX-6DjIdXOHtjVzdiBmczQ,2280010
228
231
  reconcile/gql_definitions/acs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
229
232
  reconcile/gql_definitions/acs/acs_instances.py,sha256=L91WW9LbhJbBSrECqShQpFtjoBOsmNIYLRpMbx1io5o,2181
230
233
  reconcile/gql_definitions/acs/acs_policies.py,sha256=bN5i4mks10Z23KJSj7jqp966Osq2dps4d-sPH9gjxEA,7008
@@ -237,6 +240,8 @@ reconcile/gql_definitions/app_interface_metrics_exporter/onboarding_status.py,sh
237
240
  reconcile/gql_definitions/app_sre_tekton_access_revalidation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
238
241
  reconcile/gql_definitions/app_sre_tekton_access_revalidation/roles.py,sha256=8Y4NsS5T7tumDWxY5MuoV50MK2i-DsLYSpCRjb7KaLE,2353
239
242
  reconcile/gql_definitions/app_sre_tekton_access_revalidation/users.py,sha256=XdVxBxiyTR6Cy939EHNw__0k7iWrZWlhrgS5DakST0I,2504
243
+ reconcile/gql_definitions/automated_actions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
244
+ reconcile/gql_definitions/automated_actions/instance.py,sha256=D50v0exLeK5hvjQKvxQ5V-6DnYZo_L6cX_Gaf3PGREs,5491
240
245
  reconcile/gql_definitions/aws_account_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
241
246
  reconcile/gql_definitions/aws_account_manager/aws_accounts.py,sha256=JdqtE3gMpeodymPJST-aFVkYP_MO--_CcwjF070R5Cs,4883
242
247
  reconcile/gql_definitions/aws_ami_cleanup/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -630,7 +635,7 @@ reconcile/utils/parse_dhms_duration.py,sha256=TONpLnec5gHeF7k815YNJpQyDjXhkxZIcv
630
635
  reconcile/utils/password_validator.py,sha256=XwuWg-8CPlcuG7dl_oQ1G1h2gSVSnfMym_VkuprpWVg,2183
631
636
  reconcile/utils/prometheus.py,sha256=Ad0rwLbxRuuYjHwkwJloHEdK0bvy42h-p-HIT1DhDhs,3832
632
637
  reconcile/utils/promotion_state.py,sha256=McSgGj3oog83ThJCrMR2v8q6Xb_Pxij-HEe_RbDu8cg,3946
633
- reconcile/utils/promtool.py,sha256=qOWgRY9-HgfTAcQz8NnLfnZn2WtCAvRAr85YQRXvMSA,2831
638
+ reconcile/utils/promtool.py,sha256=xmPBWEApkk0L2qZBAvTxakNXxfTz-tVLPFxGnpsxXnM,2831
634
639
  reconcile/utils/quay_api.py,sha256=uE_jxcdy3ViHtYFAfwDQuFDaO7Pr6AAPoVnmORbyHio,7822
635
640
  reconcile/utils/raw_github_api.py,sha256=2WKtE8ABYYB9UGOAh9N_kLkksBWL3320Z2_scteZddI,2805
636
641
  reconcile/utils/repo_owners.py,sha256=BHrAXxKyvn4qWJwFPWYGTtfgnLmYnWtYFEJGFeD__FE,6573
@@ -786,7 +791,7 @@ tools/saas_promotion_state/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJ
786
791
  tools/saas_promotion_state/saas_promotion_state.py,sha256=UfwwRLS5Ya4_Nh1w5n1dvoYtchQvYE9yj1VANt2IKqI,3925
787
792
  tools/sre_checkpoints/__init__.py,sha256=CDaDaywJnmRCLyl_NCcvxi-Zc0hTi_3OdwKiFOyS39I,145
788
793
  tools/sre_checkpoints/util.py,sha256=zEDbGr18ZeHNQwW8pUsr2JRjuXIPz--WAGJxZo9sv_Y,894
789
- qontract_reconcile-0.10.2.dev109.dist-info/METADATA,sha256=keuME2MAvfe3rMs380B66x0Hz4lTocctk1VCA_xcnFA,24566
790
- qontract_reconcile-0.10.2.dev109.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
791
- qontract_reconcile-0.10.2.dev109.dist-info/entry_points.txt,sha256=5i9l54La3vQrDLAdwDKQWC0iG4sV9RRfOb1BpvzOWLc,698
792
- qontract_reconcile-0.10.2.dev109.dist-info/RECORD,,
794
+ qontract_reconcile-0.10.2.dev111.dist-info/METADATA,sha256=Md2jyCPz6LwUfZ7bX6OjsZyLcD2I_z7JpH5SAKt_Zl0,24566
795
+ qontract_reconcile-0.10.2.dev111.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
796
+ qontract_reconcile-0.10.2.dev111.dist-info/entry_points.txt,sha256=5i9l54La3vQrDLAdwDKQWC0iG4sV9RRfOb1BpvzOWLc,698
797
+ qontract_reconcile-0.10.2.dev111.dist-info/RECORD,,
File without changes
File without changes
@@ -0,0 +1,300 @@
1
+ import logging
2
+ from collections.abc import (
3
+ Callable,
4
+ Generator,
5
+ Iterable,
6
+ )
7
+ from typing import Any
8
+
9
+ import yaml
10
+ from kubernetes.client import ( # type: ignore[attr-defined]
11
+ ApiClient,
12
+ V1ConfigMap,
13
+ V1ObjectMeta,
14
+ )
15
+ from pydantic import BaseModel
16
+
17
+ import reconcile.openshift_base as ob
18
+ from reconcile.gql_definitions.automated_actions.instance import (
19
+ AutomatedActionArgumentOpenshiftV1,
20
+ AutomatedActionArgumentV1,
21
+ AutomatedActionsInstanceV1,
22
+ PermissionAutomatedActionsV1,
23
+ )
24
+ from reconcile.gql_definitions.automated_actions.instance import query as instance_query
25
+ from reconcile.utils import expiration, gql
26
+ from reconcile.utils.defer import defer
27
+ from reconcile.utils.disabled_integrations import integration_is_enabled
28
+ from reconcile.utils.oc import OCCli
29
+ from reconcile.utils.oc_map import init_oc_map_from_namespaces
30
+ from reconcile.utils.openshift_resource import OpenshiftResource, ResourceInventory
31
+ from reconcile.utils.runtime.integration import (
32
+ PydanticRunParams,
33
+ QontractReconcileIntegration,
34
+ )
35
+ from reconcile.utils.semver_helper import make_semver
36
+
37
+ QONTRACT_INTEGRATION = "automated-actions-config"
38
+ QONTRACT_INTEGRATION_VERSION = make_semver(0, 1, 0)
39
+
40
+
41
+ class AutomatedActionsConfigIntegrationParams(PydanticRunParams):
42
+ thread_pool_size: int
43
+ use_jump_host: bool
44
+ internal: bool | None = None
45
+ configmap_name: str = "automated-actions-policy"
46
+
47
+
48
+ class AutomatedActionsUser(BaseModel):
49
+ username: str
50
+ roles: set[str]
51
+
52
+
53
+ class AutomatedActionsPolicy(BaseModel):
54
+ sub: str
55
+ obj: str
56
+ params: dict[str, str] = {}
57
+
58
+
59
+ AutomatedActionRoles = dict[str, list[AutomatedActionsPolicy]]
60
+
61
+
62
+ class AutomatedActionsConfigIntegration(
63
+ QontractReconcileIntegration[AutomatedActionsConfigIntegrationParams]
64
+ ):
65
+ """Manage LDAP groups based on App-Interface roles."""
66
+
67
+ @property
68
+ def name(self) -> str:
69
+ return QONTRACT_INTEGRATION
70
+
71
+ def get_early_exit_desired_state(
72
+ self, query_func: Callable | None = None
73
+ ) -> dict[str, Any]:
74
+ """Return the desired state for early exit."""
75
+ if not query_func:
76
+ query_func = gql.get_api().query
77
+ return {
78
+ "automated_actions_instances": [
79
+ c.dict() for c in self.get_automated_actions_instances(query_func)
80
+ ]
81
+ }
82
+
83
+ def get_automated_actions_instances(
84
+ self, query_func: Callable
85
+ ) -> Generator[AutomatedActionsInstanceV1, None, None]:
86
+ """Return all automated actions."""
87
+ data = instance_query(query_func, variables={})
88
+ for instance in data.automated_actions_instances_v1 or []:
89
+ if instance.deployment.delete:
90
+ continue
91
+ instance.permissions = list(
92
+ self.filter_permissions(instance.permissions or [])
93
+ )
94
+ yield instance
95
+
96
+ def is_enabled(self, argument: AutomatedActionArgumentV1) -> bool:
97
+ """Check if the integration is enabled for the given argument namespace."""
98
+ if isinstance(argument, AutomatedActionArgumentOpenshiftV1):
99
+ return (
100
+ integration_is_enabled("automated-actions", argument.namespace.cluster)
101
+ and not argument.namespace.delete
102
+ )
103
+ return True
104
+
105
+ def filter_permissions(
106
+ self, permissions: Iterable[PermissionAutomatedActionsV1]
107
+ ) -> Generator[PermissionAutomatedActionsV1, None, None]:
108
+ """Filter out expired roles and arguments (cluster.namespace) with disabled integrations."""
109
+ for permission in permissions:
110
+ # automated actions disabled for the cluster?
111
+ permission.arguments = [
112
+ arg for arg in permission.arguments or [] if self.is_enabled(arg)
113
+ ]
114
+ # remove expired roles
115
+ permission.roles = expiration.filter(permission.roles)
116
+ if not permission.roles:
117
+ continue
118
+ yield permission
119
+
120
+ def compile_users(
121
+ self, permissions: Iterable[PermissionAutomatedActionsV1]
122
+ ) -> list[AutomatedActionsUser]:
123
+ """Compile all automated actions roles."""
124
+ users: dict[str, AutomatedActionsUser] = {}
125
+ for permission in permissions:
126
+ for role in permission.roles or []:
127
+ for user in (role.users or []) + (role.bots or []):
128
+ if not user.org_username:
129
+ continue
130
+ aa_user = users.setdefault(
131
+ user.org_username,
132
+ AutomatedActionsUser(username=user.org_username, roles=[]),
133
+ )
134
+ aa_user.roles.add(role.name)
135
+
136
+ return list(users.values())
137
+
138
+ def compile_roles(
139
+ self, permissions: Iterable[PermissionAutomatedActionsV1]
140
+ ) -> AutomatedActionRoles:
141
+ """Compile all automated actions policies."""
142
+ roles: AutomatedActionRoles = {}
143
+
144
+ for permission in permissions or []:
145
+ obj = permission.action.operation_id
146
+
147
+ parameters: list[dict[str, str]] = [] if permission.arguments else [{}]
148
+ for arg in permission.arguments or []:
149
+ match arg:
150
+ case AutomatedActionArgumentOpenshiftV1():
151
+ parameters.append({
152
+ # all parameter values are regexes in the OPA policy
153
+ # therefore, cluster and namespace must be fixed to the current strings
154
+ "cluster": f"^{arg.namespace.cluster.name}$",
155
+ "namespace": f"^{arg.namespace.name}$",
156
+ "kind": arg.kind_pattern,
157
+ "name": arg.name_pattern,
158
+ })
159
+ case _:
160
+ raise NotImplementedError(
161
+ f"Unsupported argument type: {arg.q_type}"
162
+ )
163
+ for role in permission.roles or []:
164
+ aa_role = roles.setdefault(role.name, [])
165
+ aa_role.extend(
166
+ AutomatedActionsPolicy(sub=role.name, obj=obj, params=params)
167
+ for params in parameters
168
+ )
169
+ return roles
170
+
171
+ def build_policy_file(
172
+ self,
173
+ users: Iterable[AutomatedActionsUser],
174
+ roles: AutomatedActionRoles,
175
+ ) -> str:
176
+ """Build the automated actions casbin policy file."""
177
+ return yaml.dump(
178
+ {
179
+ "users": {user.username: sorted(user.roles) for user in users},
180
+ "roles": {
181
+ role: [policy.dict() for policy in policies]
182
+ for role, policies in roles.items()
183
+ },
184
+ },
185
+ sort_keys=True,
186
+ )
187
+
188
+ def build_desired_configmap(
189
+ self,
190
+ ri: ResourceInventory,
191
+ instance: AutomatedActionsInstanceV1,
192
+ name: str,
193
+ data: str,
194
+ ) -> None:
195
+ """Build the automated actions configmap."""
196
+ osr = OpenshiftResource(
197
+ body=ApiClient().sanitize_for_serialization(
198
+ V1ConfigMap(
199
+ api_version="v1",
200
+ kind="ConfigMap",
201
+ metadata=V1ObjectMeta(name=name),
202
+ data={"roles.yml": data},
203
+ )
204
+ ),
205
+ integration=QONTRACT_INTEGRATION,
206
+ integration_version=QONTRACT_INTEGRATION_VERSION,
207
+ ).annotate()
208
+ ri.initialize_resource_type(
209
+ cluster=instance.deployment.cluster.name,
210
+ namespace=instance.deployment.name,
211
+ resource_type=osr.kind,
212
+ )
213
+ ri.add_desired_resource(
214
+ cluster=instance.deployment.cluster.name,
215
+ namespace=instance.deployment.name,
216
+ resource=osr,
217
+ )
218
+
219
+ def fetch_current_configmap(
220
+ self,
221
+ ri: ResourceInventory,
222
+ instance: AutomatedActionsInstanceV1,
223
+ oc: OCCli,
224
+ name: str,
225
+ ) -> None:
226
+ """Fetch the current automated actions configmap."""
227
+ item = oc.get(
228
+ namespace=instance.deployment.name,
229
+ kind="ConfigMap",
230
+ name=name,
231
+ allow_not_found=True,
232
+ )
233
+ if not item:
234
+ return
235
+ osr = OpenshiftResource(
236
+ body=item,
237
+ integration=QONTRACT_INTEGRATION,
238
+ integration_version=QONTRACT_INTEGRATION_VERSION,
239
+ )
240
+ ri.add_current(
241
+ cluster=instance.deployment.cluster.name,
242
+ namespace=instance.deployment.name,
243
+ resource_type=osr.kind,
244
+ name=osr.name,
245
+ value=osr,
246
+ )
247
+
248
+ @defer
249
+ def run(self, dry_run: bool, defer: Callable | None = None) -> None:
250
+ """Run the integration."""
251
+ gql_api = gql.get_api()
252
+ instances = list(self.get_automated_actions_instances(gql_api.query))
253
+ if not instances:
254
+ logging.debug("No instances found.")
255
+ return
256
+
257
+ oc_map = init_oc_map_from_namespaces(
258
+ namespaces=[instance.deployment for instance in instances],
259
+ secret_reader=self.secret_reader,
260
+ integration=QONTRACT_INTEGRATION,
261
+ use_jump_host=self.params.use_jump_host,
262
+ thread_pool_size=self.params.thread_pool_size,
263
+ internal=self.params.internal,
264
+ )
265
+ if defer:
266
+ defer(oc_map.cleanup)
267
+ ri = ResourceInventory()
268
+
269
+ for instance in instances:
270
+ users = self.compile_users(instance.permissions or [])
271
+ policies = self.compile_roles(instance.permissions or [])
272
+ if not users and not policies:
273
+ logging.info(
274
+ f"{instance.deployment.cluster.name}/{instance.deployment.name}: No enabled automated actions found. Skipping this instance!"
275
+ )
276
+ continue
277
+
278
+ self.build_desired_configmap(
279
+ ri=ri,
280
+ instance=instance,
281
+ name=self.params.configmap_name,
282
+ data=self.build_policy_file(users, policies),
283
+ )
284
+
285
+ oc = oc_map.get_cluster(instance.deployment.cluster.name)
286
+ if not oc.project_exists(instance.deployment.name):
287
+ logging.info(
288
+ f"{instance.deployment.cluster.name}/{instance.deployment.name}: Namespace does not exist (yet). Skipping this instance!"
289
+ )
290
+ continue
291
+
292
+ self.fetch_current_configmap(
293
+ ri=ri,
294
+ instance=instance,
295
+ oc=oc,
296
+ name=self.params.configmap_name,
297
+ )
298
+
299
+ ob.publish_metrics(ri, QONTRACT_INTEGRATION)
300
+ ob.realize_data(dry_run, oc_map, ri, self.params.thread_pool_size)
reconcile/cli.py CHANGED
@@ -3815,6 +3815,29 @@ def external_resources_secrets_sync(
3815
3815
  )
3816
3816
 
3817
3817
 
3818
+ @integration.command(short_help="Deploy the Automated Actions Config")
3819
+ @threaded()
3820
+ @internal()
3821
+ @use_jump_host()
3822
+ @click.pass_context
3823
+ def automated_actions_config(ctx, thread_pool_size, internal, use_jump_host):
3824
+ from reconcile.automated_actions.config.integration import (
3825
+ AutomatedActionsConfigIntegration,
3826
+ AutomatedActionsConfigIntegrationParams,
3827
+ )
3828
+
3829
+ run_class_integration(
3830
+ integration=AutomatedActionsConfigIntegration(
3831
+ AutomatedActionsConfigIntegrationParams(
3832
+ thread_pool_size=thread_pool_size,
3833
+ use_jump_host=use_jump_host,
3834
+ internal=internal,
3835
+ )
3836
+ ),
3837
+ ctx=ctx.obj,
3838
+ )
3839
+
3840
+
3818
3841
  def get_integration_cli_meta() -> dict[str, IntegrationMeta]:
3819
3842
  """
3820
3843
  returns all integrations known to cli.py via click introspection
@@ -0,0 +1,204 @@
1
+ """
2
+ Generated by qenerate plugin=pydantic_v1. DO NOT MODIFY MANUALLY!
3
+ """
4
+ from collections.abc import Callable # noqa: F401 # pylint: disable=W0611
5
+ from datetime import datetime # noqa: F401 # pylint: disable=W0611
6
+ from enum import Enum # noqa: F401 # pylint: disable=W0611
7
+ from typing import ( # noqa: F401 # pylint: disable=W0611
8
+ Any,
9
+ Optional,
10
+ Union,
11
+ )
12
+
13
+ from pydantic import ( # noqa: F401 # pylint: disable=W0611
14
+ BaseModel,
15
+ Extra,
16
+ Field,
17
+ Json,
18
+ )
19
+
20
+ from reconcile.gql_definitions.fragments.oc_connection_cluster import OcConnectionCluster
21
+
22
+
23
+ DEFINITION = """
24
+ fragment CommonJumphostFields on ClusterJumpHost_v1 {
25
+ hostname
26
+ knownHosts
27
+ user
28
+ port
29
+ remotePort
30
+ identity {
31
+ ... VaultSecret
32
+ }
33
+ }
34
+
35
+ fragment OcConnectionCluster on Cluster_v1 {
36
+ name
37
+ serverUrl
38
+ internal
39
+ insecureSkipTLSVerify
40
+ jumpHost {
41
+ ...CommonJumphostFields
42
+ }
43
+ automationToken {
44
+ ...VaultSecret
45
+ }
46
+ clusterAdminAutomationToken {
47
+ ...VaultSecret
48
+ }
49
+ disable {
50
+ integrations
51
+ }
52
+ }
53
+
54
+ fragment VaultSecret on VaultSecret_v1 {
55
+ path
56
+ field
57
+ version
58
+ format
59
+ }
60
+
61
+ query AutomatedActionsInstances {
62
+ automated_actions_instances_v1 {
63
+ name
64
+ deployment {
65
+ name
66
+ clusterAdmin
67
+ delete
68
+ cluster {
69
+ ...OcConnectionCluster
70
+ }
71
+ }
72
+ permissions {
73
+ roles {
74
+ name
75
+ users {
76
+ org_username
77
+ }
78
+ bots {
79
+ org_username
80
+ }
81
+ expirationDate
82
+ }
83
+
84
+ action {
85
+ operationId
86
+ retries
87
+ maxOps
88
+ }
89
+
90
+ arguments {
91
+ type
92
+ ... on AutomatedActionArgumentOpenshift_v1 {
93
+ namespace {
94
+ name
95
+ delete
96
+ cluster {
97
+ name
98
+ disable {
99
+ integrations
100
+ }
101
+ }
102
+ }
103
+ kind_pattern
104
+ name_pattern
105
+ }
106
+ }
107
+ }
108
+ }
109
+ }
110
+ """
111
+
112
+
113
+ class ConfiguredBaseModel(BaseModel):
114
+ class Config:
115
+ smart_union=True
116
+ extra=Extra.forbid
117
+
118
+
119
+ class NamespaceV1(ConfiguredBaseModel):
120
+ name: str = Field(..., alias="name")
121
+ cluster_admin: Optional[bool] = Field(..., alias="clusterAdmin")
122
+ delete: Optional[bool] = Field(..., alias="delete")
123
+ cluster: OcConnectionCluster = Field(..., alias="cluster")
124
+
125
+
126
+ class UserV1(ConfiguredBaseModel):
127
+ org_username: str = Field(..., alias="org_username")
128
+
129
+
130
+ class BotV1(ConfiguredBaseModel):
131
+ org_username: Optional[str] = Field(..., alias="org_username")
132
+
133
+
134
+ class RoleV1(ConfiguredBaseModel):
135
+ name: str = Field(..., alias="name")
136
+ users: list[UserV1] = Field(..., alias="users")
137
+ bots: list[BotV1] = Field(..., alias="bots")
138
+ expiration_date: Optional[str] = Field(..., alias="expirationDate")
139
+
140
+
141
+ class AutomatedActionV1(ConfiguredBaseModel):
142
+ operation_id: str = Field(..., alias="operationId")
143
+ retries: int = Field(..., alias="retries")
144
+ max_ops: int = Field(..., alias="maxOps")
145
+
146
+
147
+ class AutomatedActionArgumentV1(ConfiguredBaseModel):
148
+ q_type: str = Field(..., alias="type")
149
+
150
+
151
+ class DisableClusterAutomationsV1(ConfiguredBaseModel):
152
+ integrations: Optional[list[str]] = Field(..., alias="integrations")
153
+
154
+
155
+ class AutomatedActionArgumentOpenshiftV1_NamespaceV1_ClusterV1(ConfiguredBaseModel):
156
+ name: str = Field(..., alias="name")
157
+ disable: Optional[DisableClusterAutomationsV1] = Field(..., alias="disable")
158
+
159
+
160
+ class AutomatedActionArgumentOpenshiftV1_NamespaceV1(ConfiguredBaseModel):
161
+ name: str = Field(..., alias="name")
162
+ delete: Optional[bool] = Field(..., alias="delete")
163
+ cluster: AutomatedActionArgumentOpenshiftV1_NamespaceV1_ClusterV1 = Field(..., alias="cluster")
164
+
165
+
166
+ class AutomatedActionArgumentOpenshiftV1(AutomatedActionArgumentV1):
167
+ namespace: AutomatedActionArgumentOpenshiftV1_NamespaceV1 = Field(..., alias="namespace")
168
+ kind_pattern: str = Field(..., alias="kind_pattern")
169
+ name_pattern: str = Field(..., alias="name_pattern")
170
+
171
+
172
+ class PermissionAutomatedActionsV1(ConfiguredBaseModel):
173
+ roles: Optional[list[RoleV1]] = Field(..., alias="roles")
174
+ action: AutomatedActionV1 = Field(..., alias="action")
175
+ arguments: Optional[list[Union[AutomatedActionArgumentOpenshiftV1, AutomatedActionArgumentV1]]] = Field(..., alias="arguments")
176
+
177
+
178
+ class AutomatedActionsInstanceV1(ConfiguredBaseModel):
179
+ name: str = Field(..., alias="name")
180
+ deployment: NamespaceV1 = Field(..., alias="deployment")
181
+ permissions: Optional[list[PermissionAutomatedActionsV1]] = Field(..., alias="permissions")
182
+
183
+
184
+ class AutomatedActionsInstancesQueryData(ConfiguredBaseModel):
185
+ automated_actions_instances_v1: Optional[list[AutomatedActionsInstanceV1]] = Field(..., alias="automated_actions_instances_v1")
186
+
187
+
188
+ def query(query_func: Callable, **kwargs: Any) -> AutomatedActionsInstancesQueryData:
189
+ """
190
+ This is a convenience function which queries and parses the data into
191
+ concrete types. It should be compatible with most GQL clients.
192
+ You do not have to use it to consume the generated data classes.
193
+ Alternatively, you can also mime and alternate the behavior
194
+ of this function in the caller.
195
+
196
+ Parameters:
197
+ query_func (Callable): Function which queries your GQL Server
198
+ kwargs: optional arguments that will be passed to the query function
199
+
200
+ Returns:
201
+ AutomatedActionsInstancesQueryData: queried data parsed into generated classes
202
+ """
203
+ raw_data: dict[Any, Any] = query_func(DEFINITION, **kwargs)
204
+ return AutomatedActionsInstancesQueryData(**raw_data)