qontract-reconcile 0.10.1rc471__py3-none-any.whl → 0.10.1rc473__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.1rc471
3
+ Version: 0.10.1rc473
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
@@ -44,7 +44,7 @@ reconcile/jenkins_roles.py,sha256=f8ELpZY36UjoaCpR_9LijQuIMuB6a7sVLFf_H1ct9Hc,44
44
44
  reconcile/jenkins_webhooks.py,sha256=j8vhJMWcRhOdc9XzRSm0CPj84jsF3e4Syjm7r1BIsDE,1978
45
45
  reconcile/jenkins_webhooks_cleaner.py,sha256=JsN_NVPfZJwv1JtSzZXDIHUqGiefL-DRffFnDGau9aY,1539
46
46
  reconcile/jenkins_worker_fleets.py,sha256=PMNGOX0krubFjInPiFT0za0KCiWBLEcVDuXdKRd1BrE,5378
47
- reconcile/jira_permissions_validator.py,sha256=97gn28OxY0asXlI0OH5OQ-1gzQx9LcHGuZTT-gPa_S4,9884
47
+ reconcile/jira_permissions_validator.py,sha256=kLRG9N441uN5lrLCx8QQBTS8knDdr87von_JjfyJ6X4,10177
48
48
  reconcile/jira_watcher.py,sha256=eyOQ92t8TFi6gogfNTO448h_h1CUyr24E0MPHc51R-o,3617
49
49
  reconcile/ldap_users.py,sha256=uEWQ0V41tN9KCZi4ZKPamjrJ6djSpdpvDBo7yJ0e7ZI,3008
50
50
  reconcile/mr_client_gateway.py,sha256=WhjMd-sIXDFCV8-rt8CEjurJ5OYB1pOD0K3o0tZRXQg,1885
@@ -265,6 +265,7 @@ reconcile/gql_definitions/quay_membership/__init__.py,sha256=47DEQpj8HBSa-_TImW-
265
265
  reconcile/gql_definitions/quay_membership/quay_membership.py,sha256=H2xHvdNr3K0QzB2dituwStUIWCqePt35dkgeUZycECM,2824
266
266
  reconcile/gql_definitions/rhidp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
267
267
  reconcile/gql_definitions/rhidp/organizations.py,sha256=8KVbWyvjDlvn-VGpYF06f4ZH6_PZMNCCZ8fa9W0s-Tk,2553
268
+ reconcile/gql_definitions/saas_auto_promotions_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
268
269
  reconcile/gql_definitions/service_dependencies/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
269
270
  reconcile/gql_definitions/service_dependencies/jenkins_instance_fragment.py,sha256=gEcYRrdhGKG83cOpGEnecE0mCxpQHLRzXFCp5FBIhLA,699
270
271
  reconcile/gql_definitions/service_dependencies/service_dependencies.py,sha256=CpMq9KjhFA61yniLo_11ypVInoeMBXbNmcY7_VAep-0,4700
@@ -289,7 +290,7 @@ reconcile/gql_definitions/terraform_cloudflare_dns/app_interface_cloudflare_dns_
289
290
  reconcile/gql_definitions/terraform_cloudflare_dns/terraform_cloudflare_zones.py,sha256=uVZYu5EUcvdAQYBK5YKD0mjoMKDb5inSuCJrrOD5KpE,5704
290
291
  reconcile/gql_definitions/terraform_cloudflare_resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
291
292
  reconcile/gql_definitions/terraform_cloudflare_resources/terraform_cloudflare_accounts.py,sha256=WHMyQlosDCby7p1wWd3PXpmooSeEZyR8CgRDP49bunU,3641
292
- reconcile/gql_definitions/terraform_cloudflare_resources/terraform_cloudflare_resources.py,sha256=1wxnMo4xV0jMpLQ3IhSVD5LygXeuhuYEai64Dlp7jUY,11223
293
+ reconcile/gql_definitions/terraform_cloudflare_resources/terraform_cloudflare_resources.py,sha256=YWjhWTjOR7B-RsX5gPt1PbRfYDzxPqncNq4vmVHpIQ0,12313
293
294
  reconcile/gql_definitions/terraform_cloudflare_users/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
