/*-
* -\-\-
* Helios Integration Tests
* --
* Copyright (C) 2016 Spotify AB
* --
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* -/-/-
*/
package com.spotify.helios;
import static com.spotify.helios.system.SystemTestBase.ALPINE;
import static com.spotify.helios.system.SystemTestBase.NGINX;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static java.util.concurrent.TimeUnit.MINUTES;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertThat;
import com.google.common.net.HostAndPort;
import com.spotify.helios.testing.HeliosDeploymentResource;
import com.spotify.helios.testing.HeliosSoloDeployment;
import com.spotify.helios.testing.InMemoryLogStreamFollower;
import com.spotify.helios.testing.TemporaryJob;
import com.spotify.helios.testing.TemporaryJobs;
import java.net.Socket;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import org.apache.commons.io.IOUtils;
import org.awaitility.Awaitility;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
@SuppressWarnings("AbbreviationAsWordInName")
public class HeliosSoloIT {
@Rule
public final ExpectedException expected = ExpectedException.none();
private static final InMemoryLogStreamFollower logStreamProvider =
InMemoryLogStreamFollower.create();
@ClassRule
public static HeliosDeploymentResource solo = new HeliosDeploymentResource(
HeliosSoloDeployment.fromEnv()
.heliosSoloImage(Utils.soloImage())
.checkForNewImages(false)
.removeHeliosSoloOnExit(false)
.logStreamProvider(logStreamProvider)
.env("REGISTRAR_HOST_FORMAT", "_${service}._${protocol}.test.${domain}")
.env("WHITELISTED_CAPS", "IPC_LOCK,SYSLOG")
.build()
);
@Rule public final TemporaryPorts ports = TemporaryPorts.create();
@Rule
public TemporaryJobs jobs = TemporaryJobs.builder()
.client(solo.client())
.deployTimeoutMillis(MINUTES.toMillis(1))
.hostFilter(".+")
.build();
@Test
public void testHttpHealthcheck() {
jobs.job()
.image("nginx:1.9.9")
.port("http", 80)
.httpHealthCheck("http", "/")
.deploy();
}
@Test
public void testTcpHealthcheck() {
jobs.job()
.image("nginx:1.9.9")
.port("http", 80)
.tcpHealthCheck("http")
.deploy();
}
@Test
public void testServiceDiscovery() throws Exception {
// start a container that runs nginx and registers with SkyDNS
final TemporaryJob nginx = jobs.job()
.image(NGINX)
.port("http", 80, ports.localPort("http"))
.registration("nginx", "http", "http")
.deploy();
// run a container that does SRV lookup to find the nginx service and then curl's it
final TemporaryJob alpine = jobs.job()
.image(ALPINE)
.port("nc", 4711, ports.localPort("nc"))
.command("sh", "-c",
"apk add --update bind-tools "
+ "&& export SRV=$(dig -t SRV +short _nginx._http.test.$SPOTIFY_DOMAIN) "
+ "&& export HOST=$(echo $SRV | cut -d' ' -f4) "
+ "&& export PORT=$(echo $SRV | cut -d' ' -f3) "
+ "&& nc -lk -p 4711 -e curl http://$HOST:$PORT"
)
.deploy();
final HostAndPort alpineAddress = alpine.address("nc");
// Connect to alpine container to get the curl response. If we get back the nginx welcome page
// we know that helios properly registered the nginx service in SkyDNS.
final Callable<String> socketResponse = () -> {
try (final Socket s = new Socket(alpineAddress.getHostText(), alpineAddress.getPort())) {
return IOUtils.toString(s.getInputStream()).trim();
}
};
// allow a few retries for a delay in the apk install of bind-tools
Awaitility.await("alpine container returns nginx welcome")
.atMost(10, TimeUnit.SECONDS)
.until(socketResponse, containsString("Welcome to nginx!"));
// also throw in a check to make sure log streaming is working
assertThat(new String(logStreamProvider.getStderr(nginx.job().getId())),
containsString("nginx"));
}
@Test
public void testWhitelistCaps() throws Exception {
jobs.job()
.image("nginx:1.9.9")
.addCapabilities(asList("IPC_LOCK", "SYSLOG"))
.deploy();
// NET_RAW is not whitelisted so creating this job should fail
expected.expect(AssertionError.class);
jobs.job()
.image("nginx:1.9.9")
.addCapabilities(singletonList("NET_RAW"))
.deploy();
}
}