Skip to content

Commit 9179deb

Browse files
authored
Merge pull request #29096 from vbotbuildovich/backport-pr-29071-v25.3.x-219
[v25.3.x] iceberg: support bucket names with dots in URIs
2 parents 4f2a0cb + decfa52 commit 9179deb

File tree

3 files changed

+36
-32
lines changed

3 files changed

+36
-32
lines changed

src/v/iceberg/tests/BUILD

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -677,7 +677,6 @@ redpanda_cc_gtest(
677677
],
678678
cpu = 1,
679679
deps = [
680-
":test_schemas",
681680
"//src/v/cloud_io:provider",
682681
"//src/v/iceberg:uri",
683682
"//src/v/test_utils:gtest",

src/v/iceberg/tests/uri_test.cc

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,59 +10,64 @@
1010

1111
#include "cloud_io/provider.h"
1212
#include "iceberg/uri.h"
13-
#include "test_utils/test.h"
13+
14+
#include <gtest/gtest.h>
1415

1516
#include <variant>
1617

18+
namespace {
1719
using namespace iceberg;
1820

1921
template<auto Start, auto End, auto Inc, class F>
2022
constexpr void constexpr_for(F&& f) {
2123
if constexpr (Start < End) {
2224
f(std::integral_constant<decltype(Start), Start>());
23-
constexpr_for<Start + Inc, End, Inc>(f);
25+
constexpr_for<Start + Inc, End, Inc>(std::forward<F>(f));
2426
}
2527
}
2628

27-
auto valid_paths = std::vector{
28-
std::filesystem::path("a"),
29-
std::filesystem::path("foo/bar/baz/manifest.avro"),
30-
};
29+
constexpr auto valid_paths = std::to_array({"a", "foo/bar/baz/manifest.avro"});
3130

3231
template<typename V>
3332
void test_uri_conversion();
3433

3534
template<>
3635
void test_uri_conversion<cloud_io::s3_compat_provider>() {
37-
auto bucket = cloud_storage_clients::bucket_name("testbucket1");
38-
auto other_bucket = cloud_storage_clients::bucket_name("testbucket2");
36+
const std::vector<cloud_storage_clients::bucket_name> examples = {
37+
cloud_storage_clients::bucket_name{"testbucket1"},
38+
cloud_storage_clients::bucket_name{"test.bucket.name"}};
3939

40-
auto other_converter = uri_converter(
40+
const auto unrelated_bucket = cloud_storage_clients::bucket_name(
41+
"testbucket2");
42+
43+
const auto other_converter = uri_converter(
4144
cloud_io::s3_compat_provider{"otherscheme"});
4245

4346
auto s3_compat_provider_schemes = std::vector{"s3", "gcs"};
4447
for (auto scheme : s3_compat_provider_schemes) {
4548
uri_converter convertor(
4649
cloud_io::provider{cloud_io::s3_compat_provider{scheme}});
4750

48-
for (const auto& path : valid_paths) {
49-
auto uri = convertor.to_uri(bucket, path);
51+
for (const auto& b : examples) {
52+
for (const auto& path : valid_paths) {
53+
auto uri = convertor.to_uri(b, path);
5054

51-
// Forward
52-
ASSERT_EQ(
53-
uri, fmt::format("{}://testbucket1/{}", scheme, path.native()));
55+
// Forward
56+
ASSERT_EQ(uri, fmt::format("{}://{}/{}", scheme, b, path));
5457

55-
// Backward
56-
auto path_res = convertor.from_uri(bucket, uri);
57-
ASSERT_TRUE(path_res.has_value())
58-
<< "Failed to get path from URI: " << uri;
59-
ASSERT_EQ(path_res.value(), path);
58+
// Backward
59+
auto path_res = convertor.from_uri(b, uri);
60+
ASSERT_TRUE(path_res.has_value())
61+
<< "Failed to get path from URI: " << uri;
62+
ASSERT_EQ(path_res.value(), path);
6063

61-
// Should fail with different bucket.
62-
ASSERT_FALSE(convertor.from_uri(other_bucket, uri).has_value());
64+
// Should fail with different bucket.
65+
ASSERT_FALSE(
66+
convertor.from_uri(unrelated_bucket, uri).has_value());
6367

64-
// Should fail with other converter.
65-
ASSERT_FALSE(other_converter.from_uri(bucket, uri).has_value());
68+
// Should fail with other converter.
69+
ASSERT_FALSE(other_converter.from_uri(b, uri).has_value());
70+
}
6671
}
6772
}
6873
}
@@ -83,7 +88,7 @@ void test_uri_conversion<cloud_io::abs_provider>() {
8388
uri,
8489
fmt::format(
8590
"abfss://[email protected]/{}",
86-
path.native()));
91+
path));
8792

8893
// Backward
8994
auto path_res = convertor.from_uri(bucket, uri);
@@ -108,4 +113,6 @@ constexpr void test_uri_conversion_all_providers() {
108113
});
109114
}
110115

116+
} // namespace
117+
111118
TEST(IcebergUriTest, Test) { test_uri_conversion_all_providers(); }

src/v/iceberg/uri.cc

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,15 +73,13 @@ std::optional<std::filesystem::path> uri_converter::from_uri(
7373
|| protocol.back() != ':') {
7474
return std::nullopt;
7575
}
76-
auto dotpos = uri.get_host().find('.');
77-
if (dotpos == std::string::npos) {
78-
// Host is the bucket name.
79-
if (uri.get_host() != bucket()) {
80-
return std::nullopt;
81-
}
82-
} else {
76+
if (uri.get_host() != bucket()) {
8377
// We are not generating yet virtual host style URIs so don't
8478
// parse them yet.
79+
//
80+
// We also exclude the possibility of URI looking like
81+
// s3://bucket.s3.amazonaws.com/path/to/object. I haven't seen
82+
// such examples so assume they do no exist.
8583
return std::nullopt;
8684
}
8785
// Ensure that minimum path length is at least enough to cover the

0 commit comments

Comments
 (0)