Make OpenAPI config conditional + add missing ddi methods descriptions (#1437)

* Swagger support initial concept

Signed-off-by: Stanislav Trailov <Stanislav.Trailov@bosch.io>

* Add descriptions for Target tags

Signed-off-by: Stanislav Trailov <Stanislav.Trailov@bosch.io>

* Add target filter queries descriptions

Signed-off-by: Stanislav Trailov <Stanislav.Trailov@bosch.io>

* Add target api descriptions

Signed-off-by: Stanislav Trailov <Stanislav.Trailov@bosch.io>

* Add software modules API descriptions

Signed-off-by: Stanislav Trailov <Stanislav.Trailov@bosch.io>

* Add descriptions for DS, DSTags and SMTypes

Signed-off-by: Stanislav Trailov <Stanislav.Trailov@bosch.io>

* Add DistributionSetType API descriptions

Signed-off-by: Stanislav Trailov <Stanislav.Trailov@bosch.io>

* Add Rollout API descriptions

Signed-off-by: Stanislav Trailov <Stanislav.Trailov@bosch.io>

* Bring back test scope to mariaDb

Signed-off-by: Stanislav Trailov <Stanislav.Trailov@bosch.io>

* Add tags and descriptions to System config API

Signed-off-by: Stanislav Trailov <Stanislav.Trailov@bosch.io>

* Move away OpenAPI config from Start.java

Signed-off-by: Stanislav Trailov <Stanislav.Trailov@bosch.io>

* provide license header and project version for openapi

Signed-off-by: Stanislav Trailov <Stanislav.Trailov@bosch.io>

* Fix error responses with example error body

Signed-off-by: Stanislav Trailov <Stanislav.Trailov@bosch.io>

* Add DDI API to swagger and make proper API grouping

Signed-off-by: Stanislav Trailov <Stanislav.Trailov@bosch.io>

* Revert changes from not merging before commit

Signed-off-by: Stanislav Trailov <Stanislav.Trailov@bosch.io>

* Remove more changes

Signed-off-by: Stanislav Trailov <Stanislav.Trailov@bosch.io>

* fix circle ci build

Signed-off-by: Stanislav Trailov <Stanislav.Trailov@bosch.io>

* Add missing descriptions for downloadArtifact methods in DDI

Signed-off-by: Stanislav Trailov <Stanislav.Trailov@bosch.io>

* Make configuration for openApi conditional for flexibility in transitive dependencies

Signed-off-by: Stanislav Trailov <Stanislav.Trailov@bosch.io>

* Make beans conditional not config

Signed-off-by: Stanislav Trailov <Stanislav.Trailov@bosch.io>

* Remove oAuth and switch to more general description

Signed-off-by: Stanislav Trailov <Stanislav.Trailov@bosch.io>

* remove comment

Signed-off-by: Stanislav Trailov <Stanislav.Trailov@bosch.io>

---------

Signed-off-by: Stanislav Trailov <Stanislav.Trailov@bosch.io>
This commit is contained in:
Stanislav Trailov
2023-09-27 11:44:46 +03:00
committed by GitHub
parent 3978454900
commit fd2f0293de
2 changed files with 35 additions and 23 deletions

View File

@@ -126,6 +126,17 @@ public interface DdiRootControllerRestApi {
* {@link HttpStatus#OK} or in case of partial download
* {@link HttpStatus#PARTIAL_CONTENT}.
*/
@Operation(summary = "Artifact download", description = "Handles GET DdiArtifact download request. This could be full or partial (as specified by RFC7233 (Range Requests)) download request.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or data volume restriction applies.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "404", description = "Target or Module not found", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "405", description = "The http request method is not allowed on the resource.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "406", description = "In case accept header is specified and not application/json.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "429", description = "Too many requests. The server will refuse further attempts and the client has to wait another second.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true)))
})
@GetMapping(value = DdiRestConstants.BASE_V1_REQUEST_MAPPING
+ "/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{fileName}")
ResponseEntity<InputStream> downloadArtifact(@PathVariable("tenant") final String tenant,
@@ -148,6 +159,17 @@ public interface DdiRootControllerRestApi {
* @return {@link ResponseEntity} with status {@link HttpStatus#OK} if
* successful
*/
@Operation(summary = "MD5 checksum download", description = "Handles GET {@link DdiArtifact} MD5 checksum file download request.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or data volume restriction applies.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "404", description = "Target or Module not found", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "405", description = "The http request method is not allowed on the resource.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "406", description = "In case accept header is specified and not application/json.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "429", description = "Too many requests. The server will refuse further attempts and the client has to wait another second.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true)))
})
@GetMapping(value = DdiRestConstants.BASE_V1_REQUEST_MAPPING
+ "/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{fileName}"
+ DdiRestConstants.ARTIFACT_MD5_DWNL_SUFFIX, produces = MediaType.TEXT_PLAIN_VALUE)

