Skip to content

Commit 409f306

Browse files
committed
HADOOP-18508. Support multiple s3a integration test runs on same bucket in parallel
* adds job id to fork id * adds option to disable root tests * documents this * gets more tests working under the job/fork subdir rather than absolute paths. tracking them down is tricky. Change-Id: I95530f883307b66971c0300631993798967b6739
1 parent fba46aa commit 409f306

File tree

15 files changed

+180
-45
lines changed

15 files changed

+180
-45
lines changed

hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/FileContextMainOperationsBaseTest.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,12 @@ public abstract class FileContextMainOperationsBaseTest {
8181
protected final FileContextTestHelper fileContextTestHelper =
8282
createFileContextHelper();
8383

84+
/**
85+
* Create the test helper.
86+
* Important: this is invoked during the construction of the base class,
87+
* so is very brittle.
88+
* @return a test helper.
89+
*/
8490
protected FileContextTestHelper createFileContextHelper() {
8591
return new FileContextTestHelper();
8692
}
@@ -107,7 +113,7 @@ public boolean accept(Path file) {
107113

108114
private static final byte[] data = getFileData(numBlocks,
109115
getDefaultBlockSize());
110-
116+
111117
@Before
112118
public void setUp() throws Exception {
113119
File testBuildData = GenericTestUtils.getRandomizedTestDir();

hadoop-tools/hadoop-aws/pom.xml

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,13 @@
5656

5757
<!-- Is prefetch enabled? -->
5858
<fs.s3a.prefetch.enabled>unset</fs.s3a.prefetch.enabled>
59+
60+
<!-- Job ID; allows for parallel jobs on same bucket -->
61+
<job.id>0</job.id>
62+
<!-- are root tests enabled. Set to false when running parallel jobs on same bucket -->
63+
<root.tests.enabled>unset</root.tests.enabled>
64+
65+
5966
</properties>
6067

6168
<profiles>
@@ -162,7 +169,7 @@
162169
<!-- surefire.forkNumber won't do the parameter -->
163170
<!-- substitution. Putting a prefix in front of it like -->
164171
<!-- "fork-" makes it work. -->
165-
<test.unique.fork.id>fork-000${surefire.forkNumber}</test.unique.fork.id>
172+
<test.unique.fork.id>job-${job.id}-fork-000${surefire.forkNumber}</test.unique.fork.id>
166173
<!-- Propagate scale parameters -->
167174
<fs.s3a.scale.test.enabled>${fs.s3a.scale.test.enabled}</fs.s3a.scale.test.enabled>
168175
<fs.s3a.scale.test.huge.filesize>${fs.s3a.scale.test.huge.filesize}</fs.s3a.scale.test.huge.filesize>
@@ -173,14 +180,14 @@
173180
<test.default.timeout>${test.integration.timeout}</test.default.timeout>
174181
<!-- Prefetch -->
175182
<fs.s3a.prefetch.enabled>${fs.s3a.prefetch.enabled}</fs.s3a.prefetch.enabled>
183+
<!-- are root tests enabled. Set to false when running parallel jobs on same bucket -->
184+
<fs.s3a.root.tests.enabled>${root.tests.enabled}</fs.s3a.root.tests.enabled>
185+
176186
</systemPropertyVariables>
177187
<!-- Some tests cannot run in parallel. Tests that cover -->
178188
<!-- access to the root directory must run in isolation -->
179189
<!-- from anything else that could modify the bucket. -->
180-
<!-- S3A tests that cover multi-part upload must run in -->
181-
<!-- isolation, because the file system is configured to -->
182-
<!-- purge existing multi-part upload data on -->
183-
<!-- initialization. MiniYARNCluster has not yet been -->
190+
<!-- MiniYARNCluster has not yet been -->
184191
<!-- changed to handle parallel test execution gracefully. -->
185192
<!-- Exclude all of these tests from parallel execution, -->
186193
<!-- and instead run them sequentially in a separate -->
@@ -224,6 +231,9 @@
224231
<fs.s3a.directory.marker.audit>${fs.s3a.directory.marker.audit}</fs.s3a.directory.marker.audit>
225232
<!-- Prefetch -->
226233
<fs.s3a.prefetch.enabled>${fs.s3a.prefetch.enabled}</fs.s3a.prefetch.enabled>
234+
<!-- are root tests enabled. Set to false when running parallel jobs on same bucket -->
235+
<fs.s3a.root.tests.enabled>${root.tests.enabled}</fs.s3a.root.tests.enabled>
236+
<test.unique.fork.id>job-${job.id}</test.unique.fork.id>
227237
</systemPropertyVariables>
228238
<!-- Do a sequential run for tests that cannot handle -->
229239
<!-- parallel execution. -->

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

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,50 @@ Otherwise, set a large timeout in `fs.s3a.scale.test.timeout`
518518
The tests are executed in an order to only clean up created files after
519519
the end of all the tests. If the tests are interrupted, the test data will remain.
520520

521+
## Testing through continuous integration
522+
523+
Supporting
524+
parallel test jobs against the same bucket
525+
526+
For CI testing of the module, including the integration tests,
527+
it is generally necessary to support testing multiple PRs simultaneously.
528+
529+
To do this
530+
1. A job ID must be supplied in the `job.id` property, so each job works on an isolated directory
531+
tree. This should be a number or unique string, which will be used within a path element, so
532+
must only contain characters valid in an S3/hadoop path element.
533+
2. Root directory tests need to be disabled by setting `fs.s3a.root.tests.enabled` to
534+
`false`, either in the command line to maven or in the XML configurations.
535+
536+
```
537+
mvn verify -T 1C -Dparallel-tests -DtestsThreadCount=14 -Dscale -Dfs.s3a.root.tests.enabled=false -Djob.id=001
538+
```
539+
540+
This parallel execution feature is only for isolated builds sharing a single S3 bucket; it does
541+
not support parallel builds and tests from the same local source tree.
542+
543+
Without the root tests being executed, set up a scheduled job to purge the test bucket of all
544+
data on a regular basis, to keep costs down. Running the test `ITestS3AContractRootDir` is
545+
sufficient for this, as is a `hadoop fs` command.
546+
547+
```
548+
hadoop fs -rm -r s3a://s3a-tests-us-west-1/*
549+
```
550+
551+
### Securing CI builds
552+
553+
It's clearly unsafe to have CI infrastructure testing PRs submitted to apache github account
554+
with AWS credentials -which is why it isn't done by the Yetus-initiated builds.
555+
556+
Anyone doing this privately should
557+
* Review patches before triggering the tests.
558+
* Have a dedicated IAM role with restricted access to the test bucket, any KMS keys used, and the
559+
external bucket containing the CSV test file.
560+
* Have a build process which generates short-lived session credentials for this role.
561+
* And
562+
563+
564+
521565
## <a name="alternate_s3"></a> Load tests.
522566

523567
Some are designed to overload AWS services with more

hadoop-tools/hadoop-aws/src/test/java/org/apache/hadoop/fs/contract/s3a/ITestS3AContractRootDir.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
import org.apache.hadoop.fs.contract.AbstractFSContract;
2828
import org.apache.hadoop.fs.s3a.S3AFileSystem;
2929

30+
import static org.apache.hadoop.fs.s3a.S3ATestUtils.maybeSkipRootTests;
31+
3032
/**
3133
* root dir operations against an S3 bucket.
3234
*/
@@ -36,6 +38,12 @@ public class ITestS3AContractRootDir extends
3638
private static final Logger LOG =
3739
LoggerFactory.getLogger(ITestS3AContractRootDir.class);
3840

41+
@Override
42+
public void setup() throws Exception {
43+
super.setup();
44+
maybeSkipRootTests(getFileSystem().getConf());
45+
}
46+
3947
@Override
4048
protected AbstractFSContract createContract(Configuration conf) {
4149
return new S3AContract(conf);

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -354,8 +354,10 @@ public void shouldBeAbleToSwitchOnS3PathStyleAccessViaConfigProperty()
354354
clientOptions.isPathStyleAccess());
355355
byte[] file = ContractTestUtils.toAsciiByteArray("test file");
356356
ContractTestUtils.writeAndRead(fs,
357-
new Path("/path/style/access/testFile"), file, file.length,
358-
(int) conf.getLongBytes(Constants.FS_S3A_BLOCK_SIZE, file.length), false, true);
357+
createTestPath(new Path("/path/style/access/testFile")),
358+
file, file.length,
359+
(int) conf.getLongBytes(Constants.FS_S3A_BLOCK_SIZE, file.length),
360+
false, true);
359361
} catch (final AWSS3IOException e) {
360362
LOG.error("Caught exception: ", e);
361363
// Catch/pass standard path style access behaviour when live bucket

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
import static org.apache.hadoop.fs.s3a.S3ATestUtils.createTestPath;
4949
import static org.apache.hadoop.fs.s3a.S3ATestUtils.disableFilesystemCaching;
5050
import static org.apache.hadoop.fs.s3a.S3ATestUtils.getTestBucketName;
51+
import static org.apache.hadoop.fs.s3a.S3ATestUtils.maybeSkipRootTests;
5152
import static org.apache.hadoop.fs.s3a.S3ATestUtils.removeBaseAndBucketOverrides;
5253
import static org.apache.hadoop.test.LambdaTestUtils.intercept;
5354

@@ -129,6 +130,9 @@ protected Configuration createConfiguration() {
129130
public void setup() throws Exception {
130131
super.setup();
131132
assumeEnabled();
133+
// although not a root dir test, this confuses paths enough it shouldn't be run in
134+
// parallel with other jobs
135+
maybeSkipRootTests(getConfiguration());
132136
}
133137

134138
@Override

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,11 @@
1818

1919
package org.apache.hadoop.fs.s3a;
2020

21+
import java.io.IOException;
22+
23+
import org.junit.Assert;
2124
import org.junit.Ignore;
25+
import org.junit.Test;
2226

2327
import org.apache.hadoop.conf.Configuration;
2428
import org.apache.hadoop.fs.FSMainOperationsBaseTest;
@@ -54,6 +58,26 @@ public void tearDown() throws Exception {
5458
}
5559
}
5660

61+
62+
@Test
63+
@Override
64+
public void testWDAbsolute() throws IOException {
65+
Path absoluteDir = getTestRootPath(fSys, "test/existingDir");
66+
fSys.mkdirs(absoluteDir);
67+
fSys.setWorkingDirectory(absoluteDir);
68+
Assert.assertEquals(absoluteDir, fSys.getWorkingDirectory());
69+
}
70+
71+
/**
72+
* Get an absolute directory for the test {@link #testWDAbsolute()}.
73+
*
74+
* @return a fully qualified path.
75+
*/
76+
protected Path getAbsoluteDirectoryForWorkingDir() {
77+
return new Path(new Path(fSys.getUri()),
78+
createTestPath(new Path("/test/existingDir")));
79+
}
80+
5781
@Override
5882
@Ignore("Permissions not supported")
5983
public void testListStatusThrowsExceptionForUnreadableDir() {

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,4 +251,15 @@ public interface S3ATestConstants {
251251
* Value: {@value}.
252252
*/
253253
String PROJECT_BUILD_DIRECTORY_PROPERTY = "project.build.directory";
254+
255+
/**
256+
* System property for root tests being enabled: {@value}.
257+
*/
258+
String ROOT_TESTS_ENABLED = "fs.s3a.root.tests.enabled";
259+
260+
261+
/**
262+
* Default policy on root tests: {@value}.
263+
*/
264+
boolean DEFAULT_ROOT_TESTS_ENABLED = true;
254265
}

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,7 @@ public static void skipIfStorageClassTestsDisabled(
485485
*/
486486
public static Path createTestPath(Path defVal) {
487487
String testUniqueForkId =
488-
System.getProperty(S3ATestConstants.TEST_UNIQUE_FORK_ID);
488+
System.getProperty(TEST_UNIQUE_FORK_ID);
489489
return testUniqueForkId == null ? defVal :
490490
new Path("/" + testUniqueForkId, "test");
491491
}
@@ -1510,4 +1510,13 @@ public static S3AInputStream getS3AInputStream(
15101510
public static void disablePrefetching(Configuration conf) {
15111511
removeBaseAndBucketOverrides(conf, PREFETCH_ENABLED_KEY);
15121512
}
1513+
1514+
/**
1515+
* Skip root tests if the system properties/config says so.
1516+
* @param conf configuration to check
1517+
*/
1518+
public static void maybeSkipRootTests(Configuration conf) {
1519+
assume("Root tests disabled",
1520+
getTestPropertyBool(conf, ROOT_TESTS_ENABLED, DEFAULT_ROOT_TESTS_ENABLED));
1521+
}
15131522
}

hadoop-tools/hadoop-aws/src/test/java/org/apache/hadoop/fs/s3a/fileContext/ITestS3AFileContextMainOperations.java

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,36 @@
33
* you may not use this file except in compliance with the License.
44
* You may obtain a copy of the License at
55
*
6-
* http://www.apache.org/licenses/LICENSE-2.0
6+
* http://www.apache.org/licenses/LICENSE-2.0
77
*
88
* Unless required by applicable law or agreed to in writing, software
99
* distributed under the License is distributed on an "AS IS" BASIS,
1010
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1111
* See the License for the specific language governing permissions and
1212
* limitations under the License.
1313
*/
14+
1415
package org.apache.hadoop.fs.s3a.fileContext;
1516

1617
import java.io.IOException;
17-
import org.apache.hadoop.conf.Configuration;
18-
import org.apache.hadoop.fs.FileContextMainOperationsBaseTest;
19-
import org.apache.hadoop.fs.s3a.S3ATestUtils;
18+
import java.util.UUID;
19+
2020
import org.junit.Before;
2121
import org.junit.Ignore;
2222
import org.junit.Test;
2323

24+
import org.apache.hadoop.conf.Configuration;
25+
import org.apache.hadoop.fs.FileContextMainOperationsBaseTest;
26+
import org.apache.hadoop.fs.FileContextTestHelper;
27+
import org.apache.hadoop.fs.Path;
28+
import org.apache.hadoop.fs.s3a.S3ATestUtils;
29+
2430
/**
2531
* S3A implementation of FileContextMainOperationsBaseTest.
2632
*/
2733
public class ITestS3AFileContextMainOperations
28-
extends FileContextMainOperationsBaseTest {
34+
extends FileContextMainOperationsBaseTest {
35+
2936

3037
@Before
3138
public void setUp() throws IOException, Exception {
@@ -34,6 +41,19 @@ public void setUp() throws IOException, Exception {
3441
super.setUp();
3542
}
3643

44+
45+
/**
46+
* Called before even our own constructor and fields are
47+
* inited.
48+
* @return a test helper using the s3a test path.
49+
*/
50+
@Override
51+
protected FileContextTestHelper createFileContextHelper() {
52+
Path testPath =
53+
S3ATestUtils.createTestPath(new Path("/" + UUID.randomUUID()));
54+
return new FileContextTestHelper(testPath.toUri().toString());
55+
}
56+
3757
@Override
3858
protected boolean listCorruptedBlocksSupported() {
3959
return false;

0 commit comments

Comments
 (0)