Issue 191: normalized common aggregate commands into ChefService

This commit is contained in:
Adrian Cole 2010-07-27 17:09:10 -07:00
parent d884978a98
commit 56caac57f1
38 changed files with 1374 additions and 162 deletions

View File

@ -198,7 +198,7 @@ public interface ChefAsyncClient {
*/ */
@POST @POST
@Path("nodes") @Path("nodes")
ListenableFuture<Node> createNode(@BinderParam(BindToJsonPayload.class) Node node); ListenableFuture<Void> createNode(@BinderParam(BindToJsonPayload.class) Node node);
/** /**
* @see ChefClient#updateNode * @see ChefClient#updateNode
@ -288,8 +288,7 @@ public interface ChefAsyncClient {
@ResponseParser(ParseKeySetFromJson.class) @ResponseParser(ParseKeySetFromJson.class)
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<Set<String>> listRoles(); ListenableFuture<Set<String>> listRoles();
/** /**
* @see ChefClient#createDataBag * @see ChefClient#createDataBag
*/ */
@ -302,8 +301,8 @@ public interface ChefAsyncClient {
*/ */
@PUT @PUT
@Path("data/{path}") @Path("data/{path}")
ListenableFuture<JsonBall> updateDataBag( ListenableFuture<JsonBall> updateDataBag(@PathParam("path") String path,
@PathParam("path") String path, @BinderParam(BindToJsonPayload.class) JsonBall node); @BinderParam(BindToJsonPayload.class) JsonBall node);
/** /**
* @see ChefDataBag#nodeExists * @see ChefDataBag#nodeExists

View File

@ -235,7 +235,7 @@ public interface ChefClient {
* "409 Conflict" if the node already exists * "409 Conflict" if the node already exists
*/ */
@Timeout(duration = 120, timeUnit = TimeUnit.SECONDS) @Timeout(duration = 120, timeUnit = TimeUnit.SECONDS)
Node createNode(Node node); void createNode(Node node);
/** /**
* Creates or updates (uploads) a node //TODO document * Creates or updates (uploads) a node //TODO document

View File

@ -0,0 +1,37 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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 org.jclouds.chef;
import org.jclouds.chef.internal.ChefContextImpl;
import org.jclouds.rest.RestContext;
import com.google.inject.ImplementedBy;
/**
*
*
* @author Adrian Cole
*
*/
@ImplementedBy(ChefContextImpl.class)
public interface ChefContext extends RestContext<ChefClient, ChefAsyncClient>{
ChefService getChefService();
}

View File

@ -1,24 +1,19 @@
/** /**
* *
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed under the Apache License, Version 2.0 (the "License");
* or more contributor license agreements. See the NOTICE file * you may not use this file except in compliance with the License.
* distributed with this work for additional information * You may obtain a copy of the License at
* 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 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, * Unless required by applicable law or agreed to in writing, software
* software distributed under the License is distributed on an * distributed under the License is distributed on an "AS IS" BASIS,
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* KIND, either express or implied. See the License for the * See the License for the specific language governing permissions and
* specific language governing permissions and limitations * limitations under the License.
* under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.chef; package org.jclouds.chef;
@ -27,12 +22,16 @@ import java.util.List;
import java.util.Properties; import java.util.Properties;
import org.jclouds.chef.config.ChefRestClientModule; import org.jclouds.chef.config.ChefRestClientModule;
import org.jclouds.ohai.config.ConfiguresOhai;
import org.jclouds.ohai.config.JMXOhaiJVMModule;
import org.jclouds.rest.RestContextBuilder; import org.jclouds.rest.RestContextBuilder;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.inject.Injector;
import com.google.inject.Module; import com.google.inject.Module;
/** /**
*
* @author Adrian Cole * @author Adrian Cole
*/ */
public class ChefContextBuilder extends RestContextBuilder<ChefClient, ChefAsyncClient> { public class ChefContextBuilder extends RestContextBuilder<ChefClient, ChefAsyncClient> {
@ -41,8 +40,44 @@ public class ChefContextBuilder extends RestContextBuilder<ChefClient, ChefAsync
super(ChefClient.class, ChefAsyncClient.class, props); super(ChefClient.class, ChefAsyncClient.class, props);
} }
@Override
protected void addClientModule(List<Module> modules) { protected void addClientModule(List<Module> modules) {
modules.add(new ChefRestClientModule()); modules.add(new ChefRestClientModule());
} }
} @Override
public Injector buildInjector() {
addOhaiModuleIfNotPresent();
return super.buildInjector();
}
/**
* {@inheritDoc}
*/
@Override
public ChefContextBuilder withModules(Module... modules) {
return (ChefContextBuilder) super.withModules(modules);
}
@SuppressWarnings("unchecked")
@Override
public ChefContext buildContext() {
Injector injector = buildInjector();
return injector.getInstance(ChefContext.class);
}
protected void addOhaiModuleIfNotPresent() {
if (!Iterables.any(modules, new Predicate<Module>() {
public boolean apply(Module input) {
return input.getClass().isAnnotationPresent(ConfiguresOhai.class);
}
})) {
addOhaiModule();
}
}
protected void addOhaiModule() {
modules.add(new JMXOhaiJVMModule());
}
}

View File

@ -0,0 +1,32 @@
package org.jclouds.chef;
import java.util.Set;
import org.jclouds.chef.domain.Node;
import org.jclouds.chef.internal.BaseChefService;
import com.google.common.base.Predicate;
import com.google.inject.ImplementedBy;
/**
* Provides high level chef operations
*
* @author Adrian Cole
*/
@ImplementedBy(BaseChefService.class)
public interface ChefService {
void cleanupStaleNodesAndClients(String prefix, int minutesStale);
void createNodeAndPopulateAutomaticAttributes(String nodeName, Iterable<String> runList);
void deleteAllClientsAndNodesInList(Iterable<String> names);
Set<Node> getNodes();
Set<Node> getNodesWithNamesMatching(Predicate<String> nodeNameSelector);
Set<Node> getNodesNamed(Iterable<String> names);
void updateAutomaticAttributesOnNode(String nodeName);
}

View File

