/*
* Copyright 2010 Proofpoint, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.proofpoint.cloudmanagement.service.inventoryclient;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.inject.Binder;
import com.google.inject.Module;
import com.google.inject.Scopes;
import javax.annotation.Nullable;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
@Path("/inv_api/v1")
public class MockInventoryServer
{
private static final String NAME_KEY = "fqdn";
private static final String INSTANCE_ID_KEY = "serial_number";
private final Set<Map<String, String>> inventory = Sets.newHashSet();
public static class MockInventoryServerModule
implements Module
{
@Override
public void configure(Binder binder)
{
binder.bind(MockInventoryServer.class).in(Scopes.SINGLETON);
}
}
@GET
@Path("/pcmsystemname/{instanceId}")
public Map<String, String> getPcmName(@PathParam("instanceId") String instanceId)
{
Map<String, String> system = systemWithInstanceId(instanceId);
if (system == null) {
system = Maps.newHashMap();
system.put(NAME_KEY, UUID.randomUUID().toString());
system.put(INSTANCE_ID_KEY, instanceId);
inventory.add(system);
}
return ImmutableMap.of(NAME_KEY, system.get(NAME_KEY));
}
@GET
@Path("/system/{name}")
@Produces(MediaType.APPLICATION_JSON)
public Response getSystem(@PathParam("name") String name)
{
Map<String, String> system = systemWithName(name);
if (system == null) {
// Inventory returns no content if the system doesn't exist
return Response.noContent().build();
}
return Response.ok(system).build();
}
@PUT
@Path("/system/{name}")
@Consumes(MediaType.APPLICATION_JSON)
public Response patchSystem(@PathParam("name") String name, Map<String, String> patchSource)
{
Map<String, String> system = systemWithName(name);
if (system == null) {
// Inventory errors out when trying to put to a non-existent system
return Response
.serverError()
.entity(ImmutableSet.of("\"1452: Cannot add or update a child row: a foreign key constraint fails (`inventory/device_metadata`, CONSTRAINT `fk_device_metadata_device_fqdn` FOREIGN KEY (`fqdn`) REFERENCES `device` (`fqdn`) ON DELETE CASCADE ON UPDATE CASCADE)\""))
.build();
}
system.putAll(patchSource);
return Response.noContent().build();
}
private Map<String, String> systemWithName(final String name)
{
if (name == null) {
return null;
}
return systemWithWithPredicate(new Predicate<Map<String, String>>()
{
@Override
public boolean apply(@Nullable Map<String, String> input)
{
return name.equals(input.get(NAME_KEY));
}
});
}
private Map<String, String> systemWithInstanceId(final String id)
{
if (id == null) {
return null;
}
return systemWithWithPredicate(new Predicate<Map<String, String>>()
{
@Override
public boolean apply(@Nullable Map<String, String> input)
{
return id.equals(input.get(INSTANCE_ID_KEY));
}
});
}
private Map<String, String> systemWithWithPredicate(Predicate<Map<String, String>> predicate)
{
Preconditions.checkNotNull(predicate);
Set<Map<String, String>> filtered = Sets.filter(inventory, predicate);
if (filtered.size() > 1) {
throw new IllegalStateException("Too many objects matching predicate in set");
}
if (filtered.isEmpty()) {
return null;
}
return filtered.iterator().next();
}
}