Skip to content

Commit 62f645c

Browse files
umustafiUrmi Mustafi
and
Urmi Mustafi
authored
[GOBBLIN-2049] Configure Gobblin Distcp Writer to fail if setPermission fails (apache#3929)
Configure Gobblin Distcp Writer to fail if setPermission fails --------- Co-authored-by: Urmi Mustafi <[email protected]>
1 parent b57ecbc commit 62f645c

File tree

2 files changed

+28
-8
lines changed

2 files changed

+28
-8
lines changed

gobblin-data-management/src/main/java/org/apache/gobblin/data/management/copy/publisher/CopyDataPublisher.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ public boolean isThreadSafe() {
9595
protected final DataFileVersionStrategy dstDataFileVersionStrategy;
9696
protected final boolean preserveDirModTime;
9797
protected final boolean resyncDirOwnerAndPermission;
98+
protected final boolean shouldFailWhenPermissionsFail;
9899

99100
/**
100101
* Build a new {@link CopyDataPublisher} from {@link State}. The constructor expects the following to be set in the
@@ -135,6 +136,7 @@ public CopyDataPublisher(State state) throws IOException {
135136
// Default to be true to preserve the original behavior
136137
this.preserveDirModTime = state.getPropAsBoolean(CopyConfiguration.PRESERVE_MODTIME_FOR_DIR, true);
137138
this.resyncDirOwnerAndPermission = state.getPropAsBoolean(CopyConfiguration.RESYNC_DIR_OWNER_AND_PERMISSION_FOR_MANIFEST_COPY, false);
139+
this.shouldFailWhenPermissionsFail = state.getPropAsBoolean(FileAwareInputStreamDataWriter.GOBBLIN_COPY_SHOULD_FAIL_WHEN_PERMISSIONS_FAIL, FileAwareInputStreamDataWriter.DEFAULT_COPY_SHOULD_FAIL_WHEN_PERMISSIONS_FAIL);
138140
}
139141

140142
@Override
@@ -197,7 +199,7 @@ private void preserveFileAttrInPublisher(CopyableFile copyableFile) throws IOExc
197199
FileStatus dstFile = this.fs.getFileStatus(copyableFile.getDestination());
198200
// User specifically try to copy dir metadata, so we change the group and permissions on destination even when the dir already existed
199201
log.info("Setting destination directory {} owner and permission to {}", dstFile.getPath(), copyableFile.getDestinationOwnerAndPermission().getFsPermission());
200-
FileAwareInputStreamDataWriter.safeSetPathPermission(this.fs, dstFile, copyableFile.getDestinationOwnerAndPermission());
202+
FileAwareInputStreamDataWriter.setPathPermission(this.fs, dstFile, copyableFile.getDestinationOwnerAndPermission(), this.shouldFailWhenPermissionsFail);
201203
}
202204
if (preserveDirModTime || copyableFile.getFileStatus().isFile()) {
203205
// Preserving File ModTime, and set the access time to an initializing value when ModTime is declared to be preserved.

gobblin-data-management/src/main/java/org/apache/gobblin/data/management/copy/writer/FileAwareInputStreamDataWriter.java

+25-7
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ public class FileAwareInputStreamDataWriter extends InstrumentedDataWriter<FileA
9090
public static final boolean DEFAULT_GOBBLIN_COPY_CHECK_FILESIZE = false;
9191
public static final String GOBBLIN_COPY_TASK_OVERWRITE_ON_COMMIT = "gobblin.copy.task.overwrite.on.commit";
9292
public static final boolean DEFAULT_GOBBLIN_COPY_TASK_OVERWRITE_ON_COMMIT = false;
93+
public static final String GOBBLIN_COPY_SHOULD_FAIL_WHEN_PERMISSIONS_FAIL = "gobblin.copy.shouldFailWhenPermissionsFail";
94+
public static final boolean DEFAULT_COPY_SHOULD_FAIL_WHEN_PERMISSIONS_FAIL = true;
9395

9496
protected final AtomicLong bytesWritten = new AtomicLong();
9597
protected final AtomicLong filesWritten = new AtomicLong();
@@ -108,6 +110,7 @@ public class FileAwareInputStreamDataWriter extends InstrumentedDataWriter<FileA
108110
private final Configuration conf;
109111

110112
protected final Meter copySpeedMeter;
113+
protected final boolean shouldFailWhenPermissionsFail;
111114

112115
protected final Optional<String> writerAttemptIdOptional;
113116
/**
@@ -181,6 +184,8 @@ public FileAwareInputStreamDataWriter(State state, FileSystem fileSystem, int nu
181184
} else {
182185
this.renameOptions = Options.Rename.NONE;
183186
}
187+
this.shouldFailWhenPermissionsFail = state.getPropAsBoolean(GOBBLIN_COPY_SHOULD_FAIL_WHEN_PERMISSIONS_FAIL,
188+
DEFAULT_COPY_SHOULD_FAIL_WHEN_PERMISSIONS_FAIL);
184189
}
185190

186191
public FileAwareInputStreamDataWriter(State state, int numBranches, int branchId)
@@ -350,10 +355,13 @@ public static Path getOutputDir(State state) {
350355
}
351356

352357
/**
353-
* Sets the {@link FsPermission}, owner, group for the path passed. It will not throw exceptions, if operations
354-
* cannot be executed, will warn and continue.
358+
* Sets the {@link FsPermission}, owner, group for the path passed. It uses `requirePermissionSetForSuccess` param
359+
* to determine whether an exception will be thrown or only error log printed in the case of failure.
360+
* @param requirePermissionSetForSuccess if true then throw exception, otherwise log error message and continue when
361+
* operations cannot be executed.
355362
*/
356-
public static void safeSetPathPermission(FileSystem fs, FileStatus file, OwnerAndPermission ownerAndPermission) {
363+
public static void setPathPermission(FileSystem fs, FileStatus file, OwnerAndPermission ownerAndPermission,
364+
boolean requirePermissionSetForSuccess) throws IOException {
357365

358366
Path path = file.getPath();
359367
OwnerAndPermission targetOwnerAndPermission = setOwnerExecuteBitIfDirectory(file, ownerAndPermission);
@@ -367,7 +375,12 @@ public static void safeSetPathPermission(FileSystem fs, FileStatus file, OwnerAn
367375
fs.setPermission(path, targetOwnerAndPermission.getFsPermission());
368376
}
369377
} catch (IOException ioe) {
370-
log.warn("Failed to set permission for directory " + path, ioe);
378+
String permissionFailureMessage = "Failed to set permission for directory " + path;
379+
if (requirePermissionSetForSuccess) {
380+
throw new IOException(permissionFailureMessage, ioe);
381+
} else {
382+
log.error(permissionFailureMessage, ioe);
383+
}
371384
}
372385

373386
String owner = Strings.isNullOrEmpty(targetOwnerAndPermission.getOwner()) ? null : targetOwnerAndPermission.getOwner();
@@ -378,7 +391,12 @@ public static void safeSetPathPermission(FileSystem fs, FileStatus file, OwnerAn
378391
fs.setOwner(path, owner, group);
379392
}
380393
} catch (IOException ioe) {
381-
log.warn("Failed to set owner and/or group for path " + path + " to " + owner + ":" + group, ioe);
394+
String ownerGroupFailureMessage = "Failed to set owner and/or group for path " + path + " to " + owner + ":" + group;
395+
if (requirePermissionSetForSuccess) {
396+
throw new IOException(ownerGroupFailureMessage, ioe);
397+
} else {
398+
log.error(ownerGroupFailureMessage, ioe);
399+
}
382400
}
383401
}
384402

@@ -394,7 +412,7 @@ private void setRecursivePermission(Path path, OwnerAndPermission ownerAndPermis
394412
Collections.reverse(files);
395413

396414
for (FileStatus file : files) {
397-
safeSetPathPermission(this.fs, file, ownerAndPermission);
415+
setPathPermission(this.fs, file, ownerAndPermission, this.shouldFailWhenPermissionsFail);
398416
}
399417
}
400418

@@ -480,7 +498,7 @@ public void commit()
480498
try {
481499
this.fs.delete(this.stagingDir, true);
482500
} catch (IOException ioe) {
483-
log.warn("Failed to delete staging path at " + this.stagingDir);
501+
log.error("Failed to delete staging path at " + this.stagingDir);
484502
}
485503
}
486504
}

0 commit comments

Comments
 (0)