@ -0,0 +1,86 @@
package org.jclouds.chef.internal;
import java.util.Set;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.chef.ChefService;
import org.jclouds.chef.domain.Node;
import org.jclouds.chef.reference.ChefConstants;
import org.jclouds.chef.strategy.CleanupStaleNodesAndClients;
import org.jclouds.chef.strategy.CreateNodeAndPopulateAutomaticAttributes;
import org.jclouds.chef.strategy.DeleteAllClientsAndNodesInList;
import org.jclouds.chef.strategy.GetNodes;
import org.jclouds.chef.strategy.UpdateAutomaticAttributesOnNode;
import org.jclouds.logging.Logger;
import com.google.common.base.Predicate;
/**
*
* @author Adrian Cole
*/
@Singleton
public class BaseChefService implements ChefService {
@Resource
@Named(ChefConstants.CHEF_LOGGER)
protected Logger logger = Logger.NULL;
private final CleanupStaleNodesAndClients cleanupStaleNodesAndClients;
private final CreateNodeAndPopulateAutomaticAttributes createNodeAndPopulateAutomaticAttributes;
private final DeleteAllClientsAndNodesInList deleteAllClientsAndNodesInList;
private final GetNodes getNodes;
private final UpdateAutomaticAttributesOnNode updateAutomaticAttributesOnNode;
@Inject
protected BaseChefService(CleanupStaleNodesAndClients cleanupStaleNodesAndClients,
CreateNodeAndPopulateAutomaticAttributes createNodeAndPopulateAutomaticAttributes,
DeleteAllClientsAndNodesInList deleteAllClientsAndNodesInList, GetNodes getNodes,
UpdateAutomaticAttributesOnNode updateAutomaticAttributesOnNode) {
this.cleanupStaleNodesAndClients = cleanupStaleNodesAndClients;
this.createNodeAndPopulateAutomaticAttributes = createNodeAndPopulateAutomaticAttributes;
this.deleteAllClientsAndNodesInList = deleteAllClientsAndNodesInList;
this.getNodes = getNodes;
this.updateAutomaticAttributesOnNode = updateAutomaticAttributesOnNode;
}
@Override
public void cleanupStaleNodesAndClients(String prefix, int minutesStale) {
cleanupStaleNodesAndClients.execute(prefix, minutesStale);
}
@Override
public void createNodeAndPopulateAutomaticAttributes(String nodeName, Iterable<String> runList) {
createNodeAndPopulateAutomaticAttributes.execute(nodeName, runList);
}
@Override
public void deleteAllClientsAndNodesInList(Iterable<String> names) {
deleteAllClientsAndNodesInList.execute(names);
}
@Override
public Set<Node> getNodes() {
return getNodes.execute();
}
@Override
public Set<Node> getNodesWithNamesMatching(Predicate<String> nodeNameSelector) {
return getNodes.execute(nodeNameSelector);
}
@Override
public Set<Node> getNodesNamed(Iterable<String> names) {
return getNodes.execute(names);
}
@Override
public void updateAutomaticAttributesOnNode(String nodeName) {
updateAutomaticAttributesOnNode.execute(nodeName);
}
}

View File

@ -0,0 +1,61 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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 org.jclouds.chef.internal;
import java.net.URI;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.chef.ChefAsyncClient;
import org.jclouds.chef.ChefClient;
import org.jclouds.chef.ChefContext;
import org.jclouds.chef.ChefService;
import org.jclouds.lifecycle.Closer;
import org.jclouds.rest.Utils;
import org.jclouds.rest.annotations.ApiVersion;
import org.jclouds.rest.annotations.Identity;
import org.jclouds.rest.annotations.Provider;
import org.jclouds.rest.internal.RestContextImpl;
import com.google.inject.Injector;
import com.google.inject.TypeLiteral;
/**
* @author Adrian Cole
*/
@Singleton
public class ChefContextImpl extends RestContextImpl<ChefClient, ChefAsyncClient> implements ChefContext {
private final ChefService chefService;
@Inject
protected ChefContextImpl(Closer closer, Utils utils, Injector injector, TypeLiteral<ChefClient> syncApi,
TypeLiteral<ChefAsyncClient> asyncApi, @Provider URI endpoint, @Provider String provider,
@Identity String identity, @ApiVersion String apiVersion, ChefService chefService) {
super(closer, utils, injector, syncApi, asyncApi, endpoint, provider, identity, apiVersion);
this.chefService = chefService;
}
@Override
public ChefService getChefService() {
return chefService;
}
}

View File

@ -50,7 +50,8 @@ public interface ChefConstants {
/** /**
* There are generally 3 types of identities * There are generally 3 types of identities
* <ul> * <ul>
* <li>validator - used to create clients within an organization; {@code orgname}-validator</li> * <li>validator - used to create clients within an organization; {@code
* orgname}-validator</li>
* <li>client - scoped to an organization, used on nodes to run chef</li> * <li>client - scoped to an organization, used on nodes to run chef</li>
* <li>user - used to run commands like knife and access cookbook sites</li> * <li>user - used to run commands like knife and access cookbook sites</li>
* </ul> * </ul>
@ -64,4 +65,7 @@ public interface ChefConstants {
/** /**
* how often to refresh timestamps in seconds. * how often to refresh timestamps in seconds.
*/ */
public static final String CHEF_LOGGER = "jclouds.chef";
} }

View File

@ -0,0 +1,36 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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 org.jclouds.chef.strategy;
import org.jclouds.chef.strategy.internal.CleanupStaleNodesAndClientsImpl;
import com.google.inject.ImplementedBy;
/**
*
* Cleans up nodes and clients who have been hanging around too long.
*
* @author Adrian Cole
*/
@ImplementedBy(CleanupStaleNodesAndClientsImpl.class)
public interface CleanupStaleNodesAndClients {
void execute(String prefix, int secondsStale);
}

View File

@ -0,0 +1,37 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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 org.jclouds.chef.strategy;
import org.jclouds.chef.domain.Node;
import org.jclouds.chef.strategy.internal.CreateNodeAndPopulateAutomaticAttributesImpl;
import com.google.inject.ImplementedBy;
/**
*
* Creates a new node with automatic attributes.
*
* @author Adrian Cole
*/
@ImplementedBy(CreateNodeAndPopulateAutomaticAttributesImpl.class)
public interface CreateNodeAndPopulateAutomaticAttributes {
void execute(Node node);
void execute(String nodeName, Iterable<String> runList);
}

View File

@ -18,64 +18,18 @@
*/ */
package org.jclouds.chef.strategy; package org.jclouds.chef.strategy;
import static com.google.common.collect.Maps.newHashMap; import org.jclouds.chef.strategy.internal.DeleteAllClientsAndNodesInListImpl;
import static org.jclouds.concurrent.ConcurrentUtils.awaitCompletion;
import java.util.Map; import com.google.inject.ImplementedBy;
import java.util.concurrent.ExecutorService;
import javax.annotation.Resource;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.Constants;
import org.jclouds.chef.ChefAsyncClient;
import org.jclouds.chef.ChefClient;
import org.jclouds.logging.Logger;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.inject.Inject;
/** /**
* *
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Singleton @ImplementedBy(DeleteAllClientsAndNodesInListImpl.class)
public class DeleteAllClientsAndNodesInList { public interface DeleteAllClientsAndNodesInList {
protected final ChefClient chefClient; public void execute(Iterable<String> names);
protected final ChefAsyncClient chefAsyncClient;
protected final ExecutorService userExecutor;
@Resource
protected Logger logger = Logger.NULL;
@Inject(optional = true)
@Named(Constants.PROPERTY_REQUEST_TIMEOUT)
protected Long maxTime;
@Inject
DeleteAllClientsAndNodesInList(@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor,
ChefClient getAllNode, ChefAsyncClient ablobstore) {
this.userExecutor = userExecutor;
this.chefAsyncClient = ablobstore;
this.chefClient = getAllNode;
}
public void execute() {
execute(chefClient.listNodes());
}
public void execute(Iterable<String> names) {
Map<String, Exception> exceptions = newHashMap();
Map<String, ListenableFuture<?>> responses = newHashMap();
for (String name : names) {
responses.put(name, chefAsyncClient.deleteClient(name));
responses.put(name, chefAsyncClient.deleteNode(name));
}
exceptions = awaitCompletion(responses, userExecutor, maxTime, logger, String.format(
"getting deleting clients and nodes: %s", names));
if (exceptions.size() > 0)
throw new RuntimeException(String.format("errors deleting clients and nodes: %s: %s", names, exceptions));
}
} }

View File

@ -0,0 +1,42 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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 org.jclouds.chef.strategy;
import java.util.Set;
import org.jclouds.chef.domain.Node;
import org.jclouds.chef.strategy.internal.GetNodesImpl;
import com.google.common.base.Predicate;
import com.google.inject.ImplementedBy;
/**
*
*
* @author Adrian Cole
*/
@ImplementedBy(GetNodesImpl.class)
public interface GetNodes {
Set<Node> execute();
Set<Node> execute(Predicate<String> nodeNameSelector);
Set<Node> execute(Iterable<String> toGet);
}

