From 87c4cd8cd17ed1485c17114ec069a3d118535035 Mon Sep 17 00:00:00 2001 From: Avgustin Marinov Date: Tue, 10 Feb 2026 12:50:31 +0200 Subject: [PATCH] Remove not used WeightValidationHelper (#2916) Signed-off-by: Avgustin Marinov --- hawkbit-ddi/hawkbit-ddi-server/README.md | 2 +- hawkbit-ddi/hawkbit-ddi-server/pom.xml | 2 +- .../app/ddi/{DDIStart.java => DdiStart.java} | 4 +- hawkbit-dmf/hawkbit-dmf-server/README.md | 2 +- hawkbit-dmf/hawkbit-dmf-server/pom.xml | 2 +- .../app/dmf/{DMFStart.java => DmfStart.java} | 4 +- hawkbit-mcp/pom.xml | 2 +- ...erApplication.java => McpServerStart.java} | 8 +- .../client/AuthenticationValidator.java | 3 +- .../HawkbitAuthenticationValidator.java | 16 ++-- .../client/McpAuthenticationException.java | 2 +- .../config/HawkbitClientConfiguration.java | 9 +- .../server/config/HawkbitMcpProperties.java | 36 +++++--- .../config/McpHttpClientConfiguration.java | 3 +- .../config/McpSecurityConfiguration.java | 28 +++--- .../config/McpStdioClientConfiguration.java | 8 +- .../server/config/McpToolConfiguration.java | 6 +- .../hawkbit/mcp/server/dto/ActionRequest.java | 6 +- .../hawkbit/mcp/server/dto/ListRequest.java | 7 +- .../mcp/server/dto/OperationResponse.java | 9 +- .../hawkbit/mcp/server/dto/PagedResponse.java | 9 +- .../mcp/server/dto/RolloutRequest.java | 2 +- .../mcp/server/dto/SoftwareModuleRequest.java | 2 +- .../mcp/server/dto/TargetFilterRequest.java | 2 +- .../hawkbit/mcp/server/dto/TargetRequest.java | 2 +- .../server/prompts/HawkbitPromptProvider.java | 2 +- .../HawkbitDocumentationResource.java | 2 +- .../server/tools/HawkbitMcpToolProvider.java | 68 ++++++++------ .../repository/model/DeploymentRequest.java | 7 +- .../management/JpaDeploymentManagement.java | 2 - .../jpa/management/JpaRolloutManagement.java | 3 - .../JpaTargetFilterQueryManagement.java | 8 +- .../jpa/utils/WeightValidationHelper.java | 91 ------------------- .../java/org/eclipse/hawkbit/sdk/Tenant.java | 4 +- .../eclipse/hawkbit/sdk/dmf/amqp/Amqp.java | 7 +- 35 files changed, 134 insertions(+), 236 deletions(-) rename hawkbit-ddi/hawkbit-ddi-server/src/main/java/org/eclipse/hawkbit/app/ddi/{DDIStart.java => DdiStart.java} (94%) rename hawkbit-dmf/hawkbit-dmf-server/src/main/java/org/eclipse/hawkbit/app/dmf/{DMFStart.java => DmfStart.java} (91%) rename hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/{HawkbitMcpServerApplication.java => McpServerStart.java} (86%) delete mode 100644 hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/WeightValidationHelper.java diff --git a/hawkbit-ddi/hawkbit-ddi-server/README.md b/hawkbit-ddi/hawkbit-ddi-server/README.md index eacaeea07..26e84b8d3 100644 --- a/hawkbit-ddi/hawkbit-ddi-server/README.md +++ b/hawkbit-ddi/hawkbit-ddi-server/README.md @@ -16,7 +16,7 @@ _(Note: you have to add the JDBC driver also to your class path if you intend to Or: ```bash -run org.eclipse.hawkbit.app.ddi.DDIStart +run org.eclipse.hawkbit.app.ddi.DdiStart ``` ### Usage diff --git a/hawkbit-ddi/hawkbit-ddi-server/pom.xml b/hawkbit-ddi/hawkbit-ddi-server/pom.xml index 85c985234..4847906a0 100644 --- a/hawkbit-ddi/hawkbit-ddi-server/pom.xml +++ b/hawkbit-ddi/hawkbit-ddi-server/pom.xml @@ -22,7 +22,7 @@ hawkBit :: DDI :: Server - org.eclipse.hawkbit.app.ddi.DDIStart + org.eclipse.hawkbit.app.ddi.DdiStart diff --git a/hawkbit-ddi/hawkbit-ddi-server/src/main/java/org/eclipse/hawkbit/app/ddi/DDIStart.java b/hawkbit-ddi/hawkbit-ddi-server/src/main/java/org/eclipse/hawkbit/app/ddi/DdiStart.java similarity index 94% rename from hawkbit-ddi/hawkbit-ddi-server/src/main/java/org/eclipse/hawkbit/app/ddi/DDIStart.java rename to hawkbit-ddi/hawkbit-ddi-server/src/main/java/org/eclipse/hawkbit/app/ddi/DdiStart.java index 2eedb5e0d..dfdae986c 100644 --- a/hawkbit-ddi/hawkbit-ddi-server/src/main/java/org/eclipse/hawkbit/app/ddi/DDIStart.java +++ b/hawkbit-ddi/hawkbit-ddi-server/src/main/java/org/eclipse/hawkbit/app/ddi/DdiStart.java @@ -20,7 +20,7 @@ import org.springframework.web.servlet.view.RedirectView; * The minimal configuration for the stand alone hawkBit DDI server. */ @SpringBootApplication(scanBasePackages = "org.eclipse.hawkbit") -public class DDIStart { +public class DdiStart { /** * Main method to start the spring-boot application. @@ -28,7 +28,7 @@ public class DDIStart { * @param args the VM arguments. */ public static void main(final String[] args) { - SpringApplication.run(DDIStart.class, args); + SpringApplication.run(DdiStart.class, args); } @Controller diff --git a/hawkbit-dmf/hawkbit-dmf-server/README.md b/hawkbit-dmf/hawkbit-dmf-server/README.md index 24ef1ff05..19dde1234 100644 --- a/hawkbit-dmf/hawkbit-dmf-server/README.md +++ b/hawkbit-dmf/hawkbit-dmf-server/README.md @@ -12,7 +12,7 @@ _(Note: you have to add the JDBC driver also to your class path if you intend to Or: ```bash -run org.eclipse.hawkbit.app.dmf.DMFStart +run org.eclipse.hawkbit.app.dmf.DmfStart ``` # Clustering (Experimental!!!) ## Remote Events between micro-services diff --git a/hawkbit-dmf/hawkbit-dmf-server/pom.xml b/hawkbit-dmf/hawkbit-dmf-server/pom.xml index 1a7c08d53..d0aab8a76 100644 --- a/hawkbit-dmf/hawkbit-dmf-server/pom.xml +++ b/hawkbit-dmf/hawkbit-dmf-server/pom.xml @@ -22,7 +22,7 @@ hawkBit :: DMF :: Server - org.eclipse.hawkbit.app.ddi.DMFStart + org.eclipse.hawkbit.app.ddi.DmfStart diff --git a/hawkbit-dmf/hawkbit-dmf-server/src/main/java/org/eclipse/hawkbit/app/dmf/DMFStart.java b/hawkbit-dmf/hawkbit-dmf-server/src/main/java/org/eclipse/hawkbit/app/dmf/DmfStart.java similarity index 91% rename from hawkbit-dmf/hawkbit-dmf-server/src/main/java/org/eclipse/hawkbit/app/dmf/DMFStart.java rename to hawkbit-dmf/hawkbit-dmf-server/src/main/java/org/eclipse/hawkbit/app/dmf/DmfStart.java index fc9f4effa..4564f0e3b 100644 --- a/hawkbit-dmf/hawkbit-dmf-server/src/main/java/org/eclipse/hawkbit/app/dmf/DMFStart.java +++ b/hawkbit-dmf/hawkbit-dmf-server/src/main/java/org/eclipse/hawkbit/app/dmf/DmfStart.java @@ -17,7 +17,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; * The minimal configuration for the stand alone hawkBit DMF server. */ @SpringBootApplication(scanBasePackages = "org.eclipse.hawkbit") -public class DMFStart { +public class DmfStart { /** * Main method to start the spring-boot application. @@ -25,6 +25,6 @@ public class DMFStart { * @param args the VM arguments. */ public static void main(final String[] args) { - SpringApplication.run(DMFStart.class, args); + SpringApplication.run(DmfStart.class, args); } } \ No newline at end of file diff --git a/hawkbit-mcp/pom.xml b/hawkbit-mcp/pom.xml index 06087dfc1..f25cf8c12 100644 --- a/hawkbit-mcp/pom.xml +++ b/hawkbit-mcp/pom.xml @@ -23,7 +23,7 @@ Standalone MCP server that connects to hawkBit via REST API - org.eclipse.hawkbit.mcp.server.HawkbitMcpServerApplication + org.eclipse.hawkbit.mcp.server.McpServerStart diff --git a/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/HawkbitMcpServerApplication.java b/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/McpServerStart.java similarity index 86% rename from hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/HawkbitMcpServerApplication.java rename to hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/McpServerStart.java index eb3c7c674..f9fcccadd 100644 --- a/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/HawkbitMcpServerApplication.java +++ b/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/McpServerStart.java @@ -24,9 +24,9 @@ import org.springframework.boot.autoconfigure.security.servlet.UserDetailsServic */ @SpringBootApplication(exclude = UserDetailsServiceAutoConfiguration.class) @EnableConfigurationProperties(HawkbitMcpProperties.class) -public class HawkbitMcpServerApplication { +public class McpServerStart { - public static void main(String[] args) { - SpringApplication.run(HawkbitMcpServerApplication.class, args); + public static void main(final String[] args) { + SpringApplication.run(McpServerStart.class, args); } -} +} \ No newline at end of file diff --git a/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/client/AuthenticationValidator.java b/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/client/AuthenticationValidator.java index 870be1f88..f06b8d803 100644 --- a/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/client/AuthenticationValidator.java +++ b/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/client/AuthenticationValidator.java @@ -27,6 +27,7 @@ public interface AuthenticationValidator { * Result of authentication validation. */ enum ValidationResult { + /** * Credentials are valid (authenticated user). */ @@ -47,4 +48,4 @@ public interface AuthenticationValidator { */ HAWKBIT_ERROR } -} +} \ No newline at end of file diff --git a/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/client/HawkbitAuthenticationValidator.java b/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/client/HawkbitAuthenticationValidator.java index 274936c63..09c796515 100644 --- a/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/client/HawkbitAuthenticationValidator.java +++ b/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/client/HawkbitAuthenticationValidator.java @@ -9,6 +9,11 @@ */ package org.eclipse.hawkbit.mcp.server.client; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.HexFormat; + import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Caffeine; import feign.FeignException; @@ -21,11 +26,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; -import java.nio.charset.StandardCharsets; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.HexFormat; - /** * Validates authentication credentials against hawkBit REST API using the SDK. * This validator is conditionally created when {@code hawkbit.mcp.validation.enabled=true}. @@ -39,9 +39,7 @@ public class HawkbitAuthenticationValidator implements AuthenticationValidator { private final Tenant dummyTenant; private final Cache validationCache; - public HawkbitAuthenticationValidator(final HawkbitClient hawkbitClient, - final Tenant dummyTenant, - final HawkbitMcpProperties properties) { + public HawkbitAuthenticationValidator(final HawkbitClient hawkbitClient, final Tenant dummyTenant, final HawkbitMcpProperties properties) { this.hawkbitClient = hawkbitClient; this.dummyTenant = dummyTenant; @@ -127,4 +125,4 @@ public class HawkbitAuthenticationValidator implements AuthenticationValidator { throw new McpAuthenticationException("SHA-256 not available." + e.getMessage()); } } -} +} \ No newline at end of file diff --git a/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/client/McpAuthenticationException.java b/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/client/McpAuthenticationException.java index 9f07ceb06..e56ce8248 100644 --- a/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/client/McpAuthenticationException.java +++ b/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/client/McpAuthenticationException.java @@ -14,4 +14,4 @@ public class McpAuthenticationException extends RuntimeException { public McpAuthenticationException(String message) { super(message); } -} +} \ No newline at end of file diff --git a/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/config/HawkbitClientConfiguration.java b/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/config/HawkbitClientConfiguration.java index 78caefe5e..ac83f0c61 100644 --- a/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/config/HawkbitClientConfiguration.java +++ b/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/config/HawkbitClientConfiguration.java @@ -9,6 +9,8 @@ */ package org.eclipse.hawkbit.mcp.server.config; +import java.util.function.BiFunction; + import feign.Contract; import feign.RequestInterceptor; import feign.codec.Decoder; @@ -23,8 +25,6 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; -import java.util.function.BiFunction; - /** * Common configuration for the hawkBit SDK client. *

@@ -46,7 +46,7 @@ public class HawkbitClientConfiguration { @Bean @Primary public HawkbitServer hawkbitServer() { - HawkbitServer server = new HawkbitServer(); + final HawkbitServer server = new HawkbitServer(); server.setMgmtUrl(properties.getMgmtUrl()); log.info("Configured hawkBit server URL: {}", properties.getMgmtUrl()); return server; @@ -68,5 +68,4 @@ public class HawkbitClientConfiguration { .requestInterceptorFn(hawkbitRequestInterceptor) .build(); } - -} +} \ No newline at end of file diff --git a/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/config/HawkbitMcpProperties.java b/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/config/HawkbitMcpProperties.java index c2ebec782..808a6300f 100644 --- a/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/config/HawkbitMcpProperties.java +++ b/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/config/HawkbitMcpProperties.java @@ -26,6 +26,12 @@ import java.time.Duration; @ConfigurationProperties(prefix = "hawkbit.mcp") public class HawkbitMcpProperties { + public static final String OP_LIST = "list"; + public static final String OP_CREATE = "create"; + public static final String OP_UPDATE = "update"; + public static final String OP_DELETE = "delete"; + public static final String OP_DELETE_BATCH = "delete-batch"; + /** * Base URL of the hawkBit Management API (e.g., ...). */ @@ -56,19 +62,19 @@ public class HawkbitMcpProperties { /** * Whether to enable the built-in hawkBit tools. - * Set to false to provide custom tool implementations. + * Set to false to provide custom tool implementations. */ private boolean toolsEnabled = true; /** * Whether to enable the built-in hawkBit documentation resources. - * Set to false to provide custom resource implementations. + * Set false provide custom resource implementations. */ private boolean resourcesEnabled = true; /** * Whether to enable the built-in hawkBit prompts. - * Set to false to provide custom prompt implementations. + * Set false provide custom prompt implementations. */ private boolean promptsEnabled = true; @@ -130,10 +136,10 @@ public class HawkbitMcpProperties { */ public boolean isGlobalOperationEnabled(final String operation) { return switch (operation.toLowerCase()) { - case "list" -> listEnabled; - case "create" -> createEnabled; - case "update" -> updateEnabled; - case "delete" -> deleteEnabled; + case OP_LIST -> listEnabled; + case OP_CREATE -> createEnabled; + case OP_UPDATE -> updateEnabled; + case OP_DELETE -> deleteEnabled; default -> true; }; } @@ -155,10 +161,10 @@ public class HawkbitMcpProperties { */ public Boolean getOperationEnabled(final String operation) { return switch (operation.toLowerCase()) { - case "list" -> listEnabled; - case "create" -> createEnabled; - case "update" -> updateEnabled; - case "delete" -> deleteEnabled; + case OP_LIST -> listEnabled; + case OP_CREATE -> createEnabled; + case OP_UPDATE -> updateEnabled; + case OP_DELETE -> deleteEnabled; default -> null; }; } @@ -215,11 +221,11 @@ public class HawkbitMcpProperties { */ public Boolean getOperationEnabled(final String operation) { return switch (operation.toLowerCase().replace("_", "-")) { - case "list" -> listEnabled; - case "delete" -> deleteEnabled; - case "delete-batch" -> deleteBatchEnabled; + case OP_LIST -> listEnabled; + case OP_DELETE -> deleteEnabled; + case OP_DELETE_BATCH -> deleteBatchEnabled; default -> null; }; } } -} +} \ No newline at end of file diff --git a/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/config/McpHttpClientConfiguration.java b/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/config/McpHttpClientConfiguration.java index bf41a641f..764d78965 100644 --- a/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/config/McpHttpClientConfiguration.java +++ b/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/config/McpHttpClientConfiguration.java @@ -68,5 +68,4 @@ public class McpHttpClientConfiguration { log.info("Configured tenant for HTTP mode (per-request authentication)"); return new Tenant(); } - -} +} \ No newline at end of file diff --git a/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/config/McpSecurityConfiguration.java b/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/config/McpSecurityConfiguration.java index 1c5886ae2..51030c519 100644 --- a/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/config/McpSecurityConfiguration.java +++ b/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/config/McpSecurityConfiguration.java @@ -9,10 +9,14 @@ */ package org.eclipse.hawkbit.mcp.server.config; +import java.io.IOException; +import java.util.Optional; + import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; + import lombok.NonNull; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -33,9 +37,6 @@ import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.web.filter.OncePerRequestFilter; -import java.io.IOException; -import java.util.Optional; - /** * Security configuration for the MCP server. *

@@ -62,15 +63,14 @@ public class McpSecurityConfiguration { @SuppressWarnings("java:S4502") // CSRF protection is not needed for stateless REST APIs using Authorization header public SecurityFilterChain mcpSecurityFilterChain(final HttpSecurity http) throws Exception { http - .authorizeHttpRequests(auth -> auth.anyRequest().permitAll()) - .csrf(AbstractHttpConfigurer::disable) - .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)); + .authorizeHttpRequests(auth -> auth.anyRequest().permitAll()) + .csrf(AbstractHttpConfigurer::disable) + .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)); authenticationValidator.ifPresentOrElse( validator -> { log.info("Authentication validation enabled - adding validation filter"); - http.addFilterBefore(new HawkBitAuthenticationFilter(validator), - UsernamePasswordAuthenticationFilter.class); + http.addFilterBefore(new HawkBitAuthenticationFilter(validator), UsernamePasswordAuthenticationFilter.class); }, () -> log.info("Authentication validation disabled - requests will be forwarded without validation") ); @@ -91,8 +91,9 @@ public class McpSecurityConfiguration { private final AuthenticationValidator validator; @Override - protected void doFilterInternal(final HttpServletRequest request, final @NonNull HttpServletResponse response, - final @NonNull FilterChain filterChain) throws ServletException, IOException { + protected void doFilterInternal( + final HttpServletRequest request, final @NonNull HttpServletResponse response, final @NonNull FilterChain filterChain) + throws ServletException, IOException { final String authHeader = request.getHeader(HttpHeaders.AUTHORIZATION); final ValidationResult result = validator.validate(authHeader); @@ -120,10 +121,7 @@ public class McpSecurityConfiguration { throws IOException { response.setStatus(status.value()); response.setContentType(MediaType.APPLICATION_JSON_VALUE); - response.getWriter().write(String.format( - "{\"error\":\"%s\",\"message\":\"%s\"}", - status.getReasonPhrase(), - message)); + response.getWriter().write(String.format("{\"error\":\"%s\",\"message\":\"%s\"}", status.getReasonPhrase(), message)); } } -} +} \ No newline at end of file diff --git a/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/config/McpStdioClientConfiguration.java b/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/config/McpStdioClientConfiguration.java index bca2bdfdf..1b93e4d01 100644 --- a/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/config/McpStdioClientConfiguration.java +++ b/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/config/McpStdioClientConfiguration.java @@ -46,9 +46,8 @@ public class McpStdioClientConfiguration { log.info("Configuring STDIO mode request interceptor (static credentials)"); return (tenant, controller) -> template -> { if (properties.hasStaticCredentials()) { - String credentials = properties.getUsername() + ":" + properties.getPassword(); - String authHeader = "Basic " + Base64.getEncoder().encodeToString( - credentials.getBytes(StandardCharsets.UTF_8)); + final String credentials = properties.getUsername() + ":" + properties.getPassword(); + final String authHeader = "Basic " + Base64.getEncoder().encodeToString(credentials.getBytes(StandardCharsets.UTF_8)); template.header(HttpHeaders.AUTHORIZATION, authHeader); log.trace("Using static credentials from properties (STDIO mode)"); } else { @@ -72,5 +71,4 @@ public class McpStdioClientConfiguration { } return tenant; } - -} +} \ No newline at end of file diff --git a/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/config/McpToolConfiguration.java b/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/config/McpToolConfiguration.java index 6320303e2..c62eae265 100644 --- a/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/config/McpToolConfiguration.java +++ b/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/config/McpToolConfiguration.java @@ -45,9 +45,7 @@ public class McpToolConfiguration { @ConditionalOnMissingBean @ConditionalOnProperty(name = "hawkbit.mcp.tools-enabled", havingValue = "true", matchIfMissing = true) public HawkbitMcpToolProvider hawkBitMcpToolProvider( - final HawkbitClient hawkbitClient, - final Tenant dummyTenant, - final HawkbitMcpProperties properties) { + final HawkbitClient hawkbitClient, final Tenant dummyTenant, final HawkbitMcpProperties properties) { return new HawkbitMcpToolProvider(hawkbitClient, dummyTenant, properties); } @@ -80,4 +78,4 @@ public class McpToolConfiguration { public HawkbitPromptProvider hawkBitPromptProvider() { return new HawkbitPromptProvider(); } -} +} \ No newline at end of file diff --git a/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/dto/ActionRequest.java b/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/dto/ActionRequest.java index 3475002c2..7c8395ad0 100644 --- a/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/dto/ActionRequest.java +++ b/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/dto/ActionRequest.java @@ -9,11 +9,11 @@ */ package org.eclipse.hawkbit.mcp.server.dto; +import java.util.List; + import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; -import java.util.List; - /** * Sealed interface for action management operations. */ @@ -36,7 +36,7 @@ public sealed interface ActionRequest * Request to delete multiple actions. * * @param actionIds list of action IDs to delete (mutually exclusive with rsql) - * @param rsql RSQL filter query for selecting actions to delete (mutually exclusive with actionIds) + * @param rsql RSQL filter query for selecting actions to delete (mutually exclusive with actionIds) */ record DeleteBatch(List actionIds, String rsql) implements ActionRequest {} } diff --git a/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/dto/ListRequest.java b/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/dto/ListRequest.java index bc425a503..d64732dab 100644 --- a/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/dto/ListRequest.java +++ b/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/dto/ListRequest.java @@ -17,13 +17,10 @@ import com.fasterxml.jackson.annotation.JsonPropertyDescription; public record ListRequest( @JsonPropertyDescription("RSQL filter query (e.g., 'name==test*')") String rsql, - @JsonPropertyDescription("Number of items to skip (default: 0)") Integer offset, - @JsonPropertyDescription("Maximum number of items to return (default: 50)") - Integer limit -) { + Integer limit) { public static final int DEFAULT_OFFSET = 0; public static final int DEFAULT_LIMIT = 50; @@ -39,4 +36,4 @@ public record ListRequest( public String getRsqlOrNull() { return rsql != null && !rsql.isBlank() ? rsql : null; } -} +} \ No newline at end of file diff --git a/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/dto/OperationResponse.java b/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/dto/OperationResponse.java index 40a056e28..c9444f57c 100644 --- a/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/dto/OperationResponse.java +++ b/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/dto/OperationResponse.java @@ -18,12 +18,7 @@ package org.eclipse.hawkbit.mcp.server.dto; * @param message optional message (typically for success confirmations or error details) * @param data the operation result data (e.g., created/updated entity) */ -public record OperationResponse( - String operation, - boolean success, - String message, - T data -) { +public record OperationResponse(String operation, boolean success, String message, T data) { /** * Creates a successful response with data. @@ -52,4 +47,4 @@ public record OperationResponse( public static OperationResponse failure(final String operation, final String message) { return new OperationResponse<>(operation, false, message, null); } -} +} \ No newline at end of file diff --git a/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/dto/PagedResponse.java b/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/dto/PagedResponse.java index c26107ddc..496862ca1 100644 --- a/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/dto/PagedResponse.java +++ b/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/dto/PagedResponse.java @@ -16,14 +16,9 @@ import java.util.List; * * @param the type of items in the response */ -public record PagedResponse( - List content, - long total, - int offset, - int limit -) { +public record PagedResponse(List content, long total, int offset, int limit) { public static PagedResponse of(final List content, final long total, final int offset, final int limit) { return new PagedResponse<>(content, total, offset, limit); } -} +} \ No newline at end of file diff --git a/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/dto/RolloutRequest.java b/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/dto/RolloutRequest.java index 02be86c1f..fdf0d7a3d 100644 --- a/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/dto/RolloutRequest.java +++ b/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/dto/RolloutRequest.java @@ -116,4 +116,4 @@ public sealed interface RolloutRequest * @param rolloutId the rollout ID */ record TriggerNextGroup(Long rolloutId) implements RolloutRequest {} -} +} \ No newline at end of file diff --git a/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/dto/SoftwareModuleRequest.java b/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/dto/SoftwareModuleRequest.java index 11b5bdf33..835d75a08 100644 --- a/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/dto/SoftwareModuleRequest.java +++ b/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/dto/SoftwareModuleRequest.java @@ -47,4 +47,4 @@ public sealed interface SoftwareModuleRequest * @param softwareModuleId the software module ID to delete */ record Delete(Long softwareModuleId) implements SoftwareModuleRequest {} -} +} \ No newline at end of file diff --git a/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/dto/TargetFilterRequest.java b/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/dto/TargetFilterRequest.java index ddab9dc73..c16ca5b6c 100644 --- a/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/dto/TargetFilterRequest.java +++ b/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/dto/TargetFilterRequest.java @@ -46,4 +46,4 @@ public sealed interface TargetFilterRequest * @param filterId the target filter ID to delete */ record Delete(Long filterId) implements TargetFilterRequest {} -} +} \ No newline at end of file diff --git a/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/dto/TargetRequest.java b/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/dto/TargetRequest.java index 3f5b6dbeb..179cf8b05 100644 --- a/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/dto/TargetRequest.java +++ b/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/dto/TargetRequest.java @@ -46,4 +46,4 @@ public sealed interface TargetRequest * @param controllerId the target controller ID to delete */ record Delete(String controllerId) implements TargetRequest {} -} +} \ No newline at end of file diff --git a/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/prompts/HawkbitPromptProvider.java b/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/prompts/HawkbitPromptProvider.java index a41176c2e..c2cadbd38 100644 --- a/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/prompts/HawkbitPromptProvider.java +++ b/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/prompts/HawkbitPromptProvider.java @@ -64,4 +64,4 @@ public class HawkbitPromptProvider { return "Prompt content not available."; } } -} +} \ No newline at end of file diff --git a/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/resources/HawkbitDocumentationResource.java b/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/resources/HawkbitDocumentationResource.java index e53b1f503..395a072bd 100644 --- a/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/resources/HawkbitDocumentationResource.java +++ b/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/resources/HawkbitDocumentationResource.java @@ -198,4 +198,4 @@ public class HawkbitDocumentationResource { return "Documentation not available. Please refer to the hawkBit documentation at https://eclipse.dev/hawkbit/"; } } -} +} \ No newline at end of file diff --git a/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/tools/HawkbitMcpToolProvider.java b/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/tools/HawkbitMcpToolProvider.java index afc24e221..70261393e 100644 --- a/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/tools/HawkbitMcpToolProvider.java +++ b/hawkbit-mcp/src/main/java/org/eclipse/hawkbit/mcp/server/tools/HawkbitMcpToolProvider.java @@ -53,10 +53,10 @@ import java.util.List; @RequiredArgsConstructor public class HawkbitMcpToolProvider { - private static final String OP_CREATE = "CREATE"; - private static final String OP_UPDATE = "UPDATE"; - private static final String OP_DELETE = "DELETE"; - private static final String OP_DELETE_BATCH = "DELETE_BATCH"; + private static final String OP_CREATE = HawkbitMcpProperties.OP_CREATE.toUpperCase(); + private static final String OP_UPDATE = HawkbitMcpProperties.OP_UPDATE.toUpperCase(); + private static final String OP_DELETE = HawkbitMcpProperties.OP_DELETE.toUpperCase(); + private static final String OP_DELETE_BATCH = HawkbitMcpProperties.OP_DELETE_BATCH.toUpperCase().replace('-', '_'); private static final String OP_START = "START"; private static final String OP_PAUSE = "PAUSE"; private static final String OP_STOP = "STOP"; @@ -66,6 +66,14 @@ public class HawkbitMcpToolProvider { private static final String OP_RETRY = "RETRY"; private static final String OP_TRIGGER_NEXT_GROUP = "TRIGGER_NEXT_GROUP"; + private static final String SOFTWARE_MODULES = "softwareModules"; + private static final String DISTRIBUTION_SETS = "distributionSets"; + private static final String TARGETS = "targets"; + private static final String TARGET_FILTERS = "targetFilters"; + + private static final String BODY_IS_REQUIRED_FOR_UPDATE_OPERATION = "body is required for UPDATE operation"; + private static final String BODY_IS_REQUIRED_FOR_CREATE_OPERATION = "body is required for CREATE operation"; + private final HawkbitClient hawkbitClient; private final Tenant dummyTenant; private final HawkbitMcpProperties properties; @@ -199,13 +207,14 @@ public class HawkbitMcpToolProvider { "{\"type\":\"Create\",\"body\":{\"controllerId\":\"id\",\"name\":\"name\"}}, " + "{\"type\":\"Update\",\"controllerId\":\"id\",\"body\":{...}}, " + "{\"type\":\"Delete\",\"controllerId\":\"id\"}") + @SuppressWarnings("java:S3776") // not too complex public OperationResponse manageTarget(final TargetRequest request) { log.debug("Managing target: request={}", request.getClass().getSimpleName()); final MgmtTargetRestApi api = hawkbitClient.mgmtService(MgmtTargetRestApi.class, dummyTenant); if (request instanceof TargetRequest.Create r) { - validateOperation("create", "targets"); + validateOperation(OP_CREATE, TARGETS); if (r.body() == null) { return OperationResponse.failure(OP_CREATE, "Request body is required for CREATE operation"); } @@ -214,7 +223,7 @@ public class HawkbitMcpToolProvider { return OperationResponse.success(OP_CREATE, "Target created successfully", created != null && !created.isEmpty() ? created.get(0) : null); } else if (request instanceof TargetRequest.Update r) { - validateOperation("update", "targets"); + validateOperation(OP_UPDATE, TARGETS); if (r.controllerId() == null || r.controllerId().isBlank()) { return OperationResponse.failure(OP_UPDATE, "controllerId is required for UPDATE operation"); } @@ -224,7 +233,7 @@ public class HawkbitMcpToolProvider { final ResponseEntity response = api.updateTarget(r.controllerId(), r.body()); return OperationResponse.success(OP_UPDATE, "Target updated successfully", response.getBody()); } else if (request instanceof TargetRequest.Delete r) { - validateOperation("delete", "targets"); + validateOperation(OP_DELETE, TARGETS); if (r.controllerId() == null || r.controllerId().isBlank()) { return OperationResponse.failure(OP_DELETE, "controllerId is required for DELETE operation"); } @@ -243,15 +252,16 @@ public class HawkbitMcpToolProvider { "Examples: {\"type\":\"Create\",\"body\":{...}}, " + "{\"type\":\"Start\",\"rolloutId\":123}, " + "{\"type\":\"Approve\",\"rolloutId\":123,\"remark\":\"approved\"}") + @SuppressWarnings("java:S3776") // not too complex, iterative logic public OperationResponse manageRollout(final RolloutRequest request) { log.debug("Managing rollout: request={}", request.getClass().getSimpleName()); final MgmtRolloutRestApi api = hawkbitClient.mgmtService(MgmtRolloutRestApi.class, dummyTenant); if (request instanceof RolloutRequest.Create r) { - validateRolloutOperation("create"); + validateRolloutOperation(OP_CREATE); if (r.body() == null) { - return OperationResponse.failure(OP_CREATE, "body is required for CREATE operation"); + return OperationResponse.failure(OP_CREATE, BODY_IS_REQUIRED_FOR_CREATE_OPERATION); } final ResponseEntity response = api.create(r.body()); return OperationResponse.success(OP_CREATE, "Rollout created successfully", response.getBody()); @@ -261,12 +271,12 @@ public class HawkbitMcpToolProvider { return OperationResponse.failure(OP_UPDATE, "rolloutId is required for UPDATE operation"); } if (r.body() == null) { - return OperationResponse.failure(OP_UPDATE, "body is required for UPDATE operation"); + return OperationResponse.failure(OP_UPDATE, BODY_IS_REQUIRED_FOR_UPDATE_OPERATION); } final ResponseEntity response = api.update(r.rolloutId(), r.body()); return OperationResponse.success(OP_UPDATE, "Rollout updated successfully", response.getBody()); } else if (request instanceof RolloutRequest.Delete r) { - validateRolloutOperation("delete"); + validateRolloutOperation(OP_DELETE); if (r.rolloutId() == null) { return OperationResponse.failure(OP_DELETE, "rolloutId is required for DELETE operation"); } @@ -344,26 +354,26 @@ public class HawkbitMcpToolProvider { final MgmtDistributionSetRestApi api = hawkbitClient.mgmtService(MgmtDistributionSetRestApi.class, dummyTenant); if (request instanceof DistributionSetRequest.Create r) { - validateOperation("create", "distributionSets"); + validateOperation(OP_CREATE, DISTRIBUTION_SETS); if (r.body() == null) { - return OperationResponse.failure(OP_CREATE, "body is required for CREATE operation"); + return OperationResponse.failure(OP_CREATE, BODY_IS_REQUIRED_FOR_CREATE_OPERATION); } final ResponseEntity> response = api.createDistributionSets(List.of(r.body())); final List created = response.getBody(); return OperationResponse.success(OP_CREATE, "Distribution set created successfully", created != null && !created.isEmpty() ? created.get(0) : null); } else if (request instanceof DistributionSetRequest.Update r) { - validateOperation("update", "distributionSets"); + validateOperation(OP_UPDATE, DISTRIBUTION_SETS); if (r.distributionSetId() == null) { return OperationResponse.failure(OP_UPDATE, "distributionSetId is required for UPDATE operation"); } if (r.body() == null) { - return OperationResponse.failure(OP_UPDATE, "body is required for UPDATE operation"); + return OperationResponse.failure(OP_UPDATE, BODY_IS_REQUIRED_FOR_UPDATE_OPERATION); } final ResponseEntity response = api.updateDistributionSet(r.distributionSetId(), r.body()); return OperationResponse.success(OP_UPDATE, "Distribution set updated successfully", response.getBody()); } else if (request instanceof DistributionSetRequest.Delete r) { - validateOperation("delete", "distributionSets"); + validateOperation(OP_DELETE, DISTRIBUTION_SETS); if (r.distributionSetId() == null) { return OperationResponse.failure(OP_DELETE, "distributionSetId is required for DELETE operation"); } @@ -384,7 +394,7 @@ public class HawkbitMcpToolProvider { final MgmtActionRestApi api = hawkbitClient.mgmtService(MgmtActionRestApi.class, dummyTenant); if (request instanceof ActionRequest.Delete r) { - validateActionOperation("delete"); + validateActionOperation(OP_DELETE); if (r.actionId() == null) { return OperationResponse.failure(OP_DELETE, "actionId is required for DELETE operation"); } @@ -414,26 +424,26 @@ public class HawkbitMcpToolProvider { final MgmtSoftwareModuleRestApi api = hawkbitClient.mgmtService(MgmtSoftwareModuleRestApi.class, dummyTenant); if (request instanceof SoftwareModuleRequest.Create r) { - validateOperation("create", "softwareModules"); + validateOperation(OP_CREATE, SOFTWARE_MODULES); if (r.body() == null) { - return OperationResponse.failure(OP_CREATE, "body is required for CREATE operation"); + return OperationResponse.failure(OP_CREATE, BODY_IS_REQUIRED_FOR_CREATE_OPERATION); } final ResponseEntity> response = api.createSoftwareModules(List.of(r.body())); final List created = response.getBody(); return OperationResponse.success(OP_CREATE, "Software module created successfully", created != null && !created.isEmpty() ? created.get(0) : null); } else if (request instanceof SoftwareModuleRequest.Update r) { - validateOperation("update", "softwareModules"); + validateOperation(OP_UPDATE, SOFTWARE_MODULES); if (r.softwareModuleId() == null) { return OperationResponse.failure(OP_UPDATE, "softwareModuleId is required for UPDATE operation"); } if (r.body() == null) { - return OperationResponse.failure(OP_UPDATE, "body is required for UPDATE operation"); + return OperationResponse.failure(OP_UPDATE, BODY_IS_REQUIRED_FOR_UPDATE_OPERATION); } final ResponseEntity response = api.updateSoftwareModule(r.softwareModuleId(), r.body()); return OperationResponse.success(OP_UPDATE, "Software module updated successfully", response.getBody()); } else if (request instanceof SoftwareModuleRequest.Delete r) { - validateOperation("delete", "softwareModules"); + validateOperation(OP_DELETE, SOFTWARE_MODULES); if (r.softwareModuleId() == null) { return OperationResponse.failure(OP_DELETE, "softwareModuleId is required for DELETE operation"); } @@ -455,24 +465,24 @@ public class HawkbitMcpToolProvider { final MgmtTargetFilterQueryRestApi api = hawkbitClient.mgmtService(MgmtTargetFilterQueryRestApi.class, dummyTenant); if (request instanceof TargetFilterRequest.Create r) { - validateOperation("create", "targetFilters"); + validateOperation(OP_CREATE, TARGET_FILTERS); if (r.body() == null) { - return OperationResponse.failure(OP_CREATE, "body is required for CREATE operation"); + return OperationResponse.failure(OP_CREATE, BODY_IS_REQUIRED_FOR_CREATE_OPERATION); } final ResponseEntity response = api.createFilter(r.body()); return OperationResponse.success(OP_CREATE, "Target filter created successfully", response.getBody()); } else if (request instanceof TargetFilterRequest.Update r) { - validateOperation("update", "targetFilters"); + validateOperation(OP_UPDATE, TARGET_FILTERS); if (r.filterId() == null) { return OperationResponse.failure(OP_UPDATE, "filterId is required for UPDATE operation"); } if (r.body() == null) { - return OperationResponse.failure(OP_UPDATE, "body is required for UPDATE operation"); + return OperationResponse.failure(OP_UPDATE, BODY_IS_REQUIRED_FOR_UPDATE_OPERATION); } final ResponseEntity response = api.updateFilter(r.filterId(), r.body()); return OperationResponse.success(OP_UPDATE, "Target filter updated successfully", response.getBody()); } else if (request instanceof TargetFilterRequest.Delete r) { - validateOperation("delete", "targetFilters"); + validateOperation(OP_DELETE, TARGET_FILTERS); if (r.filterId() == null) { return OperationResponse.failure(OP_DELETE, "filterId is required for DELETE operation"); } @@ -517,7 +527,7 @@ public class HawkbitMcpToolProvider { final Boolean entitySetting = config.getOperationEnabled(operation); if (entitySetting == null) { - if (operation.equals("delete") && !properties.getOperations().isGlobalOperationEnabled("delete")) { + if (operation.equals("delete") && !properties.getOperations().isGlobalOperationEnabled(OP_DELETE)) { throw new IllegalArgumentException( "Operation " + operation.toUpperCase() + " is not enabled for actions. " + "Check hawkbit.mcp.operations configuration."); @@ -547,7 +557,7 @@ public class HawkbitMcpToolProvider { private HawkbitMcpProperties.EntityConfig getEntityConfig(final String entity) { final HawkbitMcpProperties.Operations ops = properties.getOperations(); return switch (entity.toLowerCase()) { - case "targets" -> ops.getTargets(); + case TARGETS -> ops.getTargets(); case "rollouts" -> ops.getRollouts(); case "distributionsets" -> ops.getDistributionSets(); case "softwaremodules" -> ops.getSoftwareModules(); diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DeploymentRequest.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DeploymentRequest.java index b0bd25490..d9ffdb8a6 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DeploymentRequest.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DeploymentRequest.java @@ -10,6 +10,8 @@ package org.eclipse.hawkbit.repository.model; import jakarta.validation.Valid; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; import lombok.Data; import lombok.Setter; @@ -77,6 +79,8 @@ public class DeploymentRequest { @Setter private long forceTime = RepositoryModelConstants.NO_FORCE_TIME; @Setter + @Min(Action.WEIGHT_MIN) + @Max(Action.WEIGHT_MAX) private ActionType actionType = ActionType.FORCED; private String maintenanceSchedule; private String maintenanceWindowDuration; @@ -85,8 +89,7 @@ public class DeploymentRequest { private boolean confirmationRequired; /** - * Create a builder for a target distribution set assignment with the - * mandatory fields + * Create a builder for a target distribution set assignment with the mandatory fields * * @param controllerId ID of the target * @param distributionSetId ID of the distribution set diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDeploymentManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDeploymentManagement.java index 4732fef1b..fa2f274ac 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDeploymentManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDeploymentManagement.java @@ -71,7 +71,6 @@ import org.eclipse.hawkbit.repository.jpa.specifications.ActionSpecifications; import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications; import org.eclipse.hawkbit.repository.jpa.utils.DeploymentHelper; import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper; -import org.eclipse.hawkbit.repository.jpa.utils.WeightValidationHelper; import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action.ActionType; import org.eclipse.hawkbit.repository.model.Action.Status; @@ -170,7 +169,6 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl @Transactional(isolation = Isolation.READ_COMMITTED) public List assignDistributionSets( final List deploymentRequests, final String actionMessage) { - WeightValidationHelper.validate(deploymentRequests); return assignDistributionSets(deploymentRequests, actionMessage, onlineDsAssignmentStrategy); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutManagement.java index c4ea020a0..b63a0ce81 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutManagement.java @@ -71,7 +71,6 @@ import org.eclipse.hawkbit.repository.jpa.rollout.condition.StartNextGroupRollou import org.eclipse.hawkbit.repository.jpa.specifications.ActionSpecifications; import org.eclipse.hawkbit.repository.jpa.specifications.RolloutSpecification; import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper; -import org.eclipse.hawkbit.repository.jpa.utils.WeightValidationHelper; import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.ActionCancellationType; import org.eclipse.hawkbit.repository.model.DistributionSet; @@ -718,8 +717,6 @@ public class JpaRolloutManagement implements RolloutManagement { } private JpaRollout createRollout(final JpaRollout rollout, final boolean pureDynamic) { - WeightValidationHelper.validate(rollout); - rollout.setCreatedAt(System.currentTimeMillis()); final JpaDistributionSet distributionSet = rollout.getDistributionSet(); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetFilterQueryManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetFilterQueryManagement.java index 752e2ae2d..790255109 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetFilterQueryManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetFilterQueryManagement.java @@ -37,7 +37,6 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaTargetFilterQuery; import org.eclipse.hawkbit.repository.jpa.repository.TargetFilterQueryRepository; import org.eclipse.hawkbit.repository.jpa.specifications.TargetFilterQuerySpecification; import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper; -import org.eclipse.hawkbit.repository.jpa.utils.WeightValidationHelper; import org.eclipse.hawkbit.repository.model.Action.ActionType; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.Target; @@ -150,7 +149,6 @@ class JpaTargetFilterQueryManagement targetFilterQuery.setAutoAssignInitiatedBy(null); targetFilterQuery.setConfirmationRequired(false); } else { - WeightValidationHelper.validate(update); assertMaxTargetsQuota(targetFilterQuery.getQuery(), targetFilterQuery.getName(), update.dsId()); DistributionSet distributionSet = distributionSetManagement.getValidAndComplete(update.dsId()); @@ -215,10 +213,8 @@ class JpaTargetFilterQueryManagement QLSupport.getInstance().validate(query, TargetFields.class, JpaTarget.class); // enforce the 'max targets per auto assign' quota right here even if the result of the filter query can vary over time - Optional.ofNullable(create.getAutoAssignDistributionSet()).ifPresent(dsId -> { - WeightValidationHelper.validate(create); - assertMaxTargetsQuota(query, create.getName(), dsId.getId()); - }); + Optional.ofNullable(create.getAutoAssignDistributionSet()) + .ifPresent(dsId -> assertMaxTargetsQuota(query, create.getName(), dsId.getId())); }); if (create.getAutoAssignWeight() == null) { create.setAutoAssignWeight(create.getAutoAssignDistributionSet() == null ? 0 : repositoryProperties.getActionWeightIfAbsent()); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/WeightValidationHelper.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/WeightValidationHelper.java deleted file mode 100644 index c516c081b..000000000 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/WeightValidationHelper.java +++ /dev/null @@ -1,91 +0,0 @@ -/** - * Copyright (c) 2019 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.jpa.utils; - -import java.util.List; - -import lombok.NoArgsConstructor; -import org.eclipse.hawkbit.repository.TargetFilterQueryManagement; -import org.eclipse.hawkbit.repository.exception.NoWeightProvidedInMultiAssignmentModeException; -import org.eclipse.hawkbit.repository.helper.TenantConfigHelper; -import org.eclipse.hawkbit.repository.model.DeploymentRequest; -import org.eclipse.hawkbit.repository.model.Rollout; - -/** - * Utility class to handle weight validation in Rollout, Auto Assignments, and Online Assignment. - */ -@NoArgsConstructor(access = lombok.AccessLevel.PRIVATE) -public final class WeightValidationHelper { - - /** - * Validating weights associated with all the {@link DeploymentRequest}s - * - * @param deploymentRequests the {@linkplain List} of {@link DeploymentRequest}s - */ - public static void validate(final List deploymentRequests) { - final long assignmentsWithWeight = deploymentRequests.stream() - .filter(request -> request.getTargetWithActionType().getWeight() != null).count(); - final boolean containsAssignmentWithWeight = assignmentsWithWeight > 0; - final boolean containsAssignmentWithoutWeight = assignmentsWithWeight < deploymentRequests.size(); - - validateWeight(containsAssignmentWithWeight, containsAssignmentWithoutWeight); - } - - /** - * Validating weight associated with the {@link Rollout} - * - * @param rollout the {@linkplain Rollout} - */ - public static void validate(final Rollout rollout) { - validateWeight(rollout.getWeight().orElse(null)); - } - - /** - * Validating weight associated with the target filter query - * - * @param targetFilterQueryCreate the target filter query - */ - public static void validate(final TargetFilterQueryManagement.Create targetFilterQueryCreate) { - validateWeight(targetFilterQueryCreate.getAutoAssignWeight()); - } - - /** - * Validating weight associated with the auto assignment - * - * @param autoAssignDistributionSetUpdate the auto assignment distribution set update - */ - public static void validate(final TargetFilterQueryManagement.AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate) { - validateWeight(autoAssignDistributionSetUpdate.weight()); - } - - /** - * Checks if the weight is valid - * - * @param weight weight tied to the rollout, auto assignment, or online assignment. - */ - public static void validateWeight(final Integer weight) { - final boolean hasWeight = weight != null; - validateWeight(hasWeight, !hasWeight); - } - - /** - * Checks if the weight is valid with the multi-assignments being turned off/on. - * - * @param hasWeight indicator of the weight if it has numerical value - * @param hasNoWeight indicator of the weight if it doesn't have a numerical value - */ - public static void validateWeight(final boolean hasWeight, final boolean hasNoWeight) { - // remove bypassing the weight enforcement as soon as weight can be set via UI - final boolean bypassWeightEnforcement = true; - if (!bypassWeightEnforcement && hasNoWeight) { - throw new NoWeightProvidedInMultiAssignmentModeException(); - } - } -} \ No newline at end of file diff --git a/hawkbit-sdk/hawkbit-sdk-commons/src/main/java/org/eclipse/hawkbit/sdk/Tenant.java b/hawkbit-sdk/hawkbit-sdk-commons/src/main/java/org/eclipse/hawkbit/sdk/Tenant.java index c5f1a581c..a70b3e5e1 100644 --- a/hawkbit-sdk/hawkbit-sdk-commons/src/main/java/org/eclipse/hawkbit/sdk/Tenant.java +++ b/hawkbit-sdk/hawkbit-sdk-commons/src/main/java/org/eclipse/hawkbit/sdk/Tenant.java @@ -49,11 +49,11 @@ public class Tenant { // amqp settings (if DMF is used) @Nullable - private DMF dmf; + private Dmf dmf; @Data @ToString - public static class DMF { + public static class Dmf { @Nullable private String virtualHost; diff --git a/hawkbit-sdk/hawkbit-sdk-dmf/src/main/java/org/eclipse/hawkbit/sdk/dmf/amqp/Amqp.java b/hawkbit-sdk/hawkbit-sdk-dmf/src/main/java/org/eclipse/hawkbit/sdk/dmf/amqp/Amqp.java index ddf087bad..9ffee2975 100644 --- a/hawkbit-sdk/hawkbit-sdk-dmf/src/main/java/org/eclipse/hawkbit/sdk/dmf/amqp/Amqp.java +++ b/hawkbit-sdk/hawkbit-sdk-dmf/src/main/java/org/eclipse/hawkbit/sdk/dmf/amqp/Amqp.java @@ -14,7 +14,8 @@ import java.security.NoSuchAlgorithmException; import java.util.concurrent.ConcurrentHashMap; import lombok.extern.slf4j.Slf4j; -import org.eclipse.hawkbit.sdk.Tenant.DMF; +import org.eclipse.hawkbit.sdk.Tenant; +import org.eclipse.hawkbit.sdk.Tenant.Dmf; import org.springframework.amqp.rabbit.connection.CachingConnectionFactory; import org.springframework.amqp.rabbit.connection.ConnectionFactory; import org.springframework.boot.autoconfigure.amqp.RabbitProperties; @@ -40,7 +41,7 @@ public class Amqp { } @SuppressWarnings("java:S3358") // java:S3358 - public VHost getVhost(final DMF dmf, final boolean initVHost) { + public VHost getVhost(final Tenant.Dmf dmf, final boolean initVHost) { final String vHost = dmf == null || ObjectUtils.isEmpty(dmf.getVirtualHost()) ? (rabbitProperties.getVirtualHost() == null ? "/" : rabbitProperties.getVirtualHost()) : dmf.getVirtualHost(); @@ -48,7 +49,7 @@ public class Amqp { } @SuppressWarnings("java:S4449") // java:S4449 - setUsername/Password is called with non-null - private ConnectionFactory getConnectionFactory(final DMF dmf, final String vHost) { + private ConnectionFactory getConnectionFactory(final Dmf dmf, final String vHost) { final CachingConnectionFactory connectionFactory = new CachingConnectionFactory(); connectionFactory.setHost(rabbitProperties.getHost()); connectionFactory.setPort(rabbitProperties.determinePort());