Soft Module metadata as complex map value (#2568)

---------

Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
Avgustin Marinov
2025-07-30 17:29:02 +03:00
committed by GitHub
parent 4a8e60764f
commit 08cacf9034
38 changed files with 392 additions and 962 deletions

View File

@@ -32,7 +32,6 @@ import org.eclipse.hawkbit.repository.model.Action.Status;
import org.eclipse.hawkbit.repository.model.ActionStatus;
import org.eclipse.hawkbit.repository.model.AutoConfirmationStatus;
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.ControllerPollProperties;
@@ -69,14 +68,13 @@ public interface ControllerManagement {
Optional<SoftwareModule> getSoftwareModule(long moduleId);
/**
* Retrieves {@link SoftwareModuleMetadata} where {@link SoftwareModuleMetadata#isTargetVisible()}.
* Retrieves software module metadata where isTargetVisible.
*
* @param moduleId of the {@link SoftwareModule}
* @return the map of software module id to {@link SoftwareModuleMetadata} with maximum size of
* {@link RepositoryConstants#MAX_META_DATA_COUNT}
* @return the map of software module id to software module metadata with maximum size of {@link RepositoryConstants#MAX_META_DATA_COUNT}
*/
@PreAuthorize(SpringEvalExpressions.IS_CONTROLLER)
Map<Long, List<SoftwareModuleMetadata>> findTargetVisibleMetaDataBySoftwareModuleId(@NotNull Collection<Long> moduleId);
Map<Long, Map<String, String>> findTargetVisibleMetaDataBySoftwareModuleId(@NotNull Collection<Long> moduleId);
/**
* Simple addition of a new {@link ActionStatus} entry to the {@link Action}. No state changes.

View File

@@ -12,7 +12,6 @@ package org.eclipse.hawkbit.repository;
import org.eclipse.hawkbit.repository.builder.ActionStatusBuilder;
import org.eclipse.hawkbit.repository.builder.RolloutBuilder;
import org.eclipse.hawkbit.repository.builder.RolloutGroupBuilder;
import org.eclipse.hawkbit.repository.builder.SoftwareModuleMetadataBuilder;
import org.eclipse.hawkbit.repository.builder.TagBuilder;
import org.eclipse.hawkbit.repository.builder.TargetBuilder;
import org.eclipse.hawkbit.repository.builder.TargetFilterQueryBuilder;
@@ -31,11 +30,6 @@ public interface EntityFactory {
*/
ActionStatusBuilder actionStatus();
/**
* @return {@link SoftwareModuleMetadataBuilder} object
*/
SoftwareModuleMetadataBuilder softwareModuleMetadata();
/**
* @return {@link TagBuilder} object
*/

View File

@@ -9,14 +9,17 @@
*/
package org.eclipse.hawkbit.repository;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
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;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
/**
* Repository constants.
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class RepositoryConstants {
/**
@@ -46,12 +49,7 @@ public final class RepositoryConstants {
/**
* Maximum number of metadata entries provided to controllers.
*
* @see SoftwareModuleMetadata#isTargetVisible()
* @see SoftwareModule.MetadataValueCreate#isTargetVisible()
*/
public static final int MAX_META_DATA_COUNT = 50;
private RepositoryConstants() {
// Utility class.
}
}
}

View File