View File

@ -0,0 +1,35 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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 org.jclouds.chef.strategy;
import org.jclouds.chef.strategy.internal.UpdateAutomaticAttributesOnNodeImpl;
import com.google.inject.ImplementedBy;
/**
*
* Updates node with new automatic attributes.
*
* @author Adrian Cole
*/
@ImplementedBy(UpdateAutomaticAttributesOnNodeImpl.class)
public interface UpdateAutomaticAttributesOnNode {
public void execute(String nodeName);
}

View File

@ -0,0 +1,99 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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 org.jclouds.chef.strategy.internal;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Predicates.and;
import static com.google.common.base.Predicates.notNull;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.transform;
import static org.jclouds.ohai.Util.OhaiUtils.fromOhaiTime;
import java.util.Calendar;
import java.util.Date;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.chef.domain.Node;
import org.jclouds.chef.reference.ChefConstants;
import org.jclouds.chef.strategy.CleanupStaleNodesAndClients;
import org.jclouds.domain.JsonBall;
import org.jclouds.logging.Logger;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
/**
*
* Cleans up nodes and clients who have been hanging around too long.
*
* @author Adrian Cole
*/
@Singleton
public class CleanupStaleNodesAndClientsImpl implements CleanupStaleNodesAndClients {
@Resource
@Named(ChefConstants.CHEF_LOGGER)
protected Logger logger = Logger.NULL;
private final GetNodesImpl getAllNodes;
private final DeleteAllClientsAndNodesInListImpl deleter;
@Inject
public CleanupStaleNodesAndClientsImpl(DeleteAllClientsAndNodesInListImpl deleter, GetNodesImpl getAllNodes) {
this.getAllNodes = checkNotNull(getAllNodes, "getAllNodes");
this.deleter = checkNotNull(deleter, "deleter");
}
@Override
public void execute(final String prefix, int secondsStale) {
final Calendar expired = Calendar.getInstance();
expired.setTime(new Date());
expired.add(Calendar.SECOND, -secondsStale);
Iterable<Node> staleNodes = filter(getAllNodes.execute(new Predicate<String>() {
@Override
public boolean apply(String input) {
return input.startsWith(prefix);
}
}), and(notNull(), new Predicate<Node>() {
@Override
public boolean apply(Node input) {
JsonBall dateLong = input.getAutomatic().get("ohai_time");
if (dateLong == null)
return true;
Calendar nodeUpdate = Calendar.getInstance();
nodeUpdate.setTime(fromOhaiTime(dateLong));
return expired.after(nodeUpdate);
}
}));
deleter.execute(transform(staleNodes, new Function<Node, String>() {
@Override
public String apply(Node from) {
return from.getName();
}
}));
}
}

View File

@ -16,7 +16,7 @@
* limitations under the License. * limitations under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.ohai; package org.jclouds.chef.strategy.internal;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
@ -29,6 +29,8 @@ import javax.inject.Singleton;
import org.jclouds.chef.ChefClient; import org.jclouds.chef.ChefClient;
import org.jclouds.chef.domain.Node; import org.jclouds.chef.domain.Node;
import org.jclouds.chef.reference.ChefConstants;
import org.jclouds.chef.strategy.CreateNodeAndPopulateAutomaticAttributes;
import org.jclouds.domain.JsonBall; import org.jclouds.domain.JsonBall;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
@ -41,26 +43,32 @@ import com.google.common.base.Supplier;
* @author Adrian Cole * @author Adrian Cole
*/ */
@Singleton @Singleton
public class CreateNode { public class CreateNodeAndPopulateAutomaticAttributesImpl implements CreateNodeAndPopulateAutomaticAttributes {
@Resource @Resource
@Named(ChefConstants.CHEF_LOGGER)
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
private final ChefClient chef; private final ChefClient chef;
private final Supplier<Map<String, JsonBall>> automaticSupplier; private final Supplier<Map<String, JsonBall>> automaticSupplier;
@Inject @Inject
public CreateNode(ChefClient chef, @Named("automatic") Supplier<Map<String, JsonBall>> automaticSupplier) { public CreateNodeAndPopulateAutomaticAttributesImpl(ChefClient chef,
@Named("automatic") Supplier<Map<String, JsonBall>> automaticSupplier) {
this.chef = checkNotNull(chef, "chef"); this.chef = checkNotNull(chef, "chef");
this.automaticSupplier = checkNotNull(automaticSupplier, "automaticSupplier"); this.automaticSupplier = checkNotNull(automaticSupplier, "automaticSupplier");
} }
public Node createNode(String nodeName, Iterable<String> runList) { @Override
logger.info("creating node %s", nodeName); public void execute(Node node) {
Node node = new Node(nodeName, runList); logger.trace("creating node %s", node.getName());
node.getAutomatic().putAll(automaticSupplier.get()); node.getAutomatic().putAll(automaticSupplier.get());
node = chef.createNode(node); chef.createNode(node);
logger.debug("done creating node %s", nodeName); logger.debug("created node %s", node.getName());
return node; }
@Override
public void execute(String nodeName, Iterable<String> runList) {
execute(new Node(nodeName, runList));
} }
} }

View File

