Simple UI migrated over SDK Management Client (#1664)

Signed-off-by: Marinov Avgustin <Avgustin.Marinov@bosch.com>
This commit is contained in:
Avgustin Marinov
2024-02-21 15:46:44 +02:00
committed by GitHub
parent 8ea3fdb5e7
commit e30737f51b
8 changed files with 95 additions and 104 deletions

View File

@@ -9,15 +9,9 @@
*/
package org.eclipse.hawkbit.ui.simple;
import org.eclipse.hawkbit.ui.simple.view.util.Utils;
import feign.Client;
import feign.Contract;
import feign.Feign;
import org.eclipse.hawkbit.sdk.HawkbitClient;
import org.eclipse.hawkbit.sdk.Tenant;
import feign.FeignException;
import feign.RequestInterceptor;
import feign.codec.Decoder;
import feign.codec.Encoder;
import feign.codec.ErrorDecoder;
import lombok.Getter;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtDistributionSetRestApi;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtDistributionSetTagRestApi;
@@ -30,26 +24,14 @@ import org.eclipse.hawkbit.mgmt.rest.api.MgmtTargetRestApi;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtTargetTagRestApi;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtTargetTypeRestApi;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import java.util.Base64;
import java.util.Objects;
import java.util.function.Supplier;
import static feign.Util.ISO_8859_1;
@Getter
public class HawkbitClient {
public class HawkbitMgmtClient {
private static final RequestInterceptor AUTHORIZATION = requestTemplate -> {
final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
requestTemplate.header("Authorization", "Basic " + Base64.getEncoder().encodeToString(
(Objects.requireNonNull(authentication.getPrincipal(), "User is null!") + ":" + Objects.requireNonNull(
authentication.getCredentials(), "Password is not available!")).getBytes(ISO_8859_1)));
};
private final Tenant tenant;
private final HawkbitClient hawkbitClient;
private final String hawkbitUrl;
private final MgmtSoftwareModuleRestApi softwareModuleRestApi;
private final MgmtSoftwareModuleTypeRestApi softwareModuleTypeRestApi;
private final MgmtDistributionSetRestApi distributionSetRestApi;
@@ -61,20 +43,20 @@ public class HawkbitClient {
private final MgmtTargetFilterQueryRestApi targetFilterQueryRestApi;
private final MgmtRolloutRestApi rolloutRestApi;
HawkbitClient(final String hawkbitUrl,
final Client client, final Encoder encoder, final Decoder decoder, final Contract contract) {
this.hawkbitUrl = hawkbitUrl;
HawkbitMgmtClient(final Tenant tenant, final HawkbitClient hawkbitClient) {
this.tenant = tenant;
this.hawkbitClient = hawkbitClient;
softwareModuleRestApi = service(MgmtSoftwareModuleRestApi .class, client, encoder, decoder, contract);
softwareModuleTypeRestApi = service(MgmtSoftwareModuleTypeRestApi.class, client, encoder, decoder, contract);
distributionSetRestApi = service(MgmtDistributionSetRestApi.class, client, encoder, decoder, contract);
distributionSetTypeRestApi = service(MgmtDistributionSetTypeRestApi.class, client, encoder, decoder, contract);
distributionSetTagRestApi = service(MgmtDistributionSetTagRestApi.class, client, encoder, decoder, contract);
targetRestApi = service(MgmtTargetRestApi.class, client, encoder, decoder, contract);
targetTypeRestApi = service(MgmtTargetTypeRestApi.class, client, encoder, decoder, contract);
targetTagRestApi = service(MgmtTargetTagRestApi.class, client, encoder, decoder, contract);
targetFilterQueryRestApi = service(MgmtTargetFilterQueryRestApi.class, client, encoder, decoder, contract);
rolloutRestApi = service(MgmtRolloutRestApi.class, client, encoder, decoder, contract);
softwareModuleRestApi = service(MgmtSoftwareModuleRestApi .class);
softwareModuleTypeRestApi = service(MgmtSoftwareModuleTypeRestApi.class);
distributionSetRestApi = service(MgmtDistributionSetRestApi.class);
distributionSetTypeRestApi = service(MgmtDistributionSetTypeRestApi.class);
distributionSetTagRestApi = service(MgmtDistributionSetTagRestApi.class);
targetRestApi = service(MgmtTargetRestApi.class);
targetTypeRestApi = service(MgmtTargetTypeRestApi.class);
targetTagRestApi = service(MgmtTargetTagRestApi.class);
targetFilterQueryRestApi = service(MgmtTargetFilterQueryRestApi.class);
rolloutRestApi = service(MgmtRolloutRestApi.class);
}
boolean hasSoftwareModulesRead() {
@@ -102,19 +84,7 @@ public class HawkbitClient {
}
}
private static final ErrorDecoder DEFAULT_ERROR_DECODER = new ErrorDecoder.Default();
private <T> T service(final Class<T> serviceType,
final Client client, final Encoder encoder, final Decoder decoder, final Contract contract) {
return Feign.builder().client(client)
.encoder(encoder)
.decoder(decoder)
.errorDecoder((methodKey, response) -> {
final Exception e = DEFAULT_ERROR_DECODER.decode(methodKey, response);
Utils.errorNotification(e);
return e;
})
.contract(contract)
.requestInterceptor(AUTHORIZATION)
.target(serviceType, hawkbitUrl);
private <T> T service(final Class<T> serviceType) {
return hawkbitClient.mgmtService(serviceType, tenant);
}
}

View File

@@ -15,9 +15,14 @@ import com.vaadin.flow.theme.Theme;
import com.vaadin.flow.theme.lumo.Lumo;
import feign.Client;
import feign.Contract;
import feign.RequestInterceptor;
import feign.codec.Decoder;
import feign.codec.Encoder;
import org.springframework.beans.factory.annotation.Value;
import feign.codec.ErrorDecoder;
import org.eclipse.hawkbit.sdk.HawkbitClient;
import org.eclipse.hawkbit.sdk.HawkbitServer;
import org.eclipse.hawkbit.sdk.Tenant;
import org.eclipse.hawkbit.ui.simple.view.util.Utils;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.FeignClientsConfiguration;
@@ -25,12 +30,17 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import java.util.Base64;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import static feign.Util.ISO_8859_1;
@Theme(themeClass = Lumo.class)
@PWA(name="hawkBit UI", shortName="hawkBit UI")
@@ -38,21 +48,44 @@ import java.util.List;
@Import(FeignClientsConfiguration.class)
public class SimpleUIApp implements AppShellConfigurator {
private static final RequestInterceptor AUTHORIZATION = requestTemplate -> {
final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
requestTemplate.header("Authorization", "Basic " + Base64.getEncoder().encodeToString(
(Objects.requireNonNull(authentication.getPrincipal(), "User is null!") + ":" + Objects.requireNonNull(
authentication.getCredentials(), "Password is not available!")).getBytes(ISO_8859_1)));
};
private static final ErrorDecoder DEFAULT_ERROR_DECODER = new ErrorDecoder.Default();
private static final ErrorDecoder ERROR_DECODER = (methodKey, response) -> {
final Exception e = DEFAULT_ERROR_DECODER.decode(methodKey, response);
Utils.errorNotification(e);
return e;
};
public static void main(String[] args) {
SpringApplication.run(SimpleUIApp.class, args);
}
@Bean
HawkbitClient hawkbitClient(
@Value("${hawkbit.url:http://localhost:8080}")
final String hawkbitUrl,
final HawkbitServer hawkBitServer,
final Client client, final Encoder encoder, final Decoder decoder, final Contract contract) {
return new HawkbitClient(hawkbitUrl, client, encoder, decoder, contract);
return new HawkbitClient(
hawkBitServer, client, encoder, decoder, contract,
ERROR_DECODER,
(tenant, controller) ->
controller == null ?
AUTHORIZATION : HawkbitClient.DEFAULT_REQUEST_INTERCEPTOR_FN.apply(tenant, controller));
}
@Bean
HawkbitMgmtClient hawkbitMgmtClient(final Tenant tenant, final HawkbitClient hawkbitClient) {
return new HawkbitMgmtClient(tenant, hawkbitClient);
}
// accepts all user / pass, just delegating them to the feign client
@Bean
AuthenticationManager authenticationManager(final HawkbitClient hawkbitClient) {
AuthenticationManager authenticationManager(final HawkbitMgmtClient hawkbitClient) {
return authentication-> {
final String username = authentication.getName();
final String password = authentication.getCredentials().toString();

View File

@@ -10,7 +10,7 @@
package org.eclipse.hawkbit.ui.simple.view;
import org.eclipse.hawkbit.ui.simple.MainLayout;
import org.eclipse.hawkbit.ui.simple.HawkbitClient;
import org.eclipse.hawkbit.ui.simple.HawkbitMgmtClient;
import org.eclipse.hawkbit.ui.simple.view.util.Filter;
import org.eclipse.hawkbit.ui.simple.view.util.SelectionGrid;
import org.eclipse.hawkbit.ui.simple.view.util.TableView;
@@ -56,7 +56,7 @@ import java.util.stream.Stream;
@Uses(Icon.class)
public class DistributionSetView extends TableView<MgmtDistributionSet, Long> {
public DistributionSetView(final HawkbitClient hawkbitClient) {
public DistributionSetView(final HawkbitMgmtClient hawkbitClient) {
super(
new DistributionSetFilter(hawkbitClient),
new SelectionGrid.EntityRepresentation<>(MgmtDistributionSet.class, MgmtDistributionSet::getDsId) {
@@ -110,7 +110,7 @@ public class DistributionSetView extends TableView<MgmtDistributionSet, Long> {
private final CheckboxGroup<MgmtDistributionSetType> type = new CheckboxGroup<>("Type");
private final CheckboxGroup<MgmtTag> tag = new CheckboxGroup<>("Tag");
private DistributionSetFilter(final HawkbitClient hawkbitClient) {
private DistributionSetFilter(final HawkbitMgmtClient hawkbitClient) {
name.setPlaceholder("<name filter>");
type.setItemLabelGenerator(MgmtDistributionSetType::getName);
type.setItems(
@@ -144,7 +144,7 @@ public class DistributionSetView extends TableView<MgmtDistributionSet, Long> {
private static class DistributionSetDetails extends FormLayout {
private final transient HawkbitClient hawkbitClient;
private final transient HawkbitMgmtClient hawkbitClient;
private final TextArea description = new TextArea("Description");
private final TextField createdBy = Utils.textField("Created by");
@@ -153,7 +153,7 @@ public class DistributionSetView extends TableView<MgmtDistributionSet, Long> {
private final TextField lastModifiedAt = Utils.textField("Last modified at");
private final SelectionGrid<MgmtSoftwareModule, Long> softwareModulesGrid = selectSoftwareModuleGrid();
private DistributionSetDetails(final HawkbitClient hawkbitClient) {
private DistributionSetDetails(final HawkbitMgmtClient hawkbitClient) {
this.hawkbitClient = hawkbitClient;
description.setMinLength(2);
@@ -193,7 +193,7 @@ public class DistributionSetView extends TableView<MgmtDistributionSet, Long> {
private static class CreateDialog extends Utils.BaseDialog<Void> {
private final transient HawkbitClient hawkbitClient;
private final transient HawkbitMgmtClient hawkbitClient;
private final Select<MgmtDistributionSetType> type;
private final TextField name;
@@ -202,7 +202,7 @@ public class DistributionSetView extends TableView<MgmtDistributionSet, Long> {
private final Checkbox requiredMigrationStep;
private final Button create;
private CreateDialog(final HawkbitClient hawkbitClient) {
private CreateDialog(final HawkbitMgmtClient hawkbitClient) {
super("Create Distribution Set");
this.hawkbitClient = hawkbitClient;
@@ -278,7 +278,7 @@ public class DistributionSetView extends TableView<MgmtDistributionSet, Long> {
private final transient Set<MgmtSoftwareModule> softwareModules = Collections.synchronizedSet(new HashSet<>());
private AddSoftwareModulesDialog(final long distributionSetId, final HawkbitClient hawkbitClient) {
private AddSoftwareModulesDialog(final long distributionSetId, final HawkbitMgmtClient hawkbitClient) {
super("Add Software Modules");
final SelectionGrid<MgmtSoftwareModule, Long> softwareModulesGrid = selectSoftwareModuleGrid();

View File

@@ -10,7 +10,7 @@
package org.eclipse.hawkbit.ui.simple.view;
import com.vaadin.flow.component.checkbox.Checkbox;
import org.eclipse.hawkbit.ui.simple.HawkbitClient;
import org.eclipse.hawkbit.ui.simple.HawkbitMgmtClient;
import org.eclipse.hawkbit.ui.simple.MainLayout;
import org.eclipse.hawkbit.ui.simple.view.util.SelectionGrid;
import org.eclipse.hawkbit.ui.simple.view.util.TableView;
@@ -61,7 +61,7 @@ import java.util.stream.Stream;
@Uses(Icon.class)
public class RolloutView extends TableView<MgmtRolloutResponseBody, Long> {
public RolloutView(final HawkbitClient hawkbitClient) {
public RolloutView(final HawkbitMgmtClient hawkbitClient) {
super(
new RolloutFilter(),
new SelectionGrid.EntityRepresentation<>(
@@ -118,9 +118,9 @@ public class RolloutView extends TableView<MgmtRolloutResponseBody, Long> {
private final long rolloutId;
private final Grid<MgmtRolloutResponseBody> grid;
private final transient HawkbitClient hawkbitClient;
private final transient HawkbitMgmtClient hawkbitClient;
private Actions(final MgmtRolloutResponseBody rollout, final Grid<MgmtRolloutResponseBody> grid, final HawkbitClient hawkbitClient) {
private Actions(final MgmtRolloutResponseBody rollout, final Grid<MgmtRolloutResponseBody> grid, final HawkbitMgmtClient hawkbitClient) {
this.rolloutId = rollout.getRolloutId();
this.grid = grid;
this.hawkbitClient = hawkbitClient;
@@ -185,7 +185,7 @@ public class RolloutView extends TableView<MgmtRolloutResponseBody, Long> {
private static class RolloutDetails extends FormLayout {
private final transient HawkbitClient hawkbitClient;
private final transient HawkbitMgmtClient hawkbitClient;
private final TextArea description = new TextArea(Constants.DESCRIPTION);
private final TextField createdBy = Utils.textField(Constants.CREATED_BY);
@@ -199,7 +199,7 @@ public class RolloutView extends TableView<MgmtRolloutResponseBody, Long> {
private final Checkbox dynamic = new Checkbox(Constants.DYNAMIC);
private final SelectionGrid<MgmtRolloutGroupResponseBody, Long> groupGrid;
private RolloutDetails(final HawkbitClient hawkbitClient) {
private RolloutDetails(final HawkbitMgmtClient hawkbitClient) {
this.hawkbitClient = hawkbitClient;
description.setMinLength(2);
@@ -277,7 +277,7 @@ public class RolloutView extends TableView<MgmtRolloutResponseBody, Long> {
private final Button create = new Button("Create");
private CreateDialog(final HawkbitClient hawkbitClient) {
private CreateDialog(final HawkbitMgmtClient hawkbitClient) {
super("Create Rollout");
name = Utils.textField("Name", this::readyToCreate);
@@ -400,7 +400,7 @@ public class RolloutView extends TableView<MgmtRolloutResponseBody, Long> {
}
}
private void addCreateClickListener(final HawkbitClient hawkbitClient) {
private void addCreateClickListener(final HawkbitMgmtClient hawkbitClient) {
create.addClickListener(e -> {
close();
final MgmtRolloutRestRequestBody request = new MgmtRolloutRestRequestBody();

View File

@@ -9,7 +9,7 @@
*/
package org.eclipse.hawkbit.ui.simple.view;
import org.eclipse.hawkbit.ui.simple.HawkbitClient;
import org.eclipse.hawkbit.ui.simple.HawkbitMgmtClient;
import org.eclipse.hawkbit.ui.simple.MainLayout;
import org.eclipse.hawkbit.ui.simple.view.util.SelectionGrid;
import org.eclipse.hawkbit.ui.simple.view.util.TableView;
@@ -63,11 +63,11 @@ import java.util.stream.Stream;
public class SoftwareModuleView extends TableView<MgmtSoftwareModule, Long> {
@Autowired
public SoftwareModuleView(final HawkbitClient hawkbitClient) {
public SoftwareModuleView(final HawkbitMgmtClient hawkbitClient) {
this(true, hawkbitClient);
}
public SoftwareModuleView(final boolean isParent, final HawkbitClient hawkbitClient) {
public SoftwareModuleView(final boolean isParent, final HawkbitMgmtClient hawkbitClient) {
super(
new SoftwareModuleFilter(hawkbitClient),
new SelectionGrid.EntityRepresentation<>(MgmtSoftwareModule.class, MgmtSoftwareModule::getModuleId) {
@@ -122,7 +122,7 @@ public class SoftwareModuleView extends TableView<MgmtSoftwareModule, Long> {
private final TextField name = Utils.textField(Constants.NAME);
private final CheckboxGroup<MgmtSoftwareModuleType> type = new CheckboxGroup<>(Constants.TYPE);
private SoftwareModuleFilter(final HawkbitClient hawkbitClient) {
private SoftwareModuleFilter(final HawkbitMgmtClient hawkbitClient) {
name.setPlaceholder("<name filter>");
type.setItemLabelGenerator(MgmtSoftwareModuleType::getName);
type.setItems(
@@ -150,7 +150,7 @@ public class SoftwareModuleView extends TableView<MgmtSoftwareModule, Long> {
private static class SoftwareModuleDetails extends FormLayout {
private final transient HawkbitClient hawkbitClient;
private final transient HawkbitMgmtClient hawkbitClient;
private final TextArea description = new TextArea(Constants.DESCRIPTION);
private final TextField createdBy = Utils.textField(Constants.CREATED_BY);
@@ -159,7 +159,7 @@ public class SoftwareModuleView extends TableView<MgmtSoftwareModule, Long> {
private final TextField lastModifiedAt = Utils.textField(Constants.LAST_MODIFIED_AT);
private final SelectionGrid<MgmtArtifact, Long> artifactGrid;
private SoftwareModuleDetails(final HawkbitClient hawkbitClient) {
private SoftwareModuleDetails(final HawkbitMgmtClient hawkbitClient) {
this.hawkbitClient = hawkbitClient;
description.setMinLength(2);
@@ -207,7 +207,7 @@ public class SoftwareModuleView extends TableView<MgmtSoftwareModule, Long> {
private final Checkbox enableArtifactEncryption;
private final Button create;
private CreateDialog(final HawkbitClient hawkbitClient) {
private CreateDialog(final HawkbitMgmtClient hawkbitClient) {
super("Create Software Module");
type = new Select<>(
@@ -256,7 +256,7 @@ public class SoftwareModuleView extends TableView<MgmtSoftwareModule, Long> {
}
}
private void addCreateClickListener(final HawkbitClient hawkbitClient) {
private void addCreateClickListener(final HawkbitMgmtClient hawkbitClient) {
create.addClickListener(e -> {
close();
final long softwareModuleId = hawkbitClient.getSoftwareModuleRestApi().createSoftwareModules(
@@ -283,7 +283,7 @@ public class SoftwareModuleView extends TableView<MgmtSoftwareModule, Long> {
private AddArtifactsDialog(
final long softwareModuleId,
final HawkbitClient hawkbitClient) {
final HawkbitMgmtClient hawkbitClient) {
super("Add Artifacts");
final SelectionGrid<MgmtArtifact, Long> artifactGrid = createArtifactGrid();

View File

@@ -9,7 +9,7 @@
*/
package org.eclipse.hawkbit.ui.simple.view;
import org.eclipse.hawkbit.ui.simple.HawkbitClient;
import org.eclipse.hawkbit.ui.simple.HawkbitMgmtClient;
import org.eclipse.hawkbit.ui.simple.view.util.Filter;
import org.eclipse.hawkbit.ui.simple.MainLayout;
import org.eclipse.hawkbit.ui.simple.view.util.SelectionGrid;
@@ -60,7 +60,7 @@ public class TargetView extends TableView<MgmtTarget, String> {
public static final String CONTROLLER_ID = "Controller Id";
public static final String TAG = "Tag";
public TargetView(final HawkbitClient hawkbitClient) {
public TargetView(final HawkbitMgmtClient hawkbitClient) {
super(
new RawFilter(hawkbitClient), new SimpleFilter(hawkbitClient),
new SelectionGrid.EntityRepresentation<>(MgmtTarget.class, MgmtTarget::getControllerId) {
@@ -92,13 +92,13 @@ public class TargetView extends TableView<MgmtTarget, String> {
private static class SimpleFilter implements Filter.Rsql {
private final HawkbitClient hawkbitClient;
private final HawkbitMgmtClient hawkbitClient;
private final TextField controllerId;
private final CheckboxGroup<MgmtTargetType> type;
private final CheckboxGroup<MgmtTag> tag;
private SimpleFilter(final HawkbitClient hawkbitClient) {
private SimpleFilter(final HawkbitMgmtClient hawkbitClient) {
this.hawkbitClient = hawkbitClient;
controllerId = Utils.textField(CONTROLLER_ID);
@@ -140,7 +140,7 @@ public class TargetView extends TableView<MgmtTarget, String> {
private final TextField textFilter = new TextField("Raw Filter");
private final VerticalLayout layout = new VerticalLayout();
private RawFilter(final HawkbitClient hawkbitClient) {
private RawFilter(final HawkbitMgmtClient hawkbitClient) {
textFilter.setPlaceholder("<raw filter>");
final Select<MgmtTargetFilterQuery> savedFilters = new Select<>(
"Saved Filters",
@@ -246,7 +246,7 @@ public class TargetView extends TableView<MgmtTarget, String> {
private final TextField name;
private final TextArea description;
private RegisterDialog(final HawkbitClient hawkbitClient) {
private RegisterDialog(final HawkbitMgmtClient hawkbitClient) {
super("Register Target");
final Button register = Utils.tooltip(new Button("Register"), "Register (Enter)");
@@ -290,7 +290,7 @@ public class TargetView extends TableView<MgmtTarget, String> {
open();
}
private void addCreateClickListener(final Button register, final HawkbitClient hawkbitClient) {
private void addCreateClickListener(final Button register, final HawkbitMgmtClient hawkbitClient) {
register.addClickListener(e -> {
final MgmtTargetRequestBody request = new MgmtTargetRequestBody()
.setControllerId(controllerId.getValue())

View File

@@ -9,7 +9,6 @@
#
server.port=${PORT:8088}
spring.cloud.openfeign.httpclient.hc5.enabled=true
### Vaadin start ###`
# build with mvn vaadin:build-frontend to enable / disable