Skip to content

Commit

Permalink
[eclipse#1651] Add SoftwareModule and DistributionSet unlock (REST)
Browse files Browse the repository at this point in the history
Signed-off-by: Marinov Avgustin <[email protected]>
  • Loading branch information
avgustinmm committed Mar 8, 2024
1 parent 4d10487 commit f942d77
Show file tree
Hide file tree
Showing 10 changed files with 57 additions and 65 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,20 @@
package org.eclipse.hawkbit.repository.builder;

import jakarta.annotation.Nullable;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import lombok.experimental.Accessors;

import java.util.Optional;

/**
* Update implementation.
*/
@Data
@EqualsAndHashCode(callSuper = true)
@ToString
@Accessors(fluent = true)
public class GenericDistributionSetUpdate extends AbstractDistributionSetUpdateCreate<DistributionSetUpdate>
implements DistributionSetUpdate {

Expand All @@ -25,17 +33,4 @@ public class GenericDistributionSetUpdate extends AbstractDistributionSetUpdateC
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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,20 @@
package org.eclipse.hawkbit.repository.builder;

import jakarta.annotation.Nullable;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import lombok.experimental.Accessors;

import java.util.Optional;

/**
* Update implementation.
*/
@Data
@EqualsAndHashCode(callSuper = true)
@ToString
@Accessors(fluent = true)
public class GenericSoftwareModuleUpdate extends AbstractSoftwareModuleUpdateCreate<SoftwareModuleUpdate>
implements SoftwareModuleUpdate {

Expand All @@ -25,17 +33,4 @@ public class GenericSoftwareModuleUpdate extends AbstractSoftwareModuleUpdateCre
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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -286,8 +286,11 @@ public DistributionSet update(final DistributionSetUpdate u) {
update.getDescription().ifPresent(set::setDescription);
update.getVersion().ifPresent(set::setVersion);

if (Boolean.TRUE.equals(update.getLocked()) && !set.isLocked()) {
// lock/unlock ONLY if locked flag is present!
if (Boolean.TRUE.equals(update.locked())) {
set.lock();
} else if (Boolean.FALSE.equals(update.locked())) {
set.unlock();
}

if (update.isRequiredMigrationStep() != null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,12 @@ public SoftwareModule update(final SoftwareModuleUpdate u) {

update.getDescription().ifPresent(module::setDescription);
update.getVendor().ifPresent(module::setVendor);
if (Boolean.TRUE.equals(update.getLocked()) && !module.isLocked()) {

// lock/unlock ONLY if locked flag is present!
if (Boolean.TRUE.equals(update.locked())) {
module.lock();
} else if (Boolean.FALSE.equals(update.locked())) {
module.unlock();
}

return softwareModuleRepository.save(module);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,11 @@ public class MgmtDistributionSetRequestBodyPut {
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!",
@Schema(description = """
Should be set only if change of locked state is requested. If put, the distribution set locked flag will be
set to the requested. Note: unlock (i.e. set this property to false) with extreme care!
In general once distribution set is locked it shall not be unlocked. Note that it could have been assigned /
deployed to targets.""",
example = "true")
private Boolean locked;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,11 @@ public class MgmtSoftwareModuleRequestBodyPut {
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!",
@Schema(description = """
Should be set only if change of locked state is requested. If put, the software module locked flag will be
set to the requested. Note: unlock (i.e. set this property to false) with extreme care!
In general once software module is locked it shall not be unlocked. Note that it could have been assigned /
deployed to targets.""",
example = "true")
private Boolean locked;
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,44 +46,35 @@ public final class MgmtDistributionSetMapper {
/**
* {@link MgmtDistributionSetRequestBodyPost}s to {@link DistributionSet}s.
*
* @param sets
* to convert
* @param sets to convert
* @return converted list of {@link DistributionSet}s
*/
static List<DistributionSetCreate> dsFromRequest(final Collection<MgmtDistributionSetRequestBodyPost> sets,
final EntityFactory entityFactory) {

return sets.stream().map(dsRest -> fromRequest(dsRest, entityFactory)).collect(Collectors.toList());
}

/**
* {@link MgmtDistributionSetRequestBodyPost} to {@link DistributionSet}.
*
* @param dsRest
* to convert
* @param dsRest to convert
* @return converted {@link DistributionSet}
*/
private static DistributionSetCreate fromRequest(final MgmtDistributionSetRequestBodyPost dsRest,
final EntityFactory entityFactory) {

final List<Long> modules = new ArrayList<>();

if (dsRest.getOs() != null) {
modules.add(dsRest.getOs().getId());
}

if (dsRest.getApplication() != null) {
modules.add(dsRest.getApplication().getId());
}

if (dsRest.getRuntime() != null) {
modules.add(dsRest.getRuntime().getId());
}

if (dsRest.getModules() != null) {
dsRest.getModules().forEach(module -> modules.add(module.getId()));
}

return entityFactory.distributionSet().create().name(dsRest.getName()).version(dsRest.getVersion())
.description(dsRest.getDescription()).type(dsRest.getType()).modules(modules)
.requiredMigrationStep(dsRest.getRequiredMigrationStep());
Expand All @@ -103,6 +94,7 @@ static MgmtDistributionSet toResponse(final DistributionSet distributionSet) {
if (distributionSet == null) {
return null;
}

final MgmtDistributionSet response = new MgmtDistributionSet();
MgmtRestModelMapper.mapNamedToNamed(response, distributionSet);

Expand Down Expand Up @@ -180,7 +172,6 @@ static MgmtMetadata toResponseDsMetadata(final DistributionSetMetadata metadata)
}

static List<MgmtMetadata> toResponseDsMetadata(final List<DistributionSetMetadata> metadata) {

final List<MgmtMetadata> mappedList = new ArrayList<>(metadata.size());
for (final DistributionSetMetadata distributionSetMetadata : metadata) {
mappedList.add(toResponseDsMetadata(distributionSetMetadata));
Expand All @@ -195,4 +186,4 @@ static List<MgmtDistributionSet> toResponseFromDsList(final List<DistributionSet

return sets.stream().map(MgmtDistributionSetMapper::toResponse).collect(Collectors.toList());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
import java.util.List;
import java.util.stream.Collectors;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.eclipse.hawkbit.api.ApiType;
import org.eclipse.hawkbit.api.ArtifactUrl;
import org.eclipse.hawkbit.api.ArtifactUrlHandler;
Expand All @@ -42,12 +44,9 @@
/**
* A mapper which maps repository model to RESTful model representation and
* back.
*
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class MgmtSoftwareModuleMapper {
private MgmtSoftwareModuleMapper() {
// Utility class
}

private static SoftwareModuleCreate fromRequest(final EntityFactory entityFactory,
final MgmtSoftwareModuleRequestBodyPost smsRest) {
Expand Down Expand Up @@ -157,21 +156,18 @@ static MgmtArtifact toResponse(final Artifact artifact) {
}

static void addLinks(final Artifact artifact, final MgmtArtifact response) {

response.add(linkTo(methodOn(MgmtDownloadArtifactResource.class)
.downloadArtifact(artifact.getSoftwareModule().getId(), artifact.getId())).withRel("download")
.expand());
}

static void addLinks(final Artifact artifact, final MgmtArtifact response,
final ArtifactUrlHandler artifactUrlHandler, final SystemManagement systemManagement) {

final List<ArtifactUrl> urls = artifactUrlHandler.getUrls(
new URLPlaceholder(systemManagement.getTenantMetadata().getTenant(),
systemManagement.getTenantMetadata().getId(), null, null,
new URLPlaceholder.SoftwareData(artifact.getSoftwareModule().getId(), artifact.getFilename(),
artifact.getId(), artifact.getSha1Hash())), ApiType.MGMT, null);
urls.forEach(entry -> response.add(Link.of(entry.getRef()).withRel(entry.getRel()).expand()));
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1071,8 +1071,8 @@ void lockDistributionSet() throws Exception {
assertThat(distributionSetManagement.count()).isEqualTo(1);
assertThat(set.isLocked()).as("Created distribution set should not be locked").isFalse();

// lock
final String body = new JSONObject().put("locked", true).toString();

mvc.perform(put("/rest/v1/distributionsets/{dsId}", set.getId()).content(body)
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print())
Expand All @@ -1084,8 +1084,8 @@ void lockDistributionSet() throws Exception {
}

@Test
@Description("Tests the unlock. It is verified that the distribution set can't be unmarked as locked through update operation.")
void unlockDistributionSetSkippedSilently() throws Exception {
@Description("Tests the unlock.")
void unlockDistributionSet() throws Exception {
// prepare test data
assertThat(distributionSetManagement.findByCompleted(PAGE, true)).hasSize(0);

Expand All @@ -1094,19 +1094,19 @@ void unlockDistributionSetSkippedSilently() throws Exception {
distributionSetManagement.lock(set.getId());
assertThat(distributionSetManagement.get(set.getId())
.orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, set.getId())).isLocked())
.as("Created software module should not be locked")
.as("Distribution set should be locked")
.isTrue();

// unlock
final String body = new JSONObject().put("locked", false).toString();

mvc.perform(put("/rest/v1/distributionsets/{dsId}", set.getId()).content(body)
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk())
.andExpect(jsonPath("$.locked", equalTo(true)));
.andExpect(jsonPath("$.locked", equalTo(false)));

final DistributionSet updatedSet = distributionSetManagement.get(set.getId()).get();
assertThat(updatedSet.isLocked()).isEqualTo(true);
assertThat(updatedSet.isLocked()).isEqualTo(false);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ void lockSoftwareModule() throws Exception {
.pollInterval(10L, TimeUnit.MILLISECONDS)
.until(() -> sm.getLastModifiedAt() > 0L && sm.getLastModifiedBy() != null);

// lock
final String body = new JSONObject().put("locked", true).toString();
final ResultActions resultActions =
mvc.perform(put("/rest/v1/softwaremodules/{smId}", sm.getId()).content(body)
Expand All @@ -221,37 +222,38 @@ void lockSoftwareModule() throws Exception {
}

@Test
@Description("Tests the unlock. It is verified that the software module can't be unmarked as locked through update operation.")
@Description("Tests the unlock.")
@WithUser(principal = "smUpdateTester", allSpPermissions = true)
void unlockSoftwareModuleSkippedSilently() throws Exception {
void unlockSoftwareModule() throws Exception {
final SoftwareModule sm = softwareModuleManagement.create(
entityFactory.softwareModule().create().type(osType).name("name1").version("version1"));
softwareModuleManagement.lock(sm.getId());
assertThat(softwareModuleManagement.get(sm.getId())
.orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, sm.getId())).isLocked())
.as("Created software module should not be locked")
.as("Software module is locked")
.isTrue();
// ensures that we are not to fast so that last modified is not set correctly
Awaitility.await()
.atMost(Duration.ofMillis(100))
.pollInterval(10L, TimeUnit.MILLISECONDS)
.until(() -> sm.getLastModifiedAt() > 0L && sm.getLastModifiedBy() != null);

// unlock
final String body = new JSONObject().put("locked", false).toString();
final ResultActions resultActions =
mvc.perform(put("/rest/v1/softwaremodules/{smId}", sm.getId()).content(body)
.contentType(MediaType.APPLICATION_JSON));

final SoftwareModule updatedSm = softwareModuleManagement.get(sm.getId()).get();
assertThat(updatedSm.getLastModifiedBy()).isEqualTo("smUpdateTester");
assertThat(updatedSm.isLocked()).isTrue(); // not unlocked
assertThat(updatedSm.isLocked()).isFalse(); // not unlocked

resultActions
.andExpect(status().isOk())
.andExpect(jsonPath("$.id", equalTo(sm.getId().intValue())))
.andExpect(jsonPath("$.lastModifiedBy", equalTo("smUpdateTester")))
.andExpect(jsonPath("$.lastModifiedAt", equalTo(updatedSm.getLastModifiedAt())))
.andExpect(jsonPath("$.locked", equalTo(true)));
.andExpect(jsonPath("$.locked", equalTo(false)));
}

@Test
Expand Down

0 comments on commit f942d77

Please sign in to comment.