Trying to Mock GCE API for tests

This commit is contained in:
David Pilato 2013-07-01 23:17:14 +02:00
parent 530ae2169e
commit 0d40a0e2f9
7 changed files with 231 additions and 88 deletions

27
pom.xml
View File

@ -99,6 +99,14 @@ governing permissions and limitations under the License. -->
</dependencies> </dependencies>
<build> <build>
<extensions>
<extension>
<groupId>org.kuali.maven.wagons</groupId>
<artifactId>maven-s3-wagon</artifactId>
<version>1.1.19</version>
</extension>
</extensions>
<resources> <resources>
<resource> <resource>
<directory>src/main/resources</directory> <directory>src/main/resources</directory>
@ -153,6 +161,25 @@ governing permissions and limitations under the License. -->
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>wagon-maven-plugin</artifactId>
<version>1.0-beta-4</version>
<configuration>
<serverId>elasticsearch.download</serverId>
<fromFile>${project.build.directory}/releases/${project.build.finalName}.zip</fromFile>
<url>s3://test.elasticsearch.org/elasticsearch/${project.artifactId}/</url>
</configuration>
<executions>
<execution>
<id>upload-zip-to-server</id>
<phase>deploy</phase>
<goals>
<goal>upload-single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins> </plugins>
</build> </build>
</project> </project>

View File

@ -19,88 +19,20 @@
package org.elasticsearch.cloud.gce; package org.elasticsearch.cloud.gce;
import com.google.api.client.googleapis.compute.ComputeCredential; import com.google.api.services.compute.model.Instance;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport; import java.util.Collection;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.compute.Compute;
import org.elasticsearch.ElasticSearchException;
import org.elasticsearch.common.component.AbstractLifecycleComponent;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.settings.SettingsFilter;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.discovery.DiscoveryException;
/** /**
* *
*/ */
public class GceComputeService extends AbstractLifecycleComponent<GceComputeService> { public interface GceComputeService {
static final public class Fields {
static final class Fields { public static final String PROJECT = "project_id";
private static final String VERSION = "Elasticsearch/GceCloud/1.0"; public static final String ZONE = "zone";
public static final String REFRESH = "refresh_interval";
public static final String VERSION = "Elasticsearch/GceCloud/1.0";
} }
private Compute client; public Collection<Instance> instances();
private TimeValue refreshInterval = null;
private long lastRefresh;
/** Global instance of the HTTP transport. */
private static HttpTransport HTTP_TRANSPORT;
/** Global instance of the JSON factory. */
private static JsonFactory JSON_FACTORY;
@Inject
public GceComputeService(Settings settings, SettingsFilter settingsFilter) {
super(settings);
settingsFilter.addFilter(new GceSettingsFilter());
}
public synchronized Compute client() {
if (refreshInterval != null && refreshInterval.millis() != 0) {
if (client != null &&
(refreshInterval.millis() < 0 || (System.currentTimeMillis() - lastRefresh) < refreshInterval.millis())) {
if (logger.isTraceEnabled()) logger.trace("using cache to retrieve client");
return client;
}
lastRefresh = System.currentTimeMillis();
}
try {
HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
JSON_FACTORY = new JacksonFactory();
logger.debug("starting GCE discovery service");
ComputeCredential credential = new ComputeCredential.Builder(HTTP_TRANSPORT, JSON_FACTORY).build();
credential.refreshToken();
logger.debug("token [{}] will expire in [{}] s", credential.getAccessToken(), credential.getExpiresInSeconds());
refreshInterval = TimeValue.timeValueSeconds(credential.getExpiresInSeconds()-1);
// Once done, let's use this token
this.client = new Compute.Builder(HTTP_TRANSPORT, JSON_FACTORY, null)
.setApplicationName(Fields.VERSION)
.setHttpRequestInitializer(credential)
.build();
} catch (Exception e) {
logger.warn("unable to start GCE discovery service: {} : {}", e.getClass().getName(), e.getMessage());
throw new DiscoveryException("unable to start GCE discovery service", e);
}
return this.client;
}
@Override
protected void doStart() throws ElasticSearchException {
}
@Override
protected void doStop() throws ElasticSearchException {
}
@Override
protected void doClose() throws ElasticSearchException {
}
} }

