Skip to content
This repository was archived by the owner on May 14, 2025. It is now read-only.

Commit 533b753

Browse files
committed
Add check for empty deployment properties
- Trying to unregister app with undeployed stream results empty deploy props and json parsing fails. - Relates to #2013
1 parent eccc8e2 commit 533b753

File tree

2 files changed

+72
-0
lines changed

2 files changed

+72
-0
lines changed

spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/controller/SkipperAppRegistryController.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,9 @@ private String findStreamContainingAppOf(ApplicationType appType, String appName
289289
}
290290
Map<String, Map<String, String>> streamDeploymentPropertiesMap;
291291
String streamDeploymentPropertiesString = streamDeployment.getDeploymentProperties();
292+
if (!StringUtils.hasText(streamDeploymentPropertiesString)) {
293+
continue;
294+
}
292295
ObjectMapper objectMapper = new ObjectMapper();
293296
try {
294297
streamDeploymentPropertiesMap = objectMapper.readValue(streamDeploymentPropertiesString,

spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/controller/SkipperAppRegistryControllerTests.java

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,75 @@ public void testUnregisterApplicationUsedInStream() throws Exception {
353353
.andExpect(status().isOk());
354354
}
355355

356+
@Test
357+
@Transactional
358+
public void testUnregisterApplicationUsedInStreamNotDeployed() throws Exception {
359+
// Note, by default there are apps registered from classpath:META-INF/test-apps.properties.
360+
361+
// Register time source v1.2
362+
mockMvc.perform(post("/apps/source/time")
363+
.param("uri", "maven://org.springframework.cloud.stream.app:time-source-rabbit:1.2.0.RELEASE").accept(MediaType.APPLICATION_JSON))
364+
.andExpect(status().isCreated());
365+
366+
// Make sure the 1.2 time source is registered.
367+
mockMvc.perform(get("/apps/source/time/1.2.0.RELEASE").accept(MediaType.APPLICATION_JSON))
368+
.andExpect(status().isOk()).andExpect(jsonPath("name", is("time")))
369+
.andExpect(jsonPath("type", is("source")));
370+
371+
// Register log sink v1.2
372+
mockMvc.perform(post("/apps/sink/log")
373+
.param("uri", "maven://org.springframework.cloud.stream.app:log-sink-rabbit:1.2.0.RELEASE").accept(MediaType.APPLICATION_JSON))
374+
.andExpect(status().isCreated());
375+
376+
// Make sure the 1.2 log sink is registered.
377+
mockMvc.perform(get("/apps/sink/log/1.2.0.RELEASE").accept(MediaType.APPLICATION_JSON))
378+
.andExpect(status().isOk()).andExpect(jsonPath("name", is("log")))
379+
.andExpect(jsonPath("type", is("sink")));
380+
381+
// Register a transformer
382+
mockMvc.perform(post("/apps/processor/transformer")
383+
.param("uri", "maven://org.springframework.cloud.stream.app:transformer-processor-rabbit:1.2.0.RELEASE").accept(MediaType.APPLICATION_JSON))
384+
.andExpect(status().isCreated());
385+
386+
// Register a task
387+
mockMvc.perform(post("/apps/task/timestamp")
388+
.param("uri", "maven://org.springframework.cloud.task.app:timestamp-task:1.3.0.RELEASE")
389+
.accept(MediaType.APPLICATION_JSON))
390+
.andExpect(status().isCreated());
391+
392+
// Create stream definition
393+
StreamDefinition streamDefinition = new StreamDefinition("ticktock", "time --fixed-delay=100 | log --level=DEBUG");
394+
streamDefinitionRepository.save(streamDefinition);
395+
396+
// configure mock SkipperClient
397+
when(skipperClient.manifest(eq("ticktock"))).thenThrow(new ReleaseNotFoundException(""));
398+
when(skipperClient.status(eq("ticktock"))).thenThrow(new ReleaseNotFoundException(""));
399+
400+
// This log sink v1.2 is part of a deployed stream, so it can be unregistered
401+
mockMvc.perform(delete("/apps/sink/log/1.2.0.RELEASE").accept(MediaType.APPLICATION_JSON))
402+
.andExpect(status().isOk());
403+
404+
// This log sink v1.0.BS is part of a deployed stream, so it can be unregistered
405+
mockMvc.perform(delete("/apps/sink/log/1.0.0.BUILD-SNAPSHOT").accept(MediaType.APPLICATION_JSON))
406+
.andExpect(status().isOk());
407+
408+
// This time source v1.0 BS is not part of a deployed stream, so it can be unregistered
409+
mockMvc.perform(delete("/apps/source/time/1.0.0.BUILD-SNAPSHOT").accept(MediaType.APPLICATION_JSON))
410+
.andExpect(status().isOk());
411+
412+
// This time source is part of a deployed stream, so it can not be unregistered.
413+
mockMvc.perform(delete("/apps/source/time/1.2.0.RELEASE").accept(MediaType.APPLICATION_JSON))
414+
.andExpect(status().isOk());
415+
416+
417+
// This is unrelated to a stream, so should work
418+
mockMvc.perform(delete("/apps/task/timestamp/1.3.0.RELEASE").accept(MediaType.APPLICATION_JSON))
419+
.andExpect(status().isOk());
420+
421+
// Transformer processor is not deployed, so should work
422+
mockMvc.perform(delete("/apps/processor/transformer").accept(MediaType.APPLICATION_JSON))
423+
.andExpect(status().isOk());
424+
}
356425

357426
@Test
358427
public void testUnregisterApplicationNotFound() throws Exception {

0 commit comments

Comments
 (0)