Skip to content

Commit a377027

Browse files
authored
SDK improvements (#1693)
Signed-off-by: Marinov Avgustin <Avgustin.Marinov@bosch.com>
1 parent 50d34dd commit a377027

File tree

8 files changed

+84
-102
lines changed

8 files changed

+84
-102
lines changed

hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/DosFilter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ private static boolean checkIpFails(final String ip) {
166166
}
167167

168168
private static boolean handleMissingIpAddress(final HttpServletResponse response) {
169-
log.error("Failed to get peer IP adress");
169+
log.error("Failed to get peer IP address");
170170
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
171171
return false;
172172
}

hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/entity/AbstractActionEvent.java

Lines changed: 15 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,22 @@
99
*/
1010
package org.eclipse.hawkbit.repository.event.remote.entity;
1111

12-
import java.util.Objects;
12+
import java.io.Serial;
1313

14+
import lombok.Data;
15+
import lombok.EqualsAndHashCode;
16+
import lombok.ToString;
1417
import org.eclipse.hawkbit.repository.model.Action;
1518

1619
/**
1720
* Defines the remote event of creating a new {@link Action}.
1821
*/
22+
@Data
23+
@EqualsAndHashCode(callSuper = true)
24+
@ToString(callSuper = false)
1925
public abstract class AbstractActionEvent extends RemoteEntityEvent<Action> {
26+
27+
@Serial
2028
private static final long serialVersionUID = 1L;
2129

2230
private final Long targetId;
@@ -36,16 +44,11 @@ protected AbstractActionEvent() {
3644
/**
3745
* Constructor
3846
*
39-
* @param action
40-
* the created action
41-
* @param targetId
42-
* targetId identifier (optional)
43-
* @param rolloutId
44-
* rollout identifier (optional)
45-
* @param rolloutGroupId
46-
* rollout group identifier (optional)
47-
* @param applicationId
48-
* the origin application id
47+
* @param action the created action
48+
* @param targetId targetId identifier (optional)
49+
* @param rolloutId rollout identifier (optional)
50+
* @param rolloutGroupId rollout group identifier (optional)
51+
* @param applicationId the origin application id
4952
*/
5053
protected AbstractActionEvent(final Action action, final Long targetId, final Long rolloutId,
5154
final Long rolloutGroupId, final String applicationId) {
@@ -54,34 +57,4 @@ protected AbstractActionEvent(final Action action, final Long targetId, final Lo
5457
this.rolloutId = rolloutId;
5558
this.rolloutGroupId = rolloutGroupId;
5659
}
57-
58-
public Long getTargetId() {
59-
return targetId;
60-
}
61-
62-
public Long getRolloutId() {
63-
return rolloutId;
64-
}
65-
66-
public Long getRolloutGroupId() {
67-
return rolloutGroupId;
68-
}
69-
70-
@Override
71-
public boolean equals(final Object o) {
72-
if (this == o)
73-
return true;
74-
if (o == null || getClass() != o.getClass())
75-
return false;
76-
if (!super.equals(o))
77-
return false;
78-
final AbstractActionEvent that = (AbstractActionEvent) o;
79-
return Objects.equals(targetId, that.targetId) && Objects.equals(rolloutId, that.rolloutId)
80-
&& Objects.equals(rolloutGroupId, that.rolloutGroupId);
81-
}
82-
83-
@Override
84-
public int hashCode() {
85-
return Objects.hash(super.hashCode(), targetId, rolloutId, rolloutGroupId);
86-
}
87-
}
60+
}

hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/entity/RemoteEntityEvent.java

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,11 @@
99
*/
1010
package org.eclipse.hawkbit.repository.event.remote.entity;
1111

12+
import java.io.Serial;
1213
import java.util.Optional;
1314

15+
import lombok.AccessLevel;
16+
import lombok.NoArgsConstructor;
1417
import lombok.extern.slf4j.Slf4j;
1518
import org.eclipse.hawkbit.repository.event.remote.EventEntityManagerHolder;
1619
import org.eclipse.hawkbit.repository.event.remote.RemoteIdEvent;
@@ -19,32 +22,24 @@
1922
import com.fasterxml.jackson.annotation.JsonIgnore;
2023

2124
/**
22-
* A base definition class for remote events which contain a tenant aware base
23-
* entity.
25+
* A base definition class for remote events which contain a tenant aware base entity.
2426
*
2527
* @param <E> the type of the entity
2628
*/
29+
@NoArgsConstructor(access = AccessLevel.PROTECTED)
2730
@Slf4j
2831
public class RemoteEntityEvent<E extends TenantAwareBaseEntity> extends RemoteIdEvent {
2932

33+
@Serial
3034
private static final long serialVersionUID = 1L;
3135

3236
private transient E entity;
3337

34-
/**
35-
* Default constructor.
36-
*/
37-
protected RemoteEntityEvent() {
38-
// for serialization libs like jackson
39-
}
40-
4138
/**
4239
* Constructor.
4340
*
44-
* @param baseEntity
45-
* the base entity
46-
* @param applicationId
47-
* the origin application id
41+
* @param baseEntity the base entity
42+
* @param applicationId the origin application id
4843
*/
4944
protected RemoteEntityEvent(final E baseEntity, final String applicationId) {
5045
super(baseEntity.getId(), baseEntity.getTenant(), baseEntity.getClass(), applicationId);
@@ -63,8 +58,8 @@ public Optional<E> getEntity() {
6358
private E reloadEntityFromRepository() {
6459
try {
6560
final Class<E> clazz = (Class<E>) Class.forName(getEntityClass());
66-
return EventEntityManagerHolder.getInstance().getEventEntityManager().findEntity(getTenant(), getEntityId(),
67-
clazz);
61+
return EventEntityManagerHolder.getInstance().getEventEntityManager().findEntity(
62+
getTenant(), getEntityId(), clazz);
6863
} catch (final ClassNotFoundException e) {
6964
log.error("Cannot reload entity because class is not found", e);
7065
}

hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutGroupManagement.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,6 @@ public JpaRolloutGroupManagement(final RolloutGroupRepository rolloutGroupReposi
9595
final TargetRepository targetRepository, final EntityManager entityManager,
9696
final VirtualPropertyReplacer virtualPropertyReplacer, final RolloutStatusCache rolloutStatusCache,
9797
final Database database) {
98-
9998
this.rolloutGroupRepository = rolloutGroupRepository;
10099
this.rolloutRepository = rolloutRepository;
101100
this.actionRepository = actionRepository;
@@ -108,7 +107,7 @@ public JpaRolloutGroupManagement(final RolloutGroupRepository rolloutGroupReposi
108107

109108
@Override
110109
public Optional<RolloutGroup> get(final long rolloutGroupId) {
111-
return rolloutGroupRepository.findById(rolloutGroupId).map(rg -> (RolloutGroup) rg);
110+
return rolloutGroupRepository.findById(rolloutGroupId).map(RolloutGroup.class::cast);
112111
}
113112

114113
@Override
@@ -146,7 +145,7 @@ public Page<RolloutGroup> findByRolloutWithDetailedStatus(final Pageable pageabl
146145
.collect(Collectors.toList());
147146

148147
if (rolloutGroupIds.isEmpty()) {
149-
// groups might already deleted, so return empty list.
148+
// groups might have been already deleted, so return empty list.
150149
return new PageImpl<>(Collections.emptyList());
151150
}
152151

@@ -155,7 +154,7 @@ public Page<RolloutGroup> findByRolloutWithDetailedStatus(final Pageable pageabl
155154

156155
for (final JpaRolloutGroup rolloutGroup : rolloutGroups) {
157156
final TotalTargetCountStatus totalTargetCountStatus = new TotalTargetCountStatus(
158-
allStatesForRollout.get(rolloutGroup.getId()), Long.valueOf(rolloutGroup.getTotalTargets()),
157+
allStatesForRollout.get(rolloutGroup.getId()), (long)rolloutGroup.getTotalTargets(),
159158
rolloutGroup.getRollout().getActionType());
160159
rolloutGroup.setTotalTargetCountStatus(totalTargetCountStatus);
161160
}

hawkbit-rest/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ private static HandlingType calculateUpdateType(final Action action, final Handl
332332
public ResponseEntity<Void> postDeploymentBaseActionFeedback(@Valid @RequestBody final DdiActionFeedback feedback,
333333
@PathVariable("tenant") final String tenant, @PathVariable("controllerId") final String controllerId,
334334
@PathVariable("actionId") @NotNull final Long actionId) {
335-
log.debug("provideBasedeploymentActionFeedback for target [{},{}]: {}", controllerId, actionId, feedback);
335+
log.debug("postDeploymentBaseActionFeedback for target [{},{}]: {}", controllerId, actionId, feedback);
336336

337337
final Target target = findTarget(controllerId);
338338
final Action action = findActionForTarget(actionId, target);
@@ -350,7 +350,6 @@ public ResponseEntity<Void> postDeploymentBaseActionFeedback(@Valid @RequestBody
350350
controllerManagement.addUpdateActionStatus(generateUpdateStatus(feedback, controllerId, actionId));
351351

352352
return ResponseEntity.ok().build();
353-
354353
}
355354

356355
private ActionStatusCreate generateUpdateStatus(final DdiActionFeedback feedback, final String controllerId,
@@ -761,5 +760,4 @@ public ResponseEntity<Void> deactivateAutoConfirmation(final String tenant, fina
761760
confirmationManagement.deactivateAutoConfirmation(controllerId);
762761
return new ResponseEntity<>(HttpStatus.OK);
763762
}
764-
765-
}
763+
}

hawkbit-sdk/hawkbit-sdk-device/src/main/java/org/eclipse/hawkbit/sdk/device/DdiController.java

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,13 @@ public class DdiController {
7373
private volatile ScheduledExecutorService executorService;
7474
private volatile Long currentActionId;
7575

76+
private volatile Long lastActionId;
77+
7678
/**
7779
* Creates a new device instance.
7880
*
7981
* @param tenant the tenant of the device belongs to
80-
* @param controller the the controller
82+
* @param controller the controller
8183
* @param hawkbitClient a factory for creating to {@link DdiRootControllerRestApi} (and used)
8284
* for communication to hawkBit
8385
*/
@@ -102,6 +104,7 @@ public void start(final ScheduledExecutorService executorService) {
102104

103105
public void stop() {
104106
executorService = null;
107+
lastActionId = null;
105108
currentActionId = null;
106109
}
107110

@@ -121,6 +124,12 @@ private void poll() {
121124
getRequiredLink(controllerBase, DEPLOYMENT_BASE_LINK).flatMap(this::getActionWithDeployment).ifPresentOrElse(actionWithDeployment -> {
122125
final long actionId = actionWithDeployment.getKey();
123126
if (currentActionId == null) {
127+
if (lastActionId != null && lastActionId == actionId) {
128+
log.info(LOG_PREFIX + "Still receive the last action {}",
129+
getTenantId(), getControllerId(), actionId);
130+
return;
131+
}
132+
124133
log.info(LOG_PREFIX + "Process action {}", getTenantId(), getControllerId(),
125134
actionId);
126135
final DdiDeployment deployment = actionWithDeployment.getValue().getDeployment();
@@ -132,13 +141,13 @@ private void poll() {
132141
updateHandler.getUpdateProcessor(this, updateType, modules));
133142
} else if (currentActionId != actionId) {
134143
// TODO - cancel and start new one?
135-
log.info(LOG_PREFIX + "Action {} is canceled while in process!", getTenantId(),
136-
getControllerId(), getCurrentActionId());
144+
log.info(LOG_PREFIX + "Action {} is canceled while in process (new {})!", getTenantId(),
145+
getControllerId(), currentActionId, actionId);
137146
} // else same action - already processing
138147
}, () -> {
139148
if (currentActionId != null) {
140149
// TODO - cancel current?
141-
log.info(LOG_PREFIX + "Action {} is canceled while in process!", getTenantId(),
150+
log.info(LOG_PREFIX + "Action {} is canceled while in process (not returned)!", getTenantId(),
142151
getControllerId(), getCurrentActionId());
143152
}
144153
});
@@ -218,10 +227,17 @@ public void updateAttribute(final String mode, final String key, final String va
218227

219228
void sendFeedback(final UpdateStatus updateStatus) {
220229
log.debug(LOG_PREFIX + "Send feedback {} -> {}", getTenantId(), getControllerId(), currentActionId, updateStatus);
221-
getDdiApi().postDeploymentBaseActionFeedback(
222-
updateStatus.feedback(), getTenantId(), getControllerId(), currentActionId);
230+
try {
231+
getDdiApi().postDeploymentBaseActionFeedback(updateStatus.feedback(), getTenantId(), getControllerId(),
232+
currentActionId);
233+
} catch (final RuntimeException e) {
234+
log.error(LOG_PREFIX + "Failed to send feedback {} -> {}", getTenantId(), getControllerId(),
235+
currentActionId, updateStatus, e);
236+
}
237+
223238
if (updateStatus.status() == UpdateStatus.Status.SUCCESSFUL ||
224-
updateStatus.status() == UpdateStatus.Status.ERROR) {
239+
updateStatus.status() == UpdateStatus.Status.FAILURE) {
240+
lastActionId = currentActionId;
225241
currentActionId = null;
226242
}
227243
}

hawkbit-sdk/hawkbit-sdk-device/src/main/java/org/eclipse/hawkbit/sdk/device/UpdateHandler.java

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -95,25 +95,27 @@ public UpdateProcessor(
9595

9696
@Override
9797
public void run() {
98-
ddiController.sendFeedback(new UpdateStatus(UpdateStatus.Status.RUNNING, List.of("Update begins!")));
98+
ddiController.sendFeedback(new UpdateStatus(UpdateStatus.Status.PROCEEDING, List.of("Update begin ...")));
9999

100100
if (!CollectionUtils.isEmpty(modules)) {
101101
try {
102102
final UpdateStatus updateStatus = download();
103103
ddiController.sendFeedback(updateStatus);
104-
if (updateStatus.status() == UpdateStatus.Status.ERROR) {
104+
if (updateStatus.status() == UpdateStatus.Status.FAILURE) {
105105
return;
106106
} else {
107-
ddiController.sendFeedback(update());
107+
if (updateType != DdiDeployment.HandlingType.SKIP) {
108+
ddiController.sendFeedback(update());
109+
}
108110
}
109111
} finally {
110112
cleanup();
111113
}
112114
}
113115

114-
if (updateType != DdiDeployment.HandlingType.SKIP) {
116+
if (updateType == DdiDeployment.HandlingType.SKIP) {
115117
ddiController.sendFeedback(
116-
new UpdateStatus(UpdateStatus.Status.SUCCESSFUL, List.of("Update complete!")));
118+
new UpdateStatus(UpdateStatus.Status.SUCCESSFUL, List.of("Update (download-only) completed.")));
117119
}
118120
}
119121

@@ -126,11 +128,11 @@ public void run() {
126128
protected UpdateStatus download() {
127129
ddiController.sendFeedback(
128130
new UpdateStatus(
129-
UpdateStatus.Status.DOWNLOADING,
131+
UpdateStatus.Status.DOWNLOAD,
130132
modules.stream().flatMap(mod -> mod.getArtifacts().stream())
131-
.map(art -> "Download starts for: " + art.getFilename() +
133+
.map(art -> "Download start for: " + art.getFilename() +
132134
" with size " + art.getSize() +
133-
" and hashes " + art.getHashes())
135+
" and hashes " + art.getHashes() + " ...")
134136
.collect(Collectors.toList())));
135137

136138
log.info(LOG_PREFIX + "Start download", ddiController.getTenantId(), ddiController.getControllerId());
@@ -146,28 +148,28 @@ protected UpdateStatus download() {
146148
}
147149
}));
148150

149-
log.info(LOG_PREFIX + "Download complete", ddiController.getTenantId(), ddiController.getControllerId());
151+
log.info(LOG_PREFIX + "Download complete.", ddiController.getTenantId(), ddiController.getControllerId());
150152

151153
final List<String> messages = new LinkedList<>();
152-
messages.add("Download complete!");
154+
messages.add("Download complete.");
153155
updateStatusList.forEach(download -> messages.addAll(download.messages()));
154156
return new UpdateStatus(
155-
updateStatusList.stream().anyMatch(status -> status.status() == UpdateStatus.Status.ERROR) ?
156-
UpdateStatus.Status.ERROR : UpdateStatus.Status.DOWNLOADED,
157+
updateStatusList.stream().anyMatch(status -> status.status() == UpdateStatus.Status.FAILURE) ?
158+
UpdateStatus.Status.FAILURE : UpdateStatus.Status.DOWNLOADED,
157159
messages);
158160
}
159161

160162
/**
161-
* Extension point. Called after all artifacts has been successfully downloadec. An overriding implementation
163+
* Extension point. Called after all artifacts has been successfully downloaded. An overriding implementation
162164
* may get the {@link #downloads} map and apply them
163165
*/
164166
protected UpdateStatus update() {
165167
log.info(LOG_PREFIX + "Updated", ddiController.getTenantId(), ddiController.getControllerId());
166-
return new UpdateStatus(UpdateStatus.Status.SUCCESSFUL, List.of("Update applied"));
168+
return new UpdateStatus(UpdateStatus.Status.SUCCESSFUL, List.of("Update complete."));
167169
}
168170

169171
/**
170-
* Extension point. Called after download and update has been finished. By default it deletes all downloaded
172+
* Extension point. Called after download and update has been finished. By default, it deletes all downloaded
171173
* files (if any).
172174
*/
173175
protected void cleanup() {
@@ -189,8 +191,7 @@ private void handleArtifact(
189191
artifact.getLink("download").ifPresentOrElse(
190192
// HTTPS
191193
link -> status.add(downloadUrl(link.getHref(), gatewayToken, targetToken,
192-
artifact.getHashes(), artifact.getSize()))
193-
,
194+
artifact.getHashes(), artifact.getSize())),
194195
// HTTP
195196
() -> status.add(downloadUrl(
196197
artifact.getLink("download-http")
@@ -216,7 +217,7 @@ private UpdateStatus downloadUrl(
216217
log.error(LOG_PREFIX + "Failed to download {}",
217218
ddiController.getTenantId(), ddiController.getControllerId(), url, e);
218219
return new UpdateStatus(
219-
UpdateStatus.Status.ERROR,
220+
UpdateStatus.Status.FAILURE,
220221
List.of("Failed to download " + url + ": " + e.getMessage()));
221222
}
222223
}
@@ -273,7 +274,7 @@ private UpdateStatus readAndCheckDownloadUrl(final String url, final String gate
273274
ddiController.getTenantId(), ddiController.getControllerId());
274275
}
275276
downloadHandler.finished(ArtifactHandler.DownloadHandler.Status.ERROR);
276-
return new UpdateStatus(UpdateStatus.Status.ERROR, List.of(message));
277+
return new UpdateStatus(UpdateStatus.Status.FAILURE, List.of(message));
277278
}
278279
});
279280
}

0 commit comments

Comments
 (0)