qontract-reconcile 0.10.1rc879__py3-none-any.whl → 0.10.1rc894__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.1rc879.dist-info → qontract_reconcile-0.10.1rc894.dist-info}/METADATA +1 -1
- {qontract_reconcile-0.10.1rc879.dist-info → qontract_reconcile-0.10.1rc894.dist-info}/RECORD +291 -284
- reconcile/acs_rbac.py +1 -2
- reconcile/aus/advanced_upgrade_service.py +14 -14
- reconcile/aus/aus_label_source.py +1 -2
- reconcile/aus/base.py +23 -26
- reconcile/aus/cluster_version_data.py +4 -4
- reconcile/aus/models.py +2 -3
- reconcile/aus/version_gate_approver.py +2 -6
- reconcile/aus/version_gates/__init__.py +1 -3
- reconcile/aus/version_gates/sts_version_gate_handler.py +2 -3
- reconcile/aws_account_manager/integration.py +9 -14
- reconcile/aws_account_manager/reconciler.py +51 -1
- reconcile/aws_account_manager/utils.py +3 -0
- reconcile/aws_ami_cleanup/integration.py +3 -4
- reconcile/aws_iam_password_reset.py +2 -5
- reconcile/aws_version_sync/integration.py +2 -2
- reconcile/blackbox_exporter_endpoint_monitoring.py +2 -5
- reconcile/change_owners/approver.py +4 -5
- reconcile/change_owners/bundle.py +20 -22
- reconcile/change_owners/change_types.py +23 -24
- reconcile/change_owners/changes.py +13 -16
- reconcile/change_owners/decision.py +2 -5
- reconcile/change_owners/diff.py +11 -15
- reconcile/change_owners/self_service_roles.py +1 -2
- reconcile/change_owners/tester.py +7 -10
- reconcile/checkpoint.py +2 -5
- reconcile/cli.py +26 -12
- reconcile/closedbox_endpoint_monitoring_base.py +8 -11
- reconcile/cluster_deployment_mapper.py +2 -5
- reconcile/cna/assets/asset.py +4 -7
- reconcile/cna/assets/null.py +2 -5
- reconcile/cna/integration.py +2 -3
- reconcile/cna/state.py +2 -5
- reconcile/dashdotdb_base.py +8 -11
- reconcile/dashdotdb_cso.py +3 -6
- reconcile/dashdotdb_dora.py +10 -14
- reconcile/dashdotdb_dvo.py +10 -13
- reconcile/dashdotdb_slo.py +5 -8
- reconcile/database_access_manager.py +5 -6
- reconcile/dynatrace_token_provider/integration.py +3 -6
- reconcile/dynatrace_token_provider/integration_v2.py +20 -0
- reconcile/dynatrace_token_provider/meta.py +1 -0
- reconcile/external_resources/integration.py +1 -1
- reconcile/external_resources/manager.py +4 -4
- reconcile/external_resources/model.py +3 -3
- reconcile/external_resources/secrets_sync.py +5 -5
- reconcile/external_resources/state.py +5 -5
- reconcile/gabi_authorized_users.py +3 -6
- reconcile/gcr_mirror.py +1 -1
- reconcile/github_org.py +1 -3
- reconcile/github_repo_invites.py +2 -5
- reconcile/gitlab_housekeeping.py +7 -11
- reconcile/gitlab_labeler.py +1 -2
- reconcile/gitlab_members.py +2 -5
- reconcile/gitlab_permissions.py +1 -3
- reconcile/glitchtip/integration.py +5 -8
- reconcile/glitchtip_project_alerts/integration.py +57 -33
- reconcile/glitchtip_project_dsn/integration.py +8 -11
- reconcile/gql_definitions/aws_account_manager/aws_accounts.py +6 -0
- reconcile/gql_definitions/fragments/aws_account_managed.py +8 -0
- reconcile/gql_definitions/glitchtip/glitchtip_project.py +4 -4
- reconcile/gql_definitions/glitchtip_project_alerts/glitchtip_project.py +27 -7
- reconcile/integrations_manager.py +5 -8
- reconcile/jenkins/types.py +5 -6
- reconcile/jenkins_job_builder.py +9 -12
- reconcile/jenkins_roles.py +1 -1
- reconcile/jira_watcher.py +2 -2
- reconcile/ldap_groups/integration.py +2 -5
- reconcile/ocm/types.py +21 -26
- reconcile/ocm_addons_upgrade_tests_trigger.py +3 -6
- reconcile/ocm_clusters.py +8 -8
- reconcile/ocm_internal_notifications/integration.py +1 -2
- reconcile/ocm_labels/integration.py +2 -5
- reconcile/ocm_machine_pools.py +11 -15
- reconcile/ocm_upgrade_scheduler_org_updater.py +2 -5
- reconcile/openshift_base.py +29 -30
- reconcile/openshift_groups.py +15 -20
- reconcile/openshift_namespace_labels.py +8 -14
- reconcile/openshift_namespaces.py +5 -8
- reconcile/openshift_network_policies.py +2 -4
- reconcile/openshift_resources_base.py +19 -29
- reconcile/openshift_saas_deploy.py +9 -10
- reconcile/openshift_saas_deploy_change_tester.py +7 -10
- reconcile/openshift_saas_deploy_trigger_base.py +4 -7
- reconcile/openshift_saas_deploy_trigger_cleaner.py +5 -8
- reconcile/openshift_saas_deploy_trigger_configs.py +1 -2
- reconcile/openshift_saas_deploy_trigger_images.py +1 -2
- reconcile/openshift_saas_deploy_trigger_moving_commits.py +1 -2
- reconcile/openshift_saas_deploy_trigger_upstream_jobs.py +1 -2
- reconcile/openshift_tekton_resources.py +7 -11
- reconcile/openshift_upgrade_watcher.py +10 -13
- reconcile/openshift_users.py +8 -11
- reconcile/oum/base.py +3 -4
- reconcile/oum/labelset.py +1 -2
- reconcile/oum/metrics.py +2 -2
- reconcile/oum/models.py +1 -2
- reconcile/oum/standalone.py +2 -3
- reconcile/prometheus_rules_tester/integration.py +6 -9
- reconcile/quay_membership.py +1 -2
- reconcile/quay_mirror.py +12 -13
- reconcile/quay_mirror_org.py +10 -10
- reconcile/queries.py +4 -7
- reconcile/resource_scraper.py +3 -4
- reconcile/rhidp/common.py +2 -2
- reconcile/saas_auto_promotions_manager/integration.py +5 -6
- reconcile/saas_auto_promotions_manager/merge_request_manager/batcher.py +1 -2
- reconcile/saas_auto_promotions_manager/publisher.py +5 -6
- reconcile/saas_auto_promotions_manager/subscriber.py +36 -15
- reconcile/saas_auto_promotions_manager/utils/saas_files_inventory.py +8 -0
- reconcile/saas_file_validator.py +2 -5
- reconcile/signalfx_endpoint_monitoring.py +2 -5
- reconcile/skupper_network/integration.py +3 -6
- reconcile/skupper_network/models.py +3 -5
- reconcile/slack_base.py +4 -7
- reconcile/slack_usergroups.py +15 -17
- reconcile/sql_query.py +5 -9
- reconcile/status_board.py +4 -5
- reconcile/statuspage/atlassian.py +14 -15
- reconcile/statuspage/integrations/maintenances.py +3 -3
- reconcile/statuspage/page.py +8 -8
- reconcile/statuspage/state.py +4 -5
- reconcile/statuspage/status.py +7 -8
- reconcile/templating/lib/rendering.py +8 -8
- reconcile/templating/renderer.py +10 -11
- reconcile/templating/validator.py +4 -4
- reconcile/terraform_aws_route53.py +3 -6
- reconcile/terraform_cloudflare_dns.py +9 -12
- reconcile/terraform_cloudflare_resources.py +9 -11
- reconcile/terraform_cloudflare_users.py +8 -11
- reconcile/terraform_init/integration.py +2 -2
- reconcile/terraform_repo.py +11 -14
- reconcile/terraform_resources.py +20 -21
- reconcile/terraform_tgw_attachments.py +32 -36
- reconcile/terraform_users.py +6 -7
- reconcile/terraform_vpc_resources/integration.py +6 -6
- reconcile/test/conftest.py +7 -10
- reconcile/test/fixtures.py +1 -1
- reconcile/test/saas_auto_promotions_manager/conftest.py +3 -2
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/conftest.py +2 -2
- reconcile/test/test_database_access_manager.py +3 -6
- reconcile/test/test_gitlab_labeler.py +2 -5
- reconcile/test/test_jump_host.py +5 -8
- reconcile/test/test_ocm_machine_pools.py +1 -4
- reconcile/test/test_openshift_base.py +3 -6
- reconcile/test/test_openshift_cluster_bots.py +5 -5
- reconcile/test/test_openshift_namespace_labels.py +2 -3
- reconcile/test/test_openshift_saas_deploy_trigger_cleaner.py +2 -2
- reconcile/test/test_saasherder.py +9 -12
- reconcile/test/test_slack_base.py +4 -6
- reconcile/test/test_status_board.py +4 -7
- reconcile/test/test_terraform_tgw_attachments.py +14 -20
- reconcile/typed_queries/alerting_services_settings.py +1 -2
- reconcile/typed_queries/app_interface_custom_messages.py +2 -3
- reconcile/typed_queries/app_interface_deadmanssnitch_settings.py +1 -3
- reconcile/typed_queries/app_interface_repo_url.py +1 -2
- reconcile/typed_queries/app_interface_state_settings.py +1 -3
- reconcile/typed_queries/app_interface_vault_settings.py +1 -2
- reconcile/typed_queries/aws_vpc_requests.py +1 -3
- reconcile/typed_queries/aws_vpcs.py +1 -3
- reconcile/typed_queries/clusters.py +2 -4
- reconcile/typed_queries/clusters_minimal.py +1 -3
- reconcile/typed_queries/clusters_with_dms.py +1 -3
- reconcile/typed_queries/dynatrace_environments.py +14 -0
- reconcile/typed_queries/external_resources.py +3 -4
- reconcile/typed_queries/pagerduty_instances.py +1 -2
- reconcile/typed_queries/repos.py +2 -3
- reconcile/typed_queries/reserved_networks.py +1 -3
- reconcile/typed_queries/saas_files.py +49 -59
- reconcile/typed_queries/slo_documents.py +1 -3
- reconcile/typed_queries/status_board.py +3 -7
- reconcile/typed_queries/tekton_pipeline_providers.py +1 -2
- reconcile/typed_queries/terraform_namespaces.py +1 -2
- reconcile/typed_queries/terraform_tgw_attachments/aws_accounts.py +1 -3
- reconcile/utils/acs/base.py +2 -3
- reconcile/utils/acs/notifiers.py +3 -3
- reconcile/utils/acs/policies.py +3 -3
- reconcile/utils/aggregated_list.py +1 -1
- reconcile/utils/amtool.py +1 -2
- reconcile/utils/aws_api.py +28 -31
- reconcile/utils/aws_api_typed/account.py +23 -0
- reconcile/utils/aws_api_typed/api.py +20 -9
- reconcile/utils/binary.py +1 -3
- reconcile/utils/clusterhealth/providerbase.py +1 -2
- reconcile/utils/clusterhealth/telemeter.py +2 -2
- reconcile/utils/deadmanssnitch_api.py +1 -2
- reconcile/utils/disabled_integrations.py +4 -6
- reconcile/utils/environ.py +1 -1
- reconcile/utils/expiration.py +3 -7
- reconcile/utils/external_resource_spec.py +3 -4
- reconcile/utils/external_resources.py +4 -7
- reconcile/utils/filtering.py +1 -2
- reconcile/utils/git.py +3 -9
- reconcile/utils/git_secrets.py +5 -5
- reconcile/utils/github_api.py +5 -9
- reconcile/utils/gitlab_api.py +2 -3
- reconcile/utils/glitchtip/client.py +2 -4
- reconcile/utils/glitchtip/models.py +8 -11
- reconcile/utils/gql.py +26 -35
- reconcile/utils/grouping.py +1 -3
- reconcile/utils/imap_client.py +2 -5
- reconcile/utils/internal_groups/client.py +1 -2
- reconcile/utils/internal_groups/models.py +8 -9
- reconcile/utils/jenkins_api.py +4 -4
- reconcile/utils/jinja2/extensions.py +1 -1
- reconcile/utils/jinja2/filters.py +4 -4
- reconcile/utils/jinja2/utils.py +16 -16
- reconcile/utils/jira_client.py +10 -11
- reconcile/utils/jjb_client.py +14 -17
- reconcile/utils/jobcontroller/controller.py +5 -5
- reconcile/utils/jobcontroller/models.py +2 -2
- reconcile/utils/jsonpath.py +4 -5
- reconcile/utils/jump_host.py +7 -8
- reconcile/utils/keycloak.py +3 -7
- reconcile/utils/ldap_client.py +2 -3
- reconcile/utils/lean_terraform_client.py +13 -17
- reconcile/utils/membershipsources/app_interface_resolver.py +1 -1
- reconcile/utils/membershipsources/models.py +19 -22
- reconcile/utils/metrics.py +13 -15
- reconcile/utils/mr/base.py +7 -11
- reconcile/utils/mr/glitchtip_access_reporter.py +2 -2
- reconcile/utils/mr/notificator.py +1 -2
- reconcile/utils/oc.py +38 -38
- reconcile/utils/oc_connection_parameters.py +24 -25
- reconcile/utils/oc_filters.py +2 -3
- reconcile/utils/oc_map.py +9 -15
- reconcile/utils/ocm/addons.py +7 -10
- reconcile/utils/ocm/base.py +38 -39
- reconcile/utils/ocm/clusters.py +6 -9
- reconcile/utils/ocm/label_sources.py +1 -2
- reconcile/utils/ocm/labels.py +3 -6
- reconcile/utils/ocm/ocm.py +11 -14
- reconcile/utils/ocm/products.py +1 -3
- reconcile/utils/ocm/search_filters.py +16 -17
- reconcile/utils/ocm/service_log.py +2 -3
- reconcile/utils/ocm/sre_capability_labels.py +4 -8
- reconcile/utils/ocm/subscriptions.py +1 -3
- reconcile/utils/ocm/syncsets.py +2 -4
- reconcile/utils/ocm/upgrades.py +5 -9
- reconcile/utils/ocm_base_client.py +13 -16
- reconcile/utils/openshift_resource.py +5 -11
- reconcile/utils/output.py +2 -3
- reconcile/utils/pagerduty_api.py +4 -5
- reconcile/utils/prometheus.py +2 -2
- reconcile/utils/promotion_state.py +4 -5
- reconcile/utils/promtool.py +2 -8
- reconcile/utils/quay_api.py +12 -22
- reconcile/utils/raw_github_api.py +3 -5
- reconcile/utils/rosa/rosa_cli.py +6 -6
- reconcile/utils/rosa/session.py +6 -7
- reconcile/utils/runtime/desired_state_diff.py +3 -8
- reconcile/utils/runtime/environment.py +4 -7
- reconcile/utils/runtime/integration.py +4 -4
- reconcile/utils/runtime/meta.py +1 -2
- reconcile/utils/runtime/runner.py +7 -10
- reconcile/utils/runtime/sharding.py +22 -27
- reconcile/utils/saasherder/interfaces.py +63 -69
- reconcile/utils/saasherder/models.py +30 -35
- reconcile/utils/saasherder/saasherder.py +39 -54
- reconcile/utils/secret_reader.py +17 -19
- reconcile/utils/slack_api.py +15 -17
- reconcile/utils/smtp_client.py +1 -2
- reconcile/utils/sqs_gateway.py +1 -3
- reconcile/utils/state.py +1 -2
- reconcile/utils/terraform/config_client.py +4 -5
- reconcile/utils/terraform_client.py +12 -8
- reconcile/utils/terrascript/cloudflare_client.py +4 -10
- reconcile/utils/terrascript/cloudflare_resources.py +10 -13
- reconcile/utils/terrascript/models.py +2 -3
- reconcile/utils/terrascript/resources.py +1 -2
- reconcile/utils/terrascript_aws_client.py +50 -38
- reconcile/utils/unleash/client.py +4 -7
- reconcile/utils/unleash/server.py +2 -2
- reconcile/utils/vault.py +8 -11
- reconcile/utils/vaultsecretref.py +2 -3
- reconcile/utils/vcs.py +7 -8
- reconcile/vault_replication.py +4 -8
- reconcile/vpc_peerings_validator.py +4 -9
- release/version.py +6 -7
- tools/app_interface_reporter.py +2 -2
- tools/cli_commands/gpg_encrypt.py +3 -6
- tools/cli_commands/systems_and_tools.py +4 -7
- tools/qontract_cli.py +105 -17
- tools/saas_promotion_state/__init__.py +0 -0
- tools/saas_promotion_state/saas_promotion_state.py +105 -0
- tools/template_validation.py +1 -1
- tools/test/conftest.py +45 -6
- tools/test/test_saas_promotion_state.py +187 -0
- {qontract_reconcile-0.10.1rc879.dist-info → qontract_reconcile-0.10.1rc894.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.1rc879.dist-info → qontract_reconcile-0.10.1rc894.dist-info}/entry_points.txt +0 -0
- {qontract_reconcile-0.10.1rc879.dist-info → qontract_reconcile-0.10.1rc894.dist-info}/top_level.txt +0 -0
reconcile/utils/oc.py
CHANGED
@@ -17,7 +17,7 @@ from functools import wraps
|
|
17
17
|
from io import TextIOWrapper
|
18
18
|
from subprocess import Popen
|
19
19
|
from threading import Lock
|
20
|
-
from typing import Any
|
20
|
+
from typing import Any
|
21
21
|
|
22
22
|
import urllib3
|
23
23
|
from kubernetes.client import ( # type: ignore[attr-defined]
|
@@ -127,6 +127,10 @@ class JobNotRunningError(Exception):
|
|
127
127
|
pass
|
128
128
|
|
129
129
|
|
130
|
+
class RequestEntityTooLargeError(Exception):
|
131
|
+
pass
|
132
|
+
|
133
|
+
|
130
134
|
class OCDecorators:
|
131
135
|
@classmethod
|
132
136
|
def process_reconcile_time(cls, function):
|
@@ -153,7 +157,7 @@ class OCDecorators:
|
|
153
157
|
@wraps(function)
|
154
158
|
def wrapper(*args, **kwargs):
|
155
159
|
result = function(*args, **kwargs)
|
156
|
-
msg = result[:-1] if isinstance(result,
|
160
|
+
msg = result[:-1] if isinstance(result, list | tuple) else result
|
157
161
|
|
158
162
|
if not isinstance(msg, OCProcessReconcileTimeDecoratorMsg):
|
159
163
|
return result
|
@@ -207,7 +211,7 @@ class OCProcessReconcileTimeDecoratorMsg:
|
|
207
211
|
self,
|
208
212
|
namespace: str,
|
209
213
|
resource: OR,
|
210
|
-
server:
|
214
|
+
server: str | None,
|
211
215
|
slow_oc_reconcile_threshold: float,
|
212
216
|
is_log_slow_oc_reconcile: bool,
|
213
217
|
):
|
@@ -251,23 +255,23 @@ class OCCliApiResource:
|
|
251
255
|
@property
|
252
256
|
def group_version(self):
|
253
257
|
if self.group:
|
254
|
-
return "{}/{
|
258
|
+
return f"{self.group}/{self.api_version}"
|
255
259
|
return self.api_version
|
256
260
|
|
257
261
|
|
258
262
|
class OCCli: # pylint: disable=too-many-public-methods
|
259
263
|
def __init__(
|
260
264
|
self,
|
261
|
-
cluster_name:
|
262
|
-
server:
|
263
|
-
token:
|
264
|
-
jh:
|
265
|
-
settings:
|
265
|
+
cluster_name: str | None,
|
266
|
+
server: str | None,
|
267
|
+
token: str | None,
|
268
|
+
jh: Mapping[Any, Any] | None = None,
|
269
|
+
settings: Mapping[Any, Any] | None = None,
|
266
270
|
init_projects: bool = False,
|
267
271
|
init_api_resources: bool = False,
|
268
272
|
local: bool = False,
|
269
273
|
insecure_skip_tls_verify: bool = False,
|
270
|
-
connection_parameters:
|
274
|
+
connection_parameters: OCConnectionParameters | None = None,
|
271
275
|
):
|
272
276
|
"""
|
273
277
|
As of now we have to conform with 2 ways to initialize this client:
|
@@ -306,10 +310,10 @@ class OCCli: # pylint: disable=too-many-public-methods
|
|
306
310
|
def _init_old_without_types(
|
307
311
|
self,
|
308
312
|
cluster_name: str,
|
309
|
-
server:
|
310
|
-
token:
|
311
|
-
jh:
|
312
|
-
settings:
|
313
|
+
server: str | None,
|
314
|
+
token: str | None,
|
315
|
+
jh: Mapping[Any, Any] | None = None,
|
316
|
+
settings: Mapping[Any, Any] | None = None,
|
313
317
|
init_projects: bool = False,
|
314
318
|
init_api_resources: bool = False,
|
315
319
|
local: bool = False,
|
@@ -474,9 +478,7 @@ class OCCli: # pylint: disable=too-many-public-methods
|
|
474
478
|
cmd.extend(["-n", namespace])
|
475
479
|
|
476
480
|
if "labels" in kwargs:
|
477
|
-
labels_list = [
|
478
|
-
"{}={}".format(k, v) for k, v in kwargs.get("labels").items()
|
479
|
-
]
|
481
|
+
labels_list = [f"{k}={v}" for k, v in kwargs.get("labels").items()]
|
480
482
|
|
481
483
|
cmd.append("-l")
|
482
484
|
cmd.append(",".join(labels_list))
|
@@ -781,7 +783,7 @@ class OCCli: # pylint: disable=too-many-public-methods
|
|
781
783
|
def get_service_account_username(user):
|
782
784
|
namespace = user.split("/")[0]
|
783
785
|
name = user.split("/")[1]
|
784
|
-
return "system:serviceaccount:{}:{}"
|
786
|
+
return f"system:serviceaccount:{namespace}:{name}"
|
785
787
|
|
786
788
|
def get_owned_pods(self, namespace, resource):
|
787
789
|
pods = self.get(namespace, "Pod")["items"]
|
@@ -1118,6 +1120,8 @@ class OCCli: # pylint: disable=too-many-public-methods
|
|
1118
1120
|
raise StatefulSetUpdateForbidden(f"[{self.server}]: {err}")
|
1119
1121
|
if "the object has been modified" in err:
|
1120
1122
|
raise ObjectHasBeenModifiedError(f"[{self.server}]: {err}")
|
1123
|
+
if "Request entity too large" in err:
|
1124
|
+
raise RequestEntityTooLargeError(f"[{self.server}]: {err}")
|
1121
1125
|
if not (allow_not_found and "NotFound" in err):
|
1122
1126
|
raise StatusCodeError(f"[{self.server}]: {err}")
|
1123
1127
|
|
@@ -1216,15 +1220,15 @@ REQUEST_TIMEOUT = 60
|
|
1216
1220
|
class OCNative(OCCli):
|
1217
1221
|
def __init__(
|
1218
1222
|
self,
|
1219
|
-
cluster_name:
|
1220
|
-
server:
|
1221
|
-
token:
|
1222
|
-
jh:
|
1223
|
-
settings:
|
1223
|
+
cluster_name: str | None,
|
1224
|
+
server: str | None,
|
1225
|
+
token: str | None,
|
1226
|
+
jh: Mapping[Any, Any] | None = None,
|
1227
|
+
settings: Mapping[Any, Any] | None = None,
|
1224
1228
|
init_projects: bool = False,
|
1225
1229
|
local: bool = False,
|
1226
1230
|
insecure_skip_tls_verify: bool = False,
|
1227
|
-
connection_parameters:
|
1231
|
+
connection_parameters: OCConnectionParameters | None = None,
|
1228
1232
|
):
|
1229
1233
|
super().__init__(
|
1230
1234
|
cluster_name,
|
@@ -1329,9 +1333,7 @@ class OCNative(OCCli):
|
|
1329
1333
|
|
1330
1334
|
labels = ""
|
1331
1335
|
if "labels" in kwargs:
|
1332
|
-
labels_list = [
|
1333
|
-
"{}={}".format(k, v) for k, v in kwargs.get("labels").items()
|
1334
|
-
]
|
1336
|
+
labels_list = [f"{k}={v}" for k, v in kwargs.get("labels").items()]
|
1335
1337
|
|
1336
1338
|
labels = ",".join(labels_list)
|
1337
1339
|
|
@@ -1389,7 +1391,7 @@ class OCNative(OCCli):
|
|
1389
1391
|
raise StatusCodeError(f"[{self.server}]: {e}")
|
1390
1392
|
|
1391
1393
|
|
1392
|
-
OCClient =
|
1394
|
+
OCClient = OCNative | OCCli
|
1393
1395
|
|
1394
1396
|
|
1395
1397
|
class OCLocal(OCCli):
|
@@ -1417,16 +1419,16 @@ class OC:
|
|
1417
1419
|
|
1418
1420
|
def __new__(
|
1419
1421
|
cls,
|
1420
|
-
cluster_name:
|
1421
|
-
server:
|
1422
|
-
token:
|
1423
|
-
jh:
|
1424
|
-
settings:
|
1422
|
+
cluster_name: str | None = None,
|
1423
|
+
server: str | None = None,
|
1424
|
+
token: str | None = None,
|
1425
|
+
jh: Mapping[Any, Any] | None = None,
|
1426
|
+
settings: Mapping[Any, Any] | None = None,
|
1425
1427
|
init_projects: bool = False,
|
1426
1428
|
init_api_resources: bool = False,
|
1427
1429
|
local: bool = False,
|
1428
1430
|
insecure_skip_tls_verify: bool = False,
|
1429
|
-
connection_parameters:
|
1431
|
+
connection_parameters: OCConnectionParameters | None = None,
|
1430
1432
|
):
|
1431
1433
|
use_native_env = os.environ.get("USE_NATIVE_CLIENT", "")
|
1432
1434
|
use_native = True
|
@@ -1859,7 +1861,5 @@ class OpenshiftLazyDiscoverer(LazyDiscoverer):
|
|
1859
1861
|
if len(results) == 1:
|
1860
1862
|
return results[0]
|
1861
1863
|
if not results:
|
1862
|
-
raise ResourceNotFoundError("No matches found for {}"
|
1863
|
-
raise ResourceNotUniqueError(
|
1864
|
-
"Multiple matches found for {}: {}".format(kwargs, results)
|
1865
|
-
)
|
1864
|
+
raise ResourceNotFoundError(f"No matches found for {kwargs}")
|
1865
|
+
raise ResourceNotUniqueError(f"Multiple matches found for {kwargs}: {results}")
|
@@ -4,7 +4,6 @@ import logging
|
|
4
4
|
from collections.abc import Iterable
|
5
5
|
from dataclasses import dataclass
|
6
6
|
from typing import (
|
7
|
-
Optional,
|
8
7
|
Protocol,
|
9
8
|
runtime_checkable,
|
10
9
|
)
|
@@ -23,13 +22,13 @@ class OCConnectionError(Exception):
|
|
23
22
|
|
24
23
|
|
25
24
|
class Disable(Protocol):
|
26
|
-
integrations:
|
25
|
+
integrations: list[str] | None
|
27
26
|
|
28
27
|
|
29
28
|
class Jumphost(Protocol):
|
30
29
|
hostname: str
|
31
|
-
port:
|
32
|
-
remote_port:
|
30
|
+
port: int | None
|
31
|
+
remote_port: int | None
|
33
32
|
known_hosts: str
|
34
33
|
user: str
|
35
34
|
|
@@ -41,24 +40,24 @@ class Jumphost(Protocol):
|
|
41
40
|
class Cluster(Protocol):
|
42
41
|
name: str
|
43
42
|
server_url: str
|
44
|
-
internal:
|
45
|
-
insecure_skip_tls_verify:
|
43
|
+
internal: bool | None
|
44
|
+
insecure_skip_tls_verify: bool | None
|
46
45
|
|
47
46
|
@property
|
48
|
-
def jump_host(self) ->
|
47
|
+
def jump_host(self) -> Jumphost | None: ...
|
49
48
|
|
50
49
|
@property
|
51
|
-
def automation_token(self) ->
|
50
|
+
def automation_token(self) -> HasSecret | None: ...
|
52
51
|
|
53
52
|
@property
|
54
|
-
def cluster_admin_automation_token(self) ->
|
53
|
+
def cluster_admin_automation_token(self) -> HasSecret | None: ...
|
55
54
|
|
56
55
|
@property
|
57
|
-
def disable(self) ->
|
56
|
+
def disable(self) -> Disable | None: ...
|
58
57
|
|
59
58
|
|
60
59
|
class Namespace(Protocol):
|
61
|
-
cluster_admin:
|
60
|
+
cluster_admin: bool | None
|
62
61
|
|
63
62
|
@property
|
64
63
|
def cluster(self) -> Cluster: ...
|
@@ -82,20 +81,20 @@ class OCConnectionParameters:
|
|
82
81
|
|
83
82
|
cluster_name: str
|
84
83
|
server_url: str
|
85
|
-
is_internal:
|
84
|
+
is_internal: bool | None
|
86
85
|
is_cluster_admin: bool
|
87
|
-
skip_tls_verify:
|
88
|
-
automation_token:
|
89
|
-
cluster_admin_automation_token:
|
86
|
+
skip_tls_verify: bool | None
|
87
|
+
automation_token: str | None
|
88
|
+
cluster_admin_automation_token: str | None
|
90
89
|
disabled_integrations: list[str]
|
91
|
-
jumphost_hostname:
|
92
|
-
jumphost_known_hosts:
|
93
|
-
jumphost_user:
|
94
|
-
jumphost_port:
|
95
|
-
jumphost_key:
|
96
|
-
jumphost_remote_port:
|
90
|
+
jumphost_hostname: str | None
|
91
|
+
jumphost_known_hosts: str | None
|
92
|
+
jumphost_user: str | None
|
93
|
+
jumphost_port: int | None
|
94
|
+
jumphost_key: str | None
|
95
|
+
jumphost_remote_port: int | None
|
97
96
|
# The local port is currently calculated and set outside of this class
|
98
|
-
jumphost_local_port:
|
97
|
+
jumphost_local_port: int | None
|
99
98
|
|
100
99
|
@staticmethod
|
101
100
|
def _get_token_verify_server_url(secret: ClusterSecret, cluster: Cluster) -> str:
|
@@ -112,7 +111,7 @@ class OCConnectionParameters:
|
|
112
111
|
@staticmethod
|
113
112
|
def _get_automation_token(
|
114
113
|
secret_reader: SecretReaderBase, secret: HasSecret, cluster: Cluster
|
115
|
-
) ->
|
114
|
+
) -> str | None:
|
116
115
|
secret_raw = secret_reader.read_all_secret(secret)
|
117
116
|
return OCConnectionParameters._get_token_verify_server_url(
|
118
117
|
ClusterSecret(
|
@@ -130,8 +129,8 @@ class OCConnectionParameters:
|
|
130
129
|
cluster_admin: bool,
|
131
130
|
use_jump_host: bool = True,
|
132
131
|
) -> OCConnectionParameters:
|
133
|
-
automation_token:
|
134
|
-
cluster_admin_automation_token:
|
132
|
+
automation_token: str | None = None
|
133
|
+
cluster_admin_automation_token: str | None = None
|
135
134
|
|
136
135
|
if cluster_admin:
|
137
136
|
if cluster.cluster_admin_automation_token:
|
reconcile/utils/oc_filters.py
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
from collections.abc import Iterable
|
2
2
|
from typing import (
|
3
|
-
Optional,
|
4
3
|
Protocol,
|
5
4
|
TypeVar,
|
6
5
|
)
|
@@ -34,8 +33,8 @@ def filter_namespaces_by_name(
|
|
34
33
|
|
35
34
|
def filter_namespaces_by_cluster_and_namespace(
|
36
35
|
namespaces: Iterable[NS],
|
37
|
-
cluster_names:
|
38
|
-
namespace_names:
|
36
|
+
cluster_names: Iterable[str] | None,
|
37
|
+
namespace_names: Iterable[str] | None,
|
39
38
|
) -> list[NS]:
|
40
39
|
"""
|
41
40
|
Filter namespaces by cluster and namespace name.
|
reconcile/utils/oc_map.py
CHANGED
@@ -1,10 +1,6 @@
|
|
1
1
|
import logging
|
2
2
|
from collections.abc import Iterable
|
3
3
|
from threading import Lock
|
4
|
-
from typing import (
|
5
|
-
Optional,
|
6
|
-
Union,
|
7
|
-
)
|
8
4
|
|
9
5
|
from sretoolbox.utils import threaded
|
10
6
|
|
@@ -41,15 +37,15 @@ class OCMap:
|
|
41
37
|
self,
|
42
38
|
connection_parameters: Iterable[OCConnectionParameters],
|
43
39
|
integration: str = "",
|
44
|
-
internal:
|
40
|
+
internal: bool | None = None,
|
45
41
|
use_jump_host: bool = True,
|
46
42
|
thread_pool_size: int = 1,
|
47
43
|
init_projects: bool = False,
|
48
44
|
init_api_resources: bool = False,
|
49
|
-
oc_cls:
|
45
|
+
oc_cls: type[OC] | None = None,
|
50
46
|
):
|
51
|
-
self._oc_map: dict[str,
|
52
|
-
self._privileged_oc_map: dict[str,
|
47
|
+
self._oc_map: dict[str, OCCli | OCLogMsg] = {}
|
48
|
+
self._privileged_oc_map: dict[str, OCCli | OCLogMsg] = {}
|
53
49
|
self._calling_integration = integration
|
54
50
|
self._internal = internal
|
55
51
|
self._use_jump_host = use_jump_host
|
@@ -126,7 +122,7 @@ class OCMap:
|
|
126
122
|
connection_parameters=connection_parameters
|
127
123
|
)
|
128
124
|
try:
|
129
|
-
oc_client:
|
125
|
+
oc_client: OCCli | OCLogMsg = self._oc_cls(
|
130
126
|
connection_parameters=connection_parameters,
|
131
127
|
init_projects=self._init_projects,
|
132
128
|
init_api_resources=self._init_api_resources,
|
@@ -142,9 +138,7 @@ class OCMap:
|
|
142
138
|
privileged,
|
143
139
|
)
|
144
140
|
|
145
|
-
def _set_oc(
|
146
|
-
self, cluster: str, value: Union[OCCli, OCLogMsg], privileged: bool
|
147
|
-
) -> None:
|
141
|
+
def _set_oc(self, cluster: str, value: OCCli | OCLogMsg, privileged: bool) -> None:
|
148
142
|
with self._lock:
|
149
143
|
if privileged:
|
150
144
|
self._privileged_oc_map[cluster] = value
|
@@ -160,7 +154,7 @@ class OCMap:
|
|
160
154
|
pass
|
161
155
|
return False
|
162
156
|
|
163
|
-
def get(self, cluster: str, privileged: bool = False) ->
|
157
|
+
def get(self, cluster: str, privileged: bool = False) -> OCCli | OCLogMsg:
|
164
158
|
cluster_map = self._privileged_oc_map if privileged else self._oc_map
|
165
159
|
return cluster_map.get(
|
166
160
|
cluster,
|
@@ -200,7 +194,7 @@ def init_oc_map_from_clusters(
|
|
200
194
|
clusters: Iterable[Cluster],
|
201
195
|
secret_reader: SecretReaderBase,
|
202
196
|
integration: str = "",
|
203
|
-
internal:
|
197
|
+
internal: bool | None = None,
|
204
198
|
use_jump_host: bool = True,
|
205
199
|
thread_pool_size: int = 1,
|
206
200
|
init_projects: bool = False,
|
@@ -231,7 +225,7 @@ def init_oc_map_from_namespaces(
|
|
231
225
|
namespaces: Iterable[Namespace],
|
232
226
|
secret_reader: SecretReaderBase,
|
233
227
|
integration: str = "",
|
234
|
-
internal:
|
228
|
+
internal: bool | None = None,
|
235
229
|
use_jump_host: bool = True,
|
236
230
|
thread_pool_size: int = 1,
|
237
231
|
init_projects: bool = False,
|
reconcile/utils/ocm/addons.py
CHANGED
@@ -1,7 +1,4 @@
|
|
1
|
-
from typing import
|
2
|
-
Any,
|
3
|
-
Optional,
|
4
|
-
)
|
1
|
+
from typing import Any
|
5
2
|
|
6
3
|
from reconcile.utils.ocm.base import (
|
7
4
|
OCMAddonInstallation,
|
@@ -26,7 +23,7 @@ class AddonService:
|
|
26
23
|
ocm_api: OCMBaseClient,
|
27
24
|
cluster_id: str,
|
28
25
|
addon_latest_versions: dict[str, str],
|
29
|
-
required_state:
|
26
|
+
required_state: str | None,
|
30
27
|
) -> list[OCMAddonInstallation]:
|
31
28
|
"""
|
32
29
|
Returns a list of Addons installed on a cluster
|
@@ -37,7 +34,7 @@ class AddonService:
|
|
37
34
|
:param required_state: only return addons with this state
|
38
35
|
"""
|
39
36
|
|
40
|
-
params:
|
37
|
+
params: dict[str, Any] | None = None
|
41
38
|
if required_state:
|
42
39
|
params = {"search": f"state='{required_state}'"}
|
43
40
|
|
@@ -58,7 +55,7 @@ class AddonService:
|
|
58
55
|
raise NotImplementedError()
|
59
56
|
|
60
57
|
def get_addon_upgrade_policies(
|
61
|
-
self, ocm_api: OCMBaseClient, cluster_id: str, addon_id:
|
58
|
+
self, ocm_api: OCMBaseClient, cluster_id: str, addon_id: str | None = None
|
62
59
|
) -> list[OCMAddonUpgradePolicy]:
|
63
60
|
raise NotImplementedError()
|
64
61
|
|
@@ -88,7 +85,7 @@ class AddonServiceV1(AddonService):
|
|
88
85
|
return "/api/clusters_mgmt/v1"
|
89
86
|
|
90
87
|
def get_addon_upgrade_policies(
|
91
|
-
self, ocm_api: OCMBaseClient, cluster_id: str, addon_id:
|
88
|
+
self, ocm_api: OCMBaseClient, cluster_id: str, addon_id: str | None = None
|
92
89
|
) -> list[OCMAddonUpgradePolicy]:
|
93
90
|
results: list[OCMAddonUpgradePolicy] = []
|
94
91
|
|
@@ -118,7 +115,7 @@ class AddonServiceV1(AddonService):
|
|
118
115
|
|
119
116
|
def _get_addon_upgrade_policy_state(
|
120
117
|
self, ocm_api: OCMBaseClient, cluster_id: str, addon_upgrade_policy_id: str
|
121
|
-
) ->
|
118
|
+
) -> str | None:
|
122
119
|
try:
|
123
120
|
state_data = ocm_api.get(
|
124
121
|
f"{self.addon_base_api_path()}/clusters/{cluster_id}/addon_upgrade_policies/{addon_upgrade_policy_id}/state"
|
@@ -171,7 +168,7 @@ class AddonServiceV2(AddonService):
|
|
171
168
|
return "/api/addons_mgmt/v1"
|
172
169
|
|
173
170
|
def get_addon_upgrade_policies(
|
174
|
-
self, ocm_api: OCMBaseClient, cluster_id: str, addon_id:
|
171
|
+
self, ocm_api: OCMBaseClient, cluster_id: str, addon_id: str | None = None
|
175
172
|
) -> list[OCMAddonUpgradePolicy]:
|
176
173
|
results: list[OCMAddonUpgradePolicy] = []
|
177
174
|
|
reconcile/utils/ocm/base.py
CHANGED
@@ -2,9 +2,8 @@ from __future__ import annotations
|
|
2
2
|
|
3
3
|
from collections.abc import Iterable
|
4
4
|
from datetime import datetime
|
5
|
-
from enum import Enum
|
5
|
+
from enum import Enum, StrEnum
|
6
6
|
from typing import (
|
7
|
-
Optional,
|
8
7
|
TypeVar,
|
9
8
|
)
|
10
9
|
|
@@ -22,8 +21,8 @@ CAPABILITY_MANAGE_CLUSTER_ADMIN = "capability.cluster.manage_cluster_admin"
|
|
22
21
|
|
23
22
|
|
24
23
|
class OCMCollectionLink(BaseModel):
|
25
|
-
kind:
|
26
|
-
href:
|
24
|
+
kind: str | None = None
|
25
|
+
href: str | None = None
|
27
26
|
|
28
27
|
|
29
28
|
class OCMModelLink(OCMCollectionLink):
|
@@ -76,7 +75,7 @@ class OCMClusterUser(BaseModel):
|
|
76
75
|
The id represents the user name.
|
77
76
|
"""
|
78
77
|
|
79
|
-
href:
|
78
|
+
href: str | None = None
|
80
79
|
kind: str = "User"
|
81
80
|
|
82
81
|
|
@@ -86,7 +85,7 @@ class OCMClusterUserList(BaseModel):
|
|
86
85
|
"""
|
87
86
|
|
88
87
|
kind: str = "UserList"
|
89
|
-
href:
|
88
|
+
href: str | None = None
|
90
89
|
items: list[OCMClusterUser]
|
91
90
|
|
92
91
|
|
@@ -96,8 +95,8 @@ class OCMClusterGroup(BaseModel):
|
|
96
95
|
"""
|
97
96
|
|
98
97
|
id: OCMClusterGroupId
|
99
|
-
href:
|
100
|
-
users:
|
98
|
+
href: str | None = None
|
99
|
+
users: OCMClusterUserList | None = None
|
101
100
|
|
102
101
|
def user_ids(self) -> set[str]:
|
103
102
|
"""
|
@@ -135,16 +134,16 @@ class OCMClusterAWSOperatorRole(BaseModel):
|
|
135
134
|
|
136
135
|
|
137
136
|
class OCMAWSSTS(OCMClusterFlag):
|
138
|
-
role_arn:
|
139
|
-
support_role_arn:
|
140
|
-
oidc_endpoint_url:
|
141
|
-
operator_iam_roles:
|
142
|
-
instance_iam_roles:
|
143
|
-
operator_role_prefix:
|
137
|
+
role_arn: str | None
|
138
|
+
support_role_arn: str | None
|
139
|
+
oidc_endpoint_url: str | None
|
140
|
+
operator_iam_roles: list[OCMClusterAWSOperatorRole] | None
|
141
|
+
instance_iam_roles: dict[str, str] | None
|
142
|
+
operator_role_prefix: str | None
|
144
143
|
|
145
144
|
|
146
145
|
class OCMClusterAWSSettings(BaseModel):
|
147
|
-
sts:
|
146
|
+
sts: OCMAWSSTS | None
|
148
147
|
|
149
148
|
@property
|
150
149
|
def sts_enabled(self) -> bool:
|
@@ -168,7 +167,7 @@ class OCMClusterAWSSettings(BaseModel):
|
|
168
167
|
return roles
|
169
168
|
|
170
169
|
@property
|
171
|
-
def account_role_prefix(self) ->
|
170
|
+
def account_role_prefix(self) -> str | None:
|
172
171
|
INSTALLER_ROLE_BASE_NAME = "-Installer-Role"
|
173
172
|
installer_role_arn = self.sts.role_arn if self.sts else None
|
174
173
|
if installer_role_arn and installer_role_arn.endswith(INSTALLER_ROLE_BASE_NAME):
|
@@ -231,19 +230,19 @@ class OCMCluster(BaseModel):
|
|
231
230
|
product: OCMModelLink
|
232
231
|
identity_providers: OCMCollectionLink
|
233
232
|
|
234
|
-
aws:
|
233
|
+
aws: OCMClusterAWSSettings | None
|
235
234
|
|
236
235
|
version: OCMClusterVersion
|
237
236
|
|
238
237
|
hypershift: OCMClusterFlag
|
239
238
|
|
240
|
-
console:
|
239
|
+
console: OCMClusterConsole | None
|
241
240
|
|
242
|
-
api:
|
241
|
+
api: OCMClusterAPI | None
|
243
242
|
|
244
|
-
dns:
|
243
|
+
dns: OCMClusterDns | None
|
245
244
|
|
246
|
-
external_configuration:
|
245
|
+
external_configuration: OCMExternalConfiguration | None
|
247
246
|
|
248
247
|
def minor_version(self) -> str:
|
249
248
|
version_info = parse_semver(self.version.raw_id)
|
@@ -275,15 +274,15 @@ class OCMCluster(BaseModel):
|
|
275
274
|
)
|
276
275
|
|
277
276
|
@property
|
278
|
-
def console_url(self) ->
|
277
|
+
def console_url(self) -> str | None:
|
279
278
|
return self.console.url if self.console else None
|
280
279
|
|
281
280
|
@property
|
282
|
-
def api_url(self) ->
|
281
|
+
def api_url(self) -> str | None:
|
283
282
|
return self.api.url if self.api else None
|
284
283
|
|
285
284
|
@property
|
286
|
-
def base_domain(self) ->
|
285
|
+
def base_domain(self) -> str | None:
|
287
286
|
return self.dns.base_domain if self.dns else None
|
288
287
|
|
289
288
|
|
@@ -348,7 +347,7 @@ class LabelContainer(BaseModel):
|
|
348
347
|
def __bool__(self) -> bool:
|
349
348
|
return len(self.labels) > 0
|
350
349
|
|
351
|
-
def get(self, name: str) ->
|
350
|
+
def get(self, name: str) -> OCMLabel | None:
|
352
351
|
return self.labels.get(name)
|
353
352
|
|
354
353
|
def __getitem__(self, name: str) -> OCMLabel:
|
@@ -360,7 +359,7 @@ class LabelContainer(BaseModel):
|
|
360
359
|
raise ValueError(f"Required label '{name}' does not exist.")
|
361
360
|
return label
|
362
361
|
|
363
|
-
def get_label_value(self, name: str) ->
|
362
|
+
def get_label_value(self, name: str) -> str | None:
|
364
363
|
label = self.get(name)
|
365
364
|
if label:
|
366
365
|
return label.value
|
@@ -370,7 +369,7 @@ class LabelContainer(BaseModel):
|
|
370
369
|
return {label.key: label.value for label in self.labels.values()}
|
371
370
|
|
372
371
|
|
373
|
-
class OCMServiceLogSeverity(
|
372
|
+
class OCMServiceLogSeverity(StrEnum):
|
374
373
|
"""
|
375
374
|
Represents the severity of a service log.
|
376
375
|
"""
|
@@ -462,8 +461,8 @@ class OCMSubscription(BaseModel):
|
|
462
461
|
|
463
462
|
status: OCMSubscriptionStatus
|
464
463
|
|
465
|
-
labels:
|
466
|
-
capabilities:
|
464
|
+
labels: list[OCMSubscriptionLabel] | None = None
|
465
|
+
capabilities: list[OCMCapability] | None = None
|
467
466
|
"""
|
468
467
|
Capabilities are a list of features/features flags that are enabled for a subscription.
|
469
468
|
"""
|
@@ -477,8 +476,8 @@ class OCMOrganization(BaseModel):
|
|
477
476
|
id: str
|
478
477
|
name: str
|
479
478
|
|
480
|
-
labels:
|
481
|
-
capabilities:
|
479
|
+
labels: list[OCMOrganizationLabel] | None = None
|
480
|
+
capabilities: list[OCMCapability] | None = None
|
482
481
|
"""
|
483
482
|
Capabilities are a list of features/features flags that are enabled for an organization.
|
484
483
|
"""
|
@@ -509,7 +508,7 @@ class ClusterDetails(BaseModel):
|
|
509
508
|
return capa is not None and capa.value == value
|
510
509
|
|
511
510
|
|
512
|
-
class OCMOIdentityProviderMappingMethod(
|
511
|
+
class OCMOIdentityProviderMappingMethod(StrEnum):
|
513
512
|
ADD = "add"
|
514
513
|
CLAIM = "claim"
|
515
514
|
LOOKUP = "lookup"
|
@@ -519,8 +518,8 @@ class OCMOIdentityProviderMappingMethod(str, Enum):
|
|
519
518
|
class OCMOIdentityProvider(BaseModel):
|
520
519
|
type: str
|
521
520
|
name: str
|
522
|
-
id:
|
523
|
-
href:
|
521
|
+
id: str | None = None
|
522
|
+
href: str | None = None
|
524
523
|
|
525
524
|
|
526
525
|
class OCMOIdentityProviderGithub(OCMOIdentityProvider):
|
@@ -543,7 +542,7 @@ class OCMOIdentityProviderOidcOpenIdClaims(BaseModel):
|
|
543
542
|
|
544
543
|
class OCMOIdentityProviderOidcOpenId(BaseModel):
|
545
544
|
client_id: str
|
546
|
-
client_secret:
|
545
|
+
client_secret: str | None = None
|
547
546
|
issuer: str
|
548
547
|
claims: OCMOIdentityProviderOidcOpenIdClaims = OCMOIdentityProviderOidcOpenIdClaims(
|
549
548
|
email=["email"],
|
@@ -579,15 +578,15 @@ class OCMAddonUpgradePolicy(BaseModel):
|
|
579
578
|
id: str
|
580
579
|
addon_id: str
|
581
580
|
cluster_id: str
|
582
|
-
next_run:
|
583
|
-
schedule:
|
581
|
+
next_run: str | None
|
582
|
+
schedule: str | None
|
584
583
|
schedule_type: str
|
585
584
|
version: str
|
586
|
-
state:
|
585
|
+
state: str | None
|
587
586
|
|
588
587
|
|
589
588
|
def build_label_container(
|
590
|
-
*label_iterables:
|
589
|
+
*label_iterables: Iterable[OCMLabel] | None,
|
591
590
|
) -> LabelContainer:
|
592
591
|
"""
|
593
592
|
Builds a label container from a list of labels.
|