You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by ad...@apache.org on 2018/04/09 11:08:33 UTC

[ambari] branch trunk updated (0958fca -> ab99b71)

This is an automated email from the ASF dual-hosted git repository.

adoroszlai pushed a change to branch trunk
in repository https://gitbox.apache.org/repos/asf/ambari.git.


    from 0958fca  AMBARI-23507 : AMS sinks should be compatible with both ambari metrics collector versions 2.6.x and 2.7.0.
     new e88c384  AMBARI-23436 - make swagger wrapper classes unique, otherwise not parsed correctly
     new 8673521  AMBARI-23436 - add SwaggerOverwriteNestedAPI annotation to handle special API cases
     new ab99b71  AMBARI-23436 - Integrate ServiceConfigVersion service to Swagger

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../ambari/server/api/services/HostService.java    |  5 +-
 .../server/api/services/RootServiceService.java    |  4 +-
 .../api/services/ServiceConfigVersionService.java  | 49 +++++++++++-
 .../api/services/views/ViewPrivilegeService.java   |  6 +-
 .../ambari/server/controller/HostResponse.java     |  2 +-
 .../controller/ServiceConfigVersionRequest.java    | 12 +++
 .../controller/ServiceConfigVersionResponse.java   | 21 +++++-
 .../server/controller/ViewPrivilegeResponse.java   |  2 +-
 .../internal/ClusterResourceProvider.java          |  8 +-
 .../ServiceConfigVersionResourceProvider.java      | 88 +++++++++++-----------
 .../metrics/system/impl/AmbariMetricSinkImpl.java  | 10 +--
 ...dParent.java => SwaggerOverwriteNestedAPI.java} | 35 +++++++--
 .../apache/ambari/swagger/AmbariSwaggerReader.java | 44 +++++++++--
 .../ambari/swagger/AmbariSwaggerReaderTest.java    | 43 +++++++++++
 14 files changed, 250 insertions(+), 79 deletions(-)
 copy ambari-utility/src/main/java/org/apache/ambari/annotations/{SwaggerPreferredParent.java => SwaggerOverwriteNestedAPI.java} (54%)

-- 
To stop receiving notification emails like this one, please contact
adoroszlai@apache.org.

[ambari] 01/03: AMBARI-23436 - make swagger wrapper classes unique, otherwise not parsed correctly

Posted by ad...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

adoroszlai pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ambari.git

commit e88c3847aa1d5133c29b5941c38a964bdfd5f45f
Author: Gabor Boros <63...@users.noreply.github.com>
AuthorDate: Wed Apr 4 13:49:19 2018 +0200

    AMBARI-23436 - make swagger wrapper classes unique, otherwise not parsed
    correctly
    
    Change-Id: Iad4f318b76cd7a93342940412bd11fdb065101da
---
 .../java/org/apache/ambari/server/api/services/HostService.java     | 5 +++--
 .../org/apache/ambari/server/api/services/RootServiceService.java   | 4 ++--
 .../ambari/server/api/services/views/ViewPrivilegeService.java      | 6 +++---
 .../main/java/org/apache/ambari/server/controller/HostResponse.java | 2 +-
 .../org/apache/ambari/server/controller/ViewPrivilegeResponse.java  | 2 +-
 5 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/HostService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/HostService.java
index 58d1d1d..4e6eada 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/HostService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/HostService.java
@@ -90,7 +90,7 @@ public class HostService extends BaseService {
   @GET
   @Path("{hostName}")
   @Produces("text/plain")
-  @ApiOperation(value = "Returns information about a single host", response = HostResponse.Wrapper.class)
+  @ApiOperation(value = "Returns information about a single host", response = HostResponse.HostResponseWrapper.class)
   @ApiImplicitParams({
     @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION, dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY),
   })
