Skip to content

Commit ac90603

Browse files
author
David Roberts
committed
Spawn controller processes from a different directory on macOS (#47013)
This is the Java side of elastic/ml-cpp#593 with a fallback so that ml-cpp bundles with either the new or old directory structure work for the time being. A few days after merging the C++ changes a followup to this change will be made that removes the fallback.
1 parent 8a88648 commit ac90603

File tree

6 files changed

+90
-6
lines changed

6 files changed

+90
-6
lines changed

distribution/build.gradle

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,8 +277,9 @@ configure(subprojects.findAll { ['archives', 'packages'].contains(it.name) }) {
277277
modulesFiles = { oss, platform ->
278278
copySpec {
279279
eachFile {
280-
if (it.relativePath.segments[-2] == 'bin') {
280+
if (it.relativePath.segments[-2] == 'bin' || (platform == 'darwin' && it.relativePath.segments[-2] == 'MacOS')) {
281281
// bin files, wherever they are within modules (eg platform specific) should be executable
282+
// and MacOS is an alternative to bin on macOS
282283
it.mode = 0755
283284
} else {
284285
it.mode = 0644

distribution/tools/plugin-cli/src/main/java/org/elasticsearch/plugins/InstallPluginCommand.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import joptsimple.OptionSpec;
2424
import org.apache.lucene.search.spell.LevenshteinDistance;
2525
import org.apache.lucene.util.CollectionUtil;
26+
import org.apache.lucene.util.Constants;
2627
import org.bouncycastle.bcpg.ArmoredInputStream;
2728
import org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider;
2829
import org.bouncycastle.openpgp.PGPException;
@@ -842,7 +843,10 @@ private void movePlugin(Path tmpRoot, Path destination) throws IOException {
842843
Files.walkFileTree(destination, new SimpleFileVisitor<Path>() {
843844
@Override
844845
public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException {
845-
if ("bin".equals(file.getParent().getFileName().toString())) {
846+
final String parentDirName = file.getParent().getFileName().toString();
847+
if ("bin".equals(parentDirName)
848+
// "MacOS" is an alternative to "bin" on macOS
849+
|| (Constants.MAC_OS_X && "MacOS".equals(parentDirName))) {
846850
setFileAttributes(file, BIN_FILES_PERMS);
847851
} else {
848852
setFileAttributes(file, PLUGIN_FILES_PERMS);

qa/no-bootstrap-tests/src/test/java/org/elasticsearch/bootstrap/SpawnerNoBootstrapTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ public class SpawnerNoBootstrapTests extends LuceneTestCase {
6868
/**
6969
* Simplest case: a module with no controller daemon.
7070
*/
71-
public void testNoControllerSpawn() throws IOException, InterruptedException {
71+
public void testNoControllerSpawn() throws IOException {
7272
Path esHome = createTempDir().resolve("esHome");
7373
Settings.Builder settingsBuilder = Settings.builder();
7474
settingsBuilder.put(Environment.PATH_HOME_SETTING.getKey(), esHome.toString());

server/src/main/java/org/elasticsearch/bootstrap/Spawner.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,13 @@ void spawnNativeControllers(final Environment environment) throws IOException {
7272
List<Path> paths = PluginsService.findPluginDirs(environment.modulesFile());
7373
for (final Path modules : paths) {
7474
final PluginInfo info = PluginInfo.readFromProperties(modules);
75-
final Path spawnPath = Platforms.nativeControllerPath(modules);
75+
Path spawnPath = Platforms.nativeControllerPath(modules);
7676
if (!Files.isRegularFile(spawnPath)) {
77-
continue;
77+
// TODO: remove before release and just continue if the controller is not in the standard place
78+
spawnPath = Platforms.fallbackNativeControllerPath(modules);
79+
if (spawnPath == null || Files.isRegularFile(spawnPath) == false) {
80+
continue;
81+
}
7882
}
7983
if (!info.hasNativeController()) {
8084
final String message = String.format(

server/src/main/java/org/elasticsearch/plugins/Platforms.java

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,15 @@ private Platforms() {}
3838
* The path to the native controller for a plugin with native components.
3939
*/
4040
public static Path nativeControllerPath(Path plugin) {
41+
if (Constants.MAC_OS_X) {
42+
return plugin
43+
.resolve("platform")
44+
.resolve(PLATFORM_NAME)
45+
.resolve(PROGRAM_NAME + ".app")
46+
.resolve("Contents")
47+
.resolve("MacOS")
48+
.resolve(PROGRAM_NAME);
49+
}
4150
return plugin
4251
.resolve("platform")
4352
.resolve(PLATFORM_NAME)
@@ -46,7 +55,26 @@ public static Path nativeControllerPath(Path plugin) {
4655
}
4756

4857
/**
49-
* Return the platform name based on the OS name and
58+
* The fallback path to the native controller for a plugin with native
59+
* components to be used if no program is found using the standard path.
60+
* This is a temporary measure to allow developers not working on this
61+
* functionality to continue to work with C++ bundles from before or
62+
* after the change. This code should never be in a supported release.
63+
* TODO: remove this method before release
64+
*/
65+
public static Path fallbackNativeControllerPath(Path plugin) {
66+
if (Constants.MAC_OS_X) {
67+
return plugin
68+
.resolve("platform")
69+
.resolve(PLATFORM_NAME)
70+
.resolve("bin")
71+
.resolve(PROGRAM_NAME);
72+
}
73+
return null;
74+
}
75+
76+
/**
77+
* Return the platform name based on the OS name and architecture, for example:
5078
* - darwin-x86_64
5179
* - linux-x86-64
5280
* - windows-x86_64
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.elasticsearch.plugins;
20+
21+
import org.apache.lucene.util.Constants;
22+
import org.elasticsearch.test.ESTestCase;
23+
24+
import java.nio.file.Path;
25+
26+
public class PlatformsTests extends ESTestCase {
27+
28+
public void testNativeControllerPath() {
29+
30+
final Path nativeControllerPath = Platforms.nativeControllerPath(createTempDir());
31+
32+
// The directory structure on macOS must match Apple's .app
33+
// structure or Gatekeeper may refuse to run the program
34+
if (Constants.MAC_OS_X) {
35+
String programName = nativeControllerPath.getFileName().toString();
36+
Path binDirectory = nativeControllerPath.getParent();
37+
assertEquals("MacOS", binDirectory.getFileName().toString());
38+
Path contentsDirectory = binDirectory.getParent();
39+
assertEquals("Contents", contentsDirectory.getFileName().toString());
40+
Path appDirectory = contentsDirectory.getParent();
41+
assertEquals(programName + ".app", appDirectory.getFileName().toString());
42+
} else {
43+
Path binDirectory = nativeControllerPath.getParent();
44+
assertEquals("bin", binDirectory.getFileName().toString());
45+
}
46+
}
47+
}

0 commit comments

Comments
 (0)