diff --git a/pom.xml b/pom.xml
index ef51b79df9..ba4f5d27f6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -117,12 +117,12 @@ OF THE POSSIBILITY OF SUCH DAMAGE.
com.amazonaws
aws-java-sdk-ec2
- 1.12.658
+ 1.12.659
com.amazonaws
aws-java-sdk-core
- 1.12.658
+ 1.12.659
com.jcabi.incubator
diff --git a/src/main/java/com/rultor/agents/Agents.java b/src/main/java/com/rultor/agents/Agents.java
index c5cc1e151f..95e9ebe501 100644
--- a/src/main/java/com/rultor/agents/Agents.java
+++ b/src/main/java/com/rultor/agents/Agents.java
@@ -270,7 +270,10 @@ public Agent agent(final Talk talk, final Profile profile)
Manifests.read("Rultor-EC2Secret")
),
Manifests.read("Rultor-EC2Image")
- )
+ ),
+ profile,
+ Agents.PORT, Agents.LOGIN,
+ Agents.priv()
),
new RegistersShell(
profile,
diff --git a/src/main/java/com/rultor/agents/aws/AwsEc2Instance.java b/src/main/java/com/rultor/agents/aws/AwsEc2Instance.java
index 76c4cf369e..85c07acae7 100644
--- a/src/main/java/com/rultor/agents/aws/AwsEc2Instance.java
+++ b/src/main/java/com/rultor/agents/aws/AwsEc2Instance.java
@@ -33,6 +33,7 @@
import com.amazonaws.services.ec2.model.CreateTagsRequest;
import com.amazonaws.services.ec2.model.DryRunResult;
import com.amazonaws.services.ec2.model.DryRunSupportedRequest;
+import com.amazonaws.services.ec2.model.Instance;
import com.amazonaws.services.ec2.model.StopInstancesRequest;
import com.amazonaws.services.ec2.model.Tag;
import com.jcabi.aspects.Immutable;
@@ -48,7 +49,8 @@
@ToString
@SuppressWarnings({"PMD.ShortMethodName",
"PMD.ConstructorOnlyInitializesOrCallOtherConstructors",
- "PMD.AvoidFieldNameMatchingMethodName"
+ "PMD.AvoidFieldNameMatchingMethodName",
+ "PMD.OnlyOneConstructorShouldDoInitialization"
})
public final class AwsEc2Instance {
/**
@@ -56,11 +58,32 @@ public final class AwsEc2Instance {
*/
private final transient AwsEc2 api;
+ /**
+ * AWS Instance.
+ */
+ private final Instance instance;
+
/**
* AWS Instance id.
*/
private final String id;
+ /**
+ * Ctor.
+ * @param api AwsEc2 api client
+ * @param inst Instance
+ */
+ public AwsEc2Instance(final AwsEc2 api, final Instance inst) {
+ if (inst == null) {
+ throw new IllegalArgumentException(
+ "Instance id is mandatory"
+ );
+ }
+ this.api = api;
+ this.instance = inst;
+ this.id = this.instance.getInstanceId();
+ }
+
/**
* Ctor.
* @param api AwsEc2 api client
@@ -74,6 +97,7 @@ public AwsEc2Instance(final AwsEc2 api, final String id) {
}
this.api = api;
this.id = id;
+ this.instance = new Instance().withInstanceId(id);
}
/**
@@ -82,7 +106,7 @@ public AwsEc2Instance(final AwsEc2 api, final String id) {
public void stop() {
final DryRunSupportedRequest draft = () -> {
final StopInstancesRequest request = new StopInstancesRequest()
- .withInstanceIds(this.id);
+ .withInstanceIds(this.instance.getInstanceId());
return request.getDryRunRequest();
};
final AmazonEC2 client = this.api.aws();
@@ -126,4 +150,13 @@ public AwsEc2Instance tag(final String key, final String tag) {
public String id() {
return this.id;
}
+
+ /**
+ * Instance Ip.
+ * @return Instance Ipv6 address
+ * @checkstyle MethodNameCheck (3 lines)
+ */
+ public String ipv6() {
+ return this.instance.getIpv6Address();
+ }
}
diff --git a/src/main/java/com/rultor/agents/aws/StartsInstance.java b/src/main/java/com/rultor/agents/aws/StartsInstance.java
index 56bd4cea6c..fd88321b8b 100644
--- a/src/main/java/com/rultor/agents/aws/StartsInstance.java
+++ b/src/main/java/com/rultor/agents/aws/StartsInstance.java
@@ -30,8 +30,11 @@
package com.rultor.agents.aws;
import com.jcabi.aspects.Immutable;
+import com.jcabi.log.Logger;
import com.jcabi.xml.XML;
import com.rultor.agents.AbstractAgent;
+import com.rultor.agents.shells.PfShell;
+import com.rultor.spi.Profile;
import java.io.IOException;
import lombok.ToString;
import org.xembly.Directive;
@@ -44,6 +47,7 @@
*/
@Immutable
@ToString
+@SuppressWarnings("PMD.ConstructorOnlyInitializesOrCallOtherConstructors")
public final class StartsInstance extends AbstractAgent {
/**
@@ -56,34 +60,95 @@ public final class StartsInstance extends AbstractAgent {
*/
private final String tag;
+ /**
+ * Shell in profile.
+ */
+ private final transient PfShell shell;
+
/**
* Ctor.
* @param image Instance image to run
+ * @param profile Profile
+ * @param port Default Port of server
+ * @param user Default Login
+ * @param key Default Private SSH key
+ * @checkstyle ParameterNumberCheck (6 lines)
*/
- public StartsInstance(final AwsEc2Image image) {
- this(image, "rultor");
+ public StartsInstance(final AwsEc2Image image, final Profile profile,
+ final int port, final String user, final String key) {
+ this(image, "rultor", profile, port, user, key);
}
/**
* Ctor.
* @param image Instance image to run
* @param tag Name tag value
+ * @param profile Profile
+ * @param port Default Port of server
+ * @param user Default Login
+ * @param key Default Private SSH key
+ * @checkstyle ParameterNumberCheck (6 lines)
*/
- public StartsInstance(final AwsEc2Image image, final String tag) {
+ public StartsInstance(final AwsEc2Image image, final String tag,
+ final Profile profile, final int port,
+ final String user, final String key) {
super("/talk[daemon and not(shell)]");
+ if (user.isEmpty()) {
+ throw new IllegalArgumentException(
+ "User name is mandatory"
+ );
+ }
+ if (key.isEmpty()) {
+ throw new IllegalArgumentException(
+ "SSH key is mandatory"
+ );
+ }
this.image = image;
this.tag = tag;
+ this.shell = new PfShell(profile, "", port, user, key);
}
@Override
public Iterable process(final XML xml) throws IOException {
+ final String hash = xml.xpath("/talk/daemon/@id").get(0);
final Directives dirs = new Directives();
- final AwsEc2Instance inst = this.image.run();
- if (!this.tag.isEmpty()) {
- inst.tag("Name", this.tag);
+ try {
+ final String login = this.shell.login();
+ if (login.isEmpty()) {
+ throw new Profile.ConfigException(
+ "SSH login is empty, it's a mistake"
+ );
+ }
+ final String key = this.shell.key();
+ if (key.isEmpty()) {
+ throw new Profile.ConfigException(
+ "SSH key is empty, it's a mistake"
+ );
+ }
+ final AwsEc2Instance inst = this.image.run();
+ if (!this.tag.isEmpty()) {
+ inst.tag("Name", this.tag);
+ }
+ Logger.info(
+ this, "EC2 instance %s on %s started in %s",
+ inst.id(), inst.ipv6(),
+ xml.xpath("/talk/@name").get(0)
+ );
+ dirs.xpath("/talk").add("ec2")
+ .attr("id", inst.id());
+ dirs.xpath("/talk").add("shell")
+ .attr("id", hash)
+ .add("host").set(inst.ipv6()).up()
+ .add("port").set(Integer.toString(this.shell.port())).up()
+ .add("login").set(login).up()
+ .add("key").set(key);
+ } catch (final Profile.ConfigException ex) {
+ dirs.xpath("/talk/daemon/script").set(
+ String.format(
+ "Failed to read profile: %s", ex.getLocalizedMessage()
+ )
+ );
}
- dirs.xpath("/talk").add("ec2")
- .attr("id", inst.id());
return dirs;
}
}