@@ -10,7 +10,6 @@
package org.eclipse.hawkbit.repository;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@@ -25,8 +24,6 @@ import lombok.Getter;
import lombok.ToString;
import lombok.experimental.SuperBuilder;
import org.eclipse.hawkbit.im.authentication.SpringEvalExpressions;
import org.eclipse.hawkbit.repository.builder.SoftwareModuleMetadataCreate;
import org.eclipse.hawkbit.repository.builder.SoftwareModuleMetadataUpdate;
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
@@ -34,9 +31,8 @@ import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.NamedEntity;
import org.eclipse.hawkbit.repository.model.NamedVersionedEntity;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
import org.eclipse.hawkbit.repository.model.SoftwareModule.MetadataValue;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.repository.model.Type;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
@@ -53,27 +49,27 @@ public interface SoftwareModuleManagement<T extends SoftwareModule>
return "SOFTWARE_MODULE";
}
/**
* Creates or updates a distribution set meta-data value.
*
* @param id the software module id which meta-data has to be updated
* @param key the key of the meta-data entry to be updated
* @param value the meta-data value to be updated
* @throws EntityNotFoundException in case the meta-data entry does not exist and cannot be updated
*/
@PreAuthorize(SpringEvalExpressions.HAS_UPDATE_REPOSITORY)
void createMetadata(@NotNull Long id, @NotEmpty String key, @NotNull @Valid MetadataValue value);
/**
* Creates a list of software module meta-data entries.
*
* @param metadata the meta-data entries to create
* @throws EntityAlreadyExistsException in case one of the meta-data entry already exists for the specific key
* @throws EntityNotFoundException if software module with given ID does not exist
* @throws AssignmentQuotaExceededException if the maximum number of {@link SoftwareModuleMetadata} entries is exceeded for the addressed
* {@link SoftwareModule}
* @throws AssignmentQuotaExceededException if the maximum number of meta-data entries is exceeded for the addressed {@link SoftwareModule}
*/
@PreAuthorize(SpringEvalExpressions.HAS_UPDATE_REPOSITORY)
void createMetadata(@NotNull @Valid Collection<SoftwareModuleMetadataCreate> metadata);
/**
* Finds all meta-data by the given software module id.
*
* @param id 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_READ_REPOSITORY)
List<SoftwareModuleMetadata> getMetadata(long id);
void createMetadata(@NotNull Long id, @NotEmpty @Valid Map<String, ? extends MetadataValue> metadata);
/**
* Finds all meta-data by the given software module id and key.
@@ -84,52 +80,30 @@ public interface SoftwareModuleManagement<T extends SoftwareModule>
* @throws EntityNotFoundException if software module with given ID does not exist ot the
*/
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
SoftwareModuleMetadata getMetadata(long id, String key);
MetadataValue getMetadata(@NotNull Long id, @NotEmpty String key);
/**
* Finds all meta-data by the given software module id where {@link SoftwareModuleMetadata#isTargetVisible()}.
* Finds all meta-data by the given software module id.
*
* @param id the software module id to retrieve the meta-data from
* @param pageable the page request to page the result
* @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_READ_REPOSITORY)
Page<SoftwareModuleMetadata> findMetaDataBySoftwareModuleIdAndTargetVisible(long id, @NotNull Pageable pageable);
/**
* Creates or updates a single software module meta-data entry.
*
* @param metadata 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 key
* @throws EntityNotFoundException if software module with given ID does not exist
* @throws AssignmentQuotaExceededException if the maximum number of {@link SoftwareModuleMetadata}
* entries is exceeded for the addressed {@link SoftwareModule}
*/
@PreAuthorize(SpringEvalExpressions.HAS_UPDATE_REPOSITORY)
SoftwareModuleMetadata updateMetadata(@NotNull @Valid SoftwareModuleMetadataCreate metadata);
/**
* Updates a distribution set meta-data value if corresponding entry exists.
*
* @param update the meta-data entry to be updated
* @return the updated meta-data entry
* @throws EntityNotFoundException in case the meta-data entry does not exist and cannot be updated
*/
@PreAuthorize(SpringEvalExpressions.HAS_UPDATE_REPOSITORY)
SoftwareModuleMetadata updateMetadata(@NotNull @Valid SoftwareModuleMetadataUpdate update);
Map<String, MetadataValue> getMetadata(@NotNull Long id);
/**
* Deletes a software module meta-data entry.
*
* @param id where meta-data has to be deleted
* @param key of the meta-data element
* @return true if really deleted, false if not
* @throws EntityNotFoundException if software module with given ID does not exist or the key is not found
*/
@PreAuthorize(SpringEvalExpressions.HAS_UPDATE_REPOSITORY)
void deleteMetadata(long id, @NotEmpty String key);
void deleteMetadata(@NotNull Long id, @NotEmpty String key);
@PreAuthorize(SpringEvalExpressions.IS_SYSTEM_CODE)
Map<Long, Map<String, String>> findMetaDataBySoftwareModuleIdsAndTargetVisible(Collection<Long> ids);
/**
* Locks a software module.
@@ -198,9 +172,6 @@ public interface SoftwareModuleManagement<T extends SoftwareModule>
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
Slice<T> findByType(long typeId, @NotNull Pageable pageable);
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
Map<Long, List<SoftwareModuleMetadata>> findMetaDataBySoftwareModuleIdsAndTargetVisible(Collection<Long> moduleIds);
/**
* Returns count of all modules assigned to given {@link DistributionSet}.
*

View File

@@ -1,32 +0,0 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.hawkbit.repository.builder;
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 SoftwareModuleMetadata} belongs to
* @param key of {@link SoftwareModuleMetadata#getKey()}
* @return builder instance
*/
SoftwareModuleMetadataUpdate update(long softwareModuleId, String key);
/**
* @param softwareModuleId of the {@link SoftwareModule} the {@link SoftwareModuleMetadata} belongs to
* @return builder instance
*/
SoftwareModuleMetadataCreate create(long softwareModuleId);
}

