mirror of https://github.com/apache/jclouds.git
JCLOUDS-946: Properly scope images to the locations where they are available
This commit is contained in:
parent
057be8df99
commit
26210fe098
|
@ -36,7 +36,7 @@
|
|||
<test.digitalocean2.api-version>2</test.digitalocean2.api-version>
|
||||
<test.digitalocean2.identity>FIXME</test.digitalocean2.identity>
|
||||
<test.digitalocean2.credential>FIXME</test.digitalocean2.credential>
|
||||
<test.digitalocean2.template>imageId=ubuntu-14-04-x64</test.digitalocean2.template>
|
||||
<test.digitalocean2.template>osFamily=UBUNTU,os64Bit=true</test.digitalocean2.template>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
|
|
@ -65,7 +65,7 @@ public class DigitalOcean2ApiMetadata extends BaseHttpApiMetadata<DigitalOcean2A
|
|||
properties.put(AUDIENCE, "https://cloud.digitalocean.com/v1/oauth/token");
|
||||
properties.put(CREDENTIAL_TYPE, BEARER_TOKEN_CREDENTIALS.toString());
|
||||
properties.put(PROPERTY_SESSION_INTERVAL, 3600);
|
||||
properties.put(TEMPLATE, "imageId=ubuntu-14-04-x64");
|
||||
properties.put(TEMPLATE, "osFamily=UBUNTU,os64Bit=true");
|
||||
properties.put(POLL_INITIAL_PERIOD, 5000);
|
||||
properties.put(POLL_MAX_PERIOD, 20000);
|
||||
return properties;
|
||||
|
|
|
@ -17,13 +17,19 @@
|
|||
package org.jclouds.digitalocean2.compute;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static com.google.common.base.Predicates.notNull;
|
||||
import static com.google.common.collect.Iterables.concat;
|
||||
import static com.google.common.collect.Iterables.contains;
|
||||
import static com.google.common.collect.Iterables.filter;
|
||||
import static com.google.common.collect.Iterables.getOnlyElement;
|
||||
import static com.google.common.collect.Iterables.transform;
|
||||
import static com.google.common.collect.Sets.newHashSet;
|
||||
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
|
||||
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
|
||||
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
@ -32,6 +38,7 @@ import org.jclouds.compute.ComputeServiceAdapter;
|
|||
import org.jclouds.compute.domain.Template;
|
||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||
import org.jclouds.digitalocean2.DigitalOcean2Api;
|
||||
import org.jclouds.digitalocean2.compute.internal.ImageInRegion;
|
||||
import org.jclouds.digitalocean2.compute.options.DigitalOcean2TemplateOptions;
|
||||
import org.jclouds.digitalocean2.domain.Action;
|
||||
import org.jclouds.digitalocean2.domain.Droplet;
|
||||
|
@ -43,13 +50,14 @@ import org.jclouds.digitalocean2.domain.options.CreateDropletOptions;
|
|||
import org.jclouds.domain.LoginCredentials;
|
||||
import org.jclouds.logging.Logger;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.primitives.Ints;
|
||||
|
||||
/**
|
||||
* Implementation of the Compute Service for the DigitalOcean API.
|
||||
*/
|
||||
public class DigitalOcean2ComputeServiceAdapter implements ComputeServiceAdapter<Droplet, Size, Image, Region> {
|
||||
public class DigitalOcean2ComputeServiceAdapter implements ComputeServiceAdapter<Droplet, Size, ImageInRegion, Region> {
|
||||
|
||||
@Resource
|
||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||
|
@ -101,8 +109,30 @@ public class DigitalOcean2ComputeServiceAdapter implements ComputeServiceAdapter
|
|||
}
|
||||
|
||||
@Override
|
||||
public Iterable<Image> listImages() {
|
||||
return api.imageApi().list().concat();
|
||||
public Iterable<ImageInRegion> listImages() {
|
||||
// Images can claim to be available in a region that is currently marked as "unavailable". We shouldn't return
|
||||
// the images scoped to those regions.
|
||||
final Set<String> availableRegionsIds = newHashSet(transform(listLocations(), new Function<Region, String>() {
|
||||
@Override
|
||||
public String apply(Region input) {
|
||||
return input.slug();
|
||||
}
|
||||
}));
|
||||
|
||||
// Public images re globally available, but non-public ones can only be available in certain regions.
|
||||
// For these kind of images, return one instance of an ImageInRegion for each region where the image is
|
||||
// available. This way we can properly scope global and concrete images so they can be properly looked up.
|
||||
return concat(filter(api.imageApi().list().concat().transform(new Function<Image, Iterable<ImageInRegion>>() {
|
||||
@Override
|
||||
public Iterable<ImageInRegion> apply(final Image image) {
|
||||
return transform(image.regions(), new Function<String, ImageInRegion>() {
|
||||
@Override
|
||||
public ImageInRegion apply(String region) {
|
||||
return availableRegionsIds.contains(region) ? ImageInRegion.create(image, region) : null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}), notNull()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -142,11 +172,14 @@ public class DigitalOcean2ComputeServiceAdapter implements ComputeServiceAdapter
|
|||
}
|
||||
|
||||
@Override
|
||||
public Image getImage(String id) {
|
||||
public ImageInRegion getImage(String id) {
|
||||
String region = ImageInRegion.extractRegion(id);
|
||||
String imageId = ImageInRegion.extractImageId(id);
|
||||
// The id of the image can be an id or a slug. Use the corresponding method of the API depending on what is
|
||||
// provided. If it can be parsed as a number, use the method to get by ID. Otherwise, get by slug.
|
||||
Integer imageId = Ints.tryParse(id);
|
||||
return imageId != null ? api.imageApi().get(imageId) : api.imageApi().get(id);
|
||||
Integer numericId = Ints.tryParse(imageId);
|
||||
Image image = numericId == null ? api.imageApi().get(imageId) : api.imageApi().get(numericId);
|
||||
return ImageInRegion.create(image, region);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -28,6 +28,7 @@ import javax.inject.Singleton;
|
|||
import org.jclouds.compute.ComputeServiceAdapter;
|
||||
import org.jclouds.compute.config.ComputeServiceAdapterContextModule;
|
||||
import org.jclouds.compute.domain.Hardware;
|
||||
import org.jclouds.compute.domain.Image;
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
import org.jclouds.compute.domain.NodeMetadata.Status;
|
||||
import org.jclouds.compute.extensions.ImageExtension;
|
||||
|
@ -41,15 +42,15 @@ import org.jclouds.digitalocean2.compute.DigitalOcean2ComputeServiceAdapter;
|
|||
import org.jclouds.digitalocean2.compute.extensions.DigitalOcean2ImageExtension;
|
||||
import org.jclouds.digitalocean2.compute.functions.DropletStatusToStatus;
|
||||
import org.jclouds.digitalocean2.compute.functions.DropletToNodeMetadata;
|
||||
import org.jclouds.digitalocean2.compute.functions.ImageToImage;
|
||||
import org.jclouds.digitalocean2.compute.functions.ImageInRegionToImage;
|
||||
import org.jclouds.digitalocean2.compute.functions.RegionToLocation;
|
||||
import org.jclouds.digitalocean2.compute.functions.SizeToHardware;
|
||||
import org.jclouds.digitalocean2.compute.functions.TemplateOptionsToStatementWithoutPublicKey;
|
||||
import org.jclouds.digitalocean2.compute.internal.ImageInRegion;
|
||||
import org.jclouds.digitalocean2.compute.options.DigitalOcean2TemplateOptions;
|
||||
import org.jclouds.digitalocean2.compute.strategy.CreateKeyPairsThenCreateNodes;
|
||||
import org.jclouds.digitalocean2.domain.Action;
|
||||
import org.jclouds.digitalocean2.domain.Droplet;
|
||||
import org.jclouds.digitalocean2.domain.Image;
|
||||
import org.jclouds.digitalocean2.domain.Region;
|
||||
import org.jclouds.digitalocean2.domain.Size;
|
||||
import org.jclouds.domain.Location;
|
||||
|
@ -67,19 +68,19 @@ import com.google.inject.name.Named;
|
|||
* Configures the compute service classes for the DigitalOcean API.
|
||||
*/
|
||||
public class DigitalOcean2ComputeServiceContextModule extends
|
||||
ComputeServiceAdapterContextModule<Droplet, Size, Image, Region> {
|
||||
ComputeServiceAdapterContextModule<Droplet, Size, ImageInRegion, Region> {
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
super.configure();
|
||||
|
||||
bind(new TypeLiteral<ComputeServiceAdapter<Droplet, Size, Image, Region>>() {
|
||||
bind(new TypeLiteral<ComputeServiceAdapter<Droplet, Size, ImageInRegion, Region>>() {
|
||||
}).to(DigitalOcean2ComputeServiceAdapter.class);
|
||||
|
||||
bind(new TypeLiteral<Function<Droplet, NodeMetadata>>() {
|
||||
}).to(DropletToNodeMetadata.class);
|
||||
bind(new TypeLiteral<Function<Image, org.jclouds.compute.domain.Image>>() {
|
||||
}).to(ImageToImage.class);
|
||||
bind(new TypeLiteral<Function<ImageInRegion, Image>>() {
|
||||
}).to(ImageInRegionToImage.class);
|
||||
bind(new TypeLiteral<Function<Region, Location>>() {
|
||||
}).to(RegionToLocation.class);
|
||||
bind(new TypeLiteral<Function<Size, Hardware>>() {
|
||||
|
@ -87,7 +88,7 @@ public class DigitalOcean2ComputeServiceContextModule extends
|
|||
bind(new TypeLiteral<Function<Droplet.Status, Status>>() {
|
||||
}).to(DropletStatusToStatus.class);
|
||||
|
||||
install(new LocationsFromComputeServiceAdapterModule<Droplet, Size, Image, Region>() {
|
||||
install(new LocationsFromComputeServiceAdapterModule<Droplet, Size, ImageInRegion, Region>() {
|
||||
});
|
||||
|
||||
bind(CreateNodesInGroupThenAddToSet.class).to(CreateKeyPairsThenCreateNodes.class);
|
||||
|
|
|
@ -35,6 +35,7 @@ import org.jclouds.compute.domain.ImageTemplateBuilder;
|
|||
import org.jclouds.compute.extensions.ImageExtension;
|
||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||
import org.jclouds.digitalocean2.DigitalOcean2Api;
|
||||
import org.jclouds.digitalocean2.compute.internal.ImageInRegion;
|
||||
import org.jclouds.digitalocean2.domain.Action;
|
||||
import org.jclouds.digitalocean2.domain.Droplet;
|
||||
import org.jclouds.digitalocean2.domain.Droplet.Status;
|
||||
|
@ -58,12 +59,12 @@ public class DigitalOcean2ImageExtension implements ImageExtension {
|
|||
private final DigitalOcean2Api api;
|
||||
private final Predicate<Integer> imageAvailablePredicate;
|
||||
private final Predicate<Integer> nodeStoppedPredicate;
|
||||
private final Function<org.jclouds.digitalocean2.domain.Image, Image> imageTransformer;
|
||||
private final Function<ImageInRegion, Image> imageTransformer;
|
||||
|
||||
@Inject DigitalOcean2ImageExtension(DigitalOcean2Api api,
|
||||
@Named(TIMEOUT_IMAGE_AVAILABLE) Predicate<Integer> imageAvailablePredicate,
|
||||
@Named(TIMEOUT_NODE_SUSPENDED) Predicate<Integer> nodeStoppedPredicate,
|
||||
Function<org.jclouds.digitalocean2.domain.Image, Image> imageTransformer) {
|
||||
Function<ImageInRegion, Image> imageTransformer) {
|
||||
this.api = api;
|
||||
this.imageAvailablePredicate = imageAvailablePredicate;
|
||||
this.nodeStoppedPredicate = nodeStoppedPredicate;
|
||||
|
@ -111,7 +112,8 @@ public class DigitalOcean2ImageExtension implements ImageExtension {
|
|||
}
|
||||
}).get();
|
||||
|
||||
return immediateFuture(imageTransformer.apply(snapshot));
|
||||
// By default snapshots are only available in the Droplet's region
|
||||
return immediateFuture(imageTransformer.apply(ImageInRegion.create(snapshot, droplet.region().slug())));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -18,10 +18,11 @@ package org.jclouds.digitalocean2.compute.functions;
|
|||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.collect.Iterables.find;
|
||||
import static com.google.common.collect.Iterables.tryFind;
|
||||
import static org.jclouds.digitalocean2.compute.internal.ImageInRegion.encodeId;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
@ -35,6 +36,7 @@ import org.jclouds.compute.domain.NodeMetadata.Status;
|
|||
import org.jclouds.compute.domain.NodeMetadataBuilder;
|
||||
import org.jclouds.compute.functions.GroupNamingConvention;
|
||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||
import org.jclouds.digitalocean2.compute.internal.ImageInRegion;
|
||||
import org.jclouds.digitalocean2.domain.Droplet;
|
||||
import org.jclouds.digitalocean2.domain.Networks;
|
||||
import org.jclouds.digitalocean2.domain.Region;
|
||||
|
@ -42,6 +44,7 @@ import org.jclouds.domain.Credentials;
|
|||
import org.jclouds.domain.Location;
|
||||
import org.jclouds.domain.LoginCredentials;
|
||||
import org.jclouds.logging.Logger;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.base.Predicate;
|
||||
|
@ -91,7 +94,7 @@ public class DropletToNodeMetadata implements Function<Droplet, NodeMetadata> {
|
|||
builder.hardware(getHardware(input.sizeSlug()));
|
||||
builder.location(getLocation(input.region()));
|
||||
|
||||
Optional<? extends Image> image = findImage(input.image().id());
|
||||
Optional<? extends Image> image = findImage(input.image(), input.region().slug());
|
||||
if (image.isPresent()) {
|
||||
builder.imageId(image.get().getId());
|
||||
builder.operatingSystem(image.get().getOperatingSystem());
|
||||
|
@ -138,22 +141,8 @@ public class DropletToNodeMetadata implements Function<Droplet, NodeMetadata> {
|
|||
return builder.build();
|
||||
}
|
||||
|
||||
protected Optional<? extends Image> findImage(Integer id) {
|
||||
// Try to find the image by ID in the cache. The cache is indexed by slug (for public images) and by id (for
|
||||
// private ones).
|
||||
final String imageId = String.valueOf(id);
|
||||
Optional<? extends Image> image = Optional.fromNullable(images.get().get(imageId));
|
||||
if (!image.isPresent()) {
|
||||
// If it is a public image (indexed by slug) but the "int" form of the id was provided, try to find it in the
|
||||
// whole list of cached images
|
||||
image = tryFind(images.get().values(), new Predicate<Image>() {
|
||||
@Override
|
||||
public boolean apply(Image input) {
|
||||
return input.getProviderId().equals(imageId);
|
||||
}
|
||||
});
|
||||
}
|
||||
return image;
|
||||
protected Optional<? extends Image> findImage(org.jclouds.digitalocean2.domain.Image image, String region) {
|
||||
return Optional.fromNullable(images.get().get(encodeId(ImageInRegion.create(image, region))));
|
||||
}
|
||||
|
||||
protected Hardware getHardware(final String slug) {
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* 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.digitalocean2.compute.functions;
|
||||
|
||||
import static com.google.common.collect.Iterables.find;
|
||||
import static org.jclouds.compute.domain.OperatingSystem.builder;
|
||||
import static org.jclouds.digitalocean2.compute.internal.ImageInRegion.encodeId;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.collect.Memoized;
|
||||
import org.jclouds.compute.domain.Image;
|
||||
import org.jclouds.compute.domain.Image.Status;
|
||||
import org.jclouds.compute.domain.ImageBuilder;
|
||||
import org.jclouds.digitalocean2.compute.internal.ImageInRegion;
|
||||
import org.jclouds.digitalocean2.domain.OperatingSystem;
|
||||
import org.jclouds.domain.Location;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
/**
|
||||
* Transforms an {@link ImageInRegion} to the jclouds portable model.
|
||||
*/
|
||||
@Singleton
|
||||
public class ImageInRegionToImage implements Function<ImageInRegion, Image> {
|
||||
|
||||
private final Supplier<Set<? extends Location>> locations;
|
||||
|
||||
@Inject ImageInRegionToImage(@Memoized Supplier<Set<? extends Location>> locations) {
|
||||
this.locations = locations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Image apply(final ImageInRegion input) {
|
||||
String description = input.image().distribution() + " " + input.image().name();
|
||||
ImageBuilder builder = new ImageBuilder();
|
||||
// Private images don't have a slug
|
||||
builder.id(encodeId(input));
|
||||
builder.providerId(String.valueOf(input.image().id()));
|
||||
builder.name(input.image().name());
|
||||
builder.description(description);
|
||||
builder.status(Status.AVAILABLE);
|
||||
builder.location(getLocation(input.region()));
|
||||
|
||||
OperatingSystem os = OperatingSystem.create(input.image().name(), input.image().distribution());
|
||||
|
||||
builder.operatingSystem(builder()
|
||||
.name(os.distribution().value())
|
||||
.family(os.distribution().osFamily())
|
||||
.description(description)
|
||||
.arch(os.arch())
|
||||
.version(os.version())
|
||||
.is64Bit(os.is64bit())
|
||||
.build());
|
||||
|
||||
ImmutableMap.Builder<String, String> metadata = ImmutableMap.builder();
|
||||
metadata.put("publicImage", String.valueOf(input.image().isPublic()));
|
||||
builder.userMetadata(metadata.build());
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
protected Location getLocation(final String region) {
|
||||
return find(locations.get(), new Predicate<Location>() {
|
||||
@Override
|
||||
public boolean apply(Location location) {
|
||||
return region.equals(location.getId());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
/*
|
||||
* 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.digitalocean2.compute.functions;
|
||||
|
||||
import static org.jclouds.compute.domain.OperatingSystem.builder;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.compute.domain.Image.Status;
|
||||
import org.jclouds.compute.domain.ImageBuilder;
|
||||
import org.jclouds.digitalocean2.domain.Image;
|
||||
import org.jclouds.digitalocean2.domain.OperatingSystem;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
/**
|
||||
* Transforms an {@link Image} to the jclouds portable model.
|
||||
*/
|
||||
@Singleton
|
||||
public class ImageToImage implements Function<Image, org.jclouds.compute.domain.Image> {
|
||||
|
||||
@Override
|
||||
public org.jclouds.compute.domain.Image apply(final Image input) {
|
||||
String description = input.distribution() + " " + input.name();
|
||||
ImageBuilder builder = new ImageBuilder();
|
||||
// Private images don't have a slug
|
||||
builder.id(input.slug() != null ? input.slug() : String.valueOf(input.id()));
|
||||
builder.providerId(String.valueOf(input.id()));
|
||||
builder.name(input.name());
|
||||
builder.description(description);
|
||||
builder.status(Status.AVAILABLE);
|
||||
|
||||
OperatingSystem os = OperatingSystem.create(input.name(), input.distribution());
|
||||
|
||||
builder.operatingSystem(builder()
|
||||
.name(os.distribution().value())
|
||||
.family(os.distribution().osFamily())
|
||||
.description(description)
|
||||
.arch(os.arch())
|
||||
.version(os.version())
|
||||
.is64Bit(os.is64bit())
|
||||
.build());
|
||||
|
||||
ImmutableMap.Builder<String, String> metadata = ImmutableMap.builder();
|
||||
metadata.put("publicImage", String.valueOf(input.isPublic()));
|
||||
builder.userMetadata(metadata.build());
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* 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.digitalocean2.compute.internal;
|
||||
|
||||
import org.jclouds.digitalocean2.domain.Image;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
|
||||
/**
|
||||
* Scopes an image to a particular region.
|
||||
*/
|
||||
@AutoValue
|
||||
public abstract class ImageInRegion {
|
||||
|
||||
public abstract Image image();
|
||||
public abstract String region();
|
||||
|
||||
public static ImageInRegion create(Image image, String region) {
|
||||
return new AutoValue_ImageInRegion(image, region);
|
||||
}
|
||||
|
||||
public static String encodeId(ImageInRegion imageInRegion) {
|
||||
// Private images don't have a slug
|
||||
return String.format("%s/%s", imageInRegion.region(), slugOrId(imageInRegion.image()));
|
||||
}
|
||||
|
||||
public static String extractRegion(String imageId) {
|
||||
return imageId.substring(0, imageId.indexOf('/'));
|
||||
}
|
||||
|
||||
public static String extractImageId(String imageId) {
|
||||
return imageId.substring(imageId.indexOf('/') + 1);
|
||||
}
|
||||
|
||||
private static String slugOrId(Image image) {
|
||||
return image.slug() != null ? image.slug() : String.valueOf(image.id());
|
||||
}
|
||||
|
||||
ImageInRegion() { }
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
org.jclouds.digitalocean2.DigitalOcean2ApiMetadata
|
|
@ -40,7 +40,7 @@ public class DigitalOcean2TemplateBuilderLiveTest extends BaseTemplateBuilderLiv
|
|||
@Override
|
||||
public void testDefaultTemplateBuilder() throws IOException {
|
||||
Template defaultTemplate = view.getComputeService().templateBuilder().build();
|
||||
assert defaultTemplate.getImage().getOperatingSystem().getVersion().equals("14.04") : defaultTemplate
|
||||
assert defaultTemplate.getImage().getOperatingSystem().getVersion().equals("15.04") : defaultTemplate
|
||||
.getImage().getOperatingSystem().getVersion();
|
||||
assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), true);
|
||||
assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU);
|
||||
|
|
|
@ -83,7 +83,7 @@ public class DropletToNodeMetadataTest {
|
|||
region = Region.create("sfo1", "San Francisco 1", ImmutableList.of("2gb"), true, ImmutableList.<String> of());
|
||||
|
||||
images = ImmutableSet.of(new ImageBuilder()
|
||||
.id("ubuntu-1404-x86")
|
||||
.id("sfo1/ubuntu-1404-x86")
|
||||
.providerId("1")
|
||||
.name("mock image")
|
||||
.status(AVAILABLE)
|
||||
|
@ -132,7 +132,7 @@ public class DropletToNodeMetadataTest {
|
|||
ImmutableList.<Networks.Address> of()), null);
|
||||
|
||||
NodeMetadata expected = new NodeMetadataBuilder().ids("1").hardware(getOnlyElement(hardwares))
|
||||
.imageId("ubuntu-1404-x86").status(RUNNING).location(getOnlyElement(locations)).name("mock-droplet")
|
||||
.imageId("sfo1/ubuntu-1404-x86").status(RUNNING).location(getOnlyElement(locations)).name("mock-droplet")
|
||||
.hostname("mock-droplet").group("mock").credentials(credentials)
|
||||
.publicAddresses(ImmutableSet.of("84.45.69.3")).privateAddresses(ImmutableSet.of("192.168.2.5"))
|
||||
.providerId("1").backendStatus(ACTIVE.name()).operatingSystem(getOnlyElement(images).getOperatingSystem())
|
||||
|
|
|
@ -20,25 +20,64 @@ import static org.jclouds.compute.domain.Image.Status.AVAILABLE;
|
|||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jclouds.compute.domain.ImageBuilder;
|
||||
import org.jclouds.compute.domain.OperatingSystem;
|
||||
import org.jclouds.compute.domain.OsFamily;
|
||||
import org.jclouds.digitalocean2.compute.internal.ImageInRegion;
|
||||
import org.jclouds.digitalocean2.domain.Image;
|
||||
import org.jclouds.domain.Location;
|
||||
import org.jclouds.domain.LocationBuilder;
|
||||
import org.jclouds.domain.LocationScope;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
@Test(groups = "unit", testName = "ImageToImageTest")
|
||||
public class ImageToImageTest {
|
||||
public class ImageInRegionToImageTest {
|
||||
|
||||
private Set<Location> locations;
|
||||
|
||||
private ImageInRegionToImage function;
|
||||
|
||||
@BeforeMethod
|
||||
public void setup() {
|
||||
locations = ImmutableSet.of(
|
||||
new LocationBuilder()
|
||||
.id("sfo1")
|
||||
.description("sfo1/San Francisco 1")
|
||||
.scope(LocationScope.REGION)
|
||||
.parent(
|
||||
new LocationBuilder().id("0").description("mock parent location").scope(LocationScope.PROVIDER)
|
||||
.build()).build(),
|
||||
new LocationBuilder()
|
||||
.id("lon1")
|
||||
.description("lon1/London 1")
|
||||
.scope(LocationScope.REGION)
|
||||
.parent(
|
||||
new LocationBuilder().id("0").description("mock parent location").scope(LocationScope.PROVIDER)
|
||||
.build()).build());
|
||||
|
||||
function = new ImageInRegionToImage(new Supplier<Set<? extends Location>>() {
|
||||
@Override
|
||||
public Set<? extends Location> get() {
|
||||
return locations;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvertImage() {
|
||||
Image image = Image.create(1, "14.04 x64", "distribution", "Ubuntu", "ubuntu-1404-x86", true,
|
||||
ImmutableList.of("sfo1"), new Date());
|
||||
ImmutableList.of("sfo1", "lon1"), new Date());
|
||||
org.jclouds.compute.domain.Image expected = new ImageBuilder()
|
||||
.id("ubuntu-1404-x86")
|
||||
.id("lon1/ubuntu-1404-x86") // Location scoped images have the location encoded in the id
|
||||
.providerId("1")
|
||||
.name("14.04 x64")
|
||||
.description("Ubuntu 14.04 x64")
|
||||
|
@ -46,12 +85,14 @@ public class ImageToImageTest {
|
|||
.operatingSystem(
|
||||
OperatingSystem.builder().name("Ubuntu").description("Ubuntu 14.04 x64").family(OsFamily.UBUNTU)
|
||||
.version("14.04").arch("x64").is64Bit(true).build())
|
||||
.location(Iterables.get(locations, 1))
|
||||
.userMetadata(ImmutableMap.of("publicImage", "true")).build();
|
||||
|
||||
org.jclouds.compute.domain.Image result = new ImageToImage().apply(image);
|
||||
org.jclouds.compute.domain.Image result = function.apply(ImageInRegion.create(image, "lon1"));
|
||||
assertEquals(result, expected);
|
||||
assertEquals(result.getDescription(), expected.getDescription());
|
||||
assertEquals(result.getOperatingSystem(), expected.getOperatingSystem());
|
||||
assertEquals(result.getStatus(), expected.getStatus());
|
||||
assertEquals(result.getLocation(), Iterables.get(locations, 1));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue