1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package br.com.ingenieux.mojo.beanstalk;
18
19 import com.amazonaws.services.elasticbeanstalk.model.ApplicationVersionDescription;
20 import com.amazonaws.services.elasticbeanstalk.model.ConfigurationOptionSetting;
21 import com.amazonaws.services.elasticbeanstalk.model.DescribeApplicationVersionsRequest;
22 import com.amazonaws.services.elasticbeanstalk.model.DescribeApplicationVersionsResult;
23 import com.amazonaws.services.elasticbeanstalk.model.DescribeEnvironmentsRequest;
24 import com.amazonaws.services.elasticbeanstalk.model.EnvironmentDescription;
25
26 import org.apache.commons.lang.StringUtils;
27 import org.apache.commons.lang.builder.CompareToBuilder;
28 import org.apache.commons.lang.builder.ToStringBuilder;
29 import org.apache.commons.lang.builder.ToStringStyle;
30 import org.apache.maven.plugin.AbstractMojoExecutionException;
31 import org.apache.maven.plugin.MojoExecutionException;
32 import org.apache.maven.plugin.MojoFailureException;
33 import org.apache.maven.plugins.annotations.Parameter;
34 import org.apache.maven.project.MavenProject;
35
36 import java.util.ArrayList;
37 import java.util.Arrays;
38 import java.util.Collection;
39 import java.util.Collections;
40 import java.util.Comparator;
41 import java.util.LinkedHashMap;
42 import java.util.List;
43 import java.util.Map;
44 import java.util.Properties;
45 import java.util.Set;
46 import java.util.TreeMap;
47 import java.util.TreeSet;
48
49 import br.com.ingenieux.mojo.beanstalk.cmd.env.waitfor.WaitForEnvironmentCommand;
50 import br.com.ingenieux.mojo.beanstalk.cmd.env.waitfor.WaitForEnvironmentContext;
51 import br.com.ingenieux.mojo.beanstalk.cmd.env.waitfor.WaitForEnvironmentContextBuilder;
52
53 import static java.lang.String.format;
54 import static org.apache.commons.lang.StringUtils.isNotBlank;
55
56 public abstract class AbstractNeedsEnvironmentMojo extends AbstractBeanstalkMojo {
57
58 public static final String BEANSTALKX_PREFIX = "beanstalkx.";
59
60 public static class ConfigurableOptionSetting {
61 String alias;
62
63 String namespace;
64
65 String optionName;
66
67 public String getAlias() {
68 return alias;
69 }
70
71 public void setAlias(String alias) {
72 this.alias = alias;
73 }
74
75 public String getNamespace() {
76 return namespace;
77 }
78
79 public void setNamespace(String namespace) {
80 this.namespace = namespace;
81 }
82
83 public String getOptionName() {
84 return optionName;
85 }
86
87 public void setOptionName(String optionName) {
88 this.optionName = optionName;
89 }
90
91 @Override
92 public String toString() {
93 return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).append("namespace", namespace).append("optionName", optionName).toString();
94 }
95 }
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129 @Parameter List<ConfigurableOptionSetting> configurableOptionSettings = new ArrayList<ConfigurableOptionSetting>();
130
131 public static final Comparator<ConfigurationOptionSetting> COS_COMPARATOR =
132 new Comparator<ConfigurationOptionSetting>() {
133 @Override
134 public int compare(ConfigurationOptionSetting o1, ConfigurationOptionSetting o2) {
135 return new CompareToBuilder()
136 .append(o1.getNamespace(), o2.getNamespace())
137 .append(o1.getOptionName(), o2.getOptionName())
138 .append(o1.getValue(), o2.getValue())
139 .toComparison();
140 }
141 };
142
143 public static final Map<String, ConfigurationOptionSetting> COMMON_PARAMETERS =
144 new TreeMap<String, ConfigurationOptionSetting>() {
145 private static final long serialVersionUID = -6380522758234507742L;
146
147 {
148 put("beanstalk.scalingAvailabilityZones", new ConfigurationOptionSetting("aws:autoscaling:asg", "Availability Zones", ""));
149 put("beanstalk.scalingCooldown", new ConfigurationOptionSetting("aws:autoscaling:asg", "Cooldown", ""));
150 put("beanstalk.scalingCustomAvailabilityZones", new ConfigurationOptionSetting("aws:autoscaling:asg", "Custom Availability Zones", ""));
151 put("beanstalk.availabilityZones", new ConfigurationOptionSetting("aws:autoscaling:asg", "Custom Availability Zones", ""));
152 put("beanstalk.scalingMinSize", new ConfigurationOptionSetting("aws:autoscaling:asg", "MinSize", ""));
153 put("beanstalk.scalingMaxSize", new ConfigurationOptionSetting("aws:autoscaling:asg", "MaxSize", ""));
154
155 put("beanstalk.keyName", new ConfigurationOptionSetting("aws:autoscaling:launchconfiguration", "EC2KeyName", ""));
156
157 put("beanstalk.iamInstanceProfile", new ConfigurationOptionSetting("aws:autoscaling:launchconfiguration", "IamInstanceProfile", ""));
158
159 put("beanstalk.serviceRole", new ConfigurationOptionSetting("aws:elasticbeanstalk:environment", "ServiceRole", ""));
160
161 put("beanstalk.imageId", new ConfigurationOptionSetting("aws:autoscaling:launchconfiguration", "ImageId", ""));
162 put("beanstalk.instanceType", new ConfigurationOptionSetting("aws:autoscaling:launchconfiguration", "InstanceType", ""));
163 put("beanstalk.monitoringInterval", new ConfigurationOptionSetting("aws:autoscaling:launchconfiguration", "MonitoringInterval", ""));
164 put("beanstalk.securityGroups", new ConfigurationOptionSetting("aws:autoscaling:launchconfiguration", "SecurityGroups", ""));
165 put("beanstalk.sshSourceRestriction", new ConfigurationOptionSetting("aws:autoscaling:launchconfiguration", "SSHSourceRestriction", ""));
166 put("beanstalk.blockDeviceMappings", new ConfigurationOptionSetting("aws:autoscaling:launchconfiguration", "BlockDeviceMappings", ""));
167 put("beanstalk.rootVolumeType", new ConfigurationOptionSetting("aws:autoscaling:launchconfiguration", "RootVolumeType", ""));
168 put("beanstalk.rootVolumeSize", new ConfigurationOptionSetting("aws:autoscaling:launchconfiguration", "RootVolumeSize", ""));
169 put("beanstalk.rootVolumeIOPS", new ConfigurationOptionSetting("aws:autoscaling:launchconfiguration", "RootVolumeIOPS", ""));
170
171 put("beanstalk.triggerBreachDuration", new ConfigurationOptionSetting("aws:autoscaling:trigger", "BreachDuration", ""));
172 put("beanstalk.triggerLowerBreachScaleIncrement", new ConfigurationOptionSetting("aws:autoscaling:trigger", "LowerBreachScaleIncrement", ""));
173 put("beanstalk.triggerLowerThreshold", new ConfigurationOptionSetting("aws:autoscaling:trigger", "LowerThreshold", ""));
174 put("beanstalk.triggerMeasureName", new ConfigurationOptionSetting("aws:autoscaling:trigger", "MeasureName", ""));
175 put("beanstalk.triggerPeriod", new ConfigurationOptionSetting("aws:autoscaling:trigger", "Period", ""));
176 put("beanstalk.triggerStatistic", new ConfigurationOptionSetting("aws:autoscaling:trigger", "Statistic", ""));
177 put("beanstalk.triggerUnit", new ConfigurationOptionSetting("aws:autoscaling:trigger", "Unit", ""));
178 put("beanstalk.triggerUpperBreachScaleIncrement", new ConfigurationOptionSetting("aws:autoscaling:trigger", "UpperBreachScaleIncrement", ""));
179 put("beanstalk.triggerUpperThreshold", new ConfigurationOptionSetting("aws:autoscaling:trigger", "UpperThreshold", ""));
180
181 put("beanstalk.rollingupdateMaxBatchSize", new ConfigurationOptionSetting("aws:autoscaling:updatepolicy:rollingupdate", "MaxBatchSize", ""));
182 put(
183 "beanstalk.rollingupdateMinInstancesInService",
184 new ConfigurationOptionSetting("aws:autoscaling:updatepolicy:rollingupdate", "MinInstancesInService", ""));
185 put("beanstalk.rollingupdatePauseTime", new ConfigurationOptionSetting("aws:autoscaling:updatepolicy:rollingupdate", "PauseTime", ""));
186 put("beanstalk.rollingupdateEnabled", new ConfigurationOptionSetting("aws:autoscaling:updatepolicy:rollingupdate", "RollingUpdateEnabled", ""));
187
188 put("beanstalk.vpcId", new ConfigurationOptionSetting("aws:ec2:vpc", "VPCId", ""));
189 put("beanstalk.vpcSubnets", new ConfigurationOptionSetting("aws:ec2:vpc", "Subnets", ""));
190 put("beanstalk.vpcELBSubnets", new ConfigurationOptionSetting("aws:ec2:vpc", "ELBSubnets", ""));
191 put("beanstalk.vpcELBScheme", new ConfigurationOptionSetting("aws:ec2:vpc", "ELBScheme", ""));
192 put("beanstalk.vpcDBSubnets", new ConfigurationOptionSetting("aws:ec2:vpc", "DBSubnets", ""));
193 put("beanstalk.vpcAssociatePublicIpAddress", new ConfigurationOptionSetting("aws:ec2:vpc", "AssociatePublicIpAddress", ""));
194
195 put("beanstalk.applicationHealthCheckURL", new ConfigurationOptionSetting("aws:elasticbeanstalk:application", "Application Healthcheck URL", ""));
196
197 put("beanstalk.timeout", new ConfigurationOptionSetting("aws:elasticbeanstalk:command", "Timeout", ""));
198
199 put("beanstalk.environmentType", new ConfigurationOptionSetting("aws:elasticbeanstalk:environment", "EnvironmentType", ""));
200
201 put(
202 "beanstalk.automaticallyTerminateUnhealthyInstances",
203 new ConfigurationOptionSetting("aws:elasticbeanstalk:monitoring", "Automatically Terminate Unhealthy Instances", ""));
204
205 put("beanstalk.notificationEndpoint", new ConfigurationOptionSetting("aws:elasticbeanstalk:sns:topics", "Notification Endpoint", ""));
206 put("beanstalk.notificationProtocol", new ConfigurationOptionSetting("aws:elasticbeanstalk:sns:topics", "Notification Protocol", ""));
207 put("beanstalk.notificationTopicARN", new ConfigurationOptionSetting("aws:elasticbeanstalk:sns:topics", "Notification Topic ARN", ""));
208 put("beanstalk.notificationTopicName", new ConfigurationOptionSetting("aws:elasticbeanstalk:sns:topics", "Notification Topic Name", ""));
209
210 put("beanstalk.sqsdWorkerQueueUrl", new ConfigurationOptionSetting("aws:elasticbeanstalk:sqsd", "WorkerQueueURL", ""));
211 put("beanstalk.sqsdHttpPath", new ConfigurationOptionSetting("aws:elasticbeanstalk:sqsd", "HttpPath", ""));
212 put("beanstalk.sqsdMimeType", new ConfigurationOptionSetting("aws:elasticbeanstalk:sqsd", "MimeType", ""));
213 put("beanstalk.sqsdHttpConnections", new ConfigurationOptionSetting("aws:elasticbeanstalk:sqsd", "HttpConnections", ""));
214 put("beanstalk.sqsdConnectTimeout", new ConfigurationOptionSetting("aws:elasticbeanstalk:sqsd", "ConnectTimeout", ""));
215 put("beanstalk.sqsdInactivityTimeout", new ConfigurationOptionSetting("aws:elasticbeanstalk:sqsd", "InactivityTimeout", ""));
216 put("beanstalk.sqsdVisibilityTimeout", new ConfigurationOptionSetting("aws:elasticbeanstalk:sqsd", "VisibilityTimeout", ""));
217 put("beanstalk.sqsdRetentionPeriod", new ConfigurationOptionSetting("aws:elasticbeanstalk:sqsd", "RetentionPeriod", ""));
218 put("beanstalk.sqsdMaxRetries", new ConfigurationOptionSetting("aws:elasticbeanstalk:sqsd", "MaxRetries", ""));
219
220 put("beanstalk.healthcheckHealthyThreshold", new ConfigurationOptionSetting("aws:elb:healthcheck", "HealthyThreshold", ""));
221 put("beanstalk.healthcheckInterval", new ConfigurationOptionSetting("aws:elb:healthcheck", "Interval", ""));
222 put("beanstalk.healthcheckTimeout", new ConfigurationOptionSetting("aws:elb:healthcheck", "Timeout", ""));
223 put("beanstalk.healthcheckUnhealthyThreshold", new ConfigurationOptionSetting("aws:elb:healthcheck", "UnhealthyThreshold", ""));
224
225 put("beanstalk.loadBalancerHTTPPort", new ConfigurationOptionSetting("aws:elb:loadbalancer", "LoadBalancerHTTPPort", ""));
226 put("beanstalk.loadBalancerPortProtocol", new ConfigurationOptionSetting("aws:elb:loadbalancer", "LoadBalancerPortProtocol", ""));
227 put("beanstalk.loadBalancerHTTPSPort", new ConfigurationOptionSetting("aws:elb:loadbalancer", "LoadBalancerHTTPSPort", ""));
228 put("beanstalk.loadBalancerSSLPortProtocol", new ConfigurationOptionSetting("aws:elb:loadbalancer", "LoadBalancerSSLPortProtocol", ""));
229 put("beanstalk.loadBalancerSSLCertificateId", new ConfigurationOptionSetting("aws:elb:loadbalancer", "SSLCertificateId", ""));
230
231 put("beanstalk.stickinessCookieExpiration", new ConfigurationOptionSetting("aws:elb:policies", "Stickiness Cookie Expiration", ""));
232 put("beanstalk.stickinessPolicy", new ConfigurationOptionSetting("aws:elb:policies", "Stickiness Policy", ""));
233
234 put("beanstalk.dbAllocatedStorage", new ConfigurationOptionSetting("aws:rds:dbinstance", "DBAllocatedStorage", ""));
235 put("beanstalk.dbDeletionPolicy", new ConfigurationOptionSetting("aws:rds:dbinstance", "DBDeletionPolicy", ""));
236 put("beanstalk.dbEngine", new ConfigurationOptionSetting("aws:rds:dbinstance", "DBEngine", ""));
237 put("beanstalk.dbEngineVersion", new ConfigurationOptionSetting("aws:rds:dbinstance", "DBEngineVersion", ""));
238 put("beanstalk.dbInstanceClass", new ConfigurationOptionSetting("aws:rds:dbinstance", "DBInstanceClass", ""));
239 put("beanstalk.dbPassword", new ConfigurationOptionSetting("aws:rds:dbinstance", "DBPassword", ""));
240 put("beanstalk.dbSnapshotIdentifier", new ConfigurationOptionSetting("aws:rds:dbinstance", "DBSnapshotIdentifier", ""));
241 put("beanstalk.dbUser", new ConfigurationOptionSetting("aws:rds:dbinstance", "DBUser", ""));
242 put("beanstalk.dbMultiAZDatabase", new ConfigurationOptionSetting("aws:rds:dbinstance", "MultiAZDatabase", ""));
243
244 put("beanstalk.environmentAwsSecretKey", new ConfigurationOptionSetting("aws:elasticbeanstalk:application:environment", "AWS_SECRET_KEY", ""));
245 put("beanstalk.environmentAwsAccessKeyId", new ConfigurationOptionSetting("aws:elasticbeanstalk:application:environment", "AWS_ACCESS_KEY_ID", ""));
246 put(
247 "beanstalk.environmentJdbcConnectionString",
248 new ConfigurationOptionSetting("aws:elasticbeanstalk:application:environment", "JDBC_CONNECTION_STRING", ""));
249 put("beanstalk.environmentParam1", new ConfigurationOptionSetting("aws:elasticbeanstalk:application:environment", "PARAM1", ""));
250 put("beanstalk.environmentParam2", new ConfigurationOptionSetting("aws:elasticbeanstalk:application:environment", "PARAM2", ""));
251 put("beanstalk.environmentParam3", new ConfigurationOptionSetting("aws:elasticbeanstalk:application:environment", "PARAM3", ""));
252 put("beanstalk.environmentParam4", new ConfigurationOptionSetting("aws:elasticbeanstalk:application:environment", "PARAM4", ""));
253 put("beanstalk.environmentParam5", new ConfigurationOptionSetting("aws:elasticbeanstalk:application:environment", "PARAM5", ""));
254
255 put("beanstalk.logPublicationControl", new ConfigurationOptionSetting("aws:elasticbeanstalk:hostmanager", "LogPublicationControl", ""));
256
257 put("beanstalk.jvmOptions", new ConfigurationOptionSetting("aws:elasticbeanstalk:container:tomcat:jvmoptions", "JVM Options", ""));
258 put("beanstalk.jvmXmx", new ConfigurationOptionSetting("aws:elasticbeanstalk:container:tomcat:jvmoptions", "Xmx", ""));
259 put("beanstalk.jvmMaxPermSize", new ConfigurationOptionSetting("aws:elasticbeanstalk:container:tomcat:jvmoptions", "XX:MaxPermSize", ""));
260 put("beanstalk.jvmXms", new ConfigurationOptionSetting("aws:elasticbeanstalk:container:tomcat:jvmoptions", "Xms", ""));
261
262 put("beanstalk.phpDocumentRoot", new ConfigurationOptionSetting("aws:elasticbeanstalk:container:php:phpini", "document_root", ""));
263 put("beanstalk.phpMemoryLimit", new ConfigurationOptionSetting("aws:elasticbeanstalk:container:php:phpini", "memory_limit", ""));
264 put("beanstalk.phpZlibOutputCompression", new ConfigurationOptionSetting("aws:elasticbeanstalk:container:php:phpini", "zlib.output_compression", ""));
265 put("beanstalk.phpAllowUrlFopen", new ConfigurationOptionSetting("aws:elasticbeanstalk:container:php:phpini", "allow_url_fopen", ""));
266 put("beanstalk.phpDisplayErrors", new ConfigurationOptionSetting("aws:elasticbeanstalk:container:php:phpini", "display_errors", ""));
267 put("beanstalk.phpMaxExecutionTime", new ConfigurationOptionSetting("aws:elasticbeanstalk:container:php:phpini", "max_execution_time", ""));
268 put("beanstalk.phpComposerOptions", new ConfigurationOptionSetting("aws:elasticbeanstalk:container:php:phpini", "composer_options", ""));
269 }
270 };
271
272
273
274 @Parameter(property = "beanstalk.applicationName", defaultValue = "${project.artifactId}", required = true)
275 protected String applicationName;
276
277
278
279 @Parameter(defaultValue = "${project}", readonly = true)
280 protected MavenProject project;
281
282
283
284
285 @Parameter(property = "beanstalk.environmentRef", defaultValue = "${project.artifactId}.elasticbeanstalk.com")
286 protected String environmentRef;
287
288
289
290
291 protected EnvironmentDescription curEnv;
292
293 @Override
294 protected void configure() {
295 try {
296
297
298 curEnv = super.lookupEnvironment(applicationName, environmentRef);
299 } catch (MojoExecutionException e) {
300 throw new RuntimeException(e);
301 }
302 }
303
304
305
306
307
308
309
310 protected Collection<EnvironmentDescription> getEnvironmentsFor(String applicationName) {
311
312
313
314 DescribeEnvironmentsRequest req = new DescribeEnvironmentsRequest().withApplicationName(applicationName).withIncludeDeleted(false);
315
316 return getService().describeEnvironments(req).getEnvironments();
317 }
318
319 protected ConfigurationOptionSetting[] introspectOptionSettings() {
320 Set<ConfigurationOptionSetting> configOptionSetting = new TreeSet<ConfigurationOptionSetting>(COS_COMPARATOR);
321
322 Map<String, ConfigurableOptionSetting> extraOptionSettings = new LinkedHashMap<String, ConfigurableOptionSetting>();
323
324 for (ConfigurableOptionSetting e : configurableOptionSettings) {
325 if (!e.getAlias().startsWith(BEANSTALKX_PREFIX)) {
326 getLog().warn(format("Ignoring ConfigurableOptionSetting '%s' ('%s') since it doesn't start with " + BEANSTALKX_PREFIX, e.getAlias(), e));
327 continue;
328 }
329
330 getLog().info(format("Declaring alias '%s' for '%s'", e.getAlias(), e));
331
332 extraOptionSettings.put(e.getAlias(), e);
333 }
334
335 Properties properties = new Properties();
336
337 if (null != project) {
338 for (Map.Entry<Object, Object> entry : project.getProperties().entrySet()) {
339 if (("" + entry.getKey()).startsWith("beanstalk.")) {
340 properties.put(entry.getKey(), entry.getValue());
341 }
342 }
343 }
344
345 for (Map.Entry<Object, Object> entry : System.getProperties().entrySet()) {
346 if (("" + entry.getKey()).startsWith("beanstalk.")) {
347 properties.put(entry.getKey(), entry.getValue());
348 }
349 }
350
351 for (Map.Entry<Object, Object> entry : session.getSystemProperties().entrySet()) {
352 if (("" + entry.getKey()).startsWith("beanstalk.")) {
353 properties.put(entry.getKey(), entry.getValue());
354 }
355 }
356
357 for (Object o : properties.keySet()) {
358 String k = "" + o;
359
360 if (k.startsWith("beanstalk.env.aws.")) {
361 String realKey = k.substring("beanstalk.env.".length());
362 String v = "" + properties.get(k);
363 List<String> elements = new ArrayList<String>(Arrays.asList(realKey.split("\\.")));
364
365 String namespace = StringUtils.join(elements.subList(0, -1 + elements.size()), ":");
366 String optionName = elements.get(-1 + elements.size());
367
368 getLog().info("importing " + k + " as " + namespace + ":" + optionName + "=" + v);
369
370 configOptionSetting.add(new ConfigurationOptionSetting().withNamespace(namespace).withOptionName(optionName).withValue(v));
371 } else if (COMMON_PARAMETERS.containsKey(k)) {
372 String v = "" + properties.get(k);
373 String namespace = COMMON_PARAMETERS.get(k).getNamespace();
374 String optionName = COMMON_PARAMETERS.get(k).getOptionName();
375
376 getLog().info("Found alias " + k + " for " + namespace + ":" + optionName + "(value=" + v + ")");
377
378 configOptionSetting.add(new ConfigurationOptionSetting().withNamespace(namespace).withOptionName(optionName).withValue(v));
379 } else if (extraOptionSettings.containsKey(k)) {
380 ConfigurableOptionSetting cos = extraOptionSettings.get(k);
381 String v = "" + properties.get(k);
382
383 if (isNotBlank(v)) {
384 getLog().info(format("Assigning alias '%s' to '%s' (value='%s')", k, cos, v));
385 configOptionSetting.add(new ConfigurationOptionSetting(cos.getNamespace(), cos.getOptionName(), v));
386 }
387 }
388 }
389
390 return (ConfigurationOptionSetting[]) configOptionSetting.toArray(new ConfigurationOptionSetting[configOptionSetting.size()]);
391 }
392
393 protected void waitForNotUpdating() throws AbstractMojoExecutionException, MojoFailureException, MojoExecutionException {
394 WaitForEnvironmentContext context =
395 new WaitForEnvironmentContextBuilder()
396 .withApplicationName(applicationName)
397 .withStatusToWaitFor("!Updating")
398 .withTimeoutMins(2)
399 .withEnvironmentRef(environmentRef)
400 .build();
401
402 WaitForEnvironmentCommandor/WaitForEnvironmentCommand.html#WaitForEnvironmentCommand">WaitForEnvironmentCommand command = new WaitForEnvironmentCommand(this);
403
404 command.execute(context);
405 }
406
407 protected String lookupVersionLabel(String appName, String versionLabel) {
408 if (StringUtils.isBlank(versionLabel)) {
409 DescribeApplicationVersionsResult appVersionsResult =
410 getService().describeApplicationVersions(new DescribeApplicationVersionsRequest().withApplicationName(appName));
411
412 List<ApplicationVersionDescription> appVersionList = new ArrayList<ApplicationVersionDescription>(appVersionsResult.getApplicationVersions());
413
414 Collections.sort(
415 appVersionList,
416 new Comparator<ApplicationVersionDescription>() {
417 @Override
418 public int compare(ApplicationVersionDescription o1, ApplicationVersionDescription o2) {
419 return new CompareToBuilder().append(o2.getDateUpdated(), o1.getDateUpdated()).append(o2.getDateCreated(), o1.getDateUpdated()).toComparison();
420 }
421 });
422
423 if (appVersionList.isEmpty()) {
424 String message = "No version label supplied **AND** no app versions available.";
425
426 getLog().info(message);
427
428 throw new IllegalStateException(message);
429 } else {
430 versionLabel = appVersionList.get(0).getVersionLabel();
431
432 getLog().info("Using latest available application version " + versionLabel);
433 }
434 }
435
436 return versionLabel;
437 }
438 }