SLIDER-711 live/containers resource
Project: http://git-wip-us.apache.org/repos/asf/incubator-slider/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-slider/commit/9dffb405 Tree: http://git-wip-us.apache.org/repos/asf/incubator-slider/tree/9dffb405 Diff: http://git-wip-us.apache.org/repos/asf/incubator-slider/diff/9dffb405 Branch: refs/heads/develop Commit: 9dffb40590a96bac96fd411564fe09f9ae77e134 Parents: a5d1f5e Author: Steve Loughran <[email protected]> Authored: Thu Dec 18 13:48:15 2014 +0000 Committer: Steve Loughran <[email protected]> Committed: Thu Dec 18 13:48:15 2014 +0000 ---------------------------------------------------------------------- .../server/appmaster/web/WebAppApiImpl.java | 4 +- .../rest/application/ApplicationResource.java | 19 +++- .../application/resources/ContentCache.java | 9 ++ .../appstate/StubSliderClusterProtocol.groovy | 108 +++++++++++++++++++ .../TestMockAppStateAppRestIntegration.groovy | 54 ++++++++-- 5 files changed, 178 insertions(+), 16 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/9dffb405/slider-core/src/main/java/org/apache/slider/server/appmaster/web/WebAppApiImpl.java ---------------------------------------------------------------------- diff --git a/slider-core/src/main/java/org/apache/slider/server/appmaster/web/WebAppApiImpl.java b/slider-core/src/main/java/org/apache/slider/server/appmaster/web/WebAppApiImpl.java index 36d4a8f..d5532ea 100644 --- a/slider-core/src/main/java/org/apache/slider/server/appmaster/web/WebAppApiImpl.java +++ b/slider-core/src/main/java/org/apache/slider/server/appmaster/web/WebAppApiImpl.java @@ -52,11 +52,11 @@ public class WebAppApiImpl implements WebAppApi { CertificateManager certificateManager, RegistryOperations registryOperations, MetricsAndMonitoring metricsAndMonitoring) { - this.registryOperations = registryOperations; checkNotNull(clusterProto); checkNotNull(appState); checkNotNull(provider); - + + this.registryOperations = registryOperations; this.clusterProto = clusterProto; this.appState = appState; this.provider = provider; http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/9dffb405/slider-core/src/main/java/org/apache/slider/server/appmaster/web/rest/application/ApplicationResource.java ---------------------------------------------------------------------- diff --git a/slider-core/src/main/java/org/apache/slider/server/appmaster/web/rest/application/ApplicationResource.java b/slider-core/src/main/java/org/apache/slider/server/appmaster/web/rest/application/ApplicationResource.java index 374e8de..e4be96f 100644 --- a/slider-core/src/main/java/org/apache/slider/server/appmaster/web/rest/application/ApplicationResource.java +++ b/slider-core/src/main/java/org/apache/slider/server/appmaster/web/rest/application/ApplicationResource.java @@ -19,11 +19,14 @@ package org.apache.slider.server.appmaster.web.rest.application; import com.google.common.collect.Lists; +import org.apache.slider.api.types.SerializedContainerInformation; import org.apache.slider.core.conf.ConfTree; +import org.apache.slider.server.appmaster.state.StateAccessForProviders; import org.apache.slider.server.appmaster.web.WebAppApi; import org.apache.slider.server.appmaster.web.rest.AbstractSliderResource; import org.apache.slider.server.appmaster.web.rest.RestPaths; import org.apache.slider.server.appmaster.web.rest.application.resources.CachedContent; +import org.apache.slider.server.appmaster.web.rest.application.resources.ContainerListRefresher; import org.apache.slider.server.appmaster.web.rest.application.resources.ContentCache; import org.apache.slider.server.appmaster.web.rest.application.resources.LiveResourcesRefresher; import org.slf4j.Logger; @@ -35,6 +38,7 @@ import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import java.util.List; +import java.util.Map; @Singleton public class ApplicationResource extends AbstractSliderResource { @@ -46,9 +50,13 @@ public class ApplicationResource extends AbstractSliderResource { public ApplicationResource(WebAppApi slider) { super(slider); + StateAccessForProviders state = slider.getAppState(); cache.put(RestPaths.LIVE_RESOURCES, new CachedContent<ConfTree>(LIFESPAN, - new LiveResourcesRefresher(slider.getAppState()))); + new LiveResourcesRefresher(state))); + cache.put(RestPaths.LIVE_CONTAINERS, + new CachedContent<Map<String, SerializedContainerInformation>>(LIFESPAN, + new ContainerListRefresher(state))); } /** @@ -91,7 +99,7 @@ public class ApplicationResource extends AbstractSliderResource { @Produces({MediaType.APPLICATION_JSON}) public Object getLiveResources() { try { - return cache.get(RestPaths.LIVE_RESOURCES).get(); + return cache.lookup(RestPaths.LIVE_RESOURCES); } catch (Exception e) { throw buildException(RestPaths.LIVE_RESOURCES, e); } @@ -99,11 +107,12 @@ public class ApplicationResource extends AbstractSliderResource { @GET @Path(RestPaths.LIVE_CONTAINERS) @Produces({MediaType.APPLICATION_JSON}) - public Object getLiveContainers() { + public Map<String, SerializedContainerInformation> getLiveContainers() { try { - return cache.get(RestPaths.LIVE_RESOURCES).get(); + return (Map<String, SerializedContainerInformation>)cache.lookup( + RestPaths.LIVE_CONTAINERS); } catch (Exception e) { - throw buildException(RestPaths.LIVE_RESOURCES, e); + throw buildException(RestPaths.LIVE_CONTAINERS, e); } } http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/9dffb405/slider-core/src/main/java/org/apache/slider/server/appmaster/web/rest/application/resources/ContentCache.java ---------------------------------------------------------------------- diff --git a/slider-core/src/main/java/org/apache/slider/server/appmaster/web/rest/application/resources/ContentCache.java b/slider-core/src/main/java/org/apache/slider/server/appmaster/web/rest/application/resources/ContentCache.java index f309570..6ee9604 100644 --- a/slider-core/src/main/java/org/apache/slider/server/appmaster/web/rest/application/resources/ContentCache.java +++ b/slider-core/src/main/java/org/apache/slider/server/appmaster/web/rest/application/resources/ContentCache.java @@ -18,6 +18,9 @@ package org.apache.slider.server.appmaster.web.rest.application.resources; +import com.google.common.base.Preconditions; +import org.apache.slider.server.appmaster.web.rest.RestPaths; + import java.util.concurrent.ConcurrentHashMap; /** @@ -31,4 +34,10 @@ public class ContentCache extends ConcurrentHashMap<String, CachedContent> { public ContentCache() { } + + public Object lookup(String key) { + CachedContent content = get(key); + Preconditions.checkNotNull(content, "no content for path " + key); + return content.get(); + } } http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/9dffb405/slider-core/src/test/groovy/org/apache/slider/server/appmaster/model/appstate/StubSliderClusterProtocol.groovy ---------------------------------------------------------------------- diff --git a/slider-core/src/test/groovy/org/apache/slider/server/appmaster/model/appstate/StubSliderClusterProtocol.groovy b/slider-core/src/test/groovy/org/apache/slider/server/appmaster/model/appstate/StubSliderClusterProtocol.groovy new file mode 100644 index 0000000..0836dcb --- /dev/null +++ b/slider-core/src/test/groovy/org/apache/slider/server/appmaster/model/appstate/StubSliderClusterProtocol.groovy @@ -0,0 +1,108 @@ +/* + * 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.slider.server.appmaster.model.appstate + +import org.apache.hadoop.ipc.ProtocolSignature +import org.apache.hadoop.yarn.exceptions.YarnException +import org.apache.slider.api.SliderClusterProtocol +import org.apache.slider.api.proto.Messages + +class StubSliderClusterProtocol implements SliderClusterProtocol { + @Override + Messages.StopClusterResponseProto stopCluster( + Messages.StopClusterRequestProto request) + throws IOException, YarnException { + throw new UnsupportedOperationException() + } + + @Override + Messages.FlexClusterResponseProto flexCluster( + Messages.FlexClusterRequestProto request) + throws IOException, YarnException { + throw new UnsupportedOperationException() + } + + @Override + Messages.GetJSONClusterStatusResponseProto getJSONClusterStatus( + Messages.GetJSONClusterStatusRequestProto request) + throws IOException, YarnException { + throw new UnsupportedOperationException() + } + + @Override + Messages.ListNodeUUIDsByRoleResponseProto listNodeUUIDsByRole( + Messages.ListNodeUUIDsByRoleRequestProto request) + throws IOException, YarnException { + throw new UnsupportedOperationException() + } + + @Override + Messages.GetNodeResponseProto getNode(Messages.GetNodeRequestProto request) + throws IOException, YarnException { + throw new UnsupportedOperationException() + } + + @Override + Messages.GetClusterNodesResponseProto getClusterNodes( + Messages.GetClusterNodesRequestProto request) + throws IOException, YarnException { + throw new UnsupportedOperationException() + } + + @Override + Messages.EchoResponseProto echo(Messages.EchoRequestProto request) + throws IOException, YarnException { + throw new UnsupportedOperationException() + } + + @Override + Messages.KillContainerResponseProto killContainer( + Messages.KillContainerRequestProto request) + throws IOException, YarnException { + throw new UnsupportedOperationException() + } + + @Override + Messages.AMSuicideResponseProto amSuicide( + Messages.AMSuicideRequestProto request) + throws IOException, YarnException { + throw new UnsupportedOperationException() + } + + @Override + Messages.GetInstanceDefinitionResponseProto getInstanceDefinition( + Messages.GetInstanceDefinitionRequestProto request) + throws IOException, YarnException { + throw new UnsupportedOperationException() + } + + @Override + long getProtocolVersion(String protocol, long clientVersion) + throws IOException { + return 0 + } + + @Override + ProtocolSignature getProtocolSignature( + String protocol, + long clientVersion, + int clientMethodsHash) throws IOException { + throw new UnsupportedOperationException() + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/9dffb405/slider-core/src/test/groovy/org/apache/slider/server/appmaster/model/appstate/TestMockAppStateAppRestIntegration.groovy ---------------------------------------------------------------------- diff --git a/slider-core/src/test/groovy/org/apache/slider/server/appmaster/model/appstate/TestMockAppStateAppRestIntegration.groovy b/slider-core/src/test/groovy/org/apache/slider/server/appmaster/model/appstate/TestMockAppStateAppRestIntegration.groovy index aefeecf..c188b9c 100644 --- a/slider-core/src/test/groovy/org/apache/slider/server/appmaster/model/appstate/TestMockAppStateAppRestIntegration.groovy +++ b/slider-core/src/test/groovy/org/apache/slider/server/appmaster/model/appstate/TestMockAppStateAppRestIntegration.groovy @@ -19,13 +19,22 @@ package org.apache.slider.server.appmaster.model.appstate import groovy.util.logging.Slf4j +import org.apache.hadoop.ipc.ProtocolSignature +import org.apache.hadoop.yarn.exceptions.YarnException +import org.apache.slider.api.SliderClusterProtocol +import org.apache.slider.api.proto.Messages import org.apache.slider.api.types.SerializedContainerInformation import org.apache.slider.core.persist.JsonSerDeser +import org.apache.slider.server.appmaster.management.MetricsAndMonitoring import org.apache.slider.server.appmaster.model.mock.BaseMockAppStateTest +import org.apache.slider.server.appmaster.model.mock.MockProviderService import org.apache.slider.server.appmaster.model.mock.MockRoles import org.apache.slider.server.appmaster.state.ProviderAppState import org.apache.slider.server.appmaster.state.RoleInstance import org.apache.slider.server.appmaster.state.StateAccessForProviders +import org.apache.slider.server.appmaster.web.WebAppApi +import org.apache.slider.server.appmaster.web.WebAppApiImpl +import org.apache.slider.server.appmaster.web.rest.application.ApplicationResource import org.apache.slider.server.appmaster.web.rest.application.resources.CachedContent import org.apache.slider.server.appmaster.web.rest.application.resources.ContainerListRefresher import org.apache.slider.server.appmaster.web.rest.application.resources.ContentCache @@ -64,18 +73,11 @@ class TestMockAppStateAppRestIntegration extends BaseMockAppStateTest implements @Test public void testContainerListRefresher() throws Throwable { - int r0 = 1 - int r1 = 2 - int r2 = 3 - role0Status.desired = r0 - role1Status.desired = r1 - role2Status.desired = r2 ContainerListRefresher clr = new ContainerListRefresher(stateAccess) def map = clr.refresh() assert map.size() == 0 - List<RoleInstance> instances = createAndStartNodes() + List<RoleInstance> instances = startNodes() map = clr.refresh() - assert instances.size() == r0 + r1 + r2 assert map.size() == instances.size() log.info("$map") JsonSerDeser<SerializedContainerInformation> serDeser = @@ -85,11 +87,45 @@ class TestMockAppStateAppRestIntegration extends BaseMockAppStateTest implements } } - public ProviderAppState getStateAccess() { + public List<RoleInstance> startNodes() { + int r0 = 1 + int r1 = 2 + int r2 = 3 + role0Status.desired = r0 + role1Status.desired = r1 + role2Status.desired = r2 + List<RoleInstance> instances = createAndStartNodes() + assert instances.size() == r0 + r1 + r2 + return instances + } + + @Test + public void testApplicationResource() throws Throwable { + def instances = startNodes() + ApplicationResource applicationResource = + new ApplicationResource(webAppApi) + def containers = applicationResource.liveContainers + assert containers.size() == instances.size() + + } + /** + * Get a state accessor for the appState field + * @return something to hand down to refreshers and resources + */ + public StateAccessForProviders getStateAccess() { StateAccessForProviders state = new ProviderAppState("name", appState) return state } + public WebAppApi getWebAppApi() { + WebAppApi api = new WebAppApiImpl(new StubSliderClusterProtocol(), + stateAccess, + new MockProviderService(), + null, null, + new MetricsAndMonitoring("metrics")) + return api + } + /** * Little class to do integer refreshing & so test refresh logic */
