qontract-reconcile 0.10.2.dev395__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.dev395.dist-info → qontract_reconcile-0.10.2.dev408.dist-info}/METADATA +2 -2
- {qontract_reconcile-0.10.2.dev395.dist-info → qontract_reconcile-0.10.2.dev408.dist-info}/RECORD +23 -23
- reconcile/automated_actions/config/integration.py +12 -0
- reconcile/aws_ami_share.py +69 -62
- reconcile/change_owners/change_owners.py +1 -1
- reconcile/endpoints_discovery/integration.py +4 -1
- reconcile/external_resources/integration.py +1 -1
- reconcile/external_resources/reconciler.py +5 -2
- reconcile/gql_definitions/automated_actions/instance.py +41 -2
- reconcile/gql_definitions/introspection.json +219 -0
- reconcile/ocm/types.py +6 -1
- reconcile/openshift_base.py +47 -1
- reconcile/openshift_resources_base.py +6 -2
- reconcile/queries.py +6 -0
- reconcile/utils/aws_api.py +51 -20
- reconcile/utils/jobcontroller/controller.py +1 -1
- reconcile/utils/jobcontroller/models.py +17 -1
- reconcile/utils/oc.py +107 -90
- reconcile/utils/ocm/products.py +5 -5
- reconcile/utils/openshift_resource.py +5 -0
- reconcile/utils/terrascript_aws_client.py +41 -40
- {qontract_reconcile-0.10.2.dev395.dist-info → qontract_reconcile-0.10.2.dev408.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.2.dev395.dist-info → qontract_reconcile-0.10.2.dev408.dist-info}/entry_points.txt +0 -0
reconcile/utils/oc.py
CHANGED
|
@@ -68,7 +68,8 @@ if TYPE_CHECKING:
|
|
|
68
68
|
urllib3.disable_warnings()
|
|
69
69
|
|
|
70
70
|
GET_REPLICASET_MAX_ATTEMPTS = 20
|
|
71
|
-
|
|
71
|
+
DEFAULT_GROUP = ""
|
|
72
|
+
PROJECT_KIND = "Project.project.openshift.io"
|
|
72
73
|
|
|
73
74
|
oc_run_execution_counter = Counter(
|
|
74
75
|
name="oc_run_execution_counter",
|
|
@@ -145,6 +146,14 @@ class RequestEntityTooLargeError(Exception):
|
|
|
145
146
|
pass
|
|
146
147
|
|
|
147
148
|
|
|
149
|
+
class KindNotFoundError(Exception):
|
|
150
|
+
pass
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
class AmbiguousResourceTypeError(Exception):
|
|
154
|
+
pass
|
|
155
|
+
|
|
156
|
+
|
|
148
157
|
class OCDecorators:
|
|
149
158
|
@classmethod
|
|
150
159
|
def process_reconcile_time(cls, function: Callable) -> Callable:
|
|
@@ -380,10 +389,7 @@ class OCCli:
|
|
|
380
389
|
|
|
381
390
|
self.init_projects = init_projects
|
|
382
391
|
if self.init_projects:
|
|
383
|
-
if self.is_kind_supported("
|
|
384
|
-
kind = "Project.project.openshift.io"
|
|
385
|
-
else:
|
|
386
|
-
kind = "Namespace"
|
|
392
|
+
kind = PROJECT_KIND if self.is_kind_supported(PROJECT_KIND) else "Namespace"
|
|
387
393
|
self.projects = {p["metadata"]["name"] for p in self.get_all(kind)["items"]}
|
|
388
394
|
|
|
389
395
|
self.slow_oc_reconcile_threshold = float(
|
|
@@ -453,10 +459,7 @@ class OCCli:
|
|
|
453
459
|
|
|
454
460
|
self.init_projects = init_projects
|
|
455
461
|
if self.init_projects:
|
|
456
|
-
if self.is_kind_supported("
|
|
457
|
-
kind = "Project.project.openshift.io"
|
|
458
|
-
else:
|
|
459
|
-
kind = "Namespace"
|
|
462
|
+
kind = PROJECT_KIND if self.is_kind_supported(PROJECT_KIND) else "Namespace"
|
|
460
463
|
self.projects = {p["metadata"]["name"] for p in self.get_all(kind)["items"]}
|
|
461
464
|
|
|
462
465
|
self.slow_oc_reconcile_threshold = float(
|
|
@@ -637,11 +640,9 @@ class OCCli:
|
|
|
637
640
|
def project_exists(self, name: str) -> bool:
|
|
638
641
|
if name in self.projects:
|
|
639
642
|
return True
|
|
643
|
+
kind = PROJECT_KIND if self.is_kind_supported(PROJECT_KIND) else "Namespace"
|
|
640
644
|
try:
|
|
641
|
-
|
|
642
|
-
self.get(None, "Project.project.openshift.io", name)
|
|
643
|
-
else:
|
|
644
|
-
self.get(None, "Namespace", name)
|
|
645
|
+
self.get(None, kind, name)
|
|
645
646
|
except StatusCodeError as e:
|
|
646
647
|
if "NotFound" in str(e):
|
|
647
648
|
return False
|
|
@@ -650,7 +651,7 @@ class OCCli:
|
|
|
650
651
|
|
|
651
652
|
@OCDecorators.process_reconcile_time
|
|
652
653
|
def new_project(self, namespace: str) -> OCProcessReconcileTimeDecoratorMsg:
|
|
653
|
-
if self.is_kind_supported(
|
|
654
|
+
if self.is_kind_supported(PROJECT_KIND):
|
|
654
655
|
cmd = ["new-project", namespace]
|
|
655
656
|
else:
|
|
656
657
|
cmd = ["create", "namespace", namespace]
|
|
@@ -666,7 +667,7 @@ class OCCli:
|
|
|
666
667
|
|
|
667
668
|
@OCDecorators.process_reconcile_time
|
|
668
669
|
def delete_project(self, namespace: str) -> OCProcessReconcileTimeDecoratorMsg:
|
|
669
|
-
if self.is_kind_supported(
|
|
670
|
+
if self.is_kind_supported(PROJECT_KIND):
|
|
670
671
|
cmd = ["delete", "project", namespace]
|
|
671
672
|
else:
|
|
672
673
|
cmd = ["delete", "namespace", namespace]
|
|
@@ -717,7 +718,7 @@ class OCCli:
|
|
|
717
718
|
cmd = ["sa", "-n", namespace, "get-token", name]
|
|
718
719
|
return self._run(cmd)
|
|
719
720
|
|
|
720
|
-
def get_api_resources(self) -> dict[str,
|
|
721
|
+
def get_api_resources(self) -> dict[str, list[OCCliApiResource]]:
|
|
721
722
|
with self.api_resources_lock:
|
|
722
723
|
if not self.api_resources:
|
|
723
724
|
cmd = ["api-resources", "--no-headers"]
|
|
@@ -1196,76 +1197,90 @@ class OCCli:
|
|
|
1196
1197
|
|
|
1197
1198
|
return out_json
|
|
1198
1199
|
|
|
1199
|
-
def
|
|
1200
|
-
|
|
1201
|
-
# the api resources initialization.
|
|
1202
|
-
if not self.api_resources:
|
|
1203
|
-
self.get_api_resources()
|
|
1200
|
+
def parse_kind(self, kind: str) -> tuple[str, str, str]:
|
|
1201
|
+
"""Parse a Kubernetes kind string into its components.
|
|
1204
1202
|
|
|
1205
|
-
|
|
1206
|
-
kind
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
else:
|
|
1210
|
-
raise StatusCodeError(f"{self.server}: {kind} does not exist")
|
|
1211
|
-
|
|
1212
|
-
# if a kind_group has more than 1 entry than the kind_name is in
|
|
1213
|
-
# the format kind.apigroup. Find the apigroup/version that matches
|
|
1214
|
-
# the apigroup passed with the kind_name
|
|
1215
|
-
if len(kind_group) > 1:
|
|
1216
|
-
apigroup_override = kind_group[1]
|
|
1217
|
-
find = False
|
|
1218
|
-
for gv in self.api_resources[kind]:
|
|
1219
|
-
if apigroup_override == gv.group:
|
|
1220
|
-
if not gv.group:
|
|
1221
|
-
group_version = gv.api_version
|
|
1222
|
-
else:
|
|
1223
|
-
group_version = f"{gv.group}/{gv.api_version}"
|
|
1224
|
-
find = True
|
|
1225
|
-
break
|
|
1203
|
+
Supports three formats:
|
|
1204
|
+
- kind
|
|
1205
|
+
- kind.group.whatever
|
|
1206
|
+
- kind.group.whatever/version
|
|
1226
1207
|
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1208
|
+
Args:
|
|
1209
|
+
kind: A Kubernetes kind string in one of the supported formats
|
|
1210
|
+
|
|
1211
|
+
Returns:
|
|
1212
|
+
Tuple of (kind, group, version) where missing parts are empty strings
|
|
1213
|
+
|
|
1214
|
+
Raises:
|
|
1215
|
+
ValueError: If the kind string format is invalid
|
|
1216
|
+
|
|
1217
|
+
Examples:
|
|
1218
|
+
>>> parse_kind_string("Deployment")
|
|
1219
|
+
('Deployment', '', '')
|
|
1220
|
+
>>> parse_kind_string("ClusterRoleBinding.rbac.authorization.k8s.io")
|
|
1221
|
+
('ClusterRoleBinding', 'rbac.authorization.k8s.io', '')
|
|
1222
|
+
>>> parse_kind_string("CustomResource.mygroup.example.com/v1")
|
|
1223
|
+
('CustomResource', 'mygroup.example.com', 'v1')
|
|
1224
|
+
"""
|
|
1225
|
+
pattern = r"^(?P<kind>[^./]+)(?:\.(?P<group>[^/]+))?(?:/(?P<version>.+))?$"
|
|
1226
|
+
match = re.match(pattern, kind)
|
|
1227
|
+
if not match:
|
|
1228
|
+
raise ValueError(f"Invalid kind string: {kind}")
|
|
1229
|
+
|
|
1230
|
+
kind = match.group("kind") or ""
|
|
1231
|
+
group = match.group("group") or DEFAULT_GROUP
|
|
1232
|
+
version = match.group("version") or ""
|
|
1233
|
+
|
|
1234
|
+
return kind, group, version
|
|
1232
1235
|
|
|
1233
1236
|
def is_kind_supported(self, kind: str) -> bool:
|
|
1234
|
-
|
|
1235
|
-
# the api resources initialization.
|
|
1236
|
-
if not self.api_resources:
|
|
1237
|
-
self.get_api_resources()
|
|
1237
|
+
"""Returns True if the given kind is supported by the cluster, False otherwise.
|
|
1238
1238
|
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
else:
|
|
1246
|
-
return kind in self.api_resources
|
|
1239
|
+
Kind can be either kind, kind.group or kind.group/version."""
|
|
1240
|
+
try:
|
|
1241
|
+
self.get_api_resource(kind)
|
|
1242
|
+
return True
|
|
1243
|
+
except KindNotFoundError:
|
|
1244
|
+
return False
|
|
1247
1245
|
|
|
1248
1246
|
def is_kind_namespaced(self, kind: str) -> bool:
|
|
1249
|
-
|
|
1250
|
-
|
|
1247
|
+
"""Returns True if the given kind is namespaced, False if it's cluster scoped.
|
|
1248
|
+
|
|
1249
|
+
Kind can be either kind, kind.group or kind.group/version."""
|
|
1250
|
+
return self.get_api_resource(kind).namespaced
|
|
1251
|
+
|
|
1252
|
+
def get_api_resource(self, kind: str) -> OCCliApiResource:
|
|
1253
|
+
"""Return the OCCliApiResource for the given resource type.
|
|
1254
|
+
|
|
1255
|
+
Resource type can be either kind, kind.group or kind.group/version.
|
|
1256
|
+
If kind is not unique, group must be specified."""
|
|
1257
|
+
|
|
1251
1258
|
if not self.api_resources:
|
|
1252
|
-
|
|
1259
|
+
raise RuntimeError("API resources not initialized")
|
|
1253
1260
|
|
|
1254
|
-
|
|
1255
|
-
kind = kg[0]
|
|
1261
|
+
kind, group, _ = self.parse_kind(kind)
|
|
1256
1262
|
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
raise StatusCodeError(f"Kind {kind} does not exist in the ApiServer")
|
|
1263
|
+
if not (resources := self.api_resources.get(kind)):
|
|
1264
|
+
# the kind not found at all
|
|
1265
|
+
raise KindNotFoundError(f"Unsupported resource type: {kind}")
|
|
1261
1266
|
|
|
1262
|
-
if len(
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1267
|
+
if len(resources) == 1 and group == DEFAULT_GROUP:
|
|
1268
|
+
return resources[0]
|
|
1269
|
+
|
|
1270
|
+
# get the resource with the specified group
|
|
1271
|
+
if resource := next((r for r in resources if r.group == group), None):
|
|
1272
|
+
return resource
|
|
1273
|
+
|
|
1274
|
+
# no resource with the specified group found
|
|
1275
|
+
if group == DEFAULT_GROUP:
|
|
1276
|
+
message = (
|
|
1277
|
+
f"Ambiguous resource type: {kind}. "
|
|
1278
|
+
"Please fully qualify it with its API group. E.g., ClusterRoleBinding -> ClusterRoleBinding.rbac.authorization.k8s.io"
|
|
1279
|
+
)
|
|
1280
|
+
raise AmbiguousResourceTypeError(message)
|
|
1281
|
+
|
|
1282
|
+
# group was specified but no matching resource found
|
|
1283
|
+
raise KindNotFoundError(f"Unsupported resource type: {kind}")
|
|
1269
1284
|
|
|
1270
1285
|
|
|
1271
1286
|
REQUEST_TIMEOUT = 60
|
|
@@ -1305,20 +1320,16 @@ class OCNative(OCCli):
|
|
|
1305
1320
|
|
|
1306
1321
|
server = connection_parameters.server_url
|
|
1307
1322
|
|
|
1308
|
-
if server:
|
|
1309
|
-
|
|
1310
|
-
self.api_resources = self.get_api_resources()
|
|
1323
|
+
if not server:
|
|
1324
|
+
raise Exception("Server name is required!")
|
|
1311
1325
|
|
|
1312
|
-
|
|
1313
|
-
|
|
1326
|
+
self.client = self._get_client(server, token)
|
|
1327
|
+
self.api_resources = self.get_api_resources()
|
|
1314
1328
|
|
|
1315
1329
|
self.projects = set()
|
|
1316
1330
|
self.init_projects = init_projects
|
|
1317
1331
|
if self.init_projects:
|
|
1318
|
-
if self.is_kind_supported("
|
|
1319
|
-
kind = "Project.project.openshift.io"
|
|
1320
|
-
else:
|
|
1321
|
-
kind = "Namespace"
|
|
1332
|
+
kind = PROJECT_KIND if self.is_kind_supported(PROJECT_KIND) else "Namespace"
|
|
1322
1333
|
self.projects = {p["metadata"]["name"] for p in self.get_all(kind)["items"]}
|
|
1323
1334
|
|
|
1324
1335
|
def __enter__(self) -> OCNative:
|
|
@@ -1368,8 +1379,10 @@ class OCNative(OCCli):
|
|
|
1368
1379
|
|
|
1369
1380
|
@retry(max_attempts=5, exceptions=(ServerTimeoutError))
|
|
1370
1381
|
def get_items(self, kind: str, **kwargs: Any) -> list[dict[str, Any]]:
|
|
1371
|
-
|
|
1372
|
-
obj_client = self._get_obj_client(
|
|
1382
|
+
resource = self.get_api_resource(kind)
|
|
1383
|
+
obj_client = self._get_obj_client(
|
|
1384
|
+
group_version=resource.group_version, kind=resource.kind
|
|
1385
|
+
)
|
|
1373
1386
|
|
|
1374
1387
|
namespace = ""
|
|
1375
1388
|
if "namespace" in kwargs:
|
|
@@ -1421,8 +1434,10 @@ class OCNative(OCCli):
|
|
|
1421
1434
|
name: str | None = None,
|
|
1422
1435
|
allow_not_found: bool = False,
|
|
1423
1436
|
) -> dict[str, Any]:
|
|
1424
|
-
|
|
1425
|
-
obj_client = self._get_obj_client(
|
|
1437
|
+
resource = self.get_api_resource(kind)
|
|
1438
|
+
obj_client = self._get_obj_client(
|
|
1439
|
+
group_version=resource.group_version, kind=resource.kind
|
|
1440
|
+
)
|
|
1426
1441
|
try:
|
|
1427
1442
|
obj = obj_client.get(
|
|
1428
1443
|
name=name,
|
|
@@ -1436,8 +1451,10 @@ class OCNative(OCCli):
|
|
|
1436
1451
|
raise StatusCodeError(f"[{self.server}]: {e}") from None
|
|
1437
1452
|
|
|
1438
1453
|
def get_all(self, kind: str, all_namespaces: bool = False) -> dict[str, Any]:
|
|
1439
|
-
|
|
1440
|
-
obj_client = self._get_obj_client(
|
|
1454
|
+
resource = self.get_api_resource(kind)
|
|
1455
|
+
obj_client = self._get_obj_client(
|
|
1456
|
+
group_version=resource.group_version, kind=resource.kind
|
|
1457
|
+
)
|
|
1441
1458
|
try:
|
|
1442
1459
|
return obj_client.get(_request_timeout=REQUEST_TIMEOUT).to_dict()
|
|
1443
1460
|
except NotFoundError as e:
|
reconcile/utils/ocm/products.py
CHANGED
|
@@ -178,7 +178,7 @@ class OCMProductOsd(OCMProduct):
|
|
|
178
178
|
],
|
|
179
179
|
provision_shard_id=provision_shard_id,
|
|
180
180
|
hypershift=cluster["hypershift"]["enabled"],
|
|
181
|
-
fips=cluster.get("fips"),
|
|
181
|
+
fips=cluster.get("fips") or False,
|
|
182
182
|
)
|
|
183
183
|
|
|
184
184
|
if not cluster["ccs"]["enabled"]:
|
|
@@ -259,7 +259,7 @@ class OCMProductOsd(OCMProduct):
|
|
|
259
259
|
if (duwm := cluster.spec.disable_user_workload_monitoring) is not None
|
|
260
260
|
else True
|
|
261
261
|
),
|
|
262
|
-
"fips":
|
|
262
|
+
"fips": cluster.spec.fips,
|
|
263
263
|
}
|
|
264
264
|
|
|
265
265
|
# Workaround to enable type checks.
|
|
@@ -429,7 +429,7 @@ class OCMProductRosa(OCMProduct):
|
|
|
429
429
|
subnet_ids=cluster["aws"].get("subnet_ids"),
|
|
430
430
|
availability_zones=cluster["nodes"].get("availability_zones"),
|
|
431
431
|
oidc_endpoint_url=oidc_endpoint_url,
|
|
432
|
-
fips=cluster.get("fips"),
|
|
432
|
+
fips=cluster.get("fips") or False,
|
|
433
433
|
)
|
|
434
434
|
|
|
435
435
|
machine_pools = [
|
|
@@ -517,7 +517,7 @@ class OCMProductRosa(OCMProduct):
|
|
|
517
517
|
if (duwm := cluster.spec.disable_user_workload_monitoring) is not None
|
|
518
518
|
else True
|
|
519
519
|
),
|
|
520
|
-
"fips":
|
|
520
|
+
"fips": cluster.spec.fips,
|
|
521
521
|
}
|
|
522
522
|
|
|
523
523
|
provision_shard_id = cluster.spec.provision_shard_id
|
|
@@ -706,7 +706,7 @@ class OCMProductHypershift(OCMProduct):
|
|
|
706
706
|
availability_zones=cluster["nodes"].get("availability_zones"),
|
|
707
707
|
hypershift=cluster["hypershift"]["enabled"],
|
|
708
708
|
oidc_endpoint_url=oidc_endpoint_url,
|
|
709
|
-
fips=cluster.get("fips"),
|
|
709
|
+
fips=cluster.get("fips") or False,
|
|
710
710
|
)
|
|
711
711
|
|
|
712
712
|
network = OCMClusterNetwork(
|
|
@@ -5,6 +5,7 @@ import base64
|
|
|
5
5
|
import contextlib
|
|
6
6
|
import copy
|
|
7
7
|
import hashlib
|
|
8
|
+
import logging
|
|
8
9
|
import re
|
|
9
10
|
from threading import Lock
|
|
10
11
|
from typing import TYPE_CHECKING, Any
|
|
@@ -601,6 +602,10 @@ class ResourceInventory:
|
|
|
601
602
|
resource: OpenshiftResource,
|
|
602
603
|
privileged: bool = False,
|
|
603
604
|
) -> None:
|
|
605
|
+
if cluster not in self._clusters:
|
|
606
|
+
logging.error(f"Cluster {cluster} not initialized in ResourceInventory")
|
|
607
|
+
return
|
|
608
|
+
|
|
604
609
|
if resource.kind_and_group in self._clusters[cluster][namespace]:
|
|
605
610
|
kind = resource.kind_and_group
|
|
606
611
|
else:
|
|
@@ -2210,6 +2210,43 @@ class TerrascriptClient:
|
|
|
2210
2210
|
letters_and_digits = string.ascii_letters + string.digits
|
|
2211
2211
|
return "".join(random.choice(letters_and_digits) for i in range(string_length))
|
|
2212
2212
|
|
|
2213
|
+
@staticmethod
|
|
2214
|
+
def _build_tf_resource_s3_lifecycle_rules(
|
|
2215
|
+
versioning: bool,
|
|
2216
|
+
common_values: Mapping[str, Any],
|
|
2217
|
+
) -> list[dict]:
|
|
2218
|
+
lifecycle_rules = common_values.get("lifecycle_rules") or []
|
|
2219
|
+
if versioning and not any(
|
|
2220
|
+
"noncurrent_version_expiration" in lr for lr in lifecycle_rules
|
|
2221
|
+
):
|
|
2222
|
+
# Add a default noncurrent object expiration rule
|
|
2223
|
+
# if one isn't already set
|
|
2224
|
+
rule = {
|
|
2225
|
+
"id": "expire_noncurrent_versions",
|
|
2226
|
+
"enabled": True,
|
|
2227
|
+
"noncurrent_version_expiration": {"days": 30},
|
|
2228
|
+
"expiration": {"expired_object_delete_marker": True},
|
|
2229
|
+
"abort_incomplete_multipart_upload_days": 3,
|
|
2230
|
+
}
|
|
2231
|
+
lifecycle_rules.append(rule)
|
|
2232
|
+
|
|
2233
|
+
if storage_class := common_values.get("storage_class"):
|
|
2234
|
+
sc = storage_class.upper()
|
|
2235
|
+
days = "1"
|
|
2236
|
+
if sc.endswith("_IA"):
|
|
2237
|
+
# Infrequent Access storage class has minimum 30 days
|
|
2238
|
+
# before transition
|
|
2239
|
+
days = "30"
|
|
2240
|
+
rule = {
|
|
2241
|
+
"id": sc + "_storage_class",
|
|
2242
|
+
"enabled": True,
|
|
2243
|
+
"transition": {"days": days, "storage_class": sc},
|
|
2244
|
+
"noncurrent_version_transition": {"days": days, "storage_class": sc},
|
|
2245
|
+
}
|
|
2246
|
+
lifecycle_rules.append(rule)
|
|
2247
|
+
|
|
2248
|
+
return lifecycle_rules
|
|
2249
|
+
|
|
2213
2250
|
def populate_tf_resource_s3(self, spec: ExternalResourceSpec) -> aws_s3_bucket:
|
|
2214
2251
|
account = spec.provisioner_name
|
|
2215
2252
|
identifier = spec.identifier
|
|
@@ -2249,47 +2286,11 @@ class TerrascriptClient:
|
|
|
2249
2286
|
request_payer = common_values.get("request_payer")
|
|
2250
2287
|
if request_payer:
|
|
2251
2288
|
values["request_payer"] = request_payer
|
|
2252
|
-
lifecycle_rules
|
|
2253
|
-
|
|
2254
|
-
|
|
2289
|
+
if lifecycle_rules := self._build_tf_resource_s3_lifecycle_rules(
|
|
2290
|
+
versioning=versioning,
|
|
2291
|
+
common_values=common_values,
|
|
2292
|
+
):
|
|
2255
2293
|
values["lifecycle_rule"] = lifecycle_rules
|
|
2256
|
-
if versioning:
|
|
2257
|
-
lrs = values.get("lifecycle_rule", [])
|
|
2258
|
-
expiration_rule = False
|
|
2259
|
-
for lr in lrs:
|
|
2260
|
-
if "noncurrent_version_expiration" in lr:
|
|
2261
|
-
expiration_rule = True
|
|
2262
|
-
break
|
|
2263
|
-
if not expiration_rule:
|
|
2264
|
-
# Add a default noncurrent object expiration rule if
|
|
2265
|
-
# if one isn't already set
|
|
2266
|
-
rule = {
|
|
2267
|
-
"id": "expire_noncurrent_versions",
|
|
2268
|
-
"enabled": "true",
|
|
2269
|
-
"noncurrent_version_expiration": {"days": 30},
|
|
2270
|
-
}
|
|
2271
|
-
if len(lrs) > 0:
|
|
2272
|
-
lrs.append(rule)
|
|
2273
|
-
else:
|
|
2274
|
-
lrs = rule
|
|
2275
|
-
sc = common_values.get("storage_class")
|
|
2276
|
-
if sc:
|
|
2277
|
-
sc = sc.upper()
|
|
2278
|
-
days = "1"
|
|
2279
|
-
if sc.endswith("_IA"):
|
|
2280
|
-
# Infrequent Access storage class has minimum 30 days
|
|
2281
|
-
# before transition
|
|
2282
|
-
days = "30"
|
|
2283
|
-
rule = {
|
|
2284
|
-
"id": sc + "_storage_class",
|
|
2285
|
-
"enabled": "true",
|
|
2286
|
-
"transition": {"days": days, "storage_class": sc},
|
|
2287
|
-
"noncurrent_version_transition": {"days": days, "storage_class": sc},
|
|
2288
|
-
}
|
|
2289
|
-
if values.get("lifecycle_rule"):
|
|
2290
|
-
values["lifecycle_rule"].append(rule)
|
|
2291
|
-
else:
|
|
2292
|
-
values["lifecycle_rule"] = rule
|
|
2293
2294
|
cors_rules = common_values.get("cors_rules")
|
|
2294
2295
|
if cors_rules:
|
|
2295
2296
|
# common_values['cors_rules'] is a list of cors_rules
|
{qontract_reconcile-0.10.2.dev395.dist-info → qontract_reconcile-0.10.2.dev408.dist-info}/WHEEL
RENAMED
|
File without changes
|
|
File without changes
|