qontract-reconcile 0.10.1rc1064__py3-none-any.whl → 0.10.1rc1065__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: qontract-reconcile
3
- Version: 0.10.1rc1064
3
+ Version: 0.10.1rc1065
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
@@ -192,14 +192,14 @@ reconcile/endpoints_discovery/integration.py,sha256=q01DJgCv1YiDY-VUWDfQ5kfGm67B
192
192
  reconcile/endpoints_discovery/merge_request.py,sha256=_yLb4tnvoZMCko8rta2C_CvOInJa9pa3HzSmHNtjgGU,2978
193
193
  reconcile/endpoints_discovery/merge_request_manager.py,sha256=wUMsumxv8RnWaRattax4HfoRlhtVzmgro3GiJJ1C4Vc,6392
194
194
  reconcile/external_resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
195
- reconcile/external_resources/aws.py,sha256=JvjKaABy2Pg8u8Lq82Acv4zMvpE3_qGKes7OG-zlHOM,2956
196
- reconcile/external_resources/factories.py,sha256=DXgaLxoO87zZ76VOpRpu2GeYGhsbfOnOx5mrzgo4Gf4,4767
195
+ reconcile/external_resources/aws.py,sha256=7W-6d-lXO6JGwaxtO1Uc3Lw0p8csJ1EVgz__O1YWUOc,4793
196
+ reconcile/external_resources/factories.py,sha256=nhdTqf1WEfRfgd5-70KAUJVz0ZvZ19C3Pz7wmotSdrs,4857
197
197
  reconcile/external_resources/integration.py,sha256=y1gJ16woMBC3J9qniMmS5y3lCkAs7V_ETZRUwjKqaO0,6628
198
198
  reconcile/external_resources/integration_secrets_sync.py,sha256=cMEZhgCvABAMf-DWF051L6CRnJQdfbsISA_b1xuS940,1670
199
- reconcile/external_resources/manager.py,sha256=Q1l53Q0QHS7dvxCU66_BBpWLpNf6he0FfNzxVKJmVN8,15102
199
+ reconcile/external_resources/manager.py,sha256=FqOkwiWY6X8qlwE7yrwjiVxKKmZ3k0TdafQnqfihXF8,15107
200
200
  reconcile/external_resources/meta.py,sha256=noaytFzmShpzLA_ebGh7wuP45mOfHIOnnoUxivjDa1I,672
201
201
  reconcile/external_resources/metrics.py,sha256=m2TIOao2N7pD6k45driFbBGVCC_N7ai44m-lLPfa5qk,454
202
- reconcile/external_resources/model.py,sha256=RjGMHgt_J1_HQjfBodFGvdWpYKJupKB4xtWuggSnMtA,8270
202
+ reconcile/external_resources/model.py,sha256=UuQgrnv-SSkvSEQQGeCE2IZkhXjLTCVkP_mw8zBZsIQ,8349
203
203
  reconcile/external_resources/reconciler.py,sha256=E50X_lnOD0OWYXMzyZld1P6dCFJFYjHGyICWff9bxlc,9323
204
204
  reconcile/external_resources/secrets_sync.py,sha256=6n0oDPLjd9Ql0lf6zsr1AZw8A6EEe3yCzl20XodtgkE,16229
205
205
  reconcile/external_resources/state.py,sha256=fKU6PLYOZ2ZTaIwvt1BNlNOnIqcewLijOyT3Lgcd1NE,9677
@@ -291,7 +291,7 @@ reconcile/gql_definitions/endpoints_discovery/namespaces.py,sha256=FqJ0H7NdsIm5B
291
291
  reconcile/gql_definitions/external_resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
292
292
  reconcile/gql_definitions/external_resources/aws_accounts.py,sha256=XR69j9dpTQ0gv8y-AZN7AJ0dPvO-wbHscyCDgrax6Bk,2046
293
293
  reconcile/gql_definitions/external_resources/external_resources_modules.py,sha256=HFOQjmNbNxk0j5nChxppQeCnJjeDsqibJkPgA7R1zRw,2417
294
- reconcile/gql_definitions/external_resources/external_resources_namespaces.py,sha256=uNk0HOAH96qdLuDBE6VzjcIPB--PHvOLDitJ2IzPM40,41618
294
+ reconcile/gql_definitions/external_resources/external_resources_namespaces.py,sha256=6WiI1exSzyEel_vOeVH3zitroGXI7JqDkDSKav_SzT4,42483
295
295
  reconcile/gql_definitions/external_resources/external_resources_settings.py,sha256=Hw9n_90BPG6Lnt2PT3mHc6p0KEm2CxKxvSGRFc_Dhus,2982