294
295
  reconcile/gql_definitions/terraform_cloudflare_users/app_interface_setting_cloudflare_and_vault.py,sha256=KFey-0ItgpGPeIwViGKqb55HAFJoKdi3eCNSIzf6Rc8,1960
295
296
  reconcile/gql_definitions/terraform_cloudflare_users/terraform_cloudflare_roles.py,sha256=1KiTikTKSSRYmISN8tY29rJ_fVtgBnT7sK85IJjN420,4027
@@ -423,7 +424,7 @@ reconcile/test/test_sql_query.py,sha256=rC-lf1_isT9i2ZIV9W0hkUkLi2oBIjZMRMhk-6mV
423
424
  reconcile/test/test_status_board.py,sha256=WdAq4pFoWWqcOcfgMzssZD3xfvT1QLrEHJqUARldtvA,7875
424
425
  reconcile/test/test_terraform_aws_route53.py,sha256=xHggb8K1P76OyCfFcogbkmyKle-NlUylcbDnuv3IqvY,771
425
426
  reconcile/test/test_terraform_cloudflare_dns.py,sha256=aQTXX8Vr4h9aWvJZTnpZEhMGYoBpT2d45ZxU_ECIQ6o,3425
426
- reconcile/test/test_terraform_cloudflare_resources.py,sha256=siUPsLvHs-Bmt2df3-zI0v1L76lweALTQjI3xxsmMN4,9248
427
+ reconcile/test/test_terraform_cloudflare_resources.py,sha256=NK_uktyWihkQ3gMN4bCaKerpi43CXAVYGIKTfcz05rY,13550
427
428
  reconcile/test/test_terraform_cloudflare_users.py,sha256=RAFtMMdqZha3jNnNNsqbNQQUDSqUzdoM63rCw7fs4Fo,27456
428
429
  reconcile/test/test_terraform_repo.py,sha256=soKFJfF8tWIimDs39RQl3Hnh-Od-bR4PfnEA2s1UprM,11552
429
430
  reconcile/test/test_terraform_resources.py,sha256=1ny_QSFuRjV9jxZY8EeT4NVJ5dMv7cLrEEIx_cBpjgk,9075
@@ -627,7 +628,7 @@ reconcile/utils/terraform/config.py,sha256=5UVrd563TMcvi4ooa5JvWVDW1I3bIWg484u79
627
628
  reconcile/utils/terraform/config_client.py,sha256=py-Ree-QUYD6Hvng6bM40VgSuttteehIKNgwOSoJO1o,4706
628
629
  reconcile/utils/terrascript/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
629
630
  reconcile/utils/terrascript/cloudflare_client.py,sha256=EOmAnrgSUZz-UZB7x6TFd4WGk0huWZm2hh29Cueiyr8,10278
630
- reconcile/utils/terrascript/cloudflare_resources.py,sha256=GQO1KJb19bcxwUdZM3_O24afailfHewtOIs_FTNJVUM,14189
631
+ reconcile/utils/terrascript/cloudflare_resources.py,sha256=ZvmFqE-Atki6ehMA4iirYqpml4bCPHdddq8lu58udGA,15952
631
632
  reconcile/utils/terrascript/models.py,sha256=x9HReI0k71MHBpRTvvmPlE0G6rri5GTzPXM9cqyTWm0,475
632
633
  reconcile/utils/terrascript/resources.py,sha256=bQzglnO41KZZEIeXYgi-qlup1p8R03Qyx_V944LRPsc,1391
633
634
  release/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -649,8 +650,8 @@ tools/test/test_app_interface_metrics_exporter.py,sha256=SX7qL3D1SIRKFo95FoQztvf
649
650
  tools/test/test_qontract_cli.py,sha256=awwTHEc2DWlykuqGIYM0WOBoSL0KRnOraCLk3C7izis,1401
650
651
  tools/test/test_sd_app_sre_alert_report.py,sha256=v363r9zM7__0kR5K6mvJoGFcM9BvE33fWAayrqkpojA,2116