@@ -118,7 +118,8 @@ public class HostService extends BaseService {
    */
   @GET
   @Produces("text/plain")
-  @ApiOperation(value = "Returns a collection of all hosts", response = HostResponse.Wrapper.class, responseContainer = "List")
+  @ApiOperation(value = "Returns a collection of all hosts", response = HostResponse.HostResponseWrapper.class,
+          responseContainer = "List")
   @ApiImplicitParams({
     @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION, defaultValue = "Hosts/*", dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY),
     @ApiImplicitParam(name = QUERY_SORT, value = QUERY_SORT_DESCRIPTION, defaultValue = "Hosts/host_name.asc", dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY),
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 1ab2797..0414436 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
@@ -138,7 +138,7 @@ public class RootServiceService extends BaseService {
   @Path("{serviceName}/hosts")
   @Produces(MediaType.TEXT_PLAIN)
   @ApiOperation(value = "Returns the list of hosts for the given root-level service",
-    response = HostResponse.Wrapper.class, responseContainer = RESPONSE_CONTAINER_LIST)
+    response = HostResponse.HostResponseWrapper.class, responseContainer = RESPONSE_CONTAINER_LIST)
   @ApiImplicitParams({
     @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION, dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY,
       defaultValue = DEFAULT_FIELDS_HOSTS),
@@ -158,7 +158,7 @@ public class RootServiceService extends BaseService {
   @GET
   @Path("{serviceName}/hosts/{hostName}")
   @Produces(MediaType.TEXT_PLAIN)
-  @ApiOperation(value = "Returns information about the given host", response = HostResponse.Wrapper.class)
+  @ApiOperation(value = "Returns information about the given host", response = HostResponse.HostResponseWrapper.class)
   @ApiImplicitParams({
     @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION, dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY,
       defaultValue = DEFAULT_FIELDS_HOST),
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/views/ViewPrivilegeService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/views/ViewPrivilegeService.java
index 59e5b5d..2b40aec 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/views/ViewPrivilegeService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/views/ViewPrivilegeService.java
@@ -59,7 +59,7 @@ import io.swagger.annotations.ApiResponses;
 @Api(tags = "Views", description = "Endpoint for view specific operations")
 public class ViewPrivilegeService extends BaseService {
 
-  public static final String PRIVILEGE_INFO_REQUEST_TYPE = "org.apache.ambari.server.controller.ViewPrivilegeResponse.Wrapper";
+  public static final String PRIVILEGE_INFO_REQUEST_TYPE = "org.apache.ambari.server.controller.ViewPrivilegeResponse.ViewPrivilegeResponseWrapper";
 
   /**
    * Handles: GET  /views/{viewName}/versions/{version}/instances/{instanceName}/privileges
@@ -75,7 +75,7 @@ public class ViewPrivilegeService extends BaseService {
    */
   @GET
   @Produces(MediaType.TEXT_PLAIN)
-  @ApiOperation(value = "Get all view instance privileges", response = ViewPrivilegeResponse.Wrapper.class, responseContainer = "List")
+  @ApiOperation(value = "Get all view instance privileges", response = ViewPrivilegeResponse.ViewPrivilegeResponseWrapper.class, responseContainer = "List")
   @ApiImplicitParams({
     @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION, defaultValue = "PrivilegeInfo/*", dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY),
     @ApiImplicitParam(name = QUERY_SORT, value = QUERY_SORT_DESCRIPTION, dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY),
@@ -114,7 +114,7 @@ public class ViewPrivilegeService extends BaseService {
   @GET
   @Path("/{privilegeId}")
   @Produces(MediaType.TEXT_PLAIN)
-  @ApiOperation(value = "Get single view instance privilege", response = ViewPrivilegeResponse.Wrapper.class)
+  @ApiOperation(value = "Get single view instance privilege", response = ViewPrivilegeResponse.ViewPrivilegeResponseWrapper.class)
   @ApiImplicitParams({
     @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION, defaultValue = "PrivilegeInfo/*", dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY),
   })
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/HostResponse.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/HostResponse.java
index 9d02a0b..32035a5 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/HostResponse.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/HostResponse.java
@@ -428,7 +428,7 @@ public class HostResponse {
     this.recoveryReport = recoveryReport;
   }
 
-  public interface Wrapper extends ApiModel {
+  public interface HostResponseWrapper extends ApiModel {
     @ApiModelProperty(name = HostResourceProvider.RESPONSE_KEY)
     @SuppressWarnings("unused")
     HostResponse getHostResponse();
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ViewPrivilegeResponse.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ViewPrivilegeResponse.java
index 5419d17..0d6a320 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ViewPrivilegeResponse.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ViewPrivilegeResponse.java
@@ -54,7 +54,7 @@ public class ViewPrivilegeResponse extends PrivilegeResponse implements ApiModel
     return type;
   }
 
-  public interface Wrapper extends ApiModel {
+  public interface ViewPrivilegeResponseWrapper extends ApiModel {
     @ApiModelProperty(name = ViewPrivilegeResourceProvider.PRIVILEGE_INFO)
     @SuppressWarnings("unused")
     ViewPrivilegeResponse getViewPrivilegeResponse();

-- 
To stop receiving notification emails like this one, please contact
adoroszlai@apache.org.

[ambari] 03/03: AMBARI-23436 - Integrate ServiceConfigVersion service to Swagger

Posted by ad...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

adoroszlai pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ambari.git

commit ab99b71c30fc9a3a82ae15bba267957483d8da42
Author: Gabor Boros <63...@users.noreply.github.com>
AuthorDate: Fri Apr 6 13:36:52 2018 +0200

    AMBARI-23436 - Integrate ServiceConfigVersion service to Swagger
    
    Change-Id: I17e7a12c4fd24966b754b1f119199688740349c7
---
 .../api/services/ServiceConfigVersionService.java  | 49 +++++++++++-
 .../controller/ServiceConfigVersionRequest.java    | 12 +++
 .../controller/ServiceConfigVersionResponse.java   | 21 +++++-
 .../internal/ClusterResourceProvider.java          |  8 +-
 .../ServiceConfigVersionResourceProvider.java      | 88 +++++++++++-----------
 .../metrics/system/impl/AmbariMetricSinkImpl.java  | 10 +--
 6 files changed, 131 insertions(+), 57 deletions(-)

diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ServiceConfigVersionService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ServiceConfigVersionService.java
index c6e3201..bc859c5 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ServiceConfigVersionService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ServiceConfigVersionService.java
@@ -22,16 +22,32 @@ import java.util.HashMap;
 import java.util.Map;
 
 import javax.ws.rs.GET;
+import javax.ws.rs.Path;
 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.annotations.ApiIgnore;
+import org.apache.ambari.annotations.SwaggerOverwriteNestedAPI;
 import org.apache.ambari.server.api.resources.ResourceInstance;
+import org.apache.ambari.server.controller.ServiceConfigVersionResponse;
 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;
+
+@Api(value = "Configurations", description = "Endpoint for configuration-specific operations")
+@SwaggerOverwriteNestedAPI(parentApi = ConfigurationService.class, parentApiPath =
+  "/clusters", parentMethodPath = "{clusterName}/configurations/service_config_versions", pathParameters =
+  {"clusterName"})
 public class ServiceConfigVersionService extends BaseService {
   /**
    * Parent cluster name.
@@ -42,8 +58,35 @@ public class ServiceConfigVersionService extends BaseService {
     this.m_clusterName = m_clusterName;
   }
 
-  @GET @ApiIgnore // until documented
-  @Produces("text/plain")
+  /**
+   * Handles URL: /clusters/{clusterId}/configurations/service_config_versions
+   * Get all service configuration versions for a cluster and service.
+   *
+   * @param headers http headers
+   * @param ui      uri info
+   * @return service config version collection resource representation
+   */
+  @GET
+  @Path("") // This is needed if class level path is not present otherwise no Swagger docs will be generated for this method
+  @Produces(MediaType.TEXT_PLAIN)
+  @ApiOperation(value = "Get all service config versions", response = ServiceConfigVersionResponse.class,
+    responseContainer = RESPONSE_CONTAINER_LIST)
+  @ApiImplicitParams({
+    @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION, dataType = DATA_TYPE_STRING, paramType =
+      PARAM_TYPE_QUERY),
+    @ApiImplicitParam(name = QUERY_SORT, value = QUERY_SORT_DESCRIPTION, 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, allowableValues = QUERY_FROM_VALUES, defaultValue = DEFAULT_FROM, dataType = DATA_TYPE_INT, paramType = PARAM_TYPE_QUERY),
+    @ApiImplicitParam(name = QUERY_TO, value = QUERY_TO_DESCRIPTION, allowableValues = QUERY_TO_VALUES, dataType = DATA_TYPE_INT, paramType = PARAM_TYPE_QUERY),
+  })
+  @ApiResponses({
+    @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION),
+    @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = MSG_CLUSTER_OR_HOST_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),
+    @ApiResponse(code = HttpStatus.SC_BAD_REQUEST, message = MSG_INVALID_ARGUMENTS),
+  })
   public Response getServiceConfigVersions(String body, @Context HttpHeaders headers, @Context UriInfo ui) {
     return handleRequest(headers, body, ui, Request.Type.GET, createServiceConfigResource(m_clusterName));
   }
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceConfigVersionRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceConfigVersionRequest.java
index c47a5e0..9fed772 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceConfigVersionRequest.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceConfigVersionRequest.java
@@ -18,6 +18,10 @@
 
 package org.apache.ambari.server.controller;
 
+import org.apache.ambari.server.controller.internal.ServiceConfigVersionResourceProvider;
+
+import io.swagger.annotations.ApiModelProperty;
+
 public class ServiceConfigVersionRequest {
   private String clusterName;
   private String serviceName;
@@ -41,6 +45,7 @@ public class ServiceConfigVersionRequest {
     this.isCurrent = isCurrent;
   }
 
+  @ApiModelProperty(name = ServiceConfigVersionResourceProvider.SERVICE_NAME_PROPERTY_ID)
   public String getServiceName() {
     return serviceName;
   }
@@ -49,6 +54,7 @@ public class ServiceConfigVersionRequest {
     this.serviceName = serviceName;
   }
 
+  @ApiModelProperty(name = ServiceConfigVersionResourceProvider.SERVICE_CONFIG_VERSION_PROPERTY_ID)
   public Long getVersion() {
     return version;
   }
@@ -57,6 +63,7 @@ public class ServiceConfigVersionRequest {
     this.version = version;
   }
 
+  @ApiModelProperty(name = ServiceConfigVersionResourceProvider.CREATE_TIME_PROPERTY_ID)
   public Long getCreateTime() {
     return createTime;
   }
@@ -65,6 +72,7 @@ public class ServiceConfigVersionRequest {
     this.createTime = createTime;
   }
 
+  @ApiModelProperty(name = ServiceConfigVersionResourceProvider.APPLIED_TIME_PROPERTY_ID)
   public Long getApplyTime() {
     return applyTime;
   }
@@ -73,6 +81,7 @@ public class ServiceConfigVersionRequest {
     this.applyTime = applyTime;
   }
 
+  @ApiModelProperty(name = ServiceConfigVersionResourceProvider.USER_PROPERTY_ID)
   public String getUserName() {
     return userName;
   }
@@ -81,6 +90,7 @@ public class ServiceConfigVersionRequest {
     this.userName = userName;
   }
 
+  @ApiModelProperty(name = ServiceConfigVersionResourceProvider.CLUSTER_NAME_PROPERTY_ID)
   public String getClusterName() {
     return clusterName;
   }
@@ -89,6 +99,7 @@ public class ServiceConfigVersionRequest {
     this.clusterName = clusterName;
   }
 
+  @ApiModelProperty(name = ServiceConfigVersionResourceProvider.SERVICE_CONFIG_VERSION_NOTE_PROPERTY_ID)
   public String getNote() {
     return note;
   }
@@ -97,6 +108,7 @@ public class ServiceConfigVersionRequest {
     this.note = note;
   }
 
+  @ApiModelProperty(name = ServiceConfigVersionResourceProvider.IS_CURRENT_PROPERTY_ID)
   public Boolean getIsCurrent() {
     return isCurrent;
   }
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceConfigVersionResponse.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceConfigVersionResponse.java
index 275d703..d0534e2 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceConfigVersionResponse.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceConfigVersionResponse.java
@@ -18,22 +18,27 @@
 
 package org.apache.ambari.server.controller;
 
-
 import java.util.List;
 
 import org.apache.ambari.server.StaticallyInject;
+import org.apache.ambari.server.controller.internal.ServiceConfigVersionResourceProvider;
 import org.apache.ambari.server.orm.dao.HostDAO;
 import org.apache.ambari.server.orm.entities.ClusterEntity;
 import org.apache.ambari.server.orm.entities.ServiceConfigEntity;
 import org.apache.ambari.server.orm.entities.StackEntity;
 import org.apache.ambari.server.state.StackId;
+
 import org.apache.commons.lang.builder.EqualsBuilder;
 import org.apache.commons.lang.builder.HashCodeBuilder;
+
 import org.codehaus.jackson.annotate.JsonProperty;
 import org.codehaus.jackson.map.annotate.JsonSerialize;
 
 import com.google.inject.Inject;
 
+import io.swagger.annotations.ApiModelProperty;
+
+
 @StaticallyInject
 public class ServiceConfigVersionResponse {
   /**
@@ -121,25 +126,32 @@ public class ServiceConfigVersionResponse {
     stackId = new StackId(serviceConfigStackEntity).getStackId();
   }
 
+  @ApiModelProperty(name = ServiceConfigVersionResourceProvider.SERVICE_NAME_PROPERTY_ID)
   public String getServiceName() {
     return serviceName;
   }
 
+  @ApiModelProperty(name = ServiceConfigVersionResourceProvider.SERVICE_CONFIG_VERSION_PROPERTY_ID)
   public Long getVersion() {
     return version;
   }
 
+  @ApiModelProperty(name = ServiceConfigVersionResourceProvider.CREATE_TIME_PROPERTY_ID)
   public Long getCreateTime() {
     return createTime;
   }
 
+  @ApiModelProperty(name = ServiceConfigVersionResourceProvider.USER_PROPERTY_ID)
   public String getUserName() {
     return userName;
   }
+
+  @ApiModelProperty(name = ServiceConfigVersionResourceProvider.CLUSTER_NAME_PROPERTY_ID)
   public String getClusterName() {
     return clusterName;
   }
 
+  @ApiModelProperty(name = ServiceConfigVersionResourceProvider.CONFIGURATIONS_PROPERTY_ID)
   public List<ConfigurationResponse> getConfigurations() {
     return configurations;
   }
@@ -148,18 +160,22 @@ public class ServiceConfigVersionResponse {
     this.configurations = configurations;
   }
 
+  @ApiModelProperty(name = ServiceConfigVersionResourceProvider.SERVICE_CONFIG_VERSION_NOTE_PROPERTY_ID)
   public String getNote() {
     return note;
   }
 
+  @ApiModelProperty(name = ServiceConfigVersionResourceProvider.HOSTS_PROPERTY_ID)
   public List<String> getHosts() {
     return hosts;
   }
 
+  @ApiModelProperty(name = ServiceConfigVersionResourceProvider.GROUP_NAME_PROPERTY_ID)
   public String getGroupName() {
     return groupName;
   }
 
+  @ApiModelProperty(name = ServiceConfigVersionResourceProvider.GROUP_ID_PROPERTY_ID)
   public Long getGroupId() {
     return groupId;
   }
@@ -169,10 +185,12 @@ public class ServiceConfigVersionResponse {
    *
    * @return
    */
+  @ApiModelProperty(name = ServiceConfigVersionResourceProvider.STACK_ID_PROPERTY_ID)
   public String getStackId() {
     return stackId;
   }
 
+  @ApiModelProperty(name = ServiceConfigVersionResourceProvider.IS_CURRENT_PROPERTY_ID)
   public Boolean getIsCurrent() {
     return isCurrent;
   }
@@ -187,6 +205,7 @@ public class ServiceConfigVersionResponse {
    *
    * @return {@code true} if compatible, {@code false} otherwise.
    */
+  @ApiModelProperty(name = ServiceConfigVersionResourceProvider.IS_COMPATIBLE_PROPERTY_ID)
   public Boolean isCompatibleWithCurrentStack() {
     return isCompatibleWithCurrentStack;
   }
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java
index 16f04e4..96823c2 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java
@@ -327,19 +327,19 @@ public class ClusterResourceProvider extends AbstractControllerResourceProvider
           for (Collection<ServiceConfigVersionResponse> scvCollection : serviceConfigVersions.values()) {
             for (ServiceConfigVersionResponse serviceConfigVersionResponse : scvCollection) {
               Resource resource = new ResourceImpl(Resource.Type.ServiceConfigVersion);
-              resource.setProperty(ServiceConfigVersionResourceProvider.SERVICE_CONFIG_VERSION_SERVICE_NAME_PROPERTY_ID,
+              resource.setProperty(ServiceConfigVersionResourceProvider.SERVICE_NAME_PROPERTY_ID,
                 serviceConfigVersionResponse.getServiceName());
               resource.setProperty(ServiceConfigVersionResourceProvider.SERVICE_CONFIG_VERSION_PROPERTY_ID,
                 serviceConfigVersionResponse.getVersion());
               resource.setProperty(ServiceConfigVersionResourceProvider.SERVICE_CONFIG_VERSION_NOTE_PROPERTY_ID,
                 serviceConfigVersionResponse.getNote());
-              resource.setProperty(ServiceConfigVersionResourceProvider.SERVICE_CONFIG_VERSION_GROUP_ID_PROPERTY_ID,
+              resource.setProperty(ServiceConfigVersionResourceProvider.GROUP_ID_PROPERTY_ID,
                   serviceConfigVersionResponse.getGroupId());
-              resource.setProperty(ServiceConfigVersionResourceProvider.SERVICE_CONFIG_VERSION_GROUP_NAME_PROPERTY_ID,
+              resource.setProperty(ServiceConfigVersionResourceProvider.GROUP_NAME_PROPERTY_ID,
                   serviceConfigVersionResponse.getGroupName());
               if (serviceConfigVersionResponse.getConfigurations() != null) {
                 resource.setProperty(
-                  ServiceConfigVersionResourceProvider.SERVICE_CONFIG_VERSION_CONFIGURATIONS_PROPERTY_ID,
+                  ServiceConfigVersionResourceProvider.CONFIGURATIONS_PROPERTY_ID,
                   serviceConfigVersionResponse.getConfigurations());
               }
               associatedResources.add(resource);
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceConfigVersionResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceConfigVersionResourceProvider.java
index 1019e57..24febe8 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceConfigVersionResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceConfigVersionResourceProvider.java
@@ -44,25 +44,25 @@ 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.PropertyHelper;
 import org.apache.ambari.server.security.authorization.RoleAuthorization;
 
 public class ServiceConfigVersionResourceProvider extends
     AbstractControllerResourceProvider {
 
-  public static final String SERVICE_CONFIG_VERSION_CLUSTER_NAME_PROPERTY_ID = PropertyHelper.getPropertyId(null, "cluster_name");
-  public static final String SERVICE_CONFIG_VERSION_PROPERTY_ID = PropertyHelper.getPropertyId(null, "service_config_version");
-  public static final String SERVICE_CONFIG_VERSION_SERVICE_NAME_PROPERTY_ID = PropertyHelper.getPropertyId(null, "service_name");
-  public static final String SERVICE_CONFIG_VERSION_CREATE_TIME_PROPERTY_ID = PropertyHelper.getPropertyId(null, "createtime");
-  public static final String SERVICE_CONFIG_VERSION_USER_PROPERTY_ID = PropertyHelper.getPropertyId(null, "user");
-  public static final String SERVICE_CONFIG_VERSION_NOTE_PROPERTY_ID = PropertyHelper.getPropertyId(null, "service_config_version_note");
-  public static final String SERVICE_CONFIG_VERSION_GROUP_ID_PROPERTY_ID = PropertyHelper.getPropertyId(null, "group_id");
-  public static final String SERVICE_CONFIG_VERSION_GROUP_NAME_PROPERTY_ID = PropertyHelper.getPropertyId(null, "group_name");
-  public static final String SERVICE_CONFIG_VERSION_STACK_ID_PROPERTY_ID = PropertyHelper.getPropertyId(null, "stack_id");
-  public static final String SERVICE_CONFIG_VERSION_IS_CURRENT_PROPERTY_ID = PropertyHelper.getPropertyId(null, "is_current");
-  public static final String SERVICE_CONFIG_VERSION_IS_COMPATIBLE_PROPERTY_ID = PropertyHelper.getPropertyId(null, "is_cluster_compatible");
-  public static final String SERVICE_CONFIG_VERSION_HOSTS_PROPERTY_ID = PropertyHelper.getPropertyId(null, "hosts");
-  public static final String SERVICE_CONFIG_VERSION_CONFIGURATIONS_PROPERTY_ID = PropertyHelper.getPropertyId(null, "configurations");
+  public static final String CLUSTER_NAME_PROPERTY_ID = "cluster_name";
+  public static final String SERVICE_CONFIG_VERSION_PROPERTY_ID = "service_config_version";
+  public static final String SERVICE_NAME_PROPERTY_ID = "service_name";
+  public static final String CREATE_TIME_PROPERTY_ID = "createtime";
+  public static final String USER_PROPERTY_ID = "user";
+  public static final String SERVICE_CONFIG_VERSION_NOTE_PROPERTY_ID = "service_config_version_note";
+  public static final String GROUP_ID_PROPERTY_ID = "group_id";
+  public static final String GROUP_NAME_PROPERTY_ID = "group_name";
+  public static final String STACK_ID_PROPERTY_ID = "stack_id";
+  public static final String IS_CURRENT_PROPERTY_ID = "is_current";
+  public static final String IS_COMPATIBLE_PROPERTY_ID = "is_cluster_compatible";
+  public static final String HOSTS_PROPERTY_ID = "hosts";
+  public static final String CONFIGURATIONS_PROPERTY_ID = "configurations";
+  public static final String APPLIED_TIME_PROPERTY_ID = "appliedtime";
 
   /**
    * The property ids for a service configuration resource.
@@ -76,23 +76,23 @@ public class ServiceConfigVersionResourceProvider extends
 
   static {
     // properties
-    PROPERTY_IDS.add(SERVICE_CONFIG_VERSION_CLUSTER_NAME_PROPERTY_ID);
+    PROPERTY_IDS.add(CLUSTER_NAME_PROPERTY_ID);
     PROPERTY_IDS.add(SERVICE_CONFIG_VERSION_PROPERTY_ID);
-    PROPERTY_IDS.add(SERVICE_CONFIG_VERSION_SERVICE_NAME_PROPERTY_ID);
-    PROPERTY_IDS.add(SERVICE_CONFIG_VERSION_CREATE_TIME_PROPERTY_ID);
-    PROPERTY_IDS.add(SERVICE_CONFIG_VERSION_USER_PROPERTY_ID);
+    PROPERTY_IDS.add(SERVICE_NAME_PROPERTY_ID);
+    PROPERTY_IDS.add(CREATE_TIME_PROPERTY_ID);
+    PROPERTY_IDS.add(USER_PROPERTY_ID);
     PROPERTY_IDS.add(SERVICE_CONFIG_VERSION_NOTE_PROPERTY_ID);
-    PROPERTY_IDS.add(SERVICE_CONFIG_VERSION_GROUP_ID_PROPERTY_ID);
-    PROPERTY_IDS.add(SERVICE_CONFIG_VERSION_GROUP_NAME_PROPERTY_ID);
-    PROPERTY_IDS.add(SERVICE_CONFIG_VERSION_STACK_ID_PROPERTY_ID);
-    PROPERTY_IDS.add(SERVICE_CONFIG_VERSION_IS_CURRENT_PROPERTY_ID);
-    PROPERTY_IDS.add(SERVICE_CONFIG_VERSION_HOSTS_PROPERTY_ID);
-    PROPERTY_IDS.add(SERVICE_CONFIG_VERSION_CONFIGURATIONS_PROPERTY_ID);
-    PROPERTY_IDS.add(SERVICE_CONFIG_VERSION_IS_COMPATIBLE_PROPERTY_ID);
+    PROPERTY_IDS.add(GROUP_ID_PROPERTY_ID);
+    PROPERTY_IDS.add(GROUP_NAME_PROPERTY_ID);
+    PROPERTY_IDS.add(STACK_ID_PROPERTY_ID);
+    PROPERTY_IDS.add(IS_CURRENT_PROPERTY_ID);
+    PROPERTY_IDS.add(HOSTS_PROPERTY_ID);
+    PROPERTY_IDS.add(CONFIGURATIONS_PROPERTY_ID);
+    PROPERTY_IDS.add(IS_COMPATIBLE_PROPERTY_ID);
 
     // keys
-    KEY_PROPERTY_IDS.put(Resource.Type.Service,SERVICE_CONFIG_VERSION_SERVICE_NAME_PROPERTY_ID);
-    KEY_PROPERTY_IDS.put(Resource.Type.Cluster,SERVICE_CONFIG_VERSION_CLUSTER_NAME_PROPERTY_ID);
+    KEY_PROPERTY_IDS.put(Resource.Type.Service, SERVICE_NAME_PROPERTY_ID);
+    KEY_PROPERTY_IDS.put(Resource.Type.Cluster, CLUSTER_NAME_PROPERTY_ID);
     KEY_PROPERTY_IDS.put(Resource.Type.ServiceConfigVersion,SERVICE_CONFIG_VERSION_PROPERTY_ID);
   }
 
@@ -102,8 +102,8 @@ public class ServiceConfigVersionResourceProvider extends
    */
   private static Set<String> pkPropertyIds =
     new HashSet<>(Arrays.asList(new String[]{
-      SERVICE_CONFIG_VERSION_CLUSTER_NAME_PROPERTY_ID,
-      SERVICE_CONFIG_VERSION_SERVICE_NAME_PROPERTY_ID}));
+            CLUSTER_NAME_PROPERTY_ID,
+            SERVICE_NAME_PROPERTY_ID}));
 
 
   // ----- Constructors ------------------------------------------------------
@@ -154,19 +154,19 @@ public class ServiceConfigVersionResourceProvider extends
       List<Map<String,Object>> configVersionConfigurations = convertToSubResources(clusterName, configurationResponses);
 
       Resource resource = new ResourceImpl(Resource.Type.ServiceConfigVersion);
-      resource.setProperty(SERVICE_CONFIG_VERSION_CLUSTER_NAME_PROPERTY_ID, clusterName);
-      resource.setProperty(SERVICE_CONFIG_VERSION_SERVICE_NAME_PROPERTY_ID, response.getServiceName());
-      resource.setProperty(SERVICE_CONFIG_VERSION_USER_PROPERTY_ID, response.getUserName());
+      resource.setProperty(CLUSTER_NAME_PROPERTY_ID, clusterName);
+      resource.setProperty(SERVICE_NAME_PROPERTY_ID, response.getServiceName());
+      resource.setProperty(USER_PROPERTY_ID, response.getUserName());
       resource.setProperty(SERVICE_CONFIG_VERSION_PROPERTY_ID, response.getVersion());
-      resource.setProperty(SERVICE_CONFIG_VERSION_CREATE_TIME_PROPERTY_ID, response.getCreateTime());
-      resource.setProperty(SERVICE_CONFIG_VERSION_CONFIGURATIONS_PROPERTY_ID, configVersionConfigurations);
+      resource.setProperty(CREATE_TIME_PROPERTY_ID, response.getCreateTime());
+      resource.setProperty(CONFIGURATIONS_PROPERTY_ID, configVersionConfigurations);
       resource.setProperty(SERVICE_CONFIG_VERSION_NOTE_PROPERTY_ID, response.getNote());
-      resource.setProperty(SERVICE_CONFIG_VERSION_GROUP_ID_PROPERTY_ID, response.getGroupId());
-      resource.setProperty(SERVICE_CONFIG_VERSION_GROUP_NAME_PROPERTY_ID, response.getGroupName());
-      resource.setProperty(SERVICE_CONFIG_VERSION_HOSTS_PROPERTY_ID, response.getHosts());
-      resource.setProperty(SERVICE_CONFIG_VERSION_STACK_ID_PROPERTY_ID, response.getStackId());
-      resource.setProperty(SERVICE_CONFIG_VERSION_IS_CURRENT_PROPERTY_ID, response.getIsCurrent());
-      resource.setProperty(SERVICE_CONFIG_VERSION_IS_COMPATIBLE_PROPERTY_ID, response.isCompatibleWithCurrentStack());
+      resource.setProperty(GROUP_ID_PROPERTY_ID, response.getGroupId());
+      resource.setProperty(GROUP_NAME_PROPERTY_ID, response.getGroupName());
+      resource.setProperty(HOSTS_PROPERTY_ID, response.getHosts());
+      resource.setProperty(STACK_ID_PROPERTY_ID, response.getStackId());
+      resource.setProperty(IS_CURRENT_PROPERTY_ID, response.getIsCurrent());
+      resource.setProperty(IS_COMPATIBLE_PROPERTY_ID, response.isCompatibleWithCurrentStack());
 
       resources.add(resource);
     }
@@ -213,10 +213,10 @@ public class ServiceConfigVersionResourceProvider extends
 
 
   private ServiceConfigVersionRequest createRequest(Map<String, Object> properties) {
-    String clusterName = (String) properties.get(SERVICE_CONFIG_VERSION_CLUSTER_NAME_PROPERTY_ID);
-    String serviceName = (String) properties.get(SERVICE_CONFIG_VERSION_SERVICE_NAME_PROPERTY_ID);
-    String user = (String) properties.get(SERVICE_CONFIG_VERSION_USER_PROPERTY_ID);
-    Boolean isCurrent = Boolean.valueOf((String) properties.get(SERVICE_CONFIG_VERSION_IS_CURRENT_PROPERTY_ID));
+    String clusterName = (String) properties.get(CLUSTER_NAME_PROPERTY_ID);
+    String serviceName = (String) properties.get(SERVICE_NAME_PROPERTY_ID);
+    String user = (String) properties.get(USER_PROPERTY_ID);
+    Boolean isCurrent = Boolean.valueOf((String) properties.get(IS_CURRENT_PROPERTY_ID));
     Object versionObject = properties.get(SERVICE_CONFIG_VERSION_PROPERTY_ID);
     Long version = versionObject == null ? null : Long.valueOf(versionObject.toString());
 
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/metrics/system/impl/AmbariMetricSinkImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/metrics/system/impl/AmbariMetricSinkImpl.java
index a0346f6..2a5b69e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/metrics/system/impl/AmbariMetricSinkImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/metrics/system/impl/AmbariMetricSinkImpl.java
@@ -128,12 +128,12 @@ public class AmbariMetricSinkImpl extends AbstractTimelineMetricsSink implements
       }
 
       Set<String> propertyIds = new HashSet<>();
-      propertyIds.add(ServiceConfigVersionResourceProvider.SERVICE_CONFIG_VERSION_CONFIGURATIONS_PROPERTY_ID);
+      propertyIds.add(ServiceConfigVersionResourceProvider.CONFIGURATIONS_PROPERTY_ID);
 
       Predicate predicate = new PredicateBuilder().property(
-        ServiceConfigVersionResourceProvider.SERVICE_CONFIG_VERSION_CLUSTER_NAME_PROPERTY_ID).equals(clusterName).and().property(
-        ServiceConfigVersionResourceProvider.SERVICE_CONFIG_VERSION_SERVICE_NAME_PROPERTY_ID).equals(ambariMetricsServiceName).and().property(
-        ServiceConfigVersionResourceProvider.SERVICE_CONFIG_VERSION_IS_CURRENT_PROPERTY_ID).equals("true").toPredicate();
+        ServiceConfigVersionResourceProvider.CLUSTER_NAME_PROPERTY_ID).equals(clusterName).and().property(
+        ServiceConfigVersionResourceProvider.SERVICE_NAME_PROPERTY_ID).equals(ambariMetricsServiceName).and().property(
+        ServiceConfigVersionResourceProvider.IS_CURRENT_PROPERTY_ID).equals("true").toPredicate();
 
       Request request = PropertyHelper.getReadRequest(propertyIds);
 
@@ -163,7 +163,7 @@ public class AmbariMetricSinkImpl extends AbstractTimelineMetricsSink implements
         for (Resource resource : resources) {
           if (resource != null) {
             ArrayList<LinkedHashMap<Object, Object>> configs = (ArrayList<LinkedHashMap<Object, Object>>)
-              resource.getPropertyValue(ServiceConfigVersionResourceProvider.SERVICE_CONFIG_VERSION_CONFIGURATIONS_PROPERTY_ID);
+              resource.getPropertyValue(ServiceConfigVersionResourceProvider.CONFIGURATIONS_PROPERTY_ID);
             for (LinkedHashMap<Object, Object> config : configs) {
               if (config != null && config.get("type").equals("ams-site")) {
                 TreeMap<Object, Object> properties = (TreeMap<Object, Object>) config.get("properties");

-- 
To stop receiving notification emails like this one, please contact
adoroszlai@apache.org.

[ambari] 02/03: AMBARI-23436 - add SwaggerOverwriteNestedAPI annotation to handle special API cases

Posted by ad...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

adoroszlai pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ambari.git

commit 86735210772b858654fb47becac5cb99af4c64bc
Author: Gabor Boros <63...@users.noreply.github.com>
AuthorDate: Fri Apr 6 13:29:54 2018 +0200

    AMBARI-23436 - add SwaggerOverwriteNestedAPI annotation to handle
    special API cases
    
    Change-Id: I346de6f2d6f23eb7720b21bec2a4056a43df2a44
---
 .../annotations/SwaggerOverwriteNestedAPI.java     | 63 ++++++++++++++++++++++
 .../apache/ambari/swagger/AmbariSwaggerReader.java | 44 ++++++++++++---
 .../ambari/swagger/AmbariSwaggerReaderTest.java    | 43 +++++++++++++++
 3 files changed, 143 insertions(+), 7 deletions(-)

diff --git a/ambari-utility/src/main/java/org/apache/ambari/annotations/SwaggerOverwriteNestedAPI.java b/ambari-utility/src/main/java/org/apache/ambari/annotations/SwaggerOverwriteNestedAPI.java
new file mode 100644
index 0000000..29e4024
--- /dev/null
+++ b/ambari-utility/src/main/java/org/apache/ambari/annotations/SwaggerOverwriteNestedAPI.java
@@ -0,0 +1,63 @@
+/*
+ * 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.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * The {@link SwaggerOverwriteNestedAPI} is used to overwrite default values of
+ * {@link org.apache.ambari.swagger.NestedApiRecord} when {@link org.apache.ambari.swagger.AmbariSwaggerReader}
+ * processes nested API classes for Swagger annotations.
+ *
+ * It can be useful to overcome the limitations of multi-nested service endpoints or endpoints without Path
+ * parameters.
+ *
+ * Parent API and its properties are not validated.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface SwaggerOverwriteNestedAPI {
+
+    /**
+     * Class name of parent object
+     * @return
+     */
+    Class parentApi();
+
+    /**
+     * Parent API path, usually top-level API path starting with slash.
+     * @return
+     */
+    String parentApiPath();
+
+    /**
+     * Path annotation value of the method in parent class.
+     * @return
+     */
+    String parentMethodPath();
+
+    /**
+     * Array of Strings to provide path parameters. Only string types are supported as of now.
+     * @return
+     */
+    String[] pathParameters();
+}
diff --git a/ambari-utility/src/main/java/org/apache/ambari/swagger/AmbariSwaggerReader.java b/ambari-utility/src/main/java/org/apache/ambari/swagger/AmbariSwaggerReader.java
index 1e0898d..4da9f2d 100644
--- a/ambari-utility/src/main/java/org/apache/ambari/swagger/AmbariSwaggerReader.java
+++ b/ambari-utility/src/main/java/org/apache/ambari/swagger/AmbariSwaggerReader.java
@@ -18,12 +18,14 @@
 package org.apache.ambari.swagger;
 
 import java.lang.reflect.Method;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
 import javax.ws.rs.Path;
 
+import org.apache.ambari.annotations.SwaggerOverwriteNestedAPI;
 import org.apache.ambari.annotations.SwaggerPreferredParent;
 import org.apache.maven.plugin.logging.Log;
 import org.slf4j.Logger;
@@ -44,6 +46,7 @@ import io.swagger.models.Swagger;
 import io.swagger.models.Tag;
 import io.swagger.models.parameters.Parameter;
 import io.swagger.models.parameters.PathParameter;
+import io.swagger.models.properties.StringProperty;
 
 /**
  * Customized {@link com.github.kongchen.swagger.docgen.reader.ClassSwaggerReader} implementation to
@@ -95,6 +98,8 @@ public class AmbariSwaggerReader extends JaxrsReader {
             else {
               boolean skipAdd = false;
               Class<?> preferredParentClass = cls;
+              String parentApiPath;
+              String methodPathAsString = methodPath.value();
 
               // API is a nested API of multiple top level APIs
               if (nestedAPIs.containsKey(returnType)) {
@@ -128,9 +133,20 @@ public class AmbariSwaggerReader extends JaxrsReader {
                 nestedAPIs.remove(returnType);
               }
 
+              // API parent customization by @SwaggerOverwriteNestedAPI
+              SwaggerOverwriteNestedAPI swaggerOverwriteNestedAPI = AnnotationUtils.findAnnotation(returnType,
+                      SwaggerOverwriteNestedAPI.class);
+              if (null != swaggerOverwriteNestedAPI) {
+                preferredParentClass = swaggerOverwriteNestedAPI.parentApi();
+                parentApiPath = swaggerOverwriteNestedAPI.parentApiPath();
+                methodPathAsString = swaggerOverwriteNestedAPI.parentMethodPath();
+              } else {
+                parentApiPath = validateParentApiPath(preferredParentClass);
+              }
+
               logger.info("Registering nested API: {}", returnType);
-              NestedApiRecord nar = new NestedApiRecord(returnType, preferredParentClass,
-                      validateParentApiPath(preferredParentClass), method, methodPath.value());
+              NestedApiRecord nar = new NestedApiRecord(returnType, preferredParentClass, parentApiPath, method,
+                methodPathAsString);
               nestedAPIs.put(returnType, nar);
             }
           }
@@ -168,13 +184,27 @@ public class AmbariSwaggerReader extends JaxrsReader {
     NestedApiRecord nestedApiRecord = nestedAPIs.get(cls);
     if (null != nestedApiRecord) {
       logger.info("Processing nested API: {}", nestedApiRecord);
-      // Get the path parameters of the parent API method. All methods of the nested API class should include these
-      // parameters.
-      Operation operation = parseMethod(nestedApiRecord.parentMethod);
-      List<Parameter> pathParameters = ImmutableList.copyOf(
+      List<Parameter> pathParameters = new ArrayList<>();
+      SwaggerOverwriteNestedAPI swaggerOverwriteNestedAPI = AnnotationUtils.findAnnotation(nestedApiRecord.nestedApi,
+        SwaggerOverwriteNestedAPI.class);
+      if (null != swaggerOverwriteNestedAPI) {
+        logger.info("Will use path params from @SwaggerOverwriteNestedAPI: {}", (Object[]) swaggerOverwriteNestedAPI
+          .pathParameters());
+        for (String param : swaggerOverwriteNestedAPI.pathParameters()) {
+          PathParameter pathParam = new PathParameter();
+          pathParam.setName(param);
+          pathParam.setType(StringProperty.TYPE);
+          pathParameters.add(pathParam);
+        }
+      } else {
+        // Get the path parameters of the parent API method. All methods of the nested API class should include these
+        // parameters.
+        Operation operation = parseMethod(nestedApiRecord.parentMethod);
+        pathParameters = ImmutableList.copyOf(
           Collections2.filter(operation.getParameters(), Predicates.instanceOf(PathParameter.class)));
-      logger.info("Will copy path params from parent method: {}",
+        logger.info("Will copy path params from parent method: {}",
           Lists.transform(pathParameters, new ParameterToName()));
+      }
       return super.read(cls,
           joinPaths(nestedApiRecord.parentApiPath, nestedApiRecord.parentMethodPath, parentPath),
           parentMethod, readHidden,
diff --git a/ambari-utility/src/test/java/org/apache/ambari/swagger/AmbariSwaggerReaderTest.java b/ambari-utility/src/test/java/org/apache/ambari/swagger/AmbariSwaggerReaderTest.java
index fbadafa..8ca519b 100644
--- a/ambari-utility/src/test/java/org/apache/ambari/swagger/AmbariSwaggerReaderTest.java
+++ b/ambari-utility/src/test/java/org/apache/ambari/swagger/AmbariSwaggerReaderTest.java
@@ -32,6 +32,7 @@ import javax.ws.rs.GET;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 
+import org.apache.ambari.annotations.SwaggerOverwriteNestedAPI;
 import org.apache.ambari.annotations.SwaggerPreferredParent;
 import org.apache.maven.plugin.logging.Log;
 import org.junit.Test;
@@ -145,6 +146,22 @@ public class AmbariSwaggerReaderTest {
   }
 
   /**
+   * Test nested API which uses {@link org.apache.ambari.annotations.SwaggerOverwriteNestedAPI} annotation.
+   * In this case we expect default values to be overwritten by the usage of the annotation.
+   */
+  @Test
+  public void swaggerNestedApisWithOverwrite() {
+    AmbariSwaggerReader asr = new AmbariSwaggerReader(null, createMock(Log.class));
+    Set<Class<?>> classes = new LinkedHashSet<>(Arrays.asList(NestedWithOverwrite.class, TopLevel4API.class));
+    Swagger swagger = asr.read(classes);
+    assertEquals(
+            ImmutableSet.of("/toplevel3/{foo}/bar/list", "/toplevel4/top"),
+            swagger.getPaths().keySet());
+    assertPathParamsExist(swagger, "/toplevel3/{foo}/bar/list", "foo");
+  }
+
+
+  /**
    * If an API is both top level (the class has a @Path annotation) and nested (class is a return type of an
    * API operation) then it should be treated as top level.
    */
@@ -235,6 +252,20 @@ abstract class YetAnotherTopLevelAPI {
 
 }
 
+@Path("/toplevel4")
+@Api(value = "Top Level 4", description = "Yet another top level API")
+abstract class TopLevel4API {
+
+  @GET
+  @Path("/top")
+  @ApiOperation(value = "list")
+  public abstract Response getList();
+
+  @Path("{param}/nested")
+  public abstract NestedWithOverwrite getNested(@ApiParam @PathParam(value = "param") String param);
+
+}
+
 @Api(value = "Nested", description = "A nested API")
 abstract class NestedAPI {
 
@@ -288,3 +319,15 @@ abstract class NestedWithBadPreferredParentAPI {
   public abstract Response getList();
 
 }
+
+@Api(value = "NestedWithOverWrite", description = "A nested API")
+@SwaggerOverwriteNestedAPI(parentApi = YetAnotherTopLevelAPI.class, parentApiPath = "/toplevel3", parentMethodPath =
+        "{foo}/bar", pathParameters = {"foo"})
+abstract class NestedWithOverwrite {
+
+  @GET
+  @Path("/list")
+  @ApiOperation(value = "list")
+  public abstract Response getList();
+
+}

-- 
To stop receiving notification emails like this one, please contact
adoroszlai@apache.org.