View File

@@ -12,35 +12,29 @@ package org.eclipse.hawkbit.rest;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.security.OAuthFlow;
import io.swagger.v3.oas.models.security.OAuthFlows;
import io.swagger.v3.oas.models.security.Scopes;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import org.springdoc.core.GroupedOpenApi;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class OpenApiConfiguration {
private static final String DESCRIPTION = """
The Management API is a RESTful API that enables to perform Create/Read/Update/Delete operations for provisioning targets
(i.e. devices) and repository content (i.e. software). Based on the Management API you can manage and monitor software update
operations via HTTP/HTTPS. The Management API supports JSON payload with hypermedia as well as filtering, sorting and paging.
Furthermore the Management API provides permission based access control and standard roles as well as custom role creation.
The API is protected and needs authentication and authorization based on the security concept.
Eclipse hawkBit™ is a domain-independent back-end framework for rolling out software updates to constrained edge devices as well as more powerful controllers and gateways connected to IP based networking infrastructure.
""";
@Bean
public OpenAPI customOpenApi() {
final String apiTitle = "hawkBit Management REST API";
final String apiTitle = "hawkBit REST APIs";
final String basiAuthSecSchemeName = "basicAuth";
final String oauth2SecSchemeName = "OAuth2";
final String bearerAuthenticationSchemeName = "Bearer Authentication";
return new OpenAPI()
.addSecurityItem(new SecurityRequirement().addList(basiAuthSecSchemeName))
.addSecurityItem(new SecurityRequirement().addList(oauth2SecSchemeName))
.addSecurityItem(new SecurityRequirement().addList(bearerAuthenticationSchemeName))
.components(
new Components()
@@ -51,18 +45,6 @@ public class OpenApiConfiguration {
.in(SecurityScheme.In.HEADER)
.scheme("basic")
)
.addSecuritySchemes(oauth2SecSchemeName,
new SecurityScheme()
.name(oauth2SecSchemeName)
.type(SecurityScheme.Type.OAUTH2)
.flows(new OAuthFlows().authorizationCode(new OAuthFlow()
.authorizationUrl("${spring.security.oauth2.client.provider.suite.authorization-uri}")
.tokenUrl("${spring.security.oauth2.client.provider.suite.token-uri}")
.refreshUrl("${spring.security.oauth2.client.provider.suite.token-uri}")
.scopes(new Scopes()
.addString("openid", "openid")
.addString("offline_access", "offline_access"))))
)
.addSecuritySchemes(bearerAuthenticationSchemeName,
new SecurityScheme()
.name(bearerAuthenticationSchemeName)
@@ -73,6 +55,10 @@ public class OpenApiConfiguration {
}
@Bean
@ConditionalOnProperty(
value="hawkbit.server.swagger.mgmt.api.group.enabled",
havingValue = "true",
matchIfMissing = true)
public GroupedOpenApi mgmtApi() {
return GroupedOpenApi.builder()
.group("Management API")
@@ -81,6 +67,10 @@ public class OpenApiConfiguration {
}
@Bean
@ConditionalOnProperty(
value="hawkbit.server.swagger.ddi.api.group.enabled",
havingValue = "true",
matchIfMissing = true)
public GroupedOpenApi ddiApi() {
return GroupedOpenApi.builder()
.group("Direct Device Integration API")