mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-09-24 14:38:45 +00:00
bug4811: a compilable version with massively refactored procedure support, using the Builder pattern
This commit is contained in:
+15
-40
@@ -5,9 +5,6 @@ import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Collections;
|
||||
import java.util.Optional;
|
||||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
@@ -15,30 +12,22 @@ import java.util.UUID;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.jcraft.jsch.JSchException;
|
||||
import com.jcraft.jsch.SftpException;
|
||||
import com.sap.sailing.landscape.SailingAnalyticsHost;
|
||||
import com.sap.sailing.landscape.SailingAnalyticsMaster;
|
||||
import com.sap.sailing.landscape.SailingAnalyticsMetrics;
|
||||
import com.sap.sailing.landscape.SailingAnalyticsReplica;
|
||||
import com.sap.sailing.landscape.SailingReleaseRepository;
|
||||
import com.sap.sailing.landscape.procedures.StartSailingAnalyticsMaster;
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.landscape.Release;
|
||||
import com.sap.sse.landscape.application.ApplicationProcess;
|
||||
import com.sap.sse.landscape.application.impl.ApplicationProcessImpl;
|
||||
import com.sap.sse.landscape.aws.AwsInstance;
|
||||
import com.sap.sse.landscape.aws.AwsLandscape;
|
||||
import com.sap.sse.landscape.aws.Tags;
|
||||
import com.sap.sse.landscape.aws.impl.AwsRegion;
|
||||
import com.sap.sse.landscape.aws.orchestration.CreateDNSBasedLoadBalancerMapping;
|
||||
import com.sap.sse.landscape.aws.orchestration.StartAwsHost;
|
||||
|
||||
import software.amazon.awssdk.regions.Region;
|
||||
import software.amazon.awssdk.services.ec2.model.Instance;
|
||||
import software.amazon.awssdk.services.ec2.model.InstanceType;
|
||||
import software.amazon.awssdk.services.ec2.model.Tag;
|
||||
import software.amazon.awssdk.services.route53.model.RRType;
|
||||
|
||||
/**
|
||||
* Tests for the AWS SDK landscape wrapper in bundle {@code com.sap.sse.landscape.aws}. To run these tests
|
||||
@@ -61,20 +50,22 @@ public class TestProcedures {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConnectivity() throws JSchException, IOException, SftpException, NumberFormatException, InterruptedException, URISyntaxException {
|
||||
final String TARGET_GROUP_NAME_PREFIX = "S-test-";
|
||||
final String hostedZoneName = "wiesen-weg.de";
|
||||
final String hostname = "S-test-"+new Random().nextInt()+"."+hostedZoneName;
|
||||
public void testConnectivity() throws Exception {
|
||||
final String serverName = "test"+new Random().nextInt();
|
||||
final String keyName = "MyKey-"+UUID.randomUUID();
|
||||
final Release release = SailingReleaseRepository.INSTANCE.getLatestMasterRelease();
|
||||
final StartAwsHost<String, SailingAnalyticsMetrics, SailingAnalyticsMaster<String>, SailingAnalyticsReplica<String>, SailingAnalyticsHost<String>> startSailingAnalyticsMaster = new StartSailingAnalyticsMaster<String>(
|
||||
hostname, region, landscape, InstanceType.T2_SMALL, keyName, Optional.of(release), /* databaseConfiguration */ null,
|
||||
/* rabbitConfiguration */ null, /* replicationConfiguration */ null, "axel.uhl@sap.com", Optional.empty());
|
||||
final StartSailingAnalyticsMaster.Builder<String> builder = StartSailingAnalyticsMaster.builder();
|
||||
final StartSailingAnalyticsMaster<String> startSailingAnalyticsMaster = builder
|
||||
.setServerName(serverName)
|
||||
.setLandscape(landscape)
|
||||
.setRegion(region)
|
||||
.setInstanceType(InstanceType.T3_SMALL)
|
||||
.setKeyName(keyName)
|
||||
.setCommaSeparatedEmailAddressesToNotifyOfStartup("axel.uhl@sap.com")
|
||||
.setTags(Optional.of(Tags.with("Hello", "World")))
|
||||
.setOptionalTimeout(optionalTimeout)
|
||||
.build();
|
||||
startSailingAnalyticsMaster.run();
|
||||
final AwsInstance<String, SailingAnalyticsMetrics> host = landscape.launchHost(landscape
|
||||
.getImage(region, "ami-01b4b27a5699e33e6"),
|
||||
InstanceType.T3_SMALL, landscape.getAvailabilityZoneByName(region, "eu-west-2b"), keyName, Collections.singleton(()->"sg-0b2afd48960251280"),
|
||||
Optional.of(Tags.with("Name", "MyHost").and("Hello", "World")));
|
||||
final SailingAnalyticsHost<String> host = startSailingAnalyticsMaster.getHost();
|
||||
try {
|
||||
assertNotNull(host);
|
||||
final Instance instance = landscape.getInstance(host.getInstanceId(), region);
|
||||
@@ -94,24 +85,8 @@ public class TestProcedures {
|
||||
final ApplicationProcess<String, SailingAnalyticsMetrics, SailingAnalyticsMaster<String>, SailingAnalyticsReplica<String>> process = new ApplicationProcessImpl<>(8888, host, "/home/sailing/servers/server");
|
||||
final String envSh = process.getEnvSh(optionalTimeout);
|
||||
assertFalse(envSh.isEmpty());
|
||||
assertTrue(envSh.contains("SERVER_NAME="));
|
||||
assertTrue(envSh.contains("SERVER_NAME="+serverName));
|
||||
assertEquals(14888, process.getTelnetPortToOSGiConsole(optionalTimeout));
|
||||
final AwsLandscape<String, SailingAnalyticsMetrics, SailingAnalyticsMaster<String>, SailingAnalyticsReplica<String>> castLandscape = (AwsLandscape<String, SailingAnalyticsMetrics, SailingAnalyticsMaster<String>, SailingAnalyticsReplica<String>>) landscape;
|
||||
final CreateDNSBasedLoadBalancerMapping<String, SailingAnalyticsMetrics, SailingAnalyticsMaster<String>, SailingAnalyticsReplica<String>, AwsInstance<String, SailingAnalyticsMetrics>> createDNSBasedLoadBalancerMappingProcedure =
|
||||
new CreateDNSBasedLoadBalancerMapping<String, SailingAnalyticsMetrics, SailingAnalyticsMaster<String>, SailingAnalyticsReplica<String>, AwsInstance<String, SailingAnalyticsMetrics>>(
|
||||
process, hostname, TARGET_GROUP_NAME_PREFIX, castLandscape, optionalTimeout);
|
||||
final String wiesenWegId = landscape.getDNSHostedZoneId(hostedZoneName);
|
||||
try {
|
||||
createDNSBasedLoadBalancerMappingProcedure.run();
|
||||
assertNotNull(createDNSBasedLoadBalancerMappingProcedure.getLoadBalancerUsed());
|
||||
assertNotNull(createDNSBasedLoadBalancerMappingProcedure.getMasterTargetGroupCreated());
|
||||
assertEquals(TARGET_GROUP_NAME_PREFIX+process.getServerName(optionalTimeout), createDNSBasedLoadBalancerMappingProcedure.getPublicTargetGroupCreated().getName());
|
||||
} finally {
|
||||
if (createDNSBasedLoadBalancerMappingProcedure.getLoadBalancerUsed() != null) {
|
||||
createDNSBasedLoadBalancerMappingProcedure.getLoadBalancerUsed().delete();
|
||||
landscape.removeDNSRecord(wiesenWegId, hostname, RRType.CNAME, createDNSBasedLoadBalancerMappingProcedure.getLoadBalancerUsed().getDNSName());
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
landscape.terminate(host);
|
||||
landscape.deleteKeyPair(region, keyName);
|
||||
|
||||
+1
-1
@@ -3,8 +3,8 @@ package com.sap.sailing.landscape.impl;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.sap.sailing.landscape.ReplicationCredentials;
|
||||
import com.sap.sse.landscape.ProcessConfigurationVariable;
|
||||
import com.sap.sse.landscape.ReplicationCredentials;
|
||||
|
||||
public class BearerTokenReplicationCredentials implements ReplicationCredentials {
|
||||
private final String bearerToken;
|
||||
|
||||
+1
-1
@@ -3,8 +3,8 @@ package com.sap.sailing.landscape.impl;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.sap.sailing.landscape.ReplicationCredentials;
|
||||
import com.sap.sse.landscape.ProcessConfigurationVariable;
|
||||
import com.sap.sse.landscape.ReplicationCredentials;
|
||||
|
||||
public class UsernamePasswordReplicationCredentials implements ReplicationCredentials {
|
||||
private final String username;
|
||||
|
||||
+70
-34
@@ -1,55 +1,91 @@
|
||||
package com.sap.sailing.landscape.procedures;
|
||||
|
||||
import java.net.URISyntaxException;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.util.Optional;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.sap.sailing.landscape.ReplicationConfiguration;
|
||||
import com.sap.sailing.landscape.SailingAnalyticsHost;
|
||||
import com.sap.sailing.landscape.SailingAnalyticsMaster;
|
||||
import com.sap.sailing.landscape.SailingAnalyticsMetrics;
|
||||
import com.sap.sailing.landscape.SailingAnalyticsReplica;
|
||||
import com.sap.sse.landscape.Release;
|
||||
import com.sap.sse.landscape.SecurityGroup;
|
||||
import com.sap.sse.landscape.aws.AwsAvailabilityZone;
|
||||
import com.sap.sse.landscape.aws.AwsLandscape;
|
||||
import com.sap.sse.landscape.aws.Tags;
|
||||
import com.sap.sse.landscape.aws.impl.AmazonMachineImage;
|
||||
import com.sap.sse.landscape.mongodb.Database;
|
||||
import com.sap.sse.landscape.rabbitmq.RabbitMQEndpoint;
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.landscape.application.ApplicationMasterProcess;
|
||||
import com.sap.sse.landscape.application.ApplicationProcessMetrics;
|
||||
import com.sap.sse.landscape.application.ApplicationReplicaProcess;
|
||||
import com.sap.sse.landscape.aws.AwsInstance;
|
||||
import com.sap.sse.landscape.ssh.SshCommandChannel;
|
||||
|
||||
import software.amazon.awssdk.services.ec2.model.InstanceType;
|
||||
|
||||
/**
|
||||
* Starts an empty multi-server. The image will cause a {@code /home/sailing/servers/server} directory to exist, but
|
||||
* after successfully launching, that directory will be removed. A {@link DeployProcessOnMultiServer} procedure needs to
|
||||
* be run with the {@link #getHost()} of this procedure telling the host on which to deploy the process.
|
||||
* be run with the {@link #getHost()} of this procedure telling the host on which to deploy the process.<p>
|
||||
*
|
||||
* The implementation specializes the {@link UpgradeAmi} procedure in {@link Builder#setNoShutdown(boolean) no-shutdown} mode.
|
||||
* After running that part, the {@code httpd} service is launched.<p>
|
||||
*
|
||||
* You want to at least specify an {@link Builder#setInstanceName(String) instance name} and {@link Builder#setInstanceType(InstanceType)}.
|
||||
*
|
||||
* @author Axel Uhl (D043530)
|
||||
*
|
||||
* @param <ShardingKey>
|
||||
* @param <HostT>
|
||||
*/
|
||||
public class StartMultiServer<ShardingKey, HostT extends SailingAnalyticsHost<ShardingKey>>
|
||||
extends StartSailingAnalyticsHost<ShardingKey, SailingAnalyticsHost<ShardingKey>> {
|
||||
public StartMultiServer(String name, AmazonMachineImage<ShardingKey, SailingAnalyticsMetrics> machineImage,
|
||||
AwsLandscape<ShardingKey, SailingAnalyticsMetrics, SailingAnalyticsMaster<ShardingKey>, SailingAnalyticsReplica<ShardingKey>> landscape,
|
||||
InstanceType instanceType, AwsAvailabilityZone availabilityZone, String keyName,
|
||||
Iterable<SecurityGroup> securityGroups, Optional<Release> release, Database databaseConfiguration,
|
||||
RabbitMQEndpoint rabbitConfiguration, String outputReplicationExchangeName,
|
||||
Optional<ReplicationConfiguration> replicationConfiguration,
|
||||
String commaSeparatedEmailAddressesToNotifyOfStartup, Optional<Tags> tags, String[] userData)
|
||||
throws URISyntaxException {
|
||||
super(name, machineImage, landscape, instanceType, availabilityZone, keyName, securityGroups, release,
|
||||
databaseConfiguration, rabbitConfiguration, outputReplicationExchangeName, replicationConfiguration,
|
||||
commaSeparatedEmailAddressesToNotifyOfStartup, tags, userData);
|
||||
// TODO Auto-generated constructor stub
|
||||
public class StartMultiServer<ShardingKey, MetricsT extends ApplicationProcessMetrics,
|
||||
MasterProcessT extends ApplicationMasterProcess<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT>,
|
||||
ReplicaProcessT extends ApplicationReplicaProcess<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT>,
|
||||
HostT extends AwsInstance<ShardingKey, MetricsT>>
|
||||
extends UpgradeAmi<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> {
|
||||
private static final Logger logger = Logger.getLogger(StartMultiServer.class.getName());
|
||||
private Optional<Duration> optionalTimeout;
|
||||
|
||||
/**
|
||||
* Under all circumstances, this builder will return {@code true} for {@link #isNoShutdown()}, making sure
|
||||
* that after the upgrade progress the server does not try to re-boot.
|
||||
*
|
||||
* @author Axel Uhl (D043530)
|
||||
*/
|
||||
public static interface Builder<ShardingKey, MetricsT extends ApplicationProcessMetrics,
|
||||
MasterProcessT extends ApplicationMasterProcess<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT>,
|
||||
ReplicaProcessT extends ApplicationReplicaProcess<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT>,
|
||||
HostT extends AwsInstance<ShardingKey, MetricsT>>
|
||||
extends UpgradeAmi.Builder<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> {
|
||||
@Override
|
||||
default boolean isNoShutdown() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
protected static class BuilderImpl<ShardingKey, MetricsT extends ApplicationProcessMetrics,
|
||||
MasterProcessT extends ApplicationMasterProcess<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT>,
|
||||
ReplicaProcessT extends ApplicationReplicaProcess<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT>,
|
||||
HostT extends AwsInstance<ShardingKey, MetricsT>>
|
||||
extends UpgradeAmi.BuilderImpl<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT>
|
||||
implements Builder<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> {
|
||||
@Override
|
||||
public StartMultiServer<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> build() {
|
||||
return new StartMultiServer<>(this);
|
||||
}
|
||||
}
|
||||
|
||||
public static <ShardingKey, MetricsT extends ApplicationProcessMetrics,
|
||||
MasterProcessT extends ApplicationMasterProcess<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT>,
|
||||
ReplicaProcessT extends ApplicationReplicaProcess<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT>,
|
||||
HostT extends AwsInstance<ShardingKey, MetricsT>> Builder<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> builder() {
|
||||
return new BuilderImpl<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
super.run();
|
||||
// TODO clean up the default /home/sailing/servers/server directory
|
||||
protected StartMultiServer(Builder<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> builder) {
|
||||
super(builder);
|
||||
this.optionalTimeout = builder.getOptionalTimeout();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
super.run();
|
||||
final SshCommandChannel sshCommandChannel = getHost().createRootSshChannel(optionalTimeout);
|
||||
final ByteArrayOutputStream stderr = new ByteArrayOutputStream();
|
||||
sshCommandChannel.sendCommandLineSynchronously("service httpd start", stderr);
|
||||
final String instanceId = getHost().getInstanceId();
|
||||
logger.info("stdout for starting httpd service on instance "+instanceId+": "+sshCommandChannel.getStreamContentsAsString());
|
||||
logger.info("stderr for starting httpd service on instance \"+instanceId+\": "+stderr.toString());
|
||||
logger.info("exit status for starting httpd service on instance \"+instanceId+\": "+sshCommandChannel.getExitStatus());
|
||||
}
|
||||
}
|
||||
|
||||
+39
-87
@@ -1,29 +1,16 @@
|
||||
package com.sap.sailing.landscape.procedures;
|
||||
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.sap.sailing.landscape.ReplicationConfiguration;
|
||||
import com.sap.sailing.landscape.SailingAnalyticsHost;
|
||||
import com.sap.sailing.landscape.SailingAnalyticsMaster;
|
||||
import com.sap.sailing.landscape.SailingAnalyticsMetrics;
|
||||
import com.sap.sailing.landscape.SailingAnalyticsReplica;
|
||||
import com.sap.sailing.landscape.SailingReleaseRepository;
|
||||
import com.sap.sse.landscape.MachineImage;
|
||||
import com.sap.sse.landscape.ProcessConfigurationVariable;
|
||||
import com.sap.sse.landscape.Release;
|
||||
import com.sap.sse.landscape.SecurityGroup;
|
||||
import com.sap.sse.landscape.aws.AwsAvailabilityZone;
|
||||
import com.sap.sse.landscape.aws.AwsLandscape;
|
||||
import com.sap.sse.landscape.aws.Tags;
|
||||
import com.sap.sse.landscape.aws.impl.AmazonMachineImage;
|
||||
import com.sap.sse.landscape.aws.impl.AwsRegion;
|
||||
import com.sap.sse.landscape.aws.orchestration.StartAwsHost;
|
||||
import com.sap.sse.landscape.mongodb.Database;
|
||||
import com.sap.sse.landscape.orchestration.Procedure;
|
||||
import com.sap.sse.landscape.rabbitmq.RabbitMQEndpoint;
|
||||
|
||||
import software.amazon.awssdk.services.ec2.model.InstanceType;
|
||||
|
||||
/**
|
||||
* TODO handle the naming problem: base name drives instance "Name" tag generation ("SL ... (Master)"), exchange name,
|
||||
@@ -36,86 +23,51 @@ import software.amazon.awssdk.services.ec2.model.InstanceType;
|
||||
*/
|
||||
public abstract class StartSailingAnalyticsHost<ShardingKey,
|
||||
HostT extends SailingAnalyticsHost<ShardingKey>>
|
||||
extends StartAwsHost<ShardingKey, SailingAnalyticsMetrics, SailingAnalyticsMaster<ShardingKey>, SailingAnalyticsReplica<ShardingKey>, SailingAnalyticsHost<ShardingKey>>
|
||||
extends StartAwsHost<ShardingKey, SailingAnalyticsMetrics, SailingAnalyticsMaster<ShardingKey>, SailingAnalyticsReplica<ShardingKey>, HostT>
|
||||
implements Procedure<ShardingKey, SailingAnalyticsMetrics, SailingAnalyticsMaster<ShardingKey>, SailingAnalyticsReplica<ShardingKey>> {
|
||||
private final static String IMAGE_TYPE_TAG_VALUE_SAILING = "sailing-analytics-server";
|
||||
|
||||
private final static String INSTANCE_NAME_DEFAULT_PREFIX = "SL ";
|
||||
|
||||
/**
|
||||
* Configures the start host procedure using the latest default machine image for the Sailing Analytics application,
|
||||
* tagged with the value {@link #IMAGE_TYPE_TAG_VALUE_SAILING} for the image type tag key. A random availability
|
||||
* zone is picked from the {@code region} specified, and the
|
||||
* {@link SailingReleaseRepository#getLatestMasterRelease() latest master build release} is chosen as the release to
|
||||
* deploy.
|
||||
* The following defaults, in addition to the defaults implemented by the more general {@link StartAwsHost.Builder},
|
||||
* are:
|
||||
* <ul>
|
||||
* <li>If no {@link #setInstanceName(String) instance name} is provided, the instance name is constructed from the {@link #getServerName() server name}
|
||||
* by pre-pending the prefix "SL ".</li>
|
||||
* <li>Uses the latest machine image of the type described by
|
||||
* {@link StartSailingAnalyticsHost#IMAGE_TYPE_TAG_VALUE_SAILING} if no explicit {@link #setMachineImage(AmazonMachineImage) machine image is set}
|
||||
* and no {@link #setImageType(String) image type is set} of which the latest version would be used otherwise.</li>
|
||||
* <li>If no {@link Release} is explicitly {@link #setRelease set}, or that {@link Optional} is empty,
|
||||
* {@link SailingReleaseRepository#INSTANCE}{@link SailingReleaseRepository#getLatestMasterRelease()
|
||||
* getLatestMasterRelease()} will be used instead.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param name
|
||||
* the name is used as the server name, is the basis for the server-group's name
|
||||
* @author Axel Uhl (D043530)
|
||||
*/
|
||||
public StartSailingAnalyticsHost(String name,
|
||||
AwsLandscape<ShardingKey, SailingAnalyticsMetrics, SailingAnalyticsMaster<ShardingKey>, SailingAnalyticsReplica<ShardingKey>> landscape,
|
||||
AwsRegion region,
|
||||
InstanceType instanceType, String keyName, Database databaseConfiguration,
|
||||
RabbitMQEndpoint rabbitConfiguration, String outputReplicationExchangeName,
|
||||
Optional<ReplicationConfiguration> replicationConfiguration,
|
||||
String commaSeparatedEmailAddressesToNotifyOfStartup, Optional<Tags> tags, String... additionalUserData) throws URISyntaxException {
|
||||
this(name, getLatestSailingMachineImage(landscape, region), landscape, instanceType,
|
||||
getRandomAvailabilityZone(region, landscape), keyName,
|
||||
Optional.of(SailingReleaseRepository.INSTANCE.getLatestMasterRelease()), databaseConfiguration, rabbitConfiguration,
|
||||
outputReplicationExchangeName, replicationConfiguration, commaSeparatedEmailAddressesToNotifyOfStartup,
|
||||
tags, additionalUserData);
|
||||
}
|
||||
|
||||
protected static <ShardingKey> AmazonMachineImage<ShardingKey, SailingAnalyticsMetrics> getLatestSailingMachineImage(
|
||||
AwsLandscape<ShardingKey, SailingAnalyticsMetrics, SailingAnalyticsMaster<ShardingKey>, SailingAnalyticsReplica<ShardingKey>> landscape,
|
||||
AwsRegion region) {
|
||||
return getLatestImageOfType(IMAGE_TYPE_TAG_VALUE_SAILING, landscape, region);
|
||||
}
|
||||
|
||||
public StartSailingAnalyticsHost(String name, Optional<Release> release,
|
||||
AwsLandscape<ShardingKey, SailingAnalyticsMetrics, SailingAnalyticsMaster<ShardingKey>, SailingAnalyticsReplica<ShardingKey>> landscape,
|
||||
AwsRegion region,
|
||||
InstanceType instanceType, String keyName, Database databaseConfiguration,
|
||||
RabbitMQEndpoint rabbitConfiguration, String outputReplicationExchangeName,
|
||||
Optional<ReplicationConfiguration> replicationConfiguration,
|
||||
String commaSeparatedEmailAddressesToNotifyOfStartup, Optional<Tags> tags, String... additionalUserData) throws URISyntaxException {
|
||||
this(name, getLatestSailingMachineImage(landscape, region), landscape, instanceType,
|
||||
getRandomAvailabilityZone(region, landscape), keyName,
|
||||
release, databaseConfiguration, rabbitConfiguration,
|
||||
outputReplicationExchangeName, replicationConfiguration, commaSeparatedEmailAddressesToNotifyOfStartup,
|
||||
tags, additionalUserData);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name
|
||||
* the name is used as the server name, is the basis for the server-group's name
|
||||
*/
|
||||
public StartSailingAnalyticsHost(String name,
|
||||
AmazonMachineImage<ShardingKey, SailingAnalyticsMetrics> machineImage,
|
||||
AwsLandscape<ShardingKey, SailingAnalyticsMetrics, SailingAnalyticsMaster<ShardingKey>, SailingAnalyticsReplica<ShardingKey>> landscape,
|
||||
InstanceType instanceType, AwsAvailabilityZone availabilityZone, String keyName,
|
||||
Optional<Release> release, Database databaseConfiguration, RabbitMQEndpoint rabbitConfiguration,
|
||||
String outputReplicationExchangeName, Optional<ReplicationConfiguration> replicationConfiguration,
|
||||
String commaSeparatedEmailAddressesToNotifyOfStartup, Optional<Tags> tags, String... userData) {
|
||||
super(machineImage, release, landscape, instanceType, availabilityZone, keyName, addNameTag(name, tags), userData);
|
||||
public static interface Builder<T extends StartSailingAnalyticsHost<ShardingKey, HostT>, ShardingKey, HostT extends SailingAnalyticsHost<ShardingKey>>
|
||||
extends StartAwsHost.Builder<T, ShardingKey, SailingAnalyticsMetrics, SailingAnalyticsMaster<ShardingKey>, SailingAnalyticsReplica<ShardingKey>, HostT> {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name
|
||||
* the name is used as the server name, is the basis for the server-group's name
|
||||
*/
|
||||
public StartSailingAnalyticsHost(String name, MachineImage machineImage,
|
||||
AwsLandscape<ShardingKey, SailingAnalyticsMetrics, SailingAnalyticsMaster<ShardingKey>, SailingAnalyticsReplica<ShardingKey>> landscape,
|
||||
InstanceType instanceType, AwsAvailabilityZone availabilityZone, String keyName,
|
||||
Iterable<SecurityGroup> securityGroups, Optional<Release> release, Database databaseConfiguration,
|
||||
RabbitMQEndpoint rabbitConfiguration,
|
||||
String outputReplicationExchangeName,
|
||||
Optional<ReplicationConfiguration> replicationConfiguration,
|
||||
String commaSeparatedEmailAddressesToNotifyOfStartup, Optional<Tags> tags, String... additionalUserData) throws URISyntaxException {
|
||||
super(machineImage, release, landscape, instanceType, availabilityZone, keyName, securityGroups, addNameTag(name, tags), additionalUserData);
|
||||
addUserData(databaseConfiguration);
|
||||
addUserData(rabbitConfiguration);
|
||||
addUserData(ProcessConfigurationVariable.SERVER_NAME, name);
|
||||
addUserData(ProcessConfigurationVariable.REPLICATION_CHANNEL, outputReplicationExchangeName);
|
||||
addUserData(ProcessConfigurationVariable.SERVER_STARTUP_NOTIFY, commaSeparatedEmailAddressesToNotifyOfStartup);
|
||||
replicationConfiguration.ifPresent(this::addUserData);
|
||||
protected abstract static class BuilderImpl<T extends StartSailingAnalyticsHost<ShardingKey, HostT>, ShardingKey, HostT extends SailingAnalyticsHost<ShardingKey>>
|
||||
extends StartAwsHost.BuilderImpl<T, ShardingKey, SailingAnalyticsMetrics, SailingAnalyticsMaster<ShardingKey>, SailingAnalyticsReplica<ShardingKey>, HostT>
|
||||
implements Builder<T, ShardingKey, HostT> {
|
||||
@Override
|
||||
public String getImageType() {
|
||||
return super.getImageType() == null ? StartSailingAnalyticsHost.IMAGE_TYPE_TAG_VALUE_SAILING : super.getImageType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Release> getRelease() {
|
||||
return Optional.of(super.getRelease().orElse(SailingReleaseRepository.INSTANCE.getLatestMasterRelease()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInstanceName() {
|
||||
return super.getInstanceName() == null ? INSTANCE_NAME_DEFAULT_PREFIX+getServerName() : super.getInstanceName();
|
||||
}
|
||||
}
|
||||
|
||||
protected StartSailingAnalyticsHost(Builder<? extends StartSailingAnalyticsHost<ShardingKey,HostT>, ShardingKey, HostT> builder) {
|
||||
super(builder);
|
||||
}
|
||||
}
|
||||
|
||||
+29
-55
@@ -1,70 +1,44 @@
|
||||
package com.sap.sailing.landscape.procedures;
|
||||
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.sap.sailing.landscape.ReplicationConfiguration;
|
||||
import com.sap.sailing.landscape.SailingAnalyticsHost;
|
||||
import com.sap.sailing.landscape.SailingAnalyticsMaster;
|
||||
import com.sap.sailing.landscape.SailingAnalyticsMetrics;
|
||||
import com.sap.sailing.landscape.SailingAnalyticsReplica;
|
||||
import com.sap.sse.landscape.MachineImage;
|
||||
import com.sap.sse.landscape.ProcessConfigurationVariable;
|
||||
import com.sap.sse.landscape.Release;
|
||||
import com.sap.sse.landscape.SecurityGroup;
|
||||
import com.sap.sse.landscape.aws.AwsAvailabilityZone;
|
||||
import com.sap.sse.landscape.aws.AwsLandscape;
|
||||
import com.sap.sse.landscape.aws.Tags;
|
||||
import com.sap.sse.landscape.aws.impl.AwsRegion;
|
||||
import com.sap.sse.landscape.mongodb.Database;
|
||||
import com.sap.sse.landscape.rabbitmq.RabbitMQReplicaSet;
|
||||
|
||||
import software.amazon.awssdk.services.ec2.model.InstanceType;
|
||||
|
||||
/**
|
||||
* TODO handle the naming problem: base name drives instance "Name" tag generation ("SL ... (Master)"), exchange name,
|
||||
* database name and SERVER_NAME. When moving up the inheritance hierarchy, name is interpreted in some places as the instance name
|
||||
* which obviously doesn't equal the "Name" tag value. So, we have to clearly distinguish these.
|
||||
* This procedure does two things: it {@link StartSailingAnalyticsHost starts} a {@link SailingAnalyticsHost}, and
|
||||
* (currently implicitly, based on the way the /etc/init.d/sailing script works) also starts a "master" process
|
||||
* that is expected to have the default working directory {@code /home/sailing/servers/server}.<p>
|
||||
*
|
||||
* TODO What we should probably be doing instead is harmonize the way the set-up / launching of a regular default master
|
||||
* works with how a {@link StartMultiServer multi-server is started}. We could start both empty, with only the default
|
||||
* reverse proxy mappings for {@code internal-server-status} and the plain access through the {@code ec2-...} hostname.
|
||||
* From there on, all process launching and stopping would work through the {@link DeployProcessOnMultiServer} procedure
|
||||
* (which then should be renamed to {@code DeployApplicationProcessOnServer}). That procedure then would have the
|
||||
*
|
||||
* @author Axel Uhl (D043530)
|
||||
*
|
||||
* @param <ShardingKey>
|
||||
*/
|
||||
public class StartSailingAnalyticsMaster<ShardingKey>
|
||||
extends StartSailingAnalyticsHost<ShardingKey, SailingAnalyticsHost<ShardingKey>> {
|
||||
public StartSailingAnalyticsMaster(String name, AwsRegion region,
|
||||
AwsLandscape<ShardingKey, SailingAnalyticsMetrics, SailingAnalyticsMaster<ShardingKey>, SailingAnalyticsReplica<ShardingKey>> landscape,
|
||||
InstanceType instanceType, String keyName, Optional<Release> release, Database databaseConfiguration,
|
||||
RabbitMQReplicaSet rabbitConfiguration, Optional<ReplicationConfiguration> replicationConfiguration,
|
||||
String commaSeparatedEmailAddressesToNotifyOfStartup, Optional<Tags> tags) throws URISyntaxException {
|
||||
this(name,
|
||||
getLatestSailingMachineImage(landscape, region), landscape, instanceType, getRandomAvailabilityZone(region, landscape), keyName,
|
||||
getDefaultSecurityGroupForApplicationHosts(landscape, region),
|
||||
release, databaseConfiguration, rabbitConfiguration, replicationConfiguration, commaSeparatedEmailAddressesToNotifyOfStartup, tags);
|
||||
public static interface Builder<ShardingKey>
|
||||
extends StartSailingAnalyticsHost.Builder<StartSailingAnalyticsMaster<ShardingKey>, ShardingKey, SailingAnalyticsHost<ShardingKey>> {
|
||||
}
|
||||
|
||||
public StartSailingAnalyticsMaster(String name, MachineImage machineImage,
|
||||
AwsRegion region,
|
||||
AwsLandscape<ShardingKey, SailingAnalyticsMetrics, SailingAnalyticsMaster<ShardingKey>, SailingAnalyticsReplica<ShardingKey>> landscape,
|
||||
InstanceType instanceType, String keyName, Optional<Release> release,
|
||||
Database databaseConfiguration, RabbitMQReplicaSet rabbitConfiguration,
|
||||
Optional<ReplicationConfiguration> replicationConfiguration,
|
||||
String commaSeparatedEmailAddressesToNotifyOfStartup, Optional<Tags> tags) throws URISyntaxException {
|
||||
this(name, machineImage, landscape, instanceType, getRandomAvailabilityZone(region, landscape), keyName,
|
||||
getDefaultSecurityGroupForApplicationHosts(landscape, region),
|
||||
release, databaseConfiguration, rabbitConfiguration, replicationConfiguration, commaSeparatedEmailAddressesToNotifyOfStartup, tags);
|
||||
|
||||
// TODO model an AwsLandscape subclass describing the specifics of the Sailing landscape, with a central security service that a master replicates by default
|
||||
|
||||
protected static class BuilderImpl<ShardingKey>
|
||||
extends StartSailingAnalyticsHost.BuilderImpl<StartSailingAnalyticsMaster<ShardingKey>, ShardingKey, SailingAnalyticsHost<ShardingKey>>
|
||||
implements Builder<ShardingKey> {
|
||||
@Override
|
||||
public StartSailingAnalyticsMaster<ShardingKey> build() {
|
||||
return new StartSailingAnalyticsMaster<ShardingKey>(this);
|
||||
}
|
||||
}
|
||||
|
||||
public StartSailingAnalyticsMaster(String name, MachineImage machineImage,
|
||||
AwsLandscape<ShardingKey, SailingAnalyticsMetrics, SailingAnalyticsMaster<ShardingKey>, SailingAnalyticsReplica<ShardingKey>> landscape,
|
||||
InstanceType instanceType, AwsAvailabilityZone availabilityZone, String keyName,
|
||||
Iterable<SecurityGroup> securityGroups, Optional<Release> release, Database databaseConfiguration,
|
||||
RabbitMQReplicaSet rabbitConfiguration, Optional<ReplicationConfiguration> replicationConfiguration,
|
||||
String commaSeparatedEmailAddressesToNotifyOfStartup, Optional<Tags> tags) throws URISyntaxException {
|
||||
super(name, machineImage, landscape, instanceType, availabilityZone, keyName, securityGroups, release,
|
||||
databaseConfiguration, rabbitConfiguration,
|
||||
/* use {name} as outbound replication exchange name for master */ name, replicationConfiguration,
|
||||
commaSeparatedEmailAddressesToNotifyOfStartup, tags);
|
||||
addUserData(ProcessConfigurationVariable.USE_ENVIRONMENT, "live-master-server");
|
||||
|
||||
public static <ShardingKey> Builder<ShardingKey> builder() {
|
||||
return new BuilderImpl<>();
|
||||
}
|
||||
|
||||
protected StartSailingAnalyticsMaster(Builder<ShardingKey> builder) {
|
||||
super(builder);
|
||||
addUserData(ProcessConfigurationVariable.USE_ENVIRONMENT, "live-master-server"); // TODO maybe this should be handled by this procedure adding the correct defaults, e.g., for replicating security/sharedsailing?
|
||||
}
|
||||
}
|
||||
|
||||
+19
-52
@@ -1,62 +1,29 @@
|
||||
package com.sap.sailing.landscape.procedures;
|
||||
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Collections;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.sap.sailing.landscape.ReplicationConfiguration;
|
||||
import com.sap.sailing.landscape.SailingAnalyticsHost;
|
||||
import com.sap.sailing.landscape.SailingAnalyticsMaster;
|
||||
import com.sap.sailing.landscape.SailingAnalyticsMetrics;
|
||||
import com.sap.sailing.landscape.SailingAnalyticsReplica;
|
||||
import com.sap.sse.landscape.ProcessConfigurationVariable;
|
||||
import com.sap.sse.landscape.Release;
|
||||
import com.sap.sse.landscape.SecurityGroup;
|
||||
import com.sap.sse.landscape.aws.AwsAvailabilityZone;
|
||||
import com.sap.sse.landscape.aws.AwsLandscape;
|
||||
import com.sap.sse.landscape.aws.Tags;
|
||||
import com.sap.sse.landscape.aws.impl.AmazonMachineImage;
|
||||
import com.sap.sse.landscape.mongodb.Database;
|
||||
import com.sap.sse.landscape.rabbitmq.RabbitMQEndpoint;
|
||||
|
||||
import software.amazon.awssdk.services.ec2.model.InstanceType;
|
||||
|
||||
/**
|
||||
* TODO handle the naming problem: base name drives instance "Name" tag generation ("SL ... (Master)"), exchange name,
|
||||
* database name and SERVER_NAME. When moving up the inheritance hierarchy, name is interpreted in some places as the instance name
|
||||
* which obviously doesn't equal the "Name" tag value. So, we have to clearly distinguish these.
|
||||
*
|
||||
* @author Axel Uhl (D043530)
|
||||
*
|
||||
* @param <ShardingKey>
|
||||
*/
|
||||
public class StartSailingAnalyticsReplica<ShardingKey>
|
||||
extends StartSailingAnalyticsHost<ShardingKey, SailingAnalyticsHost<ShardingKey>> {
|
||||
public StartSailingAnalyticsReplica(String name, AmazonMachineImage<ShardingKey, SailingAnalyticsMetrics> machineImage,
|
||||
AwsLandscape<ShardingKey, SailingAnalyticsMetrics, SailingAnalyticsMaster<ShardingKey>, SailingAnalyticsReplica<ShardingKey>> landscape,
|
||||
InstanceType instanceType, AwsAvailabilityZone availabilityZone, String keyName, Optional<Release> release,
|
||||
Database databaseConfiguration, RabbitMQEndpoint rabbitConfiguration,
|
||||
Optional<ReplicationConfiguration> replicationConfiguration, SailingAnalyticsMaster<ShardingKey> master,
|
||||
String commaSeparatedEmailAddressesToNotifyOfStartup, Optional<Tags> tags, String[] userData)
|
||||
throws URISyntaxException {
|
||||
this(name, machineImage, landscape, instanceType, availabilityZone, keyName,
|
||||
Collections
|
||||
.singleton(landscape.getDefaultSecurityGroupForApplicationHosts(availabilityZone.getRegion())),
|
||||
release, databaseConfiguration, rabbitConfiguration, replicationConfiguration, master,
|
||||
commaSeparatedEmailAddressesToNotifyOfStartup, tags, userData);
|
||||
public static interface Builder<ShardingKey>
|
||||
extends StartSailingAnalyticsHost.Builder<StartSailingAnalyticsReplica<ShardingKey>, ShardingKey, SailingAnalyticsHost<ShardingKey>> {
|
||||
}
|
||||
|
||||
public StartSailingAnalyticsReplica(String name, AmazonMachineImage<ShardingKey, SailingAnalyticsMetrics> machineImage,
|
||||
AwsLandscape<ShardingKey, SailingAnalyticsMetrics, SailingAnalyticsMaster<ShardingKey>, SailingAnalyticsReplica<ShardingKey>> landscape,
|
||||
InstanceType instanceType, AwsAvailabilityZone availabilityZone, String keyName,
|
||||
Iterable<SecurityGroup> securityGroups, Optional<Release> release, Database databaseConfiguration,
|
||||
RabbitMQEndpoint rabbitConfiguration, Optional<ReplicationConfiguration> replicationConfiguration,
|
||||
SailingAnalyticsMaster<ShardingKey> master, String commaSeparatedEmailAddressesToNotifyOfStartup,
|
||||
Optional<Tags> tags, String... userData) throws URISyntaxException {
|
||||
super(name, machineImage, landscape, instanceType, availabilityZone, keyName, securityGroups, release,
|
||||
databaseConfiguration, rabbitConfiguration,
|
||||
/* use {name}-replica as outbound replication exchange name for master */ name + "-replica",
|
||||
replicationConfiguration, commaSeparatedEmailAddressesToNotifyOfStartup, tags, userData);
|
||||
addUserData(ProcessConfigurationVariable.USE_ENVIRONMENT, "live-replica-server");
|
||||
|
||||
protected static class BuilderImpl<ShardingKey>
|
||||
extends StartSailingAnalyticsHost.BuilderImpl<StartSailingAnalyticsReplica<ShardingKey>, ShardingKey, SailingAnalyticsHost<ShardingKey>>
|
||||
implements Builder<ShardingKey> {
|
||||
@Override
|
||||
public StartSailingAnalyticsReplica<ShardingKey> build() {
|
||||
return new StartSailingAnalyticsReplica<ShardingKey>(this);
|
||||
}
|
||||
}
|
||||
|
||||
public static <ShardingKey> Builder<ShardingKey> builder() {
|
||||
return new BuilderImpl<>();
|
||||
}
|
||||
|
||||
protected StartSailingAnalyticsReplica(Builder<ShardingKey> builder) {
|
||||
super(builder);
|
||||
addUserData(ProcessConfigurationVariable.USE_ENVIRONMENT, "live-replica-server"); // TODO maybe this should be handled by this procedure adding the correct defaults, e.g., for replicating security/sharedsailing?
|
||||
}
|
||||
}
|
||||
|
||||
+70
-19
@@ -1,22 +1,15 @@
|
||||
package com.sap.sailing.landscape.procedures;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.Collections;
|
||||
|
||||
import com.sap.sse.landscape.MachineImage;
|
||||
import com.sap.sse.landscape.SecurityGroup;
|
||||
import com.sap.sse.landscape.application.ApplicationMasterProcess;
|
||||
import com.sap.sse.landscape.application.ApplicationProcessMetrics;
|
||||
import com.sap.sse.landscape.application.ApplicationReplicaProcess;
|
||||
import com.sap.sse.landscape.aws.AwsAvailabilityZone;
|
||||
import com.sap.sse.landscape.aws.AwsInstance;
|
||||
import com.sap.sse.landscape.aws.AwsLandscape;
|
||||
import com.sap.sse.landscape.aws.Tags;
|
||||
import com.sap.sse.landscape.aws.impl.AmazonMachineImage;
|
||||
import com.sap.sse.landscape.aws.orchestration.StartAwsHost;
|
||||
import com.sap.sse.landscape.orchestration.Procedure;
|
||||
|
||||
import software.amazon.awssdk.services.ec2.model.InstanceType;
|
||||
|
||||
/**
|
||||
* Upgrades an existing Amazon Machine Image that is expected to be prepared for such an upgrade, by
|
||||
* invoking it with very specific user data that trigger the automatic upgrade. The resulting AMI can
|
||||
@@ -31,23 +24,81 @@ public class UpgradeAmi<ShardingKey, MetricsT extends ApplicationProcessMetrics,
|
||||
MasterProcessT extends ApplicationMasterProcess<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT>,
|
||||
ReplicaProcessT extends ApplicationReplicaProcess<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT>,
|
||||
HostT extends AwsInstance<ShardingKey, MetricsT>>
|
||||
extends
|
||||
StartAwsHost<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> implements
|
||||
Procedure<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT> {
|
||||
private static final String IMAGE_UPGRADE = "image-upgrade";
|
||||
extends StartAwsHost<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT>
|
||||
implements Procedure<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT> {
|
||||
private static final String IMAGE_UPGRADE_USER_DATA = "image-upgrade";
|
||||
private static final String NO_SHUTDOWN_USER_DATA = "no-shutdown";
|
||||
|
||||
private MachineImage upgradedAmi;
|
||||
|
||||
public UpgradeAmi(AmazonMachineImage<ShardingKey, MetricsT> machineImage,
|
||||
AwsLandscape<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT> landscape,
|
||||
InstanceType instanceType, AwsAvailabilityZone availabilityZone, String keyName,
|
||||
Iterable<SecurityGroup> securityGroups) {
|
||||
super(machineImage, Optional.empty(), landscape, instanceType, availabilityZone, keyName,
|
||||
securityGroups, Optional.of(Tags.with("Name", IMAGE_UPGRADE+" for "+machineImage.getId())), /* user data */ IMAGE_UPGRADE);
|
||||
/**
|
||||
* Additional default rules in addition to what the {@link StartAwsHost.Builder parent builder} defines:
|
||||
*
|
||||
* <ul>
|
||||
* <li>If no {@link #getInstanceName() instance name} is set, the default instance name will be constructed as
|
||||
* {@code IMAGE_UPGRADE+" for "+machineImage.getId()}</li>
|
||||
* <li>The user data are set to the string defined by {@link UpgradeAmi#IMAGE_UPGRADE_USER_DATA}, forcing the image to
|
||||
* boot without trying to launch a process instance.</li>
|
||||
* </ul>
|
||||
* @author Axel Uhl (D043530)
|
||||
*/
|
||||
public static interface Builder<ShardingKey, MetricsT extends ApplicationProcessMetrics,
|
||||
MasterProcessT extends ApplicationMasterProcess<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT>,
|
||||
ReplicaProcessT extends ApplicationReplicaProcess<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT>,
|
||||
HostT extends AwsInstance<ShardingKey, MetricsT>>
|
||||
extends StartAwsHost.Builder<UpgradeAmi<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT>, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> {
|
||||
boolean isNoShutdown();
|
||||
|
||||
Builder<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> setNoShutdown(boolean noShutdown);
|
||||
}
|
||||
|
||||
protected static class BuilderImpl<ShardingKey, MetricsT extends ApplicationProcessMetrics,
|
||||
MasterProcessT extends ApplicationMasterProcess<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT>,
|
||||
ReplicaProcessT extends ApplicationReplicaProcess<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT>,
|
||||
HostT extends AwsInstance<ShardingKey, MetricsT>>
|
||||
extends StartAwsHost.BuilderImpl<UpgradeAmi<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT>, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT>
|
||||
implements Builder<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> {
|
||||
private boolean noShutdown;
|
||||
|
||||
@Override
|
||||
public UpgradeAmi<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> build() {
|
||||
return new UpgradeAmi<>(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNoShutdown() {
|
||||
return noShutdown;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> setNoShutdown(boolean noShutdown) {
|
||||
this.noShutdown = noShutdown;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInstanceName() {
|
||||
return super.getInstanceName() == null ? IMAGE_UPGRADE_USER_DATA+" for "+getMachineImage().getId() : super.getInstanceName();
|
||||
}
|
||||
}
|
||||
|
||||
public static <ShardingKey, MetricsT extends ApplicationProcessMetrics,
|
||||
MasterProcessT extends ApplicationMasterProcess<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT>,
|
||||
ReplicaProcessT extends ApplicationReplicaProcess<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT>,
|
||||
HostT extends AwsInstance<ShardingKey, MetricsT>> Builder<ShardingKey, MetricsT, MasterProcessT,ReplicaProcessT, HostT> builder() {
|
||||
return new BuilderImpl<>();
|
||||
}
|
||||
|
||||
public UpgradeAmi(Builder<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> builder) {
|
||||
super(builder);
|
||||
addUserData(Collections.singleton(IMAGE_UPGRADE_USER_DATA));
|
||||
if (builder.isNoShutdown()) {
|
||||
addUserData(Collections.singleton(NO_SHUTDOWN_USER_DATA));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
public void run() throws Exception {
|
||||
super.run(); // launches the machine in upgrade mode and shuts it down again, preparing for AMI creation
|
||||
// TODO now comes the waiting for the shutdown and initiating the creation of an AMI for the instance
|
||||
// TODO then comes the tagging of the volume snapshots created
|
||||
|
||||
@@ -18,6 +18,7 @@ import com.sap.sse.landscape.application.ApplicationReplicaProcess;
|
||||
import com.sap.sse.landscape.aws.impl.AmazonMachineImage;
|
||||
import com.sap.sse.landscape.aws.impl.AwsLandscapeImpl;
|
||||
import com.sap.sse.landscape.aws.impl.AwsTargetGroupImpl;
|
||||
import com.sap.sse.landscape.mongodb.Database;
|
||||
import com.sap.sse.landscape.mongodb.MongoEndpoint;
|
||||
import com.sap.sse.landscape.ssh.SSHKeyPair;
|
||||
|
||||
@@ -280,6 +281,8 @@ extends Landscape<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT> {
|
||||
*/
|
||||
MongoEndpoint getDatabaseConfigurationForDefaultCluster(Region region);
|
||||
|
||||
Database getDatabase(Region region, String databaseName);
|
||||
|
||||
/**
|
||||
* The region to use as the default region for instance creation, DB connectivity, reverse proxy config, ...
|
||||
*/
|
||||
|
||||
+7
@@ -40,7 +40,9 @@ import com.sap.sse.landscape.aws.TargetGroup;
|
||||
import com.sap.sse.landscape.aws.persistence.DomainObjectFactory;
|
||||
import com.sap.sse.landscape.aws.persistence.MongoObjectFactory;
|
||||
import com.sap.sse.landscape.aws.persistence.PersistenceFactory;
|
||||
import com.sap.sse.landscape.mongodb.Database;
|
||||
import com.sap.sse.landscape.mongodb.MongoEndpoint;
|
||||
import com.sap.sse.landscape.mongodb.impl.DatabaseImpl;
|
||||
import com.sap.sse.landscape.rabbitmq.RabbitMQEndpoint;
|
||||
import com.sap.sse.landscape.ssh.SSHKeyPair;
|
||||
import com.sap.sse.mongodb.MongoDBService;
|
||||
@@ -710,6 +712,11 @@ ReplicaProcessT extends ApplicationReplicaProcess<ShardingKey, MetricsT, MasterP
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Database getDatabase(com.sap.sse.landscape.Region region, String databaseName) {
|
||||
return new DatabaseImpl(getDatabaseConfigurationForDefaultCluster(region), databaseName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RabbitMQEndpoint getMessagingConfigurationForDefaultCluster(com.sap.sse.landscape.Region region) {
|
||||
final RabbitMQEndpoint result;
|
||||
|
||||
+411
-46
@@ -8,16 +8,15 @@ import java.util.Map.Entry;
|
||||
import java.util.Optional;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.landscape.AvailabilityZone;
|
||||
import com.sap.sse.landscape.Landscape;
|
||||
import com.sap.sse.landscape.MachineImage;
|
||||
import com.sap.sse.landscape.ProcessConfigurationVariable;
|
||||
import com.sap.sse.landscape.Region;
|
||||
import com.sap.sse.landscape.Release;
|
||||
import com.sap.sse.landscape.ReplicationConfiguration;
|
||||
import com.sap.sse.landscape.SecurityGroup;
|
||||
import com.sap.sse.landscape.UserDataProvider;
|
||||
import com.sap.sse.landscape.application.ApplicationMasterProcess;
|
||||
@@ -29,7 +28,9 @@ import com.sap.sse.landscape.aws.AwsLandscape;
|
||||
import com.sap.sse.landscape.aws.Tags;
|
||||
import com.sap.sse.landscape.aws.impl.AmazonMachineImage;
|
||||
import com.sap.sse.landscape.aws.impl.AwsRegion;
|
||||
import com.sap.sse.landscape.mongodb.Database;
|
||||
import com.sap.sse.landscape.orchestration.StartHost;
|
||||
import com.sap.sse.landscape.rabbitmq.RabbitMQEndpoint;
|
||||
|
||||
import software.amazon.awssdk.services.ec2.model.InstanceType;
|
||||
|
||||
@@ -38,12 +39,6 @@ import software.amazon.awssdk.services.ec2.model.InstanceType;
|
||||
* calling {@link #getHost()}.
|
||||
*
|
||||
* @author Axel Uhl (D043530)
|
||||
*
|
||||
* @param <ShardingKey>
|
||||
* @param <MetricsT>
|
||||
* @param <MasterProcessT>
|
||||
* @param <ReplicaProcessT>
|
||||
* @param <HostT>
|
||||
*/
|
||||
public abstract class StartAwsHost<ShardingKey,
|
||||
MetricsT extends ApplicationProcessMetrics,
|
||||
@@ -51,8 +46,6 @@ public abstract class StartAwsHost<ShardingKey,
|
||||
ReplicaProcessT extends ApplicationReplicaProcess<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT>,
|
||||
HostT extends AwsInstance<ShardingKey, MetricsT>>
|
||||
extends StartHost<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> {
|
||||
private static final Logger logger = Logger.getLogger(StartAwsHost.class.getName());
|
||||
|
||||
/**
|
||||
* The {@link AwsLandscape#getLatestImageWithTag(com.sap.sse.landscape.Region, String, String)} method is
|
||||
* used to obtain default images for specific AWS host starting procedures that subclass this class. The
|
||||
@@ -69,34 +62,413 @@ extends StartHost<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT>
|
||||
private final String keyName;
|
||||
private final Iterable<SecurityGroup> securityGroups;
|
||||
private final Optional<Tags> tags;
|
||||
private AwsInstance<ShardingKey, MetricsT> host;
|
||||
private HostT host;
|
||||
|
||||
public StartAwsHost(MachineImage machineImage, Optional<Release> release,
|
||||
AwsLandscape<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT> landscape,
|
||||
InstanceType instanceType, AwsAvailabilityZone availabilityZone, String keyName,
|
||||
Iterable<SecurityGroup> securityGroups, Optional<Tags> tags, String... userData) {
|
||||
super(machineImage, landscape);
|
||||
/**
|
||||
* A builder that helps building an instance of type {@link StartAwsHost} or any subclass thereof (then using
|
||||
* specialized builders). The following default rules apply:
|
||||
* <ul>
|
||||
* <li>If an {@link #getImageType() image type} has been specified, it serves as the default for looking up the
|
||||
* {@link #getMachineImage() image} to launch from. However, an image type set explicitly, or subclasses overriding
|
||||
* {@link #getMachineImage()} may take precedence.</li>
|
||||
* <li>If no {@link #setRelease(Release) release is set}, an empty {@link Optional} will be returned by
|
||||
* {@link #getRelease()}, indicating to use the default release pre-deployed in the image launched.</li>
|
||||
* <li>If no {@link #setAvailabilityZone(AwsAvailabilityZone) availability zone} is specified, this builder will try
|
||||
* to obtain the {@link #getRegion()} which in this case must have been {@link #setRegion(AwsRegion)} or otherwise
|
||||
* be returned from an overridden {@link #getRegion()} in a specialized builder, and will
|
||||
* {@link StartAwsHost#getRandomAvailabilityZone(AwsRegion, AwsLandscape) pick an availability zone randomly} within
|
||||
* that region.</li>
|
||||
* <li>Conversely, if an {@link #setAvailabilityZone(AwsAvailabilityZone) availability zone has been set}, its
|
||||
* {@link AwsAvailabilityZone#getRegion() region} will be the default answer of {@link #getRegion()}.</li>
|
||||
* <li>If no {@link #setSecurityGroups(Iterable) security group} has been set, the {@link #getLandscape() landscape}
|
||||
* is asked to provide its {@link AwsLandscape#getDefaultSecurityGroupForApplicationHosts(Region) default security
|
||||
* group for application hosts} in the {@link #getRegion() region} used by this builder.</li>
|
||||
* <li>If no {@link #setDatabaseName(String) database name is set explicitly}, it defaults to the
|
||||
* {@link #getServerName() server name}.</li>
|
||||
* <li>The {@link #getOptionalTimeout() optional timeout} defaults to an {@link Optional#empty() empty optional}, meaning
|
||||
* that waiting for the instance won't timeout by default.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Axel Uhl (D043530)
|
||||
*/
|
||||
public static interface Builder<T extends StartAwsHost<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT>, ShardingKey,
|
||||
MetricsT extends ApplicationProcessMetrics,
|
||||
MasterProcessT extends ApplicationMasterProcess<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT>,
|
||||
ReplicaProcessT extends ApplicationReplicaProcess<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT>,
|
||||
HostT extends AwsInstance<ShardingKey, MetricsT>>
|
||||
extends StartHost.Builder<T, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> {
|
||||
@Override
|
||||
AmazonMachineImage<ShardingKey, MetricsT> getMachineImage();
|
||||
|
||||
Builder<T, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> setMachineImage(AmazonMachineImage<ShardingKey, MetricsT> machineImage);
|
||||
|
||||
/**
|
||||
* When not {@code null}, the newest {@link AmazonMachineImage} tagged with a tag named as specified by the constant {@link #IMAGE_TYPE_TAG_NAME}
|
||||
* with the value provided by the result of this method will be searched and will be used as the default for {@link #getMachineImage()}.
|
||||
*/
|
||||
String getImageType();
|
||||
|
||||
Builder<T, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> setImageType(String imageType);
|
||||
|
||||
/**
|
||||
* By default, the release pre-deployed in the image will be used, represented by an empty {@link Optional}
|
||||
* returned by this default method implementation.
|
||||
*/
|
||||
Optional<Release> getRelease();
|
||||
|
||||
Builder<T, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> setRelease(Optional<Release> release);
|
||||
|
||||
@Override
|
||||
AwsLandscape<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT> getLandscape();
|
||||
|
||||
Builder<T, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> setLandscape(AwsLandscape<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT> landscape);
|
||||
|
||||
InstanceType getInstanceType();
|
||||
|
||||
Builder<T, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> setInstanceType(InstanceType instanceType);
|
||||
|
||||
AwsAvailabilityZone getAvailabilityZone();
|
||||
|
||||
Builder<T, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> setAvailabilityZone(AwsAvailabilityZone availabilityZone);
|
||||
|
||||
String getKeyName();
|
||||
|
||||
Builder<T, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> setKeyName(String keyName);
|
||||
|
||||
Iterable<SecurityGroup> getSecurityGroups();
|
||||
|
||||
Builder<T, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> setSecurityGroups(Iterable<SecurityGroup> securityGroups);
|
||||
|
||||
Optional<Tags> getTags();
|
||||
|
||||
Builder<T, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> setTags(Optional<Tags> tags);
|
||||
|
||||
String[] getUserData();
|
||||
|
||||
Builder<T, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> setUserData(String[] userData);
|
||||
|
||||
AwsRegion getRegion();
|
||||
|
||||
Builder<T, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> setRegion(AwsRegion region);
|
||||
|
||||
String getInstanceName();
|
||||
|
||||
Builder<T, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> setInstanceName(String name);
|
||||
|
||||
String getServerName();
|
||||
|
||||
Builder<T, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> setServerName(String serverName);
|
||||
|
||||
String getDatabaseName();
|
||||
|
||||
Builder<T, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> setDatabaseName(String databaseName);
|
||||
|
||||
Optional<ReplicationConfiguration> getReplicationConfiguration();
|
||||
|
||||
Builder<T, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> setReplicationConfiguration(
|
||||
Optional<ReplicationConfiguration> replicationConfiguration);
|
||||
|
||||
String getOutputReplicationExchangeName();
|
||||
|
||||
Builder<T, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> setOutputReplicationExchangeName(String outputReplicationExchangeName);
|
||||
|
||||
RabbitMQEndpoint getRabbitConfiguration();
|
||||
|
||||
Builder<T, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> setRabbitConfiguration(RabbitMQEndpoint rabbitConfiguration);
|
||||
|
||||
Database getDatabaseConfiguration();
|
||||
|
||||
Builder<T, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> setDatabaseConfiguration(Database databaseConfiguration);
|
||||
|
||||
String getCommaSeparatedEmailAddressesToNotifyOfStartup();
|
||||
|
||||
Builder<T, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> setCommaSeparatedEmailAddressesToNotifyOfStartup(
|
||||
String commaSeparatedEmailAddressesToNotifyOfStartup);
|
||||
|
||||
/**
|
||||
* A timeout for interacting with the instance, such as when creating an SSH / SFTP connection or waiting for its
|
||||
* public IP address.
|
||||
*/
|
||||
Optional<Duration> getOptionalTimeout();
|
||||
|
||||
Builder<T, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> setOptionalTimeout(Optional<Duration> optionalTimeout);
|
||||
}
|
||||
|
||||
protected abstract static class BuilderImpl<T extends StartAwsHost<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT>, ShardingKey,
|
||||
MetricsT extends ApplicationProcessMetrics,
|
||||
MasterProcessT extends ApplicationMasterProcess<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT>,
|
||||
ReplicaProcessT extends ApplicationReplicaProcess<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT>,
|
||||
HostT extends AwsInstance<ShardingKey, MetricsT>> implements Builder<T, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> {
|
||||
private AmazonMachineImage<ShardingKey, MetricsT> machineImage;
|
||||
private String imageType;
|
||||
private Optional<Release> release = Optional.empty();
|
||||
private AwsLandscape<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT> landscape;
|
||||
private InstanceType instanceType;
|
||||
private AwsAvailabilityZone availabilityZone;
|
||||
private String keyName;
|
||||
private Iterable<SecurityGroup> securityGroups;
|
||||
private Optional<Tags> tags = Optional.empty();
|
||||
private String[] userData;
|
||||
private AwsRegion region;
|
||||
private String instanceName;
|
||||
private String serverName;
|
||||
private String databaseName;
|
||||
private Database databaseConfiguration;
|
||||
private RabbitMQEndpoint rabbitConfiguration;
|
||||
private String outputReplicationExchangeName;
|
||||
private Optional<ReplicationConfiguration> replicationConfiguration;
|
||||
private String commaSeparatedEmailAddressesToNotifyOfStartup;
|
||||
private Optional<Duration> optionalTimeout;
|
||||
|
||||
@Override
|
||||
public AmazonMachineImage<ShardingKey, MetricsT> getMachineImage() {
|
||||
return machineImage == null ? getLatestImageOfType(getImageType(), getLandscape(), getRegion()) : machineImage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder<T, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> setMachineImage(
|
||||
AmazonMachineImage<ShardingKey, MetricsT> machineImage) {
|
||||
this.machineImage = machineImage;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getImageType() {
|
||||
return imageType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder<T, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> setImageType(
|
||||
String imageType) {
|
||||
this.imageType = imageType;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Release> getRelease() {
|
||||
return release;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder<T, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> setRelease(Optional<Release> release) {
|
||||
this.release = release;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AwsLandscape<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT> getLandscape() {
|
||||
return landscape;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder<T, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> setLandscape(
|
||||
AwsLandscape<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT> landscape) {
|
||||
this.landscape = landscape;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InstanceType getInstanceType() {
|
||||
return instanceType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder<T, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> setInstanceType(
|
||||
InstanceType instanceType) {
|
||||
this.instanceType = instanceType;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AwsAvailabilityZone getAvailabilityZone() {
|
||||
return availabilityZone == null ? getRandomAvailabilityZone(getRegion(), getLandscape()) : availabilityZone;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder<T, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> setAvailabilityZone(
|
||||
AwsAvailabilityZone availabilityZone) {
|
||||
this.availabilityZone = availabilityZone;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKeyName() {
|
||||
return keyName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder<T, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> setKeyName(String keyName) {
|
||||
this.keyName = keyName;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<SecurityGroup> getSecurityGroups() {
|
||||
return securityGroups == null ? Collections.singleton(getLandscape().getDefaultSecurityGroupForApplicationHosts(getRegion())) : securityGroups;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder<T, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> setSecurityGroups(
|
||||
Iterable<SecurityGroup> securityGroups) {
|
||||
this.securityGroups = securityGroups;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Tags> getTags() {
|
||||
return tags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder<T, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> setTags(Optional<Tags> tags) {
|
||||
this.tags = tags;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getUserData() {
|
||||
return userData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder<T, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> setUserData(
|
||||
String[] userData) {
|
||||
this.userData = userData;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AwsRegion getRegion() {
|
||||
return region == null ? getAvailabilityZone().getRegion() : region;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder<T, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> setRegion(AwsRegion region) {
|
||||
this.region = region;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInstanceName() {
|
||||
return instanceName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder<T, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> setInstanceName(String instanceName) {
|
||||
this.instanceName = instanceName;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServerName() {
|
||||
return serverName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder<T, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> setServerName(String serverName) {
|
||||
this.serverName = serverName;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDatabaseName() {
|
||||
return databaseName == null ? getServerName() : databaseName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder<T, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> setDatabaseName(String databaseName) {
|
||||
this.databaseName = databaseName;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Database getDatabaseConfiguration() {
|
||||
return databaseConfiguration == null ? getLandscape().getDatabase(getRegion(), getDatabaseName()) : databaseConfiguration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder<T, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> setDatabaseConfiguration(Database databaseConfiguration) {
|
||||
this.databaseConfiguration = databaseConfiguration;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RabbitMQEndpoint getRabbitConfiguration() {
|
||||
return rabbitConfiguration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder<T, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> setRabbitConfiguration(RabbitMQEndpoint rabbitConfiguration) {
|
||||
this.rabbitConfiguration = rabbitConfiguration;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOutputReplicationExchangeName() {
|
||||
return outputReplicationExchangeName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder<T, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> setOutputReplicationExchangeName(String outputReplicationExchangeName) {
|
||||
this.outputReplicationExchangeName = outputReplicationExchangeName;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<ReplicationConfiguration> getReplicationConfiguration() {
|
||||
return replicationConfiguration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder<T, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> setReplicationConfiguration(Optional<ReplicationConfiguration> replicationConfiguration) {
|
||||
this.replicationConfiguration = replicationConfiguration;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommaSeparatedEmailAddressesToNotifyOfStartup() {
|
||||
return commaSeparatedEmailAddressesToNotifyOfStartup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder<T, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> setCommaSeparatedEmailAddressesToNotifyOfStartup(String commaSeparatedEmailAddressesToNotifyOfStartup) {
|
||||
this.commaSeparatedEmailAddressesToNotifyOfStartup = commaSeparatedEmailAddressesToNotifyOfStartup;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Duration> getOptionalTimeout() {
|
||||
return optionalTimeout == null ? Optional.empty() : optionalTimeout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder<T, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> setOptionalTimeout(
|
||||
Optional<Duration> optionalTimeout) {
|
||||
this.optionalTimeout = optionalTimeout;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
protected StartAwsHost(Builder<? extends StartAwsHost<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT>, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> builder) {
|
||||
super(builder);
|
||||
this.userData = new ArrayList<>();
|
||||
for (final String ud : userData) {
|
||||
for (final String ud : builder.getUserData()) {
|
||||
this.userData.add(ud);
|
||||
}
|
||||
this.instanceType = instanceType;
|
||||
this.availabilityZone = availabilityZone;
|
||||
this.keyName = keyName;
|
||||
this.tags = tags;
|
||||
this.securityGroups = securityGroups;
|
||||
release.ifPresent(this::addUserData);
|
||||
this.instanceType = builder.getInstanceType();
|
||||
this.availabilityZone = builder.getAvailabilityZone();
|
||||
this.keyName = builder.getKeyName();
|
||||
this.tags = builder.getTags();
|
||||
this.securityGroups = builder.getSecurityGroups();
|
||||
builder.getRelease().ifPresent(this::addUserData);
|
||||
addUserData(builder.getDatabaseConfiguration());
|
||||
addUserData(builder.getRabbitConfiguration());
|
||||
addUserData(ProcessConfigurationVariable.SERVER_NAME, builder.getServerName());
|
||||
addUserData(ProcessConfigurationVariable.REPLICATION_CHANNEL, builder.getOutputReplicationExchangeName());
|
||||
addUserData(ProcessConfigurationVariable.SERVER_STARTUP_NOTIFY, builder.getCommaSeparatedEmailAddressesToNotifyOfStartup());
|
||||
builder.getReplicationConfiguration().ifPresent(this::addUserData);
|
||||
}
|
||||
|
||||
public StartAwsHost(AmazonMachineImage<ShardingKey, MetricsT> machineImage,
|
||||
Optional<Release> release,
|
||||
AwsLandscape<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT> landscape, InstanceType instanceType, AwsAvailabilityZone availabilityZone, String keyName,
|
||||
Optional<Tags> tags, String[] userData) {
|
||||
this(machineImage, release, landscape, instanceType, availabilityZone,
|
||||
keyName,
|
||||
Collections.singleton(landscape.getDefaultSecurityGroupForApplicationHosts(availabilityZone.getRegion())), tags, userData);
|
||||
}
|
||||
|
||||
protected static <ShardingKey,
|
||||
MetricsT extends ApplicationProcessMetrics,
|
||||
MasterProcessT extends ApplicationMasterProcess<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT>,
|
||||
@@ -132,27 +504,20 @@ extends StartHost<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT>
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
host = getLandscape().launchHost(getMachineImage(), getInstanceType(), getAvailabilityZone(), getKeyName(), getSecurityGroups(), getTags(),
|
||||
Util.toArray(getUserData(), new String[0]));
|
||||
} catch (URISyntaxException e) {
|
||||
logger.log(Level.SEVERE, "Exception trying to launch host", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
public void run() throws Exception {
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
HostT castHost = (HostT) getLandscape().launchHost(getMachineImage(), getInstanceType(), getAvailabilityZone(), getKeyName(), getSecurityGroups(), getTags(),
|
||||
Util.toArray(getUserData(), new String[0]));
|
||||
host = castHost;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code null} before {@link #run()} is called; the host launched afterwards
|
||||
*/
|
||||
public AwsInstance<ShardingKey, MetricsT> getHost() {
|
||||
public HostT getHost() {
|
||||
return host;
|
||||
}
|
||||
|
||||
public void setHost(AwsInstance<ShardingKey, MetricsT> host) {
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
private Optional<Tags> getTags() {
|
||||
return tags;
|
||||
}
|
||||
|
||||
+1
-4
@@ -1,11 +1,8 @@
|
||||
package com.sap.sailing.landscape;
|
||||
package com.sap.sse.landscape;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.sap.sse.landscape.Landscape;
|
||||
import com.sap.sse.landscape.ProcessConfigurationVariable;
|
||||
import com.sap.sse.landscape.UserDataProvider;
|
||||
import com.sap.sse.landscape.rabbitmq.RabbitMQEndpoint;
|
||||
|
||||
/**
|
||||
+1
-3
@@ -1,6 +1,4 @@
|
||||
package com.sap.sailing.landscape;
|
||||
|
||||
import com.sap.sse.landscape.UserDataProvider;
|
||||
package com.sap.sse.landscape;
|
||||
|
||||
/**
|
||||
* Can be used to authenticate a replica to its master. Authentication may happen by
|
||||
+2
-1
@@ -2,5 +2,6 @@ package com.sap.sse.landscape.application;
|
||||
|
||||
public interface ApplicationMasterProcess<ShardingKey, MetricsT extends ApplicationProcessMetrics,
|
||||
MasterProcessT extends ApplicationMasterProcess<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT>,
|
||||
ReplicaProcessT extends ApplicationReplicaProcess<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT>> extends ApplicationProcess<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT> {
|
||||
ReplicaProcessT extends ApplicationReplicaProcess<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT>>
|
||||
extends ApplicationProcess<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT> {
|
||||
}
|
||||
|
||||
@@ -16,10 +16,27 @@ extends AbstractProcedureImpl<ShardingKey, MetricsT, MasterProcessT, ReplicaProc
|
||||
implements Procedure<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT> {
|
||||
private final MachineImage machineImage;
|
||||
|
||||
public StartHost(MachineImage machineImage,
|
||||
Landscape<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT> landscape) {
|
||||
super(landscape);
|
||||
this.machineImage = machineImage;
|
||||
/**
|
||||
* A builder that helps building an instance of type {@link StartHost} or any subclass thereof (then using
|
||||
* specialized builders).
|
||||
*
|
||||
* @author Axel Uhl (D043530)
|
||||
*/
|
||||
public static interface Builder<T extends StartHost<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT>, ShardingKey,
|
||||
MetricsT extends ApplicationProcessMetrics,
|
||||
MasterProcessT extends ApplicationMasterProcess<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT>,
|
||||
ReplicaProcessT extends ApplicationReplicaProcess<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT>,
|
||||
HostT extends Host> {
|
||||
T build();
|
||||
|
||||
MachineImage getMachineImage();
|
||||
|
||||
Landscape<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT> getLandscape();
|
||||
}
|
||||
|
||||
protected StartHost(Builder<? extends StartHost<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT>, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> builder) {
|
||||
super(builder.getLandscape());
|
||||
this.machineImage = builder.getMachineImage();
|
||||
}
|
||||
|
||||
protected MachineImage getMachineImage() {
|
||||
|
||||
Reference in New Issue
Block a user