mirror of https://github.com/apache/jclouds.git
JCLOUDS-1014: Make the login port lookup function configurable
This commit is contained in:
parent
8ca3a326c8
commit
01d43f503b
|
@ -84,6 +84,10 @@
|
||||||
<artifactId>jclouds-okhttp</artifactId>
|
<artifactId>jclouds-okhttp</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.inject.extensions</groupId>
|
||||||
|
<artifactId>guice-multibindings</artifactId>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.jclouds</groupId>
|
<groupId>org.apache.jclouds</groupId>
|
||||||
<artifactId>jclouds-core</artifactId>
|
<artifactId>jclouds-core</artifactId>
|
||||||
|
|
|
@ -16,8 +16,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.docker.compute.config;
|
package org.jclouds.docker.compute.config;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
|
||||||
import com.google.inject.TypeLiteral;
|
|
||||||
import org.jclouds.compute.ComputeServiceAdapter;
|
import org.jclouds.compute.ComputeServiceAdapter;
|
||||||
import org.jclouds.compute.config.ComputeServiceAdapterContextModule;
|
import org.jclouds.compute.config.ComputeServiceAdapterContextModule;
|
||||||
import org.jclouds.compute.domain.Hardware;
|
import org.jclouds.compute.domain.Hardware;
|
||||||
|
@ -34,6 +32,9 @@ import org.jclouds.docker.domain.State;
|
||||||
import org.jclouds.domain.Location;
|
import org.jclouds.domain.Location;
|
||||||
import org.jclouds.functions.IdentityFunction;
|
import org.jclouds.functions.IdentityFunction;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.inject.TypeLiteral;
|
||||||
|
|
||||||
public class DockerComputeServiceContextModule extends
|
public class DockerComputeServiceContextModule extends
|
||||||
ComputeServiceAdapterContextModule<Container, Hardware, Image, Location> {
|
ComputeServiceAdapterContextModule<Container, Hardware, Image, Location> {
|
||||||
|
|
||||||
|
@ -54,6 +55,8 @@ public class DockerComputeServiceContextModule extends
|
||||||
bind(new TypeLiteral<Function<State, NodeMetadata.Status>>() {
|
bind(new TypeLiteral<Function<State, NodeMetadata.Status>>() {
|
||||||
}).to(StateToStatus.class);
|
}).to(StateToStatus.class);
|
||||||
bind(TemplateOptions.class).to(DockerTemplateOptions.class);
|
bind(TemplateOptions.class).to(DockerTemplateOptions.class);
|
||||||
|
|
||||||
|
install(new LoginPortLookupModule());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You 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 org.jclouds.docker.compute.config;
|
||||||
|
|
||||||
|
import org.jclouds.docker.compute.functions.LoginPortForContainer;
|
||||||
|
|
||||||
|
import com.google.inject.AbstractModule;
|
||||||
|
import com.google.inject.Binder;
|
||||||
|
import com.google.inject.multibindings.MapBinder;
|
||||||
|
|
||||||
|
public class LoginPortLookupModule extends AbstractModule {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
// Declare it to initialize the binder allowing duplicates. Users may
|
||||||
|
// provide different functions for the same image in different modules, or
|
||||||
|
// we could provide predefined functions for known images. This allows
|
||||||
|
// users to set their own ones too.
|
||||||
|
loginPortLookupBinder(binder());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MapBinder<String, LoginPortForContainer> loginPortLookupBinder(Binder binder) {
|
||||||
|
return MapBinder.newMapBinder(binder, String.class, LoginPortForContainer.class).permitDuplicates();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -16,9 +16,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.docker.compute.functions;
|
package org.jclouds.docker.compute.functions;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
|
||||||
import static com.google.common.collect.Iterables.getOnlyElement;
|
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -34,7 +31,6 @@ import org.jclouds.compute.domain.NodeMetadataBuilder;
|
||||||
import org.jclouds.compute.domain.Processor;
|
import org.jclouds.compute.domain.Processor;
|
||||||
import org.jclouds.compute.functions.GroupNamingConvention;
|
import org.jclouds.compute.functions.GroupNamingConvention;
|
||||||
import org.jclouds.docker.domain.Container;
|
import org.jclouds.docker.domain.Container;
|
||||||
import org.jclouds.docker.domain.Port;
|
|
||||||
import org.jclouds.docker.domain.State;
|
import org.jclouds.docker.domain.State;
|
||||||
import org.jclouds.domain.Location;
|
import org.jclouds.domain.Location;
|
||||||
import org.jclouds.providers.ProviderMetadata;
|
import org.jclouds.providers.ProviderMetadata;
|
||||||
|
@ -54,24 +50,26 @@ public class ContainerToNodeMetadata implements Function<Container, NodeMetadata
|
||||||
* started outside jclouds. Client code should check for this value
|
* started outside jclouds. Client code should check for this value
|
||||||
* when accessing NodeMetadata from Docker.
|
* when accessing NodeMetadata from Docker.
|
||||||
*/
|
*/
|
||||||
public static final Integer NO_LOGIN_PORT = Integer.valueOf(-1);
|
private static final Integer NO_LOGIN_PORT = Integer.valueOf(-1);
|
||||||
|
|
||||||
private final ProviderMetadata providerMetadata;
|
private final ProviderMetadata providerMetadata;
|
||||||
private final Function<State, NodeMetadata.Status> toPortableStatus;
|
private final Function<State, NodeMetadata.Status> toPortableStatus;
|
||||||
private final GroupNamingConvention nodeNamingConvention;
|
private final GroupNamingConvention nodeNamingConvention;
|
||||||
private final Supplier<Map<String, ? extends Image>> images;
|
private final Supplier<Map<String, ? extends Image>> images;
|
||||||
private final Supplier<Set<? extends Location>> locations;
|
private final Supplier<Set<? extends Location>> locations;
|
||||||
|
private final LoginPortForContainer loginPortForContainer;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public ContainerToNodeMetadata(ProviderMetadata providerMetadata, Function<State,
|
ContainerToNodeMetadata(ProviderMetadata providerMetadata,
|
||||||
NodeMetadata.Status> toPortableStatus, GroupNamingConvention.Factory namingConvention,
|
Function<State, NodeMetadata.Status> toPortableStatus, GroupNamingConvention.Factory namingConvention,
|
||||||
Supplier<Map<String, ? extends Image>> images,
|
Supplier<Map<String, ? extends Image>> images, @Memoized Supplier<Set<? extends Location>> locations,
|
||||||
@Memoized Supplier<Set<? extends Location>> locations) {
|
LoginPortForContainer loginPortForContainer) {
|
||||||
this.providerMetadata = checkNotNull(providerMetadata, "providerMetadata");
|
this.providerMetadata = providerMetadata;
|
||||||
this.toPortableStatus = checkNotNull(toPortableStatus, "toPortableStatus cannot be null");
|
this.toPortableStatus = toPortableStatus;
|
||||||
this.nodeNamingConvention = checkNotNull(namingConvention, "namingConvention").createWithoutPrefix();
|
this.nodeNamingConvention = namingConvention.createWithoutPrefix();
|
||||||
this.images = checkNotNull(images, "images cannot be null");
|
this.images = images;
|
||||||
this.locations = checkNotNull(locations, "locations");
|
this.locations = locations;
|
||||||
|
this.loginPortForContainer = loginPortForContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -90,7 +88,7 @@ public class ContainerToNodeMetadata implements Function<Container, NodeMetadata
|
||||||
.processor(new Processor(container.config().cpuShares(), container.config().cpuShares()))
|
.processor(new Processor(container.config().cpuShares(), container.config().cpuShares()))
|
||||||
.build());
|
.build());
|
||||||
builder.status(toPortableStatus.apply(container.state()));
|
builder.status(toPortableStatus.apply(container.state()));
|
||||||
builder.loginPort(getLoginPort(container));
|
builder.loginPort(loginPortForContainer.apply(container).or(NO_LOGIN_PORT));
|
||||||
builder.publicAddresses(getPublicIpAddresses());
|
builder.publicAddresses(getPublicIpAddresses());
|
||||||
builder.privateAddresses(getPrivateIpAddresses(container));
|
builder.privateAddresses(getPrivateIpAddresses(container));
|
||||||
builder.location(Iterables.getOnlyElement(locations.get()));
|
builder.location(Iterables.getOnlyElement(locations.get()));
|
||||||
|
@ -117,20 +115,4 @@ public class ContainerToNodeMetadata implements Function<Container, NodeMetadata
|
||||||
return ImmutableList.of(dockerIpAddress);
|
return ImmutableList.of(dockerIpAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static int getLoginPort(Container container) {
|
|
||||||
if (container.networkSettings() != null) {
|
|
||||||
Map<String, List<Map<String, String>>> ports = container.networkSettings().ports();
|
|
||||||
if (ports != null && ports.containsKey("22/tcp")) {
|
|
||||||
return Integer.parseInt(getOnlyElement(ports.get("22/tcp")).get("HostPort"));
|
|
||||||
}
|
|
||||||
// this is needed in case the container list is coming from listContainers
|
|
||||||
} else if (container.ports() != null) {
|
|
||||||
for (Port port : container.ports()) {
|
|
||||||
if (port.privatePort() == 22) {
|
|
||||||
return port.publicPort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NO_LOGIN_PORT;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You 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 org.jclouds.docker.compute.functions;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import org.jclouds.docker.domain.Container;
|
||||||
|
|
||||||
|
import com.google.common.annotations.Beta;
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
|
@Beta
|
||||||
|
public class CustomLoginPortFromImage implements LoginPortForContainer {
|
||||||
|
|
||||||
|
private final Map<String, Set<LoginPortForContainer>> imageToPortLookup;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
CustomLoginPortFromImage(Map<String, Set<LoginPortForContainer>> imageToPortLookup) {
|
||||||
|
this.imageToPortLookup = imageToPortLookup;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Integer> apply(final Container container) {
|
||||||
|
Map<String, Set<LoginPortForContainer>> matchingFunctions = Maps.filterKeys(imageToPortLookup,
|
||||||
|
new Predicate<String>() {
|
||||||
|
@Override
|
||||||
|
public boolean apply(String input) {
|
||||||
|
return container.config().image().matches(input);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// We allow to provide several forms in the image-to-function map:
|
||||||
|
// - redis
|
||||||
|
// - redis:12
|
||||||
|
// - owner/redis:12
|
||||||
|
// - registry:5000/owner/redis:12
|
||||||
|
// We consider the longest match first, as it is the more accurate one
|
||||||
|
List<String> sortedImages = new ArrayList<String>(matchingFunctions.keySet());
|
||||||
|
Collections.sort(sortedImages, LongestStringFirst);
|
||||||
|
|
||||||
|
for (String currentImage : sortedImages) {
|
||||||
|
Set<LoginPortForContainer> functions = matchingFunctions.get(currentImage);
|
||||||
|
for (LoginPortForContainer function : functions) {
|
||||||
|
Optional<Integer> port = function.apply(container);
|
||||||
|
if (port.isPresent()) {
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Optional.absent();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final Comparator<String> LongestStringFirst = new Comparator<String>() {
|
||||||
|
@Override
|
||||||
|
public int compare(String s1, String s2) {
|
||||||
|
return s2.length() - s1.length();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You 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 org.jclouds.docker.compute.functions;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import org.jclouds.docker.compute.functions.LoginPortForContainer.LoginPortLookupChain;
|
||||||
|
import org.jclouds.docker.domain.Container;
|
||||||
|
|
||||||
|
import com.google.common.annotations.Beta;
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
import com.google.inject.ImplementedBy;
|
||||||
|
|
||||||
|
@Beta
|
||||||
|
@ImplementedBy(LoginPortLookupChain.class)
|
||||||
|
public interface LoginPortForContainer extends Function<Container, Optional<Integer>> {
|
||||||
|
|
||||||
|
@Beta
|
||||||
|
static final class LoginPortLookupChain implements LoginPortForContainer {
|
||||||
|
private final PublicPortForContainerPort publicPortForContainerPort;
|
||||||
|
private final CustomLoginPortFromImage customLoginPortFromImage;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
LoginPortLookupChain(CustomLoginPortFromImage customLoginPortFromImage) {
|
||||||
|
this.publicPortForContainerPort = new PublicPortForContainerPort(22);
|
||||||
|
this.customLoginPortFromImage = customLoginPortFromImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Integer> apply(Container input) {
|
||||||
|
Optional<Integer> loginPort = publicPortForContainerPort.apply(input);
|
||||||
|
return loginPort.isPresent() ? loginPort : customLoginPortFromImage.apply(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You 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 org.jclouds.docker.compute.functions;
|
||||||
|
|
||||||
|
import static com.google.common.collect.Iterables.getOnlyElement;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.jclouds.docker.domain.Container;
|
||||||
|
import org.jclouds.docker.domain.Port;
|
||||||
|
|
||||||
|
import com.google.common.annotations.Beta;
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
|
||||||
|
@Beta
|
||||||
|
public class PublicPortForContainerPort implements LoginPortForContainer {
|
||||||
|
|
||||||
|
private final int containerPort;
|
||||||
|
|
||||||
|
public PublicPortForContainerPort(int containerPort) {
|
||||||
|
this.containerPort = containerPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Integer> apply(Container container) {
|
||||||
|
if (container.networkSettings() != null) {
|
||||||
|
Map<String, List<Map<String, String>>> ports = container.networkSettings().ports();
|
||||||
|
if (ports != null && ports.containsKey(containerPort + "/tcp")) {
|
||||||
|
return Optional.of(Integer.parseInt(getOnlyElement(ports.get(containerPort + "/tcp")).get("HostPort")));
|
||||||
|
}
|
||||||
|
// this is needed in case the container list is coming from
|
||||||
|
// listContainers
|
||||||
|
} else if (container.ports() != null) {
|
||||||
|
for (Port port : container.ports()) {
|
||||||
|
if (port.privatePort() == containerPort) {
|
||||||
|
return Optional.of(port.publicPort());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Optional.absent();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -44,7 +44,6 @@ import org.jclouds.docker.domain.State;
|
||||||
import org.jclouds.domain.Location;
|
import org.jclouds.domain.Location;
|
||||||
import org.jclouds.domain.LocationBuilder;
|
import org.jclouds.domain.LocationBuilder;
|
||||||
import org.jclouds.domain.LocationScope;
|
import org.jclouds.domain.LocationScope;
|
||||||
import org.jclouds.domain.LoginCredentials;
|
|
||||||
import org.jclouds.providers.ProviderMetadata;
|
import org.jclouds.providers.ProviderMetadata;
|
||||||
import org.testng.annotations.BeforeMethod;
|
import org.testng.annotations.BeforeMethod;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
@ -62,8 +61,6 @@ import com.google.inject.Guice;
|
||||||
@Test(groups = "unit", testName = "ContainerToNodeMetadataTest")
|
@Test(groups = "unit", testName = "ContainerToNodeMetadataTest")
|
||||||
public class ContainerToNodeMetadataTest {
|
public class ContainerToNodeMetadataTest {
|
||||||
|
|
||||||
private LoginCredentials credentials;
|
|
||||||
|
|
||||||
private ContainerToNodeMetadata function;
|
private ContainerToNodeMetadata function;
|
||||||
|
|
||||||
private Container container;
|
private Container container;
|
||||||
|
@ -170,9 +167,8 @@ public class ContainerToNodeMetadataTest {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
credentials = LoginCredentials.builder().user("foo").password("bar").build();
|
function = new ContainerToNodeMetadata(providerMetadata, toPortableStatus(), namingConvention, images, locations,
|
||||||
|
new LoginPortForContainer.LoginPortLookupChain(null));
|
||||||
function = new ContainerToNodeMetadata(providerMetadata, toPortableStatus(), namingConvention, images, locations);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Function<State, NodeMetadata.Status> toPortableStatus() {
|
private Function<State, NodeMetadata.Status> toPortableStatus() {
|
||||||
|
|
|
@ -0,0 +1,106 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You 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 org.jclouds.docker.compute.functions;
|
||||||
|
|
||||||
|
import static org.jclouds.docker.compute.config.LoginPortLookupModule.loginPortLookupBinder;
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import org.jclouds.docker.compute.config.LoginPortLookupModule;
|
||||||
|
import org.jclouds.docker.domain.Config;
|
||||||
|
import org.jclouds.docker.domain.Container;
|
||||||
|
import org.testng.annotations.BeforeClass;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.inject.AbstractModule;
|
||||||
|
import com.google.inject.Guice;
|
||||||
|
import com.google.inject.Injector;
|
||||||
|
import com.google.inject.multibindings.MapBinder;
|
||||||
|
|
||||||
|
@Test(groups = "unit")
|
||||||
|
public class CustomLoginPortFromImageTest {
|
||||||
|
|
||||||
|
private CustomLoginPortFromImage customLoginPortFromImage;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public void setup() {
|
||||||
|
Injector i = Guice.createInjector(new LoginPortLookupModule(), new AbstractModule() {
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
MapBinder<String, LoginPortForContainer> imageToFunction = loginPortLookupBinder(binder());
|
||||||
|
imageToFunction.addBinding(".*alpine-ext.*").toInstance(LoginPortFromEnvVar);
|
||||||
|
imageToFunction.addBinding(".*ubuntu.*").toInstance(AlwaysPort22);
|
||||||
|
imageToFunction.addBinding(".*ubuntu:12\\.04.*").toInstance(AlwaysPort8080);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
customLoginPortFromImage = i.getInstance(CustomLoginPortFromImage.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPortFromEnvironmentVariables() {
|
||||||
|
Config config = Config.builder().image("alpine-ext:3.2").env(ImmutableList.of("FOO=bar", "SSH_PORT=2345"))
|
||||||
|
.build();
|
||||||
|
Container container = Container.builder().id("id").config(config).build();
|
||||||
|
|
||||||
|
assertEquals(customLoginPortFromImage.apply(container).get().intValue(), 2345);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testMostSpecificImageIsPicked() {
|
||||||
|
Config config = Config.builder().image("ubuntu:12.04").build();
|
||||||
|
Container container = Container.builder().id("id").config(config).build();
|
||||||
|
|
||||||
|
assertEquals(customLoginPortFromImage.apply(container).get().intValue(), 8080);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testNoImageFoundInMap() {
|
||||||
|
Config config = Config.builder().image("unexisting").build();
|
||||||
|
Container container = Container.builder().id("id").config(config).build();
|
||||||
|
|
||||||
|
assertEquals(customLoginPortFromImage.apply(container), Optional.absent());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final LoginPortForContainer LoginPortFromEnvVar = new LoginPortForContainer() {
|
||||||
|
@Override
|
||||||
|
public Optional<Integer> apply(Container input) {
|
||||||
|
Optional<String> portVariable = Iterables.tryFind(input.config().env(), new Predicate<String>() {
|
||||||
|
@Override
|
||||||
|
public boolean apply(String input) {
|
||||||
|
String[] var = input.split("=");
|
||||||
|
return var[0].equals("SSH_PORT");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return portVariable.isPresent() ? Optional.of(Integer.valueOf(portVariable.get().split("=")[1])) : Optional
|
||||||
|
.<Integer> absent();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final LoginPortForContainer AlwaysPort22 = new LoginPortForContainer() {
|
||||||
|
@Override
|
||||||
|
public Optional<Integer> apply(Container input) {
|
||||||
|
return Optional.of(22);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final LoginPortForContainer AlwaysPort8080 = new LoginPortForContainer() {
|
||||||
|
@Override
|
||||||
|
public Optional<Integer> apply(Container input) {
|
||||||
|
return Optional.of(8080);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in New Issue