Skip to content

Commit f73705b

Browse files
committed
Fully tested version of dev services for kibana and opensearch dashboards
1 parent 2b71647 commit f73705b

File tree

5 files changed

+131
-34
lines changed

5 files changed

+131
-34
lines changed

build-parent/pom.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,13 @@
7676
<!-- Defaults for integration tests -->
7777
<elasticsearch-server.version>9.1.5</elasticsearch-server.version>
7878
<elasticsearch.image>docker.io/elastic/elasticsearch:${elasticsearch-server.version}</elasticsearch.image>
79-
<kibana.server.version>docker.io/elastic/kibana:${elasticsearch-server.version}</kibana.server.version>
79+
<kibana.image>docker.io/elastic/kibana:${elasticsearch-server.version}</kibana.image>
8080
<logstash.image>docker.io/elastic/logstash:${elasticsearch-server.version}</logstash.image>
8181
<kibana.image>docker.io/elastic/kibana:${elasticsearch-server.version}</kibana.image>
8282
<elasticsearch.protocol>http</elasticsearch.protocol>
8383
<opensearch-server.version>3.1.0</opensearch-server.version>
8484
<opensearch.image>docker.io/opensearchproject/opensearch:${opensearch-server.version}</opensearch.image>
85+
<opensearch-dashboards.image>docker.io/opensearchproject/opensearch-dashboards:${opensearch-server.version}</opensearch-dashboards.image>
8586
<opensearch.protocol>http</opensearch.protocol>
8687
<junit-pioneer.version>2.2.0</junit-pioneer.version>
8788

extensions/elasticsearch-rest-client-common/deployment/src/main/java/io/quarkus/elasticsearch/restclient/common/deployment/DevServicesElasticsearchProcessor.java

Lines changed: 86 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
import static io.quarkus.devservices.common.ContainerLocator.locateContainerWithLabels;
44

5+
import java.io.IOException;
6+
import java.io.InputStream;
7+
import java.io.UncheckedIOException;
58
import java.time.Duration;
69
import java.util.Collections;
710
import java.util.HashMap;
@@ -10,6 +13,7 @@
1013
import java.util.Locale;
1114
import java.util.Map;
1215
import java.util.Optional;
16+
import java.util.Properties;
1317
import java.util.Set;
1418
import java.util.function.Supplier;
1519