296
296
  reconcile/gql_definitions/fragments/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
297
297
  reconcile/gql_definitions/fragments/aus_organization.py,sha256=uBKbTuBa3CZmTXR5HOcGhRcu2U9kM93KbYmoWTxcpB0,4767
@@ -399,7 +399,7 @@ reconcile/gql_definitions/terraform_repo/__init__.py,sha256=47DEQpj8HBSa-_TImW-5
399
399
  reconcile/gql_definitions/terraform_repo/terraform_repo.py,sha256=nm4CH7Vog4aabdvCKmhVSUvoUb7dxSLx8nwAEJAVqG0,3706
400
400
  reconcile/gql_definitions/terraform_resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
401
401
  reconcile/gql_definitions/terraform_resources/database_access_manager.py,sha256=yv0_YC-LmhaKD_gyGG3le1w5BtypBjlsO894-Zgdg4U,4813
402
- reconcile/gql_definitions/terraform_resources/terraform_resources_namespaces.py,sha256=1PQBvcJjErRaG529kAzMwfw-ShNaM92IQovlwEiYrV8,42491
402
+ reconcile/gql_definitions/terraform_resources/terraform_resources_namespaces.py,sha256=KnqoorTaTJhkdvGiUfnA7qqzgDDf7X9wre7kbKCUARk,42597
403
403
  reconcile/gql_definitions/terraform_tgw_attachments/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
404
404
  reconcile/gql_definitions/terraform_tgw_attachments/aws_accounts.py,sha256=FPyPEikpkZ_kvHfXqnkzSUDNmxMMTiUwhI-eLQtuIHM,2616
405
405
  reconcile/gql_definitions/unleash_feature_toggles/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -697,7 +697,7 @@ reconcile/utils/make.py,sha256=QaEwucrzbl8-VHS66Wfdjfo0ubmAcvt_hZGpiGsKU50,231
697
697
  reconcile/utils/metrics.py,sha256=QN37XJDajWt-FdVGgqqDUkhemwTj0srfb-rhkIBxvsE,18591
698
698
  reconcile/utils/models.py,sha256=BYsgjWyuwO7obMhqADsqEQ-_YJrmy8LmFKHSLMFbo1g,4645
699
699
  reconcile/utils/oauth2_backend_application_session.py,sha256=6W16sMpnWEPFDUX7qi5Cui2yOnmLfpgUxWtB3Ii35D0,4177
700
- reconcile/utils/oc.py,sha256=RuVXqvjofz8Vvf_eisvOxOEK1A6KrOq8FQI2YUAAYoM,65796
700
+ reconcile/utils/oc.py,sha256=tHhkBFWCqg6sDo5fbfvSkBhc3jHHM8BFzQGypoHcKYc,65862
701
701
  reconcile/utils/oc_connection_parameters.py,sha256=7DiEGo--TJelfYoZXJFyTBPeTw9kXL3L58vy2fiJnes,9643
702
702
  reconcile/utils/oc_filters.py,sha256=Tz3OwtbUaYKmxENFls5CtPVzkZDeFXknw53dJe-wbT8,1382
703
703
  reconcile/utils/oc_map.py,sha256=U8cYhiaZsomkofzbIjVrl7E7crRxkS2JKsFpVeeHVE8,8964
@@ -868,8 +868,8 @@ tools/test/test_qontract_cli.py,sha256=_D61RFGAN5x44CY1tYbouhlGXXABwYfxKSWSQx3Jr
868
868
  tools/test/test_saas_promotion_state.py,sha256=dy4kkSSAQ7bC0Xp2CociETGN-2aABEfL6FU5D9Jl00Y,6056
869
869
  tools/test/test_sd_app_sre_alert_report.py,sha256=v363r9zM7__0kR5K6mvJoGFcM9BvE33fWAayrqkpojA,2116
870
870
  tools/test/test_sre_checkpoints.py,sha256=SKqPPTl9ua0RFdSSofnoQX-JZE6dFLO3LRhfQzqtfh8,2607
