[#1580] Software Module & Distribution Set lock: add lock at rest level (#1646)

Signed-off-by: Marinov Avgustin <Avgustin.Marinov@bosch.com>
This commit is contained in:
Avgustin Marinov
2024-02-15 11:46:06 +02:00
committed by GitHub
parent e535420065
commit 850fa3507f
17 changed files with 123 additions and 35 deletions

View File

@@ -10,12 +10,15 @@
package org.eclipse.hawkbit.repository.builder;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Null;
import jakarta.validation.constraints.Size;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.NamedEntity;
import org.eclipse.hawkbit.repository.model.NamedVersionedEntity;
import java.util.Optional;
/**
* Builder to update an existing {@link DistributionSet} entry. Defines all
* fields that can be updated.
@@ -23,30 +26,32 @@ import org.eclipse.hawkbit.repository.model.NamedVersionedEntity;
*/
public interface DistributionSetUpdate {
/**
* @param name
* for {@link DistributionSet#getName()}
* @param name for {@link DistributionSet#getName()}
* @return updated builder instance
*/
DistributionSetUpdate name(@Size(min = 1, max = NamedEntity.NAME_MAX_SIZE) @NotNull String name);
/**
* @param version
* for {@link DistributionSet#getVersion()}
* @param version for {@link DistributionSet#getVersion()}
* @return updated builder instance
*/
DistributionSetUpdate version(@Size(min = 1, max = NamedVersionedEntity.VERSION_MAX_SIZE) @NotNull String version);
/**
* @param description
* for {@link DistributionSet#getDescription()}
* @param description for {@link DistributionSet#getDescription()}
* @return updated builder instance
*/
DistributionSetUpdate description(@Size(max = NamedEntity.DESCRIPTION_MAX_SIZE) String description);
/**
* @param requiredMigrationStep
* for {@link DistributionSet#isRequiredMigrationStep()}
* @param locked update request if any. If not empty shall be <code>true</code>
* @return updated builder instance
*/
DistributionSetUpdate locked(@Null Boolean locked);
/**
* @param requiredMigrationStep for {@link DistributionSet#isRequiredMigrationStep()}
* @return updated builder instance
*/
DistributionSetUpdate requiredMigrationStep(Boolean requiredMigrationStep);
}
}

View File

@@ -28,4 +28,4 @@ public interface SoftwareModuleBuilder {
* @return builder instance
*/
SoftwareModuleCreate create();
}
}

View File

@@ -9,6 +9,8 @@
*/
package org.eclipse.hawkbit.repository.builder;
import jakarta.annotation.Nullable;
import jakarta.validation.constraints.Null;
import jakarta.validation.constraints.Size;
import org.eclipse.hawkbit.repository.model.NamedEntity;
@@ -34,4 +36,10 @@ public interface SoftwareModuleUpdate {
* @return updated builder instance
*/
SoftwareModuleUpdate vendor(@Size(max = SoftwareModule.VENDOR_MAX_SIZE) String vendor);
}
/**
* @param locked update request if any. If not empty shall be <code>true</code>
* @return updated builder instance
*/
SoftwareModuleUpdate locked(@Null Boolean locked);
}

View File

@@ -18,15 +18,13 @@ import org.springframework.util.StringUtils;
/**
* Create and update builder DTO.
*
* @param <T>
* update or create builder interface
* @param <T> update or create builder interface
*/
public abstract class AbstractDistributionSetUpdateCreate<T> extends AbstractNamedEntityBuilder<T> {
@ValidString
protected String version;
protected Boolean requiredMigrationStep;
protected Collection<Long> modules;
public T modules(final Collection<Long> modules) {
@@ -55,5 +53,4 @@ public abstract class AbstractDistributionSetUpdateCreate<T> extends AbstractNam
public Optional<String> getVersion() {
return Optional.ofNullable(version);
}
}
}

View File

@@ -11,6 +11,8 @@ package org.eclipse.hawkbit.repository.builder;
import java.util.Optional;
import jakarta.annotation.Nullable;
import jakarta.validation.constraints.Null;
import org.eclipse.hawkbit.repository.ValidString;
import org.springframework.util.StringUtils;
@@ -39,5 +41,4 @@ public abstract class AbstractNamedEntityBuilder<T> extends AbstractBaseEntityBu
public Optional<String> getDescription() {
return Optional.ofNullable(description);
}
}
}

View File