View File

@ -0,0 +1,127 @@
/*
* Licensed to ElasticSearch under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. ElasticSearch 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.elasticsearch.cloud.gce;
import com.google.api.client.googleapis.compute.ComputeCredential;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.compute.Compute;
import com.google.api.services.compute.model.Instance;
import com.google.api.services.compute.model.InstanceList;
import org.elasticsearch.ElasticSearchException;
import org.elasticsearch.common.component.AbstractLifecycleComponent;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.settings.SettingsFilter;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.discovery.DiscoveryException;
import java.io.IOException;
import java.util.Collection;
/**
*
*/
public class GceComputeServiceImpl extends AbstractLifecycleComponent<GceComputeServiceImpl>
implements GceComputeService {
private final String project;
private final String zone;
@Override
public Collection<Instance> instances() {
try {
Compute.Instances.List list = client().instances().list(project, zone);
InstanceList instanceList = list.execute();
return instanceList.getItems();
} catch (IOException e) {
throw new ElasticSearchException("Pas glop");
}
}
private Compute client;
private TimeValue refreshInterval = null;
private long lastRefresh;
/** Global instance of the HTTP transport. */
private static HttpTransport HTTP_TRANSPORT;
/** Global instance of the JSON factory. */
private static JsonFactory JSON_FACTORY;
@Inject
public GceComputeServiceImpl(Settings settings, SettingsFilter settingsFilter) {
super(settings);
settingsFilter.addFilter(new GceSettingsFilter());
this.project = componentSettings.get(Fields.PROJECT, settings.get("cloud.gce." + Fields.PROJECT));
this.zone = componentSettings.get(Fields.ZONE, settings.get("cloud.gce." + Fields.ZONE));
}
public synchronized Compute client() {
if (refreshInterval != null && refreshInterval.millis() != 0) {
if (client != null &&
(refreshInterval.millis() < 0 || (System.currentTimeMillis() - lastRefresh) < refreshInterval.millis())) {
if (logger.isTraceEnabled()) logger.trace("using cache to retrieve client");
return client;
}
lastRefresh = System.currentTimeMillis();
}
try {
HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
JSON_FACTORY = new JacksonFactory();
logger.debug("starting GCE discovery service");
ComputeCredential credential = new ComputeCredential.Builder(HTTP_TRANSPORT, JSON_FACTORY).build();
credential.refreshToken();
logger.debug("token [{}] will expire in [{}] s", credential.getAccessToken(), credential.getExpiresInSeconds());
refreshInterval = TimeValue.timeValueSeconds(credential.getExpiresInSeconds()-1);
// Once done, let's use this token
this.client = new Compute.Builder(HTTP_TRANSPORT, JSON_FACTORY, null)
.setApplicationName(Fields.VERSION)
.setHttpRequestInitializer(credential)
.build();
} catch (Exception e) {
logger.warn("unable to start GCE discovery service: {} : {}", e.getClass().getName(), e.getMessage());
throw new DiscoveryException("unable to start GCE discovery service", e);
}
return this.client;
}
@Override
protected void doStart() throws ElasticSearchException {
}
@Override
protected void doStop() throws ElasticSearchException {
}
@Override
protected void doClose() throws ElasticSearchException {
}
}

View File

@ -28,6 +28,6 @@ public class GceModule extends AbstractModule {
@Override @Override
protected void configure() { protected void configure() {
bind(GceComputeService.class).asEagerSingleton(); bind(GceComputeService.class).to(GceComputeServiceImpl.class).asEagerSingleton();
} }
} }

View File