871
- qontract_reconcile-0.10.1rc1064.dist-info/METADATA,sha256=zhmq1Fv6WMFLlItqLsy0MfDZKKWBqgzndiykQ9TT4ic,2213
872
- qontract_reconcile-0.10.1rc1064.dist-info/WHEEL,sha256=eOLhNAGa2EW3wWl_TU484h7q1UNgy0JXjjoqKoxAAQc,92
873
- qontract_reconcile-0.10.1rc1064.dist-info/entry_points.txt,sha256=GKQqCl2j2X1BJQ69een6rHcR26PmnxnONLNOQB-nRjY,491
874
- qontract_reconcile-0.10.1rc1064.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
875
- qontract_reconcile-0.10.1rc1064.dist-info/RECORD,,
871
+ qontract_reconcile-0.10.1rc1065.dist-info/METADATA,sha256=m4tokwe6Lqt4qrgjrUnsAPAuYikH3iysJX1DQQgfDaU,2213
872
+ qontract_reconcile-0.10.1rc1065.dist-info/WHEEL,sha256=eOLhNAGa2EW3wWl_TU484h7q1UNgy0JXjjoqKoxAAQc,92
873
+ qontract_reconcile-0.10.1rc1065.dist-info/entry_points.txt,sha256=GKQqCl2j2X1BJQ69een6rHcR26PmnxnONLNOQB-nRjY,491
874
+ qontract_reconcile-0.10.1rc1065.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
875
+ qontract_reconcile-0.10.1rc1065.dist-info/RECORD,,
@@ -14,10 +14,10 @@ from reconcile.utils.secret_reader import SecretReaderBase
14
14
 
15
15
  class AWSResourceFactory(ABC):
16
16
  def __init__(
17
- self, er_inventory: ExternalResourcesInventory, secrets_reader: SecretReaderBase
17
+ self, er_inventory: ExternalResourcesInventory, secret_reader: SecretReaderBase
18
18
  ):
19
19
  self.er_inventory = er_inventory
20
- self.secrets_reader = secrets_reader
20
+ self.secret_reader = secret_reader
21
21
 
22
22
  @abstractmethod
23
23
  def resolve(self, spec: ExternalResourceSpec) -> dict[str, Any]: ...
@@ -83,3 +83,51 @@ class AWSRdsFactory(AWSDefaultResourceFactory):
83
83
  return data
84
84
 
85
85
  def validate(self, resource: ExternalResource) -> None: ...
86
+
87
+
88
+ class AWSMskFactory(AWSDefaultResourceFactory):
89
+ def _get_source_db_spec(
90
+ self, provisioner: str, identifier: str
91
+ ) -> ExternalResourceSpec:
92
+ return self.er_inventory.get_inventory_spec(
93
+ "aws", provisioner, "msk", identifier
94
+ )
95
+
96
+ def resolve(self, spec: ExternalResourceSpec) -> dict[str, Any]:
97
+ rvr = ResourceValueResolver(spec=spec, identifier_as_value=True)
98
+ data = rvr.resolve()
99
+ data["output_prefix"] = spec.output_prefix
100
+
101
+ scram_enabled = (
102
+ data.get("client_authentication", {}).get("sasl", {}).get("scram", False)
103
+ )
104
+ data["scram_users"] = {}
105
+ if scram_enabled:
106
+ if not data.get("users", []):
107
+ raise ValueError(
108
+ "users attribute must be given when client_authentication.sasl.scram is enabled."
109
+ )
110
+ data["scram_users"] = {
111
+ user["name"]: self.secret_reader.read_all(user["secret"])
112
+ for user in data["users"]
113
+ }
114
+ # the users attribute is not needed in the final data
115
+ del data["users"]
116
+ return data
117
+
118
+ def validate(self, resource: ExternalResource) -> None:
119
+ data = resource.data
120
+ if (
121
+ data["number_of_broker_nodes"]
122
+ % len(data["broker_node_group_info"]["client_subnets"])
123
+ != 0
124
+ ):
125
+ raise ValueError(
126
+ "number_of_broker_nodes must be a multiple of the number of specified client subnets."
127
+ )
128
+ # validate user objects
129
+ for user, secret in data["scram_users"].items():
130
+ if secret.keys() != {"password", "username"}:
131
+ raise ValueError(
132
+ f"MSK user '{user}' secret must contain only 'username' and 'password' keys!"
133
+ )
@@ -6,6 +6,7 @@ from typing import Generic, TypeVar
6
6
 