@@ -9,14 +9,33 @@
*/
package org.eclipse.hawkbit.repository.builder;
import jakarta.annotation.Nullable;
import java.util.Optional;
/**
* Update implementation.
*/
public class GenericDistributionSetUpdate extends AbstractDistributionSetUpdateCreate<DistributionSetUpdate>
implements DistributionSetUpdate {
@Nullable
protected Boolean locked;
public GenericDistributionSetUpdate(final Long id) {
super.id = id;
}
}
public DistributionSetUpdate locked(@Nullable final Boolean locked) {
if (Boolean.FALSE.equals(locked)) {
this.locked = null;
} else {
this.locked = locked;
}
return this;
}
public Boolean getLocked() {
return locked;
}
}

View File

@@ -9,14 +9,33 @@
*/
package org.eclipse.hawkbit.repository.builder;
import jakarta.annotation.Nullable;
import java.util.Optional;
/**
* Update implementation.
*/
public class GenericSoftwareModuleUpdate extends AbstractSoftwareModuleUpdateCreate<SoftwareModuleUpdate>
implements SoftwareModuleUpdate {
@Nullable
protected Boolean locked;
public GenericSoftwareModuleUpdate(final Long id) {
super.id = id;
}
}
public SoftwareModuleUpdate locked(@Nullable final Boolean locked) {
if (Boolean.FALSE.equals(locked)) {
this.locked = null;
} else {
this.locked = locked;
}
return this;
}
public Boolean getLocked() {
return locked;
}
}

View File