@@ -59,19 +63,21 @@ public class DevServicesElasticsearchProcessor {
5963
static final String DEV_SERVICE_LABEL = "quarkus-dev-service-elasticsearch";
6064
static final String NEW_DEV_SERVICE_LABEL = "io.quarkus.devservice.elasticsearch";
6165
static final int ELASTICSEARCH_PORT = 9200;
62-
static final int KIBANA_PORT = 5601;
66+
static final int DASHBOARD_PORT = 5601;
6367

6468
private static final ContainerLocator elasticsearchContainerLocator = locateContainerWithLabels(ELASTICSEARCH_PORT,
6569
DEV_SERVICE_LABEL, NEW_DEV_SERVICE_LABEL);
66-
private static final ContainerLocator dashboardContainerLocator = locateContainerWithLabels(KIBANA_PORT,
70+
private static final ContainerLocator dashboardContainerLocator = locateContainerWithLabels(DASHBOARD_PORT,
6771
DEV_SERVICE_LABEL, NEW_DEV_SERVICE_LABEL);
6872

6973
private static final Distribution DEFAULT_DISTRIBUTION = Distribution.ELASTIC;
7074
private static final String DEV_SERVICE_ELASTICSEARCH = "elasticsearch";
71-
private static final String DEV_SERVICE_KIBANA = "kibana";
7275
private static final String DEV_SERVICE_OPENSEARCH = "opensearch";
76+
private static final String DEV_SERVICE_DASHBOARDS = "opensearch-dashboards";
77+
private static final String DEV_SERVICE_KIBANA = "kibana";
7378

7479
static volatile RunningDevService devService;
80+
static volatile RunningDevService devDashboardService;
7581
static volatile ElasticsearchCommonBuildTimeConfig cfg;
7682
static volatile boolean first = true;
7783

@@ -113,11 +119,11 @@ public DevServicesResultBuildItem startElasticsearchDevService(
113119
devServicesSharedNetworkBuildItem);
114120
devService = startElasticsearchDevServices(dockerStatusBuildItem, composeProjectBuildItem,
115121
configuration.devservices(), buildItemsConfig, launchMode, useSharedNetwork, devServicesConfig.timeout());
116-
//BS
117122

118-
startDashboardDevServices(dockerStatusBuildItem, composeProjectBuildItem, configuration.devservices(),
123+
devDashboardService = startDashboardDevServices(dockerStatusBuildItem, composeProjectBuildItem,
124+
configuration.devservices(),
119125
buildItemsConfig, launchMode, useSharedNetwork, devServicesConfig.timeout());
120-
//End BS
126+
121127
if (devService == null) {
122128
compressor.closeAndDumpCaptured();
123129
} else {
@@ -139,6 +145,9 @@ public DevServicesResultBuildItem startElasticsearchDevService(
139145
if (devService != null) {
140146
shutdownElasticsearch();
141147
}
148+
if (devDashboardService != null) {
149+
shutdownDashboard();
150+
}
142151
first = true;
143152
devService = null;
144153
cfg = null;
@@ -174,6 +183,18 @@ private void shutdownElasticsearch() {
174183
}
175184
}
176185

186+
private void shutdownDashboard() {
187+
if (devService != null) {
188+
try {
189+
devDashboardService.close();
190+
} catch (Throwable e) {
191+
log.error("Failed to stop the Dashboard", e);
192+
} finally {
193+
devService = null;
194+
}
195+
}
196+
}
197+
177198
private RunningDevService startElasticsearchDevServices(
178199
DockerStatusBuildItem dockerStatusBuildItem,
179200
DevServicesComposeProjectBuildItem composeProjectBuildItem,
@@ -262,7 +283,7 @@ private RunningDevService startDashboardDevServices(
262283
return null;
263284
}
264285

265-
if (!config.kibana().enabled()) {
286+
if (!config.dashboard().enabled()) {
266287
// Kibana explicitly disabled
267288
log.debug("Not starting Kibana Dev Service, as it has been disabled in the config.");
268289
return null;
@@ -284,15 +305,15 @@ private RunningDevService startDashboardDevServices(
284305
}
285306

286307
Distribution resolvedDistribution = resolveDistribution(config, buildItemConfig);
287-
DockerImageName resolvedImageName = resolveKibanaImageName(config, resolvedDistribution);
308+
DockerImageName resolvedImageName = resolveDashboardImageName(config, resolvedDistribution);
288309

289310
final Optional<ContainerAddress> maybeContainerAddress = dashboardContainerLocator.locateContainer(
290311
config.serviceName(),
291312
config.shared(),
292313
launchMode.getLaunchMode())
293314
.or(() -> ComposeLocator.locateContainer(composeProjectBuildItem,
294315
List.of(resolvedImageName.getUnversionedPart(), "elasticsearch", "opensearch"),
295-
KIBANA_PORT,
316+
DASHBOARD_PORT,
296317
launchMode.getLaunchMode(), useSharedNetwork));
297318

298319
// Starting the server
@@ -302,25 +323,24 @@ private RunningDevService startDashboardDevServices(
302323
CreatedContainer createdContainer = resolvedDistribution.equals(Distribution.ELASTIC)
303324
? createKibanaContainer(config, resolvedImageName, defaultNetworkId, useSharedNetwork, launchMode,
304325
composeProjectBuildItem)
305-
: createKibanaContainer(config, resolvedImageName, defaultNetworkId, useSharedNetwork, launchMode,
326+
: createDashboardsContainer(config, resolvedImageName, defaultNetworkId, useSharedNetwork, launchMode,
306327
composeProjectBuildItem);
307328
GenericContainer<?> container = createdContainer.genericContainer();
308329

309330
if (config.serviceName() != null) {
310331
container.withLabel(DEV_SERVICE_LABEL, config.serviceName());
311332
container.withLabel(Labels.QUARKUS_DEV_SERVICE, config.serviceName());
312333
}
313-
if (config.port().isPresent()) {
314-
//TODO port mapping configuration
315-
container.setPortBindings(List.of(KIBANA_PORT + ":" + KIBANA_PORT));
334+
if (config.dashboard().port().isPresent()) {
335+
container.setPortBindings(List.of(config.dashboard().port().get() + ":" + DASHBOARD_PORT));
316336
}
317337
timeout.ifPresent(container::withStartupTimeout);
318-
container.withEnv(config.containerEnv());
338+
container.withEnv(config.dashboard().containerEnv());
319339
container.withReuse(config.reuse());
320340
container.start();
321341

322342
var httpHost = createdContainer.hostName + ":"
323-
+ (useSharedNetwork ? KIBANA_PORT : container.getMappedPort(KIBANA_PORT));
343+
+ (useSharedNetwork ? DASHBOARD_PORT : container.getMappedPort(DASHBOARD_PORT));
324344
return new RunningDevService(Feature.ELASTICSEARCH_REST_CLIENT_COMMON.getName(),
325345
container.getContainerId(),
326346
new ContainerShutdownCloseable(container, "Kibana"),
@@ -389,9 +409,7 @@ private CreatedContainer createKibanaContainer(ElasticsearchDevServicesBuildTime
389409

390410
String kibanaHostName = ConfigureUtil.configureNetwork(container, defaultNetworkId, useSharedNetwork,
391411
DEV_SERVICE_KIBANA);
392-
String elasticsearchHostName = ConfigureUtil.configureNetwork(container, defaultNetworkId, useSharedNetwork,
393-
DEV_SERVICE_ELASTICSEARCH);
394-
container.setExposedPorts(List.of(KIBANA_PORT));
412+
container.setExposedPorts(List.of(DASHBOARD_PORT));
395413

396414
final Optional<ContainerAddress> maybeContainerAddress = elasticsearchContainerLocator.locateContainer(
397415
config.serviceName(),
@@ -407,9 +425,37 @@ private CreatedContainer createKibanaContainer(ElasticsearchDevServicesBuildTime
407425
.replace("localhost", "host.docker.internal"))
408426
.ifPresent(addressStr -> container.addEnv("ELASTICSEARCH_HOSTS",
409427
addressStr));
410-
container.addEnv("ELASTICSEARCH_USERNAME", "kibana_system");
411-
container.addEnv("ELASTICSEARCH_PASSWORD", "test");
428+
container.addEnv("NODE_OPTIONS", config.dashboard().nodeOpts());
429+
return new CreatedContainer(container, kibanaHostName);
430+
}
431+
432+
private CreatedContainer createDashboardsContainer(ElasticsearchDevServicesBuildTimeConfig config,
433+
DockerImageName resolvedImageName, String defaultNetworkId, boolean useSharedNetwork,
434+
LaunchModeBuildItem launchMode, DevServicesComposeProjectBuildItem composeProjectBuildItem) {
435+
//Create Generic Kibana container
436+
GenericContainer<?> container = new GenericContainer<>(
437+
resolvedImageName.asCompatibleSubstituteFor("opensearchproject/opensearch-dashboards"));
438+
439+
String kibanaHostName = ConfigureUtil.configureNetwork(container, defaultNetworkId, useSharedNetwork,
440+
DEV_SERVICE_DASHBOARDS);
441+
container.setExposedPorts(List.of(DASHBOARD_PORT));
442+
443+
final Optional<ContainerAddress> maybeContainerAddress = elasticsearchContainerLocator.locateContainer(
444+
config.serviceName(),
445+
config.shared(),
446+
launchMode.getLaunchMode())
447+
.or(() -> ComposeLocator.locateContainer(composeProjectBuildItem,
448+
List.of(resolvedImageName.getUnversionedPart(), "elasticsearch", "opensearch"),
449+
ELASTICSEARCH_PORT,
450+
launchMode.getLaunchMode(), useSharedNetwork));
412451

452+
maybeContainerAddress
453+
.map(containerAddress -> ("http://" + containerAddress.getHost() + ":" + containerAddress.getPort())
454+
.replace("localhost", "host.docker.internal"))
455+
.ifPresent(addressStr -> container.addEnv("OPENSEARCH_HOSTS",
456+
addressStr));
457+
container.addEnv("NODE_OPTIONS", config.dashboard().nodeOpts());
458+
container.addEnv("DISABLE_SECURITY_DASHBOARDS_PLUGIN", "true");
413459
return new CreatedContainer(container, kibanaHostName);
414460
}
415461

@@ -424,11 +470,27 @@ private DockerImageName resolveImageName(ElasticsearchDevServicesBuildTimeConfig
424470
: DEV_SERVICE_OPENSEARCH)));
425471
}
426472

427-
private DockerImageName resolveKibanaImageName(ElasticsearchDevServicesBuildTimeConfig config,
473+
private DockerImageName resolveDashboardImageName(ElasticsearchDevServicesBuildTimeConfig config,
428474
Distribution resolvedDistribution) {
429-
return DockerImageName.parse("docker.io/elastic/kibana:9.1.5");
430-
//return DockerImageName.parse(
431-
// config.imageKibanaName().orElseThrow(() -> new RuntimeException("Image name for Kibana is not configured")));
475+
return DockerImageName.parse(config.dashboard().imageName().orElseGet(() -> loadProperties(
476+
Distribution.ELASTIC.equals(resolvedDistribution)
477+
? DEV_SERVICE_ELASTICSEARCH
478+
: DEV_SERVICE_OPENSEARCH)
479+
.getProperty("default.dashboard.image")));
480+
}
481+
482+
private static Properties loadProperties(String devserviceName) {
483+
var fileName = devserviceName + "-devservice.properties";
484+
try (InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName)) {
485+
if (in == null) {
486+
throw new IllegalArgumentException(fileName + " not found on classpath");
487+
}
488+
var properties = new Properties();
489+
properties.load(in);
490+
return properties;
491+
} catch (IOException e) {
492+
throw new UncheckedIOException(e);
493+
}
432494
}
433495

434496
private Distribution resolveDistribution(ElasticsearchDevServicesBuildTimeConfig config,

extensions/elasticsearch-rest-client-common/deployment/src/main/java/io/quarkus/elasticsearch/restclient/common/deployment/ElasticsearchCommonBuildTimeConfig.java

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,6 @@ interface ElasticsearchDevServicesBuildTimeConfig {
3535
*/
3636
Optional<Boolean> enabled();
3737

38-
/**
39-
* Kibana configuration for Dev Services.
40-
*/
41-
@ConfigDocSection
42-
KibanaDevServicesConfig kibana();
43-
4438
/**
4539
* Optional fixed port the dev service will listen to.
4640
* <p>
@@ -151,22 +145,61 @@ interface ElasticsearchDevServicesBuildTimeConfig {
151145
@WithDefault("true")
152146
boolean reuse();
153147

148+
/**
149+
* Kibana configuration for Dev Services.
150+
*/
151+
@ConfigDocSection
152+
DashboardDevServicesConfig dashboard();
153+
154154
enum Distribution {
155155
ELASTIC,
156156
OPENSEARCH
157157
}
158158

159159
@ConfigGroup
160-
interface KibanaDevServicesConfig {
160+
interface DashboardDevServicesConfig {
161161
/**
162-
* Whether the Kibana Dev Service should start with the application in dev mode or tests.
162+
* Whether the Dashboard Dev Service should start with the application in dev mode or tests.
163163
* <p>
164164
* Kibana Dev Services are disabled by default when Elasticsearch Dev Services are enabled.
165165
*
166166
* @asciidoclet
167167
*/
168168
@WithDefault("false")
169169
boolean enabled();
170+
171+
/**
172+
* Optional fixed port the dev service will listen to.
173+
* <p>
174+
* If not defined, the port will be chosen randomly.
175+
*/
176+
Optional<Integer> port();
177+
178+
/**
179+
* The Elasticsearch container image to use.
180+
*
181+
* Defaults depend on the configured `distribution`:
182+
*
183+
* * For the `elastic` distribution: {kibana-image}
184+
* * For the `opensearch` distribution: {dashboardimage}
185+
*
186+
* @asciidoclet
187+
*/
188+
Optional<String> imageName();
189+
190+
/**
191+
* Environment variables that are passed to the container.
192+
*/
193+
@ConfigDocMapKey("environment-variable-name")
194+
Map<String, String> containerEnv();
195+
196+
/**
197+
* The value for the NODE_OPTIONS env variable.
198+
*
199+
* @asciidoclet
200+
*/
201+
@WithDefault(" ")
202+
String nodeOpts();
170203
}
171204
}
172205
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
default.image=${elasticsearch.image}
2-
default.kibana.image=${kibana.image}
2+
default.dashboard.image=${kibana.image}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
default.image=${opensearch.image}
2+
default.dashboard.image=${opensearch-dashboards.image}

0 commit comments

Comments
 (0)