@ -0,0 +1,81 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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 org.jclouds.chef.strategy.internal;
import static com.google.common.collect.Maps.newHashMap;
import static org.jclouds.concurrent.ConcurrentUtils.awaitCompletion;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import javax.annotation.Resource;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.Constants;
import org.jclouds.chef.ChefAsyncClient;
import org.jclouds.chef.ChefClient;
import org.jclouds.chef.reference.ChefConstants;
import org.jclouds.chef.strategy.DeleteAllClientsAndNodesInList;
import org.jclouds.logging.Logger;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.inject.Inject;
/**
*
*
* @author Adrian Cole
*/
@Singleton
public class DeleteAllClientsAndNodesInListImpl implements DeleteAllClientsAndNodesInList {
protected final ChefClient chefClient;
protected final ChefAsyncClient chefAsyncClient;
protected final ExecutorService userExecutor;
@Resource
@Named(ChefConstants.CHEF_LOGGER)
protected Logger logger = Logger.NULL;
@Inject(optional = true)
@Named(Constants.PROPERTY_REQUEST_TIMEOUT)
protected Long maxTime;
@Inject
DeleteAllClientsAndNodesInListImpl(@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor,
ChefClient getAllNode, ChefAsyncClient ablobstore) {
this.userExecutor = userExecutor;
this.chefAsyncClient = ablobstore;
this.chefClient = getAllNode;
}
@Override
public void execute(Iterable<String> names) {
Map<String, Exception> exceptions = newHashMap();
Map<String, ListenableFuture<?>> responses = newHashMap();
for (String name : names) {
responses.put(name, chefAsyncClient.deleteClient(name));
responses.put(name, chefAsyncClient.deleteNode(name));
}
exceptions = awaitCompletion(responses, userExecutor, maxTime, logger, String.format(
"getting deleting clients and nodes: %s", names));
if (exceptions.size() > 0)
throw new RuntimeException(String.format("errors deleting clients and nodes: %s: %s", names, exceptions));
}
}

View File