7
7
  from reconcile.external_resources.aws import (
8
8
  AWSDefaultResourceFactory,
9
+ AWSMskFactory,
9
10
  AWSRdsFactory,
10
11
  AWSResourceFactory,
11
12
  )
@@ -83,12 +84,13 @@ class TerraformModuleProvisionDataFactory(ModuleProvisionDataFactory):
83
84
 
84
85
 
85
86
  def setup_aws_resource_factories(
86
- er_inventory: ExternalResourcesInventory, secrets_reader: SecretReaderBase
87
+ er_inventory: ExternalResourcesInventory, secret_reader: SecretReaderBase
87
88
  ) -> ObjectFactory[AWSResourceFactory]:
88
89
  f = ObjectFactory[AWSResourceFactory]()
89
- f.register_factory("rds", AWSRdsFactory(er_inventory, secrets_reader))
90
+ f.register_factory("rds", AWSRdsFactory(er_inventory, secret_reader))
91
+ f.register_factory("msk", AWSMskFactory(er_inventory, secret_reader))
90
92
  f.register_factory(
91
- "default", AWSDefaultResourceFactory(er_inventory, secrets_reader)
93
+ "default", AWSDefaultResourceFactory(er_inventory, secret_reader)
92
94
  )
93
95
  return f
94
96
 
@@ -357,7 +357,7 @@ class ExternalResourcesManager:
357
357
  desired_r = self._get_desired_objects_reconciliations()
358
358
  deleted_r = self._get_deleted_objects_reconciliations()
359
359
  reconciliations = desired_r.union(deleted_r)
360
- triggered = set[Reconciliation]()
360
+ triggered: set[Reconciliation] = set()
361
361
 
362
362
  for r in reconciliations:
363
363
  state = self.state_mgr.get_external_resource_state(key=r.key)
@@ -24,6 +24,7 @@ from reconcile.gql_definitions.external_resources.external_resources_modules imp
24
24
  from reconcile.gql_definitions.external_resources.external_resources_namespaces import (
25
25
  ExternalResourcesModuleOverridesV1,
26
26
  NamespaceTerraformProviderResourceAWSV1,
27
+ NamespaceTerraformResourceMskV1,
27
28
  NamespaceTerraformResourceRDSV1,
28
29
  NamespaceV1,
29
30
  )
@@ -66,7 +67,9 @@ class ExternalResourceKey(BaseModel, frozen=True):
66
67
 
67
68
 
68
69
  SUPPORTED_RESOURCE_PROVIDERS = NamespaceTerraformProviderResourceAWSV1
69
- SUPPORTED_RESOURCE_TYPES = NamespaceTerraformResourceRDSV1
70
+ SUPPORTED_RESOURCE_TYPES = (
71
+ NamespaceTerraformResourceRDSV1 | NamespaceTerraformResourceMskV1
72
+ )
70
73
 
71
74
 
72
75
  class ExternalResourcesInventory(MutableMapping):
@@ -466,6 +466,14 @@ query ExternalResourcesNamespaces {
466
466
  ...VaultSecret
467
467
  }
468
468
  }
469
+ managed_by_erv2
470
+ delete
471
+ module_overrides {
472
+ module_type
473
+ image
474
+ version
475
+ reconcile_timeout_minutes
476
+ }
469
477
  }
470
478
  }
471
479
  }
@@ -983,6 +991,13 @@ class MskSecretParametersV1(ConfiguredBaseModel):
983
991
  secret: VaultSecret = Field(..., alias="secret")
984
992
 
985
993
 
994
+ class NamespaceTerraformResourceMskV1_ExternalResourcesModuleOverridesV1(ConfiguredBaseModel):
995
+ module_type: Optional[str] = Field(..., alias="module_type")
996
+ image: Optional[str] = Field(..., alias="image")
997
+ version: Optional[str] = Field(..., alias="version")
998
+ reconcile_timeout_minutes: Optional[int] = Field(..., alias="reconcile_timeout_minutes")
999
+
1000
+
986
1001
  class NamespaceTerraformResourceMskV1(NamespaceTerraformResourceAWSV1):
987
1002
  region: Optional[str] = Field(..., alias="region")
988
1003
  identifier: str = Field(..., alias="identifier")
@@ -990,11 +1005,14 @@ class NamespaceTerraformResourceMskV1(NamespaceTerraformResourceAWSV1):
990
1005
  defaults: str = Field(..., alias="defaults")
