Skip to content

Commit f0e542f

Browse files
committedFeb 22, 2012
[FIXED JENKINS-8946] Option to set Zone as well as region for instance creation [FIXED JENKINS-11953] Dynamically local AWS regions
1 parent bec9dbf commit f0e542f

File tree

15 files changed

+209
-113
lines changed

15 files changed

+209
-113
lines changed
 

‎src/main/java/hudson/plugins/ec2/AmazonEC2Cloud.java

+61-12
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,25 @@
22

33
import hudson.Extension;
44
import hudson.util.FormValidation;
5+
import hudson.util.ListBoxModel;
56

67
import java.io.IOException;
8+
import java.net.MalformedURLException;
79
import java.net.URL;
810
import java.util.List;
11+
import java.util.Locale;
912

1013
import javax.servlet.ServletException;
1114

15+
import org.apache.commons.lang.StringUtils;
1216
import org.kohsuke.stapler.DataBoundConstructor;
1317
import org.kohsuke.stapler.QueryParameter;
1418
import org.kohsuke.stapler.StaplerResponse;
1519

20+
import com.amazonaws.services.ec2.AmazonEC2;
21+
import com.amazonaws.services.ec2.model.DescribeRegionsResult;
22+
import com.amazonaws.services.ec2.model.Region;
23+
1624
/**
1725
* The original implementation of {@link EC2Cloud}.
1826
*
@@ -22,28 +30,48 @@ public class AmazonEC2Cloud extends EC2Cloud {
2230
/**
2331
* Represents the region. Can be null for backward compatibility reasons.
2432
*/
25-
private AwsRegion region;
33+
private String region;
2634

35+
// Used when running unit tests
36+
public static boolean testMode;
37+
38+
2739
@DataBoundConstructor
28-
public AmazonEC2Cloud(AwsRegion region, String accessId, String secretKey, String privateKey, String instanceCapStr, List<SlaveTemplate> templates) {
29-
super("ec2-"+region.name(), accessId, secretKey, privateKey, instanceCapStr, templates);
40+
public AmazonEC2Cloud(String accessId, String secretKey, String region, String privateKey, String instanceCapStr, List<SlaveTemplate> templates) {
41+
super("ec2-"+region, accessId, secretKey, privateKey, instanceCapStr, templates);
3042
this.region = region;
3143
}
3244

33-
public AwsRegion getRegion() {
34-
if (region==null)
35-
region = AwsRegion.US_EAST_1; // backward data compatibility with earlier versions
45+
public String getRegion() {
46+
if (region == null)
47+
region = DEFAULT_EC2_HOST; // Backward compatibility
48+
// Handles pre 1.14 region names that used the old AwsRegion enum, note we don't change
49+
// the region here to keep the meta-data compatible in the case of a downgrade (is that right?)
50+
if (region.indexOf('_') > 0)
51+
return region.replace('_', '-').toLowerCase(Locale.ENGLISH);
3652
return region;
3753
}
3854

55+
public static URL getEc2EndpointUrl(String region) {
56+
try {
57+
return new URL("https://" + region + "." + EC2_URL_HOST + "/");
58+
} catch (MalformedURLException e) {
59+
throw new Error(e); // Impossible
60+
}
61+
}
62+
3963
@Override
4064
public URL getEc2EndpointUrl() {
41-
return getRegion().ec2Endpoint;
65+
return getEc2EndpointUrl(getRegion());
4266
}
4367

4468
@Override
4569
public URL getS3EndpointUrl() {
46-
return getRegion().s3Endpoint;
70+
try {
71+
return new URL("https://"+getRegion()+".s3.amazonaws.com/");
72+
} catch (MalformedURLException e) {
73+
throw new Error(e); // Impossible
74+
}
4775
}
4876

4977
@Extension
@@ -53,17 +81,38 @@ public String getDisplayName() {
5381
return "Amazon EC2";
5482
}
5583

84+
public ListBoxModel doFillRegionItems(@QueryParameter String accessId,
85+
@QueryParameter String secretKey) throws IOException,
86+
ServletException {
87+
ListBoxModel model = new ListBoxModel();
88+
if (testMode) {
89+
model.add(DEFAULT_EC2_HOST);
90+
return model;
91+
}
92+
93+
if (!StringUtils.isEmpty(accessId) && !StringUtils.isEmpty(secretKey)) {
94+
AmazonEC2 client = connect(accessId, secretKey, new URL(
95+
"http://ec2.amazonaws.com"));
96+
DescribeRegionsResult regions = client.describeRegions();
97+
List<Region> regionList = regions.getRegions();
98+
for (Region r : regionList) {
99+
model.add(r.getRegionName(), r.getRegionName());
100+
}
101+
}
102+
return model;
103+
}
104+
56105
public FormValidation doTestConnection(
57-
@QueryParameter AwsRegion region,
106+
@QueryParameter String region,
58107
@QueryParameter String accessId,
59108
@QueryParameter String secretKey,
60109
@QueryParameter String privateKey) throws IOException, ServletException {
61-
return super.doTestConnection(region.ec2Endpoint,accessId,secretKey,privateKey);
110+
return super.doTestConnection(getEc2EndpointUrl(region),accessId,secretKey,privateKey);
62111
}
63112

64113
public FormValidation doGenerateKey(
65-
StaplerResponse rsp, @QueryParameter AwsRegion region, @QueryParameter String accessId, @QueryParameter String secretKey) throws IOException, ServletException {
66-
return super.doGenerateKey(rsp,region.ec2Endpoint,accessId,secretKey);
114+
StaplerResponse rsp, @QueryParameter String region, @QueryParameter String accessId, @QueryParameter String secretKey) throws IOException, ServletException {
115+
return super.doGenerateKey(rsp,getEc2EndpointUrl(region),accessId,secretKey);
67116
}
68117
}
69118
}

