diff --git a/src/js/components/AppPageComponent.jsx b/src/js/components/AppPageComponent.jsx
index 4abdfc59b..4a7ec11b9 100644
--- a/src/js/components/AppPageComponent.jsx
+++ b/src/js/components/AppPageComponent.jsx
@@ -352,6 +352,7 @@ var AppPageComponent = React.createClass({
fetchState={state.fetchState}
getTaskHealthMessage={this.getTaskHealthMessage}
hasHealth={Object.keys(model.healthChecks).length > 0}
+ labels={model.labels}
tasks={model.tasks} />
);
})
diff --git a/src/js/components/TaskListItemComponent.jsx b/src/js/components/TaskListItemComponent.jsx
index 0f7001cfa..992eab5d5 100644
--- a/src/js/components/TaskListItemComponent.jsx
+++ b/src/js/components/TaskListItemComponent.jsx
@@ -7,6 +7,8 @@ import AppsStore from "../stores/AppsStore";
import HealthStatus from "../constants/HealthStatus";
import TaskStatus from "../constants/TaskStatus";
import TaskFileDownloadComponent from "../components/TaskFileDownloadComponent";
+import ServiceSchemeUtil from "../helpers/ServiceSchemeUtil";
+import { watch } from "fs";
function joinNodes(nodes, separator = ", ") {
var lastIndex = nodes.length - 1;
@@ -22,6 +24,12 @@ function joinNodes(nodes, separator = ", ") {
});
}
+function getPortScheme(labels, portIndex) {
+ const scheme = ServiceSchemeUtil
+ .getServiceSchemeFromLabels(labels, portIndex);
+ return scheme == '' ? '//' : `${scheme}://`;
+}
+
var TaskListItemComponent = React.createClass({
displayName: "TaskListItemComponent",
@@ -29,6 +37,7 @@ var TaskListItemComponent = React.createClass({
appId: React.PropTypes.string.isRequired,
hasHealth: React.PropTypes.bool,
isActive: React.PropTypes.bool.isRequired,
+ labels: React.PropTypes.object.isRequired,
onToggle: React.PropTypes.func.isRequired,
sortKey: React.PropTypes.string,
task: React.PropTypes.object.isRequired,
@@ -37,6 +46,7 @@ var TaskListItemComponent = React.createClass({
getHostAndPorts: function () {
var task = this.props.task;
+ var props = this.props;
var ports = task.ports;
if (ports == null || ports.length === 0 ) {
@@ -44,9 +54,10 @@ var TaskListItemComponent = React.createClass({
}
if (ports != null && ports.length === 1) {
+ const scheme = getPortScheme(props.labels, 0);
return (
{`${task.host}:${ports[0]}`}
@@ -54,11 +65,12 @@ var TaskListItemComponent = React.createClass({
}
if (ports != null && ports.length > 1) {
- let portNodes = ports.map(function (port) {
+ let portNodes = ports.map(function (port, i) {
+ const scheme = getPortScheme(props.labels, i);
return (
{port}
@@ -98,18 +110,22 @@ var TaskListItemComponent = React.createClass({
let ipAddress = address.ipAddress;
if (serviceDiscoveryPorts.length === 1) {
let port = serviceDiscoveryPorts[0].number;
+ const scheme = getPortScheme(props.labels, 0);
return (
+ className="text-muted"
+ href={`${scheme}${ipAddress}:${port}`}>
{`${ipAddress}:${port}`}
);
}
- let portNodes = serviceDiscoveryPorts.map((port) => {
+ let portNodes = serviceDiscoveryPorts.map((port, i) => {
+ const scheme = getPortScheme(props.labels, i);
return (
+ className="text-muted"
+ href={`${scheme}${ipAddress}:${port.number}`}>
{port.number}
);
diff --git a/src/js/components/TaskViewComponent.jsx b/src/js/components/TaskViewComponent.jsx
index 5a1d473d1..f25918ec8 100644
--- a/src/js/components/TaskViewComponent.jsx
+++ b/src/js/components/TaskViewComponent.jsx
@@ -18,6 +18,7 @@ var TaskViewComponent = React.createClass({
fetchState: React.PropTypes.number.isRequired,
getTaskHealthMessage: React.PropTypes.func.isRequired,
hasHealth: React.PropTypes.bool,
+ labels: React.PropTypes.object.isRequired,
tasks: React.PropTypes.array.isRequired
},
@@ -228,6 +229,7 @@ var TaskViewComponent = React.createClass({
hasHealth={this.props.hasHealth}
onTaskToggle={this.onTaskToggle}
itemsPerPage={this.state.itemsPerPage}
+ labels={this.props.labels}
selectedTasks={this.state.selectedTasks}
tasks={this.props.tasks}
toggleAllTasks={this.toggleAllTasks} />
diff --git a/src/js/helpers/ServiceSchemeUtil.js b/src/js/helpers/ServiceSchemeUtil.js
new file mode 100644
index 000000000..9eea7aaa9
--- /dev/null
+++ b/src/js/helpers/ServiceSchemeUtil.js
@@ -0,0 +1,36 @@
+const BASE_SCHEME_LABEL = "MARATHON_SCHEME_PORT";
+
+var ServiceSchemeUtil = {
+ /*
+ * Returns service scheme of the n-th port.
+ *
+ * Given N a port index, if `MARATHON_SCHEME_PORT` is
+ * in the set of labels, then the function returns the value
+ * of this label.
+ *
+ * Given N a port index, if `MARATHON_SCHEME_PORT0` is
+ * not in the set of labels, then the value associated with
+ * `MARATHON_SCHEME_PORT` is returned.
+ *
+ * Given N a port index, if `MARATHON_SCHEME_PORT0` and
+ * `MARATHON_SCHEME_PORT` are not in the set of labels, the
+ * function returns the `http` as the default scheme.
+ */
+ getServiceSchemeFromLabels(labels, n) {
+ function getScheme(labelValue) {
+ return (labelValue === "http" || labelValue === "https")
+ ? labelValue
+ : '';
+ }
+
+ const labelKey = ("" + BASE_SCHEME_LABEL + n);
+ if (labels && labelKey in labels)
+ return getScheme(labels[labelKey]);
+ else if (labels && BASE_SCHEME_LABEL in labels)
+ return getScheme(labels[BASE_SCHEME_LABEL]);
+
+ return '';
+ }
+};
+
+export default ServiceSchemeUtil;
\ No newline at end of file
diff --git a/src/test/units/ServiceSchemeUtil.test.js b/src/test/units/ServiceSchemeUtil.test.js
new file mode 100644
index 000000000..236722ceb
--- /dev/null
+++ b/src/test/units/ServiceSchemeUtil.test.js
@@ -0,0 +1,56 @@
+import {expect} from "chai";
+import ServiceSchemeUtil from "../../js/helpers/ServiceSchemeUtil";
+
+function verifyPortSchemeWithDefault(serviceScheme, serviceScheme0,
+ expectedSchemePort0, expectedSchemePort1) {
+ describe("MARATHON_SCHEME_PORT is set to " + serviceScheme, function() {
+ describe("MARATHON_SCHEME_PORT0 is set to " + serviceScheme0, function() {
+ it("detect scheme of port 0", function() {
+ expect(ServiceSchemeUtil.getServiceSchemeFromLabels({
+ "MARATHON_SCHEME_PORT": serviceScheme,
+ "MARATHON_SCHEME_PORT0": serviceScheme0,
+ }, 0)).to.eq(expectedSchemePort0);
+ });
+
+ it("detect scheme of port 1", function() {
+ expect(ServiceSchemeUtil.getServiceSchemeFromLabels({
+ "MARATHON_SCHEME_PORT": serviceScheme,
+ "MARATHON_SCHEME_PORT0": serviceScheme0,
+ }, 1)).to.eq(expectedSchemePort1);
+ });
+ });
+ });
+}
+
+function verifyPortSchemeWithoutDefault(serviceScheme0,
+ expectedSchemePort0, expectedSchemePort1) {
+ describe("MARATHON_SCHEME_PORT is not set", function() {
+ describe("MARATHON_SCHEME_PORT0 is set to " + serviceScheme0, function() {
+ it("detect scheme of port 0", function() {
+ expect(ServiceSchemeUtil.getServiceSchemeFromLabels({
+ "MARATHON_SCHEME_PORT0": serviceScheme0,
+ }, 0)).to.eq(expectedSchemePort0);
+ });
+
+ it("detect scheme of port 1", function() {
+ expect(ServiceSchemeUtil.getServiceSchemeFromLabels({
+ "MARATHON_SCHEME_PORT0": serviceScheme0,
+ }, 1)).to.eq(expectedSchemePort1);
+ });
+ });
+ });
+}
+
+describe("ServiceSchemeUtil", function () {
+ // default scheme scheme port 0 expected port 0 expected port 1
+ verifyPortSchemeWithDefault("http", "http", "http", "http");
+ verifyPortSchemeWithDefault("http", "https", "https", "http");
+ verifyPortSchemeWithDefault("https", "http", "http", "https");
+ verifyPortSchemeWithDefault("https", "https", "https", "https");
+
+ // scheme port 0 expected port 0 expected port 1
+ verifyPortSchemeWithoutDefault("http", "http", "");
+ verifyPortSchemeWithoutDefault("https", "https", "");
+ verifyPortSchemeWithoutDefault("http", "http", "");
+ verifyPortSchemeWithoutDefault("https", "https", "");
+});
diff --git a/src/test/units/TaskListItemComponent.test.js b/src/test/units/TaskListItemComponent.test.js
index 6bcbfd83a..5b1262d32 100644
--- a/src/test/units/TaskListItemComponent.test.js
+++ b/src/test/units/TaskListItemComponent.test.js
@@ -11,7 +11,7 @@ describe("Task List Item component", function () {
appId: "/app-1",
id: "task-123",
host: "host-1",
- ports: [1, 2, 3],
+ ports: [8081, 8082, 8083],
status: "status-0",
updatedAt: "2015-06-29T14:11:58.709Z",
version: "2015-06-29T13:54:24.171Z"
@@ -20,6 +20,7 @@ describe("Task List Item component", function () {
this.component = shallow(
{}}
@@ -37,6 +38,76 @@ describe("Task List Item component", function () {
).to.equal("task-123");
});
+ describe("task url are correct", function() {
+ function getNthPortLink(component, n) {
+ return component.find("td")
+ .at(1).children()
+ .at(2).children()
+ .at(2 + n).children().first().props().href
+ }
+
+ it("has a HTTP task url when app does not have scheme label", function() {
+ expect(getNthPortLink(this.component, 0)).to.equal("//host-1:8081");
+ expect(getNthPortLink(this.component, 1)).to.equal("//host-1:8082");
+ expect(getNthPortLink(this.component, 2)).to.equal("//host-1:8083");
+ });
+
+ it("has only https schemes", function() {
+ var model = {
+ appId: "/app-1",
+ id: "task-123",
+ host: "host-1",
+ ports: [8081, 8082, 8083],
+ status: "status-0",
+ updatedAt: "2015-06-29T14:11:58.709Z",
+ version: "2015-06-29T13:54:24.171Z"
+ };
+
+ this.component = shallow(
+ {}}
+ task={model} />
+ );
+ expect(getNthPortLink(this.component, 0)).to.equal("https://host-1:8081");
+ expect(getNthPortLink(this.component, 1)).to.equal("https://host-1:8082");
+ expect(getNthPortLink(this.component, 2)).to.equal("https://host-1:8083");
+ })
+
+ it("has different schemes depending on the port", function() {
+ var model = {
+ appId: "/app-1",
+ id: "task-123",
+ host: "host-1",
+ ports: [8081, 8082, 8083],
+ status: "status-0",
+ updatedAt: "2015-06-29T14:11:58.709Z",
+ version: "2015-06-29T13:54:24.171Z"
+ };
+
+ this.component = shallow(
+ {}}
+ task={model} />
+ );
+ expect(getNthPortLink(this.component, 0)).to.equal("https://host-1:8081");
+ expect(getNthPortLink(this.component, 1)).to.equal("//host-1:8082");
+ expect(getNthPortLink(this.component, 2)).to.equal("http://host-1:8083");
+ })
+ })
+
it("has correct health message", function () {
expect(this.component.find("td").at(2).text()).to.equal("Healthy");
});