AMBARI-22418. Make Ambari configuration API consistent with existing API. (rlevas)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/3f2743b5 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/3f2743b5 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/3f2743b5 Branch: refs/heads/branch-feature-AMBARI-22008 Commit: 3f2743b58ba65c4bdc7d37df5348d17124bf305a Parents: 2d81d49 Author: Robert Levas <rle...@hortonworks.com> Authored: Wed Nov 15 12:11:34 2017 -0500 Committer: Robert Levas <rle...@hortonworks.com> Committed: Wed Nov 15 12:11:34 2017 -0500 ---------------------------------------------------------------------- .../resources/ResourceInstanceFactoryImpl.java | 9 +- .../RootServiceComponentResourceDefinition.java | 9 +- .../AmbariConfigurationRequestSwagger.java | 37 -- .../AmbariConfigurationResponseSwagger.java | 40 -- .../services/AmbariConfigurationService.java | 193 -------- .../server/api/services/AmbariMetaInfo.java | 4 +- ...iceComponentConfigurationRequestSwagger.java | 43 ++ ...ceComponentConfigurationResponseSwagger.java | 43 ++ ...ootServiceComponentConfigurationService.java | 226 +++++++++ .../server/api/services/RootServiceService.java | 7 + .../api/services/ldap/AmbariConfiguration.java | 6 +- .../services/ldap/LdapConfigurationRequest.java | 2 +- .../services/ldap/LdapConfigurationService.java | 6 +- .../commands/StackAdvisorCommand.java | 62 ++- .../server/controller/ControllerModule.java | 4 +- .../controller/MaintenanceStateHelper.java | 3 +- .../controller/ResourceProviderFactory.java | 4 +- .../ambari/server/controller/RootComponent.java | 27 ++ .../ambari/server/controller/RootService.java | 36 ++ .../controller/RootServiceResponseFactory.java | 44 +- .../AbstractControllerResourceProvider.java | 4 +- .../AmbariConfigurationResourceProvider.java | 302 ------------ ...eComponentConfigurationResourceProvider.java | 476 +++++++++++++++++++ .../RootServiceComponentPropertyProvider.java | 4 +- .../RootServiceComponentResourceProvider.java | 4 +- .../ambari/server/controller/spi/Resource.java | 6 +- .../listeners/alerts/AlertReceivedListener.java | 10 +- .../alerts/AlertStateChangedListener.java | 6 +- .../ldap/domain/AmbariLdapConfiguration.java | 6 +- .../domain/AmbariLdapConfigurationFactory.java | 2 +- .../AmbariLdapConfigurationProvider.java | 6 +- .../metadata/AmbariServiceAlertDefinitions.java | 20 +- .../server/orm/dao/AlertDefinitionDAO.java | 7 +- .../ambari/server/orm/dao/AlertDispatchDAO.java | 4 +- .../server/state/alert/AlertDefinitionHash.java | 8 +- .../server/state/cluster/ClusterImpl.java | 4 +- .../services/AmbariServerAlertService.java | 4 +- .../commands/StackAdvisorCommandTest.java | 8 +- .../AmbariManagementControllerTest.java | 16 +- .../RootServiceResponseFactoryTest.java | 27 +- ...AmbariConfigurationResourceProviderTest.java | 377 --------------- ...ponentConfigurationResourceProviderTest.java | 393 +++++++++++++++ ...ootServiceComponentPropertyProviderTest.java | 15 +- ...ootServiceComponentResourceProviderTest.java | 9 +- .../server/ldap/LdapModuleFunctionalTest.java | 4 +- .../TestAmbariLdapConfigurationFactory.java | 2 +- .../ldap/service/AmbariLdapFacadeTest.java | 4 +- ...efaultLdapAttributeDetectionServiceTest.java | 8 +- .../DefaultLdapConfigurationServiceTest.java | 12 +- .../metadata/AgentAlertDefinitionsTest.java | 6 +- .../server/orm/dao/AlertDefinitionDAOTest.java | 7 +- .../state/alerts/AlertReceivedListenerTest.java | 16 +- .../alerts/AlertStateChangedEventTest.java | 4 +- 53 files changed, 1444 insertions(+), 1142 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/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 f5fb6e9..fecaedc 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 @@ -237,6 +237,11 @@ public class ResourceInstanceFactoryImpl implements ResourceInstanceFactory { resourceDefinition = new RootServiceComponentResourceDefinition(); break; + case RootServiceComponentConfiguration: + resourceDefinition = new SimpleResourceDefinition(Resource.Type.RootServiceComponentConfiguration, + "configuration", "configurations"); + break; + case RootServiceHostComponent: resourceDefinition = new RootServiceHostComponentResourceDefinition(); break; @@ -471,10 +476,6 @@ public class ResourceInstanceFactoryImpl implements ResourceInstanceFactory { case RemoteCluster: resourceDefinition = new RemoteClusterResourceDefinition(); break; - case AmbariConfiguration: - resourceDefinition = new SimpleResourceDefinition(Resource.Type.AmbariConfiguration, "ambariconfiguration", "ambariconfigurations"); - - break; default: throw new IllegalArgumentException("Unsupported resource type: " + type); http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/ambari-server/src/main/java/org/apache/ambari/server/api/resources/RootServiceComponentResourceDefinition.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/RootServiceComponentResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/RootServiceComponentResourceDefinition.java index e8cb570..1c036e4 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/RootServiceComponentResourceDefinition.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/RootServiceComponentResourceDefinition.java @@ -19,6 +19,7 @@ package org.apache.ambari.server.api.resources; import java.util.Collections; +import java.util.HashSet; import java.util.Set; import org.apache.ambari.server.controller.spi.Resource; @@ -44,10 +45,12 @@ public class RootServiceComponentResourceDefinition extends public String getSingularName() { return "component"; } - + @Override public Set<SubResourceDefinition> getSubResourceDefinitions() { - return Collections.singleton(new SubResourceDefinition( - Resource.Type.RootServiceHostComponent, Collections.singleton(Resource.Type.Host), true)); + Set<SubResourceDefinition> definitions = new HashSet<>(); + definitions.add(new SubResourceDefinition(Resource.Type.RootServiceHostComponent, Collections.singleton(Resource.Type.Host), true)); + definitions.add(new SubResourceDefinition(Resource.Type.RootServiceComponentConfiguration)); + return definitions; } } http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationRequestSwagger.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationRequestSwagger.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationRequestSwagger.java deleted file mode 100644 index 2dca9f5..0000000 --- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationRequestSwagger.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.ambari.server.api.services; - -import java.util.Map; - -import org.apache.ambari.server.controller.ApiModel; - -import io.swagger.annotations.ApiModelProperty; - -/** - * Request data model for {@link org.apache.ambari.server.api.services.AmbariConfigurationService} - */ -public interface AmbariConfigurationRequestSwagger extends ApiModel { - - @ApiModelProperty(name = "AmbariConfiguration") - AmbariConfigurationRequestInfo getAmbariConfiguration(); - - interface AmbariConfigurationRequestInfo { - @ApiModelProperty - String getCategoryName(); - - @ApiModelProperty - Map<String, Object> getProperties(); - } -} http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationResponseSwagger.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationResponseSwagger.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationResponseSwagger.java deleted file mode 100644 index c55ac1d..0000000 --- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationResponseSwagger.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.ambari.server.api.services; - -import java.util.Map; - -import org.apache.ambari.server.controller.ApiModel; - -import io.swagger.annotations.ApiModelProperty; - -/** - * Response data model for {@link org.apache.ambari.server.api.services.AmbariConfigurationService} - */ -public interface AmbariConfigurationResponseSwagger extends ApiModel { - - @ApiModelProperty(name = "AmbariConfiguration") - AmbariConfigurationResponseInfo getAmbariConfigurationResponse(); - - interface AmbariConfigurationResponseInfo { - @ApiModelProperty - Long getId(); - - @ApiModelProperty - Map<String, Object> getData(); - - @ApiModelProperty - String getType(); - } -} http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationService.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationService.java deleted file mode 100644 index 86ed666..0000000 --- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationService.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.ambari.server.api.services; - -import java.util.Collections; - -import javax.ws.rs.DELETE; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.PUT; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.core.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 org.apache.ambari.server.controller.spi.Resource; -import org.apache.http.HttpStatus; - -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiImplicitParam; -import io.swagger.annotations.ApiImplicitParams; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; - -/** - * Rest endpoint for managing ambari configurations. Supports CRUD operations. - * Ambari configurations are resources that relate to the ambari server instance even before a cluster is provisioned. - * - * Ambari configuration resources may be shared with components and services in the cluster - * (by recommending them as default values) - * - * Eg. LDAP configuration is stored as AmbariConfiguration. - * The request payload has the form: - * - * <pre> - * { - * "AmbariConfiguration": { - * "category": "ldap-configuration", - * "properties": { - * "authentication.ldap.primaryUrl": "localhost:33389" - * "authentication.ldap.secondaryUrl": "localhost:333" - * "authentication.ldap.baseDn": "dc=ambari,dc=apache,dc=org" - * // ...... - * } - * } - * } - * </pre> - */ -@Path("/ambariconfigs/") -@Api(value = "Ambari Configurations", description = "Endpoint for Ambari configuration related operations") -public class AmbariConfigurationService extends BaseService { - - private static final String AMBARI_CONFIGURATION_REQUEST_TYPE = - "org.apache.ambari.server.api.services.AmbariConfigurationRequestSwagger"; - - /** - * Creates an ambari configuration resource. - * - * @param body the payload in json format - * @param headers http headers - * @param uri request uri information - * @return - */ - @POST - @Produces(MediaType.TEXT_PLAIN) - @ApiOperation(value = "Creates an ambari configuration resource", - nickname = "AmbariConfigurationService#createAmbariConfiguration") - @ApiImplicitParams({ - @ApiImplicitParam(dataType = AMBARI_CONFIGURATION_REQUEST_TYPE, paramType = PARAM_TYPE_BODY) - }) - @ApiResponses({ - @ApiResponse(code = HttpStatus.SC_CREATED, message = MSG_SUCCESSFUL_OPERATION), - @ApiResponse(code = HttpStatus.SC_ACCEPTED, message = MSG_REQUEST_ACCEPTED), - @ApiResponse(code = HttpStatus.SC_BAD_REQUEST, message = MSG_INVALID_ARGUMENTS), - @ApiResponse(code = HttpStatus.SC_CONFLICT, message = MSG_RESOURCE_ALREADY_EXISTS), - @ApiResponse(code = HttpStatus.SC_UNAUTHORIZED, message = MSG_NOT_AUTHENTICATED), - @ApiResponse(code = HttpStatus.SC_FORBIDDEN, message = MSG_PERMISSION_DENIED), - @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR), - }) - public Response createAmbariConfiguration(String body, @Context HttpHeaders headers, @Context UriInfo uri) { - return handleRequest(headers, body, uri, Request.Type.POST, createResource(Resource.Type.AmbariConfiguration, - Collections.emptyMap())); - } - - @GET - @Produces(MediaType.TEXT_PLAIN) - @ApiOperation(value = "Retrieve all ambari configuration resources", - nickname = "AmbariConfigurationService#getAmbariConfigurations", - notes = "Returns all Ambari configurations.", - response = AmbariConfigurationResponseSwagger.class, - responseContainer = RESPONSE_CONTAINER_LIST) - @ApiImplicitParams({ - @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION, - defaultValue = "AmbariConfiguration/properties, AmbariConfiguration/category", - dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY), - @ApiImplicitParam(name = QUERY_SORT, value = QUERY_SORT_DESCRIPTION, - defaultValue = "AmbariConfiguration/category", - dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY), - @ApiImplicitParam(name = QUERY_PAGE_SIZE, value = QUERY_PAGE_SIZE_DESCRIPTION, defaultValue = DEFAULT_PAGE_SIZE, dataType = DATA_TYPE_INT, paramType = PARAM_TYPE_QUERY), - @ApiImplicitParam(name = QUERY_FROM, value = QUERY_FROM_DESCRIPTION, defaultValue = DEFAULT_FROM, dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY), - @ApiImplicitParam(name = QUERY_TO, value = QUERY_TO_DESCRIPTION, dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY) - }) - @ApiResponses(value = { - @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION), - @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR) - }) - public Response getAmbariConfigurations(String body, @Context HttpHeaders headers, @Context UriInfo uri) { - return handleRequest(headers, body, uri, Request.Type.GET, createResource(Resource.Type.AmbariConfiguration, - Collections.emptyMap())); - } - - @GET - @Path("{category}") - @Produces(MediaType.TEXT_PLAIN) - @ApiOperation(value = "Retrieve the details of an ambari configuration resource", - nickname = "AmbariConfigurationService#getAmbariConfiguration", - response = AmbariConfigurationResponseSwagger.class) - @ApiImplicitParams({ - @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION, defaultValue = "AmbariConfiguration/*", - dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY) - }) - @ApiResponses(value = { - @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION), - @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = MSG_RESOURCE_NOT_FOUND), - @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR) - }) - public Response getAmbariConfiguration(String body, @Context HttpHeaders headers, @Context UriInfo uri, - @PathParam("category") String category) { - return handleRequest(headers, body, uri, Request.Type.GET, createResource(Resource.Type.AmbariConfiguration, - Collections.singletonMap(Resource.Type.AmbariConfiguration, category))); - } - - @PUT - @Path("{category}") - @Produces(MediaType.TEXT_PLAIN) - @ApiOperation(value = "Updates ambari configuration resources ", - nickname = "AmbariConfigurationService#updateAmbariConfiguration") - @ApiImplicitParams({ - @ApiImplicitParam(dataType = AMBARI_CONFIGURATION_REQUEST_TYPE, paramType = PARAM_TYPE_BODY), - @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION, defaultValue = "AmbariConfiguration/*", - dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY) - }) - @ApiResponses({ - @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION), - @ApiResponse(code = HttpStatus.SC_ACCEPTED, message = MSG_REQUEST_ACCEPTED), - @ApiResponse(code = HttpStatus.SC_BAD_REQUEST, message = MSG_INVALID_ARGUMENTS), - @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = MSG_RESOURCE_NOT_FOUND), - @ApiResponse(code = HttpStatus.SC_UNAUTHORIZED, message = MSG_NOT_AUTHENTICATED), - @ApiResponse(code = HttpStatus.SC_FORBIDDEN, message = MSG_PERMISSION_DENIED), - @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR), - }) - public Response updateAmbariConfiguration(String body, @Context HttpHeaders headers, @Context UriInfo uri, - @PathParam("category") String category) { - return handleRequest(headers, body, uri, Request.Type.PUT, createResource(Resource.Type.AmbariConfiguration, - Collections.singletonMap(Resource.Type.AmbariConfiguration, category))); - } - - @DELETE - @Path("{category}") - @Produces(MediaType.TEXT_PLAIN) - @ApiOperation(value = "Deletes an ambari configuration resource", - nickname = "AmbariConfigurationService#deleteAmbariConfiguration") - @ApiResponses({ - @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION), - @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = MSG_RESOURCE_NOT_FOUND), - @ApiResponse(code = HttpStatus.SC_UNAUTHORIZED, message = MSG_NOT_AUTHENTICATED), - @ApiResponse(code = HttpStatus.SC_FORBIDDEN, message = MSG_PERMISSION_DENIED), - @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR), - }) - public Response deleteAmbariConfiguration(String body, @Context HttpHeaders headers, @Context UriInfo uri, - @PathParam("category") String category) { - return handleRequest(headers, body, uri, Request.Type.DELETE, createResource(Resource.Type.AmbariConfiguration, - Collections.singletonMap(Resource.Type.AmbariConfiguration, category))); - } - -} http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java index 46ee65a..b1eba8f 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java @@ -43,7 +43,7 @@ import org.apache.ambari.server.AmbariException; import org.apache.ambari.server.ParentObjectNotFoundException; import org.apache.ambari.server.StackAccessException; import org.apache.ambari.server.configuration.Configuration; -import org.apache.ambari.server.controller.RootServiceResponseFactory.Services; +import org.apache.ambari.server.controller.RootService; import org.apache.ambari.server.controller.utilities.PropertyHelper; import org.apache.ambari.server.customactions.ActionDefinition; import org.apache.ambari.server.customactions.ActionDefinitionManager; @@ -1179,7 +1179,7 @@ public class AmbariMetaInfo { String componentName = definition.getComponentName(); // the AMBARI service is special, skip it here - if (Services.AMBARI.name().equals(serviceName)) { + if (RootService.AMBARI.name().equals(serviceName)) { continue; } http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootServiceComponentConfigurationRequestSwagger.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootServiceComponentConfigurationRequestSwagger.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootServiceComponentConfigurationRequestSwagger.java new file mode 100644 index 0000000..dffa125 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootServiceComponentConfigurationRequestSwagger.java @@ -0,0 +1,43 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ambari.server.api.services; + +import java.util.Map; + +import org.apache.ambari.server.controller.ApiModel; + +import io.swagger.annotations.ApiModelProperty; + +/** + * Request data model for {@link org.apache.ambari.server.api.services.RootServiceComponentConfigurationService} + */ +public interface RootServiceComponentConfigurationRequestSwagger extends ApiModel { + + @ApiModelProperty(name = "Configuration") + RootServiceComponentConfigurationRequestInfo getRootServiceComponentConfigurationRequestInfo(); + + interface RootServiceComponentConfigurationRequestInfo { + @ApiModelProperty + String getServiceName(); + + @ApiModelProperty + String getComponentName(); + + @ApiModelProperty + String getCategoryName(); + + @ApiModelProperty + Map<String, String> getProperties(); + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootServiceComponentConfigurationResponseSwagger.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootServiceComponentConfigurationResponseSwagger.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootServiceComponentConfigurationResponseSwagger.java new file mode 100644 index 0000000..fb3c09d --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootServiceComponentConfigurationResponseSwagger.java @@ -0,0 +1,43 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ambari.server.api.services; + +import java.util.Map; + +import org.apache.ambari.server.controller.ApiModel; + +import io.swagger.annotations.ApiModelProperty; + +/** + * Response data model for {@link org.apache.ambari.server.api.services.RootServiceComponentConfigurationService} + */ +public interface RootServiceComponentConfigurationResponseSwagger extends ApiModel { + + @ApiModelProperty(name = "Configuration") + RootServiceComponentConfigurationResponseInfo getRootServiceComponentConfigurationResponseInfo(); + + interface RootServiceComponentConfigurationResponseInfo { + @ApiModelProperty + String getServiceName(); + + @ApiModelProperty + String getComponentName(); + + @ApiModelProperty + String getCategoryName(); + + @ApiModelProperty + Map<String, Object> getProperties(); + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootServiceComponentConfigurationService.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootServiceComponentConfigurationService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootServiceComponentConfigurationService.java new file mode 100644 index 0000000..c7c37a6 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootServiceComponentConfigurationService.java @@ -0,0 +1,226 @@ +/* + * 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. + */ + +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ambari.server.api.services; + +import java.util.HashMap; +import java.util.Map; + +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.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 org.apache.ambari.server.api.resources.ResourceInstance; +import org.apache.ambari.server.controller.spi.Resource; +import org.apache.http.HttpStatus; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; + +/** + * Rest endpoint for managing ambari root service component configurations. Supports CRUD operations. + * Ambari configurations are resources that relate to the ambari server instance even before a cluster is provisioned. + * <p> + * Ambari configuration resources may be shared with components and services in the cluster + * (by recommending them as default values) + * <p> + * Eg. LDAP configuration is stored as Configuration. + * The request payload has the form: + * <p> + * <pre> + * { + * "Configuration": { + * "service_name": "AMBARI", + * "component_name": "AMBARI_SERVER", + * "category": "ldap-configuration", + * "properties": { + * "authentication.ldap.primaryUrl": "localhost:33389" + * "authentication.ldap.secondaryUrl": "localhost:333" + * "authentication.ldap.baseDn": "dc=ambari,dc=apache,dc=org" + * // ...... + * } + * } + * } + * </pre> + */ +@Api(value = "Root Service Configurations", description = "Endpoint for Ambari root service component configuration related operations") +public class RootServiceComponentConfigurationService extends BaseService { + + private static final String REQUEST_TYPE = + "org.apache.ambari.server.api.services.RootServiceComponentConfigurationRequestSwagger"; + + private final String serviceName; + private final String componentName; + + public RootServiceComponentConfigurationService(String serviceName, String componentName) { + this.serviceName = serviceName; + this.componentName = componentName; + } + + /** + * Creates a root service component configuration resource. + * + * @param body the payload in json format + * @param headers http headers + * @param uri request uri information + * @return + */ + @POST + @Produces(MediaType.TEXT_PLAIN) + @ApiOperation(value = "Creates a root service component configuration resource", + nickname = "RootServiceComponentConfigurationService#createConfiguration") + @ApiImplicitParams({ + @ApiImplicitParam(dataType = REQUEST_TYPE, paramType = PARAM_TYPE_BODY) + }) + @ApiResponses({ + @ApiResponse(code = HttpStatus.SC_CREATED, message = MSG_SUCCESSFUL_OPERATION), + @ApiResponse(code = HttpStatus.SC_ACCEPTED, message = MSG_REQUEST_ACCEPTED), + @ApiResponse(code = HttpStatus.SC_BAD_REQUEST, message = MSG_INVALID_ARGUMENTS), + @ApiResponse(code = HttpStatus.SC_CONFLICT, message = MSG_RESOURCE_ALREADY_EXISTS), + @ApiResponse(code = HttpStatus.SC_UNAUTHORIZED, message = MSG_NOT_AUTHENTICATED), + @ApiResponse(code = HttpStatus.SC_FORBIDDEN, message = MSG_PERMISSION_DENIED), + @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR), + }) + public Response createConfiguration(String body, @Context HttpHeaders headers, @Context UriInfo uri) { + return handleRequest(headers, body, uri, Request.Type.POST, createResource(null)); + } + + @GET + @Produces(MediaType.TEXT_PLAIN) + @ApiOperation(value = "Retrieve all root service component configuration resources", + nickname = "RootServiceComponentConfigurationService#getConfigurations", + notes = "Returns all root service component configurations.", + response = RootServiceComponentConfigurationResponseSwagger.class, + responseContainer = RESPONSE_CONTAINER_LIST) + @ApiImplicitParams({ + @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION, + defaultValue = "Configuration/properties, Configuration/category, Configuration/component_name, Configuration/service_name", + dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY), + @ApiImplicitParam(name = QUERY_SORT, value = QUERY_SORT_DESCRIPTION, + defaultValue = "Configuration/category", + dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY), + @ApiImplicitParam(name = QUERY_PAGE_SIZE, value = QUERY_PAGE_SIZE_DESCRIPTION, defaultValue = DEFAULT_PAGE_SIZE, dataType = DATA_TYPE_INT, paramType = PARAM_TYPE_QUERY), + @ApiImplicitParam(name = QUERY_FROM, value = QUERY_FROM_DESCRIPTION, defaultValue = DEFAULT_FROM, dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY), + @ApiImplicitParam(name = QUERY_TO, value = QUERY_TO_DESCRIPTION, dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY) + }) + @ApiResponses(value = { + @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION), + @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR) + }) + public Response getConfigurations(String body, @Context HttpHeaders headers, @Context UriInfo uri) { + return handleRequest(headers, body, uri, Request.Type.GET, createResource(null)); + } + + @GET + @Path("{category}") + @Produces(MediaType.TEXT_PLAIN) + @ApiOperation(value = "Retrieve the details of a root service component configuration resource", + nickname = "RootServiceComponentConfigurationService#getConfiguration", + response = RootServiceComponentConfigurationResponseSwagger.class) + @ApiImplicitParams({ + @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION, defaultValue = "Configuration/*", + dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY) + }) + @ApiResponses(value = { + @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION), + @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = MSG_RESOURCE_NOT_FOUND), + @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR) + }) + public Response getConfiguration(String body, @Context HttpHeaders headers, @Context UriInfo uri, + @PathParam("category") String category) { + return handleRequest(headers, body, uri, Request.Type.GET, createResource(category)); + } + + @PUT + @Path("{category}") + @Produces(MediaType.TEXT_PLAIN) + @ApiOperation(value = "Updates root service component configuration resources ", + nickname = "RootServiceComponentConfigurationService#updateConfiguration") + @ApiImplicitParams({ + @ApiImplicitParam(dataType = REQUEST_TYPE, paramType = PARAM_TYPE_BODY), + @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION, defaultValue = "Configuration/*", + dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY) + }) + @ApiResponses({ + @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION), + @ApiResponse(code = HttpStatus.SC_ACCEPTED, message = MSG_REQUEST_ACCEPTED), + @ApiResponse(code = HttpStatus.SC_BAD_REQUEST, message = MSG_INVALID_ARGUMENTS), + @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = MSG_RESOURCE_NOT_FOUND), + @ApiResponse(code = HttpStatus.SC_UNAUTHORIZED, message = MSG_NOT_AUTHENTICATED), + @ApiResponse(code = HttpStatus.SC_FORBIDDEN, message = MSG_PERMISSION_DENIED), + @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR), + }) + public Response updateConfiguration(String body, @Context HttpHeaders headers, @Context UriInfo uri, + @PathParam("category") String category) { + return handleRequest(headers, body, uri, Request.Type.PUT, createResource(category)); + } + + @DELETE + @Path("{category}") + @Produces(MediaType.TEXT_PLAIN) + @ApiOperation(value = "Deletes a root service component configuration resource", + nickname = "RootServiceComponentConfigurationService#deleteConfiguration") + @ApiResponses({ + @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION), + @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = MSG_RESOURCE_NOT_FOUND), + @ApiResponse(code = HttpStatus.SC_UNAUTHORIZED, message = MSG_NOT_AUTHENTICATED), + @ApiResponse(code = HttpStatus.SC_FORBIDDEN, message = MSG_PERMISSION_DENIED), + @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR), + }) + public Response deleteConfiguration(String body, @Context HttpHeaders headers, @Context UriInfo uri, + @PathParam("category") String category) { + return handleRequest(headers, body, uri, Request.Type.DELETE, createResource(category)); + } + + ResourceInstance createResource(String categoryName) { + Map<Resource.Type, String> mapIds = new HashMap<>(); + mapIds.put(Resource.Type.RootService, serviceName); + mapIds.put(Resource.Type.RootServiceComponent, componentName); + mapIds.put(Resource.Type.RootServiceComponentConfiguration, categoryName); + + return createResource(Resource.Type.RootServiceComponentConfiguration, mapIds); + } + +} http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootServiceService.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootServiceService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootServiceService.java index 5afb7dc..1ab2797 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootServiceService.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootServiceService.java @@ -297,6 +297,13 @@ public class RootServiceService extends BaseService { return handleRequest(headers, body, ui, Request.Type.GET, resource); } + @Path("{serviceName}/components/{componentName}/configurations") + public RootServiceComponentConfigurationService getAmbariServerConfigurationHandler(@Context javax.ws.rs.core.Request request, + @PathParam("serviceName") String serviceName, + @PathParam("componentName") String componentName) { + return new RootServiceComponentConfigurationService(serviceName, componentName); + } + protected ResourceInstance createServiceResource(String serviceName) { Map<Resource.Type, String> mapIds = Collections.singletonMap(Resource.Type.RootService, serviceName); return createResource(Resource.Type.RootService, mapIds); http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/AmbariConfiguration.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/AmbariConfiguration.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/AmbariConfiguration.java index e9f0b1e..7bac65e 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/AmbariConfiguration.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/AmbariConfiguration.java @@ -26,7 +26,7 @@ public class AmbariConfiguration { */ private String type; - private Map<String, Object> properties = null; + private Map<String, String> properties = null; public String getType() { return type; @@ -36,11 +36,11 @@ public class AmbariConfiguration { this.type = type; } - public Map<String, Object> getProperties() { + public Map<String, String> getProperties() { return properties; } - public void setProperties(Map<String, Object> data) { + public void setProperties(Map<String, String> data) { this.properties = data; } } http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationRequest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationRequest.java index 2e478c4..0e065e5 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationRequest.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationRequest.java @@ -22,7 +22,7 @@ import com.google.gson.annotations.SerializedName; */ public class LdapConfigurationRequest { - @SerializedName("AmbariConfiguration") + @SerializedName("Configuration") private AmbariConfiguration ambariConfiguration; @SerializedName("RequestInfo") http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationService.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationService.java index 00c13f6..22784cd 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationService.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationService.java @@ -40,7 +40,7 @@ import javax.ws.rs.core.Response; import org.apache.ambari.annotations.ApiIgnore; import org.apache.ambari.server.StaticallyInject; -import org.apache.ambari.server.api.services.AmbariConfigurationService; +import org.apache.ambari.server.api.services.BaseService; import org.apache.ambari.server.api.services.Result; import org.apache.ambari.server.api.services.ResultImpl; import org.apache.ambari.server.api.services.ResultStatus; @@ -64,7 +64,7 @@ import com.google.common.collect.Sets; */ @StaticallyInject @Path("/ldapconfigs/") -public class LdapConfigurationService extends AmbariConfigurationService { +public class LdapConfigurationService extends BaseService { private static final Logger LOGGER = LoggerFactory.getLogger(LdapConfigurationService.class); @@ -133,7 +133,7 @@ public class LdapConfigurationService extends AmbariConfigurationService { } private void setResult(Set<String> groups, Result result) { - Resource resource = new ResourceImpl(Resource.Type.AmbariConfiguration); + Resource resource = new ResourceImpl(Resource.Type.RootServiceComponentConfiguration); resource.setProperty("groups", groups); result.getResultTree().addChild(resource, "payload"); } http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java index 91edf86..17591ec 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java @@ -45,6 +45,8 @@ import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorException; import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRequest; import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorResponse; import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRunner; +import org.apache.ambari.server.controller.RootComponent; +import org.apache.ambari.server.controller.RootService; import org.apache.ambari.server.controller.spi.Resource; import org.apache.ambari.server.state.ServiceInfo; import org.apache.ambari.server.utils.DateUtils; @@ -84,7 +86,9 @@ public abstract class StackAdvisorCommand<T extends StackAdvisorResponse> extend + ",services/configurations/dependencies/StackConfigurationDependency/dependency_name" + ",services/configurations/dependencies/StackConfigurationDependency/dependency_type,services/configurations/StackConfigurations/type" + "&services/StackServices/service_name.in(%s)"; - private static final String GET_LDAP_CONFIG_URI = "/api/v1/configurations?AmbariConfiguration/type=ldap&fields=AmbariConfiguration/*"; + private static final String GET_AMBARI_LDAP_CONFIG_URI = "/api/v1/services/AMBARI/components/AMBARI_SERVER/configurations" + + "?Configuration/category=ldap-configuration" + + "&fields=Configuration/properties"; private static final String SERVICES_PROPERTY = "services"; private static final String SERVICES_COMPONENTS_PROPERTY = "components"; private static final String CONFIG_GROUPS_PROPERTY = "config-groups"; @@ -96,7 +100,7 @@ public abstract class StackAdvisorCommand<T extends StackAdvisorResponse> extend private static final String CHANGED_CONFIGURATIONS_PROPERTY = "changed-configurations"; private static final String USER_CONTEXT_PROPERTY = "user-context"; private static final String AMBARI_SERVER_CONFIGURATIONS_PROPERTY = "ambari-server-properties"; - protected static final String LDAP_CONFIGURATION_PROPERTY = "ldap-configuration"; + static final String LDAP_CONFIGURATION_PROPERTY = "ldap-configuration"; private File recommendationsDir; private String recommendationsArtifactsLifetime; @@ -176,17 +180,18 @@ public abstract class StackAdvisorCommand<T extends StackAdvisorResponse> extend /** * Retrieves the LDAP configuration if exists and adds it to services.json + * * @param root The JSON document that will become service.json when passed to the stack advisor engine * @throws StackAdvisorException * @throws IOException */ - protected void populateLdapConfiguration(ObjectNode root) throws StackAdvisorException, IOException { - Response response = handleRequest(null, null, new LocalUriInfo(GET_LDAP_CONFIG_URI), Request.Type.GET, + void populateLdapConfiguration(ObjectNode root) throws StackAdvisorException, IOException { + Response response = handleRequest(null, null, new LocalUriInfo(GET_AMBARI_LDAP_CONFIG_URI), Request.Type.GET, createConfigResource()); if (response.getStatus() != Status.OK.getStatusCode()) { String message = String.format( - "Error occured during retrieving ldap configuration, status=%s, response=%s", + "Error occurred during retrieving ldap configuration, status=%s, response=%s", response.getStatus(), (String) response.getEntity()); LOG.warn(message); throw new StackAdvisorException(message); @@ -198,25 +203,28 @@ public abstract class StackAdvisorCommand<T extends StackAdvisorResponse> extend } JsonNode ldapConfigRoot = mapper.readTree(ldapConfigJSON); - ArrayNode ldapConfigs = ((ArrayNode)ldapConfigRoot.get("items")); + ArrayNode ldapConfigs = ((ArrayNode) ldapConfigRoot.get("items")); int numConfigs = ldapConfigs.size(); - // Zero or one config may exist - switch (numConfigs) { - case 0: - LOG.debug("No LDAP config is stored in the DB"); - break; - case 1: - ArrayNode ldapConfigData = (ArrayNode)ldapConfigs.get(0).get("AmbariConfiguration").get("data"); - if (ldapConfigData.size() == 0) { - throw new StackAdvisorException("No configuration data for LDAP configuration."); - } - if (ldapConfigData.size() > 1) { - throw new StackAdvisorException("Ambigous configuration data for LDAP configuration."); - } - root.put(LDAP_CONFIGURATION_PROPERTY, ldapConfigData.get(0)); - break; - default: - throw new StackAdvisorException(String.format("Multiple (%s) LDAP configs are found in the DB.", numConfigs)); + + if (numConfigs == 1) { + JsonNode ldapConfigItem = ldapConfigs.get(0); + if (ldapConfigItem == null) { + throw new StackAdvisorException("Unexpected JSON document encountered: missing data"); + } + + JsonNode ldapConfiguration = ldapConfigItem.get("Configuration"); + if (ldapConfiguration == null) { + throw new StackAdvisorException("Unexpected JSON document encountered: missing the Configuration object"); + } + + JsonNode ldapConfigurationProperties = ldapConfiguration.get("properties"); + if (ldapConfigurationProperties == null) { + throw new StackAdvisorException("Unexpected JSON document encountered: missing the Configuration/properties object"); + } + + root.put(LDAP_CONFIGURATION_PROPERTY, ldapConfigurationProperties); + } else if (numConfigs > 1) { + throw new StackAdvisorException(String.format("Multiple (%s) LDAP configs are found in the DB.", numConfigs)); } } @@ -486,8 +494,12 @@ public abstract class StackAdvisorCommand<T extends StackAdvisorResponse> extend return createResource(Resource.Type.Host, mapIds); } - protected ResourceInstance createConfigResource() { - return createResource(Resource.Type.AmbariConfiguration, new HashMap<>()); + private ResourceInstance createConfigResource() { + Map<Resource.Type, String> mapIds = new HashMap<>(); + mapIds.put(Resource.Type.RootService, RootService.AMBARI.name()); + mapIds.put(Resource.Type.RootServiceComponent, RootComponent.AMBARI_SERVER.name()); + + return createResource(Resource.Type.RootServiceComponentConfiguration, mapIds); } http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/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 1425e1b..ed7513f 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 @@ -63,7 +63,6 @@ import org.apache.ambari.server.configuration.Configuration; import org.apache.ambari.server.configuration.Configuration.ConnectionPoolType; import org.apache.ambari.server.configuration.Configuration.DatabaseType; import org.apache.ambari.server.controller.internal.AlertTargetResourceProvider; -import org.apache.ambari.server.controller.internal.AmbariConfigurationResourceProvider; import org.apache.ambari.server.controller.internal.ClusterStackVersionResourceProvider; import org.apache.ambari.server.controller.internal.ComponentResourceProvider; import org.apache.ambari.server.controller.internal.CredentialResourceProvider; @@ -73,6 +72,7 @@ import org.apache.ambari.server.controller.internal.HostResourceProvider; import org.apache.ambari.server.controller.internal.KerberosDescriptorResourceProvider; import org.apache.ambari.server.controller.internal.MemberResourceProvider; import org.apache.ambari.server.controller.internal.RepositoryVersionResourceProvider; +import org.apache.ambari.server.controller.internal.RootServiceComponentConfigurationResourceProvider; import org.apache.ambari.server.controller.internal.ServiceResourceProvider; import org.apache.ambari.server.controller.internal.UpgradeResourceProvider; import org.apache.ambari.server.controller.internal.ViewInstanceResourceProvider; @@ -471,10 +471,10 @@ public class ControllerModule extends AbstractModule { .implement(ResourceProvider.class, Names.named("credential"), CredentialResourceProvider.class) .implement(ResourceProvider.class, Names.named("kerberosDescriptor"), KerberosDescriptorResourceProvider.class) .implement(ResourceProvider.class, Names.named("upgrade"), UpgradeResourceProvider.class) - .implement(ResourceProvider.class, Names.named("ambariConfiguration"), AmbariConfigurationResourceProvider.class) .implement(ResourceProvider.class, Names.named("clusterStackVersion"), ClusterStackVersionResourceProvider.class) .implement(ResourceProvider.class, Names.named("alertTarget"), AlertTargetResourceProvider.class) .implement(ResourceProvider.class, Names.named("viewInstance"), ViewInstanceResourceProvider.class) + .implement(ResourceProvider.class, Names.named("rootServiceHostComponentConfiguration"), RootServiceComponentConfigurationResourceProvider.class) .build(ResourceProviderFactory.class)); install(new FactoryModuleBuilder().implement( http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/ambari-server/src/main/java/org/apache/ambari/server/controller/MaintenanceStateHelper.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/MaintenanceStateHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/MaintenanceStateHelper.java index d9a585f..1ffe841 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/MaintenanceStateHelper.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/MaintenanceStateHelper.java @@ -24,7 +24,6 @@ import java.util.Set; import org.apache.ambari.server.AmbariException; import org.apache.ambari.server.HostNotFoundException; -import org.apache.ambari.server.controller.RootServiceResponseFactory.Services; import org.apache.ambari.server.controller.internal.RequestOperationLevel; import org.apache.ambari.server.controller.internal.RequestResourceFilter; import org.apache.ambari.server.controller.spi.Resource; @@ -265,7 +264,7 @@ public class MaintenanceStateHelper { } // the AMBARI service is not a real service; it's never in MM - if( StringUtils.equals(Services.AMBARI.name(), serviceName)){ + if( StringUtils.equals(RootService.AMBARI.name(), serviceName)){ return MaintenanceState.OFF; } http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/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 711ae10..f6ca16b 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 @@ -68,8 +68,8 @@ public interface ResourceProviderFactory { @Named("upgrade") UpgradeResourceProvider getUpgradeResourceProvider(AmbariManagementController managementController); - @Named("ambariConfiguration") - ResourceProvider getAmbariConfigurationResourceProvider(); + @Named("rootServiceHostComponentConfiguration") + ResourceProvider getRootServiceHostComponentConfigurationResourceProvider(); @Named("clusterStackVersion") ClusterStackVersionResourceProvider getClusterStackVersionResourceProvider(AmbariManagementController managementController); http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/ambari-server/src/main/java/org/apache/ambari/server/controller/RootComponent.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/RootComponent.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/RootComponent.java new file mode 100644 index 0000000..74cdfcf --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/RootComponent.java @@ -0,0 +1,27 @@ +/* + * 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; + +/** + * RootComponent is an enumeration of root-level components. + */ +public enum RootComponent { + AMBARI_SERVER, + AMBARI_AGENT +} http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/ambari-server/src/main/java/org/apache/ambari/server/controller/RootService.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/RootService.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/RootService.java new file mode 100644 index 0000000..22f571d --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/RootService.java @@ -0,0 +1,36 @@ +/* + * 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; + +/** + * RootService is an enumeration of root-level services. + */ +public enum RootService { + AMBARI(RootComponent.values()); + + private final RootComponent[] components; + + RootService(RootComponent[] components) { + this.components = components; + } + + public RootComponent[] getComponents() { + return components; + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/ambari-server/src/main/java/org/apache/ambari/server/controller/RootServiceResponseFactory.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/RootServiceResponseFactory.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/RootServiceResponseFactory.java index ad9ed20..63d41fd 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/RootServiceResponseFactory.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/RootServiceResponseFactory.java @@ -62,9 +62,9 @@ public class RootServiceResponseFactory extends serviceName = request.getServiceName(); if (serviceName != null) { - Services service; + RootService service; try { - service = Services.valueOf(serviceName); + service = RootService.valueOf(serviceName); } catch (IllegalArgumentException ex) { throw new ObjectNotFoundException("Root service name: " + serviceName); @@ -74,7 +74,7 @@ public class RootServiceResponseFactory extends } else { response = new HashSet<>(); - for (Services service: Services.values()) + for (RootService service: RootService.values()) response.add(new RootServiceResponse(service.toString())); } return response; @@ -87,10 +87,10 @@ public class RootServiceResponseFactory extends String serviceName = request.getServiceName(); String componentName = request.getComponentName(); - Services service; + RootService service; try { - service = Services.valueOf(serviceName); + service = RootService.valueOf(serviceName); } catch (IllegalArgumentException ex) { throw new ObjectNotFoundException("Root service name: " + serviceName); @@ -100,9 +100,9 @@ public class RootServiceResponseFactory extends } if (componentName != null) { - Components component; + RootComponent component; try { - component = Components.valueOf(componentName); + component = RootComponent.valueOf(componentName); if (!ArrayUtils.contains(service.getComponents(), component)) throw new ObjectNotFoundException("No component name: " + componentName + "in service: " + serviceName); } @@ -114,7 +114,7 @@ public class RootServiceResponseFactory extends getComponentProperties(componentName))); } else { - for (Components component: service.getComponents()) + for (RootComponent component: service.getComponents()) response.add(new RootServiceComponentResponse(serviceName, component.toString(), getComponentVersion(component.name(), null), getComponentProperties(component.name()))); @@ -123,7 +123,7 @@ public class RootServiceResponseFactory extends } private String getComponentVersion(String componentName, HostResponse host) { - Components component = Components.valueOf(componentName); + RootComponent component = RootComponent.valueOf(componentName); String componentVersion; switch (component) { @@ -150,10 +150,10 @@ public class RootServiceResponseFactory extends Map<String, String> response; Set<String> propertiesToHideInResponse; - Components component = null; + RootComponent component = null; if (componentName != null) { - component = Components.valueOf(componentName); + component = RootComponent.valueOf(componentName); switch (component) { case AMBARI_SERVER: @@ -176,24 +176,6 @@ public class RootServiceResponseFactory extends return response; } - - public enum Services { - AMBARI(Components.values()); - private Components[] components; - - Services(Components[] components) { - this.components = components; - } - - public Components[] getComponents() { - return components; - } - } - - public enum Components { - AMBARI_SERVER, AMBARI_AGENT - } - @Override public Set<RootServiceHostComponentResponse> getRootServiceHostComponent(RootServiceHostComponentRequest request, Set<HostResponse> hosts) throws AmbariException { Set<RootServiceHostComponentResponse> response = new HashSet<>(); @@ -208,7 +190,7 @@ public class RootServiceResponseFactory extends Set<HostResponse> filteredHosts = new HashSet<>(hosts); //Make some filtering of hosts if need - if (component.getComponentName().equals(Components.AMBARI_SERVER.name())) { + if (component.getComponentName().equals(RootComponent.AMBARI_SERVER.name())) { CollectionUtils.filter(filteredHosts, new Predicate() { @Override public boolean evaluate(Object arg0) { @@ -220,7 +202,7 @@ public class RootServiceResponseFactory extends for (HostResponse host : filteredHosts) { String state; - if (component.getComponentName().equals(Components.AMBARI_SERVER.name())) { + if (component.getComponentName().equals(RootComponent.AMBARI_SERVER.name())) { state = RUNNING_STATE; } else { state = host.getHostState().toString(); http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/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 1dc0841..cc2548c 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 @@ -206,6 +206,8 @@ public abstract class AbstractControllerResourceProvider extends AbstractAuthori return new RootServiceResourceProvider(propertyIds, keyPropertyIds, managementController); case RootServiceComponent: return new RootServiceComponentResourceProvider(propertyIds, keyPropertyIds, managementController); + case RootServiceComponentConfiguration: + return resourceProviderFactory.getRootServiceHostComponentConfigurationResourceProvider(); case RootServiceHostComponent: return new RootServiceHostComponentResourceProvider(propertyIds, keyPropertyIds, managementController); case ConfigGroup: @@ -254,8 +256,6 @@ public abstract class AbstractControllerResourceProvider extends AbstractAuthori return new ClusterKerberosDescriptorResourceProvider(managementController); case LoggingQuery: return new LoggingResourceProvider(propertyIds, keyPropertyIds, managementController); - case AmbariConfiguration: - return resourceProviderFactory.getAmbariConfigurationResourceProvider(); case AlertTarget: return resourceProviderFactory.getAlertTargetResourceProvider(); case ViewInstance: http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariConfigurationResourceProvider.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariConfigurationResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariConfigurationResourceProvider.java deleted file mode 100644 index a24400d..0000000 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariConfigurationResourceProvider.java +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.ambari.server.controller.internal; - -import java.util.Arrays; -import java.util.Collections; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; - -import org.apache.ambari.server.AmbariException; -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.RequestStatus; -import org.apache.ambari.server.controller.spi.Resource; -import org.apache.ambari.server.controller.spi.ResourceAlreadyExistsException; -import org.apache.ambari.server.controller.spi.SystemException; -import org.apache.ambari.server.controller.spi.UnsupportedPropertyException; -import org.apache.ambari.server.controller.utilities.PredicateHelper; -import org.apache.ambari.server.controller.utilities.PropertyHelper; -import org.apache.ambari.server.events.AmbariConfigurationChangedEvent; -import org.apache.ambari.server.events.publishers.AmbariEventPublisher; -import org.apache.ambari.server.orm.dao.AmbariConfigurationDAO; -import org.apache.ambari.server.orm.entities.AmbariConfigurationEntity; -import org.apache.ambari.server.security.authorization.RoleAuthorization; -import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.lang.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.inject.Inject; - -/** - * Resource provider for AmbariConfiguration resources. - */ -public class AmbariConfigurationResourceProvider extends AbstractAuthorizedResourceProvider { - - private static final Logger LOGGER = LoggerFactory.getLogger(AmbariConfigurationResourceProvider.class); - - static final String AMBARI_CONFIGURATION_CATEGORY_PROPERTY_ID = PropertyHelper.getPropertyId("AmbariConfiguration", "category"); - static final String AMBARI_CONFIGURATION_PROPERTIES_PROPERTY_ID = PropertyHelper.getPropertyId("AmbariConfiguration", "properties"); - - private static final Set<String> PROPERTIES = Collections.unmodifiableSet( - new HashSet<>(Arrays.asList( - AMBARI_CONFIGURATION_CATEGORY_PROPERTY_ID, - AMBARI_CONFIGURATION_PROPERTIES_PROPERTY_ID) - ) - ); - - private static final Map<Resource.Type, String> PK_PROPERTY_MAP = Collections.unmodifiableMap( - Collections.singletonMap(Resource.Type.AmbariConfiguration, AMBARI_CONFIGURATION_CATEGORY_PROPERTY_ID) - ); - - private static final Set<String> PK_PROPERTY_IDS = Collections.unmodifiableSet( - new HashSet<>(PK_PROPERTY_MAP.values()) - ); - - @Inject - private AmbariConfigurationDAO ambariConfigurationDAO; - - @Inject - private AmbariEventPublisher publisher; - - public AmbariConfigurationResourceProvider() { - super(PROPERTIES, PK_PROPERTY_MAP); - - Set<RoleAuthorization> authorizations = EnumSet.of(RoleAuthorization.AMBARI_MANAGE_CONFIGURATION); - setRequiredCreateAuthorizations(authorizations); - setRequiredDeleteAuthorizations(authorizations); - setRequiredUpdateAuthorizations(authorizations); - setRequiredGetAuthorizations(authorizations); - } - - @Override - protected Set<String> getPKPropertyIds() { - return PK_PROPERTY_IDS; - } - - @Override - public RequestStatus createResourcesAuthorized(Request request) - throws SystemException, UnsupportedPropertyException, ResourceAlreadyExistsException, NoSuchParentResourceException { - - createOrAddProperties(null, request.getProperties(), true); - - return getRequestStatus(null); - } - - @Override - protected Set<Resource> getResourcesAuthorized(Request request, Predicate predicate) throws SystemException, - UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException { - - return getResources(new Command<Set<Resource>>() { - @Override - public Set<Resource> invoke() throws AmbariException { - Set<Resource> resources = new HashSet<>(); - Set<String> requestedIds = getRequestPropertyIds(request, predicate); - - if (CollectionUtils.isEmpty(requestedIds)) { - requestedIds = PROPERTIES; - } - - if (predicate == null) { - Set<Resource> _resources = getAmbariConfigurationResources(requestedIds, null); - if (!CollectionUtils.isEmpty(_resources)) { - resources.addAll(_resources); - } - } else { - for (Map<String, Object> propertyMap : getPropertyMaps(predicate)) { - Set<Resource> _resources = getAmbariConfigurationResources(requestedIds, propertyMap); - if (!CollectionUtils.isEmpty(_resources)) { - resources.addAll(_resources); - } - } - } - - return resources; - } - }); - } - - - @Override - protected RequestStatus deleteResourcesAuthorized(Request request, Predicate predicate) throws SystemException, - UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException { - - String categoryName = (String) PredicateHelper.getProperties(predicate).get(AMBARI_CONFIGURATION_CATEGORY_PROPERTY_ID); - - if (null == categoryName) { - LOGGER.debug("No resource id provided in the request"); - } else { - LOGGER.debug("Deleting Ambari configuration with id: {}", categoryName); - try { - ambariConfigurationDAO.removeByCategory(categoryName); - } catch (IllegalStateException e) { - throw new NoSuchResourceException(e.getMessage()); - } - } - - // notify subscribers about the configuration changes - publisher.publish(new AmbariConfigurationChangedEvent(categoryName)); - return getRequestStatus(null); - } - - @Override - protected RequestStatus updateResourcesAuthorized(Request request, Predicate predicate) - throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException { - - String categoryName = (String) PredicateHelper.getProperties(predicate).get(AMBARI_CONFIGURATION_CATEGORY_PROPERTY_ID); - createOrAddProperties(categoryName, request.getProperties(), false); - - return getRequestStatus(null); - } - - /** - * Retrieves groups of properties from the request data and create or updates them as needed. - * <p> - * Each group of properties is expected to have a category (<code>AmbariConfiguration/category</code>) - * value and one or more property (<code>AmbariConfiguration/properties/property.name</code>) values. - * If a category cannot be determined from the propery set, the default category value (passed in) - * is used. If a default category is set, it is assumed that it was parsed from the request predicate - * (if availabe). - * - * @param defaultCategoryName the default category to use if needed - * @param requestProperties a collection of property maps parsed from the request - * @param removePropertiesIfNotSpecified <code>true</code> to remove existing properties that have not been specifed in the request; <code>false</code> append or update the existing set of properties with values from the request - * @throws SystemException if an error occurs saving the configuration data - */ - private void createOrAddProperties(String defaultCategoryName, Set<Map<String, Object>> requestProperties, boolean removePropertiesIfNotSpecified) - throws SystemException { - // set of resource properties (each entry in the set belongs to a different resource) - if (requestProperties != null) { - for (Map<String, Object> resourceProperties : requestProperties) { - Map<String, Map<String, String>> entityMap = parseProperties(defaultCategoryName, resourceProperties); - - if (entityMap != null) { - for (Map.Entry<String, Map<String, String>> entry : entityMap.entrySet()) { - String categoryName = entry.getKey(); - - if (ambariConfigurationDAO.reconcileCategory(categoryName, entry.getValue(), removePropertiesIfNotSpecified)) { - // notify subscribers about the configuration changes - publisher.publish(new AmbariConfigurationChangedEvent(categoryName)); - } - } - } - } - } - } - - private Resource toResource(String categoryName, Map<String, String> properties, Set<String> requestedIds) { - Resource resource = new ResourceImpl(Resource.Type.AmbariConfiguration); - setResourceProperty(resource, AMBARI_CONFIGURATION_CATEGORY_PROPERTY_ID, categoryName, requestedIds); - setResourceProperty(resource, AMBARI_CONFIGURATION_PROPERTIES_PROPERTY_ID, properties, requestedIds); - return resource; - } - - /** - * Parse the property map from a request into a map of category names to maps of property names and values. - * - * @param defaultCategoryName the default category name to use if one is not found in the map of properties - * @param resourceProperties a map of properties from a request item - * @return a map of category names to maps of name/value pairs - * @throws SystemException if an issue with the data is determined - */ - private Map<String, Map<String, String>> parseProperties(String defaultCategoryName, Map<String, Object> resourceProperties) throws SystemException { - String categoryName = null; - Map<String, String> properties = new HashMap<>(); - - for (Map.Entry<String, Object> entry : resourceProperties.entrySet()) { - String propertyName = entry.getKey(); - - if (AMBARI_CONFIGURATION_CATEGORY_PROPERTY_ID.equals(propertyName)) { - if (entry.getValue() instanceof String) { - categoryName = (String) entry.getValue(); - } - } else { - String propertyCategory = PropertyHelper.getPropertyCategory(entry.getKey()); - if ((propertyCategory != null) && propertyCategory.equals(AMBARI_CONFIGURATION_PROPERTIES_PROPERTY_ID)) { - String name = PropertyHelper.getPropertyName(entry.getKey()); - Object value = entry.getValue(); - properties.put(name, (value == null) ? null : value.toString()); - } - } - } - - if (categoryName == null) { - categoryName = defaultCategoryName; - } - - if (StringUtils.isEmpty(categoryName)) { - throw new SystemException("The configuration type must be set"); - } - - if (properties.isEmpty()) { - throw new SystemException("The configuration properties must be set"); - } - - return Collections.singletonMap(categoryName, properties); - } - - private Set<Resource> getAmbariConfigurationResources(Set<String> requestedIds, Map<String, Object> propertyMap) { - Set<Resource> resources = new HashSet<>(); - - String categoryName = getStringProperty(propertyMap, AMBARI_CONFIGURATION_CATEGORY_PROPERTY_ID); - - List<AmbariConfigurationEntity> entities = (categoryName == null) - ? ambariConfigurationDAO.findAll() - : ambariConfigurationDAO.findByCategory(categoryName); - - if (entities != null) { - Map<String, Map<String, String>> configurations = new HashMap<>(); - - for (AmbariConfigurationEntity entity : entities) { - String category = entity.getCategoryName(); - Map<String, String> properties = configurations.get(category); - - if (properties == null) { - properties = new TreeMap<>(); - configurations.put(category, properties); - } - - properties.put(entity.getPropertyName(), entity.getPropertyValue()); - } - - for (Map.Entry<String, Map<String, String>> entry : configurations.entrySet()) { - resources.add(toResource(entry.getKey(), entry.getValue(), requestedIds)); - } - } - - return resources; - } - - private String getStringProperty(Map<String, Object> propertyMap, String propertyId) { - String value = null; - - if (propertyMap != null) { - Object o = propertyMap.get(propertyId); - if (o instanceof String) { - value = (String) o; - } - } - - return value; - } -}