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

Commit 95114a3

Browse files
committed
Add tests for shell 'app register' commands
- Create AppRegistryCommandsTests that verify newly added bootVersion options See #5239
1 parent 8e3f127 commit 95114a3

File tree

4 files changed

+173
-25
lines changed

4 files changed

+173
-25
lines changed

spring-cloud-dataflow-shell-core/src/main/java/org/springframework/cloud/dataflow/shell/command/AppRegistryCommands.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -182,10 +182,10 @@ public String unregister(
182182

183183
List<AppRegistrationResource> appRegistrations = findAllAppsByNameAndType(name, type);
184184
Optional<AppRegistrationResource> defaultApp = appRegistrations.stream()
185-
.filter(a -> a.getDefaultVersion() == true).findFirst();
185+
.filter(AppRegistrationResource::getDefaultVersion).findFirst();
186186

187187
if (!CollectionUtils.isEmpty(appRegistrations) && !defaultApp.isPresent()) {
188-
String appVersions = appRegistrations.stream().map(app -> app.getVersion())
188+
String appVersions = appRegistrations.stream().map(AppRegistrationResource::getVersion)
189189
.collect(Collectors.joining(", ", "(", ")"));
190190
return String.format("Successfully unregistered application '%s' with type '%s'. " +
191191
"Please select new default version from: %s", name, type, appVersions);
@@ -240,7 +240,7 @@ public String defaultApplication(
240240
public String register(
241241
@ShellOption(value = { "", "--name" }, help = "the name for the registered application") String name,
242242
@ShellOption(help = "the type for the registered application", valueProvider = EnumValueProvider.class) ApplicationType type,
243-
@ShellOption(value = { "-bv", "--bootVersion" }, help = "the boot version to use for the registered application", defaultValue = ShellOption.NULL) AppBootSchemaVersion bootVersion,
243+
@ShellOption(value = { "-b", "--bootVersion" }, help = "the boot version to use for the registered application", defaultValue = ShellOption.NULL) AppBootSchemaVersion bootVersion,
244244
@ShellOption(help = "URI for the application artifact") String uri,
245245
@ShellOption(value = { "-m", "--metadata-uri", "--metadataUri"}, help = "Metadata URI for the application artifact", defaultValue = ShellOption.NULL) String metadataUri,
246246
@ShellOption(help = "force update if application is already registered (only if not in use)", defaultValue = "false") boolean force) {
@@ -275,7 +275,7 @@ public Object list(
275275
List<String> column = mappings.get(appRegistration.getType());
276276
String value = appRegistration.getName();
277277
if (application != null) {
278-
String version = StringUtils.isEmpty(appRegistration.getVersion()) ? "" : "-"+appRegistration.getVersion();
278+
String version = StringUtils.hasLength(appRegistration.getVersion()) ? ("-" + appRegistration.getVersion()) : "";
279279
value = value + version;
280280
if (appRegistration.getDefaultVersion()) {
281281
value = String.format("> %s <", value);
@@ -333,7 +333,7 @@ public String importFromResource(
333333
try {
334334
Resource resource = this.resourceLoader.getResource(uri);
335335
Properties applications = PropertiesLoaderUtils.loadProperties(resource);
336-
PagedModel<AppRegistrationResource> registered = null;
336+
PagedModel<AppRegistrationResource> registered;
337337
try {
338338
registered = appRegistryOperations().registerAll(applications, force);
339339
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright 2015-2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.cloud.dataflow.shell.converter;
18+
19+
import org.springframework.cloud.dataflow.core.AppBootSchemaVersion;
20+
import org.springframework.core.convert.converter.Converter;
21+
import org.springframework.lang.Nullable;
22+
import org.springframework.stereotype.Component;
23+
24+
/**
25+
* Converts strings to {@link AppBootSchemaVersion}
26+
*
27+
* @author Chris Bono
28+
* @author Corneil du Plessis
29+
*/
30+
@Component
31+
public class AppBootSchemaVersionConverter implements Converter<String, AppBootSchemaVersion> {
32+
33+
@Override
34+
public AppBootSchemaVersion convert(@Nullable String value) {
35+
return value != null ? AppBootSchemaVersion.fromBootVersion(value) : null;
36+
}
37+
}

spring-cloud-dataflow-shell-core/src/test/java/org/springframework/cloud/dataflow/shell/AbstractShellIntegrationTest.java

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,14 @@
3232
import org.springframework.cloud.skipper.client.SkipperClient;
3333
import org.springframework.context.ApplicationContext;
3434
import org.springframework.shell.Shell;
35+
import org.springframework.test.util.TestSocketUtils;
3536
import org.springframework.util.AlternativeJdkIdGenerator;
3637
import org.springframework.util.IdGenerator;
37-
import org.springframework.util.SocketUtils;
3838

3939
/**
4040
* Base class for shell integration tests. This class sets up and tears down the
4141
* infrastructure required for executing shell tests - in particular, the Data Flow
4242
* server.
43-
*
4443
* Extensions of this class may obtain instances of command templates. For example, call
4544
* {@link #stream} to obtain a {@link StreamCommandTemplate} in order to perform stream
4645
* operations.
@@ -68,7 +67,7 @@ public abstract class AbstractShellIntegrationTest {
6867
/**
6968
* TCP port for the server.
7069
*/
71-
private static final int serverPort = SocketUtils.findAvailableTcpPort();
70+
private static final int serverPort = TestSocketUtils.findAvailableTcpPort();
7271

7372
/**
7473
* Application context for server application.
@@ -107,39 +106,30 @@ public abstract class AbstractShellIntegrationTest {
107106
@BeforeClass
108107
public static void startUp() {
109108
if (applicationContext == null) {
110-
if (System.getProperty(SHUTDOWN_AFTER_RUN) != null) {
111-
shutdownAfterRun = Boolean.getBoolean(SHUTDOWN_AFTER_RUN);
112-
}
113-
114-
SpringApplication application = new SpringApplicationBuilder(TestConfig.class).build();
115-
116-
int randomPort = SocketUtils.findAvailableTcpPort();
109+
shutdownAfterRun = Boolean.parseBoolean(System.getProperty(SHUTDOWN_AFTER_RUN, "false"));
110+
int randomPort = TestSocketUtils.findAvailableTcpPort();
117111
String dataFlowUri = String.format("--dataflow.uri=http://localhost:%s", serverPort);
118112
String dataSourceUrl = String.format("jdbc:h2:tcp://localhost:%s/mem:dataflow", randomPort);
113+
SpringApplication application = new SpringApplicationBuilder(TestConfig.class).build();
119114
applicationContext = application.run(String.format("--server.port=%s", serverPort), dataFlowUri,
120115
"--spring.jmx.default-domain=" + System.currentTimeMillis(), "--spring.jmx.enabled=false",
121116
"--security.basic.enabled=false", "--spring.main.show_banner=false",
122117
"--spring.cloud.config.enabled=false",
123118
"--spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration,org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration,org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,org.springframework.cloud.deployer.spi.cloudfoundry.CloudFoundryDeployerAutoConfiguration,org.springframework.cloud.deployer.spi.kubernetes.KubernetesAutoConfiguration",
124119
"--spring.datasource.url=" + dataSourceUrl,
125120
"--spring.cloud.dataflow.features.schedules-enabled=true");
126-
127121
Shell shell = applicationContext.getBean(Shell.class);
128-
129122
skipperClient = applicationContext.getBean(SkipperClient.class);
130123
commandRunner = new ShellCommandRunner(shell);
131124
}
132125
}
133126

134127
@AfterClass
135128
public static void shutdown() {
136-
if (shutdownAfterRun) {
137-
if (applicationContext != null) {
138-
logger.info("Stopping Data Flow Server");
139-
SpringApplication.exit(applicationContext);
140-
141-
applicationContext = null;
142-
}
129+
if (shutdownAfterRun && applicationContext != null) {
130+
logger.info("Stopping Data Flow Server");
131+
SpringApplication.exit(applicationContext);
132+
applicationContext = null;
143133
}
144134
}
145135

@@ -197,6 +187,14 @@ protected JobCommandTemplate job() {
197187
return new JobCommandTemplate(commandRunner);
198188
}
199189

190+
/**
191+
* Gets the configured shell command runner.
192+
* @return the configured shell command runner
193+
*/
194+
protected ShellCommandRunner commandRunner() {
195+
return commandRunner;
196+
}
197+
200198
/**
201199
* Return a unique random name for stream/task testing.
202200
*
@@ -221,4 +219,3 @@ protected String generateUniqueStreamOrTaskName() {
221219
}
222220

223221
}
224-
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
/*
2+
* Copyright 2016-2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.cloud.dataflow.shell.command;
18+
19+
import java.util.ArrayList;
20+
import java.util.List;
21+
22+
import org.junit.After;
23+
import org.junit.Before;
24+
import org.junit.Test;
25+
import org.slf4j.Logger;
26+
import org.slf4j.LoggerFactory;
27+
28+
import org.springframework.cloud.dataflow.core.AppBootSchemaVersion;
29+
import org.springframework.cloud.dataflow.core.AppRegistration;
30+
import org.springframework.cloud.dataflow.core.ApplicationType;
31+
import org.springframework.cloud.dataflow.registry.service.AppRegistryService;
32+
import org.springframework.cloud.dataflow.shell.AbstractShellIntegrationTest;
33+
import org.springframework.cloud.dataflow.shell.ShellCommandRunner;
34+
35+
import static org.assertj.core.api.Assertions.assertThat;
36+
37+
/**
38+
* Tests for {@link AppRegistryCommands}.
39+
*
40+
* @author Chris Bono
41+
* @author Corneil du Plessis
42+
*/
43+
public class AppRegistryCommandsTests extends AbstractShellIntegrationTest {
44+
45+
private static final Logger logger = LoggerFactory.getLogger(AppRegistryCommandsTests.class);
46+
47+
private AppRegistryService registry;
48+
private ShellCommandRunner commandRunner;
49+
private List<AppRegistration> registeredApps;
50+
51+
@Before
52+
public void prepareForTest() {
53+
registeredApps = new ArrayList<>();
54+
registry = applicationContext.getBean(AppRegistryService.class);
55+
commandRunner = commandRunner().withValidateCommandSuccess();
56+
}
57+
58+
@After
59+
public void unregisterApps() {
60+
registeredApps.forEach(this::safeDeleteAppRegistration);
61+
}
62+
63+
private void safeDeleteAppRegistration(AppRegistration registration) {
64+
try {
65+
registry.delete(registration.getName(), registration.getType(), registration.getVersion());
66+
} catch (Exception ex) {
67+
logger.error("Failed to delete app registration: " + registration, ex);
68+
}
69+
}
70+
71+
@Test
72+
public void testRegisterTaskAppNoBootVersion() {
73+
AppRegistration registration = registerTimestampTask("timestamp", "3.2.0", "", false);
74+
assertThat(registration.getVersion()).isEqualTo("3.2.0");
75+
assertThat(registration.getBootVersion()).isEqualTo(AppBootSchemaVersion.defaultVersion());
76+
}
77+
78+
@Test
79+
public void testRegisterTaskAppBootVersion2() {
80+
AppRegistration registration = registerTimestampTask("timestamp2", "3.2.0", "--bootVersion 2", false);
81+
assertThat(registration.getVersion()).isEqualTo("3.2.0");
82+
assertThat(registration.getBootVersion()).isEqualTo(AppBootSchemaVersion.BOOT2);
83+
}
84+
85+
@Test
86+
public void testRegisterTaskAppBootVersion3() {
87+
AppRegistration registration = registerTimestampTask("timestamp3", "3.2.1", "-b 3", false);
88+
assertThat(registration.getVersion()).isEqualTo("3.2.1");
89+
assertThat(registration.getBootVersion()).isEqualTo(AppBootSchemaVersion.BOOT3);
90+
}
91+
92+
@Test
93+
public void testRegisterTaskUpdateBootVersion3() {
94+
AppRegistration registration = registerTimestampTask("timestamp2to3", "3.2.0", "--bootVersion 2", false);
95+
assertThat(registration.getVersion()).isEqualTo("3.2.0");
96+
assertThat(registration.getBootVersion()).isEqualTo(AppBootSchemaVersion.BOOT2);
97+
// The 'force=true' signals to udpate the existing 'timestamp2to3' app
98+
registration = registerTimestampTask("timestamp2to3", "3.2.1", "-b 3", true);
99+
assertThat(registration.getVersion()).isEqualTo("3.2.1");
100+
assertThat(registration.getBootVersion()).isEqualTo(AppBootSchemaVersion.BOOT3);
101+
}
102+
103+
private AppRegistration registerTimestampTask(String name, String timestampArtifactVersion, String bootVersionOption, boolean force) {
104+
String commandTemplate = "app register --type task --name %s %s %s --uri maven://org.springframework.cloud.task.app:task-timestamp:%s";
105+
String command = String.format(commandTemplate, name, bootVersionOption, (force ? "--force" : ""), timestampArtifactVersion);
106+
logger.info("COMMAND -> {}", command);
107+
Object result = this.commandRunner.executeCommand(command);
108+
logger.info("RESULT <- {}", result);
109+
assertThat(registry.appExist(name, ApplicationType.task, timestampArtifactVersion)).isTrue();
110+
AppRegistration registration = registry.find(name, ApplicationType.task, timestampArtifactVersion);
111+
registeredApps.add(registration);
112+
return registration;
113+
}
114+
}

0 commit comments

Comments
 (0)