qontract-reconcile 0.10.1rc1014__py3-none-any.whl → 0.10.1rc1016__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.1rc1014.dist-info → qontract_reconcile-0.10.1rc1016.dist-info}/METADATA +1 -1
- {qontract_reconcile-0.10.1rc1014.dist-info → qontract_reconcile-0.10.1rc1016.dist-info}/RECORD +9 -9
- reconcile/dynatrace_token_provider/integration.py +23 -39
- reconcile/utils/aws_api.py +1 -1
- reconcile/utils/dynatrace/client.py +6 -3
- reconcile/utils/terraform_client.py +31 -20
- {qontract_reconcile-0.10.1rc1014.dist-info → qontract_reconcile-0.10.1rc1016.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.1rc1014.dist-info → qontract_reconcile-0.10.1rc1016.dist-info}/entry_points.txt +0 -0
- {qontract_reconcile-0.10.1rc1014.dist-info → qontract_reconcile-0.10.1rc1016.dist-info}/top_level.txt +0 -0
{qontract_reconcile-0.10.1rc1014.dist-info → qontract_reconcile-0.10.1rc1016.dist-info}/METADATA
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: qontract-reconcile
|
3
|
-
Version: 0.10.
|
3
|
+
Version: 0.10.1rc1016
|
4
4
|
Summary: Collection of tools to reconcile services with their desired state as defined in the app-interface DB.
|
5
5
|
Home-page: https://github.com/app-sre/qontract-reconcile
|
6
6
|
Author: Red Hat App-SRE Team
|
{qontract_reconcile-0.10.1rc1014.dist-info → qontract_reconcile-0.10.1rc1016.dist-info}/RECORD
RENAMED
@@ -181,7 +181,7 @@ reconcile/cna/assets/asset_factory.py,sha256=7T7X_J6xIsoGETqBRI45_EyIKEdQcnRPt_G
|
|
181
181
|
reconcile/cna/assets/null.py,sha256=85mVh97atCoC0aLuX47poTZiyOthmziJeBsUw0c924w,1658
|
182
182
|
reconcile/dynatrace_token_provider/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
183
183
|
reconcile/dynatrace_token_provider/dependencies.py,sha256=41q05A4C_eS3E8-MR4veeMxtQNsPoGdxmEa3d-OKxq4,2814
|
184
|
-
reconcile/dynatrace_token_provider/integration.py,sha256=
|
184
|
+
reconcile/dynatrace_token_provider/integration.py,sha256=QY-k5vsbBOm80yW_RB6G2JZD5NY21zCyqHigos7GjRM,20876
|
185
185
|
reconcile/dynatrace_token_provider/metrics.py,sha256=xiKkl8fTEBQaXJelGCPNTZhHAWdO1M3pCXNr_Tei63c,1285
|
186
186
|
reconcile/dynatrace_token_provider/model.py,sha256=gkpqo5rRRueBXnIMjp4EEHqBUBuU65TRI8zpdb8GJ0A,241
|
187
187
|
reconcile/dynatrace_token_provider/ocm.py,sha256=iHMsgbsLs-dlrB9UXmWNDF7E4UDe49JOsLa9rnowKfo,4282
|
@@ -644,7 +644,7 @@ reconcile/unleash_feature_toggles/integration.py,sha256=nx7BhtzCsTfPbOp60vI5MkNw
|
|
644
644
|
reconcile/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
645
645
|
reconcile/utils/aggregated_list.py,sha256=km0xadW0jO4G_CqZPsXmoBURQ8c90FaTu5x4X1K1cZs,3357
|
646
646
|
reconcile/utils/amtool.py,sha256=ngtBuVPETH6oAy5RnKzvreVbjwQCaATS_PYYwBprzjQ,2288
|
647
|
-
reconcile/utils/aws_api.py,sha256=
|
647
|
+
reconcile/utils/aws_api.py,sha256=FHE7tVN91ZAVDARN9EYr7kY3kB6UWtvZSlsvHcDyzx8,66830
|
648
648
|
reconcile/utils/aws_helper.py,sha256=MDbv5jrNdqqJ5pfBxniGdJXBBO_EYc2_Uf2w9ZzeMNs,2854
|
649
649
|
reconcile/utils/batches.py,sha256=TtEm64a8lWhFuNbUVpFEmXVdU2Q0sTBrP_I0Cjbgh7g,320
|
650
650
|
reconcile/utils/binary.py,sha256=7MaAFBpzuBUTJ_aA6G6-eult_BPMVyiXbBLD0Y6F-DM,2301
|
@@ -716,7 +716,7 @@ reconcile/utils/sqs_gateway.py,sha256=XNIf3PY4UCPNufP2Ul0UJj3fKlt5larBba-VTT-41F
|
|
716
716
|
reconcile/utils/state.py,sha256=a_EO5u7__Pqd0_E3MqzUttJ-0xRtuxcNx5oQi5WIahI,16392
|
717
717
|
reconcile/utils/structs.py,sha256=LcbLEg8WxfRqM6nW7NhcWN0YeqF7SQzxOgntmLs1SgY,352
|
718
718
|
reconcile/utils/template.py,sha256=wTvRU4AnAV_o042tD4Mwls2dwWMuk7MKnde3MaCjaYg,331
|
719
|
-
reconcile/utils/terraform_client.py,sha256=
|
719
|
+
reconcile/utils/terraform_client.py,sha256=4eYKaKfG5wYfR--e1jHpmoMq36Q-JX1_WtT916wlMVw,34669
|
720
720
|
reconcile/utils/terrascript_aws_client.py,sha256=1JgXcCF_-xbaAg7V9qihL1Xz5okQlSSrT1DeXGducHc,278037
|
721
721
|
reconcile/utils/three_way_diff_strategy.py,sha256=oQcHXd9LVhirJfoaOBoHUYuZVGfyL2voKr6KVI34zZE,4833
|
722
722
|
reconcile/utils/throughput.py,sha256=iP4UWAe2LVhDo69mPPmgo9nQ7RxHD6_GS8MZe-aSiuM,344
|
@@ -744,7 +744,7 @@ reconcile/utils/clusterhealth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5N
|
|
744
744
|
reconcile/utils/clusterhealth/providerbase.py,sha256=DXomGYogckBLqWtXn0PXU0hWYxB6K0F7ernldrkHhVY,1140
|
745
745
|
reconcile/utils/clusterhealth/telemeter.py,sha256=PllSLsJXvGNatmTF4mxCNPVbDrpr_MPk0m5pWj-LT6g,1534
|
746
746
|
reconcile/utils/dynatrace/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
747
|
-
reconcile/utils/dynatrace/client.py,sha256=
|
747
|
+
reconcile/utils/dynatrace/client.py,sha256=dVaTwIlLhutv_2sxL_ISIQkN5br1Tfm14dhVP_hwePI,2834
|
748
748
|
reconcile/utils/glitchtip/__init__.py,sha256=FT6iBhGqoe7KExFdbgL8AYUb64iW_4snF5__Dcl7yt0,258
|
749
749
|
reconcile/utils/glitchtip/client.py,sha256=ovh4tx-ajlihjvcq6nyY4chulbuMJYvzDPv9j9CuAKM,7867
|
750
750
|
reconcile/utils/glitchtip/models.py,sha256=uHbCK9-RWgxNYUAkEHXRAZRDDZW7jkOFFt9MdlqN4bU,6481
|
@@ -859,8 +859,8 @@ tools/test/test_qontract_cli.py,sha256=_D61RFGAN5x44CY1tYbouhlGXXABwYfxKSWSQx3Jr
|
|
859
859
|
tools/test/test_saas_promotion_state.py,sha256=dy4kkSSAQ7bC0Xp2CociETGN-2aABEfL6FU5D9Jl00Y,6056
|
860
860
|
tools/test/test_sd_app_sre_alert_report.py,sha256=v363r9zM7__0kR5K6mvJoGFcM9BvE33fWAayrqkpojA,2116
|
861
861
|
tools/test/test_sre_checkpoints.py,sha256=SKqPPTl9ua0RFdSSofnoQX-JZE6dFLO3LRhfQzqtfh8,2607
|
862
|
-
qontract_reconcile-0.10.
|
863
|
-
qontract_reconcile-0.10.
|
864
|
-
qontract_reconcile-0.10.
|
865
|
-
qontract_reconcile-0.10.
|
866
|
-
qontract_reconcile-0.10.
|
862
|
+
qontract_reconcile-0.10.1rc1016.dist-info/METADATA,sha256=yZiOVjfUvuD98NWXAJmjOZenh3UfAagM6WdkE9BQ1xo,2263
|
863
|
+
qontract_reconcile-0.10.1rc1016.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
864
|
+
qontract_reconcile-0.10.1rc1016.dist-info/entry_points.txt,sha256=GKQqCl2j2X1BJQ69een6rHcR26PmnxnONLNOQB-nRjY,491
|
865
|
+
qontract_reconcile-0.10.1rc1016.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
|
866
|
+
qontract_reconcile-0.10.1rc1016.dist-info/RECORD,,
|
@@ -96,7 +96,7 @@ class DynatraceTokenProviderIntegration(
|
|
96
96
|
for cluster in clusters
|
97
97
|
if cluster.organization_id in self.params.ocm_organization_ids
|
98
98
|
]
|
99
|
-
existing_dtp_tokens = {}
|
99
|
+
existing_dtp_tokens: dict[str, dict[str, str]] = {}
|
100
100
|
|
101
101
|
for cluster in clusters:
|
102
102
|
try:
|
@@ -139,7 +139,7 @@ class DynatraceTokenProviderIntegration(
|
|
139
139
|
continue
|
140
140
|
if tenant_id not in existing_dtp_tokens:
|
141
141
|
existing_dtp_tokens[tenant_id] = (
|
142
|
-
dt_client.
|
142
|
+
dt_client.get_token_ids_map_for_name_prefix(
|
143
143
|
prefix="dtp-"
|
144
144
|
)
|
145
145
|
)
|
@@ -172,7 +172,7 @@ class DynatraceTokenProviderIntegration(
|
|
172
172
|
cluster: Cluster,
|
173
173
|
dt_client: DynatraceClient,
|
174
174
|
ocm_client: OCMClient,
|
175
|
-
existing_dtp_tokens:
|
175
|
+
existing_dtp_tokens: Mapping[str, str],
|
176
176
|
tenant_id: str,
|
177
177
|
token_spec: DynatraceTokenProviderTokenSpecV1,
|
178
178
|
) -> None:
|
@@ -281,7 +281,7 @@ class DynatraceTokenProviderIntegration(
|
|
281
281
|
dry_run: bool,
|
282
282
|
current_k8s_secrets: Iterable[K8sSecret],
|
283
283
|
desired_spec: DynatraceTokenProviderTokenSpecV1,
|
284
|
-
existing_dtp_tokens:
|
284
|
+
existing_dtp_tokens: Mapping[str, str],
|
285
285
|
dt_client: DynatraceClient,
|
286
286
|
cluster_uuid: str,
|
287
287
|
) -> tuple[bool, Iterable[K8sSecret]]:
|
@@ -377,15 +377,12 @@ class DynatraceTokenProviderIntegration(
|
|
377
377
|
raise e
|
378
378
|
return manifest
|
379
379
|
|
380
|
-
def
|
381
|
-
self,
|
380
|
+
def get_secrets_from_data(
|
381
|
+
self,
|
382
|
+
secret_data_by_name: Mapping[str, Any],
|
383
|
+
token_spec: DynatraceTokenProviderTokenSpecV1,
|
382
384
|
) -> list[K8sSecret]:
|
383
385
|
secrets: list[K8sSecret] = []
|
384
|
-
secret_data_by_name = {
|
385
|
-
resource.get("metadata", {}).get("name"): resource.get("data", {})
|
386
|
-
for resource in syncset.get("resources", [])
|
387
|
-
if resource.get("kind") == "Secret"
|
388
|
-
}
|
389
386
|
for secret in token_spec.secrets:
|
390
387
|
secret_data = secret_data_by_name.get(secret.name)
|
391
388
|
if secret_data:
|
@@ -414,42 +411,29 @@ class DynatraceTokenProviderIntegration(
|
|
414
411
|
)
|
415
412
|
return secrets
|
416
413
|
|
414
|
+
def get_secrets_from_syncset(
|
415
|
+
self, syncset: Mapping[str, Any], token_spec: DynatraceTokenProviderTokenSpecV1
|
416
|
+
) -> list[K8sSecret]:
|
417
|
+
secret_data_by_name = {
|
418
|
+
resource.get("metadata", {}).get("name"): resource.get("data", {})
|
419
|
+
for resource in syncset.get("resources", [])
|
420
|
+
if resource.get("kind") == "Secret"
|
421
|
+
}
|
422
|
+
return self.get_secrets_from_data(
|
423
|
+
secret_data_by_name=secret_data_by_name, token_spec=token_spec
|
424
|
+
)
|
425
|
+
|
417
426
|
def get_secrets_from_manifest(
|
418
427
|
self, manifest: Mapping[str, Any], token_spec: DynatraceTokenProviderTokenSpecV1
|
419
428
|
) -> list[K8sSecret]:
|
420
|
-
secrets: list[K8sSecret] = []
|
421
429
|
secret_data_by_name = {
|
422
430
|
resource.get("metadata", {}).get("name"): resource.get("data", {})
|
423
431
|
for resource in manifest.get("workloads", [])
|
424
432
|
if resource.get("kind") == "Secret"
|
425
433
|
}
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
tokens = []
|
430
|
-
for token in secret.tokens:
|
431
|
-
token_id = self.base64_decode(
|
432
|
-
secret_data.get(f"{token.key_name_in_secret}Id", "")
|
433
|
-
)
|
434
|
-
token_value = self.base64_decode(
|
435
|
-
secret_data.get(token.key_name_in_secret, "")
|
436
|
-
)
|
437
|
-
tokens.append(
|
438
|
-
DynatraceAPIToken(
|
439
|
-
id=token_id,
|
440
|
-
token=token_value,
|
441
|
-
name=token.name,
|
442
|
-
secret_key=token.key_name_in_secret,
|
443
|
-
)
|
444
|
-
)
|
445
|
-
secrets.append(
|
446
|
-
K8sSecret(
|
447
|
-
secret_name=secret.name,
|
448
|
-
namespace_name=secret.namespace,
|
449
|
-
tokens=tokens,
|
450
|
-
)
|
451
|
-
)
|
452
|
-
return secrets
|
434
|
+
return self.get_secrets_from_data(
|
435
|
+
secret_data_by_name=secret_data_by_name, token_spec=token_spec
|
436
|
+
)
|
453
437
|
|
454
438
|
def construct_secrets_data(
|
455
439
|
self,
|
reconcile/utils/aws_api.py
CHANGED
@@ -1646,7 +1646,7 @@ class AWSApi: # pylint: disable=too-many-public-methods
|
|
1646
1646
|
parameters = {}
|
1647
1647
|
for page in paginator.paginate(DBParameterGroupName=db_parameter_group_name):
|
1648
1648
|
for param in page.get("Parameters", []):
|
1649
|
-
parameters[param["ParameterName"]] = param
|
1649
|
+
parameters[param["ParameterName"]] = param.get("ParameterValue", "")
|
1650
1650
|
return parameters
|
1651
1651
|
|
1652
1652
|
def get_organization_billing_account(self, account_name: str) -> str:
|
@@ -49,14 +49,16 @@ class DynatraceClient:
|
|
49
49
|
) from e
|
50
50
|
return DynatraceAPITokenCreated(token=token.token, id=token.id)
|
51
51
|
|
52
|
-
def
|
52
|
+
def get_token_ids_map_for_name_prefix(self, prefix: str) -> dict[str, str]:
|
53
53
|
try:
|
54
54
|
dt_tokens = self._api.tokens.list()
|
55
55
|
except Exception as e:
|
56
56
|
raise DynatraceTokenRetrievalError(
|
57
57
|
f"{self._environment_url=} Failed to retrieve tokens for {prefix=}", e
|
58
58
|
) from e
|
59
|
-
return
|
59
|
+
return {
|
60
|
+
token.id: token.name for token in dt_tokens if token.name.startswith(prefix)
|
61
|
+
}
|
60
62
|
|
61
63
|
def get_token_by_id(self, token_id: str) -> DynatraceAPIToken:
|
62
64
|
try:
|
@@ -67,10 +69,11 @@ class DynatraceClient:
|
|
67
69
|
) from e
|
68
70
|
return DynatraceAPIToken(id=token.id, scopes=token.scopes)
|
69
71
|
|
70
|
-
def
|
72
|
+
def update_token(self, token_id: str, name: str, scopes: list[str]) -> None:
|
71
73
|
try:
|
72
74
|
self._api.tokens.put(
|
73
75
|
token_id=token_id,
|
76
|
+
name=name,
|
74
77
|
api_token=ApiTokenUpdate(
|
75
78
|
scopes=scopes,
|
76
79
|
),
|
@@ -772,40 +772,45 @@ class TerraformClient: # pylint: disable=too-many-public-methods
|
|
772
772
|
None,
|
773
773
|
)
|
774
774
|
if target is None:
|
775
|
-
|
775
|
+
logging.error(
|
776
776
|
f"Cannot upgrade RDS instance: {resource_name} "
|
777
777
|
f"from {before_version} to {after_version}"
|
778
778
|
)
|
779
|
+
return
|
779
780
|
allow_major_version_upgrade = after.get(
|
780
781
|
"allow_major_version_upgrade",
|
781
782
|
False,
|
782
783
|
)
|
783
784
|
if target["IsMajorVersionUpgrade"] and not allow_major_version_upgrade:
|
784
|
-
|
785
|
+
logging.error(
|
785
786
|
"allow_major_version_upgrade is not enabled for upgrading RDS instance: "
|
786
787
|
f"{resource_name} to a new major version."
|
787
788
|
)
|
789
|
+
return
|
788
790
|
|
789
|
-
blue_green_update = after.get("blue_green_update",
|
790
|
-
if blue_green_update:
|
791
|
+
blue_green_update = after.get("blue_green_update", [])
|
792
|
+
if blue_green_update and blue_green_update[0]["enabled"]:
|
793
|
+
replica = before["replicas"] != [] or before["replicate_source_db"]
|
791
794
|
self.validate_blue_green_update_requirements(
|
792
795
|
account_name,
|
796
|
+
resource_name,
|
793
797
|
engine,
|
794
|
-
|
795
|
-
|
796
|
-
before
|
798
|
+
before_version,
|
799
|
+
replica,
|
800
|
+
before["parameter_group_name"],
|
797
801
|
region_name,
|
798
802
|
)
|
799
803
|
|
800
804
|
def validate_blue_green_update_requirements(
|
801
805
|
self,
|
802
|
-
account_name,
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
806
|
+
account_name: str,
|
807
|
+
resource_name: str,
|
808
|
+
engine: str,
|
809
|
+
version: str,
|
810
|
+
replica: bool,
|
811
|
+
parameter_group: str,
|
812
|
+
region_name: str,
|
813
|
+
) -> None:
|
809
814
|
min_supported_versions = {
|
810
815
|
"mysql": [pkg_version.parse("5.7"), pkg_version.parse("8.0.15")],
|
811
816
|
"postgres": [
|
@@ -833,23 +838,29 @@ class TerraformClient: # pylint: disable=too-many-public-methods
|
|
833
838
|
return False
|
834
839
|
|
835
840
|
if not is_supported(engine, version):
|
836
|
-
|
841
|
+
logging.error(
|
842
|
+
f"Cannot upgrade RDS instance: {resource_name}. "
|
837
843
|
f"Engine version {version} is not supported for blue/green updates."
|
838
844
|
)
|
845
|
+
return
|
839
846
|
|
840
|
-
if
|
841
|
-
|
847
|
+
if replica:
|
848
|
+
logging.error(
|
849
|
+
f"Cannot upgrade RDS instance: {resource_name}. "
|
842
850
|
"Blue/green updates are not supported for instances with read replicas."
|
843
851
|
)
|
852
|
+
return
|
844
853
|
|
845
|
-
if engine == "postgres" and
|
854
|
+
if engine == "postgres" and self._aws_api is not None:
|
846
855
|
pg_details = self._aws_api.describe_db_parameter_group(
|
847
856
|
account_name, parameter_group, region_name
|
848
857
|
)
|
849
858
|
if pg_details.get("rds.logical_replication") != "1":
|
850
|
-
|
851
|
-
f"
|
859
|
+
logging.error(
|
860
|
+
f"Cannot upgrade RDS instance: {resource_name}. "
|
861
|
+
f"Blue/green updates require logical replication to be enabled in the Parameter group {parameter_group}."
|
852
862
|
)
|
863
|
+
return
|
853
864
|
|
854
865
|
|
855
866
|
class TerraformPlanFailed(Exception):
|
{qontract_reconcile-0.10.1rc1014.dist-info → qontract_reconcile-0.10.1rc1016.dist-info}/WHEEL
RENAMED
File without changes
|
File without changes
|
File without changes
|