View Javadoc

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  import java.util.Set;
27  
28  import org.jclouds.domain.Credentials;
29  import org.jclouds.io.Payload;
30  import org.jclouds.scriptbuilder.domain.Statement;
31  import org.jclouds.scriptbuilder.domain.Statements;
32  import org.jclouds.util.Strings2;
33  
34  import com.google.common.base.Throwables;
35  import com.google.common.collect.ImmutableSet;
36  
37  /**
38   * Contains options supported in the {@code ComputeService#runNodesWithTag} operation. <h2>
39   * Usage</h2> The recommended way to instantiate a TemplateOptions object is to statically import
40   * TemplateOptions.* and invoke a static creation method followed by an instance mutator (if
41   * needed):
42   * <p/>
43   * <code>
44   * import static org.jclouds.compute.options.TemplateOptions.Builder.*;
45   * <p/>
46   * ComputeService client = // get connection
47   * templateBuilder.options(inboundPorts(22, 80, 8080, 443));
48   * Set<? extends NodeMetadata> set = client.runNodesWithTag(tag, 2, templateBuilder.build());
49   * <code>
50   * 
51   * @author Adrian Cole
52   */
53  public class TemplateOptions extends RunScriptOptions implements Cloneable {
54  
55     @Override
56     public TemplateOptions clone() {
57        TemplateOptions options = new TemplateOptions();
58        copyTo(options);
59        return options;
60     }
61  
62     public void copyTo(TemplateOptions to) {
63        if (!Arrays.equals(to.getInboundPorts(), this.getInboundPorts()))
64           to.inboundPorts(this.getInboundPorts());
65        if (this.getRunScript() != null)
66           to.runScript(this.getRunScript());
67        if (this.getPrivateKey() != null)
68           to.installPrivateKey(this.getPrivateKey());
69        if (this.getPublicKey() != null)
70           to.authorizePublicKey(this.getPublicKey());
71        if (this.getPort() != -1)
72           to.blockOnPort(this.getPort(), this.getSeconds());
73        if (this.isIncludeMetadata())
74           to.withMetadata();
75        if (this.getTags().size() > 0)
76           to.tags(getTags());
77        if (!this.shouldBlockUntilRunning())
78           to.blockUntilRunning(false);
79        if (!this.shouldBlockOnComplete())
80           to.blockOnComplete(false);
81        if (this.getOverridingCredentials() != null)
82           to.overrideCredentialsWith(this.getOverridingCredentials());
83        if (this.getTaskName() != null)
84           to.nameTask(this.getTaskName());
85     }
86  
87     public static final TemplateOptions NONE = new ImmutableTemplateOptions(new TemplateOptions());
88  
89     public static class ImmutableTemplateOptions extends TemplateOptions {
90        private final TemplateOptions delegate;
91  
92        @Override
93        public TemplateOptions clone() {
94           return delegate.clone();
95        }
96  
97        @Override
98        public String getTaskName() {
99           return delegate.getTaskName();
100       }
101 
102       @Override
103       public int getPort() {
104          return delegate.getPort();
105       }
106 
107       @Override
108       public int getSeconds() {
109          return delegate.getSeconds();
110       }
111 
112       @Override
113       public Credentials getOverridingCredentials() {
114          return delegate.getOverridingCredentials();
115       }
116 
117       @Override
118       public boolean shouldRunAsRoot() {
119          return delegate.shouldRunAsRoot();
120       }
121 
122       @Override
123       public boolean shouldBlockOnComplete() {
124          return delegate.shouldBlockOnComplete();
125       }
126 
127       @Override
128       public boolean shouldWrapInInitScript() {
129          return delegate.shouldWrapInInitScript();
130       }
131 
132       @Override
133       public void copyTo(TemplateOptions to) {
134          delegate.copyTo(to);
135       }
136 
137       public ImmutableTemplateOptions(TemplateOptions delegate) {
138          this.delegate = delegate;
139       }
140 
141       @Override
142       public String toString() {
143          return delegate.toString();
144       }
145 
146       @Override
147       public TemplateOptions runScript(Payload script) {
148          throw new IllegalArgumentException("script is immutable");
149       }
150 
151       @Override
152       public TemplateOptions runScript(Statement script) {
153          throw new IllegalArgumentException("script is immutable");
154       }
155 
156       @Override
157       public TemplateOptions installPrivateKey(Payload privateKey) {
158          throw new IllegalArgumentException("privateKey is immutable");
159       }
160 
161       @Override
162       public TemplateOptions dontAuthorizePublicKey() {
163          throw new IllegalArgumentException("public key is immutable");
164       }
165 
166       @Override
167       @Deprecated
168       public TemplateOptions authorizePublicKey(Payload publicKey) {
169          throw new IllegalArgumentException("public key is immutable");
170       }
171 
172       @Override
173       public TemplateOptions blockOnPort(int port, int seconds) {
174          throw new IllegalArgumentException("ports are immutable");
175       }
176 
177       @Override
178       public TemplateOptions nameTask(String name) {
179          throw new IllegalArgumentException("task name is immutable");
180       }
181 
182       @Override
183       public TemplateOptions runAsRoot(boolean runAsRoot) {
184          throw new IllegalArgumentException("runAsRoot is immutable");
185       }
186 
187       @Override
188       public TemplateOptions overrideCredentialsWith(Credentials overridingCredentials) {
189          throw new IllegalArgumentException("credentials are immutable");
190       }
191 
192       @Override
193       public TemplateOptions overrideLoginUserWith(String loginUser) {
194          throw new IllegalArgumentException("credentials are immutable");
195       }
196 
197       @Override
198       public TemplateOptions overrideLoginCredentialWith(String loginCredential) {
199          throw new IllegalArgumentException("credentials are immutable");
200       }
201 
202       @Override
203       public TemplateOptions wrapInInitScript(boolean wrapInInitScript) {
204          throw new IllegalArgumentException("wrapInInitScript is immutable");
205       }
206 
207       @Override
208       public TemplateOptions blockOnComplete(boolean blockOnComplete) {
209          throw new IllegalArgumentException("blockOnComplete is immutable");
210       }
211 
212       @Override
213       public <T extends TemplateOptions> T as(Class<T> clazz) {
214          return delegate.as(clazz);
215       }
216 
217       @Override
218       public TemplateOptions authorizePublicKey(String publicKey) {
219          throw new IllegalArgumentException("publicKey is immutable");
220       }
221 
222       @Override
223       public TemplateOptions blockUntilRunning(boolean blockUntilRunning) {
224          throw new IllegalArgumentException("blockUntilRunning is immutable");
225       }
226 
227       @Override
228       public int[] getInboundPorts() {
229          return delegate.getInboundPorts();
230       }
231 
232       @Override
233       public String getPrivateKey() {
234          return delegate.getPrivateKey();
235       }
236 
237       @Override
238       public String getPublicKey() {
239          return delegate.getPublicKey();
240       }
241 
242       @Override
243       public Statement getRunScript() {
244          return delegate.getRunScript();
245       }
246 
247       @Override
248       public boolean shouldBlockUntilRunning() {
249          return delegate.shouldBlockUntilRunning();
250       }
251 
252       @Override
253       public TemplateOptions inboundPorts(int... ports) {
254          throw new IllegalArgumentException("ports are immutable");
255       }
256 
257       @Override
258       public TemplateOptions installPrivateKey(String privateKey) {
259          throw new IllegalArgumentException("privateKey is immutable");
260       }
261 
262       @Override
263       public boolean isIncludeMetadata() {
264          return delegate.isIncludeMetadata();
265       }
266 
267       @Override
268       public TemplateOptions runScript(byte[] script) {
269          throw new IllegalArgumentException("script is immutable");
270       }
271 
272       @Override
273       public TemplateOptions withMetadata() {
274          throw new IllegalArgumentException("metadata is immutable");
275       }
276 
277    }
278 
279    protected int[] inboundPorts = new int[] { 22 };
280 
281    protected Statement script;
282 
283    protected Set<String> tags = ImmutableSet.of();
284 
285    protected String privateKey;
286 
287    protected String publicKey;
288 
289    protected boolean includeMetadata;
290 
291    protected boolean blockUntilRunning = true;
292 
293    public int[] getInboundPorts() {
294       return inboundPorts;
295    }
296 
297    public Statement getRunScript() {
298       return script;
299    }
300 
301    public Set<String> getTags() {
302       return tags;
303    }
304 
305    public String getPrivateKey() {
306       return privateKey;
307    }
308 
309    public String getPublicKey() {
310       return publicKey;
311    }
312 
313    public boolean isIncludeMetadata() {
314       return includeMetadata;
315    }
316 
317    public boolean shouldBlockUntilRunning() {
318       return blockUntilRunning;
319    }
320 
321    public <T extends TemplateOptions> T as(Class<T> clazz) {
322       return clazz.cast(this);
323    }
324 
325    /**
326     * This script will be executed as the root user upon system startup. This script gets a
327     * prologue, so no #!/bin/bash required, path set up, etc
328     * <p/>
329     * please use alternative that uses the {@link org.jclouds.scriptbuilder.domain.Statement} object
330     * 
331     * @see org.jclouds.io.Payloads
332     */
333    @Deprecated
334    public TemplateOptions runScript(byte[] script) {
335       return runScript(Statements.exec(new String(checkNotNull(script, "script"))));
336    }
337 
338    /**
339     * This script will be executed as the root user upon system startup. This script gets a
340     * prologue, so no #!/bin/bash required, path set up, etc
341     * 
342     * @see org.jclouds.io.Payloads
343     */
344    public TemplateOptions runScript(Payload script) {
345       try {
346          return runScript(Statements.exec(Strings2.toStringAndClose(checkNotNull(script, "script").getInput())));
347       } catch (IOException e) {
348          Throwables.propagate(e);
349          return this;
350       }
351    }
352 
353    public TemplateOptions runScript(Statement script) {
354       this.script = checkNotNull(script, "script");
355       return this;
356    }
357 
358    /**
359     * replaces the rsa ssh key used at login.
360     */
361    public TemplateOptions installPrivateKey(String privateKey) {
362       checkArgument(checkNotNull(privateKey, "privateKey").startsWith("-----BEGIN RSA PRIVATE KEY-----"),
363                "key should start with -----BEGIN RSA PRIVATE KEY-----");
364       this.privateKey = privateKey;
365       return this;
366    }
367 
368    /**
369     * replaces the rsa ssh key used at login.
370     * <p/>
371     * please use alternative that uses {@link java.lang.String}
372     * 
373     * @see org.jclouds.io.Payloads
374     */
375    @Deprecated
376    public TemplateOptions installPrivateKey(Payload privateKey) {
377       try {
378          return installPrivateKey(Strings2.toStringAndClose(checkNotNull(privateKey, "privateKey").getInput()));
379       } catch (IOException e) {
380          Throwables.propagate(e);
381          return this;
382       }
383    }
384 
385    public TemplateOptions dontAuthorizePublicKey() {
386       this.publicKey = null;
387       return this;
388    }
389 
390    /**
391     * authorize an rsa ssh key.
392     */
393    public TemplateOptions authorizePublicKey(String publicKey) {
394       checkArgument(checkNotNull(publicKey, "publicKey").startsWith("ssh-rsa"), "key should start with ssh-rsa");
395       this.publicKey = publicKey;
396       return this;
397    }
398 
399    /**
400     * authorize an rsa ssh key.
401     * <p/>
402     * please use alternative that uses {@link java.lang.String}
403     * 
404     * @see org.jclouds.io.Payloads
405     */
406    @Deprecated
407    public TemplateOptions authorizePublicKey(Payload publicKey) {
408       try {
409          return authorizePublicKey(Strings2.toStringAndClose(checkNotNull(publicKey, "publicKey").getInput()));
410       } catch (IOException e) {
411          Throwables.propagate(e);
412          return this;
413       }
414    }
415 
416    /**
417     * assigns tags to the created nodes
418     */
419    public TemplateOptions tags(Iterable<String> tags) {
420       this.tags = ImmutableSet.copyOf(checkNotNull(tags, "tags"));
421       return this;
422    }
423 
424    /**
425     * Opens the set of ports to public access.
426     */
427    public TemplateOptions inboundPorts(int... ports) {
428       for (int port : ports)
429          checkArgument(port > 0 && port < 65536, "port must be a positive integer < 65535");
430       this.inboundPorts = ports;
431       return this;
432    }
433 
434    public TemplateOptions withMetadata() {
435       this.includeMetadata = true;
436       return this;
437    }
438 
439    public static class Builder extends org.jclouds.compute.options.RunScriptOptions.Builder {
440 
441       public static TemplateOptions nameTask(String name) {
442          TemplateOptions options = new TemplateOptions();
443          return options.nameTask(name);
444       }
445 
446       public static TemplateOptions overrideLoginUserWith(String user) {
447          TemplateOptions options = new TemplateOptions();
448          return options.overrideLoginUserWith(user);
449       }
450 
451       public static TemplateOptions overrideLoginCredentialWith(String credential) {
452          TemplateOptions options = new TemplateOptions();
453          return options.overrideLoginCredentialWith(credential);
454       }
455 
456       public static TemplateOptions overrideCredentialsWith(Credentials credentials) {
457          TemplateOptions options = new TemplateOptions();
458          return options.overrideCredentialsWith(credentials);
459       }
460 
461       public static TemplateOptions runAsRoot(boolean value) {
462          TemplateOptions options = new TemplateOptions();
463          return options.runAsRoot(value);
464       }
465 
466       /**
467        * @see TemplateOptions#blockOnPort
468        */
469       public static TemplateOptions blockOnPort(int port, int seconds) {
470          TemplateOptions options = new TemplateOptions();
471          return options.blockOnPort(port, seconds);
472       }
473 
474       /**
475        * @see TemplateOptions#inboundPorts
476        */
477       public static TemplateOptions inboundPorts(int... ports) {
478          TemplateOptions options = new TemplateOptions();
479          return options.inboundPorts(ports);
480       }
481 
482       /**
483        * @see TemplateOptions#tags
484        */
485       public static TemplateOptions tags(Iterable<String> tags) {
486          TemplateOptions options = new TemplateOptions();
487          return options.tags(tags);
488       }
489 
490       /**
491        * @see TemplateOptions#blockUntilRunning
492        */
493       public static TemplateOptions blockUntilRunning(boolean blockUntilRunning) {
494          TemplateOptions options = new TemplateOptions();
495          return options.blockUntilRunning(blockUntilRunning);
496       }
497 
498       /**
499        * please use alternative that uses the {@link org.jclouds.io.Payload} object
500        * 
501        * @see org.jclouds.io.Payloads
502        * @see #runScript(Payload)
503        */
504       @Deprecated
505       public static TemplateOptions runScript(byte[] script) {
506          TemplateOptions options = new TemplateOptions();
507          return options.runScript(script);
508       }
509 
510       /**
511        * @see TemplateOptions#runScript
512        * @see org.jclouds.io.Payloads
513        */
514       public static TemplateOptions runScript(Payload script) {
515          TemplateOptions options = new TemplateOptions();
516          return options.runScript(script);
517       }
518 
519       /**
520        * @see TemplateOptions#runScript
521        * @see org.jclouds.io.Payloads
522        */
523       public static TemplateOptions runScript(Statement script) {
524          TemplateOptions options = new TemplateOptions();
525          return options.runScript(script);
526       }
527 
528       /**
529        * please use alternative that uses the {@link org.jclouds.io.Payload} object
530        * 
531        * @see org.jclouds.io.Payloads
532        * @see #installPrivateKey(Payload)
533        */
534       @Deprecated
535       public static TemplateOptions installPrivateKey(String rsaKey) {
536          TemplateOptions options = new TemplateOptions();
537          return options.installPrivateKey(rsaKey);
538       }
539 
540       /**
541        * @see TemplateOptions#installPrivateKey
542        * @see org.jclouds.io.Payloads
543        */
544       public static TemplateOptions installPrivateKey(Payload rsaKey) {
545          TemplateOptions options = new TemplateOptions();
546          return options.installPrivateKey(rsaKey);
547       }
548 
549       /**
550        * please use alternative that uses the {@link org.jclouds.io.Payload} object
551        * 
552        * @see org.jclouds.io.Payloads
553        * @see #authorizePublicKey(Payload)
554        */
555       @Deprecated
556       public static TemplateOptions authorizePublicKey(String rsaKey) {
557          TemplateOptions options = new TemplateOptions();
558          return options.authorizePublicKey(rsaKey);
559       }
560 
561       /**
562        * @see TemplateOptions#authorizePublicKey(Payload)
563        * @see org.jclouds.io.Payloads
564        */
565       public static TemplateOptions authorizePublicKey(Payload rsaKey) {
566          TemplateOptions options = new TemplateOptions();
567          return options.authorizePublicKey(rsaKey);
568       }
569 
570       public static TemplateOptions withDetails() {
571          TemplateOptions options = new TemplateOptions();
572          return options.withMetadata();
573       }
574 
575       public static TemplateOptions blockOnComplete(boolean value) {
576          TemplateOptions options = new TemplateOptions();
577          return options.blockOnComplete(value);
578       }
579 
580    }
581 
582    @Override
583    public String toString() {
584       return "[inboundPorts=" + Arrays.toString(inboundPorts) + ", privateKey=" + (privateKey != null) + ", publicKey="
585                + (publicKey != null) + ", runScript=" + (script != null) + ", blockUntilRunning=" + blockUntilRunning
586                + ", blockOnComplete=" + blockOnComplete + ", port:seconds=" + port + ":" + seconds
587                + ", metadata/details: " + includeMetadata + "]";
588    }
589 
590    public TemplateOptions blockUntilRunning(boolean blockUntilRunning) {
591       this.blockUntilRunning = blockUntilRunning;
592       if (!blockUntilRunning)
593          port = seconds = -1;
594       return this;
595    }
596 
597    @Override
598    public int hashCode() {
599       final int prime = 31;
600       int result = 1;
601       result = prime * result + (blockUntilRunning ? 1231 : 1237);
602       result = prime * result + Arrays.hashCode(inboundPorts);
603       result = prime * result + (includeMetadata ? 1231 : 1237);
604       result = prime * result + port;
605       result = prime * result + ((privateKey == null) ? 0 : privateKey.hashCode());
606       result = prime * result + ((publicKey == null) ? 0 : publicKey.hashCode());
607       result = prime * result + ((script == null) ? 0 : script.hashCode());
608       result = prime * result + seconds;
609       return result;
610    }
611 
612    @Override
613    public boolean equals(Object obj) {
614       if (this == obj)
615          return true;
616       if (obj == null)
617          return false;
618       if (getClass() != obj.getClass())
619          return false;
620       TemplateOptions other = (TemplateOptions) obj;
621       if (blockUntilRunning != other.blockUntilRunning)
622          return false;
623       if (!Arrays.equals(inboundPorts, other.inboundPorts))
624          return false;
625       if (includeMetadata != other.includeMetadata)
626          return false;
627       if (port != other.port)
628          return false;
629       if (privateKey == null) {
630          if (other.privateKey != null)
631             return false;
632       } else if (!privateKey.equals(other.privateKey))
633          return false;
634       if (publicKey == null) {
635          if (other.publicKey != null)
636             return false;
637       } else if (!publicKey.equals(other.publicKey))
638          return false;
639       if (script == null) {
640          if (other.script != null)
641             return false;
642       } else if (!script.equals(other.script))
643          return false;
644       if (seconds != other.seconds)
645          return false;
646       return true;
647    }
648 
649    @Override
650    public TemplateOptions blockOnPort(int port, int seconds) {
651       return TemplateOptions.class.cast(super.blockOnPort(port, seconds));
652    }
653 
654    @Override
655    public TemplateOptions nameTask(String name) {
656       return TemplateOptions.class.cast(super.nameTask(name));
657    }
658 
659    @Override
660    public TemplateOptions runAsRoot(boolean runAsRoot) {
661       return TemplateOptions.class.cast(super.runAsRoot(runAsRoot));
662    }
663 
664    @Override
665    public TemplateOptions overrideCredentialsWith(Credentials overridingCredentials) {
666       return TemplateOptions.class.cast(super.overrideCredentialsWith(overridingCredentials));
667    }
668 
669    @Override
670    public TemplateOptions overrideLoginUserWith(String loginUser) {
671       return TemplateOptions.class.cast(super.overrideLoginUserWith(loginUser));
672    }
673 
674    @Override
675    public TemplateOptions overrideLoginCredentialWith(String loginCredential) {
676       return TemplateOptions.class.cast(super.overrideLoginCredentialWith(loginCredential));
677    }
678 
679    @Override
680    public TemplateOptions wrapInInitScript(boolean wrapInInitScript) {
681       return TemplateOptions.class.cast(super.wrapInInitScript(wrapInInitScript));
682    }
683 
684    @Override
685    public TemplateOptions blockOnComplete(boolean blockOnComplete) {
686       return TemplateOptions.class.cast(super.blockOnComplete(blockOnComplete));
687    }
688 }