You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aurora.apache.org by wf...@apache.org on 2016/04/07 06:50:12 UTC
aurora git commit: Set DiscoveryInfo in mesos tasks.
Repository: aurora
Updated Branches:
refs/heads/master 2f480c7f3 -> 915459dac
Set DiscoveryInfo in mesos tasks.
This allows alternative service discovery methodologies
to find tasks from Aurora (e.g. mesos-dns), especially
the dynamic port mapping.
Bugs closed: AURORA-1629
Reviewed at https://reviews.apache.org/r/45177/
Project: http://git-wip-us.apache.org/repos/asf/aurora/repo
Commit: http://git-wip-us.apache.org/repos/asf/aurora/commit/915459da
Tree: http://git-wip-us.apache.org/repos/asf/aurora/tree/915459da
Diff: http://git-wip-us.apache.org/repos/asf/aurora/diff/915459da
Branch: refs/heads/master
Commit: 915459dac76ed0732addce87420a4ba51d916de8
Parents: 2f480c7
Author: Zhitao Li <zh...@gmail.com>
Authored: Wed Apr 6 21:31:48 2016 -0700
Committer: Bill Farner <wf...@apache.org>
Committed: Wed Apr 6 21:31:48 2016 -0700
----------------------------------------------------------------------
RELEASE-NOTES.md | 3 +
docs/features/service-discovery.md | 30 ++++++
docs/reference/scheduler-configuration.md | 3 +
examples/vagrant/upstart/aurora-scheduler.conf | 1 +
.../configuration/executor/ExecutorModule.java | 10 +-
.../executor/ExecutorSettings.java | 8 +-
.../scheduler/mesos/MesosTaskFactory.java | 41 +++++++-
.../scheduler/mesos/TestExecutorSettings.java | 6 +-
.../mesos/MesosTaskFactoryImplTest.java | 103 ++++++++++++++++---
.../apache/aurora/e2e/http/http_example.aurora | 13 ++-
.../sh/org/apache/aurora/e2e/test_end_to_end.sh | 44 ++++++++
11 files changed, 238 insertions(+), 24 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/aurora/blob/915459da/RELEASE-NOTES.md
----------------------------------------------------------------------
diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md
index 46fa2d4..ebc252f 100644
--- a/RELEASE-NOTES.md
+++ b/RELEASE-NOTES.md
@@ -26,6 +26,9 @@
- Added scheduler argument `-require_docker_use_executor` that indicates whether the scheduler
should accept tasks that use the Docker containerizer without an executor (experimental).
- Jobs referencing invalid tier name will be rejected by the scheduler.
+- Added a new scheduler argument `--populate_discovery_info`. If set to true, Aurora will start
+ to populate DiscoveryInfo field on TaskInfo of Mesos. This could be used for alternative
+ service discovery solution like Mesos-DNS.
### Deprecations and removals:
http://git-wip-us.apache.org/repos/asf/aurora/blob/915459da/docs/features/service-discovery.md
----------------------------------------------------------------------
diff --git a/docs/features/service-discovery.md b/docs/features/service-discovery.md
index 858ca2a..f242730 100644
--- a/docs/features/service-discovery.md
+++ b/docs/features/service-discovery.md
@@ -12,3 +12,33 @@ of which there are several reference implementations:
These can also be used natively in Finagle using the [ZookeeperServerSetCluster](https://github.com/twitter/finagle/blob/master/finagle-serversets/src/main/scala/com/twitter/finagle/zookeeper/ZookeeperServerSetCluster.scala).
For more information about how to configure announcing, see the [Configuration Reference](../reference/configuration.md).
+
+Using Mesos DiscoveryInfo
+-------------------------
+Experimental support for populating DiscoveryInfo in Mesos is introduced in Aurora. This can be used to build
+custom service discovery system not using zookeeper. Please see `Service Discovery` section in
+[Mesos Framework Development guide](http://mesos.apache.org/documentation/latest/app-framework-development-guide/) for
+explanation of the protobuf message in Mesos.
+
+To use this feature, please enable `--populate_discovery_info` flag on scheduler. All jobs started by scheduler
+afterwards will have their portmap populated to Mesos and discoverable in `/state` endpoint in Mesos master and agent.
+
+### Using Mesos DNS
+An example is using [Mesos-DNS](https://github.com/mesosphere/mesos-dns), which is able to generate multiple DNS
+records. With current implementation, the example job with key `devcluster/vagrant/test/http-example` generates at
+least the following:
+
+1. An A record for `http_example.test.vagrant.twitterscheduler.mesos` (which only includes IP address);
+2. A [SRV record](https://en.wikipedia.org/wiki/SRV_record) for
+ `_http_example.test.vagrant._tcp.twitterscheduler.mesos`, which includes IP address and every port. This should only
+ be used if the service has one port.
+3. A SRV record `_{port-name}._http_example.test.vagrant._tcp.twitterscheduler.mesos` for each port name
+ defined. This should be used when the service has multiple ports.
+
+Things to note:
+
+1. The domain part (".mesos" in above example) can be configured in [Mesos DNS](http://mesosphere.github.io/mesos-dns/docs/configuration-parameters.html);
+2. The `twitterscheduler` part is the lower-case of framework name, which is not configurable right now (see
+ [TWITTER_SCHEDULER_NAME](https://github.com/apache/aurora/blob/master/src/main/java/org/apache/aurora/scheduler/mesos/CommandLineDriverSettingsModule.java#L98));
+3. Right now, portmap and port aliases in announcer object are not reflected in DiscoveryInfo, therefore not visible in
+ Mesos DNS records either. This is because they are only resolved in thermos executors.
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/aurora/blob/915459da/docs/reference/scheduler-configuration.md
----------------------------------------------------------------------
diff --git a/docs/reference/scheduler-configuration.md b/docs/reference/scheduler-configuration.md
index e6c0bb6..f08603a 100644
--- a/docs/reference/scheduler-configuration.md
+++ b/docs/reference/scheduler-configuration.md
@@ -230,6 +230,9 @@ Optional flags:
-offer_reservation_duration=(3, mins)
Time to reserve a slave's offers while trying to satisfy a task preempting another.
(org.apache.aurora.scheduler.scheduling.SchedulingModule.offer_reservation_duration)
+-populate_discovery_info=false
+ If true, Aurora populates DiscoveryInfo field of Mesos TaskInfo.
+ (org.apache.aurora.scheduler.configuration.executor.ExecutorModule.populate_discovery_info)
-preemption_delay=(3, mins)
Time interval after which a pending task becomes eligible to preempt other tasks
(org.apache.aurora.scheduler.preemptor.PreemptorModule.preemption_delay)
http://git-wip-us.apache.org/repos/asf/aurora/blob/915459da/examples/vagrant/upstart/aurora-scheduler.conf
----------------------------------------------------------------------
diff --git a/examples/vagrant/upstart/aurora-scheduler.conf b/examples/vagrant/upstart/aurora-scheduler.conf
index d61801c..b9732d2 100644
--- a/examples/vagrant/upstart/aurora-scheduler.conf
+++ b/examples/vagrant/upstart/aurora-scheduler.conf
@@ -49,4 +49,5 @@ exec bin/aurora-scheduler \
-enable_h2_console=true \
-tier_config=/home/vagrant/aurora/src/main/resources/org/apache/aurora/scheduler/tiers.json \
-mesos_role=aurora-role \
+ -populate_discovery_info=true \
-receive_revocable_resources=true
http://git-wip-us.apache.org/repos/asf/aurora/blob/915459da/src/main/java/org/apache/aurora/scheduler/configuration/executor/ExecutorModule.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/configuration/executor/ExecutorModule.java b/src/main/java/org/apache/aurora/scheduler/configuration/executor/ExecutorModule.java
index add1270..1fe27a5 100644
--- a/src/main/java/org/apache/aurora/scheduler/configuration/executor/ExecutorModule.java
+++ b/src/main/java/org/apache/aurora/scheduler/configuration/executor/ExecutorModule.java
@@ -103,6 +103,10 @@ public class ExecutorModule extends AbstractModule {
+ "into all (non-mesos) containers.")
private static final Arg<List<Volume>> GLOBAL_CONTAINER_MOUNTS = Arg.create(ImmutableList.of());
+ @CmdLine(name = "populate_discovery_info",
+ help = "If true, Aurora populates DiscoveryInfo field of Mesos TaskInfo.")
+ private static final Arg<Boolean> POPULATE_DISCOVERY_INFO = Arg.create(false);
+
@VisibleForTesting
static CommandInfo makeExecutorCommand(
String thermosExecutorPath,
@@ -165,7 +169,8 @@ public class ExecutorModule extends AbstractModule {
.addResources(makeResource(CPUS, EXECUTOR_OVERHEAD_CPUS.get()))
.addResources(makeResource(RAM_MB, EXECUTOR_OVERHEAD_RAM.get().as(Data.MB)))
.build(),
- volumeMounts));
+ volumeMounts),
+ POPULATE_DISCOVERY_INFO.get());
}
private static ExecutorSettings makeCustomExecutorSettings() {
@@ -175,7 +180,8 @@ public class ExecutorModule extends AbstractModule {
ExecutorSettingsLoader.read(
Files.newBufferedReader(
CUSTOM_EXECUTOR_CONFIG.get().toPath(),
- StandardCharsets.UTF_8)));
+ StandardCharsets.UTF_8)),
+ POPULATE_DISCOVERY_INFO.get());
} catch (ExecutorSettingsLoader.ExecutorConfigException | IOException e) {
throw new IllegalArgumentException("Failed to read executor settings: " + e, e);
}
http://git-wip-us.apache.org/repos/asf/aurora/blob/915459da/src/main/java/org/apache/aurora/scheduler/configuration/executor/ExecutorSettings.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/configuration/executor/ExecutorSettings.java b/src/main/java/org/apache/aurora/scheduler/configuration/executor/ExecutorSettings.java
index 7beea81..e4279b1 100644
--- a/src/main/java/org/apache/aurora/scheduler/configuration/executor/ExecutorSettings.java
+++ b/src/main/java/org/apache/aurora/scheduler/configuration/executor/ExecutorSettings.java
@@ -27,9 +27,11 @@ import static java.util.Objects.requireNonNull;
*/
public class ExecutorSettings {
private final ExecutorConfig config;
+ private final boolean populateDiscoveryInfo;
- public ExecutorSettings(ExecutorConfig config) {
+ public ExecutorSettings(ExecutorConfig config, boolean populateDiscoveryInfo) {
this.config = requireNonNull(config);
+ this.populateDiscoveryInfo = populateDiscoveryInfo;
}
public ExecutorConfig getExecutorConfig() {
@@ -38,6 +40,10 @@ public class ExecutorSettings {
return config;
}
+ public boolean shouldPopulateDiscoverInfo() {
+ return populateDiscoveryInfo;
+ }
+
private double getExecutorResourceValue(ResourceType resource) {
return config.getExecutor().getResourcesList().stream()
.filter(r -> r.getName().equals(resource.getName()))
http://git-wip-us.apache.org/repos/asf/aurora/blob/915459da/src/main/java/org/apache/aurora/scheduler/mesos/MesosTaskFactory.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/mesos/MesosTaskFactory.java b/src/main/java/org/apache/aurora/scheduler/mesos/MesosTaskFactory.java
index 85c550b..fb7c7b2 100644
--- a/src/main/java/org/apache/aurora/scheduler/mesos/MesosTaskFactory.java
+++ b/src/main/java/org/apache/aurora/scheduler/mesos/MesosTaskFactory.java
@@ -14,6 +14,7 @@
package org.apache.aurora.scheduler.mesos;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
@@ -38,15 +39,18 @@ import org.apache.aurora.scheduler.storage.entities.IAssignedTask;
import org.apache.aurora.scheduler.storage.entities.IDockerContainer;
import org.apache.aurora.scheduler.storage.entities.IJobKey;
import org.apache.aurora.scheduler.storage.entities.IMetadata;
+import org.apache.aurora.scheduler.storage.entities.IServerInfo;
import org.apache.aurora.scheduler.storage.entities.ITaskConfig;
import org.apache.mesos.Protos;
import org.apache.mesos.Protos.CommandInfo;
import org.apache.mesos.Protos.ContainerInfo;
+import org.apache.mesos.Protos.DiscoveryInfo;
import org.apache.mesos.Protos.ExecutorID;
import org.apache.mesos.Protos.ExecutorInfo;
import org.apache.mesos.Protos.Label;
import org.apache.mesos.Protos.Labels;
import org.apache.mesos.Protos.Offer;
+import org.apache.mesos.Protos.Port;
import org.apache.mesos.Protos.Resource;
import org.apache.mesos.Protos.TaskID;
import org.apache.mesos.Protos.TaskInfo;
@@ -78,13 +82,22 @@ public interface MesosTaskFactory {
@VisibleForTesting
static final String METADATA_LABEL_PREFIX = "org.apache.aurora.metadata.";
+ @VisibleForTesting
+ static final String DEFAULT_PORT_PROTOCOL = "TCP";
+
private final ExecutorSettings executorSettings;
private final TierManager tierManager;
+ private final IServerInfo serverInfo;
@Inject
- MesosTaskFactoryImpl(ExecutorSettings executorSettings, TierManager tierManager) {
+ MesosTaskFactoryImpl(
+ ExecutorSettings executorSettings,
+ TierManager tierManager,
+ IServerInfo serverInfo) {
+
this.executorSettings = requireNonNull(executorSettings);
this.tierManager = requireNonNull(tierManager);
+ this.serverInfo = requireNonNull(serverInfo);
}
@VisibleForTesting
@@ -105,6 +118,11 @@ public interface MesosTaskFactory {
return String.format("%s.%s", getJobSourceName(task), instanceId);
}
+ @VisibleForTesting
+ static String getInverseJobSourceName(IJobKey job) {
+ return String.format("%s.%s.%s", job.getName(), job.getEnvironment(), job.getRole());
+ }
+
private static byte[] serializeTask(IAssignedTask task) throws SchedulerException {
try {
return ThriftBinaryCodec.encode(task.newBuilder());
@@ -146,6 +164,10 @@ public interface MesosTaskFactory {
configureTaskLabels(config.getMetadata(), taskBuilder);
+ if (executorSettings.shouldPopulateDiscoverInfo()) {
+ configureDiscoveryInfos(task, taskBuilder);
+ }
+
if (config.getContainer().isSetMesos()) {
configureTaskForNoContainer(task, taskBuilder, acceptedOffer);
} else if (config.getContainer().isSetDocker()) {
@@ -220,5 +242,22 @@ public interface MesosTaskFactory {
taskBuilder.setLabels(Labels.newBuilder().addAllLabels(labels));
}
}
+
+ private void configureDiscoveryInfos(IAssignedTask task, TaskInfo.Builder taskBuilder) {
+ DiscoveryInfo.Builder builder = taskBuilder.getDiscoveryBuilder();
+ builder.setVisibility(DiscoveryInfo.Visibility.CLUSTER);
+ builder.setName(getInverseJobSourceName(task.getTask().getJob()));
+ builder.setEnvironment(task.getTask().getJob().getEnvironment());
+ // A good sane choice for default location is current Aurora cluster name.
+ builder.setLocation(serverInfo.getClusterName());
+ for (Map.Entry<String, Integer> entry : task.getAssignedPorts().entrySet()) {
+ builder.getPortsBuilder().addPorts(
+ Port.newBuilder()
+ .setName(entry.getKey())
+ .setNumber(entry.getValue())
+ .setProtocol(DEFAULT_PORT_PROTOCOL)
+ );
+ }
+ }
}
}
http://git-wip-us.apache.org/repos/asf/aurora/blob/915459da/src/main/java/org/apache/aurora/scheduler/mesos/TestExecutorSettings.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/mesos/TestExecutorSettings.java b/src/main/java/org/apache/aurora/scheduler/mesos/TestExecutorSettings.java
index 7110fbd..8cef410 100644
--- a/src/main/java/org/apache/aurora/scheduler/mesos/TestExecutorSettings.java
+++ b/src/main/java/org/apache/aurora/scheduler/mesos/TestExecutorSettings.java
@@ -66,12 +66,14 @@ public final class TestExecutorSettings {
public static final ExecutorConfig THERMOS_CONFIG =
new ExecutorConfig(THERMOS_EXECUTOR_INFO, ImmutableList.of());
- public static final ExecutorSettings THERMOS_EXECUTOR = new ExecutorSettings(THERMOS_CONFIG);
+ public static final ExecutorSettings THERMOS_EXECUTOR = new ExecutorSettings(
+ THERMOS_CONFIG, false);
public static ExecutorSettings thermosOnlyWithOverhead(ResourceSlot overhead) {
ExecutorConfig config = THERMOS_EXECUTOR.getExecutorConfig();
ExecutorInfo.Builder executor = config.getExecutor().toBuilder();
executor.clearResources().addAllResources(overhead.toResourceList(TaskTestUtil.DEV_TIER));
- return new ExecutorSettings(new ExecutorConfig(executor.build(), config.getVolumeMounts()));
+ return new ExecutorSettings(
+ new ExecutorConfig(executor.build(), config.getVolumeMounts()), false);
}
}
http://git-wip-us.apache.org/repos/asf/aurora/blob/915459da/src/test/java/org/apache/aurora/scheduler/mesos/MesosTaskFactoryImplTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/mesos/MesosTaskFactoryImplTest.java b/src/test/java/org/apache/aurora/scheduler/mesos/MesosTaskFactoryImplTest.java
index 3a60486..4f5ac15 100644
--- a/src/test/java/org/apache/aurora/scheduler/mesos/MesosTaskFactoryImplTest.java
+++ b/src/test/java/org/apache/aurora/scheduler/mesos/MesosTaskFactoryImplTest.java
@@ -13,6 +13,7 @@
*/
package org.apache.aurora.scheduler.mesos;
+import java.util.Map;
import java.util.stream.Collectors;
import com.google.common.collect.ImmutableList;
@@ -26,6 +27,7 @@ import org.apache.aurora.gen.Container;
import org.apache.aurora.gen.DockerContainer;
import org.apache.aurora.gen.DockerParameter;
import org.apache.aurora.gen.MesosContainer;
+import org.apache.aurora.gen.ServerInfo;
import org.apache.aurora.gen.TaskConfig;
import org.apache.aurora.scheduler.ResourceSlot;
import org.apache.aurora.scheduler.ResourceType;
@@ -36,6 +38,8 @@ import org.apache.aurora.scheduler.configuration.executor.ExecutorConfig;
import org.apache.aurora.scheduler.configuration.executor.ExecutorSettings;
import org.apache.aurora.scheduler.mesos.MesosTaskFactory.MesosTaskFactoryImpl;
import org.apache.aurora.scheduler.storage.entities.IAssignedTask;
+import org.apache.aurora.scheduler.storage.entities.IJobKey;
+import org.apache.aurora.scheduler.storage.entities.IServerInfo;
import org.apache.aurora.scheduler.storage.entities.ITaskConfig;
import org.apache.mesos.Protos;
import org.apache.mesos.Protos.ContainerInfo;
@@ -55,7 +59,9 @@ import org.junit.Test;
import static org.apache.aurora.scheduler.ResourceSlot.makeMesosRangeResource;
import static org.apache.aurora.scheduler.base.TaskTestUtil.DEV_TIER;
import static org.apache.aurora.scheduler.base.TaskTestUtil.REVOCABLE_TIER;
+import static org.apache.aurora.scheduler.mesos.MesosTaskFactory.MesosTaskFactoryImpl.DEFAULT_PORT_PROTOCOL;
import static org.apache.aurora.scheduler.mesos.MesosTaskFactory.MesosTaskFactoryImpl.METADATA_LABEL_PREFIX;
+import static org.apache.aurora.scheduler.mesos.MesosTaskFactory.MesosTaskFactoryImpl.getInverseJobSourceName;
import static org.apache.aurora.scheduler.mesos.TaskExecutors.NO_OVERHEAD_EXECUTOR;
import static org.apache.aurora.scheduler.mesos.TaskExecutors.SOME_OVERHEAD_EXECUTOR;
import static org.apache.aurora.scheduler.mesos.TestExecutorSettings.THERMOS_CONFIG;
@@ -107,6 +113,10 @@ public class MesosTaskFactoryImplTest extends EasyMockTest {
.addResources(makeMesosRangeResource(ResourceType.PORTS, ImmutableSet.of(80)))
.build();
+ private static final String CLUSTER_NAME = "cluster_name";
+ private static final IServerInfo SERVER_INFO = IServerInfo.build(
+ new ServerInfo(CLUSTER_NAME, ""));
+
private MesosTaskFactory taskFactory;
private ExecutorSettings config;
private TierManager tierManager;
@@ -142,7 +152,7 @@ public class MesosTaskFactoryImplTest extends EasyMockTest {
@Test
public void testExecutorInfoUnchanged() {
expect(tierManager.getTier(TASK_CONFIG)).andReturn(DEV_TIER);
- taskFactory = new MesosTaskFactoryImpl(config, tierManager);
+ taskFactory = new MesosTaskFactoryImpl(config, tierManager, SERVER_INFO);
control.replay();
@@ -150,12 +160,13 @@ public class MesosTaskFactoryImplTest extends EasyMockTest {
assertEquals(populateDynamicFields(DEFAULT_EXECUTOR, TASK), task.getExecutor());
checkTaskResources(TASK.getTask(), task);
+ checkDiscoveryInfoUnset(task);
}
@Test
public void testTaskInfoRevocable() {
expect(tierManager.getTier(TASK_CONFIG)).andReturn(REVOCABLE_TIER);
- taskFactory = new MesosTaskFactoryImpl(config, tierManager);
+ taskFactory = new MesosTaskFactoryImpl(config, tierManager, SERVER_INFO);
Resource revocableCPU = OFFER_THERMOS_EXECUTOR.getResources(0).toBuilder()
.setRevocable(Resource.RevocableInfo.getDefaultInstance())
@@ -170,6 +181,7 @@ public class MesosTaskFactoryImplTest extends EasyMockTest {
TaskInfo task = taskFactory.createFrom(TASK, withRevocable);
checkTaskResources(TASK.getTask(), task);
assertTrue(task.getResourcesList().stream().anyMatch(Resource::hasRevocable));
+ checkDiscoveryInfoUnset(task);
}
@Test
@@ -179,12 +191,13 @@ public class MesosTaskFactoryImplTest extends EasyMockTest {
builder.unsetAssignedPorts();
IAssignedTask assignedTask = IAssignedTask.build(builder);
expect(tierManager.getTier(assignedTask.getTask())).andReturn(DEV_TIER);
- taskFactory = new MesosTaskFactoryImpl(config, tierManager);
+ taskFactory = new MesosTaskFactoryImpl(config, tierManager, SERVER_INFO);
control.replay();
TaskInfo task = taskFactory.createFrom(IAssignedTask.build(builder), OFFER_THERMOS_EXECUTOR);
checkTaskResources(ITaskConfig.build(builder.getTask()), task);
+ checkDiscoveryInfoUnset(task);
}
@Test
@@ -193,7 +206,7 @@ public class MesosTaskFactoryImplTest extends EasyMockTest {
// + executor overhead. We need to ensure we allocate a non-zero amount of ram in this case.
config = NO_OVERHEAD_EXECUTOR;
expect(tierManager.getTier(TASK_CONFIG)).andReturn(DEV_TIER);
- taskFactory = new MesosTaskFactoryImpl(config, tierManager);
+ taskFactory = new MesosTaskFactoryImpl(config, tierManager, SERVER_INFO);
control.replay();
@@ -206,6 +219,7 @@ public class MesosTaskFactoryImplTest extends EasyMockTest {
// Simulate the upsizing needed for the task to meet the minimum thermos requirements.
TaskConfig dummyTask = TASK.getTask().newBuilder();
checkTaskResources(ITaskConfig.build(dummyTask), task);
+ checkDiscoveryInfoUnset(task);
}
private void checkTaskResources(ITaskConfig task, TaskInfo taskInfo) {
@@ -214,6 +228,32 @@ public class MesosTaskFactoryImplTest extends EasyMockTest {
getTotalTaskResources(taskInfo));
}
+ private void checkDiscoveryInfoUnset(TaskInfo taskInfo) {
+ assertFalse(taskInfo.hasDiscovery());
+ }
+
+ private void checkDiscoveryInfo(
+ TaskInfo taskInfo,
+ Map<String, Integer> assignedPorts,
+ IJobKey job) {
+
+ assertTrue(taskInfo.hasDiscovery());
+ Protos.DiscoveryInfo.Builder expectedDiscoveryInfo = Protos.DiscoveryInfo.newBuilder()
+ .setVisibility(Protos.DiscoveryInfo.Visibility.CLUSTER)
+ .setLocation(CLUSTER_NAME)
+ .setEnvironment(job.getEnvironment())
+ .setName(getInverseJobSourceName(job));
+ for (Map.Entry<String, Integer> entry : assignedPorts.entrySet()) {
+ expectedDiscoveryInfo.getPortsBuilder().addPorts(
+ Protos.Port.newBuilder()
+ .setName(entry.getKey())
+ .setProtocol(DEFAULT_PORT_PROTOCOL)
+ .setNumber(entry.getValue()));
+ }
+
+ assertEquals(expectedDiscoveryInfo.build(), taskInfo.getDiscovery());
+ }
+
private TaskInfo getDockerTaskInfo() {
return getDockerTaskInfo(TASK_WITH_DOCKER);
}
@@ -222,7 +262,7 @@ public class MesosTaskFactoryImplTest extends EasyMockTest {
config = SOME_OVERHEAD_EXECUTOR;
expect(tierManager.getTier(task.getTask())).andReturn(DEV_TIER);
- taskFactory = new MesosTaskFactoryImpl(config, tierManager);
+ taskFactory = new MesosTaskFactoryImpl(config, tierManager, SERVER_INFO);
control.replay();
@@ -246,17 +286,19 @@ public class MesosTaskFactoryImplTest extends EasyMockTest {
@Test
public void testGlobalMounts() {
- config = new ExecutorSettings(new ExecutorConfig(
- TestExecutorSettings.THERMOS_EXECUTOR_INFO,
- ImmutableList.of(
- Volume.newBuilder()
- .setHostPath("/host")
- .setContainerPath("/container")
- .setMode(Mode.RO)
- .build())));
+ config = new ExecutorSettings(
+ new ExecutorConfig(
+ TestExecutorSettings.THERMOS_EXECUTOR_INFO,
+ ImmutableList.of(
+ Volume.newBuilder()
+ .setHostPath("/host")
+ .setContainerPath("/container")
+ .setMode(Mode.RO)
+ .build())),
+ false);
expect(tierManager.getTier(TASK_WITH_DOCKER.getTask())).andReturn(DEV_TIER);
- taskFactory = new MesosTaskFactoryImpl(config, tierManager);
+ taskFactory = new MesosTaskFactoryImpl(config, tierManager, SERVER_INFO);
control.replay();
@@ -269,7 +311,7 @@ public class MesosTaskFactoryImplTest extends EasyMockTest {
@Test
public void testMetadataLabelMapping() {
expect(tierManager.getTier(TASK.getTask())).andReturn(DEV_TIER);
- taskFactory = new MesosTaskFactoryImpl(config, tierManager);
+ taskFactory = new MesosTaskFactoryImpl(config, tierManager, SERVER_INFO);
control.replay();
@@ -283,6 +325,7 @@ public class MesosTaskFactoryImplTest extends EasyMockTest {
.collect(GuavaUtils.toImmutableSet());
assertEquals(labels, metadata);
+ checkDiscoveryInfoUnset(task);
}
@Test
@@ -303,6 +346,36 @@ public class MesosTaskFactoryImplTest extends EasyMockTest {
.setImage("hello-world"))
.build();
assertEquals(expectedContainer, task.getContainer());
+ checkDiscoveryInfoUnset(task);
+ }
+
+ @Test
+ public void testPopulateDiscoveryInfoNoPort() {
+ config = new ExecutorSettings(THERMOS_CONFIG, true);
+ AssignedTask builder = TASK.newBuilder();
+ builder.getTask().unsetRequestedPorts();
+ builder.unsetAssignedPorts();
+ IAssignedTask assignedTask = IAssignedTask.build(builder);
+ expect(tierManager.getTier(assignedTask.getTask())).andReturn(DEV_TIER);
+ taskFactory = new MesosTaskFactoryImpl(config, tierManager, SERVER_INFO);
+
+ control.replay();
+
+ TaskInfo task = taskFactory.createFrom(IAssignedTask.build(builder), OFFER_THERMOS_EXECUTOR);
+ checkTaskResources(ITaskConfig.build(builder.getTask()), task);
+ checkDiscoveryInfo(task, ImmutableMap.of(), assignedTask.getTask().getJob());
+ }
+
+ @Test
+ public void testPopulateDiscoveryInfo() {
+ config = new ExecutorSettings(THERMOS_CONFIG, true);
+ expect(tierManager.getTier(TASK_CONFIG)).andReturn(DEV_TIER);
+ taskFactory = new MesosTaskFactoryImpl(config, tierManager, SERVER_INFO);
+
+ control.replay();
+ TaskInfo task = taskFactory.createFrom(TASK, OFFER_THERMOS_EXECUTOR);
+ checkTaskResources(TASK.getTask(), task);
+ checkDiscoveryInfo(task, ImmutableMap.of("http", 80), TASK.getTask().getJob());
}
private static ResourceSlot getTotalTaskResources(TaskInfo task) {
http://git-wip-us.apache.org/repos/asf/aurora/blob/915459da/src/test/sh/org/apache/aurora/e2e/http/http_example.aurora
----------------------------------------------------------------------
diff --git a/src/test/sh/org/apache/aurora/e2e/http/http_example.aurora b/src/test/sh/org/apache/aurora/e2e/http/http_example.aurora
index bb4fdec..2813b6c 100644
--- a/src/test/sh/org/apache/aurora/e2e/http/http_example.aurora
+++ b/src/test/sh/org/apache/aurora/e2e/http/http_example.aurora
@@ -16,6 +16,11 @@ import getpass
DEFAULT_CMD = 'cp /vagrant/src/test/sh/org/apache/aurora/e2e/http_example.py .'
+echo_ports = Process(
+ name = 'echo_ports',
+ cmdline = 'echo "tcp port: {{thermos.ports[tcp]}}; http port: {{thermos.ports[http]}}; alias: {{thermos.ports[alias]}}"'
+)
+
run_server = Process(
name = 'run_server',
cmdline = 'python http_example.py {{thermos.ports[http]}}')
@@ -28,8 +33,8 @@ stage_server = Process(
test_task = Task(
name = 'http_example',
resources = Resources(cpu=0.4, ram=32*MB, disk=64*MB),
- processes = [stage_server, run_server],
- constraints = order(stage_server, run_server))
+ processes = [echo_ports, stage_server, run_server],
+ constraints = order(echo_ports, stage_server, run_server))
update_config = UpdateConfig(watch_secs=10, batch_size=2)
health_check_config = HealthCheckConfig(initial_interval_secs=5, interval_secs=1)
@@ -43,7 +48,9 @@ job = Service(
role = getpass.getuser(),
environment = 'test',
contact = '{{role}}@localhost',
- announce = Announcer(),
+ announce = Announcer(
+ portmap={'alias': 'http'},
+ ),
)
jobs = [
http://git-wip-us.apache.org/repos/asf/aurora/blob/915459da/src/test/sh/org/apache/aurora/e2e/test_end_to_end.sh
----------------------------------------------------------------------
diff --git a/src/test/sh/org/apache/aurora/e2e/test_end_to_end.sh b/src/test/sh/org/apache/aurora/e2e/test_end_to_end.sh
index 3471756..eee6b4c 100755
--- a/src/test/sh/org/apache/aurora/e2e/test_end_to_end.sh
+++ b/src/test/sh/org/apache/aurora/e2e/test_end_to_end.sh
@@ -266,12 +266,55 @@ test_quota() {
aurora quota get $_cluster/$_role
}
+test_discovery_info() {
+ local _task_id_prefix=$1
+ local _discovery_name=$2
+
+ if ! [[ -x "$(command -v jq)" ]]; then
+ echo "jq is not installed, skipping discovery info test"
+ return 0
+ fi
+
+ framework_info=$(curl --silent '192.168.33.7:5050/state' | jq '.frameworks | map(select(.name == "TwitterScheduler"))')
+ if [[ -z $framework_info ]]; then
+ echo "Cannot get framework info for $framework"
+ exit 1
+ fi
+
+ task_info=$(echo $framework_info | jq --arg task_id_prefix "${_task_id_prefix}" '.[0]["tasks"] | map(select(.id | contains($task_id_prefix)))')
+ if [[ -z $task_info ]]; then
+ echo "Cannot get task blob json for task id prefix ${_task_id_prefix}"
+ exit 1
+ fi
+
+ discovery_info=$(echo $task_info | jq '.[0]["discovery"]')
+ if [[ -z $discovery_info ]]; then
+ echo "Cannot get discovery info json from task blob ${task_blob}"
+ exit 1
+ fi
+
+ name=$(echo $discovery_info | jq '.["name"]')
+ if [[ "$name" -ne "\"$_discovery_name\"" ]]; then
+ echo "discovery info name $name does not equal to expected \"$_discovery_name\""
+ exit 1
+ fi
+
+ num_ports=$(echo $discovery_info | jq '.["ports"]["ports"] | length')
+
+ if ! [[ "$num_ports" -gt 0 ]]; then
+ echo "num of ports in discovery info is $num_ports which is not greater than zero"
+ exit 1
+ fi
+}
+
test_http_example() {
local _cluster=$1 _role=$2 _env=$3
local _base_config=$4 _updated_config=$5
local _bad_healthcheck_config=$6
local _job=$7
local _jobkey="$_cluster/$_role/$_env/$_job"
+ local _task_id_prefix="${_role}-${_env}-${_job}-0"
+ local _discovery_name="${_job}.${_env}.${_role}"
test_config $_base_config $_jobkey
test_inspect $_jobkey $_base_config
@@ -279,6 +322,7 @@ test_http_example() {
test_job_status $_cluster $_role $_env $_job
test_scheduler_ui $_role $_env $_job
test_observer_ui $_cluster $_role $_job
+ test_discovery_info $_task_id_prefix $_discovery_name
test_restart $_jobkey
test_update $_jobkey $_updated_config $_cluster
test_update_fail $_jobkey $_base_config $_cluster $_bad_healthcheck_config