View File

@@ -1,49 +0,0 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.hawkbit.repository.builder;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import org.eclipse.hawkbit.repository.model.BaseEntity;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
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 SoftwareModuleMetadata#getKey()}
* @return updated builder instance
*/
SoftwareModuleMetadataCreate key(@Size(min = 1, max =SoftwareModule.METADATA_KEY_MAX_SIZE) @NotNull String key);
/**
* @param value for {@link SoftwareModuleMetadata#getValue()}
* @return updated builder instance
*/
SoftwareModuleMetadataCreate value(@Size(max = SoftwareModule.METADATA_VALUE_MAX_SIZE) 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();
}

View File

@@ -1,35 +0,0 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.hawkbit.repository.builder;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
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 SoftwareModuleMetadata#getValue()}
* @return updated builder instance
*/
SoftwareModuleMetadataUpdate value(@Size(min = 1, max = SoftwareModule.METADATA_VALUE_MAX_SIZE) @NotNull String value);
/**
* @param visible for {@link SoftwareModuleMetadata#isTargetVisible()}
* @return updated builder instance
*/
SoftwareModuleMetadataUpdate targetVisible(Boolean visible);
}

View File

@@ -12,6 +12,11 @@ package org.eclipse.hawkbit.repository.model;
import java.util.List;
import java.util.Optional;
import jakarta.validation.constraints.Size;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* Software package as sub element of a {@link DistributionSet}.
*/
@@ -81,4 +86,28 @@ public interface SoftwareModule extends NamedVersionedEntity {
return getArtifacts().stream().filter(artifact -> artifact.getFilename().equalsIgnoreCase(fileName.trim()))
.findAny();
}
interface MetadataValue {
String getValue();
boolean isTargetVisible();
}
@NoArgsConstructor
@Data
class MetadataValueCreate implements MetadataValue {
@Size(max = METADATA_VALUE_MAX_SIZE)
private String value;
private boolean targetVisible;
public MetadataValueCreate(final String value) {
this(value, false);
}
public MetadataValueCreate(final String value, final boolean targetVisible) {
this.value = value;
this.targetVisible = targetVisible;
}
}
}

View File

@@ -1,34 +0,0 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.hawkbit.repository.model;
import java.io.Serializable;
/**
* Metadata element of a {@link SoftwareModule}. The software module metadata is not only (key, value) pair (like the metadata of
* targets and distribution sets), but also contains the information if the metadata is visible for targets as part of {@link Action}.
*/
public interface SoftwareModuleMetadata extends Serializable {
/**
* @return the key
*/
String getKey();
/**
* @return the value
*/
String getValue();
/**
* @return <code>true</code> if element is visible for targets as part of {@link Action}.
*/
boolean isTargetVisible();
}