You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by lp...@apache.org on 2017/10/27 10:32:10 UTC
[5/5] ambari git commit: AMBARI-21307 Feature for supporting LDAP
configuration from the UI
AMBARI-21307 Feature for supporting LDAP configuration from the UI
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/30415a18
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/30415a18
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/30415a18
Branch: refs/heads/feature-branch-AMBARI-21307
Commit: 30415a18909f37a094e4adcc27ca5f2bf39e2fb1
Parents: 7e6036c
Author: lpuskas <lp...@apache.org>
Authored: Wed Jul 5 14:20:18 2017 +0200
Committer: lpuskas <lp...@apache.org>
Committed: Fri Oct 27 11:57:59 2017 +0200
----------------------------------------------------------------------
ambari-funtest/pom.xml | 67 ----
ambari-project/pom.xml | 52 +--
ambari-server/pom.xml | 83 +----
.../resources/ResourceInstanceFactoryImpl.java | 4 +
.../AmbariConfigurationRequestSwagger.java | 47 +++
.../AmbariConfigurationResponseSwagger.java | 40 +++
.../services/AmbariConfigurationService.java | 193 +++++++++++
.../api/services/ldap/AmbariConfiguration.java | 87 +++++
.../api/services/ldap/LdapConfigOperation.java | 43 +++
.../services/ldap/LdapConfigurationRequest.java | 49 +++
.../services/ldap/LdapConfigurationService.java | 185 +++++++++++
.../api/services/ldap/LdapRequestInfo.java | 61 ++++
.../stackadvisor/StackAdvisorRequest.java | 12 +
.../commands/StackAdvisorCommand.java | 54 +++
.../ambari/server/controller/AmbariServer.java | 3 +-
.../server/controller/ControllerModule.java | 3 +
.../controller/ResourceProviderFactory.java | 24 +-
.../AbstractControllerResourceProvider.java | 2 +
.../internal/AbstractProviderModule.java | 2 +-
.../AmbariConfigurationResourceProvider.java | 328 +++++++++++++++++++
.../internal/DefaultProviderModule.java | 24 +-
.../ambari/server/controller/spi/Resource.java | 5 +-
.../ambari/server/events/AmbariEvent.java | 11 +-
.../events/AmbariLdapConfigChangedEvent.java | 37 +++
.../apache/ambari/server/ldap/LdapModule.java | 82 +++++
.../ldap/domain/AmbariLdapConfigKeys.java | 83 +++++
.../ldap/domain/AmbariLdapConfiguration.java | 199 +++++++++++
.../domain/AmbariLdapConfigurationFactory.java | 34 ++
.../AmbariLdapConfigurationProvider.java | 120 +++++++
.../ldap/service/AmbariLdapException.java | 33 ++
.../server/ldap/service/AmbariLdapFacade.java | 140 ++++++++
.../server/ldap/service/AttributeDetector.java | 41 +++
.../service/LdapAttributeDetectionService.java | 40 +++
.../ldap/service/LdapConfigurationService.java | 60 ++++
.../service/LdapConnectionConfigService.java | 36 ++
.../ambari/server/ldap/service/LdapFacade.java | 58 ++++
.../DefaultLdapAttributeDetectionService.java | 200 +++++++++++
.../ads/DefaultLdapConfigurationService.java | 213 ++++++++++++
.../ads/DefaultLdapConnectionConfigService.java | 113 +++++++
.../ads/LdapConnectionTemplateFactory.java | 111 +++++++
.../ads/detectors/AttributeDetectorFactory.java | 75 +++++
.../ads/detectors/ChainedAttributeDetector.java | 73 +++++
.../ads/detectors/GroupMemberAttrDetector.java | 65 ++++
.../ads/detectors/GroupNameAttrDetector.java | 70 ++++
.../ads/detectors/GroupObjectClassDetector.java | 73 +++++
.../OccurrenceAndWeightBasedDetector.java | 143 ++++++++
.../detectors/UserGroupMemberAttrDetector.java | 64 ++++
.../ads/detectors/UserNameAttrDetector.java | 71 ++++
.../ads/detectors/UserObjectClassDetector.java | 69 ++++
.../server/orm/dao/AmbariConfigurationDAO.java | 89 +++++
.../apache/ambari/server/orm/dao/DaoUtils.java | 13 +-
.../orm/entities/AmbariConfigurationEntity.java | 70 ++++
.../orm/entities/ConfigurationBaseEntity.java | 159 +++++++++
.../authorization/RoleAuthorization.java | 95 +++---
.../main/resources/Ambari-DDL-Derby-CREATE.sql | 21 ++
.../main/resources/Ambari-DDL-MySQL-CREATE.sql | 20 ++
.../main/resources/Ambari-DDL-Oracle-CREATE.sql | 20 ++
.../resources/Ambari-DDL-Postgres-CREATE.sql | 25 +-
.../resources/Ambari-DDL-SQLAnywhere-CREATE.sql | 20 ++
.../resources/Ambari-DDL-SQLServer-CREATE.sql | 20 ++
.../src/main/resources/META-INF/persistence.xml | 2 +
.../commands/StackAdvisorCommandTest.java | 212 ++++++++++++
.../server/checks/UpgradeCheckOrderTest.java | 3 +-
...AmbariConfigurationResourceProviderTest.java | 251 ++++++++++++++
.../StackAdvisorResourceProviderTest.java | 97 +++---
.../server/ldap/LdapModuleFunctionalTest.java | 149 +++++++++
.../TestAmbariLdapConfigurationFactory.java | 29 ++
.../ldap/service/AmbariLdapFacadeTest.java | 215 ++++++++++++
...efaultLdapAttributeDetectionServiceTest.java | 188 +++++++++++
.../DefaultLdapConfigurationServiceTest.java | 221 +++++++++++++
.../detectors/GroupMemberAttrDetectorTest.java | 107 ++++++
.../notifications/DispatchFactoryTest.java | 3 +-
.../server/orm/InMemoryDefaultTestModule.java | 2 +
.../ambari/server/orm/JdbcPropertyTest.java | 5 +-
...uthenticationProviderForDNWithSpaceTest.java | 35 +-
.../AmbariLdapAuthenticationProviderTest.java | 3 +-
.../AmbariLocalUserProviderTest.java | 3 +-
.../authorization/LdapServerPropertiesTest.java | 5 +-
78 files changed, 5409 insertions(+), 355 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/30415a18/ambari-funtest/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-funtest/pom.xml b/ambari-funtest/pom.xml
index bb2068d..6466af3 100644
--- a/ambari-funtest/pom.xml
+++ b/ambari-funtest/pom.xml
@@ -197,73 +197,6 @@
<artifactId>spring-ldap-core</artifactId>
</dependency>
<dependency>
- <groupId>org.apache.directory.server</groupId>
- <artifactId>apacheds-server-annotations</artifactId>
- <scope>test</scope>
- <exclusions>
- <exclusion>
- <groupId>net.sf.ehcache</groupId>
- <artifactId>ehcache-core</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.apache.directory.server</groupId>
- <artifactId>apacheds-core-integ</artifactId>
- <scope>test</scope>
- <exclusions>
- <exclusion>
- <groupId>net.sf.ehcache</groupId>
- <artifactId>ehcache-core</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.apache.directory.server</groupId>
- <artifactId>apacheds-server-integ</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.directory.server</groupId>
- <artifactId>apacheds-jdbm</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.directory.server</groupId>
- <artifactId>apacheds-kerberos-codec</artifactId>
- <exclusions>
- <exclusion>
- <groupId>net.sf.ehcache</groupId>
- <artifactId>ehcache-core</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.apache.directory.server</groupId>
- <artifactId>apacheds-core</artifactId>
- <scope>test</scope>
- <exclusions>
- <exclusion>
- <groupId>net.sf.ehcache</groupId>
- <artifactId>ehcache-core</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.apache.directory.server</groupId>
- <artifactId>apacheds-protocol-ldap</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.directory.server</groupId>
- <artifactId>kerberos-client</artifactId>
- </dependency>
- <dependency>
- <groupId>org.apache.directory.shared</groupId>
- <artifactId>shared-ldap</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.20</version>
http://git-wip-us.apache.org/repos/asf/ambari/blob/30415a18/ambari-project/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-project/pom.xml b/ambari-project/pom.xml
index 00ba1bc..f6e3bc7 100644
--- a/ambari-project/pom.xml
+++ b/ambari-project/pom.xml
@@ -31,6 +31,7 @@
<ambari.dir>${project.parent.basedir}</ambari.dir>
<powermock.version>1.6.3</powermock.version>
<jetty.version>8.1.19.v20160209</jetty.version>
+ <ldap-api.version>1.0.0</ldap-api.version>
<checkstyle.version>6.19</checkstyle.version> <!-- last version that does not require Java 8 -->
<swagger.version>1.5.10</swagger.version>
<swagger.maven.plugin.version>3.1.4</swagger.maven.plugin.version>
@@ -161,57 +162,6 @@
<version>2.0.4.RELEASE</version>
</dependency>
<dependency>
- <groupId>org.apache.directory.server</groupId>
- <artifactId>apacheds-server-annotations</artifactId>
- <version>2.0.0-M19</version>
- </dependency>
- <dependency>
- <groupId>org.apache.directory.server</groupId>
- <artifactId>apacheds-core-integ</artifactId>
- <version>2.0.0-M19</version>
- </dependency>
- <dependency>
- <groupId>org.apache.directory.server</groupId>
- <artifactId>apacheds-server-integ</artifactId>
- <version>2.0.0-M19</version>
- </dependency>
- <dependency>
- <groupId>org.apache.directory.server</groupId>
- <artifactId>apacheds-jdbm</artifactId>
- <version>2.0.0-M5</version>
- </dependency>
- <dependency>
- <groupId>org.apache.directory.server</groupId>
- <artifactId>apacheds-kerberos-codec</artifactId>
- <version>2.0.0-M19</version>
- </dependency>
- <dependency>
- <groupId>org.apache.directory.server</groupId>
- <artifactId>apacheds-core</artifactId>
- <version>2.0.0-M19</version>
- </dependency>
- <dependency>
- <groupId>org.apache.directory.server</groupId>
- <artifactId>kerberos-client</artifactId>
- <version>2.0.0-M19</version>
- </dependency>
- <dependency>
- <groupId>org.apache.directory.server</groupId>
- <artifactId>apacheds-protocol-ldap</artifactId>
- <version>2.0.0-M19</version>
- <exclusions>
- <exclusion>
- <groupId>org.apache.directory.jdbm</groupId>
- <artifactId>apacheds-jdbm1</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.apache.directory.shared</groupId>
- <artifactId>shared-ldap</artifactId>
- <version>0.9.17</version>
- </dependency>
- <dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
http://git-wip-us.apache.org/repos/asf/ambari/blob/30415a18/ambari-server/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-server/pom.xml b/ambari-server/pom.xml
index e250da7..a86acf5 100644
--- a/ambari-server/pom.xml
+++ b/ambari-server/pom.xml
@@ -1225,73 +1225,6 @@
<artifactId>spring-ldap-core</artifactId>
</dependency>
<dependency>
- <groupId>org.apache.directory.server</groupId>
- <artifactId>apacheds-server-annotations</artifactId>
- <scope>test</scope>
- <exclusions>
- <exclusion>
- <groupId>net.sf.ehcache</groupId>
- <artifactId>ehcache-core</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.apache.directory.server</groupId>
- <artifactId>apacheds-core-integ</artifactId>
- <scope>test</scope>
- <exclusions>
- <exclusion>
- <groupId>net.sf.ehcache</groupId>
- <artifactId>ehcache-core</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.apache.directory.server</groupId>
- <artifactId>apacheds-server-integ</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.directory.server</groupId>
- <artifactId>apacheds-jdbm</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.directory.server</groupId>
- <artifactId>apacheds-kerberos-codec</artifactId>
- <exclusions>
- <exclusion>
- <groupId>net.sf.ehcache</groupId>
- <artifactId>ehcache-core</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.apache.directory.server</groupId>
- <artifactId>apacheds-core</artifactId>
- <scope>test</scope>
- <exclusions>
- <exclusion>
- <groupId>net.sf.ehcache</groupId>
- <artifactId>ehcache-core</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.apache.directory.server</groupId>
- <artifactId>apacheds-protocol-ldap</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.directory.server</groupId>
- <artifactId>kerberos-client</artifactId>
- </dependency>
- <dependency>
- <groupId>org.apache.directory.shared</groupId>
- <artifactId>shared-ldap</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
@@ -1622,6 +1555,12 @@
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-auth</artifactId>
<version>${hadoop.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.apache.directory.server</groupId>
+ <artifactId>apacheds-kerberos-codec</artifactId>
+ </exclusion>
+ </exclusions>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
@@ -1689,6 +1628,16 @@
<version>4.2.2</version>
</dependency>
<dependency>
+ <groupId>org.apache.directory.server</groupId>
+ <artifactId>apacheds-all</artifactId>
+ <version>2.0.0-M24</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.directory.server</groupId>
+ <artifactId>kerberos-client</artifactId>
+ <version>2.0.0-M24</version>
+ </dependency>
+ <dependency>
<groupId>com.networknt</groupId>
<artifactId>json-schema-validator</artifactId>
<version>0.1.10</version>
http://git-wip-us.apache.org/repos/asf/ambari/blob/30415a18/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 d0d115d..f5fb6e9 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
@@ -471,6 +471,10 @@ 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/30415a18/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
new file mode 100644
index 0000000..5e8094e
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationRequestSwagger.java
@@ -0,0 +1,47 @@
+/*
+ * 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
+ Long getId();
+
+ @ApiModelProperty
+ Map<String, Object> getData();
+
+ @ApiModelProperty
+ String getType();
+
+ @ApiModelProperty
+ Long getVersion();
+
+ @ApiModelProperty(name = "version_tag")
+ String getVersionTag();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/30415a18/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
new file mode 100644
index 0000000..c55ac1d
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationResponseSwagger.java
@@ -0,0 +1,40 @@
+/*
+ * 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/30415a18/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
new file mode 100644
index 0000000..38ae766
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationService.java
@@ -0,0 +1,193 @@
+/*
+ * 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": {
+ * "type": "ldap-configuration",
+ * "data": [
+ * {
+ * "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.EMPTY_MAP));
+ }
+
+ @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/data, AmbariConfiguration/id, AmbariConfiguration/type",
+ dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY),
+ @ApiImplicitParam(name = QUERY_SORT, value = QUERY_SORT_DESCRIPTION,
+ defaultValue = "AmbariConfiguration/id",
+ 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.EMPTY_MAP));
+ }
+
+ @GET
+ @Path("{configurationId}")
+ @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("configurationId") String configurationId) {
+ return handleRequest(headers, body, uri, Request.Type.GET, createResource(Resource.Type.AmbariConfiguration,
+ Collections.singletonMap(Resource.Type.AmbariConfiguration, configurationId)));
+ }
+
+ @PUT
+ @Path("{configurationId}")
+ @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("configurationId") String configurationId) {
+ return handleRequest(headers, body, uri, Request.Type.PUT, createResource(Resource.Type.AmbariConfiguration,
+ Collections.singletonMap(Resource.Type.AmbariConfiguration, configurationId)));
+ }
+
+ @DELETE
+ @Path("{configurationId}")
+ @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("configurationId") String configurationId) {
+ return handleRequest(headers, body, uri, Request.Type.DELETE, createResource(Resource.Type.AmbariConfiguration,
+ Collections.singletonMap(Resource.Type.AmbariConfiguration, configurationId)));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/30415a18/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
new file mode 100644
index 0000000..b5cc921
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/AmbariConfiguration.java
@@ -0,0 +1,87 @@
+/*
+ * 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.ldap;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Domain POJO representing generic ambari configuration data.
+ */
+public class AmbariConfiguration {
+
+ /**
+ * The type of the configuration, eg.: ldap-configuration
+ */
+ private String type;
+
+ /**
+ * Version tag
+ */
+ private String versionTag;
+
+ /**
+ * Version number
+ */
+ private Integer version;
+
+ /**
+ * Created timestamp
+ */
+ private long createdTs;
+
+ private Set<Map<String, Object>> data = Collections.emptySet();
+
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public Set<Map<String, Object>> getData() {
+ return data;
+ }
+
+ public void setData(Set<Map<String, Object>> data) {
+ this.data = data;
+ }
+
+ public String getVersionTag() {
+ return versionTag;
+ }
+
+ public void setVersionTag(String versionTag) {
+ this.versionTag = versionTag;
+ }
+
+ public Integer getVersion() {
+ return version;
+ }
+
+ public void setVersion(Integer version) {
+ this.version = version;
+ }
+
+ public long getCreatedTs() {
+ return createdTs;
+ }
+
+ public void setCreatedTs(long createdTs) {
+ this.createdTs = createdTs;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/30415a18/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigOperation.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigOperation.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigOperation.java
new file mode 100644
index 0000000..478d4ff
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigOperation.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.ldap;
+
+/**
+ * Enumeration for supported operations related to LDAP configuration.
+ */
+public enum LdapConfigOperation {
+ TEST_CONNECTION("test-connection"),
+ TEST_ATTRIBUTES("test-attributes"),
+ DETECT_ATTRIBUTES("detect-attributes");
+
+ private String actionStr;
+
+ LdapConfigOperation(String actionStr) {
+ this.actionStr = actionStr;
+ }
+
+ public static LdapConfigOperation fromAction(String action) {
+ for (LdapConfigOperation val : LdapConfigOperation.values()) {
+ if (val.action().equals(action)) {
+ return val;
+ }
+ }
+ throw new IllegalStateException("Action [ " + action + " ] is not supported");
+ }
+
+ public String action() {
+ return this.actionStr;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/30415a18/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
new file mode 100644
index 0000000..2e478c4
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationRequest.java
@@ -0,0 +1,49 @@
+/*
+ * 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.ldap;
+
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * Request object wrapping information for LDAP configuration related request calls.
+ */
+public class LdapConfigurationRequest {
+
+ @SerializedName("AmbariConfiguration")
+ private AmbariConfiguration ambariConfiguration;
+
+ @SerializedName("RequestInfo")
+ private LdapRequestInfo requestInfo;
+
+ public LdapConfigurationRequest() {
+ }
+
+ public AmbariConfiguration getAmbariConfiguration() {
+ return ambariConfiguration;
+ }
+
+ public void setAmbariConfiguration(AmbariConfiguration ambariConfiguration) {
+ this.ambariConfiguration = ambariConfiguration;
+ }
+
+ public LdapRequestInfo getRequestInfo() {
+ return requestInfo;
+ }
+
+ public void setRequestInfo(LdapRequestInfo requestInfo) {
+ this.requestInfo = requestInfo;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/30415a18/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
new file mode 100644
index 0000000..13f8835
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationService.java
@@ -0,0 +1,185 @@
+/*
+ * 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.
+ */
+
+/*
+ * 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.ldap;
+
+import java.util.Set;
+
+import javax.inject.Inject;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+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.Result;
+import org.apache.ambari.server.api.services.ResultImpl;
+import org.apache.ambari.server.api.services.ResultStatus;
+import org.apache.ambari.server.controller.internal.ResourceImpl;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.ldap.domain.AmbariLdapConfiguration;
+import org.apache.ambari.server.ldap.domain.AmbariLdapConfigurationFactory;
+import org.apache.ambari.server.ldap.service.LdapFacade;
+import org.apache.ambari.server.security.authorization.AuthorizationException;
+import org.apache.ambari.server.security.authorization.AuthorizationHelper;
+import org.apache.ambari.server.security.authorization.ResourceType;
+import org.apache.ambari.server.security.authorization.RoleAuthorization;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.core.Authentication;
+
+import com.google.common.collect.Sets;
+
+/**
+ * Endpoint designated to LDAP specific operations.
+ */
+@StaticallyInject
+@Path("/ldapconfigs/")
+public class LdapConfigurationService extends AmbariConfigurationService {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(LdapConfigurationService.class);
+
+ @Inject
+ private static LdapFacade ldapFacade;
+
+ @Inject
+ private static AmbariLdapConfigurationFactory ambariLdapConfigurationFactory;
+
+
+ @POST
+ @ApiIgnore // until documented
+ @Path("/validate")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response validateConfiguration(LdapConfigurationRequest ldapConfigurationRequest) {
+
+ // check if the user is authorized to perform the operation
+ authorize();
+
+ Set<String> groups = Sets.newHashSet();
+ Object responseEntity = null;
+
+ Result result = new ResultImpl(new ResultStatus(ResultStatus.STATUS.OK));
+ try {
+
+ validateRequest(ldapConfigurationRequest);
+
+ AmbariLdapConfiguration ambariLdapConfiguration = ambariLdapConfigurationFactory.createLdapConfiguration(
+ ldapConfigurationRequest.getAmbariConfiguration().getData().iterator().next());
+
+ LdapConfigOperation action = LdapConfigOperation.fromAction(ldapConfigurationRequest.getRequestInfo().getAction());
+ switch (action) {
+
+ case TEST_CONNECTION:
+
+ LOGGER.info("Testing connection to the LDAP server ...");
+ ldapFacade.checkConnection(ambariLdapConfiguration);
+
+ break;
+ case TEST_ATTRIBUTES:
+
+ LOGGER.info("Testing LDAP attributes ....");
+ groups = ldapFacade.checkLdapAttributes(ldapConfigurationRequest.getRequestInfo().getParameters(), ambariLdapConfiguration);
+ responseEntity = groups;
+
+ break;
+ case DETECT_ATTRIBUTES:
+
+ LOGGER.info("Detecting LDAP attributes ...");
+ ambariLdapConfiguration = ldapFacade.detectAttributes(ambariLdapConfiguration);
+ responseEntity = ambariLdapConfiguration;
+
+ break;
+ default:
+ LOGGER.warn("No action provided ...");
+ throw new IllegalArgumentException("No request action provided");
+ }
+
+ } catch (Exception e) {
+ result.setResultStatus(new ResultStatus(ResultStatus.STATUS.SERVER_ERROR, e));
+ responseEntity = e.getMessage();
+ }
+
+ return Response.status(result.getStatus().getStatusCode()).entity(responseEntity).build();
+ }
+
+ private void setResult(Set<String> groups, Result result) {
+ Resource resource = new ResourceImpl(Resource.Type.AmbariConfiguration);
+ resource.setProperty("groups", groups);
+ result.getResultTree().addChild(resource, "payload");
+ }
+
+ private void validateRequest(LdapConfigurationRequest ldapConfigurationRequest) {
+ String errMsg;
+
+ if (null == ldapConfigurationRequest) {
+ errMsg = "No ldap configuraiton request provided";
+ LOGGER.error(errMsg);
+ throw new IllegalArgumentException(errMsg);
+ }
+
+ if (null == ldapConfigurationRequest.getRequestInfo()) {
+ errMsg = String.format("No request information provided. Request: [%s]", ldapConfigurationRequest);
+ LOGGER.error(errMsg);
+ throw new IllegalArgumentException(errMsg);
+ }
+
+ if (null == ldapConfigurationRequest.getAmbariConfiguration()
+ || ldapConfigurationRequest.getAmbariConfiguration().getData().size() != 1) {
+ errMsg = String.format("No / Invalid configuration data provided. Request: [%s]", ldapConfigurationRequest);
+ LOGGER.error(errMsg);
+ throw new IllegalArgumentException(errMsg);
+ }
+ }
+
+ private void authorize() {
+ try {
+ Authentication authentication = AuthorizationHelper.getAuthentication();
+
+ if (authentication == null || !authentication.isAuthenticated()) {
+ throw new AuthorizationException("Authentication data is not available, authorization to perform the requested operation is not granted");
+ }
+
+ if (!AuthorizationHelper.isAuthorized(authentication, ResourceType.AMBARI, null, requiredAuthorizations())) {
+ throw new AuthorizationException("The authenticated user does not have the appropriate authorizations to create the requested resource(s)");
+ }
+ } catch (AuthorizationException e) {
+ LOGGER.error("Unauthorized operation.", e);
+ throw new IllegalArgumentException("User is not authorized to perform the operation", e);
+ }
+
+ }
+
+ private Set<RoleAuthorization> requiredAuthorizations() {
+ return Sets.newHashSet(RoleAuthorization.AMBARI_MANAGE_CONFIGURATION);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/30415a18/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapRequestInfo.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapRequestInfo.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapRequestInfo.java
new file mode 100644
index 0000000..eeecfee
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapRequestInfo.java
@@ -0,0 +1,61 @@
+/*
+ * 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.ldap;
+
+import java.util.Map;
+
+import org.apache.ambari.server.controller.RequestPostRequest;
+
+/**
+ * Bean holding LDAP request specific request information.
+ */
+public class LdapRequestInfo implements RequestPostRequest.RequestInfo {
+
+ // no-arg costructor facilitating JSON serialization
+ public LdapRequestInfo() {
+ }
+
+ private String action;
+
+ private Map<String, Object> parameters;
+
+ @Override
+ public String getAction() {
+ return action;
+ }
+
+ public void setAction(String action) {
+ this.action = action;
+ }
+
+ public void setParameters(Map<String, Object> parameters) {
+ this.parameters = parameters;
+ }
+
+ @Override
+ public String getCommand() {
+ return null;
+ }
+
+ @Override
+ public RequestPostRequest.OperationLevel getOperationLevel() {
+ return null;
+ }
+
+ @Override
+ public Map<String, Object> getParameters() {
+ return parameters;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/30415a18/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRequest.java
index 3a2b488..cd26c56 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRequest.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRequest.java
@@ -31,6 +31,8 @@ import org.apache.ambari.server.api.services.stackadvisor.recommendations.Recomm
import org.apache.ambari.server.state.ChangedConfigInfo;
import org.apache.commons.lang.StringUtils;
+import com.google.common.base.Preconditions;
+
/**
* Stack advisor request.
*/
@@ -48,6 +50,7 @@ public class StackAdvisorRequest {
private List<ChangedConfigInfo> changedConfigurations = new LinkedList<>();
private Set<RecommendationResponse.ConfigGroup> configGroups;
private Map<String, String> userContext = new HashMap<>();
+ private Map<String, Object> ldapConfig = new HashMap<>();
public String getStackName() {
return stackName;
@@ -93,6 +96,8 @@ public class StackAdvisorRequest {
return configurations;
}
+ public Map<String, Object> getLdapConfig() { return ldapConfig; }
+
public List<ChangedConfigInfo> getChangedConfigurations() {
return changedConfigurations;
}
@@ -189,6 +194,13 @@ public class StackAdvisorRequest {
return this;
}
+ public StackAdvisorRequestBuilder withLdapConfig(Map<String, Object> ldapConfig) {
+ Preconditions.checkNotNull(ldapConfig);
+ this.instance.ldapConfig = ldapConfig;
+ return this;
+ }
+
+
public StackAdvisorRequest build() {
return this.instance;
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/30415a18/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 356754d..2dc45de 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
@@ -84,6 +84,7 @@ 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 SERVICES_PROPERTY = "services";
private static final String SERVICES_COMPONENTS_PROPERTY = "components";
private static final String CONFIG_GROUPS_PROPERTY = "config-groups";
@@ -95,6 +96,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";
private File recommendationsDir;
private String recommendationsArtifactsLifetime;
@@ -160,6 +162,7 @@ public abstract class StackAdvisorCommand<T extends StackAdvisorResponse> extend
populateConfigurations(root, request);
populateConfigGroups(root, request);
populateAmbariServerInfo(root);
+ populateLdapConfiguration(root);
data.servicesJSON = mapper.writeValueAsString(root);
} catch (Exception e) {
// should not happen
@@ -171,6 +174,52 @@ public abstract class StackAdvisorCommand<T extends StackAdvisorResponse> extend
return data;
}
+ /**
+ * 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,
+ createConfigResource());
+
+ if (response.getStatus() != Status.OK.getStatusCode()) {
+ String message = String.format(
+ "Error occured during retrieving ldap configuration, status=%s, response=%s",
+ response.getStatus(), (String) response.getEntity());
+ LOG.warn(message);
+ throw new StackAdvisorException(message);
+ }
+
+ String ldapConfigJSON = (String) response.getEntity();
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("LDAP configuration: {}", ldapConfigJSON);
+ }
+
+ JsonNode ldapConfigRoot = mapper.readTree(ldapConfigJSON);
+ 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));
+ }
+ }
+
protected void populateAmbariServerInfo(ObjectNode root) throws StackAdvisorException {
Map<String, String> serverProperties = metaInfo.getAmbariServerProperties();
@@ -437,6 +486,11 @@ 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 createStackVersionResource(String stackName, String stackVersion) {
Map<Resource.Type, String> mapIds = new HashMap<>();
mapIds.put(Resource.Type.Stack, stackName);
http://git-wip-us.apache.org/repos/asf/ambari/blob/30415a18/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
index 8988be0..6ceed4a 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
@@ -77,6 +77,7 @@ import org.apache.ambari.server.controller.internal.ViewPermissionResourceProvid
import org.apache.ambari.server.controller.metrics.ThreadPoolEnabledPropertyProvider;
import org.apache.ambari.server.controller.utilities.KerberosChecker;
import org.apache.ambari.server.controller.utilities.KerberosIdentityCleaner;
+import org.apache.ambari.server.ldap.LdapModule;
import org.apache.ambari.server.metrics.system.MetricsService;
import org.apache.ambari.server.orm.GuiceJpaInitializer;
import org.apache.ambari.server.orm.PersistenceType;
@@ -1061,7 +1062,7 @@ public class AmbariServer {
public static void main(String[] args) throws Exception {
logStartup();
- Injector injector = Guice.createInjector(new ControllerModule(), new AuditLoggerModule());
+ Injector injector = Guice.createInjector(new ControllerModule(), new AuditLoggerModule(), new LdapModule());
AmbariServer server = null;
try {
http://git-wip-us.apache.org/repos/asf/ambari/blob/30415a18/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 dc97871..1425e1b 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,6 +63,7 @@ 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;
@@ -470,6 +471,7 @@ 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)
@@ -508,6 +510,7 @@ public class ControllerModule extends AbstractModule {
install(new FactoryModuleBuilder().implement(CollectionPersisterService.class, CsvFilePersisterService.class).build(CollectionPersisterServiceFactory.class));
install(new FactoryModuleBuilder().build(ConfigureClusterTaskFactory.class));
+
}
/**
http://git-wip-us.apache.org/repos/asf/ambari/blob/30415a18/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 a198775..711ae10 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
@@ -22,6 +22,8 @@ package org.apache.ambari.server.controller;
import java.util.Map;
import java.util.Set;
+import javax.inject.Named;
+
import org.apache.ambari.server.controller.internal.AlertTargetResourceProvider;
import org.apache.ambari.server.controller.internal.ClusterStackVersionResourceProvider;
import org.apache.ambari.server.controller.internal.UpgradeResourceProvider;
@@ -30,18 +32,15 @@ import org.apache.ambari.server.controller.spi.Resource;
import org.apache.ambari.server.controller.spi.Resource.Type;
import org.apache.ambari.server.controller.spi.ResourceProvider;
-import com.google.inject.name.Named;
public interface ResourceProviderFactory {
@Named("host")
- ResourceProvider getHostResourceProvider(Set<String> propertyIds,
- Map<Type, String> keyPropertyIds,
- AmbariManagementController managementController);
+ ResourceProvider getHostResourceProvider(Set<String> propertyIds, Map<Type, String> keyPropertyIds,
+ AmbariManagementController managementController);
@Named("hostComponent")
- ResourceProvider getHostComponentResourceProvider(Set<String> propertyIds,
- Map<Type, String> keyPropertyIds,
- AmbariManagementController managementController);
+ ResourceProvider getHostComponentResourceProvider(Set<String> propertyIds, Map<Type, String> keyPropertyIds,
+ AmbariManagementController managementController);
@Named("service")
ResourceProvider getServiceResourceProvider(AmbariManagementController managementController);
@@ -50,9 +49,8 @@ public interface ResourceProviderFactory {
ResourceProvider getComponentResourceProvider(AmbariManagementController managementController);
@Named("member")
- ResourceProvider getMemberResourceProvider(Set<String> propertyIds,
- Map<Type, String> keyPropertyIds,
- AmbariManagementController managementController);
+ ResourceProvider getMemberResourceProvider(Set<String> propertyIds, Map<Type, String> keyPropertyIds,
+ AmbariManagementController managementController);
@Named("hostKerberosIdentity")
ResourceProvider getHostKerberosIdentityResourceProvider(AmbariManagementController managementController);
@@ -64,13 +62,15 @@ public interface ResourceProviderFactory {
ResourceProvider getRepositoryVersionResourceProvider();
@Named("kerberosDescriptor")
- ResourceProvider getKerberosDescriptorResourceProvider(AmbariManagementController managementController,
- Set<String> propertyIds,
+ ResourceProvider getKerberosDescriptorResourceProvider(AmbariManagementController managementController, Set<String> propertyIds,
Map<Resource.Type, String> keyPropertyIds);
@Named("upgrade")
UpgradeResourceProvider getUpgradeResourceProvider(AmbariManagementController managementController);
+ @Named("ambariConfiguration")
+ ResourceProvider getAmbariConfigurationResourceProvider();
+
@Named("clusterStackVersion")
ClusterStackVersionResourceProvider getClusterStackVersionResourceProvider(AmbariManagementController managementController);
http://git-wip-us.apache.org/repos/asf/ambari/blob/30415a18/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 a98ad46..1dc0841 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
@@ -254,6 +254,8 @@ 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/30415a18/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractProviderModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractProviderModule.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractProviderModule.java
index 1cd2d10..1501a01 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractProviderModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractProviderModule.java
@@ -224,7 +224,7 @@ public abstract class AbstractProviderModule implements ProviderModule,
* are going to work unless refactoring is complete.
*/
@Inject
- AmbariManagementController managementController;
+ protected AmbariManagementController managementController;
@Inject
TimelineMetricCacheProvider metricCacheProvider;
http://git-wip-us.apache.org/repos/asf/ambari/blob/30415a18/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
new file mode 100644
index 0000000..4f4cc70
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariConfigurationResourceProvider.java
@@ -0,0 +1,328 @@
+/*
+ * 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.Calendar;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.inject.Inject;
+
+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.events.AmbariEvent;
+import org.apache.ambari.server.events.AmbariLdapConfigChangedEvent;
+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.orm.entities.ConfigurationBaseEntity;
+import org.apache.ambari.server.security.authorization.RoleAuthorization;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Sets;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.inject.assistedinject.AssistedInject;
+
+/**
+ * Resource provider for AmbariConfiguration resources.
+ */
+public class AmbariConfigurationResourceProvider extends AbstractAuthorizedResourceProvider {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(AmbariConfigurationResourceProvider.class);
+ private static final String DEFAULT_VERSION_TAG = "Default version";
+ private static final Integer DEFAULT_VERSION = 1;
+
+ /**
+ * Resource property id constants.
+ */
+ public enum ResourcePropertyId {
+
+ ID("AmbariConfiguration/id"),
+ TYPE("AmbariConfiguration/type"),
+ VERSION("AmbariConfiguration/version"),
+ VERSION_TAG("AmbariConfiguration/version_tag"),
+ DATA("AmbariConfiguration/data");
+
+ private String propertyId;
+
+ ResourcePropertyId(String propertyId) {
+ this.propertyId = propertyId;
+ }
+
+ String getPropertyId() {
+ return this.propertyId;
+ }
+
+ public static ResourcePropertyId fromString(String propertyIdStr) {
+ ResourcePropertyId propertyIdFromStr = null;
+
+ for (ResourcePropertyId id : ResourcePropertyId.values()) {
+ if (id.getPropertyId().equals(propertyIdStr)) {
+ propertyIdFromStr = id;
+ break;
+ }
+ }
+
+ if (propertyIdFromStr == null) {
+ throw new IllegalArgumentException("Unsupported property type: " + propertyIdStr);
+ }
+
+ return propertyIdFromStr;
+
+ }
+ }
+
+ private static Set<String> PROPERTIES = Sets.newHashSet(
+ ResourcePropertyId.ID.getPropertyId(),
+ ResourcePropertyId.TYPE.getPropertyId(),
+ ResourcePropertyId.VERSION.getPropertyId(),
+ ResourcePropertyId.VERSION_TAG.getPropertyId(),
+ ResourcePropertyId.DATA.getPropertyId());
+
+ private static Map<Resource.Type, String> PK_PROPERTY_MAP = Collections.unmodifiableMap(
+ new HashMap<Resource.Type, String>() {{
+ put(Resource.Type.AmbariConfiguration, ResourcePropertyId.ID.getPropertyId());
+ }}
+ );
+
+
+ @Inject
+ private AmbariConfigurationDAO ambariConfigurationDAO;
+
+ @Inject
+ private AmbariEventPublisher publisher;
+
+
+ private Gson gson;
+
+ @AssistedInject
+ public AmbariConfigurationResourceProvider() {
+ super(PROPERTIES, PK_PROPERTY_MAP);
+ setRequiredCreateAuthorizations(EnumSet.of(RoleAuthorization.AMBARI_MANAGE_CONFIGURATION));
+ setRequiredDeleteAuthorizations(EnumSet.of(RoleAuthorization.AMBARI_MANAGE_CONFIGURATION));
+
+ gson = new GsonBuilder().create();
+ }
+
+ @Override
+ protected Set<String> getPKPropertyIds() {
+ return Sets.newHashSet(ResourcePropertyId.ID.getPropertyId());
+ }
+
+ @Override
+ public RequestStatus createResourcesAuthorized(Request request) throws SystemException, UnsupportedPropertyException,
+ ResourceAlreadyExistsException, NoSuchParentResourceException {
+
+ LOGGER.info("Creating new ambari configuration resource ...");
+ AmbariConfigurationEntity ambariConfigurationEntity = null;
+ try {
+ ambariConfigurationEntity = getEntityFromRequest(request);
+ } catch (AmbariException e) {
+ throw new NoSuchParentResourceException(e.getMessage());
+ }
+
+ LOGGER.info("Persisting new ambari configuration: {} ", ambariConfigurationEntity);
+
+ try {
+ ambariConfigurationDAO.create(ambariConfigurationEntity);
+ } catch (Exception e) {
+ LOGGER.error("Failed to create resource", e);
+ throw new ResourceAlreadyExistsException(e.getMessage());
+ }
+
+ // todo filter by configuration type
+ // notify subscribers about the configuration changes
+ publisher.publish(new AmbariLdapConfigChangedEvent(AmbariEvent.AmbariEventType.LDAP_CONFIG_CHANGED,
+ ambariConfigurationEntity.getId()));
+
+ return getRequestStatus(null);
+ }
+
+
+ @Override
+ protected Set<Resource> getResourcesAuthorized(Request request, Predicate predicate) throws SystemException,
+ UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+ Set<Resource> resources = Sets.newHashSet();
+
+ // retrieves allconfigurations, filtering is done at a higher level
+ List<AmbariConfigurationEntity> ambariConfigurationEntities = ambariConfigurationDAO.findAll();
+ for (AmbariConfigurationEntity ambariConfigurationEntity : ambariConfigurationEntities) {
+ try {
+ resources.add(toResource(ambariConfigurationEntity, getPropertyIds()));
+ } catch (AmbariException e) {
+ LOGGER.error("Error while retrieving ambari configuration", e);
+ }
+ }
+ return resources;
+ }
+
+ @Override
+ protected RequestStatus deleteResourcesAuthorized(Request request, Predicate predicate) throws SystemException,
+ UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+
+ Long idFromRequest = Long.valueOf((String) PredicateHelper.getProperties(predicate).get(ResourcePropertyId.ID.getPropertyId()));
+
+ if (null == idFromRequest) {
+ LOGGER.debug("No resource id provided in the request");
+ } else {
+ LOGGER.debug("Deleting amari configuration with id: {}", idFromRequest);
+ try {
+ ambariConfigurationDAO.removeByPK(idFromRequest);
+ } catch (IllegalStateException e) {
+ throw new NoSuchResourceException(e.getMessage());
+ }
+
+ }
+
+ // notify subscribers about the configuration changes
+ publisher.publish(new AmbariLdapConfigChangedEvent(AmbariEvent.AmbariEventType.LDAP_CONFIG_CHANGED, idFromRequest));
+
+
+ return getRequestStatus(null);
+
+ }
+
+ @Override
+ protected RequestStatus updateResourcesAuthorized(Request request, Predicate predicate) throws SystemException,
+ UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+ Long idFromRequest = Long.valueOf((String) PredicateHelper.getProperties(predicate).get(ResourcePropertyId.ID.getPropertyId()));
+
+ AmbariConfigurationEntity persistedEntity = ambariConfigurationDAO.findByPK(idFromRequest);
+ if (persistedEntity == null) {
+ String errorMsg = String.format("Entity with primary key [ %s ] not found in the database.", idFromRequest);
+ LOGGER.error(errorMsg);
+ throw new NoSuchResourceException(errorMsg);
+ }
+
+ try {
+
+ AmbariConfigurationEntity entityFromRequest = getEntityFromRequest(request);
+ persistedEntity.getConfigurationBaseEntity().setVersionTag(entityFromRequest.getConfigurationBaseEntity().getVersionTag());
+ persistedEntity.getConfigurationBaseEntity().setVersion(entityFromRequest.getConfigurationBaseEntity().getVersion());
+ persistedEntity.getConfigurationBaseEntity().setType(entityFromRequest.getConfigurationBaseEntity().getType());
+ persistedEntity.getConfigurationBaseEntity().setConfigurationData(entityFromRequest.getConfigurationBaseEntity().getConfigurationData());
+ persistedEntity.getConfigurationBaseEntity().setConfigurationAttributes(entityFromRequest.getConfigurationBaseEntity().getConfigurationAttributes());
+
+
+ ambariConfigurationDAO.update(persistedEntity);
+ } catch (AmbariException e) {
+ throw new NoSuchParentResourceException(e.getMessage());
+ }
+
+ publisher.publish(new AmbariLdapConfigChangedEvent(AmbariEvent.AmbariEventType.LDAP_CONFIG_CHANGED,
+ persistedEntity.getId()));
+
+
+ return getRequestStatus(null);
+
+ }
+
+ private Resource toResource(AmbariConfigurationEntity entity, Set<String> requestedIds) throws AmbariException {
+
+ if (null == entity) {
+ throw new IllegalArgumentException("Null entity can't be transformed into a resource");
+ }
+
+ if (null == entity.getConfigurationBaseEntity()) {
+ throw new IllegalArgumentException("Invalid configuration entity can't be transformed into a resource");
+ }
+ Resource resource = new ResourceImpl(Resource.Type.AmbariConfiguration);
+ Set<Map<String, String>> configurationSet = gson.fromJson(entity.getConfigurationBaseEntity().getConfigurationData(), Set.class);
+
+ setResourceProperty(resource, ResourcePropertyId.ID.getPropertyId(), entity.getId(), requestedIds);
+ setResourceProperty(resource, ResourcePropertyId.TYPE.getPropertyId(), entity.getConfigurationBaseEntity().getType(), requestedIds);
+ setResourceProperty(resource, ResourcePropertyId.DATA.getPropertyId(), configurationSet, requestedIds);
+ setResourceProperty(resource, ResourcePropertyId.VERSION.getPropertyId(), entity.getConfigurationBaseEntity().getVersion(), requestedIds);
+ setResourceProperty(resource, ResourcePropertyId.VERSION_TAG.getPropertyId(), entity.getConfigurationBaseEntity().getVersionTag(), requestedIds);
+
+ return resource;
+ }
+
+ private AmbariConfigurationEntity getEntityFromRequest(Request request) throws AmbariException {
+
+ AmbariConfigurationEntity ambariConfigurationEntity = new AmbariConfigurationEntity();
+ ambariConfigurationEntity.setConfigurationBaseEntity(new ConfigurationBaseEntity());
+
+ // set of resource properties (eache entry in the set belongs to a different resource)
+ Set<Map<String, Object>> resourcePropertiesSet = request.getProperties();
+
+ if (resourcePropertiesSet.size() != 1) {
+ throw new AmbariException("There must be only one resource specified in the request");
+ }
+
+ // the configuration type must be set
+ if (getValueFromResourceProperties(ResourcePropertyId.TYPE, resourcePropertiesSet.iterator().next()) == null) {
+ throw new AmbariException("The configuration type must be set");
+ }
+
+
+ for (ResourcePropertyId resourcePropertyId : ResourcePropertyId.values()) {
+ Object requestValue = getValueFromResourceProperties(resourcePropertyId, resourcePropertiesSet.iterator().next());
+
+ switch (resourcePropertyId) {
+ case DATA:
+ if (requestValue == null) {
+ throw new IllegalArgumentException("No configuration data is provided in the request");
+ }
+ ambariConfigurationEntity.getConfigurationBaseEntity().setConfigurationData(gson.toJson(requestValue));
+ break;
+ case TYPE:
+ ambariConfigurationEntity.getConfigurationBaseEntity().setType((String) requestValue);
+ break;
+ case VERSION:
+ Integer version = (requestValue == null) ? DEFAULT_VERSION : Integer.valueOf((String) requestValue);
+ ambariConfigurationEntity.getConfigurationBaseEntity().setVersion((version));
+ break;
+ case VERSION_TAG:
+ String versionTag = requestValue == null ? DEFAULT_VERSION_TAG : (String) requestValue;
+ ambariConfigurationEntity.getConfigurationBaseEntity().setVersionTag(versionTag);
+ break;
+ default:
+ LOGGER.debug("Ignored property in the request: {}", resourcePropertyId);
+ break;
+ }
+ }
+ ambariConfigurationEntity.getConfigurationBaseEntity().setCreateTimestamp(Calendar.getInstance().getTimeInMillis());
+ return ambariConfigurationEntity;
+
+ }
+
+ private Object getValueFromResourceProperties(ResourcePropertyId resourcePropertyIdEnum, Map<String, Object> resourceProperties) {
+ LOGGER.debug("Locating resource property [{}] in the resource properties map ...", resourcePropertyIdEnum);
+ Object requestValue = null;
+
+ if (resourceProperties.containsKey(resourcePropertyIdEnum.getPropertyId())) {
+ requestValue = resourceProperties.get(resourcePropertyIdEnum.getPropertyId());
+ LOGGER.debug("Found resource property {} in the resource properties map, value: {}", resourcePropertyIdEnum, requestValue);
+ }
+ return requestValue;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/30415a18/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java
index 43779a3..c3758b3 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java
@@ -21,20 +21,18 @@ package org.apache.ambari.server.controller.internal;
import java.util.Map;
import java.util.Set;
-import org.apache.ambari.server.controller.AmbariManagementController;
-import org.apache.ambari.server.controller.AmbariServer;
import org.apache.ambari.server.controller.spi.Resource;
import org.apache.ambari.server.controller.spi.ResourceProvider;
import org.apache.ambari.server.controller.utilities.PropertyHelper;
-
-import com.google.inject.Inject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* The default provider module implementation.
*/
public class DefaultProviderModule extends AbstractProviderModule {
- @Inject
- private AmbariManagementController managementController;
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(DefaultProviderModule.class);
// ----- Constructors ------------------------------------------------------
@@ -42,9 +40,7 @@ public class DefaultProviderModule extends AbstractProviderModule {
* Create a default provider module.
*/
public DefaultProviderModule() {
- if (managementController == null) {
- managementController = AmbariServer.getController();
- }
+ super();
}
@@ -52,8 +48,10 @@ public class DefaultProviderModule extends AbstractProviderModule {
@Override
protected ResourceProvider createResourceProvider(Resource.Type type) {
- Set<String> propertyIds = PropertyHelper.getPropertyIds(type);
- Map<Resource.Type,String> keyPropertyIds = PropertyHelper.getKeyPropertyIds(type);
+
+ LOGGER.debug("Creating resource provider for the type: {}", type);
+ Set<String> propertyIds = PropertyHelper.getPropertyIds(type);
+ Map<Resource.Type, String> keyPropertyIds = PropertyHelper.getKeyPropertyIds(type);
switch (type.getInternalType()) {
case Workflow:
@@ -118,10 +116,10 @@ public class DefaultProviderModule extends AbstractProviderModule {
return new ArtifactResourceProvider(managementController);
case RemoteCluster:
return new RemoteClusterResourceProvider();
-
default:
+ LOGGER.debug("Delegating creation of resource provider for: {} to the AbstractControllerResourceProvider", type.getInternalType());
return AbstractControllerResourceProvider.getResourceProvider(type, propertyIds,
- keyPropertyIds, managementController);
+ keyPropertyIds, managementController);
}
}
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/30415a18/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 362b4e6..7835373 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
@@ -160,7 +160,8 @@ public interface Resource {
VersionDefinition,
ClusterKerberosDescriptor,
LoggingQuery,
- RemoteCluster;
+ RemoteCluster,
+ AmbariConfiguration;
/**
* Get the {@link Type} that corresponds to this InternalType.
@@ -282,6 +283,8 @@ public interface Resource {
public static final Type ClusterKerberosDescriptor = InternalType.ClusterKerberosDescriptor.getType();
public static final Type LoggingQuery = InternalType.LoggingQuery.getType();
public static final Type RemoteCluster = InternalType.RemoteCluster.getType();
+ public static final Type AmbariConfiguration = InternalType.AmbariConfiguration.getType();
+
/**
* The type name.
http://git-wip-us.apache.org/repos/asf/ambari/blob/30415a18/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariEvent.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariEvent.java b/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariEvent.java
index 9a5ee79..0f9ff52 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariEvent.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariEvent.java
@@ -140,7 +140,13 @@ public abstract class AmbariEvent {
/**
* Local user has been created.
*/
- USER_CREATED;
+ USER_CREATED,
+
+ /**
+ * LDAP config changed event;
+ */
+ LDAP_CONFIG_CHANGED;
+
}
/**
@@ -151,8 +157,7 @@ public abstract class AmbariEvent {
/**
* Constructor.
*
- * @param eventType
- * the type of event (not {@code null}).
+ * @param eventType the type of event (not {@code null}).
*/
public AmbariEvent(AmbariEventType eventType) {
m_eventType = eventType;
http://git-wip-us.apache.org/repos/asf/ambari/blob/30415a18/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariLdapConfigChangedEvent.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariLdapConfigChangedEvent.java b/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariLdapConfigChangedEvent.java
new file mode 100644
index 0000000..48799d7
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariLdapConfigChangedEvent.java
@@ -0,0 +1,37 @@
+/*
+ * 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.events;
+
+/**
+ * Event signaling the creation or changing of an LDAP configuration entry.
+ */
+public class AmbariLdapConfigChangedEvent extends AmbariEvent {
+
+ private Long configurationId;
+
+ /**
+ * Constructor.
+ *
+ * @param eventType the type of event (not {@code null}).
+ */
+ public AmbariLdapConfigChangedEvent(AmbariEventType eventType, Long configurationId) {
+ super(eventType);
+ this.configurationId = configurationId;
+ }
+
+ public Long getConfigurationId() {
+ return configurationId;
+ }
+}