1 | /** |
2 | * |
3 | * Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com> |
4 | * |
5 | * ==================================================================== |
6 | * Licensed under the Apache License, Version 2.0 (the "License"); |
7 | * you may not use this file except in compliance with the License. |
8 | * You may obtain a copy of the License at |
9 | * |
10 | * http://www.apache.org/licenses/LICENSE-2.0 |
11 | * |
12 | * Unless required by applicable law or agreed to in writing, software |
13 | * distributed under the License is distributed on an "AS IS" BASIS, |
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
15 | * See the License for the specific language governing permissions and |
16 | * limitations under the License. |
17 | * ==================================================================== |
18 | */ |
19 | package org.jclouds.compute.options; |
20 | |
21 | import static com.google.common.base.Preconditions.checkArgument; |
22 | import static com.google.common.base.Preconditions.checkNotNull; |
23 | |
24 | import java.io.IOException; |
25 | import java.util.Arrays; |
26 | |
27 | import org.jclouds.domain.Credentials; |
28 | import org.jclouds.io.Payload; |
29 | import org.jclouds.scriptbuilder.domain.Statement; |
30 | import org.jclouds.scriptbuilder.domain.Statements; |
31 | import org.jclouds.util.Strings2; |
32 | |
33 | import com.google.common.base.Throwables; |
34 | |
35 | /** |
36 | * Contains options supported in the {@code ComputeService#runNodesWithTag} operation. <h2> |
37 | * Usage</h2> The recommended way to instantiate a TemplateOptions object is to statically import |
38 | * TemplateOptions.* and invoke a static creation method followed by an instance mutator (if |
39 | * needed): |
40 | * <p/> |
41 | * <code> |
42 | * import static org.jclouds.compute.options.TemplateOptions.Builder.*; |
43 | * <p/> |
44 | * ComputeService client = // get connection |
45 | * templateBuilder.options(inboundPorts(22, 80, 8080, 443)); |
46 | * Set<? extends NodeMetadata> set = client.runNodesWithTag(tag, 2, templateBuilder.build()); |
47 | * <code> |
48 | * |
49 | * @author Adrian Cole |
50 | */ |
51 | public class TemplateOptions extends RunScriptOptions { |
52 | |
53 | public static final TemplateOptions NONE = new ImmutableTemplateOptions(new TemplateOptions()); |
54 | |
55 | public static class ImmutableTemplateOptions extends TemplateOptions { |
56 | private final TemplateOptions delegate; |
57 | |
58 | public ImmutableTemplateOptions(TemplateOptions delegate) { |
59 | this.delegate = delegate; |
60 | } |
61 | |
62 | @Override |
63 | public String toString() { |
64 | return delegate.toString(); |
65 | } |
66 | |
67 | @Override |
68 | public <T extends TemplateOptions> T as(Class<T> clazz) { |
69 | return delegate.as(clazz); |
70 | } |
71 | |
72 | @Override |
73 | public TemplateOptions authorizePublicKey(String publicKey) { |
74 | throw new IllegalArgumentException("authorizePublicKey is immutable"); |
75 | } |
76 | |
77 | @Override |
78 | public TemplateOptions blockUntilRunning(boolean blockUntilRunning) { |
79 | throw new IllegalArgumentException("blockUntilRunning is immutable"); |
80 | } |
81 | |
82 | @Override |
83 | public int[] getInboundPorts() { |
84 | return delegate.getInboundPorts(); |
85 | } |
86 | |
87 | @Override |
88 | public String getPrivateKey() { |
89 | return delegate.getPrivateKey(); |
90 | } |
91 | |
92 | @Override |
93 | public String getPublicKey() { |
94 | return delegate.getPublicKey(); |
95 | } |
96 | |
97 | @Override |
98 | public Statement getRunScript() { |
99 | return delegate.getRunScript(); |
100 | } |
101 | |
102 | @Override |
103 | public boolean shouldBlockUntilRunning() { |
104 | return delegate.shouldBlockUntilRunning(); |
105 | } |
106 | |
107 | @Override |
108 | public TemplateOptions inboundPorts(int... ports) { |
109 | throw new IllegalArgumentException("ports is immutable"); |
110 | } |
111 | |
112 | @Override |
113 | public TemplateOptions installPrivateKey(String privateKey) { |
114 | throw new IllegalArgumentException("privateKey is immutable"); |
115 | } |
116 | |
117 | @Override |
118 | public boolean isIncludeMetadata() { |
119 | return delegate.isIncludeMetadata(); |
120 | } |
121 | |
122 | @Override |
123 | public TemplateOptions runScript(byte[] script) { |
124 | throw new IllegalArgumentException("withMetadata is immutable"); |
125 | } |
126 | |
127 | @Override |
128 | public TemplateOptions withMetadata() { |
129 | throw new IllegalArgumentException("withMetadata is immutable"); |
130 | } |
131 | |
132 | } |
133 | |
134 | protected int[] inboundPorts = new int[] { 22 }; |
135 | |
136 | protected Statement script; |
137 | |
138 | protected String privateKey; |
139 | |
140 | protected String publicKey; |
141 | |
142 | protected boolean includeMetadata; |
143 | |
144 | protected boolean blockUntilRunning = true; |
145 | |
146 | public int[] getInboundPorts() { |
147 | return inboundPorts; |
148 | } |
149 | |
150 | public Statement getRunScript() { |
151 | return script; |
152 | } |
153 | |
154 | public String getPrivateKey() { |
155 | return privateKey; |
156 | } |
157 | |
158 | public String getPublicKey() { |
159 | return publicKey; |
160 | } |
161 | |
162 | public boolean isIncludeMetadata() { |
163 | return includeMetadata; |
164 | } |
165 | |
166 | public boolean shouldBlockUntilRunning() { |
167 | return blockUntilRunning; |
168 | } |
169 | |
170 | public <T extends TemplateOptions> T as(Class<T> clazz) { |
171 | return clazz.cast(this); |
172 | } |
173 | |
174 | /** |
175 | * This script will be executed as the root user upon system startup. This script gets a |
176 | * prologue, so no #!/bin/bash required, path set up, etc |
177 | * <p/> |
178 | * please use alternative that uses the {@link org.jclouds.scriptbuilder.domain.Statement} object |
179 | * |
180 | * @see org.jclouds.io.Payloads |
181 | */ |
182 | @Deprecated |
183 | public TemplateOptions runScript(byte[] script) { |
184 | return runScript(Statements.exec(new String(checkNotNull(script, "script")))); |
185 | } |
186 | |
187 | /** |
188 | * This script will be executed as the root user upon system startup. This script gets a |
189 | * prologue, so no #!/bin/bash required, path set up, etc |
190 | * |
191 | * @see org.jclouds.io.Payloads |
192 | */ |
193 | public TemplateOptions runScript(Payload script) { |
194 | try { |
195 | return runScript(Statements.exec(Strings2.toStringAndClose(checkNotNull(script, "script").getInput()))); |
196 | } catch (IOException e) { |
197 | Throwables.propagate(e); |
198 | return this; |
199 | } |
200 | } |
201 | |
202 | public TemplateOptions runScript(Statement script) { |
203 | this.script = checkNotNull(script, "script"); |
204 | return this; |
205 | } |
206 | |
207 | /** |
208 | * replaces the rsa ssh key used at login. |
209 | */ |
210 | public TemplateOptions installPrivateKey(String privateKey) { |
211 | checkArgument(checkNotNull(privateKey, "privateKey").startsWith("-----BEGIN RSA PRIVATE KEY-----"), |
212 | "key should start with -----BEGIN RSA PRIVATE KEY-----"); |
213 | this.privateKey = privateKey; |
214 | return this; |
215 | } |
216 | |
217 | /** |
218 | * replaces the rsa ssh key used at login. |
219 | * <p/> |
220 | * please use alternative that uses {@link java.lang.String} |
221 | * |
222 | * @see org.jclouds.io.Payloads |
223 | */ |
224 | @Deprecated |
225 | public TemplateOptions installPrivateKey(Payload privateKey) { |
226 | try { |
227 | return installPrivateKey(Strings2.toStringAndClose(checkNotNull(privateKey, "privateKey").getInput())); |
228 | } catch (IOException e) { |
229 | Throwables.propagate(e); |
230 | return this; |
231 | } |
232 | } |
233 | |
234 | public TemplateOptions dontAuthorizePublicKey() { |
235 | this.publicKey = null; |
236 | return this; |
237 | } |
238 | |
239 | /** |
240 | * authorize an rsa ssh key. |
241 | */ |
242 | public TemplateOptions authorizePublicKey(String publicKey) { |
243 | checkArgument(checkNotNull(publicKey, "publicKey").startsWith("ssh-rsa"), "key should start with ssh-rsa"); |
244 | this.publicKey = publicKey; |
245 | return this; |
246 | } |
247 | |
248 | /** |
249 | * authorize an rsa ssh key. |
250 | * <p/> |
251 | * please use alternative that uses {@link java.lang.String} |
252 | * |
253 | * @see org.jclouds.io.Payloads |
254 | */ |
255 | @Deprecated |
256 | public TemplateOptions authorizePublicKey(Payload publicKey) { |
257 | try { |
258 | return authorizePublicKey(Strings2.toStringAndClose(checkNotNull(publicKey, "publicKey").getInput())); |
259 | } catch (IOException e) { |
260 | Throwables.propagate(e); |
261 | return this; |
262 | } |
263 | } |
264 | |
265 | /** |
266 | * Opens the set of ports to public access. |
267 | */ |
268 | public TemplateOptions inboundPorts(int... ports) { |
269 | for (int port : ports) |
270 | checkArgument(port > 0 && port < 65536, "port must be a positive integer < 65535"); |
271 | this.inboundPorts = ports; |
272 | return this; |
273 | } |
274 | |
275 | public TemplateOptions withMetadata() { |
276 | this.includeMetadata = true; |
277 | return this; |
278 | } |
279 | |
280 | public static class Builder extends org.jclouds.compute.options.RunScriptOptions.Builder { |
281 | |
282 | public static TemplateOptions nameTask(String name) { |
283 | TemplateOptions options = new TemplateOptions(); |
284 | return options.nameTask(name); |
285 | } |
286 | |
287 | public static TemplateOptions overrideCredentialsWith(Credentials credentials) { |
288 | TemplateOptions options = new TemplateOptions(); |
289 | return options.withOverridingCredentials(credentials); |
290 | } |
291 | |
292 | public static TemplateOptions runAsRoot(boolean value) { |
293 | TemplateOptions options = new TemplateOptions(); |
294 | return options.runAsRoot(value); |
295 | } |
296 | |
297 | /** |
298 | * @see TemplateOptions#blockOnPort |
299 | */ |
300 | public static TemplateOptions blockOnPort(int port, int seconds) { |
301 | TemplateOptions options = new TemplateOptions(); |
302 | return options.blockOnPort(port, seconds); |
303 | } |
304 | |
305 | /** |
306 | * @see TemplateOptions#inboundPorts |
307 | */ |
308 | public static TemplateOptions inboundPorts(int... ports) { |
309 | TemplateOptions options = new TemplateOptions(); |
310 | return options.inboundPorts(ports); |
311 | } |
312 | |
313 | /** |
314 | * @see TemplateOptions#blockUntilRunning |
315 | */ |
316 | public static TemplateOptions blockUntilRunning(boolean blockUntilRunning) { |
317 | TemplateOptions options = new TemplateOptions(); |
318 | return options.blockUntilRunning(blockUntilRunning); |
319 | } |
320 | |
321 | /** |
322 | * please use alternative that uses the {@link org.jclouds.io.Payload} object |
323 | * |
324 | * @see org.jclouds.io.Payloads |
325 | * @see #runScript(Payload) |
326 | */ |
327 | @Deprecated |
328 | public static TemplateOptions runScript(byte[] script) { |
329 | TemplateOptions options = new TemplateOptions(); |
330 | return options.runScript(script); |
331 | } |
332 | |
333 | /** |
334 | * @see TemplateOptions#runScript |
335 | * @see org.jclouds.io.Payloads |
336 | */ |
337 | public static TemplateOptions runScript(Payload script) { |
338 | TemplateOptions options = new TemplateOptions(); |
339 | return options.runScript(script); |
340 | } |
341 | |
342 | /** |
343 | * @see TemplateOptions#runScript |
344 | * @see org.jclouds.io.Payloads |
345 | */ |
346 | public static TemplateOptions runScript(Statement script) { |
347 | TemplateOptions options = new TemplateOptions(); |
348 | return options.runScript(script); |
349 | } |
350 | |
351 | /** |
352 | * please use alternative that uses the {@link org.jclouds.io.Payload} object |
353 | * |
354 | * @see org.jclouds.io.Payloads |
355 | * @see #installPrivateKey(Payload) |
356 | */ |
357 | @Deprecated |
358 | public static TemplateOptions installPrivateKey(String rsaKey) { |
359 | TemplateOptions options = new TemplateOptions(); |
360 | return options.installPrivateKey(rsaKey); |
361 | } |
362 | |
363 | /** |
364 | * @see TemplateOptions#installPrivateKey |
365 | * @see org.jclouds.io.Payloads |
366 | */ |
367 | public static TemplateOptions installPrivateKey(Payload rsaKey) { |
368 | TemplateOptions options = new TemplateOptions(); |
369 | return options.installPrivateKey(rsaKey); |
370 | } |
371 | |
372 | /** |
373 | * please use alternative that uses the {@link org.jclouds.io.Payload} object |
374 | * |
375 | * @see org.jclouds.io.Payloads |
376 | * @see #authorizePublicKey(Payload) |
377 | */ |
378 | @Deprecated |
379 | public static TemplateOptions authorizePublicKey(String rsaKey) { |
380 | TemplateOptions options = new TemplateOptions(); |
381 | return options.authorizePublicKey(rsaKey); |
382 | } |
383 | |
384 | /** |
385 | * @see TemplateOptions#authorizePublicKey(Payload) |
386 | * @see org.jclouds.io.Payloads |
387 | */ |
388 | public static TemplateOptions authorizePublicKey(Payload rsaKey) { |
389 | TemplateOptions options = new TemplateOptions(); |
390 | return options.authorizePublicKey(rsaKey); |
391 | } |
392 | |
393 | public static TemplateOptions withDetails() { |
394 | TemplateOptions options = new TemplateOptions(); |
395 | return options.withMetadata(); |
396 | } |
397 | |
398 | public static TemplateOptions blockOnComplete(boolean value) { |
399 | TemplateOptions options = new TemplateOptions(); |
400 | return options.blockOnComplete(value); |
401 | } |
402 | |
403 | } |
404 | |
405 | @Override |
406 | public String toString() { |
407 | return "[inboundPorts=" + Arrays.toString(inboundPorts) + ", privateKey=" + (privateKey != null) + ", publicKey=" |
408 | + (publicKey != null) + ", runScript=" + (script != null) + ", blockUntilRunning=" + blockUntilRunning |
409 | + ", blockOnComplete=" + blockOnComplete + ", port:seconds=" + port + ":" + seconds |
410 | + ", metadata/details: " + includeMetadata + "]"; |
411 | } |
412 | |
413 | public TemplateOptions blockUntilRunning(boolean blockUntilRunning) { |
414 | this.blockUntilRunning = blockUntilRunning; |
415 | if (!blockUntilRunning) |
416 | port = seconds = -1; |
417 | return this; |
418 | } |
419 | |
420 | @Override |
421 | public int hashCode() { |
422 | final int prime = 31; |
423 | int result = 1; |
424 | result = prime * result + (blockUntilRunning ? 1231 : 1237); |
425 | result = prime * result + Arrays.hashCode(inboundPorts); |
426 | result = prime * result + (includeMetadata ? 1231 : 1237); |
427 | result = prime * result + port; |
428 | result = prime * result + ((privateKey == null) ? 0 : privateKey.hashCode()); |
429 | result = prime * result + ((publicKey == null) ? 0 : publicKey.hashCode()); |
430 | result = prime * result + ((script == null) ? 0 : script.hashCode()); |
431 | result = prime * result + seconds; |
432 | return result; |
433 | } |
434 | |
435 | @Override |
436 | public boolean equals(Object obj) { |
437 | if (this == obj) |
438 | return true; |
439 | if (obj == null) |
440 | return false; |
441 | if (getClass() != obj.getClass()) |
442 | return false; |
443 | TemplateOptions other = (TemplateOptions) obj; |
444 | if (blockUntilRunning != other.blockUntilRunning) |
445 | return false; |
446 | if (!Arrays.equals(inboundPorts, other.inboundPorts)) |
447 | return false; |
448 | if (includeMetadata != other.includeMetadata) |
449 | return false; |
450 | if (port != other.port) |
451 | return false; |
452 | if (privateKey == null) { |
453 | if (other.privateKey != null) |
454 | return false; |
455 | } else if (!privateKey.equals(other.privateKey)) |
456 | return false; |
457 | if (publicKey == null) { |
458 | if (other.publicKey != null) |
459 | return false; |
460 | } else if (!publicKey.equals(other.publicKey)) |
461 | return false; |
462 | if (script == null) { |
463 | if (other.script != null) |
464 | return false; |
465 | } else if (!script.equals(other.script)) |
466 | return false; |
467 | if (seconds != other.seconds) |
468 | return false; |
469 | return true; |
470 | } |
471 | |
472 | @Override |
473 | public TemplateOptions blockOnPort(int port, int seconds) { |
474 | return TemplateOptions.class.cast(super.blockOnPort(port, seconds)); |
475 | } |
476 | |
477 | @Override |
478 | public TemplateOptions nameTask(String name) { |
479 | return TemplateOptions.class.cast(super.nameTask(name)); |
480 | } |
481 | |
482 | @Override |
483 | public TemplateOptions runAsRoot(boolean runAsRoot) { |
484 | return TemplateOptions.class.cast(super.runAsRoot(runAsRoot)); |
485 | } |
486 | |
487 | @Override |
488 | public TemplateOptions withOverridingCredentials(Credentials overridingCredentials) { |
489 | return TemplateOptions.class.cast(super.withOverridingCredentials(overridingCredentials)); |
490 | } |
491 | |
492 | @Override |
493 | public TemplateOptions blockOnComplete(boolean blockOnComplete) { |
494 | return TemplateOptions.class.cast(super.blockOnComplete(blockOnComplete)); |
495 | } |
496 | } |