@ -19,10 +19,8 @@
package org.elasticsearch.discovery.gce; package org.elasticsearch.discovery.gce;
import com.google.api.services.compute.Compute;
import com.google.api.services.compute.model.AccessConfig; import com.google.api.services.compute.model.AccessConfig;
import com.google.api.services.compute.model.Instance; import com.google.api.services.compute.model.Instance;
import com.google.api.services.compute.model.InstanceList;
import com.google.api.services.compute.model.NetworkInterface; import com.google.api.services.compute.model.NetworkInterface;
import org.elasticsearch.cloud.gce.GceComputeService; import org.elasticsearch.cloud.gce.GceComputeService;
import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNode;
@ -40,6 +38,7 @@ import org.elasticsearch.transport.TransportService;
import java.io.IOException; import java.io.IOException;
import java.net.InetAddress; import java.net.InetAddress;
import java.util.Collection;
import java.util.List; import java.util.List;
/** /**
@ -125,11 +124,9 @@ public class GceUnicastHostsProvider extends AbstractComponent implements Unicas
} }
try { try {
Compute.Instances.List list = gceComputeService.client().instances().list(project, zone); Collection<Instance> instances = gceComputeService.instances();
InstanceList instanceList = list.execute(); for (Instance instance : instances) {
for (Instance instance : instanceList.getItems()) {
String name = instance.getName(); String name = instance.getName();
String type = instance.getMachineType(); String type = instance.getMachineType();
String image = instance.getImage(); String image = instance.getImage();
@ -215,7 +212,7 @@ public class GceUnicastHostsProvider extends AbstractComponent implements Unicas
} }
} }
} catch (IOException e) { } catch (Throwable e) {
logger.warn("Exception caught during discovery {} : {}", e.getClass().getName(), e.getMessage()); logger.warn("Exception caught during discovery {} : {}", e.getClass().getName(), e.getMessage());
logger.trace("Exception caught during discovery", e); logger.trace("Exception caught during discovery", e);
} }

View File

@ -19,7 +19,7 @@
package org.elasticsearch.plugin.cloud.gce; package org.elasticsearch.plugin.cloud.gce;
import org.elasticsearch.cloud.gce.GceComputeService; import org.elasticsearch.cloud.gce.GceComputeServiceImpl;
import org.elasticsearch.cloud.gce.GceModule; import org.elasticsearch.cloud.gce.GceModule;
import org.elasticsearch.common.collect.Lists; import org.elasticsearch.common.collect.Lists;
import org.elasticsearch.common.component.LifecycleComponent; import org.elasticsearch.common.component.LifecycleComponent;
@ -63,7 +63,7 @@ public class CloudGcePlugin extends AbstractPlugin {
public Collection<Class<? extends LifecycleComponent>> services() { public Collection<Class<? extends LifecycleComponent>> services() {
Collection<Class<? extends LifecycleComponent>> services = Lists.newArrayList(); Collection<Class<? extends LifecycleComponent>> services = Lists.newArrayList();
if (settings.getAsBoolean("cloud.enabled", true)) { if (settings.getAsBoolean("cloud.enabled", true)) {
services.add(GceComputeService.class); services.add(GceComputeServiceImpl.class);
} }
return services; return services;
} }

View File

@ -0,0 +1,60 @@
/*
* Licensed to ElasticSearch under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. ElasticSearch 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.elasticsearch.cloud.gce.tests;
import com.google.api.services.compute.model.Instance;
import org.elasticsearch.ElasticSearchException;
import org.elasticsearch.cloud.gce.GceComputeService;
import org.elasticsearch.common.component.AbstractLifecycleComponent;
import org.elasticsearch.common.settings.Settings;
import java.util.ArrayList;
import java.util.Collection;
/**
*
*/
public class GceComputeServiceMock extends AbstractLifecycleComponent<GceComputeServiceMock>
implements GceComputeService {
protected GceComputeServiceMock(Settings settings) {
super(settings);
logger.debug("Starting MOCK");
}
@Override
public Collection<Instance> instances() {
Collection<Instance> instances = new ArrayList<Instance>();
return instances;
}
@Override
protected void doStart() throws ElasticSearchException {
}
@Override
protected void doStop() throws ElasticSearchException {
}
@Override
protected void doClose() throws ElasticSearchException {
}
}