991
1006
  annotations: Optional[str] = Field(..., alias="annotations")
992
1007
  users: Optional[list[MskSecretParametersV1]] = Field(..., alias="users")
1008
+ managed_by_erv2: Optional[bool] = Field(..., alias="managed_by_erv2")
1009
+ delete: Optional[bool] = Field(..., alias="delete")
1010
+ module_overrides: Optional[NamespaceTerraformResourceMskV1_ExternalResourcesModuleOverridesV1] = Field(..., alias="module_overrides")
993
1011
 
994
1012
 
995
1013
  class NamespaceTerraformProviderResourceAWSV1(NamespaceExternalResourceV1):
996
1014
  provisioner: AWSAccountV1 = Field(..., alias="provisioner")
997
- resources: list[Union[NamespaceTerraformResourceRDSV1, NamespaceTerraformResourceRosaAuthenticatorV1, NamespaceTerraformResourceALBV1, NamespaceTerraformResourceS3V1, NamespaceTerraformResourceASGV1, NamespaceTerraformResourceRoleV1, NamespaceTerraformResourceSNSTopicV1, NamespaceTerraformResourceElastiCacheV1, NamespaceTerraformResourceServiceAccountV1, NamespaceTerraformResourceS3SQSV1, NamespaceTerraformResourceCloudWatchV1, NamespaceTerraformResourceRosaAuthenticatorVPCEV1, NamespaceTerraformResourceS3CloudFrontV1, NamespaceTerraformResourceKMSV1, NamespaceTerraformResourceElasticSearchV1, NamespaceTerraformResourceACMV1, NamespaceTerraformResourceKinesisV1, NamespaceTerraformResourceRoute53ZoneV1, NamespaceTerraformResourceMskV1, NamespaceTerraformResourceSQSV1, NamespaceTerraformResourceDynamoDBV1, NamespaceTerraformResourceECRV1, NamespaceTerraformResourceS3CloudFrontPublicKeyV1, NamespaceTerraformResourceSecretsManagerV1, NamespaceTerraformResourceSecretsManagerServiceAccountV1, NamespaceTerraformResourceAWSV1]] = Field(..., alias="resources")
1015
+ resources: list[Union[NamespaceTerraformResourceRDSV1, NamespaceTerraformResourceRosaAuthenticatorV1, NamespaceTerraformResourceALBV1, NamespaceTerraformResourceS3V1, NamespaceTerraformResourceASGV1, NamespaceTerraformResourceMskV1, NamespaceTerraformResourceRoleV1, NamespaceTerraformResourceSNSTopicV1, NamespaceTerraformResourceElastiCacheV1, NamespaceTerraformResourceServiceAccountV1, NamespaceTerraformResourceS3SQSV1, NamespaceTerraformResourceCloudWatchV1, NamespaceTerraformResourceRosaAuthenticatorVPCEV1, NamespaceTerraformResourceS3CloudFrontV1, NamespaceTerraformResourceKMSV1, NamespaceTerraformResourceElasticSearchV1, NamespaceTerraformResourceACMV1, NamespaceTerraformResourceKinesisV1, NamespaceTerraformResourceRoute53ZoneV1, NamespaceTerraformResourceSQSV1, NamespaceTerraformResourceDynamoDBV1, NamespaceTerraformResourceECRV1, NamespaceTerraformResourceS3CloudFrontPublicKeyV1, NamespaceTerraformResourceSecretsManagerV1, NamespaceTerraformResourceSecretsManagerServiceAccountV1, NamespaceTerraformResourceAWSV1]] = Field(..., alias="resources")
998
1016
 
999
1017
 
1000
1018
  class EnvironmentV1(ConfiguredBaseModel):
@@ -474,6 +474,7 @@ query TerraformResourcesNamespaces {
474
474
  ...VaultSecret
475
475
  }
476
476
  }
477
+ managed_by_erv2
477
478
  }
478
479
  }
479
480
  }
@@ -1010,10 +1011,11 @@ class NamespaceTerraformResourceMskV1(NamespaceTerraformResourceAWSV1):
1010
1011
  defaults: str = Field(..., alias="defaults")
1011
1012
  annotations: Optional[str] = Field(..., alias="annotations")
1012
1013
  users: Optional[list[MskSecretParametersV1]] = Field(..., alias="users")
1014
+ managed_by_erv2: Optional[bool] = Field(..., alias="managed_by_erv2")
1013
1015
 