651
652
  tools/test/test_sre_checkpoints.py,sha256=SKqPPTl9ua0RFdSSofnoQX-JZE6dFLO3LRhfQzqtfh8,2607
652
- qontract_reconcile-0.10.1rc471.dist-info/METADATA,sha256=a5MSyt0Nn1ylTv3VJ8Dg_fTqg-KFOBshD57-Hd9QGXk,2348
653
- qontract_reconcile-0.10.1rc471.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
654
- qontract_reconcile-0.10.1rc471.dist-info/entry_points.txt,sha256=rTjAv28I_CHLM8ID3OPqMI_suoQ9s7tFbim4aYjn9kk,376
655
- qontract_reconcile-0.10.1rc471.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
656
- qontract_reconcile-0.10.1rc471.dist-info/RECORD,,
653
+ qontract_reconcile-0.10.1rc473.dist-info/METADATA,sha256=Rnigg-CBRz8a3ixHxvm6IblRrV35SbamdffbAThCeJM,2348
654
+ qontract_reconcile-0.10.1rc473.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
655
+ qontract_reconcile-0.10.1rc473.dist-info/entry_points.txt,sha256=rTjAv28I_CHLM8ID3OPqMI_suoQ9s7tFbim4aYjn9kk,376
656
+ qontract_reconcile-0.10.1rc473.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
657
+ qontract_reconcile-0.10.1rc473.dist-info/RECORD,,
@@ -67,6 +67,7 @@ query TerraformCloudflareResources {
67
67
  }
68
68
  managedExternalResources