@@ -285,6 +285,10 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
update.getDescription().ifPresent(set::setDescription);
update.getVersion().ifPresent(set::setVersion);
if (Boolean.TRUE.equals(update.getLocked()) && !set.isLocked()) {
set.lock();
}
if (update.isRequiredMigrationStep() != null
&& !update.isRequiredMigrationStep().equals(set.isRequiredMigrationStep())) {
assertDistributionSetIsNotAssignedToTargets(update.getId());

View File

@@ -142,6 +142,9 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement {
update.getDescription().ifPresent(module::setDescription);
update.getVendor().ifPresent(module::setVendor);
if (Boolean.TRUE.equals(update.getLocked()) && !module.isLocked()) {
module.lock();
}
return softwareModuleRepository.save(module);
}

View File

@@ -58,6 +58,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
"type" : "os",
"typeName" : "OS",
"vendor" : "vendor Limited Inc, California",
"locked" : true,
"deleted" : false,
"encrypted" : false,
"_links" : {
@@ -77,6 +78,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
"type" : "runtime",
"typeName" : "runtime",
"vendor" : "vendor GmbH, Stuttgart, Germany",
"locked" : true,
"deleted" : false,
"encrypted" : false,
"_links" : {
@@ -96,6 +98,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
"type" : "application",
"typeName" : "Application",
"vendor" : "vendor Limited, California",
"locked" : true,
"deleted" : false,
"encrypted" : false,
"_links" : {
@@ -137,12 +140,6 @@ public class MgmtDistributionSet extends MgmtNamedEntity {
@Schema(description = "Package version", example = "1.4.2")
private String version;
@JsonProperty
@Schema(description = """
True if DS is a required migration step for another DS. As a result the DSs assignment will not be cancelled
when another DS is assigned (note: updatable only if DS is not yet assigned to a target)""", example = "false")
private boolean requiredMigrationStep;
@JsonProperty
@Schema(description = "The type of the distribution set", example = "test_default_ds_type")
private String type;
@@ -158,6 +155,10 @@ public class MgmtDistributionSet extends MgmtNamedEntity {
distribution set type""", example = "true")
private Boolean complete;
@JsonProperty
@Schema(description = "If the distribution set is locked", example = "true")
private boolean locked;
@JsonProperty
@Schema(description = "Deleted flag, used for soft deleted entities", example = "false")
private boolean deleted;
@@ -167,6 +168,12 @@ public class MgmtDistributionSet extends MgmtNamedEntity {
example = "true")
private boolean valid;
@JsonProperty
@Schema(description = """
True if DS is a required migration step for another DS. As a result the DSs assignment will not be cancelled
when another DS is assigned (note: updatable only if DS is not yet assigned to a target)""", example = "false")
private boolean requiredMigrationStep;
@JsonProperty
private List<MgmtSoftwareModule> modules = new ArrayList<>();
}

View File

@@ -29,12 +29,21 @@ public class MgmtDistributionSetRequestBodyPut {
@JsonProperty
@Schema(description = "The name of the entity", example = "dsOne")
private String name;
@JsonProperty
@Schema(description = "The description of the entity", example = "Description of the distribution set.")
private String description;
@JsonProperty
@Schema(description = "Package version", example = "1.0.0")
private String version;
@JsonProperty
@Schema(description = "Put it to true only if want to lock the distribution set. Otherwise skip it. " +
"Shall not be false!",
example = "true")
private Boolean locked;
@JsonProperty
@Schema(description = """
True if DS is a required migration step for another DS. As a result the DSs assignment will not be cancelled

View File

@@ -45,8 +45,9 @@ import com.fasterxml.jackson.annotation.JsonProperty;
"type" : "os",
"typeName" : "OS",
"vendor" : "Vendor Limited, California",
"deleted" : false,
"encrypted" : false,
"locked" : true,
"deleted" : false,
"_links" : {
"self" : {
"href" : "https://management-api.host.com/rest/v1/softwaremodules/6"
@@ -84,11 +85,15 @@ public class MgmtSoftwareModule extends MgmtNamedEntity {
@Schema(description = "The software vendor", example = "Vendor Limited, California")
private String vendor;
@JsonProperty
@Schema(description = "If the software module is deleted", example = "false")
private boolean deleted;
@JsonProperty
@Schema(description = "If the software module is encrypted", example = "false")
private boolean encrypted;
@JsonProperty
@Schema(description = "If the software module is locked", example = "true")
private boolean locked;
@JsonProperty
@Schema(description = "If the software module is deleted", example = "false")
private boolean deleted;
}

View File

@@ -24,7 +24,14 @@ public class MgmtSoftwareModuleRequestBodyPut {
@JsonProperty
@Schema(example = "SM Description")
private String description;
@JsonProperty
@Schema(example = "SM Vendor Name")
private String vendor;
@JsonProperty
@Schema(description = "Put it to true only if want to lock the software module. Otherwise skip it. " +
"Shall not be false!",
example = "true")
private Boolean locked;
}

View File

@@ -111,6 +111,7 @@ public final class MgmtDistributionSetMapper {
response.setComplete(distributionSet.isComplete());
response.setType(distributionSet.getType().getKey());
response.setTypeName(distributionSet.getType().getName());
response.setLocked(distributionSet.isLocked());
response.setDeleted(distributionSet.isDeleted());
response.setValid(distributionSet.isValid());

View File

@@ -198,10 +198,10 @@ public class MgmtDistributionSetResource implements MgmtDistributionSetRestApi {
public ResponseEntity<MgmtDistributionSet> updateDistributionSet(
@PathVariable("distributionSetId") final Long distributionSetId,
@RequestBody final MgmtDistributionSetRequestBodyPut toUpdate) {
final DistributionSet updated = distributionSetManagement.update(entityFactory.distributionSet()
.update(distributionSetId).name(toUpdate.getName()).description(toUpdate.getDescription())
.version(toUpdate.getVersion()).requiredMigrationStep(toUpdate.getRequiredMigrationStep()));
.version(toUpdate.getVersion()).locked(toUpdate.getLocked())
.requiredMigrationStep(toUpdate.getRequiredMigrationStep()));
final MgmtDistributionSet response = MgmtDistributionSetMapper.toResponse(updated);
MgmtDistributionSetMapper.addLinks(updated, response);

View File

@@ -115,6 +115,7 @@ public final class MgmtSoftwareModuleMapper {
response.setType(softwareModule.getType().getKey());
response.setTypeName(softwareModule.getType().getName());
response.setVendor(softwareModule.getVendor());
response.setLocked(softwareModule.isLocked());
response.setDeleted(softwareModule.isDeleted());
response.setEncrypted(softwareModule.isEncrypted());

View File

@@ -248,7 +248,9 @@ public class MgmtSoftwareModuleResource implements MgmtSoftwareModuleRestApi {
@RequestBody final MgmtSoftwareModuleRequestBodyPut restSoftwareModule) {
final SoftwareModule module = softwareModuleManagement
.update(entityFactory.softwareModule().update(softwareModuleId)
.description(restSoftwareModule.getDescription()).vendor(restSoftwareModule.getVendor()));
.description(restSoftwareModule.getDescription())
.vendor(restSoftwareModule.getVendor())
.locked(restSoftwareModule.getLocked()));
final MgmtSoftwareModule response = MgmtSoftwareModuleMapper.toResponse(module);
MgmtSoftwareModuleMapper.addLinks(module, response);