1014
1016
 
1015
1017
  class NamespaceTerraformProviderResourceAWSV1(NamespaceExternalResourceV1):
1016
- resources: list[Union[NamespaceTerraformResourceRDSV1, NamespaceTerraformResourceRosaAuthenticatorV1, NamespaceTerraformResourceALBV1, NamespaceTerraformResourceS3V1, NamespaceTerraformResourceRoleV1, NamespaceTerraformResourceASGV1, NamespaceTerraformResourceSNSTopicV1, NamespaceTerraformResourceElastiCacheV1, NamespaceTerraformResourceServiceAccountV1, NamespaceTerraformResourceS3SQSV1, NamespaceTerraformResourceCloudWatchV1, NamespaceTerraformResourceRosaAuthenticatorVPCEV1, NamespaceTerraformResourceS3CloudFrontV1, NamespaceTerraformResourceKMSV1, NamespaceTerraformResourceElasticSearchV1, NamespaceTerraformResourceACMV1, NamespaceTerraformResourceKinesisV1, NamespaceTerraformResourceRoute53ZoneV1, NamespaceTerraformResourceMskV1, NamespaceTerraformResourceSQSV1, NamespaceTerraformResourceDynamoDBV1, NamespaceTerraformResourceECRV1, NamespaceTerraformResourceS3CloudFrontPublicKeyV1, NamespaceTerraformResourceSecretsManagerV1, NamespaceTerraformResourceSecretsManagerServiceAccountV1, NamespaceTerraformResourceAWSV1]] = Field(..., alias="resources")
1018
+ resources: list[Union[NamespaceTerraformResourceRDSV1, NamespaceTerraformResourceRosaAuthenticatorV1, NamespaceTerraformResourceALBV1, NamespaceTerraformResourceS3V1, NamespaceTerraformResourceRoleV1, NamespaceTerraformResourceASGV1, NamespaceTerraformResourceSNSTopicV1, NamespaceTerraformResourceElastiCacheV1, NamespaceTerraformResourceServiceAccountV1, NamespaceTerraformResourceS3SQSV1, NamespaceTerraformResourceCloudWatchV1, NamespaceTerraformResourceRosaAuthenticatorVPCEV1, NamespaceTerraformResourceMskV1, NamespaceTerraformResourceS3CloudFrontV1, NamespaceTerraformResourceKMSV1, NamespaceTerraformResourceElasticSearchV1, NamespaceTerraformResourceACMV1, NamespaceTerraformResourceKinesisV1, NamespaceTerraformResourceRoute53ZoneV1, NamespaceTerraformResourceSQSV1, NamespaceTerraformResourceDynamoDBV1, NamespaceTerraformResourceECRV1, NamespaceTerraformResourceS3CloudFrontPublicKeyV1, NamespaceTerraformResourceSecretsManagerV1, NamespaceTerraformResourceSecretsManagerServiceAccountV1, NamespaceTerraformResourceAWSV1]] = Field(..., alias="resources")
1017
1019
 
1018
1020
 
1019
1021
  class EnvironmentV1(ConfiguredBaseModel):
reconcile/utils/oc.py CHANGED
@@ -2,6 +2,7 @@ import copy
2
2
  import json
3
3
  import logging
4
4
  import os
5
+ import pathlib
5
6
  import re
6
7
  import subprocess
7
8
  import threading
@@ -14,7 +15,6 @@ from contextlib import suppress
14
15
  from dataclasses import dataclass
15
16
  from datetime import datetime
16
17
  from functools import wraps
17
- from io import TextIOWrapper
18
18
  from subprocess import Popen
19
19
  from threading import Lock
20
20
  from typing import Any
@@ -744,10 +744,11 @@ class OCCli: # pylint: disable=too-many-public-methods
744
744
  if follow:
745
745
  cmd.append("-f")
746
746
 
747
- if isinstance(output, TextIOWrapper):
748
- output_file = output
749
- else:
747
+ if isinstance(output, str | pathlib.Path):
750
748
  output_file = open(os.path.join(output, name), "w", encoding="locale") # noqa: SIM115
749
+ else:
750
+ # assume it's a file-like object, e.g. sys.stdout, TextIO, ...
751
+ output_file = output
751
752
 
752
753
  if wait_for_logs_process:
753
754
  subprocess.run(self.oc_base_cmd + cmd, stdout=output_file, check=False)