Skip to content

Commit afc6787

Browse files
committed
HADOOP-18820. Audit handler migration.
v1 conf load uses getTrimmed() and logs the list of values; v2 ExecutionInterceptor will, if they implement Configurable, get the auditor Configuration Change-Id: Ic0d49cbceb4a0c9fed9013c9a605f9b240801d73
1 parent f7b2638 commit afc6787

File tree

5 files changed

+49
-12
lines changed

5 files changed

+49
-12
lines changed

hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/audit/impl/ActiveAuditManagerS3A.java

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
import software.amazon.awssdk.http.SdkHttpRequest;
3434
import software.amazon.awssdk.http.SdkHttpResponse;
3535
import software.amazon.awssdk.transfer.s3.progress.TransferListener;
36+
37+
import org.apache.hadoop.conf.Configurable;
3638
import org.apache.hadoop.util.Preconditions;
3739
import org.slf4j.Logger;
3840
import org.slf4j.LoggerFactory;
@@ -404,19 +406,26 @@ public List<ExecutionInterceptor> createExecutionInterceptors()
404406
List<ExecutionInterceptor> executionInterceptors = new ArrayList<>();
405407
executionInterceptors.add(this);
406408

407-
final String handlers = getConfig().get(AUDIT_REQUEST_HANDLERS);
408-
if (handlers != null) {
409-
V2Migration.v1RequestHandlersUsed();
409+
final String handlers = getConfig().getTrimmed(AUDIT_REQUEST_HANDLERS, "");
410+
if (!handlers.isEmpty()) {
411+
// warn and ignore v1 handlers.
412+
V2Migration.v1RequestHandlersUsed(handlers);
410413
}
411414

412-
// TODO: should we remove this and use Global/Service interceptors, see:
413-
// https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/interceptor/ExecutionInterceptor.html
415+
// V2 SDK supports global/service interceptors, but they need to be configured on the
416+
// classpath and don't get the filesystem/job configuration passed down.
414417
final Class<?>[] interceptors = getConfig().getClasses(AUDIT_EXECUTION_INTERCEPTORS);
415418
if (interceptors != null) {
416419
for (Class<?> handler : interceptors) {
417420
try {
421+
LOG.debug("Adding intercept of class {}", handler);
418422
Constructor<?> ctor = handler.getConstructor();
419-
executionInterceptors.add((ExecutionInterceptor) ctor.newInstance());
423+
final ExecutionInterceptor interceptor = (ExecutionInterceptor) ctor.newInstance();
424+
if (interceptor instanceof Configurable) {
425+
// pass in the configuration.
426+
((Configurable) interceptor).setConf(getConfig());
427+
}
428+
executionInterceptors.add(interceptor);
420429
} catch (ExceptionInInitializerError e) {
421430
throw FutureIO.unwrapInnerException(e);
422431
} catch (Exception e) {

hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/impl/V2Migration.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
import org.apache.hadoop.fs.store.LogExactlyOnce;
2525

26+
import static org.apache.hadoop.fs.s3a.audit.S3AAuditConstants.AUDIT_REQUEST_HANDLERS;
2627
import static org.apache.hadoop.fs.s3a.impl.InternalConstants.SDK_V2_UPGRADE_LOG_NAME;
2728

2829
/**
@@ -50,11 +51,12 @@ private V2Migration() { }
5051

5152
/**
5253
* Notes use of request handlers.
54+
* @param handlers handlers declared
5355
*/
54-
public static void v1RequestHandlersUsed() {
56+
public static void v1RequestHandlersUsed(final String handlers) {
5557
WARN_OF_REQUEST_HANDLERS.warn(
56-
"The request handler interface has changed in AWS SDK V2, use exception interceptors "
57-
+ "now S3A is upgraded to SDK V2");
58+
"Ignoring V1 SDK request handlers set in {}: {}",
59+
AUDIT_REQUEST_HANDLERS, handlers);
5860
}
5961

6062
}

hadoop-tools/hadoop-aws/src/site/markdown/tools/hadoop-aws/auditing.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,9 @@ all of which must implement the interface `software.amazon.awssdk.core.intercept
172172

173173
The list of classes is set in the configuration option `fs.s3a.audit.execution.interceptors`.
174174

175+
Any class in the list which implements `org.apache.hadoop.conf.Configurable` will have
176+
`Configurable.setConf()` called with the filesystem configuration passed down.
177+
175178
Before the upgrade to the V2 SDK, a list of extra subclasses of the AWS SDK `com.amazonaws.handlers.RequestHandler2`
176179
class could be declared in the option `fs.s3a.audit.request.handlers`;
177180
these would be wired up into the V1 request processing pipeline.

hadoop-tools/hadoop-aws/src/test/java/org/apache/hadoop/fs/s3a/audit/ITestAuditManager.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import static org.apache.hadoop.fs.s3a.audit.AuditTestSupport.enableLoggingAuditor;
3535
import static org.apache.hadoop.fs.s3a.audit.AuditTestSupport.resetAuditOptions;
3636
import static org.apache.hadoop.fs.s3a.audit.S3AAuditConstants.AUDIT_EXECUTION_INTERCEPTORS;
37+
import static org.apache.hadoop.fs.s3a.audit.S3AAuditConstants.AUDIT_REQUEST_HANDLERS;
3738
import static org.apache.hadoop.fs.s3a.audit.S3AAuditConstants.UNAUDITED_OPERATION;
3839
import static org.apache.hadoop.fs.statistics.IOStatisticAssertions.assertThatStatisticCounter;
3940
import static org.apache.hadoop.fs.statistics.IOStatisticAssertions.lookupCounterStatistic;
@@ -59,6 +60,7 @@ public Configuration createConfiguration() {
5960
enableLoggingAuditor(conf);
6061
conf.set(AUDIT_EXECUTION_INTERCEPTORS,
6162
SimpleAWSExecutionInterceptor.CLASS);
63+
conf.set(AUDIT_REQUEST_HANDLERS, "not-valid-class");
6264
return conf;
6365
}
6466

@@ -114,8 +116,8 @@ public void testInvokeOutOfSpanRejected() throws Throwable {
114116
}
115117

116118
@Test
117-
public void testRequestHandlerBinding() throws Throwable {
118-
describe("Verify that extra request handlers can be added and that they"
119+
public void testExecutionInterceptorBinding() throws Throwable {
120+
describe("Verify that extra ExecutionInterceptor can be added and that they"
119121
+ " will be invoked during request execution");
120122
final long baseCount = SimpleAWSExecutionInterceptor.getInvocationCount();
121123
final S3AFileSystem fs = getFileSystem();
@@ -131,5 +133,9 @@ public void testRequestHandlerBinding() throws Throwable {
131133
.isGreaterThan(exec0);
132134
assertThatStatisticCounter(iostats(), AUDIT_FAILURE.getSymbol())
133135
.isZero();
136+
Assertions.assertThat(SimpleAWSExecutionInterceptor.getStaticConf())
137+
.describedAs("configuratin of SimpleAWSExecutionInterceptor")
138+
.isNotNull()
139+
.isSameAs(fs.getConf());
134140
}
135141
}

hadoop-tools/hadoop-aws/src/test/java/org/apache/hadoop/fs/s3a/audit/SimpleAWSExecutionInterceptor.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,24 +24,31 @@
2424
import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
2525
import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
2626

27+
import org.apache.hadoop.conf.Configuration;
28+
import org.apache.hadoop.conf.Configured;
29+
2730
/**
2831
* Simple AWS interceptor to verify dynamic loading of extra
2932
* execution interceptors during auditing setup.
3033
* The invocation counter tracks the count of calls to
3134
* {@link #beforeExecution}.
3235
*/
33-
public final class SimpleAWSExecutionInterceptor implements ExecutionInterceptor {
36+
public final class SimpleAWSExecutionInterceptor extends Configured
37+
implements ExecutionInterceptor {
3438

3539
public static final String CLASS
3640
= "org.apache.hadoop.fs.s3a.audit.SimpleAWSExecutionInterceptor";
3741

42+
private static Configuration staticConf;
43+
3844
/** Count of invocations. */
3945
private static final AtomicLong INVOCATIONS = new AtomicLong(0);
4046

4147
@Override
4248
public void beforeExecution(Context.BeforeExecution context,
4349
ExecutionAttributes executionAttributes) {
4450
INVOCATIONS.incrementAndGet();
51+
staticConf = getConf();
4552
}
4653

4754
/**
@@ -51,4 +58,14 @@ public void beforeExecution(Context.BeforeExecution context,
5158
public static long getInvocationCount() {
5259
return INVOCATIONS.get();
5360
}
61+
62+
/**
63+
* get the static conf, which is set the config of the
64+
* last executor invoked.
65+
* @return the static configuration.
66+
*/
67+
68+
public static Configuration getStaticConf() {
69+
return staticConf;
70+
}
5471
}

0 commit comments

Comments
 (0)