69
69
  externalResources {
70
+ provider
70
71
  ... on NamespaceTerraformProviderResourceCloudflare_v1 {
71
72
  provider
72
73
  provisioner {
@@ -128,6 +129,20 @@ query TerraformCloudflareResources {
128
129
  cloudflare_branding
129
130
  wait_for_active_status
130
131
  }
132
+ custom_ssl_certificates {
133
+ identifier
134
+ type
135
+ bundle_method
136
+ geo_restrictions
137
+ certificate_secret {
138
+ certificate {
139
+ ... VaultSecret
140
+ }
141
+ key {
142
+ ... VaultSecret
143
+ }
144
+ }
145
+ }
131
146
  }
132
147
  ... on NamespaceTerraformResourceLogpushOwnershipChallenge_v1
133
148
  {
@@ -190,7 +205,7 @@ class ClusterV1(ConfiguredBaseModel):
190
205
 
191
206
 
192
207
  class NamespaceExternalResourceV1(ConfiguredBaseModel):
193
- ...
208
+ provider: str = Field(..., alias="provider")
194
209
 
195
210
 
196
211
  class CloudflareAccountV1(ConfiguredBaseModel):
@@ -258,6 +273,19 @@ class CloudflareZoneCertificateV1(ConfiguredBaseModel):
258
273
  wait_for_active_status: Optional[bool] = Field(..., alias="wait_for_active_status")
259
274
 
260
275
 
276
+ class CertificateSecretV1(ConfiguredBaseModel):
277
+ certificate: VaultSecret = Field(..., alias="certificate")
278
+ key: VaultSecret = Field(..., alias="key")
279
+
280
+
281
+ class CloudflareCustomSSLCertificateV1(ConfiguredBaseModel):
282
+ identifier: str = Field(..., alias="identifier")
283
+ q_type: str = Field(..., alias="type")
284
+ bundle_method: Optional[str] = Field(..., alias="bundle_method")
285
+ geo_restrictions: Optional[str] = Field(..., alias="geo_restrictions")
286
+ certificate_secret: CertificateSecretV1 = Field(..., alias="certificate_secret")
287
+
288
+
261
289
  class NamespaceTerraformResourceCloudflareZoneV1(NamespaceTerraformResourceCloudflareV1):
262
290
  identifier: str = Field(..., alias="identifier")
263
291
  zone: str = Field(..., alias="zone")
@@ -270,6 +298,7 @@ class NamespaceTerraformResourceCloudflareZoneV1(NamespaceTerraformResourceCloud
270
298
  records: Optional[list[CloudflareDnsRecordV1]] = Field(..., alias="records")
271
299
  workers: Optional[list[CloudflareZoneWorkerV1]] = Field(..., alias="workers")
272
300
  certificates: Optional[list[CloudflareZoneCertificateV1]] = Field(..., alias="certificates")
301
+ custom_ssl_certificates: Optional[list[CloudflareCustomSSLCertificateV1]] = Field(..., alias="custom_ssl_certificates")
273
302
 
274
303
 
275
304
  class NamespaceTerraformResourceLogpushOwnershipChallengeV1(NamespaceTerraformResourceCloudflareV1):
@@ -128,16 +128,23 @@ def board_is_valid(
128
128
  error |= ValidationError.INVALID_SECURITY_LEVEL
129
129
 
130
130
  project_priorities = jira.project_priority_scheme()
131
+ # get the priority names from the project priorities ids
132
+ project_priorities_names = [
133
+ p_name
134
+ for project_p_id in project_priorities
135
+ for p_name, p_id in jira_server_priorities.items()
136
+ if p_id == project_p_id
137
+ ]
131
138
  for priority in board.severity_priority_mappings.mappings:
132
139
  if priority.priority not in jira_server_priorities:
133
140
  logging.error(
134
- f"[{board.name}] {priority.priority} is not a valid Jira priority. Valid priorities: {project_priorities}"
141
+ f"[{board.name}] {priority.priority} is not a valid Jira priority. Valid priorities: {project_priorities_names}"
135
142
  )
136
143
  error |= ValidationError.INVALID_PRIORITY
137
144
  continue
138
145
  if jira_server_priorities[priority.priority] not in project_priorities:
139
146
  logging.error(
140
- f"[{board.name}] {priority.priority} is not a valid priority in project. Valid priorities: {project_priorities}"
147
+ f"[{board.name}] {priority.priority} is not a valid priority in project. Valid priorities: {project_priorities_names}"
141
148
  )
142
149
  error |= ValidationError.INVALID_PRIORITY
143
150
  except JIRAError as e:
@@ -1,4 +1,5 @@
1
1
  import logging
2
+ from unittest.mock import call
2
3
 
3
4
  import pytest
4
5
 
@@ -18,7 +19,9 @@ from reconcile.gql_definitions.terraform_cloudflare_resources.terraform_cloudfla
18
19
  CloudflareAccountV1 as CFAccountV1,
19
20
  )
20
21
  from reconcile.gql_definitions.terraform_cloudflare_resources.terraform_cloudflare_resources import (
22
+ CertificateSecretV1,
21
23
  CloudflareAccountV1,
24
+ CloudflareCustomSSLCertificateV1,
22
25
  CloudflareDnsRecordV1,
23
26
  CloudflareZoneArgoV1,
24
27
  CloudflareZoneCacheReserveV1,
@@ -31,6 +34,10 @@ from reconcile.gql_definitions.terraform_cloudflare_resources.terraform_cloudfla
31
34
  NamespaceV1,
32
35
  TerraformCloudflareResourcesQueryData,
33
36
  )
37
+ from reconcile.status import ExitCodes
38
+ from reconcile.utils.secret_reader import (
39
+ SecretReaderBase,
40
+ )
34
41
 
35
42
 
36
43
  @pytest.fixture
@@ -72,7 +79,7 @@ def external_resources(provisioner_config):
72
79
  provisioner=provisioner_config,
73
80
  resources=[
74
81
  NamespaceTerraformResourceCloudflareZoneV1(
75
- provider="cloudflare_zone",
82
+ provider="zone",
76
83
  identifier="testzone-com",
77
84
  zone="testzone.com",
78
85
  plan="enterprise",
@@ -115,6 +122,28 @@ def external_resources(provisioner_config):
115
122
  wait_for_active_status=False,
116
123
  )
117
124
  ],
125
+ custom_ssl_certificates=[
126
+ CloudflareCustomSSLCertificateV1(
127
+ identifier="testcustomssl",
128
+ type="legacy_custom",
129
+ bundle_method="ubiquitous",
130
+ geo_restrictions="us",
131
+ certificate_secret=CertificateSecretV1(
132
+ certificate=VaultSecret(
133
+ path="certificate/secret/cert/path",
134
+ field="certificate.crt",
135
+ format="plain",
136
+ version=1,
137
+ ),
138
+ key=VaultSecret(
139
+ path="certificate/secret/key/path",
140
+ field="certificate.key",
141
+ format="plain",
142
+ version=1,
143
+ ),
144
+ ),
145
+ )
146
+ ],
118
147
  ),
119
148
  ],
120
149
  )
@@ -126,12 +155,51 @@ def mock_gql(mocker):
126
155
 
127
156
 
128
157
  @pytest.fixture
129
- def mock_vault_secret(mocker):
130
- mocked_vault_secret = mocker.patch(
158
+ def mock_app_interface_vault_settings(mocker):
159
+ mocked_app_interface_vault_settings = mocker.patch(
131
160
  "reconcile.terraform_cloudflare_resources.get_app_interface_vault_settings",
132
161
  autospec=True,
133
162
  )
134
- mocked_vault_secret.return_value = AppInterfaceSettingsV1(vault=False)
163
+ mocked_app_interface_vault_settings.return_value = AppInterfaceSettingsV1(
164
+ vault=True
165
+ )
166
+
167
+
168
+ def secret_reader_side_effect(*args):
169
+ if {
170
+ "path": "aws-account-path",
171
+ "field": "token",
172
+ "version": 1,
173
+ "q_format": "plain",
174
+ } == args[0]:
175
+ aws_acct_creds = {}
176
+ aws_acct_creds["aws_access_key_id"] = "key_id"
177
+ aws_acct_creds["aws_secret_access_key"] = "access_key"
178
+ return aws_acct_creds
179
+
180
+ if {
181
+ "path": "cf-account-path",
182
+ "field": "key",
183
+ "version": 1,
184
+ "q_format": "plain",
185
+ } == args[0]:
186
+ cf_acct_creds = {}
187
+ cf_acct_creds["api_token"] = "api_token"
188
+ cf_acct_creds["account_id"] = "account_id"
189
+ return cf_acct_creds
190
+
191
+
192
+ @pytest.fixture
193
+ def mock_create_secret_reader(mocker):
194
+ secret_reader = mocker.Mock(SecretReaderBase)
195
+ secret_reader.read_all_secret.side_effect = secret_reader_side_effect
196
+
197
+ mocked_create_secret_reader = mocker.patch(
198
+ "reconcile.terraform_cloudflare_resources.create_secret_reader",
199
+ autospec=True,
200
+ )
201
+
202
+ mocked_create_secret_reader.return_value = secret_reader
135
203
 
136
204
 
137
205
  @pytest.fixture
@@ -147,26 +215,27 @@ def mock_cloudflare_accounts(mocker):
147
215
  name="cfaccount",
148
216
  providerVersion="0.33.x",
149
217
  apiCredentials=VaultSecret(
150
- path="somepath",
218
+ path="cf-account-path",
151
219
  field="key",
152
220
  version=1,
153
- format="??",
221
+ format="plain",
154
222
  ),
155
223
  terraformStateAccount=AWSAccountV1(
156
224
  name="awsaccoutn",
157
225
  automationToken=VaultSecret(
158
- path="someotherpath",
226
+ path="aws-account-path",
159
227
  field="token",
160
228
  version=1,
161
- format="",
229
+ format="plain",
162
230
  ),
163
231
  terraformState=TerraformStateAWSV1(
164
- provider="",
165
- bucket="",
166
- region="",
232
+ provider="s3",
233
+ bucket="app-interface",
234
+ region="us-east-1",
167
235
  integrations=[
168
236
  AWSTerraformStateIntegrationsV1(
169
- integration="terraform-cloudflare-resources", key=""
237
+ integration="terraform-cloudflare-resources",
238
+ key="somekey.tfstate",
170
239
  )
171
240
  ],
172
241
  ),
@@ -183,16 +252,29 @@ def mock_cloudflare_accounts(mocker):
183
252
 
184
253
 
185
254
  @pytest.fixture
186
- def mock_cloudflare_resources(mocker, external_resources):
255
+ def mock_cloudflare_resources(mocker, query_data):
187
256
  mocked_cloudflare_resources = mocker.patch(
188
257
  "reconcile.terraform_cloudflare_resources.terraform_cloudflare_resources",
189
258
  autospec=True,
190
259
  )
191
- mocked_cloudflare_resources.query.return_value = external_resources
260
+ mocked_cloudflare_resources.query.return_value = query_data
261
+
262
+
263
+ @pytest.fixture
264
+ def mock_terraform_client(mocker):
265
+ mocked_tf_client = mocker.patch(
266
+ "reconcile.terraform_cloudflare_resources.TerraformClient", autospec=True
267
+ )
268
+ mocked_tf_client.return_value.plan.return_value = False, None
269
+ return mocked_tf_client
192
270
 
193
271
 
194
272
  def test_cloudflare_accounts_validation(
195
- mocker, caplog, mock_gql, mock_vault_secret, mock_cloudflare_resources
273
+ mocker,
274
+ caplog,
275
+ mock_gql,
276
+ mock_app_interface_vault_settings,
277
+ mock_cloudflare_resources,
196
278
  ):
197
279
  # Mocking accounts with an empty response
198
280
  mocked_cloudflare_accounts = mocker.patch(
@@ -212,14 +294,17 @@ def test_cloudflare_accounts_validation(
212
294
 
213
295
 
214
296
  def test_namespace_validation(
215
- mocker, caplog, mock_gql, mock_vault_secret, mock_cloudflare_accounts
297
+ mocker,
298
+ caplog,
299
+ mock_gql,
300
+ mock_app_interface_vault_settings,
301
+ mock_cloudflare_accounts,
216
302
  ):
217
303
  # Mocking resources without namespaces
218
304
  mocked_resources = mocker.patch(
219
305
  "reconcile.terraform_cloudflare_resources.terraform_cloudflare_resources",
220
306
  autospec=True,
221
307
  )
222
-
223
308
  mocked_resources.query.return_value = TerraformCloudflareResourcesQueryData(
224
309
  namespaces=[],
225
310
  )
@@ -233,7 +318,11 @@ def test_namespace_validation(
233
318
 
234
319
 
235
320
  def test_cloudflare_namespace_validation(
236
- mocker, caplog, mock_gql, mock_vault_secret, mock_cloudflare_accounts
321
+ mocker,
322
+ caplog,
323
+ mock_gql,
324
+ mock_app_interface_vault_settings,
325
+ mock_cloudflare_accounts,
237
326
  ):
238
327
  # Mocking resources without cloudflare namespaces
239
328
  mocked_resources = mocker.patch(
@@ -269,3 +358,50 @@ def test_cloudflare_namespace_validation(
269
358
  assert ["No cloudflare namespaces were detected, nothing to do."] == [
270
359
  rec.message for rec in caplog.records
271
360
  ]
361
+
362
+
363
+ def custom_ssl_secret_reader_side_effect(*args):
364
+ """For use of secret_reader inside cloudflare client"""
365
+ if {
366
+ "path": "certificate/secret/cert/path",
367
+ "field": "certificate.crt",
368
+ "version": 1,
369
+ "q_format": "plain",
370
+ } == args[0]:
371
+ return "----- CERTIFICATE -----"
372
+
373
+ if {
374
+ "path": "certificate/secret/cert/path",
375
+ "field": "certificate.key",
376
+ "version": 1,
377
+ "q_format": "plain",
378
+ } == args[0]:
379
+ return "----- KEY -----"
380
+
381
+
382
+ def test_terraform_cloudflare_resources_dry_run(
383
+ mocker,
384
+ mock_gql,
385
+ mock_create_secret_reader,
386
+ mock_terraform_client,
387
+ mock_app_interface_vault_settings,
388
+ mock_cloudflare_accounts,
389
+ mock_cloudflare_resources,
390
+ ):
391
+ # Mocking vault settings and secret reader inside cloudflare_client
392
+ mocker.patch(
393
+ "reconcile.utils.terrascript.cloudflare_resources.get_app_interface_vault_settings",
394
+ atospec=True,
395
+ )
396
+ secret_reader = mocker.Mock(SecretReaderBase)
397
+ secret_reader.read.side_effect = custom_ssl_secret_reader_side_effect
398
+ create_secret_reader = mocker.patch(
399
+ "reconcile.utils.terrascript.cloudflare_resources.create_secret_reader",
400
+ autospec=True,
401
+ )
402
+ create_secret_reader.return_value = secret_reader
403
+ with pytest.raises(SystemExit) as sample:
404
+ integ.run(True, None, False, 10)
405
+ assert sample.value.code == ExitCodes.SUCCESS
406
+ assert mock_terraform_client.called is True
407
+ assert call().apply() not in mock_terraform_client.method_calls
@@ -16,6 +16,7 @@ from terrascript import (
16
16
  from terrascript.resource import (
17
17
  cloudflare_account_member,
18
18
  cloudflare_argo,
19
+ cloudflare_custom_ssl,
19
20
  cloudflare_logpull_retention,
20
21
  cloudflare_logpush_job,
21
22
  cloudflare_logpush_ownership_challenge,
@@ -186,6 +187,38 @@ class CloudflareZoneTerrascriptResource(TerrascriptResource):
186
187
 
187
188
  return resources
188
189
 
190
+ def _create_cloudflare_custom_ssl_certificates(
191
+ self,
192
+ zone: Resource,
193
+ zone_custom_ssl: Iterable[MutableMapping[str, Any]],
194
+ ) -> list[Union[Resource, Output]]:
195
+ vault_settings = get_app_interface_vault_settings()
196
+ secret_reader = create_secret_reader(use_vault=vault_settings.vault)
197
+
198
+ resources = []
199
+ for cert_values in zone_custom_ssl:
200
+ identifier = safe_resource_id(cert_values.pop("identifier"))
201
+ certificate_secret = cert_values.pop("certificate_secret")
202
+ certificate = secret_reader.read(certificate_secret.pop("certificate"))
203
+ key = secret_reader.read(certificate_secret.pop("key"))
204
+ custom_ssl_values: dict[Any, Any] = {
205
+ "zone_id": f"${{{zone.id}}}",
206
+ "depends_on": self._get_dependencies([zone]),
207
+ "custom_ssl_options": {
208
+ "bundle_method": cert_values.pop("bundle_method", "ubiquitous"),
209
+ "type": cert_values.pop("type"),
210
+ "certificate": certificate,
211
+ "private_key": key,
212
+ },
213
+ }
214
+ if cert_values.get("geo_restrictions", None):
215
+ custom_ssl_values["custom_ssl_options"]["geo_restrictions"] = (
216
+ cert_values.get("geo_resrtictions")
217
+ )
218
+ custom_ssl = cloudflare_custom_ssl(identifier, **custom_ssl_values)
219
+ resources.append(custom_ssl)
220
+ return resources
221
+
189
222
  def populate(self) -> list[Union[Resource, Output]]:
190
223
  resources = []
191
224
 
@@ -202,6 +235,7 @@ class CloudflareZoneTerrascriptResource(TerrascriptResource):
202
235
  zone_records = values.pop("records", [])
203
236
  zone_workers = values.pop("workers", [])
204
237
  zone_certs = values.pop("certificates", [])
238
+ zone_custom_ssl = values.pop("custom_ssl_certificates", [])
205
239
 
206
240
  zone_values = {
207
241
  "account_id": "${var.account_id}",
@@ -268,6 +302,11 @@ class CloudflareZoneTerrascriptResource(TerrascriptResource):
268
302
 
269
303
  resources.extend(self._create_cloudflare_certificate_pack(zone, zone_certs))
270
304
 
305
+ if zone_custom_ssl:
306
+ resources.extend(
307
+ self._create_cloudflare_custom_ssl_certificates(zone, zone_custom_ssl)
308
+ )
309
+
271
310
  return resources
272
311
 
273
312