88import static io .quarkus .devservices .common .ContainerLocator .locateContainerWithLabels ;
99
1010import java .util .ArrayList ;
11+ import java .util .Collections ;
1112import java .util .HashMap ;
1213import java .util .List ;
1314import java .util .Map ;
@@ -37,10 +38,15 @@ public class DevServicesDaprProcessor {
3738
3839 private static final Logger LOGGER = LoggerFactory .getLogger (DevServicesDaprProcessor .class );
3940 static final String DEV_SERVICE_LABEL = "quarkus-dev-service-dapr" ;
41+ static final String DASHBOARD_WORKFLOW_LABEL = "quarkus-dev-service-dapr-dashboard" ;
42+
4043 private static final int DAPR_INTERNAL_HTTP_PORT = 3500 ;
4144 private static final int DAPR_INTERNAL_GRPC_PORT = 50001 ;
4245 private static final ContainerLocator DAPR_CONTAINER_LOCATOR = locateContainerWithLabels (DAPR_INTERNAL_HTTP_PORT ,
4346 DEV_SERVICE_LABEL );
47+ private static final ContainerLocator DASHBOARD_CONTAINER_LOCATOR = locateContainerWithLabels (
48+ DashboardContainerStartable .INTERNAL_DAPR_DASHBOARD_WORKFLOW_PORT ,
49+ DASHBOARD_WORKFLOW_LABEL );
4450
4551 private static final String QUARKUS_DAPR_SERVICE_NAME_PREFIX = "quarkus-dev-service-" ;
4652 private static final String DASHBOARD_WORKFLOW = QUARKUS_DAPR_SERVICE_NAME_PREFIX + "dashboard-workflow" ;
@@ -79,17 +85,35 @@ List<DevServicesResultBuildItem> devServices(
7985 DevServicesResultBuildItem discoveredDapr = discoverDaprContainer (config , launchMode );
8086 if (discoveredDapr != null ) {
8187 containers .add (discoveredDapr );
88+ // Even when reusing a shared Dapr container, we still need to start the
89+ // dashboard and state-store containers for this application (or discover them).
90+ if (config .dashboard ().enabled ().get ()) {
91+ DevServicesResultBuildItem discoveredDashboard = discoverDashboardContainer (config , launchMode );
92+ if (discoveredDashboard != null ) {
93+ containers .add (discoveredDashboard );
94+ } else {
95+ DevServicesResultBuildItem pgsql = configurePgsqlContainer (network , launchMode );
96+ DevServicesResultBuildItem dashboard = configureDashboardWorkflowContainer (config , network , launchMode );
97+ containers .add (pgsql );
98+ containers .add (dashboard );
99+ }
100+ }
82101 return containers ;
83102 }
84103
85104 DevServicesResultBuildItem dapr = configureDaprContainer (config , launchMode , network );
86105 containers .add (dapr );
87106
88107 if (config .dashboard ().enabled ().get ()) {
89- DevServicesResultBuildItem pgsql = configurePgsqlContainer (network );
90- DevServicesResultBuildItem dashboard = configureDashboardWorkflowContainer (network );
91- containers .add (dashboard );
92- containers .add (pgsql );
108+ DevServicesResultBuildItem discoveredDashboard = discoverDashboardContainer (config , launchMode );
109+ if (discoveredDashboard != null ) {
110+ containers .add (discoveredDashboard );
111+ } else {
112+ DevServicesResultBuildItem pgsql = configurePgsqlContainer (network , launchMode );
113+ DevServicesResultBuildItem dashboard = configureDashboardWorkflowContainer (config , network , launchMode );
114+ containers .add (pgsql );
115+ containers .add (dashboard );
116+ }
93117 }
94118
95119 return containers ;
@@ -114,12 +138,21 @@ private static DevServicesResultBuildItem discoverDaprContainer(DaprDevServiceBu
114138 return null ;
115139 }
116140
117- configureDaprPorts (grpcAddress .getPort (), httpAddress .getPort ());
141+ int grpcPort = grpcAddress .getPort ();
142+ int httpPort = httpAddress .getPort ();
143+ configureDaprPorts (grpcPort , httpPort );
118144 LOGGER .info ("Re-using shared Dapr container {} listening on HTTP {} and gRPC {}" ,
119- containerId .get (), httpAddress .getPort (), grpcAddress .getPort ());
145+ containerId .get (), httpPort , grpcPort );
146+
147+ // Always supply a non-null config map so DevServicesConfigBuildStep#setup won't NPE
148+ Map <String , String > portConfig = new HashMap <>();
149+ portConfig .put (Properties .HTTP_PORT .getName (), Integer .toString (httpPort ));
150+ portConfig .put (Properties .GRPC_PORT .getName (), Integer .toString (grpcPort ));
151+
120152 return DevServicesResultBuildItem .discovered ()
121153 .name (FEATURE )
122154 .containerId (containerId .get ())
155+ .config (Collections .unmodifiableMap (portConfig ))
123156 .build ();
124157 }
125158
@@ -150,19 +183,54 @@ public Startable get() {
150183 .build ();
151184 }
152185
186+ private static DevServicesResultBuildItem discoverDashboardContainer (DaprDevServiceBuildTimeConfig config ,
187+ LaunchModeBuildItem launchModeBuildItem ) {
188+ Map <Integer , ContainerAddress > mappedPorts = new HashMap <>();
189+ Optional <String > containerId = DASHBOARD_CONTAINER_LOCATOR .locateContainer (
190+ config .dashboard ().serviceName (),
191+ config .shared ().get (),
192+ launchModeBuildItem .getLaunchMode (),
193+ mappedPorts ::put );
194+
195+ if (containerId .isEmpty ()) {
196+ return null ;
197+ }
198+
199+ ContainerAddress dashboardAddress = mappedPorts .get (DashboardContainerStartable .INTERNAL_DAPR_DASHBOARD_WORKFLOW_PORT );
200+ if (dashboardAddress == null ) {
201+ LOGGER .warn ("Found shared Dapr Dashboard container {} but missing mapped port. Creating a new one instead." ,
202+ containerId .get ());
203+ return null ;
204+ }
205+
206+ String dashboardUrl = "http://127.0.0.1:" + dashboardAddress .getPort ();
207+ LOGGER .info ("Re-using shared Dapr Dashboard container {} at {}" , containerId .get (), dashboardUrl );
208+
209+ Map <String , String > dashboardConfig = new HashMap <>();
210+ dashboardConfig .put (DAPR_DASHBOARD_WORKFLOW_URL , dashboardUrl );
211+
212+ return DevServicesResultBuildItem .discovered ()
213+ .name (FEATURE )
214+ .containerId (containerId .get ())
215+ .config (Collections .unmodifiableMap (dashboardConfig ))
216+ .build ();
217+ }
218+
153219 private static void configureDaprPorts (int grpcPort , int httpPort ) {
154220 System .setProperty (Properties .GRPC_PORT .getName (), Integer .toString (grpcPort ));
155221 System .setProperty (Properties .HTTP_PORT .getName (), Integer .toString (httpPort ));
156222 }
157223
158- private static DevServicesResultBuildItem configureDashboardWorkflowContainer (Network network ) {
224+ private static DevServicesResultBuildItem configureDashboardWorkflowContainer (DaprDevServiceBuildTimeConfig config ,
225+ Network network , LaunchModeBuildItem launchMode ) {
159226 DevServicesResultBuildItem dashboard = DevServicesResultBuildItem .owned ()
160227 .serviceName (DASHBOARD_WORKFLOW )
161228 .feature (FEATURE )
162229 .startable (new Supplier <Startable >() {
163230 @ Override
164231 public Startable get () {
165- return new DashboardContainerStartable (network );
232+ return new DashboardContainerStartable (network , launchMode .getLaunchMode (),
233+ config .dashboard ().serviceName ());
166234 }
167235 })
168236 .dependsOnConfig (POSTGRESQL_PORT_PROPERTY , (Startable startable , String value ) -> {
@@ -178,7 +246,8 @@ public Startable get() {
178246 return dashboard ;
179247 }
180248
181- private static DevServicesResultBuildItem configurePgsqlContainer (Network network ) {
249+ private static DevServicesResultBuildItem configurePgsqlContainer (Network network ,
250+ LaunchModeBuildItem launchMode ) {
182251 return DevServicesResultBuildItem .owned ()
183252 .serviceName (STATESTORE_PG )
184253 .feature (FEATURE )
@@ -189,7 +258,7 @@ private static DevServicesResultBuildItem configurePgsqlContainer(Network networ
189258 .startable (new Supplier <Startable >() {
190259 @ Override
191260 public Startable get () {
192- return new StateStoreContainerStartable (network );
261+ return new StateStoreContainerStartable (network , launchMode . getLaunchMode () );
193262 }
194263 })
195264 .build ();
0 commit comments