/* * 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.apache.brooklyn.rest.resources; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; import org.apache.brooklyn.api.entity.ImplementedBy; import org.apache.brooklyn.api.mgmt.ManagementContext; import org.apache.brooklyn.core.BrooklynVersion; import org.apache.brooklyn.core.internal.BrooklynProperties; import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal; import org.apache.brooklyn.entity.software.base.EmptySoftwareProcess; import org.apache.brooklyn.entity.software.base.EmptySoftwareProcessDriver; import org.apache.brooklyn.entity.software.base.EmptySoftwareProcessImpl; import org.apache.brooklyn.rest.domain.HighAvailabilitySummary; import org.apache.brooklyn.rest.domain.VersionSummary; import org.apache.brooklyn.rest.testing.BrooklynRestResourceTest; import org.apache.brooklyn.test.Asserts; import org.apache.brooklyn.util.exceptions.Exceptions; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.annotations.Test; import com.google.common.collect.ImmutableSet; import com.sun.jersey.api.client.UniformInterfaceException; @Test(singleThreaded = true) public class ServerResourceTest extends BrooklynRestResourceTest { private static final Logger log = LoggerFactory.getLogger(ServerResourceTest.class); @Test public void testGetVersion() throws Exception { VersionSummary version = client().resource("/v1/server/version").get(VersionSummary.class); assertEquals(version.getVersion(), BrooklynVersion.get()); } @Test public void testGetStatus() throws Exception { String status = client().resource("/v1/server/status").get(String.class); assertEquals(status, "MASTER"); } @Test public void testGetHighAvailability() throws Exception { // Note by default management context from super is started without HA enabled. // Therefore can only assert a minimal amount of stuff. HighAvailabilitySummary summary = client().resource("/v1/server/highAvailability").get(HighAvailabilitySummary.class); log.info("HA summary is: "+summary); String ownNodeId = getManagementContext().getManagementNodeId(); assertEquals(summary.getOwnId(), ownNodeId); assertEquals(summary.getMasterId(), ownNodeId); assertEquals(summary.getNodes().keySet(), ImmutableSet.of(ownNodeId)); assertEquals(summary.getNodes().get(ownNodeId).getNodeId(), ownNodeId); assertEquals(summary.getNodes().get(ownNodeId).getStatus(), "MASTER"); assertNotNull(summary.getNodes().get(ownNodeId).getLocalTimestamp()); // remote will also be non-null if there is no remote backend (local is re-used) assertNotNull(summary.getNodes().get(ownNodeId).getRemoteTimestamp()); assertEquals(summary.getNodes().get(ownNodeId).getLocalTimestamp(), summary.getNodes().get(ownNodeId).getRemoteTimestamp()); } @SuppressWarnings("serial") @Test public void testReloadsBrooklynProperties() throws Exception { final AtomicInteger reloadCount = new AtomicInteger(); getManagementContext().addPropertiesReloadListener(new ManagementContext.PropertiesReloadListener() { @Override public void reloaded() { reloadCount.incrementAndGet(); }}); client().resource("/v1/server/properties/reload").post(); assertEquals(reloadCount.get(), 1); } @Test void testGetConfig() throws Exception { ((ManagementContextInternal)getManagementContext()).getBrooklynProperties().put("foo.bar.baz", "quux"); try { assertEquals(client().resource("/v1/server/config/foo.bar.baz").get(String.class), "quux"); } finally { ((ManagementContextInternal)getManagementContext()).getBrooklynProperties().remove("foo.bar.baz"); } } @Test void testGetMissingConfigThrowsException() throws Exception { final String key = "foo.bar.baz"; BrooklynProperties properties = ((ManagementContextInternal)getManagementContext()).getBrooklynProperties(); Object existingValue = null; boolean keyAlreadyPresent = false; String response = null; if (properties.containsKey(key)) { existingValue = properties.remove(key); keyAlreadyPresent = true; } try { response = client().resource("/v1/server/config/" + key).get(String.class); Asserts.fail("Expected call to /v1/server/config/" + key + " to fail with status 404, instead server returned " + response); } catch (UniformInterfaceException e) { assertEquals(e.getResponse().getStatus(), 204); } finally { if (keyAlreadyPresent) { properties.put(key, existingValue); } } } // Alternatively could reuse a blocking location, see org.apache.brooklyn.entity.software.base.SoftwareProcessEntityTest.ReleaseLatchLocation @ImplementedBy(StopLatchEntityImpl.class) public interface StopLatchEntity extends EmptySoftwareProcess { public void unblock(); public boolean isBlocked(); } public static class StopLatchEntityImpl extends EmptySoftwareProcessImpl implements StopLatchEntity { private CountDownLatch lock = new CountDownLatch(1); private volatile boolean isBlocked; @Override public void unblock() { lock.countDown(); } @Override protected void postStop() { super.preStop(); try { isBlocked = true; lock.await(); isBlocked = false; } catch (InterruptedException e) { throw Exceptions.propagate(e); } } @Override public Class<?> getDriverInterface() { return EmptySoftwareProcessDriver.class; } @Override public boolean isBlocked() { return isBlocked; } } }