Skip to content

Commit 9be15e1

Browse files
committed
Allow differentiating blobstores by buckets
Allows differentiating the backend blobstores by configured buckets. The commit allows using the same s3proxy credentials across the different backends and relies on the bucket names to disambiguate them. The "default" blobstore is the one that occurs first. Fixes: #371
1 parent 35fea54 commit 9be15e1

File tree

2 files changed

+58
-15
lines changed

2 files changed

+58
-15
lines changed

src/main/java/org/gaul/s3proxy/Main.java

+46-15
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,11 @@
2424
import java.io.PrintStream;
2525
import java.nio.charset.StandardCharsets;
2626
import java.util.ArrayList;
27+
import java.util.HashSet;
2728
import java.util.List;
2829
import java.util.Map;
2930
import java.util.Properties;
31+
import java.util.Set;
3032
import java.util.concurrent.ExecutorService;
3133
import java.util.concurrent.Executors;
3234
import java.util.concurrent.ThreadFactory;
@@ -101,8 +103,10 @@ public static void main(String[] args) throws Exception {
101103
.build();
102104
ExecutorService executorService = DynamicExecutors.newScalingThreadPool(
103105
1, 20, 60 * 1000, factory);
104-
ImmutableMap.Builder<String, Map.Entry<String, BlobStore>> locators =
106+
ImmutableMap.Builder<Map.Entry<String, String>,
107+
Map.Entry<String, BlobStore>> locators =
105108
ImmutableMap.builder();
109+
Set<Map.Entry<String, String>> parsedLocations = new HashSet<>();
106110
for (File propertiesFile : options.propertiesFiles) {
107111
Properties properties = new Properties();
108112
try (InputStream is = new FileInputStream(propertiesFile)) {
@@ -117,14 +121,42 @@ public static void main(String[] args) throws Exception {
117121

118122
String s3ProxyAuthorizationString = properties.getProperty(
119123
S3ProxyConstants.PROPERTY_AUTHORIZATION);
124+
ImmutableList.Builder<String> locatorBuckets =
125+
new ImmutableList.Builder<>();
126+
for (String key : properties.stringPropertyNames()) {
127+
if (key.startsWith(S3ProxyConstants.PROPERTY_BUCKET_LOCATOR)) {
128+
locatorBuckets.add(properties.getProperty(key));
129+
}
130+
}
131+
ImmutableList<String> buckets = locatorBuckets.build();
132+
String localIdentity = null;
133+
String localCredential = null;
120134
if (AuthenticationType.fromString(s3ProxyAuthorizationString) !=
121135
AuthenticationType.NONE) {
122-
String localIdentity = properties.getProperty(
136+
localIdentity = properties.getProperty(
123137
S3ProxyConstants.PROPERTY_IDENTITY);
124-
String localCredential = properties.getProperty(
138+
localCredential = properties.getProperty(
125139
S3ProxyConstants.PROPERTY_CREDENTIAL);
126-
locators.put(localIdentity, Maps.immutableEntry(
127-
localCredential, blobStore));
140+
Map.Entry<String, String> key = Maps.immutableEntry(
141+
localIdentity, null);
142+
if (parsedLocations.add(key)) {
143+
locators.put(key, Maps.immutableEntry(
144+
localCredential, blobStore));
145+
}
146+
}
147+
if (!buckets.isEmpty()) {
148+
for (String bucket : buckets) {
149+
Map.Entry<String, String> key = Maps.immutableEntry(
150+
localIdentity, bucket);
151+
if (!parsedLocations.add(key)) {
152+
System.err.printf("The same bucket locator cannot be" +
153+
" used in two properties files: %s\n",
154+
bucket);
155+
System.exit(1);
156+
}
157+
locators.put(key,
158+
Maps.immutableEntry(localCredential, blobStore));
159+
}
128160
}
129161

130162
S3Proxy.Builder s3ProxyBuilder2 = S3Proxy.Builder
@@ -149,23 +181,22 @@ public static void main(String[] args) throws Exception {
149181
throw e;
150182
}
151183

152-
final Map<String, Map.Entry<String, BlobStore>> locator =
153-
locators.build();
184+
final Map<Map.Entry<String, String>, Map.Entry<String, BlobStore>>
185+
locator = locators.build();
154186
if (!locator.isEmpty()) {
155187
s3Proxy.setBlobStoreLocator(new BlobStoreLocator() {
156188
@Override
157189
public Map.Entry<String, BlobStore> locateBlobStore(
158190
String identity, String container, String blob) {
191+
Map.Entry<String, BlobStore> entry = locator.get(
192+
Maps.immutableEntry(identity, container));
193+
if (entry != null) {
194+
return entry;
195+
}
159196
if (identity == null) {
160-
if (locator.size() == 1) {
161-
return locator.entrySet().iterator().next()
162-
.getValue();
163-
}
164-
throw new IllegalArgumentException(
165-
"cannot use anonymous access with multiple" +
166-
" backends");
197+
return locator.entrySet().iterator().next().getValue();
167198
}
168-
return locator.get(identity);
199+
return locator.get(Maps.immutableEntry(identity, null));
169200
}
170201
});
171202
}

src/main/java/org/gaul/s3proxy/S3ProxyConstants.java

+12
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,18 @@ public final class S3ProxyConstants {
6666
"s3proxy.max-single-part-object-size";
6767
public static final String PROPERTY_V4_MAX_NON_CHUNKED_REQUEST_SIZE =
6868
"s3proxy.v4-max-non-chunked-request-size";
69+
/** Used to locate blobstores by specified bucket names. Each property
70+
* file should contain a list of buckets associated with it, e.g.
71+
* s3proxy.bucket-locator.1 = data
72+
* s3proxy.bucket-locator.2 = metadata
73+
* s3proxy.bucket-locator.3 = other
74+
* When a request is made for the specified bucket, the backend defined
75+
* in that properties file is used. This allows using the same
76+
* credentials in multiple properties file and select the backend based
77+
* on the bucket names.
78+
*/
79+
public static final String PROPERTY_BUCKET_LOCATOR =
80+
"s3proxy.bucket-locator";
6981
/** When true, model eventual consistency using two storage backends. */
7082
public static final String PROPERTY_EVENTUAL_CONSISTENCY =
7183
"s3proxy.eventual-consistency";

0 commit comments

Comments
 (0)