1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package br.com.ingenieux.mojo.beanstalk.bg;
18
19 import com.google.common.base.Function;
20 import com.google.common.collect.Collections2;
21
22 import com.amazonaws.services.elasticbeanstalk.model.EnvironmentDescription;
23 import com.amazonaws.services.elasticbeanstalk.model.SwapEnvironmentCNAMEsRequest;
24
25 import org.apache.maven.plugins.annotations.Mojo;
26 import org.apache.maven.plugins.annotations.Parameter;
27
28 import java.util.Collection;
29
30 import br.com.ingenieux.mojo.beanstalk.AbstractNeedsEnvironmentMojo;
31 import br.com.ingenieux.mojo.beanstalk.cmd.env.update.UpdateEnvironmentCommand;
32 import br.com.ingenieux.mojo.beanstalk.cmd.env.update.UpdateEnvironmentContextBuilder;
33 import br.com.ingenieux.mojo.beanstalk.cmd.env.waitfor.WaitForEnvironmentCommand;
34 import br.com.ingenieux.mojo.beanstalk.cmd.env.waitfor.WaitForEnvironmentContextBuilder;
35
36 import static java.lang.String.format;
37
38
39
40
41
42
43 @Mojo(name = "blue-green")
44 public class BluegreenDeploymentMojo extends AbstractNeedsEnvironmentMojo {
45
46
47
48
49 @Parameter(property = "beanstalk.environmentNamePrefix", required = true, defaultValue = "${beanstalk.environmentName}")
50 protected String environmentNamePrefix;
51
52
53
54 @Parameter(property = "beanstalk.versionLabel", defaultValue = "${project.version}-${maven.build.timestamp}")
55 String versionLabel;
56
57 @Override
58 protected Object executeInternal() throws Exception {
59 versionLabel = lookupVersionLabel(applicationName, versionLabel);
60
61 getLog().info(format("Using version %s", versionLabel));
62
63 Collection<EnvironmentDescription> envs =
64 new WaitForEnvironmentCommand(this)
65 .lookupInternal(
66 new WaitForEnvironmentContextBuilder().withApplicationName(applicationName).withEnvironmentRef(environmentNamePrefix + "*").build());
67
68 if (envs.size() > 2) {
69 final Collection<String> environmentList =
70 Collections2.transform(
71 envs,
72 new Function<EnvironmentDescription, String>() {
73 @Override
74 public String apply(EnvironmentDescription input) {
75 return format("%s[%s]", input.getEnvironmentId(), input.getEnvironmentName());
76 }
77 });
78
79 String message = "Ooops. There are multiple environments matching the lookup spec: " + environmentList;
80
81 getLog().warn(message);
82 getLog().warn("Will pick one at random anyway as long as it uses WebServer tier name");
83 }
84
85 String otherEnvId = null;
86 for (EnvironmentDescription e : envs) {
87 if (!e.getEnvironmentId().equals(curEnv.getEnvironmentId()) && "WebServer".equals(e.getTier().getName())) {
88 otherEnvId = e.getEnvironmentId();
89 break;
90 }
91 }
92
93 getLog().info(format("(Green) Environment with environmentId['%s'] will be prepared once its ready to update", curEnv.getEnvironmentId()));
94
95 new WaitForEnvironmentCommand(this)
96 .execute(
97 new WaitForEnvironmentContextBuilder()
98 .withStatusToWaitFor("Ready")
99 .withApplicationName(applicationName)
100 .withEnvironmentRef(curEnv.getEnvironmentId())
101 .build());
102
103 getLog().info(format("(Blue) Environment with environmentId['%s'] will be prepared once its ready to update", otherEnvId));
104
105 new WaitForEnvironmentCommand(this)
106 .execute(
107 new WaitForEnvironmentContextBuilder().withStatusToWaitFor("Ready").withApplicationName(applicationName).withEnvironmentRef(otherEnvId).build());
108
109 getLog().info(format("(Blue) Updating environmentId to version %s", versionLabel));
110
111 new UpdateEnvironmentCommand(this).execute(new UpdateEnvironmentContextBuilder().withEnvironmentId(otherEnvId).withVersionLabel(versionLabel).build());
112
113 getLog().info(format("(Blue) Waiting for environmentId['%s'] to get ready and green prior to switching", otherEnvId));
114
115 new WaitForEnvironmentCommand(this)
116 .execute(
117 new WaitForEnvironmentContextBuilder()
118 .withStatusToWaitFor("Ready")
119 .withApplicationName(applicationName)
120 .withHealth("Green")
121 .withEnvironmentRef(otherEnvId)
122 .build());
123
124 getLog().info(format("Ok. Switching"));
125
126 getService()
127 .swapEnvironmentCNAMEs(new SwapEnvironmentCNAMEsRequest().withDestinationEnvironmentId(curEnv.getEnvironmentId()).withSourceEnvironmentId(otherEnvId));
128
129 getLog().info(format("Done."));
130
131 return null;
132 }
133 }