Skip to content

Commit af005ef

Browse files
authored
fix post commit yaml test (#39142)
* try to fix iceberg post commit test * trigger file * isort * oops more lint * lint * fix tmp dir * add timeouts per gemini comments
1 parent edd3bfc commit af005ef

3 files changed

Lines changed: 107 additions & 23 deletions

File tree

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
22
"comment": "Modify this file in a trivial way to cause this test suite to run",
3-
"revision": 6
3+
"revision": 7
44
}

sdks/python/apache_beam/yaml/extended_tests/databases/iceberg.yaml

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,18 @@
1616
#
1717

1818
fixtures:
19-
- name: TEMP_DIR
20-
type: "tempfile.TemporaryDirectory"
19+
- name: ICEBERG_FIXTURE
20+
type: "apache_beam.yaml.integration_tests.temp_iceberg_table_with_pk"
21+
config:
22+
table_data:
23+
name: "labels"
24+
schema:
25+
type: "struct"
26+
schema-id: 0
27+
fields:
28+
- { id: 1, name: "label", required: true, type: "string" }
29+
- { id: 2, name: "rank", required: true, type: "long" }
30+
identifier-field-ids: [1]
2131

2232
pipelines:
2333
- name: write
@@ -32,26 +42,26 @@ pipelines:
3242
- {label: "389a", rank: 2}
3343
- type: WriteToIceberg
3444
config:
35-
table: db.labels
36-
catalog_name: hadoop_catalog
45+
table: "{ICEBERG_FIXTURE[table]}"
46+
catalog_name: rest_catalog
3747
catalog_properties:
38-
type: hadoop
39-
warehouse: "{TEMP_DIR}"
48+
type: rest
49+
uri: "{ICEBERG_FIXTURE[api_url]}"
4050
options:
4151
project: "apache-beam-testing"
42-
temp_location: "{TEMP_DIR}"
52+
temp_location: "{ICEBERG_FIXTURE[temp_dir]}"
4353

4454
- name: read
4555
pipeline:
4656
type: chain
4757
transforms:
4858
- type: ReadFromIceberg
4959
config:
50-
table: db.labels
51-
catalog_name: hadoop_catalog
60+
table: "{ICEBERG_FIXTURE[table]}"
61+
catalog_name: rest_catalog
5262
catalog_properties:
53-
type: hadoop
54-
warehouse: "{TEMP_DIR}"
63+
type: rest
64+
uri: "{ICEBERG_FIXTURE[api_url]}"
5565
- type: AssertEqual
5666
config:
5767
elements:
@@ -60,19 +70,19 @@ pipelines:
6070
- {label: "389a", rank: 2}
6171
options:
6272
project: "apache-beam-testing"
63-
temp_location: "{TEMP_DIR}"
73+
temp_location: "{ICEBERG_FIXTURE[temp_dir]}"
6474

6575
- name: read_cdc_batch
6676
pipeline:
6777
type: chain
6878
transforms:
6979
- type: ReadFromIcebergCDC
7080
config:
71-
table: db.labels
72-
catalog_name: hadoop_catalog
81+
table: "{ICEBERG_FIXTURE[table]}"
82+
catalog_name: rest_catalog
7383
catalog_properties:
74-
type: hadoop
75-
warehouse: "{TEMP_DIR}"
84+
type: rest
85+
uri: "{ICEBERG_FIXTURE[api_url]}"
7686
from_timestamp: 1762819200000
7787
to_timestamp: 2078352000000
7888
filter: '"label" = ''11a'' or "rank" = 1'
@@ -86,19 +96,19 @@ pipelines:
8696
- {label: "37a", rank: 1}
8797
options:
8898
project: "apache-beam-testing"
89-
temp_location: "{TEMP_DIR}"
99+
temp_location: "{ICEBERG_FIXTURE[temp_dir]}"
90100

