/*-
* -\-\-
* docker-client
* --
* 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.docker.client;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.util.concurrent.Futures;
import com.spotify.docker.client.messages.ContainerConfig;
import com.spotify.docker.client.messages.ContainerCreation;
import com.spotify.docker.client.messages.HostConfig;
import com.spotify.docker.client.messages.Info;
import java.net.URI;
import java.util.Map;
import java.util.concurrent.Future;
import javax.ws.rs.client.AsyncInvoker;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.Invocation;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Configuration;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Variant;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
public class DefaultDockerClientUnitTest {
@Mock
private Client clientMock;
@Mock
private ClientBuilder clientBuilderMock;
@Mock
private Invocation.Builder builderMock;
@Mock
private AsyncInvoker asyncInvoker;
@Mock
private WebTarget webTargetMock;
private Supplier<ClientBuilder> clientBuilderSupplier;
private DefaultDockerClient.Builder builder;
@Before
public void setup() throws Exception {
MockitoAnnotations.initMocks(this);
when(clientBuilderMock.build()).thenReturn(clientMock);
when(clientBuilderMock.withConfig(any(Configuration.class))).thenReturn(clientBuilderMock);
when(clientBuilderMock.property(anyString(), any())).thenReturn(clientBuilderMock);
clientBuilderSupplier = Suppliers.ofInstance(clientBuilderMock);
when(clientMock.target(any(URI.class))).thenReturn(webTargetMock);
// return the same mock for any path.
when(webTargetMock.path(anyString())).thenReturn(webTargetMock);
when(webTargetMock.request(MediaType.APPLICATION_JSON_TYPE)).thenReturn(builderMock);
when(builderMock.async()).thenReturn(asyncInvoker);
final Future<Info> futureMock = Futures.immediateFuture(mock(Info.class));
when(asyncInvoker.method(anyString(), any(Class.class))).thenReturn(futureMock);
builder = DefaultDockerClient.builder();
builder.uri("https://perdu.com:2375");
}
@Test
public void testHostForUnixSocket() {
final DefaultDockerClient client = DefaultDockerClient.builder()
.uri("unix:///var/run/docker.sock").build();
assertThat(client.getHost(), equalTo("localhost"));
}
@Test
public void testHostForLocalHttps() {
final DefaultDockerClient client = DefaultDockerClient.builder()
.uri("https://localhost:2375").build();
assertThat(client.getHost(), equalTo("localhost"));
}
@Test
public void testHostForFqdnHttps() {
final DefaultDockerClient client = DefaultDockerClient.builder()
.uri("https://perdu.com:2375").build();
assertThat(client.getHost(), equalTo("perdu.com"));
}
@Test
public void testHostForIpHttps() {
final DefaultDockerClient client = DefaultDockerClient.builder()
.uri("https://192.168.53.103:2375").build();
assertThat(client.getHost(), equalTo("192.168.53.103"));
}
@Test
public void testNoHeaders() throws Exception {
final DefaultDockerClient dockerClient = new DefaultDockerClient(
builder, clientBuilderSupplier);
dockerClient.info();
verify(builderMock, never()).header(anyString(), anyString());
}
@Test
public void testOneHeader() throws Exception {
builder.header("foo", 1);
final DefaultDockerClient dockerClient = new DefaultDockerClient(
builder, clientBuilderSupplier);
dockerClient.info();
final ArgumentCaptor<String> keyArgument = ArgumentCaptor.forClass(String.class);
final ArgumentCaptor<Object> valueArgument = ArgumentCaptor.forClass(Object.class);
verify(builderMock, times(1)).header(keyArgument.capture(), valueArgument.capture());
Assert.assertEquals("foo", keyArgument.getValue());
Assert.assertEquals(1, valueArgument.getValue());
}
@Test
public void testMultipleHeaders() throws Exception {
final Map<String, Object> headers = Maps.newHashMap();
headers.put("int", 1);
headers.put("string", "2");
headers.put("list", Lists.newArrayList("a", "b", "c"));
for (final Map.Entry<String, Object> entry : headers.entrySet()) {
builder.header(entry.getKey(), entry.getValue());
}
final DefaultDockerClient dockerClient = new DefaultDockerClient(
builder, clientBuilderSupplier);
dockerClient.info();
final ArgumentCaptor<String> nameCaptor = ArgumentCaptor.forClass(String.class);
final ArgumentCaptor<String> valueCaptor = ArgumentCaptor.forClass(String.class);
verify(builderMock, times(headers.size())).header(nameCaptor.capture(), valueCaptor.capture());
int idx = 0;
for (final Map.Entry<String, Object> entry : headers.entrySet()) {
Assert.assertEquals(entry.getKey(), nameCaptor.getAllValues().get(idx));
Assert.assertEquals(entry.getValue(), valueCaptor.getAllValues().get(idx));
++idx;
}
}
@Test
public void testCapAddAndDrop() throws Exception {
final DefaultDockerClient dockerClient = new DefaultDockerClient(
builder, clientBuilderSupplier);
final HostConfig hostConfig = HostConfig.builder()
.capAdd(ImmutableList.of("foo", "bar"))
.capAdd(ImmutableList.of("baz", "qux"))
.build();
final ContainerConfig containerConfig = ContainerConfig.builder()
.hostConfig(hostConfig)
.build();
//noinspection unchecked
when(asyncInvoker.method(
anyString(), any(Entity.class), any(Class.class)))
.thenReturn(Futures.immediateFuture(ContainerCreation.builder().build()));
dockerClient.createContainer(containerConfig);
final ArgumentCaptor<String> methodArg = ArgumentCaptor.forClass(String.class);
final ArgumentCaptor<Entity> entityArg = ArgumentCaptor.forClass(Entity.class);
final ArgumentCaptor<Class> classArg = ArgumentCaptor.forClass(Class.class);
//noinspection unchecked
verify(asyncInvoker, times(1)).method(
methodArg.capture(), entityArg.capture(), classArg.capture());
final Entity expectedEntity = Entity.entity(
containerConfig, new Variant(MediaType.valueOf(APPLICATION_JSON), (String) null, null));
// Check that we've called the right method on the underlying AsyncInvoker with the right params
assertThat(methodArg.getValue(), equalTo("POST"));
assertThat(entityArg.getValue(), equalTo(expectedEntity));
assertThat(classArg.getValue(), instanceOf(Class.class));
}
}