/*- * -\-\- * Helios Testing Library * -- * 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.testing; import static com.google.common.collect.Lists.newArrayList; import static com.google.common.util.concurrent.Futures.immediateFuture; import static com.spotify.helios.testing.TemporaryJobsTestBase.temporaryJobsBuilder; import static java.lang.String.format; import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertThat; import static org.junit.experimental.results.PrintableResult.testResult; import static org.junit.experimental.results.ResultMatchers.isSuccessful; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.when; import com.google.common.collect.ImmutableMap; import com.google.common.util.concurrent.ListenableFuture; import com.spotify.helios.client.HeliosClient; import com.spotify.helios.common.descriptors.Job; import com.spotify.helios.common.descriptors.JobId; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Answers; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; @RunWith(MockitoJUnitRunner.class) public class ConfigTest { private static TestParameters parameters; @Mock private static HeliosClient client; @Mock(answer = Answers.CALLS_REAL_METHODS) private static HeliosClient.Builder clientBuilder; @Before public void setup() { final ListenableFuture<Map<JobId, Job>> future = immediateFuture((Map<JobId, Job>) new HashMap<JobId, Job>()); // Return an empty job list to skip trying to remove old jobs when(client.jobs()).thenReturn(future); } public static class ProfileTest implements Deployer { // Local is the default profile, so don't specify it explicitly to test default loading @Rule public final TemporaryJobs temporaryJobs = parameters.builder .client(client) .deployer(this) .build(); @Before public void setup() { // This job will get deployed test-host temporaryJobs.job().deploy("test-host"); // this job will get deployed using the host filter in the conf file temporaryJobs.job().deploy(); } @Test public void test() throws Exception { // Dummy test so junit doesn't complain. } @Override public TemporaryJob deploy(Job job, List<String> hosts, Set<String> waitPorts, Prober prober, TemporaryJobReports.ReportWriter reportWriter) { // This is called when the first job is deployed assertThat(hosts, equalTo((List<String>) newArrayList("test-host"))); parameters.validate(job, temporaryJobs.prefix()); return null; } @Override public TemporaryJob deploy(Job job, String hostFilter, Set<String> waitPorts, Prober prober, TemporaryJobReports.ReportWriter reportWriter) { // This is called when the second job is deployed assertThat(hostFilter, equalTo(parameters.hostFilter)); parameters.validate(job, temporaryJobs.prefix()); return null; } @Override public void readyToDeploy() { } } @Test public void testLocalProfile() throws Exception { final TestParameters.JobValidator validator = new TestParameters.JobValidator() { @Override public void validate(Job job, String prefix) { final String local = prefix + ".local."; final Map<String, String> map = ImmutableMap.of( "SPOTIFY_TEST_THING", format("See, we used the prefix here -->%s<--", prefix), "SPOTIFY_DOMAIN", local, "SPOTIFY_POD", local); assertThat(job.getEnv(), equalTo(map)); assertThat(job.getImage(), equalTo("spotify/busybox:latest")); } }; // The local profile is the default, so we don't specify it explicitly so we can test // the default loading mechanism. parameters = new TestParameters(temporaryJobsBuilder(), ".*", validator); assertThat(testResult(ProfileTest.class), isSuccessful()); } @Test public void testHeliosCiProfile() throws Exception { final TestParameters.JobValidator validator = new TestParameters.JobValidator() { @Override public void validate(Job job, String prefix) { final String domain = prefix + ".services.helios-ci.cloud.spotify.net"; final Map<String, String> map = ImmutableMap.of( "SPOTIFY_DOMAIN", domain, "SPOTIFY_POD", domain, "SPOTIFY_SYSLOG_HOST", "10.99.0.1"); assertThat(job.getEnv(), equalTo(map)); assertThat(job.getImage(), equalTo("spotify/busybox:latest")); } }; // Specify the helios-ci profile explicitly, but make sure that the construction of the // HeliosClient used by TemporaryJobs is mocked out to avoid attempting to connect to // possibly-unresolvable hosts. doReturn(client).when(clientBuilder).build(); final TemporaryJobs.Builder builder = TemporaryJobs.builder("helios-ci", Collections.<String, String>emptyMap(), clientBuilder); parameters = new TestParameters(builder, ".+\\.helios-ci\\.cloud", validator); assertThat(testResult(ProfileTest.class), isSuccessful()); } /** * Helper class allows us to inject different test parameters into ProfileTest so we can * reuse it to test multiple profiles. */ private static class TestParameters { private final TemporaryJobs.Builder builder; private final String hostFilter; private final JobValidator jobValidator; private TestParameters(TemporaryJobs.Builder builder, String hostFilter, JobValidator jobValidator) { this.builder = builder; this.hostFilter = hostFilter; this.jobValidator = jobValidator; } private void validate(final Job job, final String prefix) { jobValidator.validate(job, prefix); } private interface JobValidator { void validate(Job job, String prefix); } } }