Skip to content

Commit

Permalink
CLI: fix temp file permissions (#629)
Browse files Browse the repository at this point in the history
  • Loading branch information
nicoloboschi authored Oct 20, 2023
1 parent bb8dbe5 commit 08b9c1c
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.input.Tailer;
import org.apache.commons.io.input.TailerListener;
import org.apache.commons.lang3.SystemUtils;
import picocli.CommandLine;

@CommandLine.Command(name = "run", header = "Run on a docker container a LangStream application")
Expand Down Expand Up @@ -302,14 +303,9 @@ private void executeOnDocker(
boolean startDatabase,
boolean dryRun)
throws Exception {
final File appTmp = generateTempFile("app");
FileUtils.copyDirectory(appDirectory, appTmp);
makeDirOrFileReadable(appTmp);
File tmpInstanceFile = createReadableTempFile("instance", instanceContents);
File tmpSecretsFile = null;
if (secretsContents != null) {
tmpSecretsFile = createReadableTempFile("secrets", secretsContents);
}
final File appTmp = prepareAppDirectory(appDirectory);
File tmpInstanceFile = prepareInstanceFile(instanceContents);
File tmpSecretsFile = prepareSecretsFile(secretsContents);
String imageName = dockerImageName + ":" + dockerImageVersion;
List<String> commandLine = new ArrayList<>();
commandLine.add(dockerCommand);
Expand Down Expand Up @@ -403,6 +399,33 @@ private void executeOnDocker(
}
}

private File prepareSecretsFile(String secretsContents) throws IOException {
File tmpSecretsFile = null;
if (secretsContents != null) {
tmpSecretsFile = createReadableTempFile("secrets", secretsContents);
}
return tmpSecretsFile;
}

private File prepareInstanceFile(String instanceContents) throws IOException {
return createReadableTempFile("instance", instanceContents);
}

private File prepareAppDirectory(File appDirectory) throws IOException {
// depending on the docker engine, we should ensure the permissions are properly set.
// On MacOs, Docker runs on a VM, so the user mapping between the host and the container is
// performed by the engine.
// On Linux, we need to make sure all the mounted volumes are readable from others because
// the docker container runs with a different user than the file owner.
if (SystemUtils.IS_OS_MAC) {
return appDirectory;
}
final File appTmp = generateTempFile("app");
FileUtils.copyDirectory(appDirectory, appTmp);
makeDirOrFileReadable(appTmp);
return appTmp;
}

private static File createReadableTempFile(String prefix, String instanceContents)
throws IOException {
File tempFile = generateTempFile(prefix);
Expand All @@ -416,8 +439,12 @@ private static void makeDirOrFileReadable(File file) throws IOException {
for (File child : file.listFiles()) {
makeDirOrFileReadable(child);
}
Files.setPosixFilePermissions(
file.toPath(), PosixFilePermissions.fromString("rwxr-xr-x"));
} else {
Files.setPosixFilePermissions(
file.toPath(), PosixFilePermissions.fromString("rw-r--r--"));
}
Files.setPosixFilePermissions(file.toPath(), PosixFilePermissions.fromString("rw-r--r--"));
}

@SneakyThrows
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@
import ai.langstream.cli.NamedProfile;
import ai.langstream.cli.commands.applications.CommandTestBase;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.PosixFilePermission;
Expand All @@ -31,15 +29,19 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import org.apache.commons.lang3.SystemUtils;
import org.junit.jupiter.api.Test;

class LocalRunApplicationCmdTest extends CommandTestBase {

@Test
void testArgs() throws Exception {
final Path tempDir = Files.createTempDirectory(this.tempDir, "langstream");
final Path appConfigFile = Files.createTempFile(tempDir, "configuration", ".yaml");
Files.writeString(appConfigFile, "configuration: {}");

final Path secrets = Files.createTempFile("langstream", ".yaml");
Files.write(secrets, "secrets: []".getBytes(StandardCharsets.UTF_8));
Files.writeString(secrets, "secrets: []");

final String appDir = tempDir.toFile().getAbsolutePath();
CommandResult result =
Expand Down Expand Up @@ -74,32 +76,62 @@ void testArgs() throws Exception {

final List<String> volumes = extractVolumes(lastLine);
assertEquals(3, volumes.size());
volumes.forEach(
volume -> {
final String hostPath = volume.split(":")[0];
final File file = new File(hostPath);
assertTrue(file.exists());
final Path langstreamTmp =
Path.of(System.getProperty("user.home"), ".langstream", "tmp");
for (String volume : volumes) {

final String hostPath = volume.split(":")[0];
final File file = new File(hostPath);
assertTrue(file.exists());
final Path langstreamTmp =
Path.of(System.getProperty("user.home"), ".langstream", "tmp");

final Set<PosixFilePermission> posixFilePermissions =
Files.getPosixFilePermissions(file.toPath());
if (file.isDirectory()) {
if (SystemUtils.IS_OS_MAC) {
assertNotEquals(langstreamTmp, file.toPath().getParent());
} else {
assertEquals(langstreamTmp, file.toPath().getParent());
final Set<PosixFilePermission> posixFilePermissions;
try {
posixFilePermissions = Files.getPosixFilePermissions(file.toPath());
assertTrue(posixFilePermissions.contains(PosixFilePermission.OTHERS_READ));
assertTrue(posixFilePermissions.contains(PosixFilePermission.OWNER_READ));
assertTrue(posixFilePermissions.contains(PosixFilePermission.GROUP_READ));
} catch (IOException e) {
throw new RuntimeException(e);
}
});
assertEquals(
Set.of(
PosixFilePermission.OWNER_READ,
PosixFilePermission.OWNER_WRITE,
PosixFilePermission.GROUP_READ,
PosixFilePermission.OTHERS_READ,
PosixFilePermission.OWNER_EXECUTE,
PosixFilePermission.GROUP_EXECUTE,
PosixFilePermission.OTHERS_EXECUTE),
posixFilePermissions);
}
final String[] children = file.list();
assertEquals(1, children.length);
if (!SystemUtils.IS_OS_MAC) {
assertFileReadable(
Files.getPosixFilePermissions(
Path.of(file.getAbsolutePath(), children[0])));
}

} else {
assertEquals(langstreamTmp, file.toPath().getParent());
assertFileReadable(posixFilePermissions);
}
}
final NamedProfile namedProfile = getConfig().getProfiles().get("local-docker-run");
assertNotNull(namedProfile);
assertEquals("default", namedProfile.getTenant());
assertEquals("http://localhost:8090", namedProfile.getWebServiceUrl());
assertEquals("ws://localhost:8091", namedProfile.getApiGatewayUrl());
}

private void assertFileReadable(Set<PosixFilePermission> posixFilePermissions) {
assertEquals(
Set.of(
PosixFilePermission.OWNER_READ,
PosixFilePermission.OWNER_WRITE,
PosixFilePermission.GROUP_READ,
PosixFilePermission.OTHERS_READ),
posixFilePermissions);
}

private static List<String> extractVolumes(String input) {
List<String> volumes = new ArrayList<>();
Pattern pattern = Pattern.compile("-v\\s+([^\\s]+)");
Expand Down

0 comments on commit 08b9c1c

Please sign in to comment.