‎src/main/java/hudson/plugins/ec2/AwsRegion.java

-52
This file was deleted.

‎src/main/java/hudson/plugins/ec2/EC2Cloud.java

+6-14
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@
5656
*/
5757
public abstract class EC2Cloud extends Cloud {
5858

59+
public static final String DEFAULT_EC2_HOST = "us-east-1";
60+
public static final String EC2_URL_HOST = "ec2.amazonaws.com";
61+
5962
private final String accessId;
6063
private final Secret secretKey;
6164
private final EC2PrivateKey privateKey;
@@ -292,23 +295,12 @@ public static AmazonEC2 connect(String accessId, Secret secretKey, URL endpoint)
292295
*/
293296
public static String convertHostName(String ec2HostName) {
294297
if (ec2HostName == null || ec2HostName.length()==0)
295-
ec2HostName = "us-east-1";
298+
ec2HostName = DEFAULT_EC2_HOST;
296299
if (!ec2HostName.contains("."))
297-
ec2HostName = ec2HostName + ".ec2.amazonaws.com";
300+
ec2HostName = ec2HostName + "." + EC2_URL_HOST;
298301
return ec2HostName;
299302
}
300303

301-
/***
302-
* Convert a configured s3 endpoint to a FQDN or ip address
303-
*/
304-
public static String convertS3HostName(String s3HostName) {
305-
if (s3HostName == null || s3HostName.length()==0)
306-
s3HostName = "s3";
307-
if (!s3HostName.contains("."))
308-
s3HostName = s3HostName + ".amazonaws.com";
309-
return s3HostName;
310-
}
311-
312304
/***
313305
* Convert a user entered string into a port number
314306
* "" -> -1 to indicate default based on SSL setting
@@ -391,7 +383,7 @@ protected FormValidation doTestConnection( URL ec2endpoint,
391383
// check if this key exists
392384
EC2PrivateKey pk = new EC2PrivateKey(privateKey);
393385
if(pk.find(ec2)==null)
394-
return FormValidation.error("The private key entered below isn't registered to this EC2 region (fingerprint is "+pk.getFingerprint()+")");
386+
return FormValidation.error("The EC2 key pair private key isn't registered to this EC2 region (fingerprint is "+pk.getFingerprint()+")");
395387
}
396388

397389
return FormValidation.ok(Messages.EC2Cloud_Success());

‎src/main/java/hudson/plugins/ec2/EC2Computer.java

+7
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
11
package hudson.plugins.ec2;
22

3+
import hudson.Extension;
34
import hudson.Util;
5+
import hudson.model.Slave.SlaveDescriptor;
46
import hudson.slaves.SlaveComputer;
7+
import hudson.util.ListBoxModel;
58

69
import java.io.IOException;
710
import java.util.Collections;
811

12+
import javax.servlet.ServletException;
13+
914
import org.kohsuke.stapler.HttpRedirect;
1015
import org.kohsuke.stapler.HttpResponse;
16+
import org.kohsuke.stapler.QueryParameter;
1117

1218
import com.amazonaws.AmazonClientException;
1319
import com.amazonaws.services.ec2.AmazonEC2;
@@ -123,4 +129,5 @@ public int getSshPort() {
123129
public String getRootCommandPrefix() {
124130
return getNode().getRootCommandPrefix();
125131
}
132+
126133
}

‎src/main/java/hudson/plugins/ec2/EC2Slave.java

+48-4
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,24 @@
88
import hudson.model.Slave;
99
import hudson.plugins.ec2.ssh.EC2UnixLauncher;
1010
import hudson.slaves.NodeProperty;
11+
import hudson.util.ListBoxModel;
1112

1213
import java.io.IOException;
1314
import java.util.Collections;
1415
import java.util.List;
1516
import java.util.logging.Level;
1617
import java.util.logging.Logger;
1718

19+
import javax.servlet.ServletException;
20+
21+
import org.apache.commons.lang.StringUtils;
1822
import org.kohsuke.stapler.DataBoundConstructor;
23+
import org.kohsuke.stapler.QueryParameter;
1924

2025
import com.amazonaws.AmazonClientException;
2126
import com.amazonaws.services.ec2.AmazonEC2;
27+
import com.amazonaws.services.ec2.model.AvailabilityZone;
28+
import com.amazonaws.services.ec2.model.DescribeAvailabilityZonesResult;
2229
import com.amazonaws.services.ec2.model.InstanceType;
2330
import com.amazonaws.services.ec2.model.TerminateInstancesRequest;
2431

@@ -31,6 +38,7 @@ public final class EC2Slave extends Slave {
3138
/**
3239
* Comes from {@link SlaveTemplate#initScript}.
3340
*/
41+
public final String zone;
3442
public final String initScript;
3543
public final String remoteAdmin; // e.g. 'ubuntu'
3644
public final String rootCommandPrefix; // e.g. 'sudo'
@@ -41,13 +49,16 @@ public final class EC2Slave extends Slave {
4149
*/
4250
private final int sshPort;
4351

44-
public EC2Slave(String instanceId, String description, String remoteFS, int sshPort, int numExecutors, String labelString, String initScript, String remoteAdmin, String rootCommandPrefix, String jvmopts) throws FormException, IOException {
45-
this(instanceId, description, remoteFS, sshPort, numExecutors, Mode.NORMAL, labelString, initScript, Collections.<NodeProperty<?>>emptyList(), remoteAdmin, rootCommandPrefix, jvmopts);
52+
public static final String TEST_ZONE = "testZone";
53+
54+
public EC2Slave(String instanceId, String description, String zone, String remoteFS, int sshPort, int numExecutors, String labelString, String initScript, String remoteAdmin, String rootCommandPrefix, String jvmopts) throws FormException, IOException {
55+
this(instanceId, description, zone, remoteFS, sshPort, numExecutors, Mode.NORMAL, labelString, initScript, Collections.<NodeProperty<?>>emptyList(), remoteAdmin, rootCommandPrefix, jvmopts);
4656
}
4757

4858
@DataBoundConstructor
49-
public EC2Slave(String instanceId, String description, String remoteFS, int sshPort, int numExecutors, Mode mode, String labelString, String initScript, List<? extends NodeProperty<?>> nodeProperties, String remoteAdmin, String rootCommandPrefix, String jvmopts) throws FormException, IOException {
59+
public EC2Slave(String instanceId, String description, String zone, String remoteFS, int sshPort, int numExecutors, Mode mode, String labelString, String initScript, List<? extends NodeProperty<?>> nodeProperties, String remoteAdmin, String rootCommandPrefix, String jvmopts) throws FormException, IOException {
5060
super(instanceId, description, remoteFS, numExecutors, mode, labelString, new EC2UnixLauncher(), new EC2RetentionStrategy(), nodeProperties);
61+
this.zone = zone;
5162
this.initScript = initScript;
5263
this.remoteAdmin = remoteAdmin;
5364
this.rootCommandPrefix = rootCommandPrefix;
@@ -59,7 +70,7 @@ public EC2Slave(String instanceId, String description, String remoteFS, int sshP
5970
* Constructor for debugging.
6071
*/
6172
public EC2Slave(String instanceId) throws FormException, IOException {
62-
this(instanceId,"debug","/tmp/hudson", 22, 1, Mode.NORMAL, "debug", "", Collections.<NodeProperty<?>>emptyList(), null, null, null);
73+
this(instanceId,"debug","zone", "/tmp/hudson", 22, 1, Mode.NORMAL, "debug", "", Collections.<NodeProperty<?>>emptyList(), null, null, null);
6374
}
6475

6576
/**
@@ -111,6 +122,10 @@ public void terminate() {
111122
}
112123
}
113124

125+
String getZone() {
126+
return zone;
127+
}
128+
114129
String getRemoteAdmin() {
115130
if (remoteAdmin == null || remoteAdmin.length() == 0)
116131
return "root";
@@ -131,6 +146,29 @@ public int getSshPort() {
131146
return sshPort!=0 ? sshPort : 22;
132147
}
133148

149+
public static ListBoxModel fillZoneItems(String accessId,
150+
String secretKey, String region) throws IOException,
151+
ServletException {
152+
ListBoxModel model = new ListBoxModel();
153+
if (AmazonEC2Cloud.testMode) {
154+
model.add(TEST_ZONE);
155+
return model;
156+
}
157+
158+
if (!StringUtils.isEmpty(accessId) && !StringUtils.isEmpty(secretKey) && !StringUtils.isEmpty(region)) {
159+
AmazonEC2 client = AmazonEC2Cloud.connect(accessId, secretKey, AmazonEC2Cloud.getEc2EndpointUrl(region));
160+
DescribeAvailabilityZonesResult zones = client.describeAvailabilityZones();
161+
List<AvailabilityZone> zoneList = zones.getAvailabilityZones();
162+
model.add("<not specified>", "");
163+
for (AvailabilityZone z : zoneList) {
164+
model.add(z.getZoneName(), z.getZoneName());
165+
}
166+
}
167+
return model;
168+
}
169+
170+
171+
134172
@Extension
135173
public static final class DescriptorImpl extends SlaveDescriptor {
136174
@Override
@@ -142,6 +180,12 @@ public String getDisplayName() {
142180
public boolean isInstantiable() {
143181
return false;
144182
}
183+
184+
public ListBoxModel doFillZoneItems(@QueryParameter String accessId,
185+
@QueryParameter String secretKey, @QueryParameter String region) throws IOException,
186+
ServletException {
187+
return fillZoneItems(accessId, secretKey, region);
188+
}
145189
}
146190

147191
private static final Logger LOGGER = Logger.getLogger(EC2Slave.class.getName());

‎src/main/java/hudson/plugins/ec2/PluginImpl.java

-3
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,6 @@ public void start() throws Exception {
1717
Hudson.XSTREAM.alias("hudson.plugins.ec2.EC2Cloud",AmazonEC2Cloud.class);
1818
// backward compatibility with the legacy instance type
1919
Hudson.XSTREAM.registerConverter(new InstanceTypeConverter());
20-
21-
// make sure the converter gets registered by forcing static initializer
22-
AwsRegion.AP_NORTHEAST_1.toString();
2320

2421
load();
2522
}

0 commit comments

Comments
 (0)
Please sign in to comment.