View Javadoc
1   /*
2    * Copyright (c) 2016 ingenieux Labs
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    * http://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 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     * <p>Allows you to declare your own properties inside the plugin configuration, as long as it
99     * starts with "beanstalk.x." <p> <p>
100    * <code><pre>
101    * &lt;pluginManagement&gt;
102    *   &lt;plugins&gt;
103    *     &lt;plugin&gt;
104    *       &lt;groupId&gt;br.com.ingenieux&lt;/groupId&gt;
105    *       &lt;artifactId&gt;beanstalk-maven-plugin&lt;/artifactId&gt;
106    *       &lt;inherited&gt;true&lt;/inherited&gt;
107    *       &lt;version&gt;XXX&lt;/version&gt;
108    *       &lt;configuration&gt;
109    *         &lt;tags&gt;
110    *           &lt;Uses&gt;ingenieux Beanstalker, http://beanstalker.ingenieux.com.br/&lt;/Uses&gt;
111    *         &lt;/tags&gt;
112    *         &lt;configurableOptionSettings&gt;
113    *           &lt;configurableOptionSetting&gt;
114    *             &lt;alias&gt;beanstalkx.serviceRole&lt;/alias&gt;
115    *             &lt;namespace&gt;aws:elasticbeanstalk:environment&lt;/namespace&gt;
116    *             &lt;optionName&gt;ServiceRole&lt;/optionName&gt;
117    *           &lt;/configurableOptionSetting&gt;
118    *         &lt;/configurableOptionSettings&gt;
119    *       &lt;/configuration&gt;
120    *     &lt;/plugin&gt;
121    *   &lt;/plugins&gt;
122    * &lt;/pluginManagement&gt;
123    * </pre>
124    * </code>
125    *
126    * <p>This basically exposes the <code>beanstalkx.serviceRole</code> property as the mentioned
127    * Configuration Option Setting</p>
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    * Beanstalk Application Name
273    */
274   @Parameter(property = "beanstalk.applicationName", defaultValue = "${project.artifactId}", required = true)
275   protected String applicationName;
276   /**
277    * Maven Project
278    */
279   @Parameter(defaultValue = "${project}", readonly = true)
280   protected MavenProject project;
281 
282   /**
283    * Environment Ref
284    */
285   @Parameter(property = "beanstalk.environmentRef", defaultValue = "${project.artifactId}.elasticbeanstalk.com")
286   protected String environmentRef;
287 
288   /**
289    * Current Environment
290    */
291   protected EnvironmentDescription curEnv;
292 
293   @Override
294   protected void configure() {
295     try {
296       // TODO Add Convenient Warning Later
297 
298       curEnv = super.lookupEnvironment(applicationName, environmentRef);
299     } catch (MojoExecutionException e) {
300       throw new RuntimeException(e);
301     }
302   }
303 
304   /**
305    * Returns a list of environments for applicationName
306    *
307    * @param applicationName applicationName
308    * @return environments
309    */
310   protected Collection<EnvironmentDescription> getEnvironmentsFor(String applicationName) {
311     /*
312      * Requests
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 }