-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: create the metastore backups directory if it does not exist #5879
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,11 +19,14 @@ | |
import com.google.common.base.Ticker; | ||
import io.confluent.ksql.rest.entity.CommandId; | ||
import io.confluent.ksql.rest.server.computation.Command; | ||
import io.confluent.ksql.util.KsqlException; | ||
import io.confluent.ksql.util.KsqlConfig; | ||
import io.confluent.ksql.util.KsqlServerException; | ||
import io.confluent.ksql.util.Pair; | ||
import java.io.File; | ||
import java.io.IOException; | ||
import java.nio.file.Files; | ||
import java.nio.file.Paths; | ||
import java.nio.file.attribute.PosixFilePermissions; | ||
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.Objects; | ||
|
@@ -66,10 +69,7 @@ public CommandTopicBackupImpl( | |
final Ticker ticker | ||
) { | ||
final File dir = new File(Objects.requireNonNull(location, "location")); | ||
if (!dir.exists() || !dir.isDirectory()) { | ||
throw new KsqlException(String.format( | ||
"Backup location '%s' does not exist or it is not a directory.", location)); | ||
} | ||
ensureDirectoryExists(dir); | ||
|
||
this.backupLocation = dir; | ||
this.topicName = Objects.requireNonNull(topicName, "topicName"); | ||
|
@@ -222,4 +222,50 @@ private Optional<BackupReplayFile> latestReplayFile() { | |
? Optional.of(new BackupReplayFile(latestBakFile)) | ||
: Optional.empty(); | ||
} | ||
|
||
private void ensureDirectoryExists(final File backupsDir) { | ||
if (!backupsDir.exists()) { | ||
if (!backupsDir.mkdirs()) { | ||
throw new KsqlServerException("Couldn't create the backups directory: " | ||
+ backupsDir.getPath() | ||
+ "\n Make sure the directory exists and is readable/writable for KSQL server " | ||
+ "\n or its parent directory is readable/writable by KSQL server" | ||
+ "\n or change it to a readable/writable directory by setting '" | ||
+ KsqlConfig.KSQL_METASTORE_BACKUP_LOCATION | ||
+ "' config in the properties file." | ||
); | ||
} | ||
|
||
try { | ||
Files.setPosixFilePermissions(backupsDir.toPath(), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does it make sense to explicitly set permissions here? I see we don't do that for the Kafka Streams state directory. I'm in favor of consistency unless there's a good reason to deviate. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd like to keep the metastore directory restricted from other uses to access the data. By default, the directory created has I don't know why the streams state directory is not protected. We might want to do that. I won't do it in this patch until I understand their reason. |
||
PosixFilePermissions.fromString("rwx------")); | ||
} catch (final IOException e) { | ||
throw new KsqlServerException(String.format( | ||
"Couldn't set POSIX permissions on the backups directory: %s. Error = %s", | ||
backupsDir.getPath(), e.getMessage())); | ||
} | ||
} | ||
|
||
if (!backupsDir.isDirectory()) { | ||
throw new KsqlServerException(backupsDir.getPath() | ||
+ " is not a directory." | ||
+ "\n Make sure the directory exists and is readable/writable for KSQL server " | ||
+ "\n or its parent directory is readable/writable by KSQL server" | ||
+ "\n or change it to a readable/writable directory by setting '" | ||
+ KsqlConfig.KSQL_METASTORE_BACKUP_LOCATION | ||
+ "' config in the properties file." | ||
); | ||
} | ||
|
||
if (!backupsDir.canWrite() || !backupsDir.canRead() || !backupsDir.canExecute()) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we need execute permissions? I see we have a similar check for the Kafka Streams state directory so I assume there's good reason. Curious what it is. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Directories need to have execute permissions in order to create files in it. By default, a new directory has
|
||
throw new KsqlServerException("The backups directory is not readable/writable " | ||
+ "for KSQL server: " | ||
+ backupsDir.getPath() | ||
+ "\n Make sure the directory exists and is readable/writable for KSQL server " | ||
+ "\n or change it to a readable/writable directory by setting '" | ||
+ KsqlConfig.KSQL_METASTORE_BACKUP_LOCATION | ||
+ "' config in the properties file." | ||
); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: can we de-dup this code from
enforceStreamStateDirAvailability()
inKsqlServerMain
? Not required if it's annoying to de-dup (especially since we're trying to keep this patch small in order to cherry-pick) but it's weird to me that we have the same code in two places.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, I see it. But I have the extra step to restrict the permissions to the KSQL server user only. I'd like to do that in the state directory too, but I don't know why the directory is not too restrictive. I'd rather investigate more and do it in another follow-up PR.