91101
- name: read_cdc_streaming
92102
pipeline:
93103
type: chain
94104
transforms:
95105
- type: ReadFromIcebergCDC
96106
config:
97-
table: db.labels
98-
catalog_name: hadoop_catalog
107+
table: "{ICEBERG_FIXTURE[table]}"
108+
catalog_name: rest_catalog
99109
catalog_properties:
100-
type: hadoop
101-
warehouse: "{TEMP_DIR}"
110+
type: rest
111+
uri: "{ICEBERG_FIXTURE[api_url]}"
102112
streaming: True
103113
to_timestamp: 2078352000000
104114
filter: '"label" = ''11a'' or "rank" = 1'
@@ -112,4 +122,4 @@ pipelines:
112122
- {label: "37a", rank: 1}
113123
options:
114124
project: "apache-beam-testing"
115-
temp_location: "{TEMP_DIR}"
125+
temp_location: "{ICEBERG_FIXTURE[temp_dir]}"

sdks/python/apache_beam/yaml/integration_tests.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,20 @@
2626
import os
2727
import random
2828
import secrets
29+
import shutil
2930
import sqlite3
3031
import string
3132
import struct
33+
import tempfile
34+
import time
3235
import unittest
3336
import uuid
3437
from datetime import datetime
3538
from datetime import timezone
3639

3740
import mock
41+
import requests
42+
from testcontainers.core.container import DockerContainer
3843

3944
from apache_beam.coders import Coder
4045
from apache_beam.coders.coder_impl import CoderImpl
@@ -556,6 +561,75 @@ def temp_oracle_database():
556561
yield f"jdbc:oracle:thin:system/oracle@localhost:{port}/XEPDB1"
557562

558563

564+
@contextlib.contextmanager
565+
def temp_iceberg_table_with_pk(table_data):
566+
567+
# Create a temp dir that will be shared between host and container.
568+
# We use the exact same path on both to avoid path mapping issues.
569+
# We create it in the current working directory (workspace) because
570+
# Docker in GitHub Actions often cannot mount directories from /tmp.
571+
temp_dir = tempfile.mkdtemp(dir=os.getcwd())
572+
os.chmod(temp_dir, 0o777)
573+
574+
# Start the Iceberg REST catalog container
575+
container = DockerContainer("tabulario/iceberg-rest:0.6.0")
576+
container.with_exposed_ports(8181)
577+
container.with_volume_mapping(temp_dir, temp_dir, mode='rw')
578+
container.with_env("HADOOP_USER_NAME", "iceberg")
579+
container.with_env("CATALOG_WAREHOUSE", temp_dir)
580+
container.with_env(
581+
"CATALOG_IO__IMPL", "org.apache.iceberg.hadoop.HadoopFileIO")
582+
583+
try:
584+
container.start()
585+
586+
ip = container.get_container_host_ip()
587+
port = container.get_exposed_port(8181)
588+
api_url = f"http://{ip}:{port}"
589+
590+
# Poll the REST API until it is ready
591+
for _ in range(30):
592+
try:
593+
response = requests.get(f"{api_url}/v1/config", timeout=5)
594+
if response.status_code == 200:
595+
break
596+
except (requests.exceptions.ConnectionError, requests.exceptions.Timeout):
597+
pass
598+
time.sleep(1)
599+
else:
600+
raise RuntimeError("Iceberg REST catalog failed to start in time.")
601+
602+
# Create namespace 'db'
603+
requests.post(
604+
f"{api_url}/v1/namespaces",
605+
json={"namespace": ["db"]},
606+
headers={"Content-Type": "application/json"},
607+
timeout=10)
608+
609+
# Create table with primary key
610+
response = requests.post(
611+
f"{api_url}/v1/namespaces/db/tables",
612+
json=table_data,
613+
headers={"Content-Type": "application/json"},
614+
timeout=10)
615+
if response.status_code != 200:
616+
raise RuntimeError(f"Failed to create Iceberg table: {response.text}")
617+
618+
# Change permissions of the created directories inside the container
619+
# so the host user can write to them.
620+
container.get_wrapped_container().exec_run(f"chmod -R 777 {temp_dir}")
621+
622+
yield {
623+
"api_url": api_url,
624+
"temp_dir": temp_dir,
625+
"table": f"db.{table_data['name']}"
626+
}
627+
628+
finally:
629+
container.stop()
630+
shutil.rmtree(temp_dir, ignore_errors=True)
631+
632+
559633
@contextlib.contextmanager
560634
def temp_kafka_server():
561635
"""Context manager to provide a temporary Kafka server for testing.

0 commit comments

Comments
 (0)