Return-Path: X-Original-To: apmail-ambari-commits-archive@www.apache.org Delivered-To: apmail-ambari-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 4BBCE17E87 for ; Wed, 29 Apr 2015 17:02:13 +0000 (UTC) Received: (qmail 56555 invoked by uid 500); 29 Apr 2015 17:02:13 -0000 Delivered-To: apmail-ambari-commits-archive@ambari.apache.org Received: (qmail 56459 invoked by uid 500); 29 Apr 2015 17:02:13 -0000 Mailing-List: contact commits-help@ambari.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: ambari-dev@ambari.apache.org Delivered-To: mailing list commits@ambari.apache.org Received: (qmail 56443 invoked by uid 99); 29 Apr 2015 17:02:13 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 29 Apr 2015 17:02:13 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id E7145E09B2; Wed, 29 Apr 2015 17:02:12 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: rlevas@apache.org To: commits@ambari.apache.org Date: Wed, 29 Apr 2015 17:02:13 -0000 Message-Id: <6154033953b74ceab1869eb67d8b7688@git.apache.org> In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [2/2] ambari git commit: AMBARI-10576. Add the ability to obtain details about required Kerberos identities (rlevas) AMBARI-10576. Add the ability to obtain details about required Kerberos identities (rlevas) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/66e42cba Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/66e42cba Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/66e42cba Branch: refs/heads/trunk Commit: 66e42cbab8a714eac49b4ae84eb238d0c08accb5 Parents: 1e3afa8 Author: Robert Levas Authored: Wed Apr 29 13:01:52 2015 -0400 Committer: Robert Levas Committed: Wed Apr 29 13:02:01 2015 -0400 ---------------------------------------------------------------------- .../query/render/ClusterBlueprintRenderer.java | 2 +- .../render/HostKerberosIdentityCsvRenderer.java | 83 +++ .../api/resources/BaseResourceDefinition.java | 28 +- .../HostComponentResourceDefinition.java | 2 +- .../HostKerberosIdentityResourceDefinition.java | 56 ++ .../api/resources/HostResourceDefinition.java | 1 + .../resources/ResourceInstanceFactoryImpl.java | 4 + .../ambari/server/api/services/BaseService.java | 6 + .../server/api/services/ClusterService.java | 16 + .../services/HostKerberosIdentityService.java | 121 ++++ .../ambari/server/api/services/HostService.java | 11 + .../api/services/ResultPostProcessorImpl.java | 4 +- .../api/services/serializers/CsvSerializer.java | 224 +++++++ .../services/serializers/JsonSerializer.java | 4 +- .../apache/ambari/server/api/util/TreeNode.java | 12 +- .../ambari/server/api/util/TreeNodeImpl.java | 14 +- .../server/controller/ControllerModule.java | 2 + .../server/controller/KerberosHelper.java | 167 +++++ .../controller/ResourceProviderFactory.java | 3 + .../AbstractControllerResourceProvider.java | 2 + .../HostKerberosIdentityResourceProvider.java | 243 +++++++ .../ambari/server/controller/spi/Resource.java | 4 +- .../kerberos/KerberosIdentityDescriptor.java | 13 + .../kerberos/KerberosKeytabDescriptor.java | 21 + .../kerberos/KerberosPrincipalDescriptor.java | 58 +- .../render/ClusterBlueprintRendererTest.java | 4 +- .../api/query/render/MinimalRendererTest.java | 4 +- .../resources/BaseResourceDefinitionTest.java | 4 +- ...tKerberosIdentityResourceDefinitionTest.java | 48 ++ .../resources/HostResourceDefinitionTest.java | 3 +- .../ResourceInstanceFactoryImplTest.java | 10 + .../HostKerberosIdentityServiceTest.java | 93 +++ .../services/serializers/CsvSerializerTest.java | 258 ++++++++ .../server/controller/KerberosHelperTest.java | 631 +++++++++++++++++++ ...ostKerberosIdentityResourceProviderTest.java | 362 +++++++++++ 35 files changed, 2482 insertions(+), 36 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/66e42cba/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/ClusterBlueprintRenderer.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/ClusterBlueprintRenderer.java b/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/ClusterBlueprintRenderer.java index 5c84d4c..351f6b4 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/ClusterBlueprintRenderer.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/ClusterBlueprintRenderer.java @@ -264,7 +264,7 @@ public class ClusterBlueprintRenderer extends BaseRenderer implements Renderer { * @return true if the node represents a collection; false otherwise */ private boolean isCollection(TreeNode node) { - String isCollection = node.getProperty("isCollection"); + String isCollection = node.getStringProperty("isCollection"); return isCollection != null && isCollection.equals("true"); } http://git-wip-us.apache.org/repos/asf/ambari/blob/66e42cba/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/HostKerberosIdentityCsvRenderer.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/HostKerberosIdentityCsvRenderer.java b/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/HostKerberosIdentityCsvRenderer.java new file mode 100644 index 0000000..31e95e1 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/HostKerberosIdentityCsvRenderer.java @@ -0,0 +1,83 @@ +/* + * 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.ambari.server.api.query.render; + +import org.apache.ambari.server.api.services.Result; +import org.apache.ambari.server.api.services.serializers.CsvSerializer; +import org.apache.ambari.server.api.util.TreeNode; +import org.apache.ambari.server.controller.spi.Resource; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Renderer which updates a KerberosHostIdentity resource so it may be serialized using a CSV serializer. + *

+ * This implementation extends the DefaultRenderer to add the header mapping and column order information + * to the root of TreeNode structure. + * + * @see CsvSerializer + */ +public class HostKerberosIdentityCsvRenderer extends DefaultRenderer { + + @Override + public Result finalizeResult(Result queryResult) { + TreeNode resultTree = queryResult.getResultTree(); + + if(resultTree != null) { + // TODO: Determine which columns/fields are relevant for the query and prune as needed. + Map columnMap = new HashMap() {{ + put("KerberosIdentity/host_name", "host"); + put("KerberosIdentity/description", "description"); + put("KerberosIdentity/principal_name", "principal name"); + put("KerberosIdentity/principal_type", "principal type"); + put("KerberosIdentity/principal_local_username", "local username"); + put("KerberosIdentity/keytab_file_path", "keytab file path"); + put("KerberosIdentity/keytab_file_owner", "keytab file owner"); + put("KerberosIdentity/keytab_file_owner_access", "keytab file owner access"); + put("KerberosIdentity/keytab_file_group", "keytab file group"); + put("KerberosIdentity/keytab_file_group_access", "keytab file group access"); + put("KerberosIdentity/keytab_file_mode", "keytab file mode"); + put("KerberosIdentity/keytab_file_installed", "keytab file installed"); + }}; + + List columnOrder = new ArrayList() {{ + add("KerberosIdentity/host_name"); + add("KerberosIdentity/description"); + add("KerberosIdentity/principal_name"); + add("KerberosIdentity/principal_type"); + add("KerberosIdentity/principal_local_username"); + add("KerberosIdentity/keytab_file_path"); + add("KerberosIdentity/keytab_file_owner"); + add("KerberosIdentity/keytab_file_owner_access"); + add("KerberosIdentity/keytab_file_group"); + add("KerberosIdentity/keytab_file_group_access"); + add("KerberosIdentity/keytab_file_mode"); + add("KerberosIdentity/keytab_file_installed"); + }}; + + resultTree.setProperty(CsvSerializer.PROPERTY_COLUMN_MAP, columnMap); + resultTree.setProperty(CsvSerializer.PROPERTY_COLUMN_ORDER, columnOrder); + } + + return queryResult; + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/66e42cba/ambari-server/src/main/java/org/apache/ambari/server/api/resources/BaseResourceDefinition.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/BaseResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/BaseResourceDefinition.java index 02342a8..e63f7eb 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/BaseResourceDefinition.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/BaseResourceDefinition.java @@ -28,6 +28,8 @@ import org.apache.ambari.server.controller.spi.ClusterController; import org.apache.ambari.server.controller.spi.Resource; import org.apache.ambari.server.controller.spi.Schema; import org.apache.ambari.server.controller.utilities.ClusterControllerHelper; +import org.apache.commons.codec.EncoderException; +import org.apache.commons.codec.net.URLCodec; import java.util.ArrayList; import java.util.Collection; @@ -180,13 +182,33 @@ public abstract class BaseResourceDefinition implements ResourceDefinition { } Schema schema = getClusterController().getSchema(r.getType()); - Object id = r.getPropertyValue(schema.getKeyPropertyId(r.getType())); + Object id = r.getPropertyValue(schema.getKeyPropertyId(r.getType())); - href = parent.getProperty("isCollection").equals("true") ? - href + id : href + parent.getName() + '/' + id; + String hrefIdPart = urlencode(id); + + href = parent.getStringProperty("isCollection").equals("true") ? + href + hrefIdPart : href + parent.getName() + '/' + hrefIdPart; } resultNode.setProperty("href", href); } + + /** + * URL encodes the id (string) value + * + * @param id the id to URL encode + * @return null if id is null, else the URL encoded value of the id + */ + protected String urlencode(Object id) { + if (id == null) + return ""; + else { + try { + return new URLCodec().encode(id.toString()); + } catch (EncoderException e) { + return id.toString(); + } + } + } } /** http://git-wip-us.apache.org/repos/asf/ambari/blob/66e42cba/ambari-server/src/main/java/org/apache/ambari/server/api/resources/HostComponentResourceDefinition.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/HostComponentResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/HostComponentResourceDefinition.java index 6dc9e2d..33d4c46 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/HostComponentResourceDefinition.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/HostComponentResourceDefinition.java @@ -106,7 +106,7 @@ public class HostComponentResourceDefinition extends BaseResourceDefinition { //todo: look at partial request fields to ensure that hosts should be returned if (request.getResource().getResourceDefinition().getType() == getType()) { // only add host if query host_resource was directly queried - String nodeHref = resultNode.getProperty("href"); + String nodeHref = resultNode.getStringProperty("href"); resultNode.getObject().setProperty(PropertyHelper.getPropertyId("host", "href"), nodeHref.substring(0, nodeHref.indexOf("/host_components/"))); } http://git-wip-us.apache.org/repos/asf/ambari/blob/66e42cba/ambari-server/src/main/java/org/apache/ambari/server/api/resources/HostKerberosIdentityResourceDefinition.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/HostKerberosIdentityResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/HostKerberosIdentityResourceDefinition.java new file mode 100644 index 0000000..65cf1de --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/HostKerberosIdentityResourceDefinition.java @@ -0,0 +1,56 @@ +/* + * 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.ambari.server.api.resources; + +import org.apache.ambari.server.api.query.render.HostKerberosIdentityCsvRenderer; +import org.apache.ambari.server.api.query.render.Renderer; +import org.apache.ambari.server.controller.spi.Resource; + +/** + * HostKerberosIdentity resource definition. + */ +public class HostKerberosIdentityResourceDefinition extends BaseResourceDefinition { + + /** + * Constructor. + */ + public HostKerberosIdentityResourceDefinition() { + super(Resource.Type.HostKerberosIdentity); + } + + @Override + public String getPluralName() { + return "kerberos_identities"; + } + + @Override + public String getSingularName() { + return "kerberos_identity"; + } + + @Override + public Renderer getRenderer(String name) { + if ("csv".equalsIgnoreCase(name)) { + return new HostKerberosIdentityCsvRenderer(); + } else { + return super.getRenderer(name); + } + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/66e42cba/ambari-server/src/main/java/org/apache/ambari/server/api/resources/HostResourceDefinition.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/HostResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/HostResourceDefinition.java index 380e751..c9b0878 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/HostResourceDefinition.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/HostResourceDefinition.java @@ -52,6 +52,7 @@ public class HostResourceDefinition extends BaseResourceDefinition { subs.add(new SubResourceDefinition(Resource.Type.HostComponent)); subs.add(new SubResourceDefinition(Resource.Type.Alert)); subs.add(new SubResourceDefinition(Resource.Type.HostStackVersion)); + subs.add(new SubResourceDefinition(Resource.Type.HostKerberosIdentity)); return subs; } } http://git-wip-us.apache.org/repos/asf/ambari/blob/66e42cba/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java index 776f1f4..1e219ff 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java @@ -384,6 +384,10 @@ public class ResourceInstanceFactoryImpl implements ResourceInstanceFactory { resourceDefinition = new ActiveWidgetLayoutResourceDefinition(); break; + case HostKerberosIdentity: + resourceDefinition = new HostKerberosIdentityResourceDefinition(); + break; + default: throw new IllegalArgumentException("Unsupported resource type: " + type); } http://git-wip-us.apache.org/repos/asf/ambari/blob/66e42cba/ambari-server/src/main/java/org/apache/ambari/server/api/services/BaseService.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/BaseService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/BaseService.java index 3afc23d..1016ed7 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/BaseService.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/BaseService.java @@ -24,6 +24,7 @@ import org.apache.ambari.server.api.resources.ResourceInstanceFactoryImpl; import org.apache.ambari.server.api.services.parsers.BodyParseException; import org.apache.ambari.server.api.services.parsers.JsonRequestBodyParser; import org.apache.ambari.server.api.services.parsers.RequestBodyParser; +import org.apache.ambari.server.api.services.serializers.CsvSerializer; import org.apache.ambari.server.api.services.serializers.JsonSerializer; import org.apache.ambari.server.api.services.serializers.ResultSerializer; import org.apache.ambari.server.controller.spi.Resource; @@ -41,6 +42,7 @@ import java.util.Set; * Provides common functionality to all services. */ public abstract class BaseService { + public final static MediaType MEDIA_TYPE_TEXT_CSV_TYPE = new MediaType("text", "csv"); /** * Factory for creating resource instances. @@ -175,6 +177,10 @@ public abstract class BaseService { } }; } + else if (mediaType.equals(MEDIA_TYPE_TEXT_CSV_TYPE)) { + return new CsvSerializer(); + } + throw new IllegalArgumentException("The media type " + mediaType + " is not supported."); } http://git-wip-us.apache.org/repos/asf/ambari/blob/66e42cba/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java index be40bc4..7bb0a72 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java @@ -419,6 +419,22 @@ public class ClusterService extends BaseService { } /** + * Get the host Kerberos identity resource without specifying the parent host component. + * Allows accessing host Kerberos identity resources across hosts. + * + * @param request the request + * @param clusterName the cluster name + * + * @return the host component service with no parent set + */ + @Path("{clusterName}/kerberos_identities") + public HostKerberosIdentityService getHostKerberosIdentityHandler(@Context javax.ws.rs.core.Request request, @PathParam("clusterName") String clusterName) { + + hasPermission(Request.Type.valueOf(request.getMethod()), clusterName); + return new HostKerberosIdentityService(clusterName, null); + } + + /** * Get the component resource without specifying the parent service. * Allows accessing component resources across services. * http://git-wip-us.apache.org/repos/asf/ambari/blob/66e42cba/ambari-server/src/main/java/org/apache/ambari/server/api/services/HostKerberosIdentityService.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/HostKerberosIdentityService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/HostKerberosIdentityService.java new file mode 100644 index 0000000..624a335 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/HostKerberosIdentityService.java @@ -0,0 +1,121 @@ +/* + * 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.ambari.server.api.services; + +import org.apache.ambari.server.api.resources.ResourceInstance; +import org.apache.ambari.server.controller.spi.Resource; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; +import java.util.HashMap; +import java.util.Map; + +/** + * Service responsible for kerberos identity resource requests. + */ +public class HostKerberosIdentityService extends BaseService { + + /** + * Parent cluster id. + */ + private String clusterName; + + /** + * Relevant hostname + */ + private String hostName; + + /** + * Constructor. + * + * @param clusterName cluster name + * @param hostName host name + */ + public HostKerberosIdentityService(String clusterName, String hostName) { + this.clusterName = clusterName; + this.hostName = hostName; + } + + /** + * Handles GET: /clusters/{clusterID}/services/{serviceID}/components/{componentID}/kerberos_identities/{identityId} + * Get a specific Kerberos identity. + * + * @param headers http headers + * @param ui uri info + * @param identityID Kerberos identity id + * @param format output format + * @return a component resource representation + */ + @GET + @Path("{kerberosIdentityID}") + @Produces("text/plain") + public Response getKerberosIdentity(String body, @Context HttpHeaders headers, @Context UriInfo ui, + @PathParam("kerberosIdentityID") String identityID, + @QueryParam("format") String format) { + + MediaType mediaType; + if ("csv".equalsIgnoreCase(format)) { + mediaType = MEDIA_TYPE_TEXT_CSV_TYPE; + } else { + mediaType = null; + } + + return handleRequest(headers, body, ui, Request.Type.GET, mediaType, createResource(clusterName, hostName, identityID)); + } + + /** + * Handles GET: /clusters/{clusterID}/services/{serviceID}/components/{componentID}/kerberos_identities + * Get all Kerberos identities for a service. + * + * @param headers http headers + * @param ui uri info + * @return component collection resource representation + */ + @GET + @Produces("text/plain") + public Response getKerberosIdentities(String body, @Context HttpHeaders headers, @Context UriInfo ui, @QueryParam("format") String format) { + return getKerberosIdentity(body, headers, ui, null, format); + } + + /** + * Create a kerberos identity resource instance. + * + * @param clusterName cluster name + * @param hostName host name + * @param identityId Kerberos identity id + * @return a component resource instance + */ + ResourceInstance createResource(String clusterName, String hostName, String identityId) { + Map mapIds = new HashMap(); + mapIds.put(Resource.Type.Cluster, clusterName); + mapIds.put(Resource.Type.Host, hostName); + mapIds.put(Resource.Type.HostKerberosIdentity, identityId); + + return createResource(Resource.Type.HostKerberosIdentity, mapIds); + } + +} http://git-wip-us.apache.org/repos/asf/ambari/blob/66e42cba/ambari-server/src/main/java/org/apache/ambari/server/api/services/HostService.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/HostService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/HostService.java index aaf3007..c54d30f 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/HostService.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/HostService.java @@ -207,6 +207,17 @@ public class HostService extends BaseService { } /** + * Get the kerberos_identities sub-resource. + * + * @param hostName host id + * @return the host_components service + */ + @Path("{hostName}/kerberos_identities") + public HostKerberosIdentityService getHostKerberosIdentityHandler(@PathParam("hostName") String hostName) { + return new HostKerberosIdentityService(m_clusterName, hostName); + } + + /** * Get the alerts sub-resource. * * @param hostName host id http://git-wip-us.apache.org/repos/asf/ambari/blob/66e42cba/ambari-server/src/main/java/org/apache/ambari/server/api/services/ResultPostProcessorImpl.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ResultPostProcessorImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ResultPostProcessorImpl.java index 61afee2..4d469d7 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ResultPostProcessorImpl.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ResultPostProcessorImpl.java @@ -89,7 +89,7 @@ public class ResultPostProcessorImpl implements ResultPostProcessor { for (ResourceDefinition.PostProcessor processor : listProcessors) { processor.process(m_request, node, href); } - href = node.getProperty("href"); + href = node.getStringProperty("href"); int i = href.indexOf('?'); if (i != -1) { try { @@ -99,7 +99,7 @@ public class ResultPostProcessorImpl implements ResultPostProcessor { } } } else { - String isItemsCollection = node.getProperty("isCollection"); + String isItemsCollection = node.getStringProperty("isCollection"); if (node.getName() == null && "true".equals(isItemsCollection)) { node.setName("items"); node.setProperty("href", href); http://git-wip-us.apache.org/repos/asf/ambari/blob/66e42cba/ambari-server/src/main/java/org/apache/ambari/server/api/services/serializers/CsvSerializer.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/serializers/CsvSerializer.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/serializers/CsvSerializer.java new file mode 100644 index 0000000..87751dc --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/serializers/CsvSerializer.java @@ -0,0 +1,224 @@ +/* + * 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.ambari.server.api.services.serializers; + +import org.apache.ambari.server.api.services.Result; +import org.apache.ambari.server.api.services.ResultStatus; +import org.apache.ambari.server.api.util.TreeNode; +import org.apache.ambari.server.controller.spi.Resource; +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVPrinter; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * CSV serializer used to generate a CSV-formatted document from a result. + */ +public class CsvSerializer implements ResultSerializer { + /** + * Property name for the CsvSerializer-specific column map where the value of this property + * contains a map of resource property names to header descriptive names. + *

+ * If not specified, no header record will be serialized. + */ + public static final String PROPERTY_COLUMN_MAP = "csv_column_map"; + + /** + * Property name for the CsvSerializer-specific column order where the value of this property + * contains a list of resource property names in the order to export. + *

+ * If not specified, the order will be taken from key order in the csv_column_map property (if + * available) or from the "natural" order of the properties in the resource. + */ + public static final String PROPERTY_COLUMN_ORDER = "csv_column_order"; + + /** + * Serialize the result into a CSV-formatted text document. + *

+ * It is expected that the result set is a collection of flat resources - no sub-resources will be + * included in the output. The root of the tree structure may have a column map (csv_column_map) + * and a column order (csv_column_order) property set to indicate the header record and ordering + * of the columns. + *

+ * The csv_column_map is a map of resource property names to header descriptive names. If not + * specified, a header record will not be serialized. + *

+ * The csv_column_order is a list of resource property names declaring the order of the columns. + * If not specified, the order will be taken from the key order of csv_column_map or the "natural" + * ordering of the resource property names, both may be unpredictable. + * + * @param result internal result + * @return a String containing the CSV-formatted document + */ + @Override + public Object serialize(Result result) { + if (result.getStatus().isErrorState()) { + return serializeError(result.getStatus()); + } else { + + try { + // A StringBuffer to store the CSV-formatted document while building it. It may be + // necessary to use file-based storage if the data set is expected to be really large. + StringBuffer buffer = new StringBuffer(); + + TreeNode root = result.getResultTree(); + + if (root != null) { + CSVPrinter csvPrinter = new CSVPrinter(buffer, CSVFormat.DEFAULT); + + // TODO: recursively handle tree structure, for now only handle single level of detail + if ("true".equalsIgnoreCase(root.getStringProperty("isCollection"))) { + List fieldNameOrder = processHeader(csvPrinter, root); + + Collection> children = root.getChildren(); + if (children != null) { + // Iterate over the child nodes of the collection an add each as a new record in the + // CSV document. + for (TreeNode child : children) { + processRecord(csvPrinter, child, fieldNameOrder); + } + } + } + } + + return buffer.toString(); + } catch (IOException e) { + //todo: exception handling. Create ResultStatus 500 and call serializeError + throw new RuntimeException("Unable to serialize to csv: " + e, e); + } + } + } + + @Override + public Object serializeError(ResultStatus error) { + try { + StringBuffer buffer = new StringBuffer(); + CSVPrinter csvPrinter = new CSVPrinter(buffer, CSVFormat.DEFAULT); + + csvPrinter.printRecord(Arrays.asList("status", "message")); + csvPrinter.printRecord(Arrays.asList(error.getStatus().getStatus(), error.getMessage())); + + return buffer.toString(); + } catch (IOException e) { + //todo: exception handling. Create ResultStatus 500 and call serializeError + throw new RuntimeException("Unable to serialize to csv: " + e, e); + } + } + + /** + * Generate a CSV record by processing the resource embedded in the specified node. The order of + * the fields are to be set as specified. + * + * @param csvPrinter the CSVPrinter used to create the record + * @param node the relevant node in the collection + * @param fieldNameOrder a list of field names indicating order + * @throws IOException if an error occurs creating the CSV record + */ + private void processRecord(CSVPrinter csvPrinter, TreeNode node, List fieldNameOrder) + throws IOException { + + if (node != null) { + Resource recordResource = node.getObject(); + if (recordResource != null) { + List values = new ArrayList(); + + if (fieldNameOrder != null) { + for (String fieldName : fieldNameOrder) { + values.add(recordResource.getPropertyValue(fieldName)); + } + } else { + Map> properties = recordResource.getPropertiesMap(); + if (properties != null) { + + for (Map.Entry> outer : properties.entrySet()) { + Map innerProperties = outer.getValue(); + + if (innerProperties != null) { + for (Map.Entry inner : innerProperties.entrySet()) { + values.add(inner.getValue()); + } + } + } + } + } + + if (!values.isEmpty()) { + csvPrinter.printRecord(values); + } + } + } + } + + /** + * Optionally generate the CSV header record and establish the field order by processing the + * csv_column_map and csv_column_order node properties. + * + * @param csvPrinter the CSVPrinter used to create the record + * @param node a node containing header and ordering information + * @return a list indicating the field order for the CSV records + * @throws IOException if an error occurs creating the CSV header + */ + private List processHeader(CSVPrinter csvPrinter, TreeNode node) throws IOException { + Map header; + List fieldNameOrder; + Object object; + + // Get the explicitly set header property for the current tree node. This may be null if no + // header needs to be written out. The header map is expected to be a map of field names to + // descriptive header values. + object = node.getProperty(PROPERTY_COLUMN_MAP); + if (object instanceof Map) { + header = (Map) object; + } else { + header = null; + } + + // Determine the field name order. If explicitly set, use it, else grab it from the header map + // (if available). + object = node.getProperty(PROPERTY_COLUMN_ORDER); + if (object instanceof List) { + // Use the explicitly set ordering + fieldNameOrder = (List) object; + } else if (header != null) { + // Use the ordering specified by the map. + fieldNameOrder = new ArrayList(header.keySet()); + } else { + fieldNameOrder = null; + } + + if (header != null) { + // build the header record + List headerNames = new ArrayList(); + for (String fieldName : fieldNameOrder) { + headerNames.add(header.get(fieldName)); + } + + // write out the header... + csvPrinter.printRecord(headerNames); + } + + return fieldNameOrder; + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/66e42cba/ambari-server/src/main/java/org/apache/ambari/server/api/services/serializers/JsonSerializer.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/serializers/JsonSerializer.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/serializers/JsonSerializer.java index 7f57f7f..c17f162 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/serializers/JsonSerializer.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/serializers/JsonSerializer.java @@ -214,14 +214,14 @@ public class JsonSerializer implements ResultSerializer { } private void writeHref(TreeNode node) throws IOException { - String hrefProp = node.getProperty("href"); + String hrefProp = node.getStringProperty("href"); if (hrefProp != null) { m_generator.writeStringField("href", hrefProp); } } private void writeItemCount(TreeNode node) throws IOException { - String countProp = node.getProperty("count"); + String countProp = node.getStringProperty("count"); if (countProp != null) { m_generator.writeStringField("itemTotal", countProp); // Write once http://git-wip-us.apache.org/repos/asf/ambari/blob/66e42cba/ambari-server/src/main/java/org/apache/ambari/server/api/util/TreeNode.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/util/TreeNode.java b/ambari-server/src/main/java/org/apache/ambari/server/api/util/TreeNode.java index 796d64f..60d365f 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/api/util/TreeNode.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/util/TreeNode.java @@ -98,7 +98,7 @@ public interface TreeNode { * @param name the name of the property * @param value the value of the property */ - public void setProperty(String name, String value); + public void setProperty(String name, Object value); /** * Get the specified node property. @@ -106,7 +106,15 @@ public interface TreeNode { * @param name property name * @return the requested property value or null */ - public String getProperty(String name); + public Object getProperty(String name); + + /** + * Get the specified node property as a String. + * + * @param name property name + * @return the requested property value (as a String) or null + */ + public String getStringProperty(String name); /** * Remove a property from the node. http://git-wip-us.apache.org/repos/asf/ambari/blob/66e42cba/ambari-server/src/main/java/org/apache/ambari/server/api/util/TreeNodeImpl.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/util/TreeNodeImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/api/util/TreeNodeImpl.java index 1739b88..c498ad7 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/api/util/TreeNodeImpl.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/util/TreeNodeImpl.java @@ -50,7 +50,7 @@ public class TreeNodeImpl implements TreeNode { /** * properties */ - private Map m_mapNodeProps; + private Map m_mapNodeProps; /** * Constructor. @@ -117,19 +117,25 @@ public class TreeNodeImpl implements TreeNode { } @Override - public void setProperty(String name, String value) { + public void setProperty(String name, Object value) { if (m_mapNodeProps == null) { - m_mapNodeProps = new LinkedHashMap(); + m_mapNodeProps = new LinkedHashMap(); } m_mapNodeProps.put(name, value); } @Override - public String getProperty(String name) { + public Object getProperty(String name) { return m_mapNodeProps == null ? null : m_mapNodeProps.get(name); } @Override + public String getStringProperty(String name) { + Object value = getProperty(name); + return value == null ? null : value.toString(); + } + + @Override public void removeProperty(String name) { if (m_mapNodeProps != null) { m_mapNodeProps.remove(name); http://git-wip-us.apache.org/repos/asf/ambari/blob/66e42cba/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java index d6da1eb..e2f6ccb 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java @@ -61,6 +61,7 @@ import org.apache.ambari.server.configuration.Configuration.ConnectionPoolType; import org.apache.ambari.server.configuration.Configuration.DatabaseType; import org.apache.ambari.server.controller.internal.ComponentResourceProvider; import org.apache.ambari.server.controller.internal.HostComponentResourceProvider; +import org.apache.ambari.server.controller.internal.HostKerberosIdentityResourceProvider; import org.apache.ambari.server.controller.internal.HostResourceProvider; import org.apache.ambari.server.controller.internal.MemberResourceProvider; import org.apache.ambari.server.controller.internal.RepositoryVersionResourceProvider; @@ -389,6 +390,7 @@ public class ControllerModule extends AbstractModule { .implement(ResourceProvider.class, Names.named("component"), ComponentResourceProvider.class) .implement(ResourceProvider.class, Names.named("member"), MemberResourceProvider.class) .implement(ResourceProvider.class, Names.named("repositoryVersion"), RepositoryVersionResourceProvider.class) + .implement(ResourceProvider.class, Names.named("hostKerberosIdentity"), HostKerberosIdentityResourceProvider.class) .build(ResourceProviderFactory.class)); install(new FactoryModuleBuilder().implement( http://git-wip-us.apache.org/repos/asf/ambari/blob/66e42cba/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelper.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelper.java index bdf94a5..b131c4c 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelper.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelper.java @@ -1999,6 +1999,173 @@ public class KerberosHelper { } /** + * Returns the active identities for the named cluster. Results are filtered by host, service, + * and/or component; and grouped by host. + *

+ * The cluster name is mandatory; however the active identities may be filtered by one or more of + * host, service, or component. A null value for any of these filters indicates no + * filter for that parameter. + *

+ * The return values are grouped by host and optionally _HOST in principals will be + * replaced with the relevant hostname if specified to do so. + * + * @param clusterName the name of the relevant cluster (mandatory) + * @param hostName the name of a host for which to find results, null indicates all hosts + * @param serviceName the name of a service for which to find results, null indicates all + * services + * @param componentName the name of a component for which to find results, null indicates all + * components + * @param replaceHostNames if true, _HOST in principals will be replace with the relevant host + * name + * @return a map of host names to kerberos identities + * @throws AmbariException if an error occurs processing the cluster's active identities + */ + public Map> getActiveIdentities(String clusterName, + String hostName, + String serviceName, + String componentName, + boolean replaceHostNames) + throws AmbariException { + + if ((clusterName == null) || clusterName.isEmpty()) { + throw new IllegalArgumentException("Invalid argument, cluster name is required"); + } + + Cluster cluster = clusters.getCluster(clusterName); + + if (cluster == null) { + throw new AmbariException(String.format("The cluster object for the cluster name %s is not available", clusterName)); + } + + Map> activeIdentities = new HashMap>(); + + if (isClusterKerberosEnabled(cluster)) { + Collection hosts; + + if (hostName == null) { + Map hostMap = clusters.getHostsForCluster(clusterName); + if (hostMap == null) { + hosts = null; + } else { + hosts = hostMap.keySet(); + } + } else { + hosts = Collections.singleton(hostName); + } + + if ((hosts != null) && !hosts.isEmpty()) { + KerberosDescriptor kerberosDescriptor = getKerberosDescriptor(cluster); + + if (kerberosDescriptor != null) { + Map kerberosDescriptorProperties = kerberosDescriptor.getProperties(); + + for (String hostname : hosts) { + Map hostActiveIdentities = new HashMap(); + List identities = getActiveIdentities(cluster, hostname, serviceName, componentName, kerberosDescriptor); + + if (!identities.isEmpty()) { + // Calculate the current host-specific configurations. These will be used to replace + // variables within the Kerberos descriptor data + Map> configurations = calculateConfigurations(cluster, hostname, kerberosDescriptorProperties); + + for (KerberosIdentityDescriptor identity : identities) { + KerberosPrincipalDescriptor principalDescriptor = identity.getPrincipalDescriptor(); + String principal = null; + + if (principalDescriptor != null) { + principal = KerberosDescriptor.replaceVariables(principalDescriptor.getValue(), configurations); + } + + if (principal != null) { + if (replaceHostNames) { + principal = principal.replace("_HOST", hostname); + } + + if (!hostActiveIdentities.containsKey(principal)) { + KerberosPrincipalDescriptor resolvedPrincipalDescriptor = + new KerberosPrincipalDescriptor(principal, + principalDescriptor.getType(), + KerberosDescriptor.replaceVariables(principalDescriptor.getConfiguration(), configurations), + KerberosDescriptor.replaceVariables(principalDescriptor.getLocalUsername(), configurations)); + + KerberosKeytabDescriptor resolvedKeytabDescriptor; + + KerberosKeytabDescriptor keytabDescriptor = identity.getKeytabDescriptor(); + if (keytabDescriptor == null) { + resolvedKeytabDescriptor = null; + } else { + resolvedKeytabDescriptor = + new KerberosKeytabDescriptor( + KerberosDescriptor.replaceVariables(keytabDescriptor.getFile(), configurations), + KerberosDescriptor.replaceVariables(keytabDescriptor.getOwnerName(), configurations), + KerberosDescriptor.replaceVariables(keytabDescriptor.getOwnerAccess(), configurations), + KerberosDescriptor.replaceVariables(keytabDescriptor.getGroupName(), configurations), + KerberosDescriptor.replaceVariables(keytabDescriptor.getGroupAccess(), configurations), + KerberosDescriptor.replaceVariables(keytabDescriptor.getConfiguration(), configurations), + keytabDescriptor.isCachable()); + } + + hostActiveIdentities.put(principal, new KerberosIdentityDescriptor( + identity.getName(), + resolvedPrincipalDescriptor, + resolvedKeytabDescriptor)); + } + } + } + } + + activeIdentities.put(hostname, hostActiveIdentities.values()); + } + } + } + } + + return activeIdentities; + } + + private List getActiveIdentities(Cluster cluster, + String hostname, + String serviceName, + String componentName, + KerberosDescriptor kerberosDescriptor) + throws AmbariException { + + List identities = new ArrayList(); + + List serviceComponentHosts = cluster.getServiceComponentHosts(hostname); + + if(serviceComponentHosts != null) { + for (ServiceComponentHost serviceComponentHost : serviceComponentHosts) { + String schServiceName = serviceComponentHost.getServiceName(); + String schComponentName = serviceComponentHost.getServiceComponentName(); + + if (((serviceName == null) || serviceName.equals(schServiceName)) && + ((componentName == null) || componentName.equals(schComponentName))) { + + KerberosServiceDescriptor serviceDescriptor = kerberosDescriptor.getService(schServiceName); + + if (serviceDescriptor != null) { + List serviceIdentities = serviceDescriptor.getIdentities(true); + if (serviceIdentities != null) { + identities.addAll(serviceIdentities); + } + + KerberosComponentDescriptor componentDescriptor = serviceDescriptor.getComponent(schComponentName); + if (componentDescriptor != null) { + List componentIdentities = componentDescriptor.getIdentities(true); + if (componentIdentities != null) { + identities.addAll(componentIdentities); + } + } + } + } + } + } + + return identities; + } + + /** * A enumeration of the supported custom operations */ public static enum SupportedCustomOperation { http://git-wip-us.apache.org/repos/asf/ambari/blob/66e42cba/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java index f7eb2d9..5d1143a 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java @@ -53,6 +53,9 @@ public interface ResourceProviderFactory { Map keyPropertyIds, AmbariManagementController managementController); + @Named("hostKerberosIdentity") + ResourceProvider getHostKerberosIdentityResourceProvider(AmbariManagementController managementController); + @Named("repositoryVersion") ResourceProvider getRepositoryVersionResourceProvider(); } http://git-wip-us.apache.org/repos/asf/ambari/blob/66e42cba/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java index 210227e..9163656 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java @@ -167,6 +167,8 @@ public abstract class AbstractControllerResourceProvider extends AbstractResourc return new WidgetLayoutResourceProvider(managementController); case Widget: return new WidgetResourceProvider(managementController); + case HostKerberosIdentity: + return resourceProviderFactory.getHostKerberosIdentityResourceProvider(managementController); default: throw new IllegalArgumentException("Unknown type " + type); http://git-wip-us.apache.org/repos/asf/ambari/blob/66e42cba/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostKerberosIdentityResourceProvider.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostKerberosIdentityResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostKerberosIdentityResourceProvider.java new file mode 100644 index 0000000..c76ae6c --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostKerberosIdentityResourceProvider.java @@ -0,0 +1,243 @@ +/* + * 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.ambari.server.controller.internal; + +import com.google.inject.Inject; +import com.google.inject.assistedinject.Assisted; +import com.google.inject.assistedinject.AssistedInject; +import org.apache.ambari.server.AmbariException; +import org.apache.ambari.server.controller.AmbariManagementController; +import org.apache.ambari.server.controller.KerberosHelper; +import org.apache.ambari.server.controller.spi.NoSuchParentResourceException; +import org.apache.ambari.server.controller.spi.NoSuchResourceException; +import org.apache.ambari.server.controller.spi.Predicate; +import org.apache.ambari.server.controller.spi.Request; +import org.apache.ambari.server.controller.spi.Resource; +import org.apache.ambari.server.controller.spi.SystemException; +import org.apache.ambari.server.controller.spi.UnsupportedPropertyException; +import org.apache.ambari.server.orm.dao.HostDAO; +import org.apache.ambari.server.orm.dao.KerberosPrincipalDAO; +import org.apache.ambari.server.orm.dao.KerberosPrincipalHostDAO; +import org.apache.ambari.server.orm.entities.HostEntity; +import org.apache.ambari.server.state.kerberos.KerberosIdentityDescriptor; +import org.apache.ambari.server.state.kerberos.KerberosKeytabDescriptor; +import org.apache.ambari.server.state.kerberos.KerberosPrincipalDescriptor; + +import java.text.DecimalFormat; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * Read-only resource provider for Kerberos identity resources. + */ +public class HostKerberosIdentityResourceProvider extends ReadOnlyResourceProvider { + + protected static final String KERBEROS_IDENTITY_CLUSTER_NAME_PROPERTY_ID = "KerberosIdentity/cluster_name"; + protected static final String KERBEROS_IDENTITY_HOST_NAME_PROPERTY_ID = "KerberosIdentity/host_name"; + protected static final String KERBEROS_IDENTITY_DESCRIPTION_PROPERTY_ID = "KerberosIdentity/description"; + protected static final String KERBEROS_IDENTITY_PRINCIPAL_NAME_PROPERTY_ID = "KerberosIdentity/principal_name"; + protected static final String KERBEROS_IDENTITY_PRINCIPAL_TYPE_PROPERTY_ID = "KerberosIdentity/principal_type"; + protected static final String KERBEROS_IDENTITY_PRINCIPAL_LOCAL_USERNAME_PROPERTY_ID = "KerberosIdentity/principal_local_username"; + protected static final String KERBEROS_IDENTITY_KEYTAB_FILE_PATH_PROPERTY_ID = "KerberosIdentity/keytab_file_path"; + protected static final String KERBEROS_IDENTITY_KEYTAB_FILE_OWNER_PROPERTY_ID = "KerberosIdentity/keytab_file_owner"; + protected static final String KERBEROS_IDENTITY_KEYTAB_FILE_OWNER_ACCESS_PROPERTY_ID = "KerberosIdentity/keytab_file_owner_access"; + protected static final String KERBEROS_IDENTITY_KEYTAB_FILE_GROUP_PROPERTY_ID = "KerberosIdentity/keytab_file_group"; + protected static final String KERBEROS_IDENTITY_KEYTAB_FILE_GROUP_ACCESS_PROPERTY_ID = "KerberosIdentity/keytab_file_group_access"; + protected static final String KERBEROS_IDENTITY_KEYTAB_FILE_MODE_PROPERTY_ID = "KerberosIdentity/keytab_file_mode"; + protected static final String KERBEROS_IDENTITY_KEYTAB_FILE_INSTALLED_PROPERTY_ID = "KerberosIdentity/keytab_file_installed"; + + protected static final Map PK_PROPERTY_MAP = Collections.unmodifiableMap( + new HashMap() {{ + put(Resource.Type.Cluster, KERBEROS_IDENTITY_CLUSTER_NAME_PROPERTY_ID); + put(Resource.Type.Host, KERBEROS_IDENTITY_HOST_NAME_PROPERTY_ID); + put(Resource.Type.HostKerberosIdentity, KERBEROS_IDENTITY_PRINCIPAL_NAME_PROPERTY_ID); + }} + ); + + protected static final Set PK_PROPERTY_IDS = Collections.unmodifiableSet( + new HashSet(PK_PROPERTY_MAP.values()) + ); + + protected static final Set PROPERTY_IDS = Collections.unmodifiableSet( + new HashSet() {{ + add(KERBEROS_IDENTITY_CLUSTER_NAME_PROPERTY_ID); + add(KERBEROS_IDENTITY_HOST_NAME_PROPERTY_ID); + add(KERBEROS_IDENTITY_DESCRIPTION_PROPERTY_ID); + add(KERBEROS_IDENTITY_PRINCIPAL_NAME_PROPERTY_ID); + add(KERBEROS_IDENTITY_PRINCIPAL_TYPE_PROPERTY_ID); + add(KERBEROS_IDENTITY_PRINCIPAL_LOCAL_USERNAME_PROPERTY_ID); + add(KERBEROS_IDENTITY_KEYTAB_FILE_PATH_PROPERTY_ID); + add(KERBEROS_IDENTITY_KEYTAB_FILE_OWNER_PROPERTY_ID); + add(KERBEROS_IDENTITY_KEYTAB_FILE_OWNER_ACCESS_PROPERTY_ID); + add(KERBEROS_IDENTITY_KEYTAB_FILE_GROUP_PROPERTY_ID); + add(KERBEROS_IDENTITY_KEYTAB_FILE_GROUP_ACCESS_PROPERTY_ID); + add(KERBEROS_IDENTITY_KEYTAB_FILE_MODE_PROPERTY_ID); + add(KERBEROS_IDENTITY_KEYTAB_FILE_INSTALLED_PROPERTY_ID); + }} + ); + + @Inject + private KerberosHelper kerberosHelper; + + /** + * KerberosPrincipalHostDAO used to get Kerberos principal details + */ + @Inject + private KerberosPrincipalHostDAO kerberosPrincipalHostDAO; + + /** + * KerberosPrincipalDAO used to get Kerberos principal details + */ + @Inject + private KerberosPrincipalDAO kerberosPrincipalDAO; + + /** + * HostDAO used to translate host names to host ids + */ + @Inject + private HostDAO hostDAO; + + /** + * Create a new resource provider for the given management controller. + * + * @param managementController the management controller + */ + @AssistedInject + HostKerberosIdentityResourceProvider(@Assisted AmbariManagementController managementController) { + super(PROPERTY_IDS, PK_PROPERTY_MAP, managementController); + } + + + @Override + public Set getResources(Request request, Predicate predicate) + throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException { + return getResources(new GetResourcesCommand(getPropertyMaps(predicate), getRequestPropertyIds(request, predicate))); + } + + @Override + protected Set getPKPropertyIds() { + return PK_PROPERTY_IDS; + } + + /** + * Inner class to implement the "get resource" command. + */ + private class GetResourcesCommand implements Command> { + private final Set> propertyMaps; + private final Set requestPropertyIds; + + public GetResourcesCommand(Set> propertyMaps, Set requestPropertyIds) { + this.propertyMaps = propertyMaps; + this.requestPropertyIds = requestPropertyIds; + } + + @Override + public Set invoke() throws AmbariException { + Set resources = new HashSet(); + + for (Map propertyMap : propertyMaps) { + String clusterName = (String) propertyMap.get(KERBEROS_IDENTITY_CLUSTER_NAME_PROPERTY_ID); + String hostName = (String) propertyMap.get(KERBEROS_IDENTITY_HOST_NAME_PROPERTY_ID); + + // Retrieve the active identities for the cluster filtered and grouped by hostname + Map> hostDescriptors = + kerberosHelper.getActiveIdentities(clusterName, hostName, null, null, true); + + if (hostDescriptors != null) { + for (Map.Entry> entry : hostDescriptors.entrySet()) { + Collection descriptors = entry.getValue(); + + if (descriptors != null) { + String currentHostName = entry.getKey(); + HostEntity host = hostDAO.findByName(currentHostName); + Long hostId = (host == null) ? null : host.getHostId(); + + for (KerberosIdentityDescriptor descriptor : descriptors) { + KerberosPrincipalDescriptor principalDescriptor = descriptor.getPrincipalDescriptor(); + if (principalDescriptor != null) { + String principal = principalDescriptor.getValue(); + + if ((principal != null) && !principal.isEmpty()) { + Resource resource = new ResourceImpl(Resource.Type.HostKerberosIdentity); + + setResourceProperty(resource, KERBEROS_IDENTITY_CLUSTER_NAME_PROPERTY_ID, clusterName, requestPropertyIds); + setResourceProperty(resource, KERBEROS_IDENTITY_HOST_NAME_PROPERTY_ID, currentHostName, requestPropertyIds); + + setResourceProperty(resource, KERBEROS_IDENTITY_PRINCIPAL_NAME_PROPERTY_ID, principal, requestPropertyIds); + setResourceProperty(resource, KERBEROS_IDENTITY_PRINCIPAL_TYPE_PROPERTY_ID, principalDescriptor.getType(), requestPropertyIds); + setResourceProperty(resource, KERBEROS_IDENTITY_PRINCIPAL_LOCAL_USERNAME_PROPERTY_ID, principalDescriptor.getLocalUsername(), requestPropertyIds); + + String installedStatus; + if ((hostId != null) && kerberosPrincipalDAO.exists(principal)) { + if (kerberosPrincipalHostDAO.exists(principal, hostId)) { + installedStatus = "true"; + } else { + installedStatus = "false"; + } + } else { + installedStatus = "unknown"; + } + + setResourceProperty(resource, KERBEROS_IDENTITY_KEYTAB_FILE_INSTALLED_PROPERTY_ID, installedStatus, requestPropertyIds); + + KerberosKeytabDescriptor keytabDescriptor = descriptor.getKeytabDescriptor(); + if (keytabDescriptor != null) { + String ownerAccess = keytabDescriptor.getOwnerAccess(); + String groupAccess = keytabDescriptor.getGroupAccess(); + int mode = 0; + + // Create the file access mode using *nix chmod values. + if ("rw".equals(ownerAccess)) { + mode += 600; + } else if ("r".equals(ownerAccess)) { + mode += 400; + } + + if ("rw".equals(groupAccess)) { + mode += 60; + } else if ("r".equals(groupAccess)) { + mode += 40; + } + + setResourceProperty(resource, KERBEROS_IDENTITY_KEYTAB_FILE_PATH_PROPERTY_ID, keytabDescriptor.getFile(), requestPropertyIds); + setResourceProperty(resource, KERBEROS_IDENTITY_KEYTAB_FILE_OWNER_PROPERTY_ID, keytabDescriptor.getOwnerName(), requestPropertyIds); + setResourceProperty(resource, KERBEROS_IDENTITY_KEYTAB_FILE_OWNER_ACCESS_PROPERTY_ID, ownerAccess, requestPropertyIds); + setResourceProperty(resource, KERBEROS_IDENTITY_KEYTAB_FILE_GROUP_PROPERTY_ID, keytabDescriptor.getGroupName(), requestPropertyIds); + setResourceProperty(resource, KERBEROS_IDENTITY_KEYTAB_FILE_GROUP_ACCESS_PROPERTY_ID, groupAccess, requestPropertyIds); + setResourceProperty(resource, KERBEROS_IDENTITY_KEYTAB_FILE_MODE_PROPERTY_ID, new DecimalFormat("000").format(mode), requestPropertyIds); + } + + setResourceProperty(resource, KERBEROS_IDENTITY_DESCRIPTION_PROPERTY_ID, descriptor.getName(), requestPropertyIds); + + resources.add(resource); + } + } + } + } + } + } + } + + return resources; + } + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/66e42cba/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java index 30bac9e..1b208fb 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java @@ -143,7 +143,8 @@ public interface Resource { Widget, WidgetLayout, ActiveWidgetLayout, - Theme; + Theme, + HostKerberosIdentity; /** * Get the {@link Type} that corresponds to this InternalType. @@ -248,6 +249,7 @@ public interface Resource { public static final Type Widget = InternalType.Widget.getType(); public static final Type WidgetLayout = InternalType.WidgetLayout.getType(); public static final Type ActiveWidgetLayout = InternalType.ActiveWidgetLayout.getType(); + public static final Type HostKerberosIdentity = InternalType.HostKerberosIdentity.getType(); /** * The type name. http://git-wip-us.apache.org/repos/asf/ambari/blob/66e42cba/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosIdentityDescriptor.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosIdentityDescriptor.java b/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosIdentityDescriptor.java index 2e5a27d..d31dd21 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosIdentityDescriptor.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosIdentityDescriptor.java @@ -87,6 +87,19 @@ public class KerberosIdentityDescriptor extends AbstractKerberosDescriptor { /** * Creates a new KerberosIdentityDescriptor + * + * @param name the name of this identity descriptor + * @param principal a KerberosPrincipalDescriptor + * @param keytab a KerberosKeytabDescriptor + */ + public KerberosIdentityDescriptor(String name, KerberosPrincipalDescriptor principal, KerberosKeytabDescriptor keytab) { + setName(name); + setPrincipalDescriptor(principal); + setKeytabDescriptor(keytab); + } + + /** + * Creates a new KerberosIdentityDescriptor *

* See {@link org.apache.ambari.server.state.kerberos.KerberosIdentityDescriptor} for the JSON * Schema that may be used to generate this map. http://git-wip-us.apache.org/repos/asf/ambari/blob/66e42cba/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosKeytabDescriptor.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosKeytabDescriptor.java b/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosKeytabDescriptor.java index 79537d4..404efa2 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosKeytabDescriptor.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosKeytabDescriptor.java @@ -156,6 +156,27 @@ public class KerberosKeytabDescriptor extends AbstractKerberosDescriptor { /** * Creates a new KerberosKeytabDescriptor + * + * @param file the path to the keytab file + * @param ownerName the local username of the file owner + * @param ownerAccess the file access privileges for the file owner ("r", "rw", "") + * @param groupName the local group name with privileges to access the file + * @param groupAccess the file access privileges for the group ("r", "rw", "") + * @param configuration the configuration used to store the principal name + * @param cachable true if the keytab may be cached by Ambari; otherwise false + */ + public KerberosKeytabDescriptor(String file, String ownerName, String ownerAccess, String groupName, + String groupAccess, String configuration, boolean cachable) { + setName(file); + setOwnerName(ownerName); + setOwnerAccess(ownerAccess); + setGroupName(groupName); + setGroupAccess(groupAccess); + setConfiguration(configuration); + setCachable(cachable); + } + /** + * Creates a new KerberosKeytabDescriptor *

* See {@link org.apache.ambari.server.state.kerberos.KerberosKeytabDescriptor} for the JSON * Schema that may be used to generate this map. http://git-wip-us.apache.org/repos/asf/ambari/blob/66e42cba/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosPrincipalDescriptor.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosPrincipalDescriptor.java b/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosPrincipalDescriptor.java index 2c0c90a..6e5ac5c 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosPrincipalDescriptor.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosPrincipalDescriptor.java @@ -73,7 +73,7 @@ public class KerberosPrincipalDescriptor extends AbstractKerberosDescriptor { *

* Expecting either "service" or "user" */ - private KerberosPrincipalType type; + private KerberosPrincipalType type = KerberosPrincipalType.SERVICE; /** * A string declaring configuration type and property name indicating the property to be updated @@ -87,7 +87,7 @@ public class KerberosPrincipalDescriptor extends AbstractKerberosDescriptor { *

* Example: hdfs-site/dfs.namenode.kerberos.principal */ - private String configuration; + private String configuration = null; /** * a String indicating the local username related to this principal, or null of no local mapping is @@ -95,7 +95,24 @@ public class KerberosPrincipalDescriptor extends AbstractKerberosDescriptor { *

* This value may be using in generating auth_to_local configuration settings. */ - private String localUsername; + private String localUsername = null; + + /** + * Creates a new KerberosPrincipalDescriptor + * + * @param principal the principal name + * @param type the principal type (user, service, etc...) + * @param configuration the configuration used to store the principal name + * @param localUsername the local username to map to the principal + */ + public KerberosPrincipalDescriptor(String principal, KerberosPrincipalType type, String configuration, String localUsername) { + // The name for this KerberosPrincipalDescriptor is stored in the "value" entry in the map + // This is not automatically set by the super classes. + setName(principal); + setType((type == null) ? KerberosPrincipalType.SERVICE : type); + setConfiguration(configuration); + setLocalUsername(localUsername); + } /** * Creates a new KerberosPrincipalDescriptor @@ -107,16 +124,11 @@ public class KerberosPrincipalDescriptor extends AbstractKerberosDescriptor { * @see org.apache.ambari.server.state.kerberos.KerberosPrincipalDescriptor */ public KerberosPrincipalDescriptor(Map data) { - // The name for this KerberosPrincipalDescriptor is stored in the "value" entry in the map - // This is not automatically set by the super classes. - setName(getStringValue(data, "value")); - - String type = getStringValue(data, "type"); - setType((type == null) ? KerberosPrincipalType.SERVICE : KerberosPrincipalType.valueOf(type.toUpperCase())); - - setConfiguration(getStringValue(data, "configuration")); - - setLocalUsername(getStringValue(data, "local_username")); + this(getStringValue(data, "value"), + getKerberosPrincipalTypeValue(data, "type"), + getStringValue(data, "configuration"), + getStringValue(data, "local_username") + ); } /** @@ -299,4 +311,24 @@ public class KerberosPrincipalDescriptor extends AbstractKerberosDescriptor { return false; } } + + /** + * Translates a string value representing a principal type to a KerberosPrincipalType. + *

+ * If no value is supplied for the key or a translation cannot be made then KerberosPrincipalType.SERVICE + * is assumed. + * + * @param map a Map containing the relevant data + * @param key a String declaring the item to retrieve + * @return a KerberosPrincipalType + * @throws IllegalArgumentException if the principal type value is not one of the expected types. + */ + private static KerberosPrincipalType getKerberosPrincipalTypeValue(Map map, String key) { + String type = getStringValue(map, key); + if ((type == null) || type.isEmpty()) { + return KerberosPrincipalType.SERVICE; + } else { + return KerberosPrincipalType.valueOf(type.toUpperCase()); + } + } } http://git-wip-us.apache.org/repos/asf/ambari/blob/66e42cba/ambari-server/src/test/java/org/apache/ambari/server/api/query/render/ClusterBlueprintRendererTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/query/render/ClusterBlueprintRendererTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/query/render/ClusterBlueprintRendererTest.java index d33adcd..96abb8c 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/api/query/render/ClusterBlueprintRendererTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/api/query/render/ClusterBlueprintRendererTest.java @@ -193,7 +193,7 @@ public class ClusterBlueprintRendererTest { Result blueprintResult = renderer.finalizeResult(result); TreeNode blueprintTree = blueprintResult.getResultTree(); - assertNull(blueprintTree.getProperty("isCollection")); + assertNull(blueprintTree.getStringProperty("isCollection")); assertEquals(1, blueprintTree.getChildren().size()); TreeNode blueprintNode = blueprintTree.getChildren().iterator().next(); @@ -272,7 +272,7 @@ public class ClusterBlueprintRendererTest { Result blueprintResult = renderer.finalizeResult(result); TreeNode blueprintTree = blueprintResult.getResultTree(); - assertNull(blueprintTree.getProperty("isCollection")); + assertNull(blueprintTree.getStringProperty("isCollection")); assertEquals(1, blueprintTree.getChildren().size()); TreeNode blueprintNode = blueprintTree.getChildren().iterator().next(); http://git-wip-us.apache.org/repos/asf/ambari/blob/66e42cba/ambari-server/src/test/java/org/apache/ambari/server/api/query/render/MinimalRendererTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/query/render/MinimalRendererTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/query/render/MinimalRendererTest.java index 37bf33c..9b9b614 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/api/query/render/MinimalRendererTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/api/query/render/MinimalRendererTest.java @@ -348,7 +348,7 @@ public class MinimalRendererTest { renderer.finalizeProperties(createPropertyTree(), false); TreeNode resultTree = renderer.finalizeResult(result).getResultTree(); - assertNull(resultTree.getProperty("isCollection")); + assertNull(resultTree.getStringProperty("isCollection")); assertEquals(1, resultTree.getChildren().size()); TreeNode clusterNode = resultTree.getChildren().iterator().next(); @@ -414,7 +414,7 @@ public class MinimalRendererTest { renderer.finalizeProperties(createPropertyTreeWithSubProps(), false); TreeNode resultTree = renderer.finalizeResult(result).getResultTree(); - assertNull(resultTree.getProperty("isCollection")); + assertNull(resultTree.getStringProperty("isCollection")); assertEquals(1, resultTree.getChildren().size()); TreeNode clusterNode = resultTree.getChildren().iterator().next(); http://git-wip-us.apache.org/repos/asf/ambari/blob/66e42cba/ambari-server/src/test/java/org/apache/ambari/server/api/resources/BaseResourceDefinitionTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/resources/BaseResourceDefinitionTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/resources/BaseResourceDefinitionTest.java index 3f64d9a..f174cb6 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/api/resources/BaseResourceDefinitionTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/api/resources/BaseResourceDefinitionTest.java @@ -106,7 +106,7 @@ public class BaseResourceDefinitionTest { processor.process(null, serviceNode, "http://c6401.ambari.apache.org:8080/api/v1/clusters/c1/services"); - String href = serviceNode.getProperty("href"); + String href = serviceNode.getStringProperty("href"); Assert.assertEquals("http://c6401.ambari.apache.org:8080/api/v1/clusters/c1/services/Service1", href); @@ -121,7 +121,7 @@ public class BaseResourceDefinitionTest { processor.process(null, configGroupNode, "http://c6401.ambari.apache.org:8080/api/v1/clusters/c1/config_groups"); - href = configGroupNode.getProperty("href"); + href = configGroupNode.getStringProperty("href"); Assert.assertEquals("http://c6401.ambari.apache.org:8080/api/v1/clusters/c1/config_groups/2", href); } http://git-wip-us.apache.org/repos/asf/ambari/blob/66e42cba/ambari-server/src/test/java/org/apache/ambari/server/api/resources/HostKerberosIdentityResourceDefinitionTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/resources/HostKerberosIdentityResourceDefinitionTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/resources/HostKerberosIdentityResourceDefinitionTest.java new file mode 100644 index 0000000..603e00e --- /dev/null +++ b/ambari-server/src/test/java/org/apache/ambari/server/api/resources/HostKerberosIdentityResourceDefinitionTest.java @@ -0,0 +1,48 @@ +/* + * 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.ambari.server.api.resources; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.Set; + +/** + * HostKerberosIdentityResourceDefinition tests. + */ +public class HostKerberosIdentityResourceDefinitionTest { + @Test + public void testGetPluralName() throws Exception { + final HostKerberosIdentityResourceDefinition resourceDefinition = new HostKerberosIdentityResourceDefinition(); + Assert.assertEquals("kerberos_identities", resourceDefinition.getPluralName()); + } + + @Test + public void testGetSingularName() throws Exception { + final HostKerberosIdentityResourceDefinition resourceDefinition = new HostKerberosIdentityResourceDefinition(); + Assert.assertEquals("kerberos_identity", resourceDefinition.getSingularName()); + } + + @Test + public void testGetSubResourceDefinitions() throws Exception { + final HostKerberosIdentityResourceDefinition resourceDefinition = new HostKerberosIdentityResourceDefinition(); + final Set subResourceDefinitions = resourceDefinition.getSubResourceDefinitions (); + Assert.assertEquals(0, subResourceDefinitions.size()); + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/66e42cba/ambari-server/src/test/java/org/apache/ambari/server/api/resources/HostResourceDefinitionTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/resources/HostResourceDefinitionTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/resources/HostResourceDefinitionTest.java index b3851eb..3d3fe11 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/api/resources/HostResourceDefinitionTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/api/resources/HostResourceDefinitionTest.java @@ -46,10 +46,11 @@ public class HostResourceDefinitionTest { final ResourceDefinition resource = new HostResourceDefinition(); Set subResources = resource.getSubResourceDefinitions(); - assertEquals(3, subResources.size()); + assertEquals(4, subResources.size()); assertTrue(includesType(subResources, Resource.Type.HostComponent)); assertTrue(includesType(subResources, Resource.Type.Alert)); assertTrue(includesType(subResources, Resource.Type.HostStackVersion)); + assertTrue(includesType(subResources, Resource.Type.HostKerberosIdentity)); } private boolean includesType(Set resources, Resource.Type type) { http://git-wip-us.apache.org/repos/asf/ambari/blob/66e42cba/ambari-server/src/test/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImplTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImplTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImplTest.java index 0daffce..2daa273 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImplTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImplTest.java @@ -47,4 +47,14 @@ public class ResourceInstanceFactoryImplTest { assertEquals("artifacts", resourceDefinition.getPluralName()); assertEquals(Resource.Type.Artifact, resourceDefinition.getType()); } + + @Test + public void testGetHostKerberosIdentityDefinition() { + ResourceDefinition resourceDefinition = ResourceInstanceFactoryImpl.getResourceDefinition( + Resource.Type.HostKerberosIdentity, null); + + assertEquals("kerberos_identity", resourceDefinition.getSingularName()); + assertEquals("kerberos_identities", resourceDefinition.getPluralName()); + assertEquals(Resource.Type.HostKerberosIdentity, resourceDefinition.getType()); + } }