diff --git a/README.md b/README.md
index 5ca2799b9..2fde2b3d8 100644
--- a/README.md
+++ b/README.md
@@ -27,6 +27,10 @@ We offer a sandbox installation that is free for everyone to try out hawkBit. Ho
https://hawkbit.eu-gb.mybluemix.net/UI/
+In addition the following vendors offer free trial accounts for their hawkBit compatible products:
+
+- [Bosch IoT Rollouts](https://www.bosch-iot-suite.com/rollouts/)
+
# Device Integration
hawkBit does not provide off the shelf clients for devices as part of the project. The long term goal is to provide an [Eclipse hono](https://github.com/eclipse/hono) integration which will provide connectivity through various IoT protocols and as a result allows a wide range of clients to connect to hawkBit. However, the hawkBit [Direct Device Integration (API) API](http://www.eclipse.org/hawkbit/documentation/interfaces/ddi-api.html) is HTTP/JSon based which should allow any update client to integrate quite easily.
@@ -83,7 +87,7 @@ $ java -jar ./hawkbit-device-simulator/target/hawkbit-device-simulator-#version#
## Generate getting started data with the [Management API example](https://github.com/eclipse/hawkbit-examples/tree/master/hawkbit-example-mgmt-simulator) (optional)
```
-$ java -jar ./hawkbit-example-mgmt-simulator/target/hawkbit-example-mgmt-simulator-#version#.jar
+$ java -jar ./hawkbit-example-mgmt-simulator/target/hawkbit-example-mgmt-simulator-#version#-exec.jar
```
# Releases and Roadmap
diff --git a/docs/src/main/resources/documentation/interfaces/dmf-api.md b/docs/src/main/resources/documentation/interfaces/dmf-api.md
index b2dc47361..e7c24beee 100644
--- a/docs/src/main/resources/documentation/interfaces/dmf-api.md
+++ b/docs/src/main/resources/documentation/interfaces/dmf-api.md
@@ -237,7 +237,13 @@ Payload Template
"sha1":"String"
},
"size":long
- }]
+ }],
+ "metadata":[
+ {
+ "key":"String",
+ "value":"String"
+ }
+ ]
}]
}
```
@@ -249,7 +255,6 @@ Payload Template
| type=EVENT
tenant=tenant123
thingId=abc
topic=DOWNLOAD\_AND\_INSTALL | content_type=application/json
```json
-{
"actionId":137,
"targetSecurityToken":"bH7XXAprK1ChnLfKSdtlsp7NOlPnZAYY",
"softwareModules":[
@@ -269,7 +274,13 @@ Payload Template
"sha1":"sha1hash"
},
"size":512
- }]
+ }],
+ "metadata":[
+ {
+ "key":"installationType",
+ "value":"5784K#"
+ }
+ ]
}]
}
```
\ No newline at end of file
diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleMetadataFields.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleMetadataFields.java
index 8286170cd..725d0f206 100644
--- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleMetadataFields.java
+++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleMetadataFields.java
@@ -24,7 +24,12 @@ public enum SoftwareModuleMetadataFields implements FieldNameProvider {
/**
* The key field.
*/
- KEY("key");
+ KEY("key"),
+
+ /**
+ * The target visible field.
+ */
+ TARGETVISIBLE("targetVisible");
private final String fieldName;
diff --git a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiChunk.java b/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiChunk.java
index 8f1172c39..fcb33598a 100644
--- a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiChunk.java
+++ b/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiChunk.java
@@ -13,22 +13,33 @@ import java.util.List;
import javax.validation.constraints.NotNull;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
/**
* Deployment chunks.
*/
public class DdiChunk {
+ @JsonProperty("part")
@NotNull
private String part;
+ @JsonProperty("version")
@NotNull
private String version;
+ @JsonProperty("name")
@NotNull
private String name;
+ @JsonProperty("artifacts")
private List artifacts;
+ @JsonProperty("metadata")
+ @JsonInclude(JsonInclude.Include.NON_NULL)
+ private List metadata;
+
public DdiChunk() {
// needed for json create
}
@@ -44,13 +55,16 @@ public class DdiChunk {
* of the artifact
* @param artifacts
* download information
+ * @param metadata
+ * optional as additional information for the target/device
*/
- public DdiChunk(final String part, final String version, final String name, final List artifacts) {
- super();
+ public DdiChunk(final String part, final String version, final String name, final List artifacts,
+ final List metadata) {
this.part = part;
this.version = version;
this.name = name;
this.artifacts = artifacts;
+ this.metadata = metadata;
}
public String getPart() {
@@ -73,4 +87,8 @@ public class DdiChunk {
return Collections.unmodifiableList(artifacts);
}
+ public List getMetadata() {
+ return metadata;
+ }
+
}
diff --git a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiDeployment.java b/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiDeployment.java
index 2f7fd593e..2d62035e2 100644
--- a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiDeployment.java
+++ b/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiDeployment.java
@@ -11,6 +11,9 @@ package org.eclipse.hawkbit.ddi.json.model;
import java.util.Collections;
import java.util.List;
+import javax.validation.constraints.NotNull;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonValue;
/**
@@ -22,6 +25,8 @@ public class DdiDeployment {
private HandlingType update;
+ @JsonProperty("chunks")
+ @NotNull
private List chunks;
/**
@@ -59,7 +64,7 @@ public class DdiDeployment {
if (chunks == null) {
return Collections.emptyList();
}
-
+
return Collections.unmodifiableList(chunks);
}
diff --git a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiMetadata.java b/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiMetadata.java
new file mode 100644
index 000000000..94b458840
--- /dev/null
+++ b/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiMetadata.java
@@ -0,0 +1,41 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit.ddi.json.model;
+
+import javax.validation.constraints.NotNull;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * Additional metadata to be provided for the target/device.
+ *
+ */
+public class DdiMetadata {
+ @JsonProperty
+ @NotNull
+ private final String key;
+
+ @JsonProperty
+ @NotNull
+ private final String value;
+
+ public DdiMetadata(final String key, final String value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+}
diff --git a/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DataConversionHelper.java b/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DataConversionHelper.java
index 0cc0b93a6..b5077379e 100644
--- a/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DataConversionHelper.java
+++ b/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DataConversionHelper.java
@@ -9,6 +9,7 @@
package org.eclipse.hawkbit.ddi.rest.resource;
import java.util.List;
+import java.util.Map;
import java.util.stream.Collectors;
import org.eclipse.hawkbit.api.ApiType;
@@ -20,17 +21,22 @@ import org.eclipse.hawkbit.ddi.json.model.DdiArtifactHash;
import org.eclipse.hawkbit.ddi.json.model.DdiChunk;
import org.eclipse.hawkbit.ddi.json.model.DdiConfig;
import org.eclipse.hawkbit.ddi.json.model.DdiControllerBase;
+import org.eclipse.hawkbit.ddi.json.model.DdiMetadata;
import org.eclipse.hawkbit.ddi.json.model.DdiPolling;
import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants;
+import org.eclipse.hawkbit.repository.ControllerManagement;
import org.eclipse.hawkbit.repository.SystemManagement;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Artifact;
+import org.eclipse.hawkbit.repository.model.SoftwareModule;
+import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.rest.data.ResponseList;
import org.eclipse.hawkbit.tenancy.TenantAware;
import org.springframework.hateoas.Link;
import org.springframework.hateoas.mvc.ControllerLinkBuilder;
import org.springframework.http.HttpRequest;
+import org.springframework.util.CollectionUtils;
/**
* Utility class for the DDI API.
@@ -43,15 +49,26 @@ public final class DataConversionHelper {
static List createChunks(final Target target, final Action uAction,
final ArtifactUrlHandler artifactUrlHandler, final SystemManagement systemManagement,
- final HttpRequest request) {
+ final HttpRequest request, final ControllerManagement controllerManagement) {
+
+ final Map> metadata = controllerManagement
+ .findTargetVisibleMetaDataBySoftwareModuleId(uAction.getDistributionSet().getModules().stream()
+ .map(SoftwareModule::getId).collect(Collectors.toList()));
+
return uAction.getDistributionSet().getModules().stream()
.map(module -> new DdiChunk(mapChunkLegacyKeys(module.getType().getKey()), module.getVersion(),
module.getName(),
- createArtifacts(target, module, artifactUrlHandler, systemManagement, request)))
+ createArtifacts(target, module, artifactUrlHandler, systemManagement, request),
+ mapMetadata(metadata.get(module.getId()))))
.collect(Collectors.toList());
}
+ private static List mapMetadata(final List metadata) {
+ return CollectionUtils.isEmpty(metadata) ? null
+ : metadata.stream().map(md -> new DdiMetadata(md.getKey(), md.getValue())).collect(Collectors.toList());
+ }
+
private static String mapChunkLegacyKeys(final String key) {
if ("application".equals(key)) {
return "bApp";
diff --git a/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java b/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java
index 71c955149..c858768c6 100644
--- a/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java
+++ b/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java
@@ -20,6 +20,7 @@ import org.eclipse.hawkbit.api.ArtifactUrlHandler;
import org.eclipse.hawkbit.artifact.repository.model.AbstractDbArtifact;
import org.eclipse.hawkbit.ddi.json.model.DdiActionFeedback;
import org.eclipse.hawkbit.ddi.json.model.DdiActionHistory;
+import org.eclipse.hawkbit.ddi.json.model.DdiArtifact;
import org.eclipse.hawkbit.ddi.json.model.DdiCancel;
import org.eclipse.hawkbit.ddi.json.model.DdiCancelActionToStop;
import org.eclipse.hawkbit.ddi.json.model.DdiChunk;
@@ -115,8 +116,8 @@ public class DdiRootController implements DdiRootControllerRestApi {
private EntityFactory entityFactory;
@Override
- public ResponseEntity> getSoftwareModulesArtifacts(
- @PathVariable("tenant") final String tenant, @PathVariable("controllerId") final String controllerId,
+ public ResponseEntity> getSoftwareModulesArtifacts(@PathVariable("tenant") final String tenant,
+ @PathVariable("controllerId") final String controllerId,
@PathVariable("softwareModuleId") final Long softwareModuleId) {
LOG.debug("getSoftwareModulesArtifacts({})", controllerId);
@@ -270,7 +271,8 @@ public class DdiRootController implements DdiRootControllerRestApi {
final List chunks = DataConversionHelper.createChunks(target, action, artifactUrlHandler,
systemManagement,
- new ServletServerHttpRequest(requestResponseContextHolder.getHttpServletRequest()));
+ new ServletServerHttpRequest(requestResponseContextHolder.getHttpServletRequest()),
+ controllerManagement);
final HandlingType handlingType = action.isForce() ? HandlingType.FORCED : HandlingType.ATTEMPT;
diff --git a/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiDeploymentBaseTest.java b/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiDeploymentBaseTest.java
index a7a4409eb..c4d6371b3 100644
--- a/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiDeploymentBaseTest.java
+++ b/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiDeploymentBaseTest.java
@@ -111,10 +111,10 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
final DistributionSet ds2 = testdataFactory.createDistributionSet("2", true);
final byte random[] = RandomUtils.nextBytes(5 * 1024);
- final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), getOsModule(ds),
- "test1", false);
- final Artifact artifactSignature = artifactManagement.create(new ByteArrayInputStream(random),
- getOsModule(ds), "test1.signature", false);
+ final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), getOsModule(ds), "test1",
+ false);
+ final Artifact artifactSignature = artifactManagement.create(new ByteArrayInputStream(random), getOsModule(ds),
+ "test1.signature", false);
final Target savedTarget = testdataFactory.createTarget("4712");
@@ -265,12 +265,19 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
// Prepare test data
final DistributionSet ds = testdataFactory.createDistributionSet("", true);
final DistributionSet ds2 = testdataFactory.createDistributionSet("2", true);
+ final String visibleMetadataOsKey = "metaDataVisible";
+ final String visibleMetadataOsValue = "withValue";
final byte random[] = RandomUtils.nextBytes(5 * 1024);
- final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), getOsModule(ds),
- "test1", false);
- final Artifact artifactSignature = artifactManagement.create(new ByteArrayInputStream(random),
- getOsModule(ds), "test1.signature", false);
+ final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), getOsModule(ds), "test1",
+ false);
+ final Artifact artifactSignature = artifactManagement.create(new ByteArrayInputStream(random), getOsModule(ds),
+ "test1.signature", false);
+
+ softwareModuleManagement.createMetaData(entityFactory.softwareModuleMetadata().create(getOsModule(ds))
+ .key(visibleMetadataOsKey).value(visibleMetadataOsValue).targetVisible(true));
+ softwareModuleManagement.createMetaData(entityFactory.softwareModuleMetadata().create(getOsModule(ds))
+ .key("metaDataNotVisible").value("withValue").targetVisible(false));
final Target savedTarget = testdataFactory.createTarget("4712");
@@ -328,6 +335,9 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
contains(ds.findFirstModuleByType(osType).get().getName())))
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].version",
contains(ds.findFirstModuleByType(osType).get().getVersion())))
+ .andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].metadata[0].key").value(visibleMetadataOsKey))
+ .andExpect(
+ jsonPath("$.deployment.chunks[?(@.part==os)].metadata[0].value").value(visibleMetadataOsValue))
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].artifacts[0].size", contains(5 * 1024)))
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].artifacts[0].filename", contains("test1")))
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].artifacts[0].hashes.md5",
@@ -362,8 +372,9 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
+ "/artifacts/test1.signature.MD5SUM")))
.andExpect(jsonPath("$.deployment.chunks[?(@.part==bApp)].version",
contains(ds.findFirstModuleByType(appType).get().getVersion())))
- .andExpect(jsonPath("$.deployment.chunks[?(@.part==bApp)].name",
- contains(ds.findFirstModuleByType(appType).get().getName())));
+ .andExpect(jsonPath("$.deployment.chunks[?(@.part==bApp)].metadata").doesNotExist())
+ .andExpect(jsonPath("$.deployment.chunks[?(@.part==bApp)].name")
+ .value(ds.findFirstModuleByType(appType).get().getName()));
// Retrieved is reported
final List actionStatusMessages = deploymentManagement
@@ -381,10 +392,10 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
final DistributionSet ds2 = testdataFactory.createDistributionSet("2", true);
final byte random[] = RandomUtils.nextBytes(5 * 1024);
- final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), getOsModule(ds),
- "test1", false);
- final Artifact artifactSignature = artifactManagement.create(new ByteArrayInputStream(random),
- getOsModule(ds), "test1.signature", false);
+ final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), getOsModule(ds), "test1",
+ false);
+ final Artifact artifactSignature = artifactManagement.create(new ByteArrayInputStream(random), getOsModule(ds),
+ "test1.signature", false);
final Target savedTarget = testdataFactory.createTarget("4712");
diff --git a/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpConfiguration.java b/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpConfiguration.java
index a840e6747..7b0674c88 100644
--- a/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpConfiguration.java
+++ b/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpConfiguration.java
@@ -19,6 +19,7 @@ import org.eclipse.hawkbit.repository.ArtifactManagement;
import org.eclipse.hawkbit.repository.ControllerManagement;
import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.EntityFactory;
+import org.eclipse.hawkbit.repository.SoftwareModuleManagement;
import org.eclipse.hawkbit.repository.SystemManagement;
import org.eclipse.hawkbit.repository.TargetManagement;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
@@ -311,9 +312,11 @@ public class AmqpConfiguration {
AmqpMessageDispatcherService amqpMessageDispatcherService(final RabbitTemplate rabbitTemplate,
final AmqpMessageSenderService amqpSenderService, final ArtifactUrlHandler artifactUrlHandler,
final SystemSecurityContext systemSecurityContext, final SystemManagement systemManagement,
- final TargetManagement targetManagement, final DistributionSetManagement distributionSetManagement) {
+ final TargetManagement targetManagement, final DistributionSetManagement distributionSetManagement,
+ final SoftwareModuleManagement softwareModuleManagement) {
return new AmqpMessageDispatcherService(rabbitTemplate, amqpSenderService, artifactUrlHandler,
- systemSecurityContext, systemManagement, targetManagement, serviceMatcher, distributionSetManagement);
+ systemSecurityContext, systemManagement, targetManagement, serviceMatcher, distributionSetManagement,
+ softwareModuleManagement);
}
private static Map getTTLMaxArgsAuthenticationQueue() {
diff --git a/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherService.java b/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherService.java
index 38ea6a66a..51770bcde 100644
--- a/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherService.java
+++ b/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherService.java
@@ -9,9 +9,10 @@
package org.eclipse.hawkbit.amqp;
import java.net.URI;
-import java.util.Collection;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
import java.util.stream.Collectors;
import org.eclipse.hawkbit.api.ApiType;
@@ -25,8 +26,11 @@ import org.eclipse.hawkbit.dmf.amqp.api.MessageType;
import org.eclipse.hawkbit.dmf.json.model.DmfArtifact;
import org.eclipse.hawkbit.dmf.json.model.DmfArtifactHash;
import org.eclipse.hawkbit.dmf.json.model.DmfDownloadAndUpdateRequest;
+import org.eclipse.hawkbit.dmf.json.model.DmfMetadata;
import org.eclipse.hawkbit.dmf.json.model.DmfSoftwareModule;
import org.eclipse.hawkbit.repository.DistributionSetManagement;
+import org.eclipse.hawkbit.repository.RepositoryConstants;
+import org.eclipse.hawkbit.repository.SoftwareModuleManagement;
import org.eclipse.hawkbit.repository.SystemManagement;
import org.eclipse.hawkbit.repository.TargetManagement;
import org.eclipse.hawkbit.repository.event.remote.TargetAssignDistributionSetEvent;
@@ -34,6 +38,7 @@ import org.eclipse.hawkbit.repository.event.remote.TargetDeletedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.CancelTargetAssignmentEvent;
import org.eclipse.hawkbit.repository.model.Artifact;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
+import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.util.IpUtil;
@@ -46,6 +51,9 @@ import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.cloud.bus.ServiceMatcher;
import org.springframework.cloud.bus.event.RemoteApplicationEvent;
import org.springframework.context.event.EventListener;
+import org.springframework.data.domain.PageRequest;
+
+import com.google.common.collect.Maps;
/**
* {@link AmqpMessageDispatcherService} create all outgoing AMQP messages and
@@ -66,6 +74,7 @@ public class AmqpMessageDispatcherService extends BaseAmqpService {
private final TargetManagement targetManagement;
private final ServiceMatcher serviceMatcher;
private final DistributionSetManagement distributionSetManagement;
+ private final SoftwareModuleManagement softwareModuleManagement;
/**
* Constructor.
@@ -92,7 +101,8 @@ public class AmqpMessageDispatcherService extends BaseAmqpService {
final AmqpMessageSenderService amqpSenderService, final ArtifactUrlHandler artifactUrlHandler,
final SystemSecurityContext systemSecurityContext, final SystemManagement systemManagement,
final TargetManagement targetManagement, final ServiceMatcher serviceMatcher,
- final DistributionSetManagement distributionSetManagement) {
+ final DistributionSetManagement distributionSetManagement,
+ final SoftwareModuleManagement softwareModuleManagement) {
super(rabbitTemplate);
this.artifactUrlHandler = artifactUrlHandler;
this.amqpSenderService = amqpSenderService;
@@ -101,6 +111,7 @@ public class AmqpMessageDispatcherService extends BaseAmqpService {
this.targetManagement = targetManagement;
this.serviceMatcher = serviceMatcher;
this.distributionSetManagement = distributionSetManagement;
+ this.softwareModuleManagement = softwareModuleManagement;
}
/**
@@ -118,11 +129,22 @@ public class AmqpMessageDispatcherService extends BaseAmqpService {
LOG.debug("targetAssignDistributionSet retrieved. I will forward it to DMF broker.");
- distributionSetManagement.get(assignedEvent.getDistributionSetId()).ifPresent(set ->
+ distributionSetManagement.get(assignedEvent.getDistributionSetId()).ifPresent(set -> {
- targetManagement.getByControllerID(assignedEvent.getActions().keySet())
- .forEach(target -> sendUpdateMessageToTarget(assignedEvent.getTenant(), target,
- assignedEvent.getActions().get(target.getControllerId()), set.getModules())));
+ final Map> modules = Maps
+ .newHashMapWithExpectedSize(set.getModules().size());
+ set.getModules()
+ .forEach(
+ module -> modules.put(module,
+ softwareModuleManagement.findMetaDataBySoftwareModuleIdAndTargetVisible(
+ new PageRequest(0, RepositoryConstants.MAX_META_DATA_COUNT), module.getId())
+ .getContent()));
+
+ targetManagement.getByControllerID(assignedEvent.getActions().keySet())
+ .forEach(target -> sendUpdateMessageToTarget(assignedEvent.getTenant(), target,
+ assignedEvent.getActions().get(target.getControllerId()), modules));
+
+ });
}
/**
@@ -159,7 +181,7 @@ public class AmqpMessageDispatcherService extends BaseAmqpService {
}
protected void sendUpdateMessageToTarget(final String tenant, final Target target, final Long actionId,
- final Collection modules) {
+ final Map> modules) {
final URI targetAdress = target.getAddress();
if (!IpUtil.isAmqpUri(targetAdress)) {
@@ -172,10 +194,11 @@ public class AmqpMessageDispatcherService extends BaseAmqpService {
final String targetSecurityToken = systemSecurityContext.runAsSystem(target::getSecurityToken);
downloadAndUpdateRequest.setTargetSecurityToken(targetSecurityToken);
- for (final SoftwareModule softwareModule : modules) {
- final DmfSoftwareModule amqpSoftwareModule = convertToAmqpSoftwareModule(target, softwareModule);
+ modules.entrySet().forEach(entry -> {
+
+ final DmfSoftwareModule amqpSoftwareModule = convertToAmqpSoftwareModule(target, entry);
downloadAndUpdateRequest.addSoftwareModule(amqpSoftwareModule);
- }
+ });
final Message message = getMessageConverter().toMessage(downloadAndUpdateRequest,
createConnectorMessagePropertiesEvent(tenant, target.getControllerId(),
@@ -248,17 +271,22 @@ public class AmqpMessageDispatcherService extends BaseAmqpService {
return messageProperties;
}
- private DmfSoftwareModule convertToAmqpSoftwareModule(final Target target, final SoftwareModule softwareModule) {
+ private DmfSoftwareModule convertToAmqpSoftwareModule(final Target target,
+ final Entry> entry) {
final DmfSoftwareModule amqpSoftwareModule = new DmfSoftwareModule();
- amqpSoftwareModule.setModuleId(softwareModule.getId());
- amqpSoftwareModule.setModuleType(softwareModule.getType().getKey());
- amqpSoftwareModule.setModuleVersion(softwareModule.getVersion());
+ amqpSoftwareModule.setModuleId(entry.getKey().getId());
+ amqpSoftwareModule.setModuleType(entry.getKey().getType().getKey());
+ amqpSoftwareModule.setModuleVersion(entry.getKey().getVersion());
+ amqpSoftwareModule.setArtifacts(convertArtifacts(target, entry.getKey().getArtifacts()));
+ amqpSoftwareModule.setMetadata(convertMetadata(entry.getValue()));
- final List artifacts = convertArtifacts(target, softwareModule.getArtifacts());
- amqpSoftwareModule.setArtifacts(artifacts);
return amqpSoftwareModule;
}
+ private List convertMetadata(final List metadata) {
+ return metadata.stream().map(md -> new DmfMetadata(md.getKey(), md.getValue())).collect(Collectors.toList());
+ }
+
private List convertArtifacts(final Target target, final List localArtifacts) {
if (localArtifacts.isEmpty()) {
return Collections.emptyList();
diff --git a/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerService.java b/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerService.java
index 1ad903c4e..9c62de00e 100644
--- a/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerService.java
+++ b/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerService.java
@@ -12,8 +12,10 @@ import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
import java.util.Optional;
import java.util.UUID;
+import java.util.stream.Collectors;
import org.eclipse.hawkbit.dmf.amqp.api.EventTopic;
import org.eclipse.hawkbit.dmf.amqp.api.MessageHeaderKey;
@@ -28,6 +30,8 @@ import org.eclipse.hawkbit.repository.RepositoryConstants;
import org.eclipse.hawkbit.repository.builder.ActionStatusCreate;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.Status;
+import org.eclipse.hawkbit.repository.model.SoftwareModule;
+import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.util.IpUtil;
import org.slf4j.Logger;
@@ -45,6 +49,8 @@ import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextImpl;
import org.springframework.util.StringUtils;
+import com.google.common.collect.Maps;
+
/**
*
* {@link AmqpMessageHandlerService} handles all incoming target interaction
@@ -199,8 +205,17 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
return;
}
+ final Map> modules = Maps
+ .newHashMapWithExpectedSize(action.getDistributionSet().getModules().size());
+
+ final Map> metadata = controllerManagement
+ .findTargetVisibleMetaDataBySoftwareModuleId(action.getDistributionSet().getModules().stream()
+ .map(SoftwareModule::getId).collect(Collectors.toList()));
+
+ action.getDistributionSet().getModules().forEach(module -> modules.put(module, metadata.get(module.getId())));
+
amqpMessageDispatcherService.sendUpdateMessageToTarget(action.getTenant(), action.getTarget(), action.getId(),
- action.getDistributionSet().getModules());
+ modules);
}
/**
diff --git a/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherServiceTest.java b/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherServiceTest.java
index 483ff6eba..d4ff8d147 100644
--- a/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherServiceTest.java
+++ b/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherServiceTest.java
@@ -34,6 +34,7 @@ import org.eclipse.hawkbit.dmf.amqp.api.EventTopic;
import org.eclipse.hawkbit.dmf.amqp.api.MessageHeaderKey;
import org.eclipse.hawkbit.dmf.amqp.api.MessageType;
import org.eclipse.hawkbit.dmf.json.model.DmfDownloadAndUpdateRequest;
+import org.eclipse.hawkbit.dmf.json.model.DmfMetadata;
import org.eclipse.hawkbit.repository.SystemManagement;
import org.eclipse.hawkbit.repository.event.remote.TargetAssignDistributionSetEvent;
import org.eclipse.hawkbit.repository.event.remote.TargetDeletedEvent;
@@ -46,6 +47,7 @@ import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TenantMetaData;
import org.eclipse.hawkbit.repository.test.util.AbstractIntegrationTest;
+import org.eclipse.hawkbit.repository.test.util.TestdataFactory;
import org.eclipse.hawkbit.util.IpUtil;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
@@ -109,7 +111,7 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest {
amqpMessageDispatcherService = new AmqpMessageDispatcherService(rabbitTemplate, senderService,
artifactUrlHandlerMock, systemSecurityContext, systemManagement, targetManagement, serviceMatcher,
- distributionSetManagement);
+ distributionSetManagement, softwareModuleManagement);
}
@@ -129,6 +131,8 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest {
public void testSendDownloadRequesWithSoftwareModulesAndNoArtifacts() {
final DistributionSet createDistributionSet = testdataFactory
.createDistributionSet(UUID.randomUUID().toString());
+ testdataFactory.addSoftwareModuleMetadata(createDistributionSet);
+
final Action action = createAction(createDistributionSet);
final TargetAssignDistributionSetEvent targetAssignDistributionSetEvent = new TargetAssignDistributionSetEvent(
@@ -142,6 +146,10 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest {
for (final org.eclipse.hawkbit.dmf.json.model.DmfSoftwareModule softwareModule : downloadAndUpdateRequest
.getSoftwareModules()) {
assertTrue("Artifact list for softwaremodule should be empty", softwareModule.getArtifacts().isEmpty());
+
+ assertThat(softwareModule.getMetadata()).containsExactly(
+ new DmfMetadata(TestdataFactory.VISIBLE_SM_MD_KEY, TestdataFactory.VISIBLE_SM_MD_VALUE));
+
for (final SoftwareModule softwareModule2 : action.getDistributionSet().getModules()) {
assertNotNull("Sofware module ID should be set", softwareModule.getModuleId());
if (!softwareModule.getModuleId().equals(softwareModule2.getId())) {
diff --git a/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerServiceTest.java b/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerServiceTest.java
index 7b8e8c44e..5f6fbad24 100644
--- a/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerServiceTest.java
+++ b/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerServiceTest.java
@@ -22,7 +22,6 @@ import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
-import java.util.Collection;
import java.util.Map;
import java.util.Optional;
@@ -421,7 +420,7 @@ public class AmqpMessageHandlerServiceTest {
final ArgumentCaptor actionIdCaptor = ArgumentCaptor.forClass(Long.class);
verify(amqpMessageDispatcherServiceMock, times(1)).sendUpdateMessageToTarget(tenantCaptor.capture(),
- targetCaptor.capture(), actionIdCaptor.capture(), any(Collection.class));
+ targetCaptor.capture(), actionIdCaptor.capture(), any(Map.class));
final String tenant = tenantCaptor.getValue();
final String controllerId = targetCaptor.getValue().getControllerId();
final Long actionId = actionIdCaptor.getValue();
diff --git a/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AmqpMessageDispatcherServiceIntegrationTest.java b/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AmqpMessageDispatcherServiceIntegrationTest.java
index 60e129ca2..fe2fdc05b 100644
--- a/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AmqpMessageDispatcherServiceIntegrationTest.java
+++ b/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AmqpMessageDispatcherServiceIntegrationTest.java
@@ -20,6 +20,7 @@ import org.eclipse.hawkbit.repository.event.remote.entity.ActionUpdatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.CancelTargetAssignmentEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetCreatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedEvent;
+import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleUpdatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.TargetCreatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.TargetUpdatedEvent;
import org.eclipse.hawkbit.repository.model.DistributionSet;
@@ -45,6 +46,7 @@ public class AmqpMessageDispatcherServiceIntegrationTest extends AmqpServiceInte
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
@Expect(type = ActionCreatedEvent.class, count = 1),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
+ @Expect(type = SoftwareModuleUpdatedEvent.class, count = 6),
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 2) })
public void sendDownloadAndInstallStatus() {
@@ -63,6 +65,7 @@ public class AmqpMessageDispatcherServiceIntegrationTest extends AmqpServiceInte
@Expect(type = CancelTargetAssignmentEvent.class, count = 1),
@Expect(type = ActionCreatedEvent.class, count = 2), @Expect(type = ActionUpdatedEvent.class, count = 1),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 6),
+ @Expect(type = SoftwareModuleUpdatedEvent.class, count = 6),
@Expect(type = DistributionSetCreatedEvent.class, count = 2),
@Expect(type = TargetUpdatedEvent.class, count = 2), @Expect(type = TargetPollEvent.class, count = 3) })
public void assignDistributionSetMultipleTimes() {
@@ -88,6 +91,7 @@ public class AmqpMessageDispatcherServiceIntegrationTest extends AmqpServiceInte
@Expect(type = CancelTargetAssignmentEvent.class, count = 1),
@Expect(type = ActionUpdatedEvent.class, count = 1), @Expect(type = ActionCreatedEvent.class, count = 1),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
+ @Expect(type = SoftwareModuleUpdatedEvent.class, count = 6),
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 2) })
public void sendCancelStatus() {
diff --git a/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AmqpMessageHandlerServiceIntegrationTest.java b/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AmqpMessageHandlerServiceIntegrationTest.java
index 7bb7e4515..89554a4b4 100644
--- a/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AmqpMessageHandlerServiceIntegrationTest.java
+++ b/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AmqpMessageHandlerServiceIntegrationTest.java
@@ -30,6 +30,7 @@ import org.eclipse.hawkbit.repository.event.remote.entity.ActionUpdatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.CancelTargetAssignmentEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetCreatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedEvent;
+import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleUpdatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.TargetCreatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.TargetUpdatedEvent;
import org.eclipse.hawkbit.repository.model.Action.Status;
@@ -363,6 +364,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AmqpServiceIntegra
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
@Expect(type = ActionUpdatedEvent.class, count = 1), @Expect(type = ActionCreatedEvent.class, count = 1),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
+ @Expect(type = SoftwareModuleUpdatedEvent.class, count = 6),
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
@Expect(type = TargetUpdatedEvent.class, count = 2), @Expect(type = TargetPollEvent.class, count = 1) })
public void finishActionStatus() {
@@ -376,6 +378,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AmqpServiceIntegra
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
@Expect(type = ActionUpdatedEvent.class, count = 0), @Expect(type = ActionCreatedEvent.class, count = 1),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
+ @Expect(type = SoftwareModuleUpdatedEvent.class, count = 6),
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 1) })
public void runningActionStatus() {
@@ -389,6 +392,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AmqpServiceIntegra
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
@Expect(type = ActionCreatedEvent.class, count = 1),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
+ @Expect(type = SoftwareModuleUpdatedEvent.class, count = 6),
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 1) })
public void downloadActionStatus() {
@@ -402,6 +406,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AmqpServiceIntegra
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
@Expect(type = ActionUpdatedEvent.class, count = 1), @Expect(type = ActionCreatedEvent.class, count = 1),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
+ @Expect(type = SoftwareModuleUpdatedEvent.class, count = 6),
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
@Expect(type = TargetUpdatedEvent.class, count = 2), @Expect(type = TargetPollEvent.class, count = 1) })
public void errorActionStatus() {
@@ -415,6 +420,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AmqpServiceIntegra
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
@Expect(type = ActionCreatedEvent.class, count = 1),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
+ @Expect(type = SoftwareModuleUpdatedEvent.class, count = 6),
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 1) })
public void warningActionStatus() {
@@ -428,6 +434,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AmqpServiceIntegra
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
@Expect(type = ActionCreatedEvent.class, count = 1),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
+ @Expect(type = SoftwareModuleUpdatedEvent.class, count = 6),
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 1) })
public void retrievedActionStatus() {
@@ -441,6 +448,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AmqpServiceIntegra
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
@Expect(type = ActionCreatedEvent.class, count = 1),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
+ @Expect(type = SoftwareModuleUpdatedEvent.class, count = 6),
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 1) })
public void cancelNotAllowActionStatus() {
@@ -455,6 +463,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AmqpServiceIntegra
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
@Expect(type = ActionCreatedEvent.class, count = 1),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
+ @Expect(type = SoftwareModuleUpdatedEvent.class, count = 6),
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 2) })
public void receiveDownLoadAndInstallMessageAfterAssignment() {
@@ -463,6 +472,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AmqpServiceIntegra
// setup
createAndSendTarget(controllerId, TENANT_EXIST);
final DistributionSet distributionSet = testdataFactory.createDistributionSet(UUID.randomUUID().toString());
+ testdataFactory.addSoftwareModuleMetadata(distributionSet);
assignDistributionSet(distributionSet.getId(), controllerId);
// test
@@ -507,6 +517,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AmqpServiceIntegra
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
@Expect(type = ActionUpdatedEvent.class, count = 1), @Expect(type = ActionCreatedEvent.class, count = 1),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
+ @Expect(type = SoftwareModuleUpdatedEvent.class, count = 6),
@Expect(type = CancelTargetAssignmentEvent.class, count = 1),
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 1) })
@@ -526,6 +537,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AmqpServiceIntegra
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
@Expect(type = ActionCreatedEvent.class, count = 1),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
+ @Expect(type = SoftwareModuleUpdatedEvent.class, count = 6),
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 1) })
public void canceledRejectedNotAllowActionStatus() {
@@ -541,6 +553,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AmqpServiceIntegra
@Expect(type = CancelTargetAssignmentEvent.class, count = 1),
@Expect(type = ActionUpdatedEvent.class, count = 1), @Expect(type = ActionCreatedEvent.class, count = 1),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
+ @Expect(type = SoftwareModuleUpdatedEvent.class, count = 6),
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 1) })
public void canceledRejectedActionStatus() {
diff --git a/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AmqpServiceIntegrationTest.java b/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AmqpServiceIntegrationTest.java
index 62e83e3c3..3cdb34eb7 100644
--- a/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AmqpServiceIntegrationTest.java
+++ b/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AmqpServiceIntegrationTest.java
@@ -24,6 +24,7 @@ import org.eclipse.hawkbit.dmf.amqp.api.MessageHeaderKey;
import org.eclipse.hawkbit.dmf.amqp.api.MessageType;
import org.eclipse.hawkbit.dmf.json.model.DmfAttributeUpdate;
import org.eclipse.hawkbit.dmf.json.model.DmfDownloadAndUpdateRequest;
+import org.eclipse.hawkbit.dmf.json.model.DmfMetadata;
import org.eclipse.hawkbit.integration.listener.DeadletterListener;
import org.eclipse.hawkbit.integration.listener.ReplyToListener;
import org.eclipse.hawkbit.matcher.SoftwareModuleJsonMatcher;
@@ -35,6 +36,7 @@ import org.eclipse.hawkbit.repository.model.DistributionSetAssignmentResult;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
+import org.eclipse.hawkbit.repository.test.util.TestdataFactory;
import org.eclipse.hawkbit.util.IpUtil;
import org.junit.Assert;
import org.junit.Before;
@@ -107,6 +109,8 @@ public abstract class AmqpServiceIntegrationTest extends AbstractAmqpIntegration
protected DistributionSetAssignmentResult registerTargetAndAssignDistributionSet(final String controllerId) {
distributionSet = testdataFactory.createDistributionSet(UUID.randomUUID().toString());
+ testdataFactory.addSoftwareModuleMetadata(distributionSet);
+
return registerTargetAndAssignDistributionSet(distributionSet.getId(), TargetUpdateStatus.REGISTERED,
distributionSet.getModules(), controllerId);
}
@@ -165,6 +169,10 @@ public abstract class AmqpServiceIntegrationTest extends AbstractAmqpIntegration
Assert.assertThat(dsModules,
SoftwareModuleJsonMatcher.containsExactly(downloadAndUpdateRequest.getSoftwareModules()));
+ downloadAndUpdateRequest.getSoftwareModules()
+ .forEach(dmfModule -> assertThat(dmfModule.getMetadata()).containsExactly(
+ new DmfMetadata(TestdataFactory.VISIBLE_SM_MD_KEY, TestdataFactory.VISIBLE_SM_MD_VALUE)));
+
final Target updatedTarget = waitUntilIsPresent(() -> targetManagement.getByControllerID(controllerId));
assertThat(updatedTarget.getSecurityToken()).isEqualTo(downloadAndUpdateRequest.getTargetSecurityToken());
diff --git a/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/matcher/SoftwareModuleJsonMatcher.java b/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/matcher/SoftwareModuleJsonMatcher.java
index ad0ca16f1..1e29fc2bc 100644
--- a/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/matcher/SoftwareModuleJsonMatcher.java
+++ b/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/matcher/SoftwareModuleJsonMatcher.java
@@ -12,6 +12,7 @@ import java.util.Collection;
import java.util.List;
import java.util.Set;
+import org.eclipse.hawkbit.dmf.json.model.DmfSoftwareModule;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
@@ -44,21 +45,19 @@ public final class SoftwareModuleJsonMatcher {
* the json sofware modules.
*/
@Factory
- public static SoftwareModulesMatcher containsExactly(
- final List expectedModules) {
+ public static SoftwareModulesMatcher containsExactly(final List expectedModules) {
return new SoftwareModulesMatcher(expectedModules);
}
private static class SoftwareModulesMatcher extends BaseMatcher> {
- private final List expectedModules;
+ private final List expectedModules;
- public SoftwareModulesMatcher(List expectedModules) {
+ public SoftwareModulesMatcher(final List expectedModules) {
this.expectedModules = expectedModules;
}
- static boolean containsExactly(Object actual,
- List expected) {
+ static boolean containsExactly(final Object actual, final List expected) {
if (actual == null) {
return expected == null;
}
@@ -73,7 +72,7 @@ public final class SoftwareModuleJsonMatcher {
for (final SoftwareModule repoSoftwareModule : modules) {
boolean containsElement = false;
- for (final org.eclipse.hawkbit.dmf.json.model.DmfSoftwareModule jsonSoftwareModule : expected) {
+ for (final DmfSoftwareModule jsonSoftwareModule : expected) {
if (!jsonSoftwareModule.getModuleId().equals(repoSoftwareModule.getId())) {
continue;
}
@@ -100,12 +99,12 @@ public final class SoftwareModuleJsonMatcher {
}
@Override
- public boolean matches(Object actualValue) {
+ public boolean matches(final Object actualValue) {
return containsExactly(actualValue, expectedModules);
}
@Override
- public void describeTo(Description description) {
+ public void describeTo(final Description description) {
description.appendValue(expectedModules);
}
}
diff --git a/hawkbit-dmf/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/DmfArtifactHash.java b/hawkbit-dmf/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/DmfArtifactHash.java
index d8f8a9426..ffc159530 100644
--- a/hawkbit-dmf/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/DmfArtifactHash.java
+++ b/hawkbit-dmf/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/DmfArtifactHash.java
@@ -32,7 +32,6 @@ public class DmfArtifactHash {
*/
@JsonCreator
public DmfArtifactHash(@JsonProperty("sha1") final String sha1, @JsonProperty("md5") final String md5) {
- super();
this.sha1 = sha1;
this.md5 = md5;
}
diff --git a/hawkbit-dmf/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/DmfMetadata.java b/hawkbit-dmf/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/DmfMetadata.java
new file mode 100644
index 000000000..2f7ca7acc
--- /dev/null
+++ b/hawkbit-dmf/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/DmfMetadata.java
@@ -0,0 +1,82 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit.dmf.json.model;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * Additional metadata to be provided for the target/device.
+ *
+ */
+@JsonInclude(Include.NON_NULL)
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class DmfMetadata {
+ @JsonProperty
+ private final String key;
+
+ @JsonProperty
+ private final String value;
+
+ @JsonCreator
+ public DmfMetadata(@JsonProperty("key") final String key, @JsonProperty("value") final String value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((key == null) ? 0 : key.hashCode());
+ result = prime * result + ((value == null) ? 0 : value.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final DmfMetadata other = (DmfMetadata) obj;
+ if (key == null) {
+ if (other.key != null) {
+ return false;
+ }
+ } else if (!key.equals(other.key)) {
+ return false;
+ }
+ if (value == null) {
+ if (other.value != null) {
+ return false;
+ }
+ } else if (!value.equals(other.value)) {
+ return false;
+ }
+ return true;
+ }
+
+}
diff --git a/hawkbit-dmf/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/DmfSoftwareModule.java b/hawkbit-dmf/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/DmfSoftwareModule.java
index d85643f23..4b89ea712 100644
--- a/hawkbit-dmf/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/DmfSoftwareModule.java
+++ b/hawkbit-dmf/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/DmfSoftwareModule.java
@@ -20,9 +20,6 @@ import com.fasterxml.jackson.annotation.JsonProperty;
/**
* JSON representation of a software module.
*
- *
- *
- *
*/
@JsonInclude(Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
@@ -36,6 +33,8 @@ public class DmfSoftwareModule {
private String moduleVersion;
@JsonProperty
private List artifacts;
+ @JsonProperty
+ private List metadata;
public String getModuleType() {
return moduleType;
@@ -74,4 +73,14 @@ public class DmfSoftwareModule {
this.artifacts = artifacts;
}
+ public List getMetadata() {
+ return metadata;
+ }
+
+ public void setMetadata(final List metadata) {
+ if (metadata != null && !metadata.isEmpty()) {
+ this.metadata = metadata;
+ }
+ }
+
}
diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtMetadata.java b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtMetadata.java
index 6a6371d6b..73bd372c3 100644
--- a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtMetadata.java
+++ b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtMetadata.java
@@ -14,7 +14,7 @@ import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
- * The representation of an meta data in the REST API.
+ * The representation of an meta data in the REST API for POST/Create.
*
*/
@JsonInclude(Include.NON_NULL)
@@ -26,32 +26,18 @@ public class MgmtMetadata {
@JsonProperty
private String value;
- /**
- * @return the key
- */
public String getKey() {
return key;
}
- /**
- * @param key
- * the key to set
- */
public void setKey(final String key) {
this.key = key;
}
- /**
- * @return the value
- */
public String getValue() {
return value;
}
- /**
- * @param value
- * the value to set
- */
public void setValue(final String value) {
this.value = value;
}
diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtMetadataBodyPut.java b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtMetadataBodyPut.java
new file mode 100644
index 000000000..eaf7e8ca8
--- /dev/null
+++ b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtMetadataBodyPut.java
@@ -0,0 +1,34 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit.mgmt.json.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * The representation of an meta data in the REST API for PUT/Update.
+ *
+ */
+@JsonInclude(Include.NON_NULL)
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class MgmtMetadataBodyPut {
+
+ @JsonProperty
+ private String value;
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(final String value) {
+ this.value = value;
+ }
+}
diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremodule/MgmtSoftwareModuleMetadata.java b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremodule/MgmtSoftwareModuleMetadata.java
new file mode 100644
index 000000000..01750d26d
--- /dev/null
+++ b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremodule/MgmtSoftwareModuleMetadata.java
@@ -0,0 +1,55 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit.mgmt.json.model.softwaremodule;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * The representation of SoftwareModuleMetadata in the REST API for POST/Create.
+ *
+ */
+@JsonInclude(Include.NON_NULL)
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class MgmtSoftwareModuleMetadata {
+
+ @JsonProperty(required = true)
+ private String key;
+ @JsonProperty
+ private String value;
+ @JsonProperty
+ private boolean targetVisible;
+
+ public String getKey() {
+ return key;
+ }
+
+ public void setKey(final String key) {
+ this.key = key;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(final String value) {
+ this.value = value;
+ }
+
+ public boolean isTargetVisible() {
+ return targetVisible;
+ }
+
+ public void setTargetVisible(final boolean targetVisible) {
+ this.targetVisible = targetVisible;
+ }
+
+}
diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremodule/MgmtSoftwareModuleMetadataBodyPut.java b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremodule/MgmtSoftwareModuleMetadataBodyPut.java
new file mode 100644
index 000000000..67d6b39b1
--- /dev/null
+++ b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremodule/MgmtSoftwareModuleMetadataBodyPut.java
@@ -0,0 +1,44 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit.mgmt.json.model.softwaremodule;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * The representation of an meta data in the REST API for PUT/Update.
+ *
+ */
+@JsonInclude(Include.NON_NULL)
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class MgmtSoftwareModuleMetadataBodyPut {
+
+ @JsonProperty
+ private String value;
+ @JsonProperty
+ private Boolean targetVisible;
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(final String value) {
+ this.value = value;
+ }
+
+ public Boolean isTargetVisible() {
+ return targetVisible;
+ }
+
+ public void setTargetVisible(final Boolean targetVisible) {
+ this.targetVisible = targetVisible;
+ }
+}
diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtDistributionSetRestApi.java b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtDistributionSetRestApi.java
index b4200494c..0be8711e3 100644
--- a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtDistributionSetRestApi.java
+++ b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtDistributionSetRestApi.java
@@ -11,6 +11,7 @@ package org.eclipse.hawkbit.mgmt.rest.api;
import java.util.List;
import org.eclipse.hawkbit.mgmt.json.model.MgmtMetadata;
+import org.eclipse.hawkbit.mgmt.json.model.MgmtMetadataBodyPut;
import org.eclipse.hawkbit.mgmt.json.model.PagedList;
import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtDistributionSet;
import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtDistributionSetRequestBodyPost;
@@ -256,7 +257,8 @@ public interface MgmtDistributionSetRestApi {
*/
@RequestMapping(method = RequestMethod.GET, value = "/{distributionSetId}/metadata", produces = {
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
- ResponseEntity> getMetadata(@PathVariable("distributionSetId") Long distributionSetId,
+ ResponseEntity> getMetadata(
+ @PathVariable("distributionSetId") Long distributionSetId,
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) int pagingOffsetParam,
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) int pagingLimitParam,
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SORTING, required = false) String sortParam,
@@ -292,7 +294,7 @@ public interface MgmtDistributionSetRestApi {
@RequestMapping(method = RequestMethod.PUT, value = "/{distributionSetId}/metadata/{metadataKey}", produces = {
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
ResponseEntity updateMetadata(@PathVariable("distributionSetId") Long distributionSetId,
- @PathVariable("metadataKey") String metadataKey, MgmtMetadata metadata);
+ @PathVariable("metadataKey") String metadataKey, MgmtMetadataBodyPut metadata);
/**
* Deletes a single meta data entry from the distribution set.
diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtRestConstants.java b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtRestConstants.java
index 46b195031..5893eaba0 100644
--- a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtRestConstants.java
+++ b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtRestConstants.java
@@ -185,6 +185,9 @@ public final class MgmtRestConstants {
*/
public static final String SOFTWAREMODULETYPE_V1_REQUEST_MAPPING = BASE_V1_REQUEST_MAPPING + "/softwaremoduletypes";
+ /**
+ * The distributon set base resource.
+ */
public static final String DISTRIBUTIONSETTYPE_V1_REQUEST_MAPPING = BASE_V1_REQUEST_MAPPING
+ "/distributionsettypes";
diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtSoftwareModuleRestApi.java b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtSoftwareModuleRestApi.java
index 37c6b1eab..d271335fd 100644
--- a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtSoftwareModuleRestApi.java
+++ b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtSoftwareModuleRestApi.java
@@ -10,10 +10,11 @@ package org.eclipse.hawkbit.mgmt.rest.api;
import java.util.List;
-import org.eclipse.hawkbit.mgmt.json.model.MgmtMetadata;
import org.eclipse.hawkbit.mgmt.json.model.PagedList;
import org.eclipse.hawkbit.mgmt.json.model.artifact.MgmtArtifact;
import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModule;
+import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModuleMetadata;
+import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModuleMetadataBodyPut;
import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModuleRequestBodyPost;
import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModuleRequestBodyPut;
import org.springframework.hateoas.MediaTypes;
@@ -214,7 +215,8 @@ public interface MgmtSoftwareModuleRestApi {
*/
@RequestMapping(method = RequestMethod.GET, value = "/{softwareModuleId}/metadata", produces = {
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
- ResponseEntity> getMetadata(@PathVariable("softwareModuleId") final Long softwareModuleId,
+ ResponseEntity> getMetadata(
+ @PathVariable("softwareModuleId") final Long softwareModuleId,
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) final int pagingOffsetParam,
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) final int pagingLimitParam,
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SORTING, required = false) final String sortParam,
@@ -232,7 +234,8 @@ public interface MgmtSoftwareModuleRestApi {
*/
@RequestMapping(method = RequestMethod.GET, value = "/{softwareModuleId}/metadata/{metadataKey}", produces = {
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
- ResponseEntity getMetadataValue(@PathVariable("softwareModuleId") final Long softwareModuleId,
+ ResponseEntity getMetadataValue(
+ @PathVariable("softwareModuleId") final Long softwareModuleId,
@PathVariable("metadataKey") final String metadataKey);
/**
@@ -242,13 +245,16 @@ public interface MgmtSoftwareModuleRestApi {
* the ID of the software module to update the meta data entry
* @param metadataKey
* the key of the meta data to update the value
+ * @param metadata
+ * body to update
* @return status OK if the update request is successful and the updated
* meta data result
*/
@RequestMapping(method = RequestMethod.PUT, value = "/{softwareModuleId}/metadata/{metadataKey}", produces = {
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
- ResponseEntity updateMetadata(@PathVariable("softwareModuleId") final Long softwareModuleId,
- @PathVariable("metadataKey") final String metadataKey, final MgmtMetadata metadata);
+ ResponseEntity updateMetadata(
+ @PathVariable("softwareModuleId") final Long softwareModuleId,
+ @PathVariable("metadataKey") final String metadataKey, final MgmtSoftwareModuleMetadataBodyPut metadata);
/**
* Deletes a single meta data entry from the software module.
@@ -276,7 +282,8 @@ public interface MgmtSoftwareModuleRestApi {
@RequestMapping(method = RequestMethod.POST, value = "/{softwareModuleId}/metadata", consumes = {
MediaType.APPLICATION_JSON_VALUE,
MediaTypes.HAL_JSON_VALUE }, produces = { MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
- ResponseEntity> createMetadata(@PathVariable("softwareModuleId") final Long softwareModuleId,
- final List metadataRest);
+ ResponseEntity> createMetadata(
+ @PathVariable("softwareModuleId") final Long softwareModuleId,
+ final List metadataRest);
}
diff --git a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetResource.java b/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetResource.java
index 896b15078..b9b89f2ff 100644
--- a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetResource.java
+++ b/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetResource.java
@@ -13,6 +13,7 @@ import java.util.List;
import java.util.stream.Collectors;
import org.eclipse.hawkbit.mgmt.json.model.MgmtMetadata;
+import org.eclipse.hawkbit.mgmt.json.model.MgmtMetadataBodyPut;
import org.eclipse.hawkbit.mgmt.json.model.PagedList;
import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtDistributionSet;
import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtDistributionSetRequestBodyPost;
@@ -298,8 +299,9 @@ public class MgmtDistributionSetResource implements MgmtDistributionSetRestApi {
}
@Override
- public ResponseEntity updateMetadata(@PathVariable("distributionSetId") final Long distributionSetId,
- @PathVariable("metadataKey") final String metadataKey, @RequestBody final MgmtMetadata metadata) {
+ public ResponseEntity updateMetadata(
+ @PathVariable("distributionSetId") final Long distributionSetId,
+ @PathVariable("metadataKey") final String metadataKey, @RequestBody final MgmtMetadataBodyPut metadata) {
// check if distribution set exists otherwise throw exception
// immediately
final DistributionSetMetadata updated = distributionSetManagement.updateMetaData(distributionSetId,
diff --git a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleMapper.java b/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleMapper.java
index bf09750e4..bb8952285 100644
--- a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleMapper.java
+++ b/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleMapper.java
@@ -16,18 +16,18 @@ import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
-import org.eclipse.hawkbit.mgmt.json.model.MgmtMetadata;
import org.eclipse.hawkbit.mgmt.json.model.artifact.MgmtArtifact;
import org.eclipse.hawkbit.mgmt.json.model.artifact.MgmtArtifactHash;
import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModule;
+import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModuleMetadata;
import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModuleRequestBodyPost;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtSoftwareModuleRestApi;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtSoftwareModuleTypeRestApi;
import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.builder.SoftwareModuleCreate;
+import org.eclipse.hawkbit.repository.builder.SoftwareModuleMetadataCreate;
import org.eclipse.hawkbit.repository.model.Artifact;
-import org.eclipse.hawkbit.repository.model.MetaData;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
import org.eclipse.hawkbit.rest.data.ResponseList;
@@ -48,14 +48,16 @@ public final class MgmtSoftwareModuleMapper {
.version(smsRest.getVersion()).description(smsRest.getDescription()).vendor(smsRest.getVendor());
}
- static List fromRequestSwMetadata(final EntityFactory entityFactory,
- final Collection metadata) {
+ static List fromRequestSwMetadata(final EntityFactory entityFactory,
+ final Long softwareModuleId, final Collection metadata) {
if (metadata == null) {
return Collections.emptyList();
}
return metadata.stream()
- .map(metadataRest -> entityFactory.generateMetadata(metadataRest.getKey(), metadataRest.getValue()))
+ .map(metadataRest -> entityFactory.softwareModuleMetadata().create(softwareModuleId)
+ .key(metadataRest.getKey()).value(metadataRest.getValue())
+ .targetVisible(metadataRest.isTargetVisible()))
.collect(Collectors.toList());
}
@@ -77,7 +79,8 @@ public final class MgmtSoftwareModuleMapper {
softwareModules.stream().map(MgmtSoftwareModuleMapper::toResponse).collect(Collectors.toList()));
}
- static List toResponseSwMetadata(final Collection metadata) {
+ static List toResponseSwMetadata(
+ final Collection metadata) {
if (metadata == null) {
return Collections.emptyList();
}
@@ -85,10 +88,11 @@ public final class MgmtSoftwareModuleMapper {
return metadata.stream().map(MgmtSoftwareModuleMapper::toResponseSwMetadata).collect(Collectors.toList());
}
- static MgmtMetadata toResponseSwMetadata(final SoftwareModuleMetadata metadata) {
- final MgmtMetadata metadataRest = new MgmtMetadata();
+ static MgmtSoftwareModuleMetadata toResponseSwMetadata(final SoftwareModuleMetadata metadata) {
+ final MgmtSoftwareModuleMetadata metadataRest = new MgmtSoftwareModuleMetadata();
metadataRest.setKey(metadata.getKey());
metadataRest.setValue(metadata.getValue());
+ metadataRest.setTargetVisible(metadata.isTargetVisible());
return metadataRest;
}
diff --git a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResource.java b/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResource.java
index acd8159ff..ab9ad091a 100644
--- a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResource.java
+++ b/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResource.java
@@ -12,10 +12,11 @@ import java.io.IOException;
import java.util.Collection;
import java.util.List;
-import org.eclipse.hawkbit.mgmt.json.model.MgmtMetadata;
import org.eclipse.hawkbit.mgmt.json.model.PagedList;
import org.eclipse.hawkbit.mgmt.json.model.artifact.MgmtArtifact;
import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModule;
+import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModuleMetadata;
+import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModuleMetadataBodyPut;
import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModuleRequestBodyPost;
import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModuleRequestBodyPut;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
@@ -205,7 +206,7 @@ public class MgmtSoftwareModuleResource implements MgmtSoftwareModuleRestApi {
}
@Override
- public ResponseEntity> getMetadata(
+ public ResponseEntity> getMetadata(
@PathVariable("softwareModuleId") final Long softwareModuleId,
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) final int pagingOffsetParam,
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) final int pagingLimitParam,
@@ -234,7 +235,8 @@ public class MgmtSoftwareModuleResource implements MgmtSoftwareModuleRestApi {
}
@Override
- public ResponseEntity getMetadataValue(@PathVariable("softwareModuleId") final Long softwareModuleId,
+ public ResponseEntity getMetadataValue(
+ @PathVariable("softwareModuleId") final Long softwareModuleId,
@PathVariable("metadataKey") final String metadataKey) {
final SoftwareModuleMetadata findOne = softwareModuleManagement
@@ -245,10 +247,13 @@ public class MgmtSoftwareModuleResource implements MgmtSoftwareModuleRestApi {
}
@Override
- public ResponseEntity updateMetadata(@PathVariable("softwareModuleId") final Long softwareModuleId,
- @PathVariable("metadataKey") final String metadataKey, @RequestBody final MgmtMetadata metadata) {
- final SoftwareModuleMetadata updated = softwareModuleManagement.updateMetaData(softwareModuleId,
- entityFactory.generateMetadata(metadataKey, metadata.getValue()));
+ public ResponseEntity updateMetadata(
+ @PathVariable("softwareModuleId") final Long softwareModuleId,
+ @PathVariable("metadataKey") final String metadataKey,
+ @RequestBody final MgmtSoftwareModuleMetadataBodyPut metadata) {
+ final SoftwareModuleMetadata updated = softwareModuleManagement
+ .updateMetaData(entityFactory.softwareModuleMetadata().update(softwareModuleId, metadataKey)
+ .value(metadata.getValue()).targetVisible(metadata.isTargetVisible()));
return ResponseEntity.ok(MgmtSoftwareModuleMapper.toResponseSwMetadata(updated));
}
@@ -262,12 +267,12 @@ public class MgmtSoftwareModuleResource implements MgmtSoftwareModuleRestApi {
}
@Override
- public ResponseEntity> createMetadata(
+ public ResponseEntity> createMetadata(
@PathVariable("softwareModuleId") final Long softwareModuleId,
- @RequestBody final List metadataRest) {
+ @RequestBody final List metadataRest) {
- final List created = softwareModuleManagement.createMetaData(softwareModuleId,
- MgmtSoftwareModuleMapper.fromRequestSwMetadata(entityFactory, metadataRest));
+ final List created = softwareModuleManagement.createMetaData(
+ MgmtSoftwareModuleMapper.fromRequestSwMetadata(entityFactory, softwareModuleId, metadataRest));
return ResponseEntity.status(HttpStatus.CREATED).body(MgmtSoftwareModuleMapper.toResponseSwMetadata(created));
}
diff --git a/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResourceTest.java b/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResourceTest.java
index 80fa141fc..d410d29cf 100644
--- a/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResourceTest.java
+++ b/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResourceTest.java
@@ -85,9 +85,8 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
final String updateVendor = "newVendor1";
final String updateDescription = "newDescription1";
- SoftwareModule sm = softwareModuleManagement
- .create(entityFactory.softwareModule().create().type(osType).name(knownSWName)
- .version(knownSWVersion).description(knownSWDescription).vendor(knownSWVendor));
+ SoftwareModule sm = softwareModuleManagement.create(entityFactory.softwareModule().create().type(osType)
+ .name(knownSWName).version(knownSWVersion).description(knownSWDescription).vendor(knownSWVendor));
assertThat(sm.getName()).as("Wrong name of the software module").isEqualTo(knownSWName);
@@ -140,8 +139,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
// check rest of response compared to DB
final MgmtArtifact artResult = ResourceUtility
.convertArtifactResponse(mvcResult.getResponse().getContentAsString());
- final Long artId = softwareModuleManagement.get(sm.getId()).get().getArtifacts().get(0)
- .getId();
+ final Long artId = softwareModuleManagement.get(sm.getId()).get().getArtifacts().get(0).getId();
assertThat(artResult.getArtifactId()).as("Wrong artifact id").isEqualTo(artId);
assertThat(JsonPath.compile("$._links.self.href").read(mvcResult.getResponse().getContentAsString()).toString())
.as("Link contains no self url")
@@ -159,8 +157,8 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
assertThat(artifactManagement.count()).as("Wrong artifact size").isEqualTo(1);
// binary
- try (InputStream fileInputStream = artifactManagement.loadArtifactBinary(
- softwareModuleManagement.get(sm.getId()).get().getArtifacts().get(0).getSha1Hash())
+ try (InputStream fileInputStream = artifactManagement
+ .loadArtifactBinary(softwareModuleManagement.get(sm.getId()).get().getArtifacts().get(0).getSha1Hash())
.get().getFileInputStream()) {
assertTrue("Wrong artifact content",
IOUtils.contentEquals(new ByteArrayInputStream(random), fileInputStream));
@@ -174,9 +172,8 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
.isEqualTo(HashGeneratorUtils.generateMD5(random));
// metadata
- assertThat(
- softwareModuleManagement.get(sm.getId()).get().getArtifacts().get(0).getFilename())
- .as("wrong metadata of the filename").isEqualTo("origFilename");
+ assertThat(softwareModuleManagement.get(sm.getId()).get().getArtifacts().get(0).getFilename())
+ .as("wrong metadata of the filename").isEqualTo("origFilename");
}
@Test
@@ -237,8 +234,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
assertThat(artifactManagement.count()).isEqualTo(1);
// hashes
- assertThat(artifactManagement.getByFilename("customFilename")).as("Local artifact is wrong")
- .isPresent();
+ assertThat(artifactManagement.getByFilename("customFilename")).as("Local artifact is wrong").isPresent();
}
@Test
@@ -291,10 +287,10 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
final byte random[] = RandomStringUtils.random(5 * 1024).getBytes();
- final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), sm.getId(),
- "file1", false);
- final Artifact artifact2 = artifactManagement.create(new ByteArrayInputStream(random), sm.getId(),
- "file2", false);
+ final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), sm.getId(), "file1",
+ false);
+ final Artifact artifact2 = artifactManagement.create(new ByteArrayInputStream(random), sm.getId(), "file2",
+ false);
downloadAndVerify(sm, random, artifact);
downloadAndVerify(sm, random, artifact2);
@@ -321,8 +317,8 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
final SoftwareModule sm = testdataFactory.createSoftwareModuleOs();
final byte random[] = RandomStringUtils.random(5 * 1024).getBytes();
- final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), sm.getId(),
- "file1", false);
+ final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), sm.getId(), "file1",
+ false);
// perform test
mvc.perform(get("/rest/v1/softwaremodules/{smId}/artifacts/{artId}", sm.getId(), artifact.getId())
@@ -347,10 +343,10 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
final byte random[] = RandomStringUtils.random(5 * 1024).getBytes();
- final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), sm.getId(),
- "file1", false);
- final Artifact artifact2 = artifactManagement.create(new ByteArrayInputStream(random), sm.getId(),
- "file2", false);
+ final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), sm.getId(), "file1",
+ false);
+ final Artifact artifact2 = artifactManagement.create(new ByteArrayInputStream(random), sm.getId(), "file2",
+ false);
mvc.perform(get("/rest/v1/softwaremodules/{smId}/artifacts", sm.getId()).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
@@ -678,16 +674,14 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
.isEqualTo("http://localhost/rest/v1/softwaremodules/" + appCreated.getId());
assertThat(softwareModuleManagement.findAll(PAGE)).as("Wrong softwaremodule size").hasSize(2);
- assertThat(
- softwareModuleManagement.findByType(PAGE, osType.getId()).getContent().get(0).getName())
- .as("Softwaremoudle name is wrong").isEqualTo(os.getName());
- assertThat(softwareModuleManagement.findByType(PAGE, osType.getId()).getContent().get(0)
- .getCreatedBy()).as("Softwaremoudle created by is wrong").isEqualTo("uploadTester");
- assertThat(softwareModuleManagement.findByType(PAGE, osType.getId()).getContent().get(0)
- .getCreatedAt()).as("Softwaremoudle created at is wrong").isGreaterThanOrEqualTo(current);
- assertThat(
- softwareModuleManagement.findByType(PAGE, appType.getId()).getContent().get(0).getName())
- .as("Softwaremoudle name is wrong").isEqualTo(ah.getName());
+ assertThat(softwareModuleManagement.findByType(PAGE, osType.getId()).getContent().get(0).getName())
+ .as("Softwaremoudle name is wrong").isEqualTo(os.getName());
+ assertThat(softwareModuleManagement.findByType(PAGE, osType.getId()).getContent().get(0).getCreatedBy())
+ .as("Softwaremoudle created by is wrong").isEqualTo("uploadTester");
+ assertThat(softwareModuleManagement.findByType(PAGE, osType.getId()).getContent().get(0).getCreatedAt())
+ .as("Softwaremoudle created at is wrong").isGreaterThanOrEqualTo(current);
+ assertThat(softwareModuleManagement.findByType(PAGE, appType.getId()).getContent().get(0).getName())
+ .as("Softwaremoudle name is wrong").isEqualTo(ah.getName());
}
@Test
@@ -706,8 +700,8 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
mvc.perform(delete("/rest/v1/softwaremodules/{smId}", sm.getId())).andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk());
- assertThat(softwareModuleManagement.findAll(PAGE))
- .as("After delete no softwarmodule should be available").isEmpty();
+ assertThat(softwareModuleManagement.findAll(PAGE)).as("After delete no softwarmodule should be available")
+ .isEmpty();
assertThat(artifactManagement.count()).isEqualTo(0);
}
@@ -718,8 +712,8 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
final byte random[] = RandomStringUtils.random(5 * 1024).getBytes();
- artifactManagement.create(new ByteArrayInputStream(random),
- ds1.findFirstModuleByType(appType).get().getId(), "file1", false);
+ artifactManagement.create(new ByteArrayInputStream(random), ds1.findFirstModuleByType(appType).get().getId(),
+ "file1", false);
assertThat(softwareModuleManagement.findAll(PAGE)).hasSize(3);
assertThat(artifactManagement.count()).isEqualTo(1);
@@ -746,8 +740,8 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
final byte random[] = RandomStringUtils.random(5 * 1024).getBytes();
// Create 2 artifacts
- final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), sm.getId(),
- "file1", false);
+ final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), sm.getId(), "file1",
+ false);
artifactManagement.create(new ByteArrayInputStream(random), sm.getId(), "file2", false);
// check repo before delete
@@ -761,8 +755,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
// check that only one artifact is still alive and still assigned
- assertThat(softwareModuleManagement.findAll(PAGE)).as("After the sm should be marked as deleted")
- .hasSize(1);
+ assertThat(softwareModuleManagement.findAll(PAGE)).as("After the sm should be marked as deleted").hasSize(1);
assertThat(artifactManagement.count()).isEqualTo(1);
assertThat(softwareModuleManagement.get(sm.getId()).get().getArtifacts())
.as("After delete artifact should available for marked as deleted sm's").hasSize(1);
@@ -775,22 +768,23 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
final String knownKey1 = "knownKey1";
final String knownValue1 = "knownValue1";
- final String knownKey2 = "knownKey1";
+ final String knownKey2 = "knownKey2";
final String knownValue2 = "knownValue1";
final SoftwareModule sm = testdataFactory.createSoftwareModuleOs();
final JSONArray jsonArray = new JSONArray();
jsonArray.put(new JSONObject().put("key", knownKey1).put("value", knownValue1));
- jsonArray.put(new JSONObject().put("key", knownKey2).put("value", knownValue2));
+ jsonArray.put(new JSONObject().put("key", knownKey2).put("value", knownValue2).put("targetVisible", true));
mvc.perform(post("/rest/v1/softwaremodules/{swId}/metadata", sm.getId()).accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON).content(jsonArray.toString()))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
.andExpect(jsonPath("[0]key", equalTo(knownKey1))).andExpect(jsonPath("[0]value", equalTo(knownValue1)))
- .andExpect(jsonPath("[1]key", equalTo(knownKey2)))
- .andExpect(jsonPath("[1]value", equalTo(knownValue2)));
+ .andExpect(jsonPath("[0]targetVisible", equalTo(false)))
+ .andExpect(jsonPath("[1]key", equalTo(knownKey2))).andExpect(jsonPath("[1]value", equalTo(knownValue2)))
+ .andExpect(jsonPath("[1]targetVisible", equalTo(true)));
final SoftwareModuleMetadata metaKey1 = softwareModuleManagement
.getMetaDataBySoftwareModuleId(sm.getId(), knownKey1).get();
@@ -810,10 +804,11 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
final String updateValue = "valueForUpdate";
final SoftwareModule sm = testdataFactory.createSoftwareModuleOs();
- softwareModuleManagement.createMetaData(sm.getId(),
- entityFactory.generateMetadata(knownKey, knownValue));
+ softwareModuleManagement.createMetaData(
+ entityFactory.softwareModuleMetadata().create(sm.getId()).key(knownKey).value(knownValue));
- final JSONObject jsonObject = new JSONObject().put("key", knownKey).put("value", updateValue);
+ final JSONObject jsonObject = new JSONObject().put("key", knownKey).put("value", updateValue)
+ .put("targetVisible", true);
mvc.perform(put("/rest/v1/softwaremodules/{swId}/metadata/{key}", sm.getId(), knownKey)
.accept(MediaType.APPLICATION_JSON).contentType(MediaType.APPLICATION_JSON)
@@ -824,6 +819,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
final SoftwareModuleMetadata assertDS = softwareModuleManagement
.getMetaDataBySoftwareModuleId(sm.getId(), knownKey).get();
assertThat(assertDS.getValue()).as("Metadata is wrong").isEqualTo(updateValue);
+ assertThat(assertDS.isTargetVisible()).as("target visible is wrong").isTrue();
}
@Test
@@ -834,8 +830,8 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
final String knownValue = "knownValue";
final SoftwareModule sm = testdataFactory.createSoftwareModuleOs();
- softwareModuleManagement.createMetaData(sm.getId(),
- entityFactory.generateMetadata(knownKey, knownValue));
+ softwareModuleManagement.createMetaData(
+ entityFactory.softwareModuleMetadata().create(sm.getId()).key(knownKey).value(knownValue));
mvc.perform(delete("/rest/v1/softwaremodules/{swId}/metadata/{key}", sm.getId(), knownKey))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
@@ -851,8 +847,8 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
final String knownValue = "knownValue";
final SoftwareModule sm = testdataFactory.createSoftwareModuleOs();
- softwareModuleManagement.createMetaData(sm.getId(),
- entityFactory.generateMetadata(knownKey, knownValue));
+ softwareModuleManagement.createMetaData(
+ entityFactory.softwareModuleMetadata().create(sm.getId()).key(knownKey).value(knownValue));
mvc.perform(delete("/rest/v1/softwaremodules/{swId}/metadata/XXX", sm.getId(), knownKey))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
@@ -879,8 +875,8 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
final SoftwareModule sm = testdataFactory.createSoftwareModuleOs();
for (int index = 0; index < totalMetadata; index++) {
- softwareModuleManagement.createMetaData(sm.getId(),
- entityFactory.generateMetadata(knownKeyPrefix + index, knownValuePrefix + index));
+ softwareModuleManagement.createMetaData(entityFactory.softwareModuleMetadata().create(sm.getId())
+ .key(knownKeyPrefix + index).value(knownValuePrefix + index));
}
final String rsqlSearchValue1 = "value==knownValue1";
diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java
index 863212a25..5bd07e6d5 100644
--- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java
+++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java
@@ -9,6 +9,7 @@
package org.eclipse.hawkbit.repository;
import java.net.URI;
+import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@@ -25,6 +26,7 @@ import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.Status;
import org.eclipse.hawkbit.repository.model.ActionStatus;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
+import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey;
@@ -72,7 +74,20 @@ public interface ControllerManagement {
* @return {@link SoftwareModule} identified by ID
*/
@PreAuthorize(SpringEvalExpressions.IS_CONTROLLER)
- Optional getSoftwareModule(@NotNull final Long moduleId);
+ Optional getSoftwareModule(@NotNull Long moduleId);
+
+ /**
+ * Retrieves {@link SoftwareModuleMetadata} where
+ * {@link SoftwareModuleMetadata#isTargetVisible()}.
+ *
+ * @param moduleId
+ * of the {@link SoftwareModule}
+ * @return list of {@link SoftwareModuleMetadata} with maximum size of
+ * {@link RepositoryConstants#MAX_META_DATA_COUNT}
+ */
+ @PreAuthorize(SpringEvalExpressions.IS_CONTROLLER)
+ Map> findTargetVisibleMetaDataBySoftwareModuleId(
+ @NotNull Collection moduleId);
/**
* Simple addition of a new {@link ActionStatus} entry to the {@link Action}
diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/EntityFactory.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/EntityFactory.java
index d0036c4d2..0de3174bf 100644
--- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/EntityFactory.java
+++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/EntityFactory.java
@@ -9,6 +9,7 @@
package org.eclipse.hawkbit.repository;
import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
import org.eclipse.hawkbit.repository.builder.ActionStatusBuilder;
import org.eclipse.hawkbit.repository.builder.DistributionSetBuilder;
@@ -16,13 +17,13 @@ import org.eclipse.hawkbit.repository.builder.DistributionSetTypeBuilder;
import org.eclipse.hawkbit.repository.builder.RolloutBuilder;
import org.eclipse.hawkbit.repository.builder.RolloutGroupBuilder;
import org.eclipse.hawkbit.repository.builder.SoftwareModuleBuilder;
+import org.eclipse.hawkbit.repository.builder.SoftwareModuleMetadataBuilder;
import org.eclipse.hawkbit.repository.builder.SoftwareModuleTypeBuilder;
import org.eclipse.hawkbit.repository.builder.TagBuilder;
import org.eclipse.hawkbit.repository.builder.TargetBuilder;
import org.eclipse.hawkbit.repository.builder.TargetFilterQueryBuilder;
import org.eclipse.hawkbit.repository.model.BaseEntity;
import org.eclipse.hawkbit.repository.model.MetaData;
-import org.hibernate.validator.constraints.NotEmpty;
/**
* central {@link BaseEntity} generation service. Objects are created but not
@@ -51,7 +52,13 @@ public interface EntityFactory {
*
* @return {@link MetaData} object
*/
- MetaData generateMetadata(@NotEmpty String key, @NotNull String value);
+ MetaData generateMetadata(@Size(min = 1, max = MetaData.KEY_MAX_SIZE) @NotNull String key,
+ @Size(min = 1, max = MetaData.VALUE_MAX_SIZE) @NotNull String value);
+
+ /**
+ * @return {@link SoftwareModuleMetadataBuilder} object
+ */
+ SoftwareModuleMetadataBuilder softwareModuleMetadata();
/**
* @return {@link TagBuilder} object
diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RepositoryConstants.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RepositoryConstants.java
index e4d801b8e..9ec08272d 100644
--- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RepositoryConstants.java
+++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RepositoryConstants.java
@@ -8,8 +8,10 @@
*/
package org.eclipse.hawkbit.repository;
+import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.ActionStatus;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
+import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
/**
* Repository constants.
@@ -36,6 +38,13 @@ public final class RepositoryConstants {
*/
public static final int MAX_ACTION_HISTORY_MSG_COUNT = 100;
+ /**
+ * Maximum number of metadata entries provided to controllers.
+ *
+ * @see SoftwareModuleMetadata#isTargetVisible()
+ */
+ public static final int MAX_META_DATA_COUNT = 50;
+
private RepositoryConstants() {
// Utility class.
}
diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleManagement.java
index dc5076444..3803177fb 100644
--- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleManagement.java
+++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleManagement.java
@@ -16,6 +16,8 @@ import javax.validation.constraints.NotNull;
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
import org.eclipse.hawkbit.repository.builder.SoftwareModuleCreate;
+import org.eclipse.hawkbit.repository.builder.SoftwareModuleMetadataCreate;
+import org.eclipse.hawkbit.repository.builder.SoftwareModuleMetadataUpdate;
import org.eclipse.hawkbit.repository.builder.SoftwareModuleUpdate;
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
@@ -23,7 +25,6 @@ import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException;
import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException;
import org.eclipse.hawkbit.repository.model.AssignedSoftwareModule;
import org.eclipse.hawkbit.repository.model.DistributionSet;
-import org.eclipse.hawkbit.repository.model.MetaData;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
@@ -60,10 +61,8 @@ public interface SoftwareModuleManagement
/**
* creates a list of software module meta data entries.
*
- * @param moduleId
- * the metadata belongs to
* @param metadata
- * the meta data entries to create or update
+ * the meta data entries to create
* @return the updated or created software module meta data entries
* @throws EntityAlreadyExistsException
* in case one of the meta data entry already exists for the
@@ -72,15 +71,13 @@ public interface SoftwareModuleManagement
* if software module with given ID does not exist
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY)
- List createMetaData(@NotNull Long moduleId, @NotNull Collection metadata);
+ List createMetaData(@NotNull Collection metadata);
/**
* creates or updates a single software module meta data entry.
*
- * @param moduleId
- * the metadata belongs to
* @param metadata
- * the meta data entry to create or update
+ * the meta data entry to create
* @return the updated or created software module meta data entry
* @throws EntityAlreadyExistsException
* in case the meta data entry already exists for the specific
@@ -89,7 +86,7 @@ public interface SoftwareModuleManagement
* if software module with given ID does not exist
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY)
- SoftwareModuleMetadata createMetaData(@NotNull Long moduleId, @NotNull MetaData metadata);
+ SoftwareModuleMetadata createMetaData(@NotNull SoftwareModuleMetadataCreate metadata);
/**
* deletes a software module meta data entry.
@@ -188,6 +185,25 @@ public interface SoftwareModuleManagement
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
Page findMetaDataBySoftwareModuleId(@NotNull Pageable pageable, @NotNull Long moduleId);
+ /**
+ * finds all meta data by the given software module id where
+ * {@link SoftwareModuleMetadata#isTargetVisible()}.
+ *
+ * @param pageable
+ * the page request to page the result
+ * @param moduleId
+ * the software module id to retrieve the meta data from
+ *
+ * @return a paged result of all meta data entries for a given software
+ * module id
+ *
+ * @throws EntityNotFoundException
+ * if software module with given ID does not exist
+ */
+ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
+ Page findMetaDataBySoftwareModuleIdAndTargetVisible(@NotNull Pageable pageable,
+ @NotNull Long moduleId);
+
/**
* finds all meta data by the given software module id.
*
@@ -259,9 +275,7 @@ public interface SoftwareModuleManagement
/**
* updates a distribution set meta data value if corresponding entry exists.
*
- * @param moduleId
- * the metadata belongs to
- * @param metadata
+ * @param update
* the meta data entry to be updated
*
* @return the updated meta data entry
@@ -271,5 +285,5 @@ public interface SoftwareModuleManagement
* updated
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY)
- SoftwareModuleMetadata updateMetaData(@NotNull Long moduleId, @NotNull MetaData metadata);
+ SoftwareModuleMetadata updateMetaData(@NotNull SoftwareModuleMetadataUpdate update);
}
diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SystemManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SystemManagement.java
index fcad67fd7..6a144096f 100644
--- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SystemManagement.java
+++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SystemManagement.java
@@ -57,6 +57,8 @@ public interface SystemManagement {
/**
* Runs consumer for each teant as
* {@link TenantAware#runAsTenant(String, org.eclipse.hawkbit.tenancy.TenantAware.TenantRunner)}
+ * sliently (i.e. exceptions will be logged but operations will continue for
+ * further tenants).
*
* @param consumer
* to run as teanant
diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleMetadataBuilder.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleMetadataBuilder.java
new file mode 100644
index 000000000..b4a748744
--- /dev/null
+++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleMetadataBuilder.java
@@ -0,0 +1,37 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit.repository.builder;
+
+import org.eclipse.hawkbit.repository.model.MetaData;
+import org.eclipse.hawkbit.repository.model.SoftwareModule;
+import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
+
+/**
+ * Builder for {@link SoftwareModuleMetadata}.
+ *
+ */
+public interface SoftwareModuleMetadataBuilder {
+
+ /**
+ * @param softwareModuleId
+ * of the {@link SoftwareModule} the {@link MetaData} belongs to
+ * @param key
+ * of {@link MetaData#getKey()}
+ * @return builder instance
+ */
+ SoftwareModuleMetadataUpdate update(long softwareModuleId, String key);
+
+ /**
+ * @param softwareModuleId
+ * of the {@link SoftwareModule} the {@link MetaData} belongs to
+ * @return builder instance
+ */
+ SoftwareModuleMetadataCreate create(long softwareModuleId);
+
+}
diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleMetadataCreate.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleMetadataCreate.java
new file mode 100644
index 000000000..6bcf6ce11
--- /dev/null
+++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleMetadataCreate.java
@@ -0,0 +1,53 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit.repository.builder;
+
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+
+import org.eclipse.hawkbit.repository.model.BaseEntity;
+import org.eclipse.hawkbit.repository.model.MetaData;
+import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
+
+/**
+ * Builder to create a new {@link SoftwareModuleMetadata} entry. Defines all
+ * fields that can be set at creation time. Other fields are set by the
+ * repository automatically, e.g. {@link BaseEntity#getCreatedAt()}.
+ *
+ */
+public interface SoftwareModuleMetadataCreate {
+
+ /**
+ * @param key
+ * for {@link MetaData#getKey()}
+ * @return updated builder instance
+ */
+ SoftwareModuleMetadataCreate key(@Size(min = 1, max = MetaData.KEY_MAX_SIZE) @NotNull String key);
+
+ /**
+ * @param value
+ * for {@link MetaData#getValue()}
+ * @return updated builder instance
+ */
+ SoftwareModuleMetadataCreate value(@Size(min = 1, max = MetaData.VALUE_MAX_SIZE) @NotNull String value);
+
+ /**
+ * @param visible
+ * for {@link SoftwareModuleMetadata#isTargetVisible()}
+ * @return updated builder instance
+ */
+ SoftwareModuleMetadataCreate targetVisible(Boolean visible);
+
+ /**
+ * @return peek on current state of {@link SoftwareModuleMetadata} in the
+ * builder
+ */
+ SoftwareModuleMetadata build();
+
+}
diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleMetadataUpdate.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleMetadataUpdate.java
new file mode 100644
index 000000000..9a3734f60
--- /dev/null
+++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleMetadataUpdate.java
@@ -0,0 +1,37 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit.repository.builder;
+
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+
+import org.eclipse.hawkbit.repository.model.MetaData;
+import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
+
+/**
+ * Builder to update an existing {@link SoftwareModuleMetadata} entry. Defines
+ * all fields that can be updated.
+ *
+ */
+public interface SoftwareModuleMetadataUpdate {
+ /**
+ * @param value
+ * for {@link MetaData#getValue()}
+ * @return updated builder instance
+ */
+ SoftwareModuleMetadataUpdate value(@Size(min = 1, max = MetaData.VALUE_MAX_SIZE) @NotNull String value);
+
+ /**
+ * @param visible
+ * for {@link SoftwareModuleMetadata#isTargetVisible()}
+ * @return updated builder instance
+ */
+ SoftwareModuleMetadataUpdate targetVisible(Boolean visible);
+
+}
diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DistributionSetMetadata.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DistributionSetMetadata.java
index 87a62e9ba..6e43d18cf 100644
--- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DistributionSetMetadata.java
+++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DistributionSetMetadata.java
@@ -19,4 +19,9 @@ public interface DistributionSetMetadata extends MetaData {
*/
DistributionSet getDistributionSet();
+ @Override
+ default Long getEntityId() {
+ return getDistributionSet().getId();
+ }
+
}
diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/MetaData.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/MetaData.java
index e3322782f..d8433609b 100644
--- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/MetaData.java
+++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/MetaData.java
@@ -15,6 +15,20 @@ import java.io.Serializable;
*
*/
public interface MetaData extends Serializable {
+ /**
+ * Maximum length of metadata key.
+ */
+ int KEY_MAX_SIZE = 128;
+
+ /**
+ * Maximum length of metadata value.
+ */
+ int VALUE_MAX_SIZE = 4000;
+
+ /**
+ * @return {@link BaseEntity#getId()} the metadata is related to
+ */
+ Long getEntityId();
/**
* @return the key
diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/SoftwareModuleMetadata.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/SoftwareModuleMetadata.java
index cfb5be5d1..23058447b 100644
--- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/SoftwareModuleMetadata.java
+++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/SoftwareModuleMetadata.java
@@ -18,4 +18,15 @@ public interface SoftwareModuleMetadata extends MetaData {
* @return {@link SoftwareModule} this entry belongs to.
*/
SoftwareModule getSoftwareModule();
+
+ @Override
+ default Long getEntityId() {
+ return getSoftwareModule().getId();
+ }
+
+ /**
+ * @return true if element is visible for targets as part of
+ * {@link Action}.
+ */
+ boolean isTargetVisible();
}
diff --git a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/AbstractMetadataUpdateCreate.java b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/AbstractMetadataUpdateCreate.java
new file mode 100644
index 000000000..5bddf2edf
--- /dev/null
+++ b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/AbstractMetadataUpdateCreate.java
@@ -0,0 +1,41 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit.repository.builder;
+
+import java.util.Optional;
+
+/**
+ * Create and update builder DTO.
+ *
+ * @param
+ * update or create builder interface
+ */
+public abstract class AbstractMetadataUpdateCreate {
+ protected String key;
+ protected String value;
+
+ public T key(final String key) {
+ this.key = key;
+ return (T) this;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public T value(final String value) {
+ this.value = value;
+ return (T) this;
+ }
+
+ public Optional getValue() {
+ return Optional.ofNullable(value);
+ }
+
+}
diff --git a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/AbstractSoftwareModuleMetadataUpdateCreate.java b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/AbstractSoftwareModuleMetadataUpdateCreate.java
new file mode 100644
index 000000000..5833bd812
--- /dev/null
+++ b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/AbstractSoftwareModuleMetadataUpdateCreate.java
@@ -0,0 +1,41 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit.repository.builder;
+
+import java.util.Optional;
+
+/**
+ * Create and update builder DTO.
+ *
+ * @param
+ * update or create builder interface
+ */
+public abstract class AbstractSoftwareModuleMetadataUpdateCreate extends AbstractMetadataUpdateCreate {
+ protected Boolean targetVisible;
+ protected long softwareModuleId;
+
+ public T softwareModuleId(final long softwareModuleId) {
+ this.softwareModuleId = softwareModuleId;
+ return (T) this;
+ }
+
+ public long getSoftwareModuleId() {
+ return softwareModuleId;
+ }
+
+ public Optional isTargetVisible() {
+ return Optional.ofNullable(targetVisible);
+ }
+
+ public T targetVisible(final Boolean targetVisible) {
+ this.targetVisible = targetVisible;
+ return (T) this;
+ }
+
+}
diff --git a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/GenericSoftwareModuleMetadataUpdate.java b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/GenericSoftwareModuleMetadataUpdate.java
new file mode 100644
index 000000000..d05bece24
--- /dev/null
+++ b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/GenericSoftwareModuleMetadataUpdate.java
@@ -0,0 +1,23 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit.repository.builder;
+
+/**
+ * Update implementation.
+ */
+public class GenericSoftwareModuleMetadataUpdate
+ extends AbstractSoftwareModuleMetadataUpdateCreate
+ implements SoftwareModuleMetadataUpdate {
+
+ public GenericSoftwareModuleMetadataUpdate(final long softwareModuleId, final String key) {
+ super.softwareModuleId = softwareModuleId;
+ this.key = key;
+ }
+
+}
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaControllerManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaControllerManagement.java
index 702824861..f2e499743 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaControllerManagement.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaControllerManagement.java
@@ -9,10 +9,12 @@
package org.eclipse.hawkbit.repository.jpa;
import java.net.URI;
+import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
+import java.util.stream.Collectors;
import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
@@ -45,6 +47,7 @@ import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.Status;
import org.eclipse.hawkbit.repository.model.ActionStatus;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
+import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
import org.eclipse.hawkbit.security.SystemSecurityContext;
@@ -115,6 +118,9 @@ public class JpaControllerManagement implements ControllerManagement {
@Autowired
private AfterTransactionCommitExecutor afterCommit;
+ @Autowired
+ private SoftwareModuleMetadataRepository softwareModuleMetadataRepository;
+
@Override
public String getPollingTime() {
return systemSecurityContext.runAsSystem(() -> tenantConfigurationManagement
@@ -523,4 +529,15 @@ public class JpaControllerManagement implements ControllerManagement {
public Optional getSoftwareModule(final Long id) {
return Optional.ofNullable(softwareModuleRepository.findOne(id));
}
+
+ @Override
+ public Map> findTargetVisibleMetaDataBySoftwareModuleId(
+ final Collection moduleId) {
+
+ return softwareModuleMetadataRepository
+ .findBySoftwareModuleIdInAndTargetVisible(new PageRequest(0, RepositoryConstants.MAX_META_DATA_COUNT),
+ moduleId, true)
+ .getContent().stream().collect(Collectors.groupingBy(o -> (Long) o[0],
+ Collectors.mapping(o -> (SoftwareModuleMetadata) o[1], Collectors.toList())));
+ }
}
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaEntityFactory.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaEntityFactory.java
index 43d67f576..59566da63 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaEntityFactory.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaEntityFactory.java
@@ -15,6 +15,7 @@ import org.eclipse.hawkbit.repository.builder.DistributionSetTypeBuilder;
import org.eclipse.hawkbit.repository.builder.RolloutBuilder;
import org.eclipse.hawkbit.repository.builder.RolloutGroupBuilder;
import org.eclipse.hawkbit.repository.builder.SoftwareModuleBuilder;
+import org.eclipse.hawkbit.repository.builder.SoftwareModuleMetadataBuilder;
import org.eclipse.hawkbit.repository.builder.SoftwareModuleTypeBuilder;
import org.eclipse.hawkbit.repository.builder.TagBuilder;
import org.eclipse.hawkbit.repository.builder.TargetBuilder;
@@ -24,7 +25,7 @@ import org.eclipse.hawkbit.repository.jpa.builder.JpaRolloutGroupBuilder;
import org.eclipse.hawkbit.repository.jpa.builder.JpaSoftwareModuleTypeBuilder;
import org.eclipse.hawkbit.repository.jpa.builder.JpaTagBuilder;
import org.eclipse.hawkbit.repository.jpa.builder.JpaTargetBuilder;
-import org.eclipse.hawkbit.repository.jpa.model.JpaMetaData;
+import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetMetadata;
import org.eclipse.hawkbit.repository.model.MetaData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
@@ -51,9 +52,12 @@ public class JpaEntityFactory implements EntityFactory {
@Autowired
private TargetFilterQueryBuilder targetFilterQueryBuilder;
+ @Autowired
+ private SoftwareModuleMetadataBuilder softwareModuleMetadataBuilder;
+
@Override
public MetaData generateMetadata(final String key, final String value) {
- return new JpaMetaData(key, value);
+ return new JpaDistributionSetMetadata(key, value);
}
@Override
@@ -106,4 +110,9 @@ public class JpaEntityFactory implements EntityFactory {
return new JpaRolloutGroupBuilder();
}
+ @Override
+ public SoftwareModuleMetadataBuilder softwareModuleMetadata() {
+ return softwareModuleMetadataBuilder;
+ }
+
}
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSoftwareModuleManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSoftwareModuleManagement.java
index c06c8f244..9490863cf 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSoftwareModuleManagement.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSoftwareModuleManagement.java
@@ -28,15 +28,20 @@ import javax.persistence.criteria.Root;
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
import org.eclipse.hawkbit.repository.ArtifactManagement;
+import org.eclipse.hawkbit.repository.RepositoryConstants;
import org.eclipse.hawkbit.repository.SoftwareModuleFields;
import org.eclipse.hawkbit.repository.SoftwareModuleManagement;
import org.eclipse.hawkbit.repository.SoftwareModuleMetadataFields;
+import org.eclipse.hawkbit.repository.builder.GenericSoftwareModuleMetadataUpdate;
import org.eclipse.hawkbit.repository.builder.GenericSoftwareModuleUpdate;
import org.eclipse.hawkbit.repository.builder.SoftwareModuleCreate;
+import org.eclipse.hawkbit.repository.builder.SoftwareModuleMetadataCreate;
+import org.eclipse.hawkbit.repository.builder.SoftwareModuleMetadataUpdate;
import org.eclipse.hawkbit.repository.builder.SoftwareModuleUpdate;
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.jpa.builder.JpaSoftwareModuleCreate;
+import org.eclipse.hawkbit.repository.jpa.builder.JpaSoftwareModuleMetadataCreate;
import org.eclipse.hawkbit.repository.jpa.configuration.Constants;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet_;
@@ -51,7 +56,6 @@ import org.eclipse.hawkbit.repository.jpa.specifications.SpecificationsBuilder;
import org.eclipse.hawkbit.repository.model.Artifact;
import org.eclipse.hawkbit.repository.model.AssignedSoftwareModule;
import org.eclipse.hawkbit.repository.model.DistributionSet;
-import org.eclipse.hawkbit.repository.model.MetaData;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
@@ -61,6 +65,7 @@ import org.springframework.dao.ConcurrencyFailureException;
import org.springframework.data.domain.AuditorAware;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
+import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.SliceImpl;
@@ -443,15 +448,17 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement {
@Transactional
@Retryable(include = {
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
- public SoftwareModuleMetadata createMetaData(final Long moduleId, final MetaData md) {
+ public SoftwareModuleMetadata createMetaData(final SoftwareModuleMetadataCreate c) {
+ final JpaSoftwareModuleMetadataCreate create = (JpaSoftwareModuleMetadataCreate) c;
- checkAndThrowAlreadyIfSoftwareModuleMetadataExists(moduleId, md);
+ checkAndThrowAlreadyIfSoftwareModuleMetadataExists(create.getSoftwareModuleId(), create);
+ touch(create.getSoftwareModuleId());
- return softwareModuleMetadataRepository
- .save(new JpaSoftwareModuleMetadata(md.getKey(), touch(moduleId), md.getValue()));
+ return softwareModuleMetadataRepository.save(create.build());
}
- private void checkAndThrowAlreadyIfSoftwareModuleMetadataExists(final Long moduleId, final MetaData md) {
+ private void checkAndThrowAlreadyIfSoftwareModuleMetadataExists(final Long moduleId,
+ final JpaSoftwareModuleMetadataCreate md) {
if (softwareModuleMetadataRepository.exists(new SwMetadataCompositeKey(moduleId, md.getKey()))) {
throwMetadataKeyAlreadyExists(md.getKey());
}
@@ -461,28 +468,26 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement {
@Transactional
@Retryable(include = {
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
- public List createMetaData(final Long moduleId, final Collection md) {
- md.forEach(meta -> checkAndThrowAlreadyIfSoftwareModuleMetadataExists(moduleId, meta));
+ public List createMetaData(final Collection create) {
- final JpaSoftwareModule module = touch(moduleId);
-
- return Collections.unmodifiableList(md.stream()
- .map(meta -> softwareModuleMetadataRepository
- .save(new JpaSoftwareModuleMetadata(meta.getKey(), module, meta.getValue())))
- .collect(Collectors.toList()));
+ return create.stream().map(this::createMetaData).collect(Collectors.toList());
}
@Override
@Transactional
@Retryable(include = {
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
- public SoftwareModuleMetadata updateMetaData(final Long moduleId, final MetaData md) {
+ public SoftwareModuleMetadata updateMetaData(final SoftwareModuleMetadataUpdate u) {
+ final GenericSoftwareModuleMetadataUpdate update = (GenericSoftwareModuleMetadataUpdate) u;
// check if exists otherwise throw entity not found exception
- final JpaSoftwareModuleMetadata metadata = (JpaSoftwareModuleMetadata) getMetaDataBySoftwareModuleId(moduleId,
- md.getKey()).orElseThrow(
- () -> new EntityNotFoundException(SoftwareModuleMetadata.class, moduleId, md.getKey()));
- metadata.setValue(md.getValue());
+ final JpaSoftwareModuleMetadata metadata = (JpaSoftwareModuleMetadata) getMetaDataBySoftwareModuleId(
+ update.getSoftwareModuleId(), update.getKey())
+ .orElseThrow(() -> new EntityNotFoundException(SoftwareModuleMetadata.class,
+ update.getSoftwareModuleId(), update.getKey()));
+
+ update.getValue().ifPresent(metadata::setValue);
+ update.isTargetVisible().ifPresent(metadata::setTargetVisible);
touch(metadata.getSoftwareModule());
return softwareModuleMetadataRepository.save(metadata);
@@ -593,4 +598,13 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement {
return softwareModuleRepository.exists(id);
}
+ @Override
+ public Page findMetaDataBySoftwareModuleIdAndTargetVisible(final Pageable pageable,
+ final Long moduleId) {
+ throwExceptionIfSoftwareModuleDoesNotExist(moduleId);
+
+ return convertMdPage(softwareModuleMetadataRepository.findBySoftwareModuleIdAndTargetVisible(
+ new PageRequest(0, RepositoryConstants.MAX_META_DATA_COUNT), moduleId, true), pageable);
+ }
+
}
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSystemManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSystemManagement.java
index c91d24421..cf4671092 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSystemManagement.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSystemManagement.java
@@ -34,6 +34,8 @@ import org.eclipse.hawkbit.repository.report.model.SystemUsageReportWithTenants;
import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.tenancy.TenantAware;
import org.eclipse.persistence.config.PersistenceUnitProperties;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.interceptor.KeyGenerator;
@@ -59,6 +61,8 @@ import org.springframework.validation.annotation.Validated;
@Transactional(readOnly = true)
@Validated
public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, SystemManagement {
+ private static final Logger LOGGER = LoggerFactory.getLogger(JpaSystemManagement.class);
+
private static final int MAX_TENANTS_QUERY = 500;
@Autowired
@@ -328,7 +332,12 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst
do {
tenants = findTenants(query);
tenants.forEach(tenant -> tenantAware.runAsTenant(tenant, () -> {
- consumer.accept(tenant);
+ try {
+ consumer.accept(tenant);
+ } catch (final RuntimeException ex) {
+ LOGGER.error("Exception on forEachTenant execution for tenant {}. Continue with next tenant.",
+ tenant, ex);
+ }
return null;
}));
} while (tenants.hasNext() && (query = tenants.nextPageable()) != null);
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RepositoryApplicationConfiguration.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RepositoryApplicationConfiguration.java
index b70a6acbb..5f9f5c0a6 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RepositoryApplicationConfiguration.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RepositoryApplicationConfiguration.java
@@ -39,6 +39,7 @@ import org.eclipse.hawkbit.repository.builder.DistributionSetBuilder;
import org.eclipse.hawkbit.repository.builder.DistributionSetTypeBuilder;
import org.eclipse.hawkbit.repository.builder.RolloutBuilder;
import org.eclipse.hawkbit.repository.builder.SoftwareModuleBuilder;
+import org.eclipse.hawkbit.repository.builder.SoftwareModuleMetadataBuilder;
import org.eclipse.hawkbit.repository.builder.TargetFilterQueryBuilder;
import org.eclipse.hawkbit.repository.event.ApplicationEventFilter;
import org.eclipse.hawkbit.repository.event.remote.EventEntityManager;
@@ -51,6 +52,7 @@ import org.eclipse.hawkbit.repository.jpa.builder.JpaDistributionSetBuilder;
import org.eclipse.hawkbit.repository.jpa.builder.JpaDistributionSetTypeBuilder;
import org.eclipse.hawkbit.repository.jpa.builder.JpaRolloutBuilder;
import org.eclipse.hawkbit.repository.jpa.builder.JpaSoftwareModuleBuilder;
+import org.eclipse.hawkbit.repository.jpa.builder.JpaSoftwareModuleMetadataBuilder;
import org.eclipse.hawkbit.repository.jpa.builder.JpaTargetFilterQueryBuilder;
import org.eclipse.hawkbit.repository.jpa.configuration.MultiTenantJpaTransactionManager;
import org.eclipse.hawkbit.repository.jpa.event.JpaEventEntityManager;
@@ -167,6 +169,12 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
return new JpaDistributionSetBuilder(distributionSetTypeManagement, softwareManagement);
}
+ @Bean
+ SoftwareModuleMetadataBuilder softwareModuleMetadataBuilder(
+ final SoftwareModuleManagement softwareModuleManagement) {
+ return new JpaSoftwareModuleMetadataBuilder(softwareModuleManagement);
+ }
+
/**
* @param softwareManagement
* for loading
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RolloutGroupRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RolloutGroupRepository.java
index 839a21a53..fd8b4cd08 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RolloutGroupRepository.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RolloutGroupRepository.java
@@ -38,7 +38,7 @@ public interface RolloutGroupRepository
* the rollout the rolloutgroups belong to
* @return the rollout groups belonging to a rollout ordered by ID ASC.
*/
- List findByRolloutOrderByIdAsc(final JpaRollout rollout);
+ List findByRolloutOrderByIdAsc(JpaRollout rollout);
/**
* Retrieves all {@link RolloutGroup} referring a specific rollout in a
@@ -50,7 +50,7 @@ public interface RolloutGroupRepository
* the status of the rollout groups
* @return the rollout groups belonging to a rollout in a specific status
*/
- List findByRolloutAndStatus(final Rollout rollout, final RolloutGroupStatus status);
+ List findByRolloutAndStatus(Rollout rollout, RolloutGroupStatus status);
/**
* Counts all {@link RolloutGroup} referring a specific rollout in specific
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/SoftwareModuleMetadataRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/SoftwareModuleMetadataRepository.java
index d874025a0..2616d8e03 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/SoftwareModuleMetadataRepository.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/SoftwareModuleMetadataRepository.java
@@ -8,11 +8,17 @@
*/
package org.eclipse.hawkbit.repository.jpa;
+import java.util.Collection;
+
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleMetadata;
import org.eclipse.hawkbit.repository.jpa.model.SwMetadataCompositeKey;
import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.PagingAndSortingRepository;
+import org.springframework.data.repository.query.Param;
import org.springframework.transaction.annotation.Transactional;
/**
@@ -24,4 +30,11 @@ public interface SoftwareModuleMetadataRepository
extends PagingAndSortingRepository,
JpaSpecificationExecutor {
+ Page findBySoftwareModuleIdAndTargetVisible(Pageable page, Long moduleId,
+ boolean targetVisible);
+
+ @Query("SELECT smd.softwareModule.id, smd FROM JpaSoftwareModuleMetadata smd WHERE smd.softwareModule.id IN :moduleId AND smd.targetVisible = :targetVisible")
+ Page