View Javadoc
1   /**
2    * Copyright (c) 2012-2014, jcabi.com
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions
7    * are met: 1) Redistributions of source code must retain the above
8    * copyright notice, this list of conditions and the following
9    * disclaimer. 2) Redistributions in binary form must reproduce the above
10   * copyright notice, this list of conditions and the following
11   * disclaimer in the documentation and/or other materials provided
12   * with the distribution. 3) Neither the name of the jcabi.com nor
13   * the names of its contributors may be used to endorse or promote
14   * products derived from this software without specific prior written
15   * permission.
16   *
17   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
19   * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20   * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21   * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
22   * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28   * OF THE POSSIBILITY OF SUCH DAMAGE.
29   */
30  package com.jcabi.beanstalk.maven.plugin;
31  
32  import com.amazonaws.services.elasticbeanstalk.AWSElasticBeanstalk;
33  import com.amazonaws.services.elasticbeanstalk.model.ApplicationVersionDescription;
34  import com.amazonaws.services.elasticbeanstalk.model.CreateApplicationVersionRequest;
35  import com.amazonaws.services.elasticbeanstalk.model.CreateApplicationVersionResult;
36  import com.amazonaws.services.elasticbeanstalk.model.DeleteApplicationVersionRequest;
37  import com.amazonaws.services.elasticbeanstalk.model.DescribeApplicationVersionsRequest;
38  import com.amazonaws.services.elasticbeanstalk.model.DescribeApplicationVersionsResult;
39  import com.jcabi.aspects.Loggable;
40  import com.jcabi.log.Logger;
41  import javax.validation.constraints.NotNull;
42  import lombok.EqualsAndHashCode;
43  
44  /**
45   * EBT application version.
46   *
47   * @author Yegor Bugayenko (yegor@tpc2.com)
48   * @version $Id$
49   * @since 0.3
50   */
51  @EqualsAndHashCode(of = { "client", "application", "bundle" })
52  @Loggable(Loggable.DEBUG)
53  final class OverridingVersion implements Version {
54  
55      /**
56       * AWS beanstalk client.
57       */
58      private final transient AWSElasticBeanstalk client;
59  
60      /**
61       * Application name.
62       */
63      private final transient String application;
64  
65      /**
66       * Bundle with a file.
67       */
68      private final transient Bundle bundle;
69  
70      /**
71       * Public ctor.
72       * @param clnt Client
73       * @param app Application name
74       * @param bndl Bundle
75       */
76      protected OverridingVersion(@NotNull final AWSElasticBeanstalk clnt,
77          @NotNull final String app, @NotNull final Bundle bndl) {
78          this.client = clnt;
79          this.application = app;
80          this.bundle = bndl;
81      }
82  
83      /**
84       * {@inheritDoc}
85       */
86      @Override
87      public String toString() {
88          return this.bundle.name();
89      }
90  
91      /**
92       * {@inheritDoc}
93       */
94      @Override
95      public String label() {
96          if (this.exists()) {
97              Logger.info(
98                  this,
99                  "Version '%s' already exists for '%s'",
100                 this.bundle.name(),
101                 this.application
102             );
103         } else {
104             final CreateApplicationVersionResult res =
105                 this.client.createApplicationVersion(
106                     new CreateApplicationVersionRequest()
107                         .withApplicationName(this.application)
108                         .withVersionLabel(this.bundle.name())
109                         .withSourceBundle(this.bundle.location())
110                         .withDescription(this.bundle.etag())
111                 );
112             final ApplicationVersionDescription desc =
113                 res.getApplicationVersion();
114             Logger.info(
115                 this,
116                 "Version '%s' created for '%s' (%s): '%s'",
117                 desc.getVersionLabel(),
118                 desc.getApplicationName(),
119                 this.bundle.location(),
120                 desc.getDescription()
121             );
122             if (!desc.getVersionLabel().equals(this.bundle.name())) {
123                 throw new DeploymentException(
124                     String.format(
125                         "version label is '%s' while '%s' expected",
126                         desc.getVersionLabel(),
127                         this.bundle.name()
128                     )
129                 );
130             }
131         }
132         return this.bundle.name();
133     }
134 
135     /**
136      * This label exists already?
137      * @return Yes or no
138      */
139     private boolean exists() {
140         final DescribeApplicationVersionsResult res =
141             this.client.describeApplicationVersions(
142                 new DescribeApplicationVersionsRequest()
143                     .withApplicationName(this.application)
144                     .withVersionLabels(this.bundle.name())
145             );
146         boolean exists = false;
147         if (res.getApplicationVersions().isEmpty()) {
148             Logger.info(
149                 this,
150                 "Version '%s' is absent in '%s'",
151                 this.bundle.name(),
152                 this.application
153             );
154         } else {
155             final ApplicationVersionDescription ver =
156                 res.getApplicationVersions().get(0);
157             if (ver.getSourceBundle().equals(this.bundle.location())
158                 && ver.getDescription().equals(this.bundle.etag())) {
159                 Logger.info(
160                     this,
161                     "Version '%s' already exists for '%s', etag='%s'",
162                     ver.getVersionLabel(),
163                     ver.getApplicationName(),
164                     ver.getDescription()
165                 );
166                 exists = true;
167             } else {
168                 this.client.deleteApplicationVersion(
169                     new DeleteApplicationVersionRequest()
170                         .withApplicationName(this.application)
171                         .withVersionLabel(this.bundle.name())
172                 );
173                 Logger.info(
174                     this,
175                     // @checkstyle LineLength (1 line)
176                     "Version '%s' deleted in '%s' because of its outdated S3 location",
177                     this.bundle.name(),
178                     this.application
179                 );
180             }
181         }
182         return exists;
183     }
184 
185 }