qontract-reconcile 0.10.2.dev345__py3-none-any.whl → 0.10.2.dev408__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.dev345.dist-info → qontract_reconcile-0.10.2.dev408.dist-info}/METADATA +11 -10
- {qontract_reconcile-0.10.2.dev345.dist-info → qontract_reconcile-0.10.2.dev408.dist-info}/RECORD +126 -120
- reconcile/aus/base.py +17 -14
- reconcile/automated_actions/config/integration.py +12 -0
- reconcile/aws_account_manager/integration.py +2 -2
- reconcile/aws_ami_cleanup/integration.py +6 -7
- reconcile/aws_ami_share.py +69 -62
- reconcile/aws_cloudwatch_log_retention/integration.py +155 -126
- reconcile/aws_ecr_image_pull_secrets.py +2 -2
- reconcile/aws_iam_keys.py +1 -0
- reconcile/aws_saml_idp/integration.py +7 -1
- reconcile/aws_saml_roles/integration.py +9 -3
- reconcile/change_owners/change_owners.py +1 -1
- reconcile/change_owners/diff.py +2 -4
- reconcile/checkpoint.py +11 -3
- reconcile/cli.py +33 -8
- reconcile/dashdotdb_dora.py +4 -11
- reconcile/database_access_manager.py +118 -111
- reconcile/endpoints_discovery/integration.py +4 -1
- reconcile/endpoints_discovery/merge_request_manager.py +9 -11
- reconcile/external_resources/factories.py +5 -12
- reconcile/external_resources/integration.py +1 -1
- reconcile/external_resources/manager.py +5 -3
- reconcile/external_resources/meta.py +0 -1
- reconcile/external_resources/model.py +10 -10
- reconcile/external_resources/reconciler.py +5 -2
- reconcile/external_resources/secrets_sync.py +4 -6
- reconcile/external_resources/state.py +5 -4
- reconcile/gabi_authorized_users.py +8 -5
- reconcile/gitlab_housekeeping.py +13 -15
- reconcile/gitlab_mr_sqs_consumer.py +2 -2
- reconcile/gitlab_owners.py +15 -11
- reconcile/gql_definitions/automated_actions/instance.py +41 -2
- reconcile/gql_definitions/aws_ami_cleanup/aws_accounts.py +10 -0
- reconcile/gql_definitions/aws_cloudwatch_log_retention/aws_accounts.py +22 -61
- reconcile/gql_definitions/aws_saml_idp/aws_accounts.py +10 -0
- reconcile/gql_definitions/aws_saml_roles/aws_accounts.py +10 -0
- reconcile/gql_definitions/common/aws_vpc_requests.py +10 -0
- reconcile/gql_definitions/common/clusters.py +2 -0
- reconcile/gql_definitions/external_resources/external_resources_namespaces.py +84 -1
- reconcile/gql_definitions/external_resources/external_resources_settings.py +2 -0
- reconcile/gql_definitions/fragments/aws_account_common.py +2 -0
- reconcile/gql_definitions/fragments/aws_organization.py +33 -0
- reconcile/gql_definitions/fragments/aws_vpc_request.py +2 -0
- reconcile/gql_definitions/introspection.json +3474 -1986
- reconcile/gql_definitions/jira_permissions_validator/jira_boards_for_permissions_validator.py +4 -0
- reconcile/gql_definitions/terraform_init/aws_accounts.py +14 -0
- reconcile/gql_definitions/terraform_resources/terraform_resources_namespaces.py +33 -1
- reconcile/gql_definitions/terraform_tgw_attachments/aws_accounts.py +10 -0
- reconcile/jenkins_worker_fleets.py +1 -0
- reconcile/jira_permissions_validator.py +236 -121
- reconcile/ocm/types.py +6 -0
- reconcile/openshift_base.py +47 -1
- reconcile/openshift_cluster_bots.py +2 -1
- reconcile/openshift_resources_base.py +6 -2
- reconcile/openshift_saas_deploy.py +2 -2
- reconcile/openshift_saas_deploy_trigger_cleaner.py +3 -5
- reconcile/openshift_upgrade_watcher.py +3 -3
- reconcile/queries.py +131 -0
- reconcile/saas_auto_promotions_manager/subscriber.py +4 -3
- reconcile/slack_usergroups.py +4 -3
- reconcile/sql_query.py +1 -0
- reconcile/statuspage/integrations/maintenances.py +4 -3
- reconcile/statuspage/status.py +5 -8
- reconcile/templates/rosa-classic-cluster-creation.sh.j2 +4 -0
- reconcile/templates/rosa-hcp-cluster-creation.sh.j2 +3 -0
- reconcile/templating/renderer.py +2 -1
- reconcile/terraform_aws_route53.py +7 -1
- reconcile/terraform_init/integration.py +185 -21
- reconcile/terraform_resources.py +11 -1
- reconcile/terraform_tgw_attachments.py +7 -1
- reconcile/terraform_users.py +7 -0
- reconcile/terraform_vpc_peerings.py +14 -3
- reconcile/terraform_vpc_resources/integration.py +7 -0
- reconcile/typed_queries/aws_account_tags.py +41 -0
- reconcile/typed_queries/saas_files.py +2 -2
- reconcile/utils/aggregated_list.py +4 -3
- reconcile/utils/aws_api.py +51 -20
- reconcile/utils/aws_api_typed/api.py +38 -9
- reconcile/utils/aws_api_typed/cloudformation.py +149 -0
- reconcile/utils/aws_api_typed/logs.py +73 -0
- reconcile/utils/datetime_util.py +67 -0
- reconcile/utils/differ.py +2 -3
- reconcile/utils/early_exit_cache.py +3 -2
- reconcile/utils/expiration.py +7 -3
- reconcile/utils/external_resource_spec.py +24 -1
- reconcile/utils/filtering.py +1 -1
- reconcile/utils/helm.py +2 -1
- reconcile/utils/helpers.py +1 -1
- reconcile/utils/jinja2/utils.py +4 -96
- reconcile/utils/jira_client.py +82 -63
- reconcile/utils/jjb_client.py +9 -12
- reconcile/utils/jobcontroller/controller.py +1 -1
- reconcile/utils/jobcontroller/models.py +17 -1
- reconcile/utils/json.py +32 -0
- reconcile/utils/merge_request_manager/merge_request_manager.py +3 -3
- reconcile/utils/merge_request_manager/parser.py +2 -2
- reconcile/utils/mr/app_interface_reporter.py +2 -2
- reconcile/utils/mr/base.py +2 -2
- reconcile/utils/mr/notificator.py +2 -2
- reconcile/utils/mr/update_access_report_base.py +3 -4
- reconcile/utils/oc.py +113 -95
- reconcile/utils/oc_filters.py +3 -3
- reconcile/utils/ocm/products.py +6 -0
- reconcile/utils/ocm/search_filters.py +3 -6
- reconcile/utils/ocm/service_log.py +3 -5
- reconcile/utils/openshift_resource.py +10 -5
- reconcile/utils/output.py +3 -2
- reconcile/utils/pagerduty_api.py +5 -5
- reconcile/utils/runtime/integration.py +1 -2
- reconcile/utils/runtime/runner.py +2 -2
- reconcile/utils/saasherder/models.py +2 -1
- reconcile/utils/saasherder/saasherder.py +9 -7
- reconcile/utils/slack_api.py +24 -2
- reconcile/utils/sloth.py +171 -2
- reconcile/utils/sqs_gateway.py +2 -1
- reconcile/utils/state.py +2 -1
- reconcile/utils/terraform_client.py +4 -3
- reconcile/utils/terrascript_aws_client.py +165 -111
- reconcile/utils/vault.py +1 -1
- reconcile/vault_replication.py +107 -42
- tools/app_interface_reporter.py +4 -4
- tools/cli_commands/systems_and_tools.py +5 -1
- tools/qontract_cli.py +25 -13
- {qontract_reconcile-0.10.2.dev345.dist-info → qontract_reconcile-0.10.2.dev408.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.2.dev345.dist-info → qontract_reconcile-0.10.2.dev408.dist-info}/entry_points.txt +0 -0
reconcile/openshift_base.py
CHANGED
|
@@ -30,9 +30,11 @@ from reconcile.utils import (
|
|
|
30
30
|
)
|
|
31
31
|
from reconcile.utils.constants import DEFAULT_THREAD_POOL_SIZE
|
|
32
32
|
from reconcile.utils.oc import (
|
|
33
|
+
AmbiguousResourceTypeError,
|
|
33
34
|
DeploymentFieldIsImmutableError,
|
|
34
35
|
FieldIsImmutableError,
|
|
35
36
|
InvalidValueApplyError,
|
|
37
|
+
KindNotFoundError,
|
|
36
38
|
MayNotChangeOnceSetError,
|
|
37
39
|
MetaDataAnnotationsTooLongApplyError,
|
|
38
40
|
OC_Map,
|
|
@@ -128,6 +130,29 @@ class ClusterMap(Protocol):
|
|
|
128
130
|
) -> list[str]: ...
|
|
129
131
|
|
|
130
132
|
|
|
133
|
+
def validate_managed_resource_types(
|
|
134
|
+
oc: OCCli,
|
|
135
|
+
managed_resource_types: Iterable[str],
|
|
136
|
+
managed_resource_names: Iterable[Mapping[str, Any]],
|
|
137
|
+
cluster_scope_resource_validation: bool,
|
|
138
|
+
) -> None:
|
|
139
|
+
"""Validate the managed resource types."""
|
|
140
|
+
managed_resources = [
|
|
141
|
+
managed_resource_name["resource"]
|
|
142
|
+
for managed_resource_name in managed_resource_names
|
|
143
|
+
]
|
|
144
|
+
for managed_resource_type in managed_resource_types:
|
|
145
|
+
# The k8s kind must be supported by the cluster
|
|
146
|
+
resource = oc.get_api_resource(managed_resource_type)
|
|
147
|
+
|
|
148
|
+
if cluster_scope_resource_validation and not resource.namespaced:
|
|
149
|
+
# cluster-scoped resources must be use managedResourceNames!
|
|
150
|
+
if managed_resource_type not in managed_resources:
|
|
151
|
+
raise ValidationError(
|
|
152
|
+
f"Cluster-scoped resource {managed_resource_type} must be managed by name only. Please use 'managedResourceNames' field to specify the names of the resources to manage."
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
|
|
131
156
|
def init_specs_to_fetch(
|
|
132
157
|
ri: ResourceInventory,
|
|
133
158
|
oc_map: ClusterMap,
|
|
@@ -136,6 +161,7 @@ def init_specs_to_fetch(
|
|
|
136
161
|
override_managed_types: Iterable[str] | None = None,
|
|
137
162
|
managed_types_key: str = "managedResourceTypes",
|
|
138
163
|
cluster_admin: bool = False,
|
|
164
|
+
cluster_scope_resource_validation: bool = False,
|
|
139
165
|
) -> list[StateSpec]:
|
|
140
166
|
state_specs: list[StateSpec] = []
|
|
141
167
|
|
|
@@ -163,9 +189,27 @@ def init_specs_to_fetch(
|
|
|
163
189
|
logging.log(level=ex.log_level, msg=ex.message)
|
|
164
190
|
continue
|
|
165
191
|
|
|
192
|
+
managed_resource_names = namespace_info.get("managedResourceNames") or []
|
|
193
|
+
try:
|
|
194
|
+
validate_managed_resource_types(
|
|
195
|
+
oc,
|
|
196
|
+
managed_types,
|
|
197
|
+
managed_resource_names,
|
|
198
|
+
cluster_scope_resource_validation=cluster_scope_resource_validation,
|
|
199
|
+
)
|
|
200
|
+
except KindNotFoundError:
|
|
201
|
+
# We must allow kinds that are not supported by the cluster because:
|
|
202
|
+
# 1. We install CRD with an operator in the same MR
|
|
203
|
+
# 2. SAAS files initialize the namespace objects with managedResourceTypes from the SAAS file
|
|
204
|
+
# and we can't expect that all of those are valid for all clusters
|
|
205
|
+
pass
|
|
206
|
+
except (AmbiguousResourceTypeError, ValidationError) as e:
|
|
207
|
+
ri.register_error()
|
|
208
|
+
logging.error(f"[{cluster}/{namespace_info['name']}] {e}")
|
|
209
|
+
continue
|
|
210
|
+
|
|
166
211
|
namespace = namespace_info["name"]
|
|
167
212
|
# These may exit but have a value of None
|
|
168
|
-
managed_resource_names = namespace_info.get("managedResourceNames") or []
|
|
169
213
|
managed_resource_type_overrides = (
|
|
170
214
|
namespace_info.get("managedResourceTypeOverrides") or []
|
|
171
215
|
)
|
|
@@ -340,6 +384,7 @@ def fetch_current_state(
|
|
|
340
384
|
cluster_admin: bool = False,
|
|
341
385
|
caller: str | None = None,
|
|
342
386
|
init_projects: bool = False,
|
|
387
|
+
cluster_scope_resource_validation: bool = False,
|
|
343
388
|
) -> tuple[ResourceInventory, OC_Map]:
|
|
344
389
|
ri = ResourceInventory()
|
|
345
390
|
settings = queries.get_app_interface_settings()
|
|
@@ -362,6 +407,7 @@ def fetch_current_state(
|
|
|
362
407
|
clusters=clusters,
|
|
363
408
|
override_managed_types=override_managed_types,
|
|
364
409
|
cluster_admin=cluster_admin,
|
|
410
|
+
cluster_scope_resource_validation=cluster_scope_resource_validation,
|
|
365
411
|
)
|
|
366
412
|
threaded.run(
|
|
367
413
|
populate_current_state,
|
|
@@ -16,6 +16,7 @@ from reconcile.gql_definitions.openshift_cluster_bots.clusters import ClusterV1
|
|
|
16
16
|
from reconcile.status import ExitCodes
|
|
17
17
|
from reconcile.utils import gql
|
|
18
18
|
from reconcile.utils.disabled_integrations import integration_is_enabled
|
|
19
|
+
from reconcile.utils.json import json_dumps
|
|
19
20
|
from reconcile.utils.mr import clusters_updates
|
|
20
21
|
from reconcile.utils.ocm import OCM, OCMMap
|
|
21
22
|
from reconcile.utils.openshift_resource import (
|
|
@@ -102,7 +103,7 @@ def oc(
|
|
|
102
103
|
|
|
103
104
|
def oc_apply(kubeconfig: str, namespace: str, items: list[dict]) -> None:
|
|
104
105
|
for item in items:
|
|
105
|
-
stdin =
|
|
106
|
+
stdin = json_dumps(item).encode()
|
|
106
107
|
oc(kubeconfig, namespace, ["apply", "-f", "-"], stdin)
|
|
107
108
|
|
|
108
109
|
|
|
@@ -806,7 +806,11 @@ def fetch_data(
|
|
|
806
806
|
init_api_resources=init_api_resources,
|
|
807
807
|
)
|
|
808
808
|
state_specs = ob.init_specs_to_fetch(
|
|
809
|
-
ri,
|
|
809
|
+
ri,
|
|
810
|
+
oc_map,
|
|
811
|
+
namespaces=namespaces,
|
|
812
|
+
override_managed_types=overrides,
|
|
813
|
+
cluster_scope_resource_validation=True,
|
|
810
814
|
)
|
|
811
815
|
threaded.run(fetch_states, state_specs, thread_pool_size, ri=ri, settings=settings)
|
|
812
816
|
|
|
@@ -861,7 +865,7 @@ def canonicalize_namespaces(
|
|
|
861
865
|
elif providers[0] == "route":
|
|
862
866
|
override = ["Route"]
|
|
863
867
|
elif providers[0] == "prometheus-rule":
|
|
864
|
-
override = ["PrometheusRule"]
|
|
868
|
+
override = ["PrometheusRule.monitoring.coreos.com"]
|
|
865
869
|
|
|
866
870
|
namespace_info["openshiftResources"] = ors
|
|
867
871
|
canonicalized_namespaces.append(namespace_info)
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import json
|
|
2
1
|
import logging
|
|
3
2
|
import os
|
|
4
3
|
import sys
|
|
@@ -28,6 +27,7 @@ from reconcile.typed_queries.saas_files import (
|
|
|
28
27
|
from reconcile.utils.constants import DEFAULT_THREAD_POOL_SIZE
|
|
29
28
|
from reconcile.utils.defer import defer
|
|
30
29
|
from reconcile.utils.gitlab_api import GitLabApi
|
|
30
|
+
from reconcile.utils.json import json_dumps
|
|
31
31
|
from reconcile.utils.openshift_resource import ResourceInventory
|
|
32
32
|
from reconcile.utils.saasherder import SaasHerder
|
|
33
33
|
from reconcile.utils.secret_reader import create_secret_reader
|
|
@@ -346,4 +346,4 @@ def run(
|
|
|
346
346
|
if image_auth.auth_server:
|
|
347
347
|
json_file = os.path.join(io_dir, "dockerconfigjson")
|
|
348
348
|
with open(json_file, "w", encoding="locale") as f:
|
|
349
|
-
f.write(
|
|
349
|
+
f.write(json_dumps(image_auth.get_docker_config_json(), indent=2))
|
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
from collections.abc import Callable
|
|
3
3
|
from datetime import (
|
|
4
|
-
UTC,
|
|
5
4
|
datetime,
|
|
6
5
|
timedelta,
|
|
7
6
|
)
|
|
8
7
|
from typing import Any
|
|
9
8
|
|
|
10
|
-
from dateutil import parser
|
|
11
|
-
|
|
12
9
|
from reconcile.gql_definitions.fragments.pipeline_provider_retention import (
|
|
13
10
|
PipelineProviderRetention,
|
|
14
11
|
)
|
|
@@ -19,6 +16,7 @@ from reconcile.typed_queries.tekton_pipeline_providers import (
|
|
|
19
16
|
get_tekton_pipeline_providers,
|
|
20
17
|
)
|
|
21
18
|
from reconcile.utils.constants import DEFAULT_THREAD_POOL_SIZE
|
|
19
|
+
from reconcile.utils.datetime_util import from_utc_iso_format, utc_now
|
|
22
20
|
from reconcile.utils.defer import defer
|
|
23
21
|
from reconcile.utils.oc_map import (
|
|
24
22
|
OCLogMsg,
|
|
@@ -35,7 +33,7 @@ def within_retention_days(
|
|
|
35
33
|
resource: dict[str, Any], days: int, now_date: datetime
|
|
36
34
|
) -> bool:
|
|
37
35
|
metadata = resource["metadata"]
|
|
38
|
-
creation_date =
|
|
36
|
+
creation_date = from_utc_iso_format(metadata["creationTimestamp"])
|
|
39
37
|
interval = now_date.timestamp() - creation_date.timestamp()
|
|
40
38
|
|
|
41
39
|
return interval < timedelta(days=days).total_seconds()
|
|
@@ -69,7 +67,7 @@ def run(
|
|
|
69
67
|
use_jump_host: bool = True,
|
|
70
68
|
defer: Callable | None = None,
|
|
71
69
|
) -> None:
|
|
72
|
-
now_date =
|
|
70
|
+
now_date = utc_now()
|
|
73
71
|
vault_settings = get_app_interface_vault_settings()
|
|
74
72
|
secret_reader = create_secret_reader(use_vault=vault_settings.vault)
|
|
75
73
|
pipeline_providers = get_tekton_pipeline_providers()
|
|
@@ -3,7 +3,6 @@ from collections.abc import (
|
|
|
3
3
|
Callable,
|
|
4
4
|
Iterable,
|
|
5
5
|
)
|
|
6
|
-
from datetime import datetime
|
|
7
6
|
|
|
8
7
|
from reconcile import queries
|
|
9
8
|
from reconcile.gql_definitions.common.clusters import ClusterV1
|
|
@@ -13,6 +12,7 @@ from reconcile.typed_queries.app_interface_vault_settings import (
|
|
|
13
12
|
)
|
|
14
13
|
from reconcile.typed_queries.clusters import get_clusters
|
|
15
14
|
from reconcile.utils.constants import DEFAULT_THREAD_POOL_SIZE
|
|
15
|
+
from reconcile.utils.datetime_util import from_utc_iso_format, utc_now
|
|
16
16
|
from reconcile.utils.defer import defer
|
|
17
17
|
from reconcile.utils.oc_map import (
|
|
18
18
|
OCLogMsg,
|
|
@@ -101,7 +101,7 @@ def notify_upgrades_start(
|
|
|
101
101
|
state: State,
|
|
102
102
|
slack: SlackApi | None,
|
|
103
103
|
) -> None:
|
|
104
|
-
now =
|
|
104
|
+
now = utc_now()
|
|
105
105
|
for cluster in clusters:
|
|
106
106
|
if cluster.spec and not cluster.spec.hypershift:
|
|
107
107
|
upgrade_at, version = _get_start_osd(oc_map, cluster.name)
|
|
@@ -113,7 +113,7 @@ def notify_upgrades_start(
|
|
|
113
113
|
continue
|
|
114
114
|
|
|
115
115
|
if upgrade_at and version:
|
|
116
|
-
upgrade_at_obj =
|
|
116
|
+
upgrade_at_obj = from_utc_iso_format(upgrade_at)
|
|
117
117
|
state_key = f"{cluster.name}-{upgrade_at}1"
|
|
118
118
|
# if this is the first iteration in which 'now' had passed
|
|
119
119
|
# the upgrade at date time, we send a notification
|
reconcile/queries.py
CHANGED
|
@@ -477,6 +477,12 @@ AWS_ACCOUNTS_QUERY = """
|
|
|
477
477
|
integrations
|
|
478
478
|
}
|
|
479
479
|
deleteKeys
|
|
480
|
+
organization {
|
|
481
|
+
payerAccount {
|
|
482
|
+
organizationAccountTags
|
|
483
|
+
}
|
|
484
|
+
tags
|
|
485
|
+
}
|
|
480
486
|
{% if reset_passwords %}
|
|
481
487
|
resetPasswords {
|
|
482
488
|
user {
|
|
@@ -499,6 +505,12 @@ AWS_ACCOUNTS_QUERY = """
|
|
|
499
505
|
name
|
|
500
506
|
uid
|
|
501
507
|
supportedDeploymentRegions
|
|
508
|
+
organization {
|
|
509
|
+
payerAccount {
|
|
510
|
+
organizationAccountTags
|
|
511
|
+
}
|
|
512
|
+
tags
|
|
513
|
+
}
|
|
502
514
|
}
|
|
503
515
|
... on AWSAccountSharingOptionAMI_v1 {
|
|
504
516
|
regex
|
|
@@ -606,6 +618,12 @@ awsInfrastructureManagementAccounts {
|
|
|
606
618
|
version
|
|
607
619
|
format
|
|
608
620
|
}
|
|
621
|
+
organization {
|
|
622
|
+
payerAccount {
|
|
623
|
+
organizationAccountTags
|
|
624
|
+
}
|
|
625
|
+
tags
|
|
626
|
+
}
|
|
609
627
|
}
|
|
610
628
|
accessLevel
|
|
611
629
|
default
|
|
@@ -636,6 +654,12 @@ awsInfrastructureAccess {
|
|
|
636
654
|
version
|
|
637
655
|
format
|
|
638
656
|
}
|
|
657
|
+
organization {
|
|
658
|
+
payerAccount {
|
|
659
|
+
organizationAccountTags
|
|
660
|
+
}
|
|
661
|
+
tags
|
|
662
|
+
}
|
|
639
663
|
}
|
|
640
664
|
roles {
|
|
641
665
|
users {
|
|
@@ -745,6 +769,12 @@ CLUSTERS_QUERY = """
|
|
|
745
769
|
version
|
|
746
770
|
format
|
|
747
771
|
}
|
|
772
|
+
organization {
|
|
773
|
+
payerAccount {
|
|
774
|
+
organizationAccountTags
|
|
775
|
+
}
|
|
776
|
+
tags
|
|
777
|
+
}
|
|
748
778
|
rosa {
|
|
749
779
|
ocm_environments {
|
|
750
780
|
ocm {
|
|
@@ -773,6 +803,7 @@ CLUSTERS_QUERY = """
|
|
|
773
803
|
private
|
|
774
804
|
provision_shard_id
|
|
775
805
|
disable_user_workload_monitoring
|
|
806
|
+
fips
|
|
776
807
|
}
|
|
777
808
|
externalConfiguration {
|
|
778
809
|
labels
|
|
@@ -829,6 +860,12 @@ CLUSTERS_QUERY = """
|
|
|
829
860
|
version
|
|
830
861
|
format
|
|
831
862
|
}
|
|
863
|
+
organization {
|
|
864
|
+
payerAccount {
|
|
865
|
+
organizationAccountTags
|
|
866
|
+
}
|
|
867
|
+
tags
|
|
868
|
+
}
|
|
832
869
|
}
|
|
833
870
|
vpc_id
|
|
834
871
|
cidr_block
|
|
@@ -847,6 +884,12 @@ CLUSTERS_QUERY = """
|
|
|
847
884
|
version
|
|
848
885
|
format
|
|
849
886
|
}
|
|
887
|
+
organization {
|
|
888
|
+
payerAccount {
|
|
889
|
+
organizationAccountTags
|
|
890
|
+
}
|
|
891
|
+
tags
|
|
892
|
+
}
|
|
850
893
|
}
|
|
851
894
|
tags
|
|
852
895
|
}
|
|
@@ -861,6 +904,12 @@ CLUSTERS_QUERY = """
|
|
|
861
904
|
version
|
|
862
905
|
format
|
|
863
906
|
}
|
|
907
|
+
organization {
|
|
908
|
+
payerAccount {
|
|
909
|
+
organizationAccountTags
|
|
910
|
+
}
|
|
911
|
+
tags
|
|
912
|
+
}
|
|
864
913
|
}
|
|
865
914
|
tags
|
|
866
915
|
cidrBlock
|
|
@@ -889,6 +938,12 @@ CLUSTERS_QUERY = """
|
|
|
889
938
|
version
|
|
890
939
|
format
|
|
891
940
|
}
|
|
941
|
+
organization {
|
|
942
|
+
payerAccount {
|
|
943
|
+
organizationAccountTags
|
|
944
|
+
}
|
|
945
|
+
tags
|
|
946
|
+
}
|
|
892
947
|
}
|
|
893
948
|
}
|
|
894
949
|
accessLevel
|
|
@@ -914,6 +969,12 @@ CLUSTERS_QUERY = """
|
|
|
914
969
|
version
|
|
915
970
|
format
|
|
916
971
|
}
|
|
972
|
+
organization {
|
|
973
|
+
payerAccount {
|
|
974
|
+
organizationAccountTags
|
|
975
|
+
}
|
|
976
|
+
tags
|
|
977
|
+
}
|
|
917
978
|
}
|
|
918
979
|
}
|
|
919
980
|
}
|
|
@@ -1067,6 +1128,12 @@ CLUSTER_PEERING_QUERY = """
|
|
|
1067
1128
|
version
|
|
1068
1129
|
format
|
|
1069
1130
|
}
|
|
1131
|
+
organization {
|
|
1132
|
+
payerAccount {
|
|
1133
|
+
organizationAccountTags
|
|
1134
|
+
}
|
|
1135
|
+
tags
|
|
1136
|
+
}
|
|
1070
1137
|
}
|
|
1071
1138
|
accessLevel
|
|
1072
1139
|
default
|
|
@@ -1088,6 +1155,12 @@ CLUSTER_PEERING_QUERY = """
|
|
|
1088
1155
|
version
|
|
1089
1156
|
format
|
|
1090
1157
|
}
|
|
1158
|
+
organization {
|
|
1159
|
+
payerAccount {
|
|
1160
|
+
organizationAccountTags
|
|
1161
|
+
}
|
|
1162
|
+
tags
|
|
1163
|
+
}
|
|
1091
1164
|
}
|
|
1092
1165
|
}
|
|
1093
1166
|
}
|
|
@@ -1112,6 +1185,12 @@ CLUSTER_PEERING_QUERY = """
|
|
|
1112
1185
|
version
|
|
1113
1186
|
format
|
|
1114
1187
|
}
|
|
1188
|
+
organization {
|
|
1189
|
+
payerAccount {
|
|
1190
|
+
organizationAccountTags
|
|
1191
|
+
}
|
|
1192
|
+
tags
|
|
1193
|
+
}
|
|
1115
1194
|
}
|
|
1116
1195
|
vpc_id
|
|
1117
1196
|
cidr_block
|
|
@@ -1131,6 +1210,12 @@ CLUSTER_PEERING_QUERY = """
|
|
|
1131
1210
|
version
|
|
1132
1211
|
format
|
|
1133
1212
|
}
|
|
1213
|
+
organization {
|
|
1214
|
+
payerAccount {
|
|
1215
|
+
organizationAccountTags
|
|
1216
|
+
}
|
|
1217
|
+
tags
|
|
1218
|
+
}
|
|
1134
1219
|
}
|
|
1135
1220
|
tags
|
|
1136
1221
|
assumeRole
|
|
@@ -1146,6 +1231,12 @@ CLUSTER_PEERING_QUERY = """
|
|
|
1146
1231
|
version
|
|
1147
1232
|
format
|
|
1148
1233
|
}
|
|
1234
|
+
organization {
|
|
1235
|
+
payerAccount {
|
|
1236
|
+
organizationAccountTags
|
|
1237
|
+
}
|
|
1238
|
+
tags
|
|
1239
|
+
}
|
|
1149
1240
|
}
|
|
1150
1241
|
tags
|
|
1151
1242
|
cidrBlock
|
|
@@ -1175,6 +1266,12 @@ CLUSTER_PEERING_QUERY = """
|
|
|
1175
1266
|
version
|
|
1176
1267
|
format
|
|
1177
1268
|
}
|
|
1269
|
+
organization {
|
|
1270
|
+
payerAccount {
|
|
1271
|
+
organizationAccountTags
|
|
1272
|
+
}
|
|
1273
|
+
tags
|
|
1274
|
+
}
|
|
1178
1275
|
}
|
|
1179
1276
|
}
|
|
1180
1277
|
}
|
|
@@ -1190,6 +1287,12 @@ CLUSTER_PEERING_QUERY = """
|
|
|
1190
1287
|
version
|
|
1191
1288
|
format
|
|
1192
1289
|
}
|
|
1290
|
+
organization {
|
|
1291
|
+
payerAccount {
|
|
1292
|
+
organizationAccountTags
|
|
1293
|
+
}
|
|
1294
|
+
tags
|
|
1295
|
+
}
|
|
1193
1296
|
}
|
|
1194
1297
|
accessLevel
|
|
1195
1298
|
default
|
|
@@ -1216,6 +1319,12 @@ CLUSTER_PEERING_QUERY = """
|
|
|
1216
1319
|
version
|
|
1217
1320
|
format
|
|
1218
1321
|
}
|
|
1322
|
+
organization {
|
|
1323
|
+
payerAccount {
|
|
1324
|
+
organizationAccountTags
|
|
1325
|
+
}
|
|
1326
|
+
tags
|
|
1327
|
+
}
|
|
1219
1328
|
}
|
|
1220
1329
|
}
|
|
1221
1330
|
}
|
|
@@ -1231,6 +1340,12 @@ CLUSTER_PEERING_QUERY = """
|
|
|
1231
1340
|
version
|
|
1232
1341
|
format
|
|
1233
1342
|
}
|
|
1343
|
+
organization {
|
|
1344
|
+
payerAccount {
|
|
1345
|
+
organizationAccountTags
|
|
1346
|
+
}
|
|
1347
|
+
tags
|
|
1348
|
+
}
|
|
1234
1349
|
}
|
|
1235
1350
|
}
|
|
1236
1351
|
}
|
|
@@ -2230,6 +2345,12 @@ JIRA_BOARDS_QUICK_QUERY = """
|
|
|
2230
2345
|
version
|
|
2231
2346
|
format
|
|
2232
2347
|
}
|
|
2348
|
+
email {
|
|
2349
|
+
path
|
|
2350
|
+
field
|
|
2351
|
+
version
|
|
2352
|
+
format
|
|
2353
|
+
}
|
|
2233
2354
|
}
|
|
2234
2355
|
}
|
|
2235
2356
|
}
|
|
@@ -2336,6 +2457,12 @@ DNS_ZONES_QUERY = """
|
|
|
2336
2457
|
version
|
|
2337
2458
|
format
|
|
2338
2459
|
}
|
|
2460
|
+
organization {
|
|
2461
|
+
payerAccount {
|
|
2462
|
+
organizationAccountTags
|
|
2463
|
+
}
|
|
2464
|
+
tags
|
|
2465
|
+
}
|
|
2339
2466
|
}
|
|
2340
2467
|
vpc {
|
|
2341
2468
|
vpc_id
|
|
@@ -2697,6 +2824,10 @@ APP_METADATA = """
|
|
|
2697
2824
|
path
|
|
2698
2825
|
field
|
|
2699
2826
|
}
|
|
2827
|
+
email {
|
|
2828
|
+
path
|
|
2829
|
+
field
|
|
2830
|
+
}
|
|
2700
2831
|
}
|
|
2701
2832
|
}
|
|
2702
2833
|
slackUserGroup {
|
|
@@ -2,7 +2,7 @@ import hashlib
|
|
|
2
2
|
import logging
|
|
3
3
|
from collections.abc import Iterable
|
|
4
4
|
from dataclasses import dataclass
|
|
5
|
-
from datetime import
|
|
5
|
+
from datetime import timedelta
|
|
6
6
|
|
|
7
7
|
from croniter import croniter
|
|
8
8
|
|
|
@@ -13,6 +13,7 @@ from reconcile.saas_auto_promotions_manager.publisher import (
|
|
|
13
13
|
DeploymentInfo,
|
|
14
14
|
Publisher,
|
|
15
15
|
)
|
|
16
|
+
from reconcile.utils.datetime_util import utc_now
|
|
16
17
|
from reconcile.utils.slo_document_manager import SLODocumentManager
|
|
17
18
|
|
|
18
19
|
CONTENT_HASH_LENGTH = 32
|
|
@@ -113,7 +114,7 @@ class Subscriber:
|
|
|
113
114
|
We accumulate the time a ref is running on all publishers for this subscriber.
|
|
114
115
|
We compare that accumulated time with the soak_days setting of the subscriber.
|
|
115
116
|
"""
|
|
116
|
-
now =
|
|
117
|
+
now = utc_now()
|
|
117
118
|
delta = timedelta(days=0)
|
|
118
119
|
for channel in self.channels:
|
|
119
120
|
for publisher in channel.publishers:
|
|
@@ -136,7 +137,7 @@ class Subscriber:
|
|
|
136
137
|
self.schedule,
|
|
137
138
|
)
|
|
138
139
|
return False
|
|
139
|
-
return croniter.match(self.schedule,
|
|
140
|
+
return croniter.match(self.schedule, utc_now(), day_or=False)
|
|
140
141
|
|
|
141
142
|
def _compute_desired_ref(self) -> None:
|
|
142
143
|
"""
|
reconcile/slack_usergroups.py
CHANGED
|
@@ -40,6 +40,7 @@ from reconcile.typed_queries.app_interface_vault_settings import (
|
|
|
40
40
|
)
|
|
41
41
|
from reconcile.typed_queries.pagerduty_instances import get_pagerduty_instances
|
|
42
42
|
from reconcile.utils import gql
|
|
43
|
+
from reconcile.utils.datetime_util import ensure_utc, utc_now
|
|
43
44
|
from reconcile.utils.disabled_integrations import integration_is_enabled
|
|
44
45
|
from reconcile.utils.exceptions import (
|
|
45
46
|
AppInterfaceSettingsError,
|
|
@@ -357,11 +358,11 @@ def get_slack_usernames_from_owners(
|
|
|
357
358
|
|
|
358
359
|
def get_slack_usernames_from_schedule(schedule: Iterable[ScheduleEntryV1]) -> list[str]:
|
|
359
360
|
"""Return list of usernames from all schedules."""
|
|
360
|
-
now =
|
|
361
|
+
now = utc_now()
|
|
361
362
|
all_slack_usernames: list[str] = []
|
|
362
363
|
for entry in schedule:
|
|
363
|
-
start = datetime.strptime(entry.start, DATE_FORMAT)
|
|
364
|
-
end = datetime.strptime(entry.end, DATE_FORMAT)
|
|
364
|
+
start = ensure_utc(datetime.strptime(entry.start, DATE_FORMAT)) # noqa: DTZ007
|
|
365
|
+
end = ensure_utc(datetime.strptime(entry.end, DATE_FORMAT)) # noqa: DTZ007
|
|
365
366
|
if start <= now <= end:
|
|
366
367
|
all_slack_usernames.extend(get_slack_username(u) for u in entry.users)
|
|
367
368
|
return all_slack_usernames
|
reconcile/sql_query.py
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import sys
|
|
3
|
-
from datetime import
|
|
3
|
+
from datetime import datetime, timedelta
|
|
4
4
|
|
|
5
5
|
from reconcile.slack_base import slackapi_from_queries
|
|
6
6
|
from reconcile.statuspage.atlassian import AtlassianStatusPageProvider
|
|
7
7
|
from reconcile.statuspage.integration import get_binding_state, get_status_pages
|
|
8
8
|
from reconcile.statuspage.page import StatusMaintenance
|
|
9
9
|
from reconcile.statuspage.state import S3ComponentBindingState
|
|
10
|
+
from reconcile.utils.datetime_util import utc_now
|
|
10
11
|
from reconcile.utils.differ import diff_iterables
|
|
11
12
|
from reconcile.utils.runtime.integration import (
|
|
12
13
|
NoParams,
|
|
@@ -52,7 +53,7 @@ class StatusPageMaintenancesIntegration(QontractReconcileIntegration[NoParams]):
|
|
|
52
53
|
desired_state: list[StatusMaintenance],
|
|
53
54
|
binding_state: S3ComponentBindingState,
|
|
54
55
|
) -> None:
|
|
55
|
-
now =
|
|
56
|
+
now = utc_now()
|
|
56
57
|
slack = slackapi_from_queries(QONTRACT_INTEGRATION, init_usergroups=False)
|
|
57
58
|
for m in desired_state:
|
|
58
59
|
scheduled_start = m.schedule_start
|
|
@@ -68,7 +69,7 @@ class StatusPageMaintenancesIntegration(QontractReconcileIntegration[NoParams]):
|
|
|
68
69
|
def run(self, dry_run: bool = False) -> None:
|
|
69
70
|
binding_state = get_binding_state(self.name, self.secret_reader)
|
|
70
71
|
pages = get_status_pages()
|
|
71
|
-
now =
|
|
72
|
+
now = utc_now()
|
|
72
73
|
|
|
73
74
|
error = False
|
|
74
75
|
for p in pages:
|
reconcile/statuspage/status.py
CHANGED
|
@@ -2,18 +2,15 @@ from abc import (
|
|
|
2
2
|
ABC,
|
|
3
3
|
abstractmethod,
|
|
4
4
|
)
|
|
5
|
-
from datetime import
|
|
6
|
-
UTC,
|
|
7
|
-
datetime,
|
|
8
|
-
)
|
|
5
|
+
from datetime import datetime
|
|
9
6
|
|
|
10
|
-
from dateutil.parser import isoparse
|
|
11
7
|
from pydantic import BaseModel
|
|
12
8
|
|
|
13
9
|
from reconcile.gql_definitions.statuspage.statuspages import (
|
|
14
10
|
ManualStatusProviderV1,
|
|
15
11
|
StatusProviderV1,
|
|
16
12
|
)
|
|
13
|
+
from reconcile.utils.datetime_util import from_utc_iso_format, utc_now
|
|
17
14
|
|
|
18
15
|
# This module defines the interface for status providers for components on status
|
|
19
16
|
# pages. A status provider is responsible for determining the status of a component.
|
|
@@ -70,7 +67,7 @@ class ManualStatusProvider(StatusProvider, BaseModel):
|
|
|
70
67
|
raise ValueError(
|
|
71
68
|
"manual component status time window is invalid: end before start"
|
|
72
69
|
)
|
|
73
|
-
now =
|
|
70
|
+
now = utc_now()
|
|
74
71
|
if self.start and now < self.start:
|
|
75
72
|
return False
|
|
76
73
|
return not (self.end and self.end < now)
|
|
@@ -84,8 +81,8 @@ def build_status_provider_config(
|
|
|
84
81
|
provider specific implementation that provides the status resolution logic.
|
|
85
82
|
"""
|
|
86
83
|
if isinstance(cfg, ManualStatusProviderV1):
|
|
87
|
-
start =
|
|
88
|
-
end =
|
|
84
|
+
start = from_utc_iso_format(cfg.manual.q_from) if cfg.manual.q_from else None
|
|
85
|
+
end = from_utc_iso_format(cfg.manual.until) if cfg.manual.until else None
|
|
89
86
|
return ManualStatusProvider(
|
|
90
87
|
component_status=cfg.manual.component_status,
|
|
91
88
|
start=start,
|
|
@@ -55,4 +55,8 @@ rosa create cluster -y --cluster-name={{ cluster_name }} \
|
|
|
55
55
|
{% if cluster.spec.provision_shard_id -%}
|
|
56
56
|
--properties provision_shard_id:{{ cluster.spec.provision_shard_id }} \
|
|
57
57
|
{% endif -%}
|
|
58
|
+
{% if cluster.spec.fips -%}
|
|
59
|
+
--fips \
|
|
60
|
+
{% endif -%}
|
|
58
61
|
--channel-group {{ cluster.spec.channel }}
|
|
62
|
+
|
|
@@ -59,4 +59,7 @@ rosa create cluster --cluster-name={{ cluster_name }} \
|
|
|
59
59
|
{% if cluster.spec.provision_shard_id -%}
|
|
60
60
|
--properties provision_shard_id:{{ cluster.spec.provision_shard_id }} \
|
|
61
61
|
{% endif -%}
|
|
62
|
+
{% if cluster.spec.fips -%}
|
|
63
|
+
--fips \
|
|
64
|
+
{% endif -%}
|
|
62
65
|
--channel-group {{ cluster.spec.channel }}
|
reconcile/templating/renderer.py
CHANGED
|
@@ -33,6 +33,7 @@ from reconcile.utils import gql
|
|
|
33
33
|
from reconcile.utils.git import checkout, clone
|
|
34
34
|
from reconcile.utils.gql import GqlApi
|
|
35
35
|
from reconcile.utils.jinja2.utils import TemplateRenderOptions, process_jinja2_template
|
|
36
|
+
from reconcile.utils.json import json_dumps
|
|
36
37
|
from reconcile.utils.ruamel import create_ruamel_instance
|
|
37
38
|
from reconcile.utils.runtime.integration import (
|
|
38
39
|
PydanticRunParams,
|
|
@@ -215,7 +216,7 @@ def unpack_static_variables(
|
|
|
215
216
|
each: dict[str, Any],
|
|
216
217
|
) -> dict:
|
|
217
218
|
return {
|
|
218
|
-
k: json.loads(process_jinja2_template(body=
|
|
219
|
+
k: json.loads(process_jinja2_template(body=json_dumps(v), vars={"each": each}))
|
|
219
220
|
for k, v in (collection_variables.static or {}).items()
|
|
220
221
|
}
|
|
221
222
|
|