@ -16,7 +16,7 @@
* limitations under the License. * limitations under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.chef.strategy; package org.jclouds.chef.strategy.internal;
import static com.google.common.base.Throwables.propagate; import static com.google.common.base.Throwables.propagate;
import static com.google.common.collect.Iterables.filter; import static com.google.common.collect.Iterables.filter;
@ -38,6 +38,8 @@ import org.jclouds.Constants;
import org.jclouds.chef.ChefAsyncClient; import org.jclouds.chef.ChefAsyncClient;
import org.jclouds.chef.ChefClient; import org.jclouds.chef.ChefClient;
import org.jclouds.chef.domain.Node; import org.jclouds.chef.domain.Node;
import org.jclouds.chef.reference.ChefConstants;
import org.jclouds.chef.strategy.GetNodes;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
@ -50,12 +52,13 @@ import com.google.inject.Inject;
* @author Adrian Cole * @author Adrian Cole
*/ */
@Singleton @Singleton
public class GetAllNodesInList { public class GetNodesImpl implements GetNodes {
protected final ChefClient chefClient; protected final ChefClient chefClient;
protected final ChefAsyncClient chefAsyncClient; protected final ChefAsyncClient chefAsyncClient;
protected final ExecutorService userExecutor; protected final ExecutorService userExecutor;
@Resource @Resource
@Named(ChefConstants.CHEF_LOGGER)
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
@Inject(optional = true) @Inject(optional = true)
@ -63,21 +66,24 @@ public class GetAllNodesInList {
protected Long maxTime; protected Long maxTime;
@Inject @Inject
GetAllNodesInList(@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor, ChefClient getAllNode, GetNodesImpl(@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor, ChefClient getAllNode,
ChefAsyncClient ablobstore) { ChefAsyncClient ablobstore) {
this.userExecutor = userExecutor; this.userExecutor = userExecutor;
this.chefAsyncClient = ablobstore; this.chefAsyncClient = ablobstore;
this.chefClient = getAllNode; this.chefClient = getAllNode;
} }
@Override
public Set<Node> execute() { public Set<Node> execute() {
return execute(chefClient.listNodes()); return execute(chefClient.listNodes());
} }
@Override
public Set<Node> execute(Predicate<String> nodeNameSelector) { public Set<Node> execute(Predicate<String> nodeNameSelector) {
return execute(filter(chefClient.listNodes(), nodeNameSelector)); return execute(filter(chefClient.listNodes(), nodeNameSelector));
} }
@Override
public Set<Node> execute(Iterable<String> toGet) { public Set<Node> execute(Iterable<String> toGet) {
Map<String, Exception> exceptions = newHashMap(); Map<String, Exception> exceptions = newHashMap();
final Set<Node> nodes = newHashSet(); final Set<Node> nodes = newHashSet();

View File

@ -16,7 +16,7 @@
* limitations under the License. * limitations under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.ohai; package org.jclouds.chef.strategy.internal;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
@ -29,6 +29,8 @@ import javax.inject.Singleton;
import org.jclouds.chef.ChefClient; import org.jclouds.chef.ChefClient;
import org.jclouds.chef.domain.Node; import org.jclouds.chef.domain.Node;
import org.jclouds.chef.reference.ChefConstants;
import org.jclouds.chef.strategy.UpdateAutomaticAttributesOnNode;
import org.jclouds.domain.JsonBall; import org.jclouds.domain.JsonBall;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
@ -41,25 +43,28 @@ import com.google.common.base.Supplier;
* @author Adrian Cole * @author Adrian Cole
*/ */
@Singleton @Singleton
public class UpdateNode { public class UpdateAutomaticAttributesOnNodeImpl implements UpdateAutomaticAttributesOnNode {
@Resource @Resource
@Named(ChefConstants.CHEF_LOGGER)
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
private final ChefClient chef; private final ChefClient chef;
private final Supplier<Map<String, JsonBall>> automaticSupplier; private final Supplier<Map<String, JsonBall>> automaticSupplier;
@Inject @Inject
public UpdateNode(ChefClient chef, @Named("automatic") Supplier<Map<String, JsonBall>> automaticSupplier) { public UpdateAutomaticAttributesOnNodeImpl(ChefClient chef,
@Named("automatic") Supplier<Map<String, JsonBall>> automaticSupplier) {
this.chef = checkNotNull(chef, "chef"); this.chef = checkNotNull(chef, "chef");
this.automaticSupplier = checkNotNull(automaticSupplier, "automaticSupplier"); this.automaticSupplier = checkNotNull(automaticSupplier, "automaticSupplier");
} }
public void updateNode(String nodeName) { @Override
logger.info("updating node %s", nodeName); public void execute(String nodeName) {
logger.trace("updating node %s", nodeName);
Node node = chef.getNode(nodeName); Node node = chef.getNode(nodeName);
node.getAutomatic().putAll(automaticSupplier.get()); node.getAutomatic().putAll(automaticSupplier.get());
chef.updateNode(node); chef.updateNode(node);
logger.debug("done updating node %s", nodeName); logger.debug("updated node %s", nodeName);
} }
} }

View File

@ -0,0 +1,45 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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 org.jclouds.ohai.Util;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Date;
import org.jclouds.domain.JsonBall;
/**
*
*
* @author Adrian Cole
*/
public class OhaiUtils {
public static Date fromOhaiTime(JsonBall ohaiDate) {
return new Date(Long.parseLong(checkNotNull(ohaiDate, "ohaiDate").toString().replaceAll("\\.[0-9]*$", "")));
}
public static JsonBall toOhaiTime(long nanos) {
String now = nanos + "";
StringBuilder nowBuilder = new StringBuilder(now).insert(now.length() - 6, '.');
while (nowBuilder.lastIndexOf("0") != -1 && nowBuilder.lastIndexOf("0") == nowBuilder.length() - 1)
nowBuilder.deleteCharAt(nowBuilder.length() - 1);
return new JsonBall(nowBuilder.toString());
}
}

View File

@ -18,11 +18,23 @@
*/ */
package org.jclouds.ohai.config; package org.jclouds.ohai.config;
import java.util.Properties;
import javax.inject.Named;
import com.google.inject.Provides;
/** /**
* Wires the components needed to parse ohai data without violating the GAE JVM * Wires the components needed to parse ohai data from a JVM
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public class WhiteListCompliantOhaiModule extends BaseOhaiModule { public abstract class BaseOhaiJVMModule extends BaseOhaiModule {
@Named("systemProperties")
@Provides
protected Properties systemProperties() {
return System.getProperties();
}
} }

View File

@ -18,31 +18,29 @@
*/ */
package org.jclouds.ohai.config; package org.jclouds.ohai.config;
import static org.jclouds.util.Utils.composeMapSupplier;
import java.util.Map; import java.util.Map;
import java.util.Properties;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.domain.JsonBall; import org.jclouds.domain.JsonBall;
import org.jclouds.ohai.WhiteListCompliantJVM;
import org.jclouds.ohai.functions.ByteArrayToMacAddress; import org.jclouds.ohai.functions.ByteArrayToMacAddress;
import org.jclouds.util.Utils;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableList;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import com.google.inject.Injector; import com.google.inject.Injector;
import com.google.inject.Provides; import com.google.inject.Provides;
import com.google.inject.TypeLiteral; import com.google.inject.TypeLiteral;
/** /**
* Wires the components needed to parse ohai data from a JVM * Wires the components needed to parse ohai data
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public class BaseOhaiModule extends AbstractModule { public abstract class BaseOhaiModule extends AbstractModule {
@Override @Override
protected void configure() { protected void configure() {
@ -57,25 +55,17 @@ public class BaseOhaiModule extends AbstractModule {
return System.nanoTime(); return System.nanoTime();
} }
@Named("systemProperties")
@Provides
protected Properties systemProperties() {
return System.getProperties();
}
@Named("automatic") @Named("automatic")
@Provides @Provides
@Singleton @Singleton
Supplier<Map<String, JsonBall>> automaticSupplier( Supplier<Map<String, JsonBall>> automaticSupplier(
@Named("automatic") Iterable<Supplier<Map<String, JsonBall>>> suppliers) { @Named("automatic") Iterable<Supplier<Map<String, JsonBall>>> suppliers) {
return Utils.composeMapSupplier(suppliers); return composeMapSupplier(suppliers);
} }
@Named("automatic") @Named("automatic")
@Singleton @Singleton
@Provides @Provides
Iterable<Supplier<Map<String, JsonBall>>> suppliers(Injector injector) { protected abstract Iterable<Supplier<Map<String, JsonBall>>> suppliers(Injector injector);
return ImmutableList.<Supplier<Map<String, JsonBall>>> of(injector.getInstance(WhiteListCompliantJVM.class));
}
} }

View File

@ -0,0 +1,16 @@
package org.jclouds.ohai.config;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
*
* @author Adrian Cole
*/
@Retention(RUNTIME)
@Target(TYPE)
public @interface ConfiguresOhai {
}

View File

@ -25,8 +25,8 @@ import java.util.Map;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.domain.JsonBall; import org.jclouds.domain.JsonBall;
import org.jclouds.ohai.JMX; import org.jclouds.ohai.plugins.JMX;
import org.jclouds.ohai.WhiteListCompliantJVM; import org.jclouds.ohai.plugins.WhiteListCompliantJVM;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
@ -38,7 +38,8 @@ import com.google.inject.Provides;
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public class OhaiModule extends BaseOhaiModule { @ConfiguresOhai
public class JMXOhaiJVMModule extends BaseOhaiJVMModule {
@Provides @Provides
@Singleton @Singleton
@ -47,7 +48,7 @@ public class OhaiModule extends BaseOhaiModule {
} }
@Override @Override
Iterable<Supplier<Map<String, JsonBall>>> suppliers(Injector injector) { protected Iterable<Supplier<Map<String, JsonBall>>> suppliers(Injector injector) {
return ImmutableList.<Supplier<Map<String, JsonBall>>> of(injector.getInstance(WhiteListCompliantJVM.class), return ImmutableList.<Supplier<Map<String, JsonBall>>> of(injector.getInstance(WhiteListCompliantJVM.class),
injector.getInstance(JMX.class)); injector.getInstance(JMX.class));
} }

View File

@ -0,0 +1,42 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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 org.jclouds.ohai.config;
import java.util.Map;
import org.jclouds.domain.JsonBall;
import org.jclouds.ohai.plugins.WhiteListCompliantJVM;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableList;
import com.google.inject.Injector;
/**
* Wires the components needed to parse ohai data without violating the GAE JVM
*
* @author Adrian Cole
*/
@ConfiguresOhai
public class WhiteListCompliantOhaiJVMModule extends BaseOhaiJVMModule {
@Override
protected Iterable<Supplier<Map<String, JsonBall>>> suppliers(Injector injector) {
return ImmutableList.<Supplier<Map<String, JsonBall>>> of(injector.getInstance(WhiteListCompliantJVM.class));
}
}

View File

@ -16,7 +16,7 @@
* limitations under the License. * limitations under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.ohai; package org.jclouds.ohai.plugins;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;

View File

@ -16,9 +16,11 @@
* limitations under the License. * limitations under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.ohai; package org.jclouds.ohai.plugins;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.inject.internal.Maps.newLinkedHashMap;
import static org.jclouds.ohai.Util.OhaiUtils.toOhaiTime;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
@ -34,7 +36,6 @@ import org.jclouds.json.Json;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.inject.internal.Maps;
/** /**
* *
@ -63,14 +64,10 @@ public class WhiteListCompliantJVM implements Supplier<Map<String, JsonBall>> {
} }
public Map<String, JsonBall> get() { public Map<String, JsonBall> get() {
Map<String, JsonBall> returnVal = Maps.newLinkedHashMap(); Map<String, JsonBall> returnVal = newLinkedHashMap();
Properties systemProperties = systemPropertiesProvider.get(); Properties systemProperties = systemPropertiesProvider.get();
String now = nanoTimeProvider.get() + "";
StringBuilder nowBuilder = new StringBuilder(now).insert(now.length() - 6, '.'); returnVal.put("ohai_time", toOhaiTime(nanoTimeProvider.get()));
while (nowBuilder.lastIndexOf("0") != -1 && nowBuilder.lastIndexOf("0") == nowBuilder.length() - 1)
nowBuilder.deleteCharAt(nowBuilder.length() - 1);
now = nowBuilder.toString();
returnVal.put("ohai_time", new JsonBall(now));
returnVal.put("java", new JsonBall(json.toJson(systemProperties))); returnVal.put("java", new JsonBall(json.toJson(systemProperties)));

View File

@ -44,7 +44,6 @@ import org.jclouds.chef.domain.UploadSandbox;
import org.jclouds.io.Payloads; import org.jclouds.io.Payloads;
import org.jclouds.io.payloads.FilePayload; import org.jclouds.io.payloads.FilePayload;
import org.jclouds.logging.log4j.config.Log4JLoggingModule; import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.rest.RestContext;
import org.jclouds.rest.RestContextFactory; import org.jclouds.rest.RestContextFactory;
import org.testng.annotations.AfterClass; import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeClass;
@ -65,9 +64,9 @@ import com.google.inject.Module;
@Test(groups = "live", testName = "chef.ChefClientLiveTest") @Test(groups = "live", testName = "chef.ChefClientLiveTest")
public class ChefClientLiveTest { public class ChefClientLiveTest {
private RestContext<ChefClient, ChefAsyncClient> validatorConnection; private ChefContext validatorConnection;
private RestContext<ChefClient, ChefAsyncClient> clientConnection; private ChefContext clientConnection;
private RestContext<ChefClient, ChefAsyncClient> adminConnection; private ChefContext adminConnection;
private String clientKey; private String clientKey;
private String endpoint; private String endpoint;
@ -95,11 +94,11 @@ public class ChefClientLiveTest {
adminConnection = createConnection(user, Files.toString(new File(keyfile), Charsets.UTF_8)); adminConnection = createConnection(user, Files.toString(new File(keyfile), Charsets.UTF_8));
} }
private RestContext<ChefClient, ChefAsyncClient> createConnection(String identity, String key) throws IOException { private ChefContext createConnection(String identity, String key) throws IOException {
Properties props = new Properties(); Properties props = new Properties();
props.setProperty("chef.endpoint", endpoint); props.setProperty("chef.endpoint", endpoint);
return new RestContextFactory().createContext("chef", identity, key, ImmutableSet return (ChefContext) new RestContextFactory().<ChefClient, ChefAsyncClient> createContext("chef", identity, key,
.<Module> of(new Log4JLoggingModule()), props); ImmutableSet.<Module> of(new Log4JLoggingModule()), props);
} }
public void testCreateNewCookbook() throws Exception { public void testCreateNewCookbook() throws Exception {
@ -228,7 +227,8 @@ public class ChefClientLiveTest {
@Test(dependsOnMethods = "testCreateRole") @Test(dependsOnMethods = "testCreateRole")
public void testCreateNode() throws Exception { public void testCreateNode() throws Exception {
adminConnection.getApi().deleteNode(PREFIX); adminConnection.getApi().deleteNode(PREFIX);
node = clientConnection.getApi().createNode(new Node(PREFIX, Collections.singleton("role[" + PREFIX + "]"))); clientConnection.getApi().createNode(new Node(PREFIX, Collections.singleton("role[" + PREFIX + "]")));
node = adminConnection.getApi().getNode(PREFIX);
// TODO check recipes // TODO check recipes
assertNotNull(node); assertNotNull(node);
Set<String> nodes = adminConnection.getApi().listNodes(); Set<String> nodes = adminConnection.getApi().listNodes();

View File

@ -0,0 +1,85 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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.chef.strategy.internal;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.File;
import java.io.IOException;
import java.util.Properties;
import java.util.Set;
import org.jclouds.chef.ChefAsyncClient;
import org.jclouds.chef.ChefClient;
import org.jclouds.lifecycle.Closer;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.rest.RestContextFactory;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import com.google.common.base.Charsets;
import com.google.common.collect.Sets;
import com.google.common.io.Files;
import com.google.inject.Injector;
import com.google.inject.Module;
/**
* Tests behavior of {@code ChefService} strategies
*
* @author Adrian Cole
*/
@Test(groups = "live", testName = "chef.BaseChefStrategyLiveTest")
public abstract class BaseChefStrategyLiveTest {
protected Injector injector;
protected String prefix = System.getProperty("user.name") + getClass().getSimpleName();
@BeforeTest(groups = { "live" })
public void setupClient() throws IOException {
String endpoint = checkNotNull(System.getProperty("jclouds.test.endpoint"), "jclouds.test.endpoint");
String user = checkNotNull(System.getProperty("jclouds.test.identity"), "jclouds.test.identity");
String keyfile = System.getProperty("jclouds.test.credential");
if (keyfile == null || keyfile.equals(""))
keyfile = System.getProperty("user.home") + "/.chef/" + user + ".pem";
Properties props = new Properties();
props.setProperty("chef.endpoint", endpoint);
Set<Module> modules = Sets.newHashSet();
modules.add(new Log4JLoggingModule());
addTestModulesTo(modules);
injector = new RestContextFactory().<ChefClient, ChefAsyncClient> createContextBuilder("chef", user,
Files.toString(new File(keyfile), Charsets.UTF_8), modules, props).buildInjector();
}
protected void addTestModulesTo(Set<Module> modules) {
}
@AfterTest(groups = { "live" })
public void teardownClient() throws IOException {
if (injector != null)
injector.getInstance(Closer.class).close();
}
}

View File

@ -0,0 +1,67 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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.chef.strategy.internal;
import org.jclouds.chef.ChefClient;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
/**
* Tests behavior of {@code CleanupStaleNodesAndClientsImpl} strategies
*
* @author Adrian Cole
*/
@Test(groups = "live", testName = "chef.CleanupStaleNodesAndClientsImplLiveTest")
public class CleanupStaleNodesAndClientsImplTest extends BaseChefStrategyLiveTest {
private CreateNodeAndPopulateAutomaticAttributesImpl creater;
private CleanupStaleNodesAndClientsImpl strategy;
private ChefClient chef;
@BeforeTest(groups = "live", dependsOnMethods = "setupClient")
void setupStrategy() {
this.creater = injector.getInstance(CreateNodeAndPopulateAutomaticAttributesImpl.class);
this.strategy = injector.getInstance(CleanupStaleNodesAndClientsImpl.class);
this.chef = injector.getInstance(ChefClient.class);
}
@Test
public void testExecute() throws InterruptedException {
try {
creater.execute(prefix, ImmutableSet.<String> of());
// http://tickets.corp.opscode.com/browse/PL-522
// assert chef.nodeExists(prefix);
assert chef.getNode(prefix) != null;
strategy.execute(prefix, 10);
assert chef.getNode(prefix) != null;
Thread.sleep(1000);
strategy.execute(prefix, 1);
assert chef.getNode(prefix) == null;
} finally {
chef.deleteNode(prefix);
}
}
}

View File

@ -0,0 +1,93 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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.chef.strategy.internal;
import static org.testng.Assert.assertEquals;
import java.util.Map;
import java.util.Set;
import org.jclouds.chef.ChefClient;
import org.jclouds.chef.domain.Node;
import org.jclouds.domain.JsonBall;
import org.jclouds.ohai.config.BaseOhaiModule;
import org.jclouds.ohai.config.ConfiguresOhai;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Injector;
import com.google.inject.Module;
/**
* Tests behavior of {@code CreateNodeAndPopulateAutomaticAttributesImpl}
* strategies
*
* @author Adrian Cole
*/
@Test(groups = "live", testName = "chef.CreateNodeAndPopulateAutomaticAttributesImplLiveTest")
public class CreateNodeAndPopulateAutomaticAttributesImplLiveTest extends BaseChefStrategyLiveTest {
private CreateNodeAndPopulateAutomaticAttributesImpl strategy;
private ChefClient chef;
@ConfiguresOhai
static class TestOhaiModule extends BaseOhaiModule {
@Override
protected Iterable<Supplier<Map<String, JsonBall>>> suppliers(Injector injector) {
Supplier<Map<String, JsonBall>> supplier = Suppliers.<Map<String, JsonBall>> ofInstance(ImmutableMap
.<String, JsonBall> of("foo", new JsonBall("bar")));
return ImmutableList.<Supplier<Map<String, JsonBall>>> of(supplier);
}
}
protected void addTestModulesTo(Set<Module> modules) {
modules.add(new TestOhaiModule());
}
@BeforeTest(groups = "live", dependsOnMethods = "setupClient")
void setupStrategy() {
this.strategy = injector.getInstance(CreateNodeAndPopulateAutomaticAttributesImpl.class);
this.chef = injector.getInstance(ChefClient.class);
}
@Test
public void testExecute() {
Set<String> runList = ImmutableSet.of("role[" + prefix + "]");
try {
strategy.execute(prefix, runList);
Node node = chef.getNode(prefix);
assertEquals(node.getName(), prefix);
assertEquals(node.getRunList(), runList);
assertEquals(node.getAutomatic().get("foo").toString(), "\"bar\"");
} finally {
injector.getInstance(ChefClient.class).deleteNode(prefix);
}
}
}

View File

@ -21,9 +21,8 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.ohai; package org.jclouds.chef.strategy.internal;
import static org.easymock.EasyMock.expect;
import static org.easymock.classextension.EasyMock.createMock; import static org.easymock.classextension.EasyMock.createMock;
import static org.easymock.classextension.EasyMock.replay; import static org.easymock.classextension.EasyMock.replay;
import static org.easymock.classextension.EasyMock.verify; import static org.easymock.classextension.EasyMock.verify;
@ -41,12 +40,12 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
/** /**
* Tests behavior of {@code CreateNode} * Tests behavior of {@code CreateNodeAndPopulateAutomaticAttributesImpl}
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "unit", testName = "ohai.CreateNodeTest") @Test(groups = "unit", testName = "ohai.CreateNodeAndPopulateAutomaticAttributesImplTest")
public class CreateNodeTest { public class CreateNodeAndPopulateAutomaticAttributesImplTest {
@Test @Test
public void testWithNoRunlist() { public void testWithNoRunlist() {
@ -62,13 +61,13 @@ public class CreateNodeTest {
.<String, JsonBall> of(), ImmutableMap.<String, JsonBall> of(), automatic, ImmutableSet.<String> of()); .<String, JsonBall> of(), ImmutableMap.<String, JsonBall> of(), automatic, ImmutableSet.<String> of());
node.getAutomatic().putAll(automaticSupplier.get()); node.getAutomatic().putAll(automaticSupplier.get());
expect(chef.createNode(nodeWithAutomatic)).andReturn(null); chef.createNode(nodeWithAutomatic);
replay(chef); replay(chef);
CreateNode updater = new CreateNode(chef, automaticSupplier); CreateNodeAndPopulateAutomaticAttributesImpl updater = new CreateNodeAndPopulateAutomaticAttributesImpl(chef, automaticSupplier);
updater.createNode("name", ImmutableSet.<String> of()); updater.execute("name", ImmutableSet.<String> of());
verify(chef); verify(chef);
} }

View File

@ -0,0 +1,69 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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.chef.strategy.internal;
import org.jclouds.chef.ChefClient;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
/**
* Tests behavior of {@code DeleteAllClientsAndNodesInListImpl} strategies
*
* @author Adrian Cole
*/
@Test(groups = "live", testName = "chef.DeleteAllClientsAndNodesInListImplTest")
public class DeleteAllClientsAndNodesInListImplLiveTest extends BaseChefStrategyLiveTest {
private DeleteAllClientsAndNodesInListImpl strategy;
private CreateNodeAndPopulateAutomaticAttributesImpl creater;
private ChefClient chef;
@BeforeTest(groups = "live", dependsOnMethods = "setupClient")
void setupStrategy() {
this.creater = injector.getInstance(CreateNodeAndPopulateAutomaticAttributesImpl.class);
this.strategy = injector.getInstance(DeleteAllClientsAndNodesInListImpl.class);
this.chef = injector.getInstance(ChefClient.class);
}
@Test
public void testExecute() throws InterruptedException {
try {
creater.execute(prefix, ImmutableSet.<String> of());
creater.execute(prefix + 1, ImmutableSet.<String> of());
// http://tickets.corp.opscode.com/browse/PL-522
// assert chef.nodeExists(prefix);
assert chef.getNode(prefix) != null;
assert chef.getNode(prefix + 1) != null;
strategy.execute(ImmutableSet.of(prefix, prefix + 1));
assert chef.getNode(prefix) == null;
assert chef.getNode(prefix + 1) == null;
} finally {
chef.deleteNode(prefix);
chef.deleteNode(prefix + 1);
}
}
}

View File

@ -0,0 +1,92 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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.chef.strategy.internal;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import org.jclouds.chef.ChefClient;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableSet;
/**
* Tests behavior of {@code GetNodesImpl} strategies
*
* @author Adrian Cole
*/
@Test(groups = "live", testName = "chef.GetNodesImplLiveTest")
public class GetNodesImplLiveTest extends BaseChefStrategyLiveTest {
private GetNodesImpl strategy;
private CreateNodeAndPopulateAutomaticAttributesImpl creater;
private ChefClient chef;
@BeforeTest(groups = "live", dependsOnMethods = "setupClient")
void setupStrategy() {
this.creater = injector.getInstance(CreateNodeAndPopulateAutomaticAttributesImpl.class);
this.strategy = injector.getInstance(GetNodesImpl.class);
this.chef = injector.getInstance(ChefClient.class);
}
@BeforeTest(groups = "live", dependsOnMethods = "setupStrategy")
void setupNodes() {
creater.execute(prefix, ImmutableSet.<String> of());
creater.execute(prefix + 1, ImmutableSet.<String> of());
}
@AfterTest(groups = { "live" })
@Override
public void teardownClient() throws IOException {
chef.deleteNode(prefix);
chef.deleteNode(prefix + 1);
super.teardownClient();
}
@Test
public void testExecute() {
assert strategy.execute().size() > 0;
}
@Test
public void testExecutePredicateOfString() {
assertEquals(strategy.execute(new Predicate<String>() {
@Override
public boolean apply(String input) {
return input.startsWith(prefix);
}
}).size(), 2);
}
@Test
public void testExecuteIterableOfString() {
assertEquals(strategy.execute(ImmutableSet.of(prefix, prefix + 1)).size(), 2);
}
}

View File

@ -0,0 +1,92 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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.chef.strategy.internal;
import static org.testng.Assert.assertEquals;
import java.util.Map;
import java.util.Set;
import org.jclouds.chef.ChefClient;
import org.jclouds.chef.domain.Node;
import org.jclouds.domain.JsonBall;
import org.jclouds.ohai.config.BaseOhaiModule;
import org.jclouds.ohai.config.ConfiguresOhai;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Injector;
import com.google.inject.Module;
/**
* Tests behavior of {@code UpdateAutomaticAttributesOnNodeImpl} strategies
*
* @author Adrian Cole
*/
@Test(groups = "live", testName = "chef.UpdateAutomaticAttributesOnNodeImplLiveTest")
public class UpdateAutomaticAttributesOnNodeImplLiveTest extends BaseChefStrategyLiveTest {
private UpdateAutomaticAttributesOnNodeImpl strategy;
private ChefClient chef;
@ConfiguresOhai
static class TestOhaiModule extends BaseOhaiModule {
@Override
protected Iterable<Supplier<Map<String, JsonBall>>> suppliers(Injector injector) {
Supplier<Map<String, JsonBall>> supplier = Suppliers.<Map<String, JsonBall>> ofInstance(ImmutableMap
.<String, JsonBall> of("foo", new JsonBall("bar")));
return ImmutableList.<Supplier<Map<String, JsonBall>>> of(supplier);
}
}
protected void addTestModulesTo(Set<Module> modules) {
modules.add(new TestOhaiModule());
}
@BeforeTest(groups = "live", dependsOnMethods = "setupClient")
void setupStrategy() {
this.strategy = injector.getInstance(UpdateAutomaticAttributesOnNodeImpl.class);
this.chef = injector.getInstance(ChefClient.class);
}
@Test
public void testExecute() {
Set<String> runList = ImmutableSet.of("role[" + prefix + "]");
try {
chef.createNode(new Node(prefix, runList));
strategy.execute(prefix);
Node node = chef.getNode(prefix);
assertEquals(node.getName(), prefix);
assertEquals(node.getRunList(), runList);
assertEquals(node.getAutomatic().get("foo").toString(), "\"bar\"");
} finally {
injector.getInstance(ChefClient.class).deleteNode(prefix);
}
}
}

View File

@ -21,7 +21,7 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.ohai; package org.jclouds.chef.strategy.internal;
import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.expect;
import static org.easymock.classextension.EasyMock.createMock; import static org.easymock.classextension.EasyMock.createMock;
@ -41,12 +41,12 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
/** /**
* Tests behavior of {@code UpdateNode} * Tests behavior of {@code UpdateAutomaticAttributesOnNodeImpl}
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "unit", testName = "ohai.UpdateNodeTest") @Test(groups = "unit", testName = "ohai.UpdateAutomaticAttributesOnNodeImplTest")
public class UpdateNodeTest { public class UpdateAutomaticAttributesOnNodeImplTest {
@Test @Test
public void test() { public void test() {
@ -67,9 +67,9 @@ public class UpdateNodeTest {
replay(chef); replay(chef);
UpdateNode updater = new UpdateNode(chef, automaticSupplier); UpdateAutomaticAttributesOnNodeImpl updater = new UpdateAutomaticAttributesOnNodeImpl(chef, automaticSupplier);
updater.updateNode("name"); updater.execute("name");
verify(chef); verify(chef);
} }

View File

@ -21,7 +21,7 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.ohai; package org.jclouds.ohai.plugins;
import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.expect;
import static org.easymock.classextension.EasyMock.createMock; import static org.easymock.classextension.EasyMock.createMock;
@ -34,7 +34,7 @@ import java.lang.management.RuntimeMXBean;
import org.jclouds.chef.config.ChefParserModule; import org.jclouds.chef.config.ChefParserModule;
import org.jclouds.json.Json; import org.jclouds.json.Json;
import org.jclouds.json.config.GsonModule; import org.jclouds.json.config.GsonModule;
import org.jclouds.ohai.config.OhaiModule; import org.jclouds.ohai.config.JMXOhaiJVMModule;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.inject.Guice; import com.google.inject.Guice;
@ -57,7 +57,7 @@ public class JMXTest {
replay(runtime); replay(runtime);
Injector injector = Guice.createInjector(new ChefParserModule(), new GsonModule(), new OhaiModule() { Injector injector = Guice.createInjector(new ChefParserModule(), new GsonModule(), new JMXOhaiJVMModule() {
@Override @Override
protected RuntimeMXBean provideRuntimeMXBean() { protected RuntimeMXBean provideRuntimeMXBean() {
return runtime; return runtime;

View File

@ -21,7 +21,7 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.ohai; package org.jclouds.ohai.plugins;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
@ -31,7 +31,7 @@ import java.util.Properties;
import org.jclouds.chef.config.ChefParserModule; import org.jclouds.chef.config.ChefParserModule;
import org.jclouds.json.Json; import org.jclouds.json.Json;
import org.jclouds.json.config.GsonModule; import org.jclouds.json.config.GsonModule;
import org.jclouds.ohai.config.BaseOhaiModule; import org.jclouds.ohai.config.WhiteListCompliantOhaiJVMModule;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.inject.Guice; import com.google.inject.Guice;
@ -54,18 +54,19 @@ public class WhiteListCompliantJVMTest {
sysProperties.setProperty("os.version", "10.3.0"); sysProperties.setProperty("os.version", "10.3.0");
sysProperties.setProperty("user.name", "user"); sysProperties.setProperty("user.name", "user");
Injector injector = Guice.createInjector(new ChefParserModule(), new GsonModule(), new BaseOhaiModule() { Injector injector = Guice.createInjector(new ChefParserModule(), new GsonModule(),
@Override new WhiteListCompliantOhaiJVMModule() {
protected Long nanoTime() { @Override
return 1279992919325290l; protected Long nanoTime() {
} return 1279992919325290l;
}
@Override @Override
protected Properties systemProperties() { protected Properties systemProperties() {
return sysProperties; return sysProperties;
} }
}); });
Json json = injector.getInstance(Json.class); Json json = injector.getInstance(Json.class);
WhiteListCompliantJVM WhiteListCompliantJVM = injector.getInstance(WhiteListCompliantJVM.class); WhiteListCompliantJVM WhiteListCompliantJVM = injector.getInstance(WhiteListCompliantJVM.class);

View File

@ -0,0 +1,54 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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.ohai.util;
import static org.testng.Assert.assertEquals;
import java.util.Date;
import org.jclouds.domain.JsonBall;
import org.jclouds.ohai.Util.OhaiUtils;
import org.testng.annotations.Test;
/**
* Tests behavior of {@code OhaiUtils}
*
* @author Adrian Cole
*/
@Test(groups = "unit", sequential = true, testName = "ohai.OhaiUtilsTest")
public class OhaiUtilsTest {
public static long nanotime = 1280251180727244000l;
public static String nanotimeString = "1280251180727.244";
public static Date now = new Date(1280251180727l);
public void testToOhaiTime() {
assertEquals(OhaiUtils.toOhaiTime(nanotime).toString(), nanotimeString);
}
public void testFromOhaiTime() {
assertEquals(OhaiUtils.fromOhaiTime(new JsonBall(nanotimeString)), now);
}
}