Merge remote-tracking branch 'eclipse/master' into cleanup-properties
# Conflicts: # hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpProperties.j ava
This commit is contained in:
@@ -8,21 +8,12 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.app;
|
package org.eclipse.hawkbit.app;
|
||||||
|
|
||||||
import org.eclipse.hawkbit.eventbus.EventSubscriber;
|
|
||||||
import org.eclipse.hawkbit.eventbus.event.EntityEvent;
|
|
||||||
import org.eclipse.hawkbit.ui.DispatcherRunnable;
|
|
||||||
import org.eclipse.hawkbit.ui.HawkbitUI;
|
import org.eclipse.hawkbit.ui.HawkbitUI;
|
||||||
import org.springframework.security.core.context.SecurityContext;
|
import org.eclipse.hawkbit.ui.push.DelayedEventBusPushStrategy;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
|
|
||||||
import org.vaadin.spring.events.EventBus.SessionEventBus;
|
|
||||||
|
|
||||||
import com.google.common.eventbus.AllowConcurrentEvents;
|
import com.google.common.eventbus.EventBus;
|
||||||
import com.google.common.eventbus.Subscribe;
|
|
||||||
import com.vaadin.annotations.Push;
|
import com.vaadin.annotations.Push;
|
||||||
import com.vaadin.server.VaadinSession;
|
|
||||||
import com.vaadin.server.VaadinSession.State;
|
|
||||||
import com.vaadin.server.WrappedSession;
|
|
||||||
import com.vaadin.shared.communication.PushMode;
|
import com.vaadin.shared.communication.PushMode;
|
||||||
import com.vaadin.shared.ui.ui.Transport;
|
import com.vaadin.shared.ui.ui.Transport;
|
||||||
import com.vaadin.spring.annotation.SpringUI;
|
import com.vaadin.spring.annotation.SpringUI;
|
||||||
@@ -33,45 +24,16 @@ import com.vaadin.spring.annotation.SpringUI;
|
|||||||
* A {@link SpringUI} annotated class must be present in the classpath. The
|
* A {@link SpringUI} annotated class must be present in the classpath. The
|
||||||
* easiest way to get an hawkBit UI running is to extend the {@link HawkbitUI}
|
* easiest way to get an hawkBit UI running is to extend the {@link HawkbitUI}
|
||||||
* and to annotated it with {@link SpringUI} as in this example.
|
* and to annotated it with {@link SpringUI} as in this example.
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@SpringUI
|
@SpringUI
|
||||||
@Push(value = PushMode.AUTOMATIC, transport = Transport.WEBSOCKET)
|
@Push(value = PushMode.AUTOMATIC, transport = Transport.WEBSOCKET)
|
||||||
@EventSubscriber
|
|
||||||
public class MyUI extends HawkbitUI {
|
public class MyUI extends HawkbitUI {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
/**
|
@Autowired
|
||||||
* An {@link com.google.common.eventbus.EventBus} subscriber which
|
public MyUI(final EventBus systemEventBus, final org.vaadin.spring.events.EventBus.SessionEventBus eventBus) {
|
||||||
* subscribes {@link EntityEvent} from the repository to dispatch these
|
super(new DelayedEventBusPushStrategy(eventBus, systemEventBus));
|
||||||
* events to the UI {@link SessionEventBus}.
|
|
||||||
*
|
|
||||||
* @param event
|
|
||||||
* the entity event which has been published from the repository
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
@Subscribe
|
|
||||||
@AllowConcurrentEvents
|
|
||||||
public void dispatch(final org.eclipse.hawkbit.eventbus.event.Event event) {
|
|
||||||
final VaadinSession session = getSession();
|
|
||||||
if (session != null && session.getState() == State.OPEN) {
|
|
||||||
final WrappedSession wrappedSession = session.getSession();
|
|
||||||
if (wrappedSession != null) {
|
|
||||||
final SecurityContext userContext = (SecurityContext) wrappedSession
|
|
||||||
.getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
|
|
||||||
if (eventSecurityCheck(userContext, event)) {
|
|
||||||
final SecurityContext oldContext = SecurityContextHolder.getContext();
|
|
||||||
try {
|
|
||||||
access(new DispatcherRunnable(eventBus, session, userContext, event));
|
|
||||||
} finally {
|
|
||||||
SecurityContextHolder.setContext(oldContext);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ public class SoftwareModuleAssigmentBuilder {
|
|||||||
private final List<Long> ids;
|
private final List<Long> ids;
|
||||||
|
|
||||||
public SoftwareModuleAssigmentBuilder() {
|
public SoftwareModuleAssigmentBuilder() {
|
||||||
ids = new ArrayList<Long>();
|
ids = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -51,7 +51,12 @@ public class TenantAwareCacheManager implements TenancyCacheManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Cache getCache(final String name) {
|
public Cache getCache(final String name) {
|
||||||
final String currentTenant = tenantAware.getCurrentTenant().toUpperCase();
|
String currentTenant = tenantAware.getCurrentTenant();
|
||||||
|
if (currentTenant == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentTenant = currentTenant.toUpperCase();
|
||||||
if (currentTenant.contains(TENANT_CACHE_DELIMITER)) {
|
if (currentTenant.contains(TENANT_CACHE_DELIMITER)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -60,7 +65,12 @@ public class TenantAwareCacheManager implements TenancyCacheManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<String> getCacheNames() {
|
public Collection<String> getCacheNames() {
|
||||||
final String currentTenant = tenantAware.getCurrentTenant().toUpperCase();
|
String currentTenant = tenantAware.getCurrentTenant();
|
||||||
|
if (currentTenant == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentTenant = currentTenant.toUpperCase();
|
||||||
if (currentTenant.contains(TENANT_CACHE_DELIMITER)) {
|
if (currentTenant.contains(TENANT_CACHE_DELIMITER)) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,12 @@ public enum ActionStatusFields implements FieldNameProvider {
|
|||||||
/**
|
/**
|
||||||
* The id field.
|
* The id field.
|
||||||
*/
|
*/
|
||||||
ID("id");
|
ID("id"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The reportedAt field.
|
||||||
|
*/
|
||||||
|
REPORTEDAT("createdAt");
|
||||||
|
|
||||||
private final String fieldName;
|
private final String fieldName;
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
|
|||||||
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
|
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
|
||||||
import org.springframework.amqp.support.converter.MessageConverter;
|
import org.springframework.amqp.support.converter.MessageConverter;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
|
||||||
@@ -121,11 +122,22 @@ public class AmqpConfiguration {
|
|||||||
/**
|
/**
|
||||||
* Create amqp handler service bean.
|
* Create amqp handler service bean.
|
||||||
*
|
*
|
||||||
* @return
|
* @return handler service bean
|
||||||
*/
|
*/
|
||||||
@Bean
|
@Bean
|
||||||
public AmqpMessageHandlerService amqpMessageHandlerService() {
|
public AmqpMessageHandlerService amqpMessageHandlerService() {
|
||||||
return new AmqpMessageHandlerService();
|
return new AmqpMessageHandlerService(rabbitTemplate);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create default amqp sender service bean.
|
||||||
|
*
|
||||||
|
* @return the default amqp sender service bean
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
public AmqpSenderService amqpSenderServiceBean() {
|
||||||
|
return new DefaultAmqpSenderService(rabbitTemplate);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -127,10 +127,7 @@ public class AmqpControllerAuthentfication {
|
|||||||
|
|
||||||
LOGGER.debug("preAuthenticatedPrincipal = {} trying to authenticate", principal);
|
LOGGER.debug("preAuthenticatedPrincipal = {} trying to authenticate", principal);
|
||||||
|
|
||||||
final PreAuthenticatedAuthenticationToken authRequest = new PreAuthenticatedAuthenticationToken(principal,
|
return new PreAuthenticatedAuthenticationToken(principal, credentials);
|
||||||
credentials);
|
|
||||||
|
|
||||||
return authRequest;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setControllerManagement(final ControllerManagement controllerManagement) {
|
public void setControllerManagement(final ControllerManagement controllerManagement) {
|
||||||
|
|||||||
@@ -25,35 +25,43 @@ import org.eclipse.hawkbit.eventbus.EventSubscriber;
|
|||||||
import org.eclipse.hawkbit.eventbus.event.CancelTargetAssignmentEvent;
|
import org.eclipse.hawkbit.eventbus.event.CancelTargetAssignmentEvent;
|
||||||
import org.eclipse.hawkbit.eventbus.event.TargetAssignDistributionSetEvent;
|
import org.eclipse.hawkbit.eventbus.event.TargetAssignDistributionSetEvent;
|
||||||
import org.eclipse.hawkbit.repository.model.LocalArtifact;
|
import org.eclipse.hawkbit.repository.model.LocalArtifact;
|
||||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
|
||||||
import org.eclipse.hawkbit.util.ArtifactUrlHandler;
|
import org.eclipse.hawkbit.util.ArtifactUrlHandler;
|
||||||
import org.eclipse.hawkbit.util.IpUtil;
|
import org.eclipse.hawkbit.util.IpUtil;
|
||||||
import org.springframework.amqp.core.Message;
|
import org.springframework.amqp.core.Message;
|
||||||
import org.springframework.amqp.core.MessageProperties;
|
import org.springframework.amqp.core.MessageProperties;
|
||||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||||
import org.springframework.amqp.support.converter.AbstractJavaTypeMapper;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
import com.google.common.eventbus.Subscribe;
|
import com.google.common.eventbus.Subscribe;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link AmqpMessageDispatcherService} handles all outgoing AMQP messages.
|
* {@link AmqpMessageDispatcherService} create all outgoing AMQP messages and
|
||||||
*
|
* delegate the messages to a {@link AmqpSenderService}.
|
||||||
*
|
*
|
||||||
|
* Additionally the dispatcher listener/subscribe for some target events e.g.
|
||||||
|
* assignment.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@EventSubscriber
|
@EventSubscriber
|
||||||
public class AmqpMessageDispatcherService {
|
public class AmqpMessageDispatcherService extends BaseAmqpService {
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private RabbitTemplate rabbitTemplate;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private TenantAware tenantAware;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ArtifactUrlHandler artifactUrlHandler;
|
private ArtifactUrlHandler artifactUrlHandler;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AmqpSenderService amqpSenderService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param messageConverter
|
||||||
|
* message converter
|
||||||
|
*/
|
||||||
|
@Autowired
|
||||||
|
public AmqpMessageDispatcherService(final RabbitTemplate rabbitTemplate) {
|
||||||
|
super(rabbitTemplate);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to send a message to a RabbitMQ Exchange after the Distribution
|
* Method to send a message to a RabbitMQ Exchange after the Distribution
|
||||||
* set has been assign to a Target.
|
* set has been assign to a Target.
|
||||||
@@ -79,11 +87,10 @@ public class AmqpMessageDispatcherService {
|
|||||||
downloadAndUpdateRequest.addSoftwareModule(amqpSoftwareModule);
|
downloadAndUpdateRequest.addSoftwareModule(amqpSoftwareModule);
|
||||||
}
|
}
|
||||||
|
|
||||||
final Message message = rabbitTemplate.getMessageConverter().toMessage(
|
final Message message = getMessageConverter().toMessage(downloadAndUpdateRequest,
|
||||||
downloadAndUpdateRequest,
|
|
||||||
createConnectorMessageProperties(targetAssignDistributionSetEvent.getTenant(), controllerId,
|
createConnectorMessageProperties(targetAssignDistributionSetEvent.getTenant(), controllerId,
|
||||||
EventTopic.DOWNLOAD_AND_INSTALL));
|
EventTopic.DOWNLOAD_AND_INSTALL));
|
||||||
sendMessage(targetAdress.getHost(), message);
|
amqpSenderService.sendMessage(message, targetAdress);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -98,29 +105,13 @@ public class AmqpMessageDispatcherService {
|
|||||||
final CancelTargetAssignmentEvent cancelTargetAssignmentDistributionSetEvent) {
|
final CancelTargetAssignmentEvent cancelTargetAssignmentDistributionSetEvent) {
|
||||||
final String controllerId = cancelTargetAssignmentDistributionSetEvent.getControllerId();
|
final String controllerId = cancelTargetAssignmentDistributionSetEvent.getControllerId();
|
||||||
final Long actionId = cancelTargetAssignmentDistributionSetEvent.getActionId();
|
final Long actionId = cancelTargetAssignmentDistributionSetEvent.getActionId();
|
||||||
final Message message = rabbitTemplate.getMessageConverter().toMessage(
|
final Message message = getMessageConverter().toMessage(actionId, createConnectorMessageProperties(
|
||||||
actionId,
|
cancelTargetAssignmentDistributionSetEvent.getTenant(), controllerId, EventTopic.CANCEL_DOWNLOAD));
|
||||||
createConnectorMessageProperties(cancelTargetAssignmentDistributionSetEvent.getTenant(), controllerId,
|
|
||||||
EventTopic.CANCEL_DOWNLOAD));
|
|
||||||
|
|
||||||
sendMessage(cancelTargetAssignmentDistributionSetEvent.getTargetAdress().getHost(), message);
|
amqpSenderService.sendMessage(message, cancelTargetAssignmentDistributionSetEvent.getTargetAdress());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Send message to exchange.
|
|
||||||
*
|
|
||||||
* @param exchange
|
|
||||||
* the exchange
|
|
||||||
* @param message
|
|
||||||
* the message
|
|
||||||
*/
|
|
||||||
public void sendMessage(final String exchange, final Message message) {
|
|
||||||
message.getMessageProperties().getHeaders().remove(AbstractJavaTypeMapper.DEFAULT_CLASSID_FIELD_NAME);
|
|
||||||
rabbitTemplate.setExchange(exchange);
|
|
||||||
rabbitTemplate.send(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
private MessageProperties createConnectorMessageProperties(final String tenant, final String controllerId,
|
private MessageProperties createConnectorMessageProperties(final String tenant, final String controllerId,
|
||||||
final EventTopic topic) {
|
final EventTopic topic) {
|
||||||
final MessageProperties messageProperties = createMessageProperties();
|
final MessageProperties messageProperties = createMessageProperties();
|
||||||
@@ -155,9 +146,8 @@ public class AmqpMessageDispatcherService {
|
|||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<Artifact> convertedArtifacts = localArtifacts.stream()
|
return localArtifacts.stream().map(localArtifact -> convertArtifact(targetId, localArtifact))
|
||||||
.map(localArtifact -> convertArtifact(targetId, localArtifact)).collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
return convertedArtifacts;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Artifact convertArtifact(final String targetId, final LocalArtifact localArtifact) {
|
private Artifact convertArtifact(final String targetId, final LocalArtifact localArtifact) {
|
||||||
@@ -175,15 +165,11 @@ public class AmqpMessageDispatcherService {
|
|||||||
return artifact;
|
return artifact;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTenantAware(final TenantAware tenantAware) {
|
|
||||||
this.tenantAware = tenantAware;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRabbitTemplate(final RabbitTemplate rabbitTemplate) {
|
|
||||||
this.rabbitTemplate = rabbitTemplate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setArtifactUrlHandler(final ArtifactUrlHandler artifactUrlHandler) {
|
public void setArtifactUrlHandler(final ArtifactUrlHandler artifactUrlHandler) {
|
||||||
this.artifactUrlHandler = artifactUrlHandler;
|
this.artifactUrlHandler = artifactUrlHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setAmqpSenderService(final AmqpSenderService amqpSenderService) {
|
||||||
|
this.amqpSenderService = amqpSenderService;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import java.net.URI;
|
|||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
@@ -50,8 +49,6 @@ import org.springframework.amqp.core.Message;
|
|||||||
import org.springframework.amqp.core.MessageProperties;
|
import org.springframework.amqp.core.MessageProperties;
|
||||||
import org.springframework.amqp.rabbit.annotation.RabbitListener;
|
import org.springframework.amqp.rabbit.annotation.RabbitListener;
|
||||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||||
import org.springframework.amqp.support.converter.AbstractJavaTypeMapper;
|
|
||||||
import org.springframework.amqp.support.converter.MessageConverter;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
import org.springframework.cache.Cache;
|
import org.springframework.cache.Cache;
|
||||||
@@ -72,19 +69,14 @@ import com.google.common.eventbus.EventBus;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* {@link AmqpMessageHandlerService} handles all incoming AMQP messages.
|
* {@link AmqpMessageHandlerService} handles all incoming AMQP messages for the
|
||||||
*
|
* queue which is configure for the property hawkbit.dmf.rabbitmq.receiverQueue.
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class AmqpMessageHandlerService {
|
public class AmqpMessageHandlerService extends BaseAmqpService {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(AmqpMessageHandlerService.class);
|
private static final Logger LOG = LoggerFactory.getLogger(AmqpMessageHandlerService.class);
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private RabbitTemplate rabbitTemplate;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ControllerManagement controllerManagement;
|
private ControllerManagement controllerManagement;
|
||||||
|
|
||||||
@@ -105,7 +97,23 @@ public class AmqpMessageHandlerService {
|
|||||||
private HostnameResolver hostnameResolver;
|
private HostnameResolver hostnameResolver;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* /** Method to handle all incoming amqp messages.
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param defaultTemplate
|
||||||
|
* the configured amqp template.
|
||||||
|
*/
|
||||||
|
public AmqpMessageHandlerService(final RabbitTemplate defaultTemplate) {
|
||||||
|
super(defaultTemplate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@RabbitListener(queues = "${hawkbit.dmf.rabbitmq.receiverQueue}", containerFactory = "listenerContainerFactory")
|
||||||
|
private Message onMessage(final Message message, @Header(MessageHeaderKey.TYPE) final String type,
|
||||||
|
@Header(MessageHeaderKey.TENANT) final String tenant) {
|
||||||
|
return onMessage(message, type, tenant, getRabbitTemplate().getConnectionFactory().getVirtualHost());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to handle all incoming amqp messages.
|
||||||
*
|
*
|
||||||
* @param message
|
* @param message
|
||||||
* incoming message
|
* incoming message
|
||||||
@@ -115,11 +123,11 @@ public class AmqpMessageHandlerService {
|
|||||||
* the contentType of the message
|
* the contentType of the message
|
||||||
* @param tenant
|
* @param tenant
|
||||||
* the contentType of the message
|
* the contentType of the message
|
||||||
|
* @param virtualHost
|
||||||
|
* the virtual host
|
||||||
* @return a message if <null> no message is send back to sender
|
* @return a message if <null> no message is send back to sender
|
||||||
*/
|
*/
|
||||||
@RabbitListener(queues = "${hawkbit.dmf.rabbitmq.receiverQueue}", containerFactory = "listenerContainerFactory")
|
public Message onMessage(final Message message, final String type, final String tenant, final String virtualHost) {
|
||||||
public Message onMessage(final Message message, @Header(MessageHeaderKey.TYPE) final String type,
|
|
||||||
@Header(MessageHeaderKey.TENANT) final String tenant) {
|
|
||||||
checkContentTypeJson(message);
|
checkContentTypeJson(message);
|
||||||
final SecurityContext oldContext = SecurityContextHolder.getContext();
|
final SecurityContext oldContext = SecurityContextHolder.getContext();
|
||||||
try {
|
try {
|
||||||
@@ -127,7 +135,7 @@ public class AmqpMessageHandlerService {
|
|||||||
switch (messageType) {
|
switch (messageType) {
|
||||||
case THING_CREATED:
|
case THING_CREATED:
|
||||||
setTenantSecurityContext(tenant);
|
setTenantSecurityContext(tenant);
|
||||||
registerTarget(message);
|
registerTarget(message, virtualHost);
|
||||||
break;
|
break;
|
||||||
case EVENT:
|
case EVENT:
|
||||||
setTenantSecurityContext(tenant);
|
setTenantSecurityContext(tenant);
|
||||||
@@ -153,8 +161,8 @@ public class AmqpMessageHandlerService {
|
|||||||
final String sha1 = secruityToken.getSha1();
|
final String sha1 = secruityToken.getSha1();
|
||||||
try {
|
try {
|
||||||
SecurityContextHolder.getContext().setAuthentication(authenticationManager.doAuthenticate(secruityToken));
|
SecurityContextHolder.getContext().setAuthentication(authenticationManager.doAuthenticate(secruityToken));
|
||||||
final LocalArtifact localArtifact = artifactManagement.findFirstLocalArtifactsBySHA1(secruityToken
|
final LocalArtifact localArtifact = artifactManagement
|
||||||
.getSha1());
|
.findFirstLocalArtifactsBySHA1(secruityToken.getSha1());
|
||||||
if (localArtifact == null) {
|
if (localArtifact == null) {
|
||||||
throw new EntityNotFoundException();
|
throw new EntityNotFoundException();
|
||||||
}
|
}
|
||||||
@@ -177,9 +185,9 @@ public class AmqpMessageHandlerService {
|
|||||||
final String downloadId = UUID.randomUUID().toString();
|
final String downloadId = UUID.randomUUID().toString();
|
||||||
final DownloadArtifactCache downloadCache = new DownloadArtifactCache(DownloadType.BY_SHA1, sha1);
|
final DownloadArtifactCache downloadCache = new DownloadArtifactCache(DownloadType.BY_SHA1, sha1);
|
||||||
cache.put(downloadId, downloadCache);
|
cache.put(downloadId, downloadCache);
|
||||||
authentificationResponse.setDownloadUrl(UriComponentsBuilder
|
authentificationResponse
|
||||||
.fromUri(hostnameResolver.resolveHostname().toURI()).path("/api/v1/downloadserver/downloadId/")
|
.setDownloadUrl(UriComponentsBuilder.fromUri(hostnameResolver.resolveHostname().toURI())
|
||||||
.path(downloadId).build().toUriString());
|
.path("/api/v1/downloadserver/downloadId/").path(downloadId).build().toUriString());
|
||||||
authentificationResponse.setResponseCode(HttpStatus.OK.value());
|
authentificationResponse.setResponseCode(HttpStatus.OK.value());
|
||||||
} catch (final BadCredentialsException | AuthenticationServiceException | CredentialsExpiredException e) {
|
} catch (final BadCredentialsException | AuthenticationServiceException | CredentialsExpiredException e) {
|
||||||
LOG.error("Login failed", e);
|
LOG.error("Login failed", e);
|
||||||
@@ -196,7 +204,7 @@ public class AmqpMessageHandlerService {
|
|||||||
authentificationResponse.setMessage(errorMessage);
|
authentificationResponse.setMessage(errorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
return rabbitTemplate.getMessageConverter().toMessage(authentificationResponse, messageProperties);
|
return getMessageConverter().toMessage(authentificationResponse, messageProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Artifact convertDbArtifact(final DbArtifact dbArtifact) {
|
private static Artifact convertDbArtifact(final DbArtifact dbArtifact) {
|
||||||
@@ -207,11 +215,6 @@ public class AmqpMessageHandlerService {
|
|||||||
return artifact;
|
return artifact;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void logAndThrowMessageError(final Message message, final String error) {
|
|
||||||
LOG.error("Error \"{}\" reported by message {}", error, message.getMessageProperties().getMessageId());
|
|
||||||
throw new IllegalArgumentException(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void setSecurityContext(final Authentication authentication) {
|
private static void setSecurityContext(final Authentication authentication) {
|
||||||
final SecurityContextImpl securityContextImpl = new SecurityContextImpl();
|
final SecurityContextImpl securityContextImpl = new SecurityContextImpl();
|
||||||
securityContextImpl.setAuthentication(authentication);
|
securityContextImpl.setAuthentication(authentication);
|
||||||
@@ -219,22 +222,13 @@ public class AmqpMessageHandlerService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void setTenantSecurityContext(final String tenantId) {
|
private static void setTenantSecurityContext(final String tenantId) {
|
||||||
final AnonymousAuthenticationToken authenticationToken = new AnonymousAuthenticationToken(UUID.randomUUID()
|
final AnonymousAuthenticationToken authenticationToken = new AnonymousAuthenticationToken(
|
||||||
.toString(), "AMQP-Controller", Collections.singletonList(new SimpleGrantedAuthority(
|
UUID.randomUUID().toString(), "AMQP-Controller",
|
||||||
SpringEvalExpressions.CONTROLLER_ROLE_ANONYMOUS)));
|
Collections.singletonList(new SimpleGrantedAuthority(SpringEvalExpressions.CONTROLLER_ROLE_ANONYMOUS)));
|
||||||
authenticationToken.setDetails(new TenantAwareAuthenticationDetails(tenantId, true));
|
authenticationToken.setDetails(new TenantAwareAuthenticationDetails(tenantId, true));
|
||||||
setSecurityContext(authenticationToken);
|
setSecurityContext(authenticationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getStringHeaderKey(final Message message, final String key, final String errorMessageIfNull) {
|
|
||||||
final Map<String, Object> header = message.getMessageProperties().getHeaders();
|
|
||||||
final Object value = header.get(key);
|
|
||||||
if (value == null) {
|
|
||||||
logAndThrowMessageError(message, errorMessageIfNull);
|
|
||||||
}
|
|
||||||
return value.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to create a new target or to find the target if it already exists.
|
* Method to create a new target or to find the target if it already exists.
|
||||||
*
|
*
|
||||||
@@ -243,14 +237,15 @@ public class AmqpMessageHandlerService {
|
|||||||
* @param ip
|
* @param ip
|
||||||
* the ip of the target/thing
|
* the ip of the target/thing
|
||||||
*/
|
*/
|
||||||
private void registerTarget(final Message message) {
|
private void registerTarget(final Message message, final String virtualHost) {
|
||||||
final String thingId = getStringHeaderKey(message, MessageHeaderKey.THING_ID, "ThingId is null");
|
final String thingId = getStringHeaderKey(message, MessageHeaderKey.THING_ID, "ThingId is null");
|
||||||
final String replyTo = message.getMessageProperties().getReplyTo();
|
final String replyTo = message.getMessageProperties().getReplyTo();
|
||||||
|
|
||||||
if (StringUtils.isEmpty(replyTo)) {
|
if (StringUtils.isEmpty(replyTo)) {
|
||||||
logAndThrowMessageError(message, "No ReplyTo was set for the createThing Event.");
|
logAndThrowMessageError(message, "No ReplyTo was set for the createThing Event.");
|
||||||
}
|
}
|
||||||
final URI amqpUri = IpUtil.createAmqpUri(replyTo);
|
|
||||||
|
final URI amqpUri = IpUtil.createAmqpUri(virtualHost, replyTo);
|
||||||
final Target target = controllerManagement.findOrRegisterTargetIfItDoesNotexist(thingId, amqpUri);
|
final Target target = controllerManagement.findOrRegisterTargetIfItDoesNotexist(thingId, amqpUri);
|
||||||
LOG.debug("Target {} reported online state.", thingId);
|
LOG.debug("Target {} reported online state.", thingId);
|
||||||
|
|
||||||
@@ -267,8 +262,8 @@ public class AmqpMessageHandlerService {
|
|||||||
final DistributionSet distributionSet = action.getDistributionSet();
|
final DistributionSet distributionSet = action.getDistributionSet();
|
||||||
final List<SoftwareModule> softwareModuleList = controllerManagement
|
final List<SoftwareModule> softwareModuleList = controllerManagement
|
||||||
.findSoftwareModulesByDistributionSet(distributionSet);
|
.findSoftwareModulesByDistributionSet(distributionSet);
|
||||||
eventBus.post(new TargetAssignDistributionSetEvent(target.getOptLockRevision(), target.getTenant(), target
|
eventBus.post(new TargetAssignDistributionSetEvent(target.getOptLockRevision(), target.getTenant(),
|
||||||
.getControllerId(), action.getId(), softwareModuleList, target.getTargetInfo().getAddress()));
|
target.getControllerId(), action.getId(), softwareModuleList, target.getTargetInfo().getAddress()));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,13 +276,11 @@ public class AmqpMessageHandlerService {
|
|||||||
* the topic of the event.
|
* the topic of the event.
|
||||||
*/
|
*/
|
||||||
private void handleIncomingEvent(final Message message, final EventTopic topic) {
|
private void handleIncomingEvent(final Message message, final EventTopic topic) {
|
||||||
switch (topic) {
|
if (EventTopic.UPDATE_ACTION_STATUS.equals(topic)) {
|
||||||
case UPDATE_ACTION_STATUS:
|
|
||||||
updateActionStatus(message);
|
updateActionStatus(message);
|
||||||
return;
|
return;
|
||||||
default:
|
|
||||||
logAndThrowMessageError(message, "Got event without appropriate topic.");
|
|
||||||
}
|
}
|
||||||
|
logAndThrowMessageError(message, "Got event without appropriate topic.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -336,28 +329,24 @@ public class AmqpMessageHandlerService {
|
|||||||
logAndThrowMessageError(message, "Status for action does not exisit.");
|
logAndThrowMessageError(message, "Status for action does not exisit.");
|
||||||
}
|
}
|
||||||
|
|
||||||
Action addUpdateActionStatus;
|
final Action addUpdateActionStatus = getUpdateActionStatus(action, actionStatus);
|
||||||
|
|
||||||
if (!actionStatus.getStatus().equals(Status.CANCELED)) {
|
|
||||||
addUpdateActionStatus = controllerManagement.addUpdateActionStatus(actionStatus, action);
|
|
||||||
} else {
|
|
||||||
addUpdateActionStatus = controllerManagement.addCancelActionStatus(actionStatus, action);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!addUpdateActionStatus.isActive()) {
|
if (!addUpdateActionStatus.isActive()) {
|
||||||
lookIfUpdateAvailable(action.getTarget());
|
lookIfUpdateAvailable(action.getTarget());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private Action getUpdateActionStatus(final Action action, final ActionStatus actionStatus) {
|
||||||
* @param message
|
if (actionStatus.getStatus().equals(Status.CANCELED)) {
|
||||||
* @param actionUpdateStatus
|
return controllerManagement.addCancelActionStatus(actionStatus, action);
|
||||||
* @return
|
}
|
||||||
*/
|
return controllerManagement.addUpdateActionStatus(actionStatus, action);
|
||||||
|
}
|
||||||
|
|
||||||
private Action checkActionExist(final Message message, final ActionUpdateStatus actionUpdateStatus) {
|
private Action checkActionExist(final Message message, final ActionUpdateStatus actionUpdateStatus) {
|
||||||
final Long actionId = actionUpdateStatus.getActionId();
|
final Long actionId = actionUpdateStatus.getActionId();
|
||||||
LOG.debug("Target notifies intermediate about action {} with status {}.", actionId, actionUpdateStatus
|
LOG.debug("Target notifies intermediate about action {} with status {}.", actionId,
|
||||||
.getActionStatus().name());
|
actionUpdateStatus.getActionStatus().name());
|
||||||
|
|
||||||
if (actionId == null) {
|
if (actionId == null) {
|
||||||
logAndThrowMessageError(message, "Invalid message no action id");
|
logAndThrowMessageError(message, "Invalid message no action id");
|
||||||
@@ -366,8 +355,8 @@ public class AmqpMessageHandlerService {
|
|||||||
final Action action = controllerManagement.findActionWithDetails(actionId);
|
final Action action = controllerManagement.findActionWithDetails(actionId);
|
||||||
|
|
||||||
if (action == null) {
|
if (action == null) {
|
||||||
logAndThrowMessageError(message, "Got intermediate notification about action " + actionId
|
logAndThrowMessageError(message,
|
||||||
+ " but action does not exist");
|
"Got intermediate notification about action " + actionId + " but action does not exist");
|
||||||
}
|
}
|
||||||
return action;
|
return action;
|
||||||
}
|
}
|
||||||
@@ -381,38 +370,12 @@ public class AmqpMessageHandlerService {
|
|||||||
// back to running action status
|
// back to running action status
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
logAndThrowMessageError(message, "Cancel Recjected message is not allowed, if action is on state: "
|
logAndThrowMessageError(message,
|
||||||
+ action.getStatus());
|
"Cancel recjected message is not allowed, if action is on state: " + action.getStatus());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private void checkContentTypeJson(final Message message) {
|
||||||
* Is needed to convert a incoming message to is originally object type.
|
|
||||||
*
|
|
||||||
* @param message
|
|
||||||
* the message to convert.
|
|
||||||
* @param clazz
|
|
||||||
* the class of the originally object.
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private <T> T convertMessage(final Message message, final Class<T> clazz) {
|
|
||||||
message.getMessageProperties().getHeaders()
|
|
||||||
.put(AbstractJavaTypeMapper.DEFAULT_CLASSID_FIELD_NAME, clazz.getTypeName());
|
|
||||||
return (T) rabbitTemplate.getMessageConverter().fromMessage(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is needed to verify if an incoming message has the content type json.
|
|
||||||
*
|
|
||||||
* @param message
|
|
||||||
* the to verify
|
|
||||||
* @param contentType
|
|
||||||
* the content type
|
|
||||||
* @return true if the content type has json, false it not.
|
|
||||||
*/
|
|
||||||
|
|
||||||
private static void checkContentTypeJson(final Message message) {
|
|
||||||
final MessageProperties messageProperties = message.getMessageProperties();
|
final MessageProperties messageProperties = message.getMessageProperties();
|
||||||
if (messageProperties.getContentType() != null && messageProperties.getContentType().contains("json")) {
|
if (messageProperties.getContentType() != null && messageProperties.getContentType().contains("json")) {
|
||||||
return;
|
return;
|
||||||
@@ -428,14 +391,6 @@ public class AmqpMessageHandlerService {
|
|||||||
this.hostnameResolver = hostnameResolver;
|
this.hostnameResolver = hostnameResolver;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setRabbitTemplate(final RabbitTemplate rabbitTemplate) {
|
|
||||||
this.rabbitTemplate = rabbitTemplate;
|
|
||||||
}
|
|
||||||
|
|
||||||
MessageConverter getMessageConverter() {
|
|
||||||
return rabbitTemplate.getMessageConverter();
|
|
||||||
}
|
|
||||||
|
|
||||||
void setAuthenticationManager(final AmqpControllerAuthentfication authenticationManager) {
|
void setAuthenticationManager(final AmqpControllerAuthentfication authenticationManager) {
|
||||||
this.authenticationManager = authenticationManager;
|
this.authenticationManager = authenticationManager;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import org.springframework.stereotype.Component;
|
|||||||
@Component
|
@Component
|
||||||
@ConfigurationProperties("hawkbit.dmf.rabbitmq")
|
@ConfigurationProperties("hawkbit.dmf.rabbitmq")
|
||||||
public class AmqpProperties {
|
public class AmqpProperties {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DMF API dead letter queue.
|
* DMF API dead letter queue.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*/
|
||||||
|
package org.eclipse.hawkbit.amqp;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
import org.springframework.amqp.core.Message;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface to send a amqp message.
|
||||||
|
*/
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface AmqpSenderService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send the given message to the given uri. The uri contains the (virtual)
|
||||||
|
* host and exchange e.g amqp://host/exchange.
|
||||||
|
*
|
||||||
|
* @param message
|
||||||
|
* the amqp message
|
||||||
|
* @param uri
|
||||||
|
* the reply to uri
|
||||||
|
*/
|
||||||
|
void sendMessage(Message message, URI uri);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract the exchange from the uri. Default implementation removes the
|
||||||
|
* first /.
|
||||||
|
*
|
||||||
|
* @param amqpUri
|
||||||
|
* the amqp uri
|
||||||
|
* @return the exchange.
|
||||||
|
*/
|
||||||
|
default String extractExchange(final URI amqpUri) {
|
||||||
|
return amqpUri.getPath().substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*/
|
||||||
|
package org.eclipse.hawkbit.amqp;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.amqp.core.Message;
|
||||||
|
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||||
|
import org.springframework.amqp.support.converter.AbstractJavaTypeMapper;
|
||||||
|
import org.springframework.amqp.support.converter.MessageConverter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A base class which provide basis amqp staff.
|
||||||
|
*/
|
||||||
|
public class BaseAmqpService {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(BaseAmqpService.class);
|
||||||
|
private final RabbitTemplate rabbitTemplate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param rabbitTemplate
|
||||||
|
* the rabbit template.
|
||||||
|
*/
|
||||||
|
public BaseAmqpService(final RabbitTemplate rabbitTemplate) {
|
||||||
|
this.rabbitTemplate = rabbitTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clean message properties before sending a message.
|
||||||
|
*
|
||||||
|
* @param message
|
||||||
|
* the message to cleaned up
|
||||||
|
*/
|
||||||
|
protected void cleanMessageHeaderProperties(final Message message) {
|
||||||
|
message.getMessageProperties().getHeaders().remove(AbstractJavaTypeMapper.DEFAULT_CLASSID_FIELD_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is needed to convert a incoming message to is originally object type.
|
||||||
|
*
|
||||||
|
* @param message
|
||||||
|
* the message to convert.
|
||||||
|
* @param clazz
|
||||||
|
* the class of the originally object.
|
||||||
|
* @return the converted object
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
protected <T> T convertMessage(final Message message, final Class<T> clazz) {
|
||||||
|
if (message == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
message.getMessageProperties().getHeaders().put(AbstractJavaTypeMapper.DEFAULT_CLASSID_FIELD_NAME,
|
||||||
|
clazz.getName());
|
||||||
|
return (T) rabbitTemplate.getMessageConverter().fromMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is needed to convert a incoming message to is originally list object
|
||||||
|
* type.
|
||||||
|
*
|
||||||
|
* @param message
|
||||||
|
* the message to convert.
|
||||||
|
* @param clazz
|
||||||
|
* the class of the list content.
|
||||||
|
* @return the list of converted objects
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
protected <T> List<T> convertMessageList(final Message message, final Class<T> clazz) {
|
||||||
|
if (message == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
message.getMessageProperties().getHeaders().put(AbstractJavaTypeMapper.DEFAULT_CLASSID_FIELD_NAME,
|
||||||
|
ArrayList.class.getName());
|
||||||
|
message.getMessageProperties().getHeaders().put(AbstractJavaTypeMapper.DEFAULT_CONTENT_CLASSID_FIELD_NAME,
|
||||||
|
clazz.getName());
|
||||||
|
return (List<T>) rabbitTemplate.getMessageConverter().fromMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MessageConverter getMessageConverter() {
|
||||||
|
return rabbitTemplate.getMessageConverter();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final String getStringHeaderKey(final Message message, final String key,
|
||||||
|
final String errorMessageIfNull) {
|
||||||
|
final Map<String, Object> header = message.getMessageProperties().getHeaders();
|
||||||
|
final Object value = header.get(key);
|
||||||
|
if (value == null) {
|
||||||
|
logAndThrowMessageError(message, errorMessageIfNull);
|
||||||
|
}
|
||||||
|
return value.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final void logAndThrowMessageError(final Message message, final String error) {
|
||||||
|
LOGGER.error("Error \"{}\" reported by message {}", error, message.getMessageProperties().getMessageId());
|
||||||
|
throw new IllegalArgumentException(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected RabbitTemplate getRabbitTemplate() {
|
||||||
|
return rabbitTemplate;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*/
|
||||||
|
package org.eclipse.hawkbit.amqp;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
import org.springframework.amqp.core.Message;
|
||||||
|
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A default implementation for the sender service. The service sends all amqp
|
||||||
|
* message to the configured spring rabbitmq connections. The exchange is
|
||||||
|
* extracted from the uri.
|
||||||
|
*/
|
||||||
|
public class DefaultAmqpSenderService implements AmqpSenderService {
|
||||||
|
|
||||||
|
private final RabbitTemplate internalAmqpTemplate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param internalAmqpTemplate
|
||||||
|
* the amqp template
|
||||||
|
*/
|
||||||
|
public DefaultAmqpSenderService(final RabbitTemplate internalAmqpTemplate) {
|
||||||
|
this.internalAmqpTemplate = internalAmqpTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendMessage(final Message message, final URI uri) {
|
||||||
|
internalAmqpTemplate.send(extractExchange(uri), message);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*/
|
||||||
|
package org.eclipse.hawkbit;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.amqp.AmqpSenderService;
|
||||||
|
import org.eclipse.hawkbit.amqp.DefaultAmqpSenderService;
|
||||||
|
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||||
|
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
|
||||||
|
import org.springframework.amqp.support.converter.MessageConverter;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class AmqpTestConfiguration {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to set the Jackson2JsonMessageConverter.
|
||||||
|
*
|
||||||
|
* @return the Jackson2JsonMessageConverter
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public MessageConverter jsonMessageConverter() {
|
||||||
|
return new Jackson2JsonMessageConverter();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create default amqp sender service bean.
|
||||||
|
*
|
||||||
|
* @param rabbitTemplate
|
||||||
|
*
|
||||||
|
* @return the default amqp sender service bean
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
@Autowired
|
||||||
|
public AmqpSenderService amqpSenderServiceBean(final RabbitTemplate rabbitTemplate) {
|
||||||
|
return new DefaultAmqpSenderService(rabbitTemplate);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -61,11 +61,10 @@ public class AmqpControllerAuthentficationTest {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void before() throws Exception {
|
public void before() throws Exception {
|
||||||
amqpMessageHandlerService = new AmqpMessageHandlerService();
|
|
||||||
messageConverter = new Jackson2JsonMessageConverter();
|
messageConverter = new Jackson2JsonMessageConverter();
|
||||||
final RabbitTemplate rabbitTemplate = new RabbitTemplate();
|
final RabbitTemplate rabbitTemplate = mock(RabbitTemplate.class);
|
||||||
rabbitTemplate.setMessageConverter(messageConverter);
|
when(rabbitTemplate.getMessageConverter()).thenReturn(messageConverter);
|
||||||
amqpMessageHandlerService.setRabbitTemplate(rabbitTemplate);
|
amqpMessageHandlerService = new AmqpMessageHandlerService(rabbitTemplate);
|
||||||
|
|
||||||
authenticationManager = new AmqpControllerAuthentfication();
|
authenticationManager = new AmqpControllerAuthentfication();
|
||||||
authenticationManager.setControllerManagement(mock(ControllerManagement.class));
|
authenticationManager.setControllerManagement(mock(ControllerManagement.class));
|
||||||
@@ -82,7 +81,6 @@ public class AmqpControllerAuthentficationTest {
|
|||||||
final ControllerManagement controllerManagement = mock(ControllerManagement.class);
|
final ControllerManagement controllerManagement = mock(ControllerManagement.class);
|
||||||
when(controllerManagement.getSecurityTokenByControllerId(anyString())).thenReturn(CONTROLLLER_ID);
|
when(controllerManagement.getSecurityTokenByControllerId(anyString())).thenReturn(CONTROLLLER_ID);
|
||||||
authenticationManager.setControllerManagement(controllerManagement);
|
authenticationManager.setControllerManagement(controllerManagement);
|
||||||
|
|
||||||
amqpMessageHandlerService.setArtifactManagement(mock(ArtifactManagement.class));
|
amqpMessageHandlerService.setArtifactManagement(mock(ArtifactManagement.class));
|
||||||
|
|
||||||
authenticationManager.setTenantAware(new SecurityContextTenantAware());
|
authenticationManager.setTenantAware(new SecurityContextTenantAware());
|
||||||
@@ -143,7 +141,7 @@ public class AmqpControllerAuthentficationTest {
|
|||||||
|
|
||||||
// test
|
// test
|
||||||
final Message onMessage = amqpMessageHandlerService.onMessage(message, MessageType.AUTHENTIFICATION.name(),
|
final Message onMessage = amqpMessageHandlerService.onMessage(message, MessageType.AUTHENTIFICATION.name(),
|
||||||
TENANT);
|
TENANT, "vHost");
|
||||||
|
|
||||||
// verify
|
// verify
|
||||||
final DownloadResponse downloadResponse = (DownloadResponse) messageConverter.fromMessage(onMessage);
|
final DownloadResponse downloadResponse = (DownloadResponse) messageConverter.fromMessage(onMessage);
|
||||||
@@ -165,7 +163,7 @@ public class AmqpControllerAuthentficationTest {
|
|||||||
|
|
||||||
// test
|
// test
|
||||||
final Message onMessage = amqpMessageHandlerService.onMessage(message, MessageType.AUTHENTIFICATION.name(),
|
final Message onMessage = amqpMessageHandlerService.onMessage(message, MessageType.AUTHENTIFICATION.name(),
|
||||||
TENANT);
|
TENANT, "vHost");
|
||||||
|
|
||||||
// verify
|
// verify
|
||||||
final DownloadResponse downloadResponse = (DownloadResponse) messageConverter.fromMessage(onMessage);
|
final DownloadResponse downloadResponse = (DownloadResponse) messageConverter.fromMessage(onMessage);
|
||||||
@@ -187,7 +185,7 @@ public class AmqpControllerAuthentficationTest {
|
|||||||
|
|
||||||
// test
|
// test
|
||||||
final Message onMessage = amqpMessageHandlerService.onMessage(message, MessageType.AUTHENTIFICATION.name(),
|
final Message onMessage = amqpMessageHandlerService.onMessage(message, MessageType.AUTHENTIFICATION.name(),
|
||||||
TENANT);
|
TENANT, "vHost");
|
||||||
|
|
||||||
// verify
|
// verify
|
||||||
final DownloadResponse downloadResponse = (DownloadResponse) messageConverter.fromMessage(onMessage);
|
final DownloadResponse downloadResponse = (DownloadResponse) messageConverter.fromMessage(onMessage);
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import static org.mockito.Matchers.eq;
|
|||||||
import static org.mockito.Mockito.spy;
|
import static org.mockito.Mockito.spy;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -45,7 +46,6 @@ import org.springframework.amqp.core.MessageProperties;
|
|||||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||||
import org.springframework.amqp.support.converter.AbstractJavaTypeMapper;
|
import org.springframework.amqp.support.converter.AbstractJavaTypeMapper;
|
||||||
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
|
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
|
||||||
import org.springframework.amqp.support.converter.MessageConverter;
|
|
||||||
import org.springframework.test.context.ActiveProfiles;
|
import org.springframework.test.context.ActiveProfiles;
|
||||||
|
|
||||||
import ru.yandex.qatools.allure.annotations.Description;
|
import ru.yandex.qatools.allure.annotations.Description;
|
||||||
@@ -59,39 +59,41 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTestWit
|
|||||||
|
|
||||||
private AmqpMessageDispatcherService amqpMessageDispatcherService;
|
private AmqpMessageDispatcherService amqpMessageDispatcherService;
|
||||||
|
|
||||||
private MessageConverter messageConverter;
|
|
||||||
|
|
||||||
private RabbitTemplate rabbitTemplate;
|
private RabbitTemplate rabbitTemplate;
|
||||||
|
|
||||||
|
private DefaultAmqpSenderService senderService;
|
||||||
|
|
||||||
private static final String CONTROLLER_ID = "1";
|
private static final String CONTROLLER_ID = "1";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void before() throws Exception {
|
public void before() throws Exception {
|
||||||
super.before();
|
super.before();
|
||||||
amqpMessageDispatcherService = new AmqpMessageDispatcherService();
|
this.rabbitTemplate = Mockito.mock(RabbitTemplate.class);
|
||||||
|
when(rabbitTemplate.getMessageConverter()).thenReturn(new Jackson2JsonMessageConverter());
|
||||||
|
amqpMessageDispatcherService = new AmqpMessageDispatcherService(rabbitTemplate);
|
||||||
amqpMessageDispatcherService = spy(amqpMessageDispatcherService);
|
amqpMessageDispatcherService = spy(amqpMessageDispatcherService);
|
||||||
messageConverter = new Jackson2JsonMessageConverter();
|
|
||||||
|
senderService = Mockito.mock(DefaultAmqpSenderService.class);
|
||||||
|
amqpMessageDispatcherService.setAmqpSenderService(senderService);
|
||||||
|
|
||||||
final ArtifactUrlHandler artifactUrlHandlerMock = Mockito.mock(ArtifactUrlHandler.class);
|
final ArtifactUrlHandler artifactUrlHandlerMock = Mockito.mock(ArtifactUrlHandler.class);
|
||||||
when(artifactUrlHandlerMock.getUrl(anyString(), any(), anyObject())).thenReturn("http://mockurl");
|
when(artifactUrlHandlerMock.getUrl(anyString(), any(), anyObject())).thenReturn("http://mockurl");
|
||||||
|
|
||||||
this.rabbitTemplate = Mockito.mock(RabbitTemplate.class);
|
|
||||||
when(rabbitTemplate.getMessageConverter()).thenReturn(messageConverter);
|
|
||||||
|
|
||||||
amqpMessageDispatcherService.setRabbitTemplate(rabbitTemplate);
|
|
||||||
amqpMessageDispatcherService.setTenantAware(tenantAware);
|
|
||||||
amqpMessageDispatcherService.setArtifactUrlHandler(artifactUrlHandlerMock);
|
amqpMessageDispatcherService.setArtifactUrlHandler(artifactUrlHandlerMock);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Verfies that download and install event with no software modul works")
|
@Description("Verfies that download and install event with no software modul works")
|
||||||
public void testSendDownloadRequesWithEmptySoftwareModules() {
|
public void testSendDownloadRequesWithEmptySoftwareModules() {
|
||||||
final TargetAssignDistributionSetEvent targetAssignDistributionSetEvent = new TargetAssignDistributionSetEvent(
|
final TargetAssignDistributionSetEvent targetAssignDistributionSetEvent = new TargetAssignDistributionSetEvent(
|
||||||
1L, "default", CONTROLLER_ID, 1l, new ArrayList<SoftwareModule>(), IpUtil.createAmqpUri("mytest"));
|
1L, "default", CONTROLLER_ID, 1l, new ArrayList<SoftwareModule>(),
|
||||||
|
IpUtil.createAmqpUri("vHost", "mytest"));
|
||||||
amqpMessageDispatcherService.targetAssignDistributionSet(targetAssignDistributionSetEvent);
|
amqpMessageDispatcherService.targetAssignDistributionSet(targetAssignDistributionSetEvent);
|
||||||
final Message sendMessage = createArgumentCapture(targetAssignDistributionSetEvent.getTargetAdress().getHost());
|
final Message sendMessage = createArgumentCapture(targetAssignDistributionSetEvent.getTargetAdress());
|
||||||
final DownloadAndUpdateRequest downloadAndUpdateRequest = assertDownloadAndInstallMessage(sendMessage);
|
final DownloadAndUpdateRequest downloadAndUpdateRequest = assertDownloadAndInstallMessage(sendMessage);
|
||||||
assertTrue(downloadAndUpdateRequest.getSoftwareModules().isEmpty());
|
assertTrue("No softwaremmodule should be contained in the request",
|
||||||
|
downloadAndUpdateRequest.getSoftwareModules().isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -100,21 +102,26 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTestWit
|
|||||||
final DistributionSet dsA = TestDataUtil.generateDistributionSet("", softwareManagement,
|
final DistributionSet dsA = TestDataUtil.generateDistributionSet("", softwareManagement,
|
||||||
distributionSetManagement);
|
distributionSetManagement);
|
||||||
final TargetAssignDistributionSetEvent targetAssignDistributionSetEvent = new TargetAssignDistributionSetEvent(
|
final TargetAssignDistributionSetEvent targetAssignDistributionSetEvent = new TargetAssignDistributionSetEvent(
|
||||||
1L, "default", CONTROLLER_ID, 1l, dsA.getModules(), IpUtil.createAmqpUri("mytest"));
|
1L, "default", CONTROLLER_ID, 1l, dsA.getModules(), IpUtil.createAmqpUri("vHost", "mytest"));
|
||||||
amqpMessageDispatcherService.targetAssignDistributionSet(targetAssignDistributionSetEvent);
|
amqpMessageDispatcherService.targetAssignDistributionSet(targetAssignDistributionSetEvent);
|
||||||
final Message sendMessage = createArgumentCapture(targetAssignDistributionSetEvent.getTargetAdress().getHost());
|
final Message sendMessage = createArgumentCapture(targetAssignDistributionSetEvent.getTargetAdress());
|
||||||
final DownloadAndUpdateRequest downloadAndUpdateRequest = assertDownloadAndInstallMessage(sendMessage);
|
final DownloadAndUpdateRequest downloadAndUpdateRequest = assertDownloadAndInstallMessage(sendMessage);
|
||||||
assertEquals(3, downloadAndUpdateRequest.getSoftwareModules().size());
|
assertEquals("Expecting a size of 3 software modules in the reuqest", 3,
|
||||||
|
downloadAndUpdateRequest.getSoftwareModules().size());
|
||||||
for (final org.eclipse.hawkbit.dmf.json.model.SoftwareModule softwareModule : downloadAndUpdateRequest
|
for (final org.eclipse.hawkbit.dmf.json.model.SoftwareModule softwareModule : downloadAndUpdateRequest
|
||||||
.getSoftwareModules()) {
|
.getSoftwareModules()) {
|
||||||
assertTrue(softwareModule.getArtifacts().isEmpty());
|
assertTrue("Artifact list for softwaremodule should be empty", softwareModule.getArtifacts().isEmpty());
|
||||||
for (final SoftwareModule softwareModule2 : dsA.getModules()) {
|
for (final SoftwareModule softwareModule2 : dsA.getModules()) {
|
||||||
assertNotNull(softwareModule.getModuleId());
|
assertNotNull("Sofware module ID should be set", softwareModule.getModuleId());
|
||||||
if (!softwareModule.getModuleId().equals(softwareModule2.getId())) {
|
if (!softwareModule.getModuleId().equals(softwareModule2.getId())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
assertEquals(softwareModule.getModuleType(), softwareModule2.getType().getKey());
|
assertEquals(
|
||||||
assertEquals(softwareModule.getModuleVersion(), softwareModule2.getVersion());
|
"Software module type in event should be the same as the softwaremodule in the distribution set",
|
||||||
|
softwareModule.getModuleType(), softwareModule2.getType().getKey());
|
||||||
|
assertEquals(
|
||||||
|
"Software module version in event should be the same as the softwaremodule in the distribution set",
|
||||||
|
softwareModule.getModuleVersion(), softwareModule2.getVersion());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -134,17 +141,18 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTestWit
|
|||||||
Mockito.when(rabbitTemplate.convertSendAndReceive(any())).thenReturn(receivedList);
|
Mockito.when(rabbitTemplate.convertSendAndReceive(any())).thenReturn(receivedList);
|
||||||
|
|
||||||
final TargetAssignDistributionSetEvent targetAssignDistributionSetEvent = new TargetAssignDistributionSetEvent(
|
final TargetAssignDistributionSetEvent targetAssignDistributionSetEvent = new TargetAssignDistributionSetEvent(
|
||||||
1L, "default", CONTROLLER_ID, 1l, dsA.getModules(), IpUtil.createAmqpUri("mytest"));
|
1L, "default", CONTROLLER_ID, 1l, dsA.getModules(), IpUtil.createAmqpUri("vHost", "mytest"));
|
||||||
amqpMessageDispatcherService.targetAssignDistributionSet(targetAssignDistributionSetEvent);
|
amqpMessageDispatcherService.targetAssignDistributionSet(targetAssignDistributionSetEvent);
|
||||||
final Message sendMessage = createArgumentCapture(targetAssignDistributionSetEvent.getTargetAdress().getHost());
|
final Message sendMessage = createArgumentCapture(targetAssignDistributionSetEvent.getTargetAdress());
|
||||||
final DownloadAndUpdateRequest downloadAndUpdateRequest = assertDownloadAndInstallMessage(sendMessage);
|
final DownloadAndUpdateRequest downloadAndUpdateRequest = assertDownloadAndInstallMessage(sendMessage);
|
||||||
assertEquals(3, downloadAndUpdateRequest.getSoftwareModules().size());
|
assertEquals("DownloadAndUpdateRequest event should contains 3 software modules", 3,
|
||||||
|
downloadAndUpdateRequest.getSoftwareModules().size());
|
||||||
for (final org.eclipse.hawkbit.dmf.json.model.SoftwareModule softwareModule : downloadAndUpdateRequest
|
for (final org.eclipse.hawkbit.dmf.json.model.SoftwareModule softwareModule : downloadAndUpdateRequest
|
||||||
.getSoftwareModules()) {
|
.getSoftwareModules()) {
|
||||||
if (!softwareModule.getModuleId().equals(module.getId())) {
|
if (!softwareModule.getModuleId().equals(module.getId())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
assertFalse(softwareModule.getArtifacts().isEmpty());
|
assertFalse("The software module artifacts should not be empty", softwareModule.getArtifacts().isEmpty());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,11 +160,10 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTestWit
|
|||||||
@Description("Verfies that send cancel event works")
|
@Description("Verfies that send cancel event works")
|
||||||
public void testSendCancelRequest() {
|
public void testSendCancelRequest() {
|
||||||
final CancelTargetAssignmentEvent cancelTargetAssignmentDistributionSetEvent = new CancelTargetAssignmentEvent(
|
final CancelTargetAssignmentEvent cancelTargetAssignmentDistributionSetEvent = new CancelTargetAssignmentEvent(
|
||||||
1L, "default", CONTROLLER_ID, 1l, IpUtil.createAmqpUri("mytest"));
|
1L, "default", CONTROLLER_ID, 1l, IpUtil.createAmqpUri("vHost", "mytest"));
|
||||||
amqpMessageDispatcherService
|
amqpMessageDispatcherService
|
||||||
.targetCancelAssignmentToDistributionSet(cancelTargetAssignmentDistributionSetEvent);
|
.targetCancelAssignmentToDistributionSet(cancelTargetAssignmentDistributionSetEvent);
|
||||||
final Message sendMessage = createArgumentCapture(
|
final Message sendMessage = createArgumentCapture(cancelTargetAssignmentDistributionSetEvent.getTargetAdress());
|
||||||
cancelTargetAssignmentDistributionSetEvent.getTargetAdress().getHost());
|
|
||||||
assertCancelMessage(sendMessage);
|
assertCancelMessage(sendMessage);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -164,8 +171,8 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTestWit
|
|||||||
private void assertCancelMessage(final Message sendMessage) {
|
private void assertCancelMessage(final Message sendMessage) {
|
||||||
assertEventMessage(sendMessage);
|
assertEventMessage(sendMessage);
|
||||||
final Long actionId = convertMessage(sendMessage, Long.class);
|
final Long actionId = convertMessage(sendMessage, Long.class);
|
||||||
assertEquals(actionId, Long.valueOf(1));
|
assertEquals("Action ID should be 1", actionId, Long.valueOf(1));
|
||||||
assertEquals(EventTopic.CANCEL_DOWNLOAD,
|
assertEquals("The topc in the message should be a CANCEL_DOWNLOAD value", EventTopic.CANCEL_DOWNLOAD,
|
||||||
sendMessage.getMessageProperties().getHeaders().get(MessageHeaderKey.TOPIC));
|
sendMessage.getMessageProperties().getHeaders().get(MessageHeaderKey.TOPIC));
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -174,8 +181,9 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTestWit
|
|||||||
assertEventMessage(sendMessage);
|
assertEventMessage(sendMessage);
|
||||||
final DownloadAndUpdateRequest downloadAndUpdateRequest = convertMessage(sendMessage,
|
final DownloadAndUpdateRequest downloadAndUpdateRequest = convertMessage(sendMessage,
|
||||||
DownloadAndUpdateRequest.class);
|
DownloadAndUpdateRequest.class);
|
||||||
assertEquals(downloadAndUpdateRequest.getActionId(), Long.valueOf(1));
|
assertEquals("The action ID of the downloadAndUpdateRequest event shuold be 1",
|
||||||
assertEquals(EventTopic.DOWNLOAD_AND_INSTALL,
|
downloadAndUpdateRequest.getActionId(), Long.valueOf(1));
|
||||||
|
assertEquals("The topic of the event shuold contain DOWNLOAD_AND_INSTALL", EventTopic.DOWNLOAD_AND_INSTALL,
|
||||||
sendMessage.getMessageProperties().getHeaders().get(MessageHeaderKey.TOPIC));
|
sendMessage.getMessageProperties().getHeaders().get(MessageHeaderKey.TOPIC));
|
||||||
return downloadAndUpdateRequest;
|
return downloadAndUpdateRequest;
|
||||||
|
|
||||||
@@ -185,16 +193,19 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTestWit
|
|||||||
* @param sendMessage
|
* @param sendMessage
|
||||||
*/
|
*/
|
||||||
private void assertEventMessage(final Message sendMessage) {
|
private void assertEventMessage(final Message sendMessage) {
|
||||||
assertNotNull(sendMessage);
|
assertNotNull("The message should not be null", sendMessage);
|
||||||
|
|
||||||
assertEquals(CONTROLLER_ID, sendMessage.getMessageProperties().getHeaders().get(MessageHeaderKey.THING_ID));
|
assertEquals("The value of the message header THING_ID should be " + CONTROLLER_ID, CONTROLLER_ID,
|
||||||
assertEquals(MessageType.EVENT, sendMessage.getMessageProperties().getHeaders().get(MessageHeaderKey.TYPE));
|
sendMessage.getMessageProperties().getHeaders().get(MessageHeaderKey.THING_ID));
|
||||||
assertEquals(MessageProperties.CONTENT_TYPE_JSON, sendMessage.getMessageProperties().getContentType());
|
assertEquals("The value of the message header TYPE should be EVENT", MessageType.EVENT,
|
||||||
|
sendMessage.getMessageProperties().getHeaders().get(MessageHeaderKey.TYPE));
|
||||||
|
assertEquals("The content type message should be " + MessageProperties.CONTENT_TYPE_JSON,
|
||||||
|
MessageProperties.CONTENT_TYPE_JSON, sendMessage.getMessageProperties().getContentType());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Message createArgumentCapture(final String exchange) {
|
protected Message createArgumentCapture(final URI uri) {
|
||||||
final ArgumentCaptor<Message> argumentCaptor = ArgumentCaptor.forClass(Message.class);
|
final ArgumentCaptor<Message> argumentCaptor = ArgumentCaptor.forClass(Message.class);
|
||||||
Mockito.verify(amqpMessageDispatcherService).sendMessage(eq(exchange), argumentCaptor.capture());
|
Mockito.verify(senderService).sendMessage(argumentCaptor.capture(), eq(uri));
|
||||||
return argumentCaptor.getValue();
|
return argumentCaptor.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -99,14 +99,15 @@ public class AmqpMessageHandlerServiceTest {
|
|||||||
@Mock
|
@Mock
|
||||||
private EventBus eventBus;
|
private EventBus eventBus;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private RabbitTemplate rabbitTemplate;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void before() throws Exception {
|
public void before() throws Exception {
|
||||||
amqpMessageHandlerService = new AmqpMessageHandlerService();
|
|
||||||
amqpMessageHandlerService.setControllerManagement(controllerManagementMock);
|
|
||||||
messageConverter = new Jackson2JsonMessageConverter();
|
messageConverter = new Jackson2JsonMessageConverter();
|
||||||
final RabbitTemplate rabbitTemplate = new RabbitTemplate();
|
when(rabbitTemplate.getMessageConverter()).thenReturn(messageConverter);
|
||||||
rabbitTemplate.setMessageConverter(messageConverter);
|
amqpMessageHandlerService = new AmqpMessageHandlerService(rabbitTemplate);
|
||||||
amqpMessageHandlerService.setRabbitTemplate(rabbitTemplate);
|
amqpMessageHandlerService.setControllerManagement(controllerManagementMock);
|
||||||
amqpMessageHandlerService.setAuthenticationManager(authenticationManagerMock);
|
amqpMessageHandlerService.setAuthenticationManager(authenticationManagerMock);
|
||||||
amqpMessageHandlerService.setArtifactManagement(artifactManagementMock);
|
amqpMessageHandlerService.setArtifactManagement(artifactManagementMock);
|
||||||
amqpMessageHandlerService.setCache(cacheMock);
|
amqpMessageHandlerService.setCache(cacheMock);
|
||||||
@@ -115,14 +116,16 @@ public class AmqpMessageHandlerServiceTest {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
|
||||||
@Description("Tests not allowed content-type in message")
|
@Description("Tests not allowed content-type in message")
|
||||||
public void testWrongContentType() {
|
public void testWrongContentType() {
|
||||||
final MessageProperties messageProperties = new MessageProperties();
|
final MessageProperties messageProperties = new MessageProperties();
|
||||||
messageProperties.setContentType("xml");
|
messageProperties.setContentType("xml");
|
||||||
final Message message = new Message(new byte[0], messageProperties);
|
final Message message = new Message(new byte[0], messageProperties);
|
||||||
amqpMessageHandlerService.onMessage(message, MessageType.THING_CREATED.name(), TENANT);
|
try {
|
||||||
fail();
|
amqpMessageHandlerService.onMessage(message, MessageType.THING_CREATED.name(), TENANT, "vHost");
|
||||||
|
fail("IllegalArgumentException was excepeted due to worng content type");
|
||||||
|
} catch (final IllegalArgumentException e) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -138,10 +141,11 @@ public class AmqpMessageHandlerServiceTest {
|
|||||||
when(controllerManagementMock.findOrRegisterTargetIfItDoesNotexist(targetIdCaptor.capture(),
|
when(controllerManagementMock.findOrRegisterTargetIfItDoesNotexist(targetIdCaptor.capture(),
|
||||||
uriCaptor.capture())).thenReturn(null);
|
uriCaptor.capture())).thenReturn(null);
|
||||||
|
|
||||||
amqpMessageHandlerService.onMessage(message, MessageType.THING_CREATED.name(), TENANT);
|
amqpMessageHandlerService.onMessage(message, MessageType.THING_CREATED.name(), TENANT, "vHost");
|
||||||
|
|
||||||
assertThat(targetIdCaptor.getValue()).as("Extraxted Thing should be the same").isEqualTo(knownThingId);
|
// verify
|
||||||
assertThat(uriCaptor.getValue().toString()).as("Extraxted Uri should be the same").isEqualTo("amqp://MyTest");
|
assertThat(targetIdCaptor.getValue()).as("Thing id is wrong").isEqualTo(knownThingId);
|
||||||
|
assertThat(uriCaptor.getValue().toString()).as("Uri is not right").isEqualTo("amqp://vHost/MyTest");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,7 +157,7 @@ public class AmqpMessageHandlerServiceTest {
|
|||||||
final Message message = messageConverter.toMessage("", messageProperties);
|
final Message message = messageConverter.toMessage("", messageProperties);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
amqpMessageHandlerService.onMessage(message, MessageType.THING_CREATED.name(), TENANT);
|
amqpMessageHandlerService.onMessage(message, MessageType.THING_CREATED.name(), TENANT, "vHost");
|
||||||
fail("IllegalArgumentException was excepeted since no replyTo header was set");
|
fail("IllegalArgumentException was excepeted since no replyTo header was set");
|
||||||
} catch (final IllegalArgumentException exception) {
|
} catch (final IllegalArgumentException exception) {
|
||||||
// test ok - exception was excepted
|
// test ok - exception was excepted
|
||||||
@@ -167,7 +171,7 @@ public class AmqpMessageHandlerServiceTest {
|
|||||||
final MessageProperties messageProperties = createMessageProperties(MessageType.THING_CREATED);
|
final MessageProperties messageProperties = createMessageProperties(MessageType.THING_CREATED);
|
||||||
final Message message = messageConverter.toMessage(new byte[0], messageProperties);
|
final Message message = messageConverter.toMessage(new byte[0], messageProperties);
|
||||||
try {
|
try {
|
||||||
amqpMessageHandlerService.onMessage(message, MessageType.THING_CREATED.name(), TENANT);
|
amqpMessageHandlerService.onMessage(message, MessageType.THING_CREATED.name(), TENANT, "vHost");
|
||||||
fail("IllegalArgumentException was excepeted since no thingID was set");
|
fail("IllegalArgumentException was excepeted since no thingID was set");
|
||||||
} catch (final IllegalArgumentException exception) {
|
} catch (final IllegalArgumentException exception) {
|
||||||
// test ok - exception was excepted
|
// test ok - exception was excepted
|
||||||
@@ -183,7 +187,7 @@ public class AmqpMessageHandlerServiceTest {
|
|||||||
final Message message = messageConverter.toMessage(new byte[0], messageProperties);
|
final Message message = messageConverter.toMessage(new byte[0], messageProperties);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
amqpMessageHandlerService.onMessage(message, type, TENANT);
|
amqpMessageHandlerService.onMessage(message, type, TENANT, "vHost");
|
||||||
fail("IllegalArgumentException was excepeted due to unknown message type");
|
fail("IllegalArgumentException was excepeted due to unknown message type");
|
||||||
} catch (final IllegalArgumentException exception) {
|
} catch (final IllegalArgumentException exception) {
|
||||||
// test ok - exception was excepted
|
// test ok - exception was excepted
|
||||||
@@ -196,21 +200,21 @@ public class AmqpMessageHandlerServiceTest {
|
|||||||
final MessageProperties messageProperties = createMessageProperties(MessageType.EVENT);
|
final MessageProperties messageProperties = createMessageProperties(MessageType.EVENT);
|
||||||
final Message message = new Message(new byte[0], messageProperties);
|
final Message message = new Message(new byte[0], messageProperties);
|
||||||
try {
|
try {
|
||||||
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT);
|
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, "vHost");
|
||||||
fail();
|
fail("IllegalArgumentException was excepeted due to unknown message type");
|
||||||
} catch (final IllegalArgumentException e) {
|
} catch (final IllegalArgumentException e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
messageProperties.setHeader(MessageHeaderKey.TOPIC, "wrongTopic");
|
messageProperties.setHeader(MessageHeaderKey.TOPIC, "wrongTopic");
|
||||||
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT);
|
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, "vHost");
|
||||||
fail();
|
fail("IllegalArgumentException was excepeted due to unknown topic");
|
||||||
} catch (final IllegalArgumentException e) {
|
} catch (final IllegalArgumentException e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
messageProperties.setHeader(MessageHeaderKey.TOPIC, EventTopic.CANCEL_DOWNLOAD.name());
|
messageProperties.setHeader(MessageHeaderKey.TOPIC, EventTopic.CANCEL_DOWNLOAD.name());
|
||||||
try {
|
try {
|
||||||
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT);
|
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, "vHost");
|
||||||
fail("IllegalArgumentException was excepeted because there was no event topic");
|
fail("IllegalArgumentException was excepeted because there was no event topic");
|
||||||
} catch (final IllegalArgumentException exception) {
|
} catch (final IllegalArgumentException exception) {
|
||||||
// test ok - exception was excepted
|
// test ok - exception was excepted
|
||||||
@@ -229,7 +233,7 @@ public class AmqpMessageHandlerServiceTest {
|
|||||||
messageProperties);
|
messageProperties);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT);
|
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, "vHost");
|
||||||
fail("IllegalArgumentException was excepeted since no action id was set");
|
fail("IllegalArgumentException was excepeted since no action id was set");
|
||||||
} catch (final IllegalArgumentException exception) {
|
} catch (final IllegalArgumentException exception) {
|
||||||
// test ok - exception was excepted
|
// test ok - exception was excepted
|
||||||
@@ -246,7 +250,7 @@ public class AmqpMessageHandlerServiceTest {
|
|||||||
messageProperties);
|
messageProperties);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT);
|
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, "vHost");
|
||||||
fail("IllegalArgumentException was excepeted since no action id was set");
|
fail("IllegalArgumentException was excepeted since no action id was set");
|
||||||
} catch (final IllegalArgumentException exception) {
|
} catch (final IllegalArgumentException exception) {
|
||||||
// test ok - exception was excepted
|
// test ok - exception was excepted
|
||||||
@@ -264,7 +268,7 @@ public class AmqpMessageHandlerServiceTest {
|
|||||||
|
|
||||||
// test
|
// test
|
||||||
final Message onMessage = amqpMessageHandlerService.onMessage(message, MessageType.AUTHENTIFICATION.name(),
|
final Message onMessage = amqpMessageHandlerService.onMessage(message, MessageType.AUTHENTIFICATION.name(),
|
||||||
TENANT);
|
TENANT, "vHost");
|
||||||
|
|
||||||
// verify
|
// verify
|
||||||
final DownloadResponse downloadResponse = (DownloadResponse) messageConverter.fromMessage(onMessage);
|
final DownloadResponse downloadResponse = (DownloadResponse) messageConverter.fromMessage(onMessage);
|
||||||
@@ -288,7 +292,7 @@ public class AmqpMessageHandlerServiceTest {
|
|||||||
|
|
||||||
// test
|
// test
|
||||||
final Message onMessage = amqpMessageHandlerService.onMessage(message, MessageType.AUTHENTIFICATION.name(),
|
final Message onMessage = amqpMessageHandlerService.onMessage(message, MessageType.AUTHENTIFICATION.name(),
|
||||||
TENANT);
|
TENANT, "vHost");
|
||||||
|
|
||||||
// verify
|
// verify
|
||||||
final DownloadResponse downloadResponse = (DownloadResponse) messageConverter.fromMessage(onMessage);
|
final DownloadResponse downloadResponse = (DownloadResponse) messageConverter.fromMessage(onMessage);
|
||||||
@@ -320,7 +324,7 @@ public class AmqpMessageHandlerServiceTest {
|
|||||||
|
|
||||||
// test
|
// test
|
||||||
final Message onMessage = amqpMessageHandlerService.onMessage(message, MessageType.AUTHENTIFICATION.name(),
|
final Message onMessage = amqpMessageHandlerService.onMessage(message, MessageType.AUTHENTIFICATION.name(),
|
||||||
TENANT);
|
TENANT, "vHost");
|
||||||
|
|
||||||
// verify
|
// verify
|
||||||
final DownloadResponse downloadResponse = (DownloadResponse) messageConverter.fromMessage(onMessage);
|
final DownloadResponse downloadResponse = (DownloadResponse) messageConverter.fromMessage(onMessage);
|
||||||
@@ -328,7 +332,8 @@ public class AmqpMessageHandlerServiceTest {
|
|||||||
assertThat(downloadResponse.getResponseCode()).as("Message body response code is wrong")
|
assertThat(downloadResponse.getResponseCode()).as("Message body response code is wrong")
|
||||||
.isEqualTo(HttpStatus.OK.value());
|
.isEqualTo(HttpStatus.OK.value());
|
||||||
assertThat(downloadResponse.getArtifact().getSize()).as("Wrong artifact size in message body").isEqualTo(1L);
|
assertThat(downloadResponse.getArtifact().getSize()).as("Wrong artifact size in message body").isEqualTo(1L);
|
||||||
assertThat(downloadResponse.getDownloadUrl()).startsWith("http://localhost/api/v1/downloadserver/downloadId/");
|
assertThat(downloadResponse.getDownloadUrl()).as("download url is wrong")
|
||||||
|
.startsWith("http://localhost/api/v1/downloadserver/downloadId/");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -355,7 +360,7 @@ public class AmqpMessageHandlerServiceTest {
|
|||||||
messageProperties);
|
messageProperties);
|
||||||
|
|
||||||
// test
|
// test
|
||||||
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT);
|
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, "vHost");
|
||||||
|
|
||||||
// verify
|
// verify
|
||||||
final ArgumentCaptor<TargetAssignDistributionSetEvent> captorTargetAssignDistributionSetEvent = ArgumentCaptor
|
final ArgumentCaptor<TargetAssignDistributionSetEvent> captorTargetAssignDistributionSetEvent = ArgumentCaptor
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ package org.eclipse.hawkbit.util;
|
|||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
import org.eclipse.hawkbit.AbstractIntegrationTestWithMongoDB;
|
import org.eclipse.hawkbit.AbstractIntegrationTestWithMongoDB;
|
||||||
|
import org.eclipse.hawkbit.AmqpTestConfiguration;
|
||||||
|
import org.eclipse.hawkbit.RepositoryApplicationConfiguration;
|
||||||
|
import org.eclipse.hawkbit.TestConfiguration;
|
||||||
import org.eclipse.hawkbit.TestDataUtil;
|
import org.eclipse.hawkbit.TestDataUtil;
|
||||||
import org.eclipse.hawkbit.dmf.json.model.Artifact;
|
import org.eclipse.hawkbit.dmf.json.model.Artifact;
|
||||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||||
@@ -20,6 +23,7 @@ import org.eclipse.hawkbit.tenancy.TenantAware;
|
|||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||||
|
|
||||||
import ru.yandex.qatools.allure.annotations.Description;
|
import ru.yandex.qatools.allure.annotations.Description;
|
||||||
import ru.yandex.qatools.allure.annotations.Features;
|
import ru.yandex.qatools.allure.annotations.Features;
|
||||||
@@ -31,6 +35,8 @@ import ru.yandex.qatools.allure.annotations.Stories;
|
|||||||
*/
|
*/
|
||||||
@Features("Component Tests - Artifact URL Handler")
|
@Features("Component Tests - Artifact URL Handler")
|
||||||
@Stories("Test to generate the artifact download URL")
|
@Stories("Test to generate the artifact download URL")
|
||||||
|
@SpringApplicationConfiguration(classes = { RepositoryApplicationConfiguration.class, TestConfiguration.class,
|
||||||
|
AmqpTestConfiguration.class })
|
||||||
public class PropertyBasedArtifactUrlHandlerTest extends AbstractIntegrationTestWithMongoDB {
|
public class PropertyBasedArtifactUrlHandlerTest extends AbstractIntegrationTestWithMongoDB {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@@ -53,18 +59,22 @@ public class PropertyBasedArtifactUrlHandlerTest extends AbstractIntegrationTest
|
|||||||
@Description("Tests the generation of http download url.")
|
@Description("Tests the generation of http download url.")
|
||||||
public void testHttpUrl() {
|
public void testHttpUrl() {
|
||||||
final String url = urlHandlerProperties.getUrl(controllerId, localArtifact, Artifact.UrlProtocol.HTTP);
|
final String url = urlHandlerProperties.getUrl(controllerId, localArtifact, Artifact.UrlProtocol.HTTP);
|
||||||
assertEquals("http://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId
|
assertEquals("http is build incorrect",
|
||||||
+ "/softwaremodules/" + localArtifact.getSoftwareModule().getId() + "/artifacts/"
|
"http://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId
|
||||||
+ localArtifact.getFilename(), url);
|
+ "/softwaremodules/" + localArtifact.getSoftwareModule().getId() + "/artifacts/"
|
||||||
|
+ localArtifact.getFilename(),
|
||||||
|
url);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Tests the generation of https download url.")
|
@Description("Tests the generation of https download url.")
|
||||||
public void testHttpsUrl() {
|
public void testHttpsUrl() {
|
||||||
final String url = urlHandlerProperties.getUrl(controllerId, localArtifact, Artifact.UrlProtocol.HTTPS);
|
final String url = urlHandlerProperties.getUrl(controllerId, localArtifact, Artifact.UrlProtocol.HTTPS);
|
||||||
assertEquals("https://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId
|
assertEquals("https is build incorrect",
|
||||||
+ "/softwaremodules/" + localArtifact.getSoftwareModule().getId() + "/artifacts/"
|
"https://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId
|
||||||
+ localArtifact.getFilename(), url);
|
+ "/softwaremodules/" + localArtifact.getSoftwareModule().getId() + "/artifacts/"
|
||||||
|
+ localArtifact.getFilename(),
|
||||||
|
url);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -72,7 +82,7 @@ public class PropertyBasedArtifactUrlHandlerTest extends AbstractIntegrationTest
|
|||||||
public void testCoapUrl() {
|
public void testCoapUrl() {
|
||||||
final String url = urlHandlerProperties.getUrl(controllerId, localArtifact, Artifact.UrlProtocol.COAP);
|
final String url = urlHandlerProperties.getUrl(controllerId, localArtifact, Artifact.UrlProtocol.COAP);
|
||||||
|
|
||||||
assertEquals("coap://127.0.0.1:5683/fw/" + tenantAware.getCurrentTenant() + "/" + controllerId + "/sha1/"
|
assertEquals("coap is build incorrect", "coap://127.0.0.1:5683/fw/" + tenantAware.getCurrentTenant() + "/"
|
||||||
+ localArtifact.getSha1Hash(), url);
|
+ controllerId + "/sha1/" + localArtifact.getSha1Hash(), url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -220,7 +220,7 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>com.ethlo.persistence.tools</groupId>
|
<groupId>com.ethlo.persistence.tools</groupId>
|
||||||
<artifactId>eclipselink-maven-plugin</artifactId>
|
<artifactId>eclipselink-maven-plugin</artifactId>
|
||||||
<version>1.1-SNAPSHOT</version>
|
<version>2.6.2</version>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<phase>process-classes</phase>
|
<phase>process-classes</phase>
|
||||||
|
|||||||
@@ -48,7 +48,9 @@ public class MultiTenantJpaTransactionManager extends JpaTransactionManager {
|
|||||||
&& !definition.getName().startsWith(SystemManagement.class.getCanonicalName() + ".deleteTenant")
|
&& !definition.getName().startsWith(SystemManagement.class.getCanonicalName() + ".deleteTenant")
|
||||||
&& !definition.getName()
|
&& !definition.getName()
|
||||||
.startsWith(SystemManagement.class.getCanonicalName() + ".currentTenantKeyGenerator")
|
.startsWith(SystemManagement.class.getCanonicalName() + ".currentTenantKeyGenerator")
|
||||||
&& !definition.getName().startsWith(RolloutManagement.class.getCanonicalName() + ".rolloutScheduler")) {
|
&& !definition.getName().startsWith(RolloutManagement.class.getCanonicalName() + ".rolloutScheduler")
|
||||||
|
&& !definition.getName()
|
||||||
|
.startsWith(SystemManagement.class.getCanonicalName() + ".getOrCreateTenantMetadata")) {
|
||||||
|
|
||||||
final String currentTenant = tenantAware.getCurrentTenant();
|
final String currentTenant = tenantAware.getCurrentTenant();
|
||||||
if (currentTenant == null) {
|
if (currentTenant == null) {
|
||||||
|
|||||||
@@ -21,45 +21,47 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
/**
|
/**
|
||||||
* {@link ActionStatus} repository.
|
* {@link ActionStatus} repository.
|
||||||
*
|
*
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
@Transactional(readOnly = true)
|
@Transactional(readOnly = true)
|
||||||
public interface ActionStatusRepository
|
public interface ActionStatusRepository
|
||||||
extends BaseEntityRepository<ActionStatus, Long>, JpaSpecificationExecutor<ActionStatus> {
|
extends BaseEntityRepository<ActionStatus, Long>, JpaSpecificationExecutor<ActionStatus> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param target
|
* Counts {@link ActionStatus} entries of given {@link Action} in
|
||||||
|
* repository.
|
||||||
|
*
|
||||||
* @param action
|
* @param action
|
||||||
* @return
|
* to count status entries
|
||||||
|
* @return number of actions in repository
|
||||||
*/
|
*/
|
||||||
Long countByAction(Action action);
|
Long countByAction(Action action);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Counts {@link ActionStatus} entries of given {@link Action} with given
|
||||||
|
* {@link Status} in repository.
|
||||||
|
*
|
||||||
* @param action
|
* @param action
|
||||||
* @param retrieved
|
* to count status entries
|
||||||
* @return
|
* @param status
|
||||||
|
* to filter for
|
||||||
|
* @return number of actions in repository
|
||||||
*/
|
*/
|
||||||
Long countByActionAndStatus(Action action, Status retrieved);
|
Long countByActionAndStatus(Action action, Status status);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Retrieves all {@link ActionStatus} entries from repository of given
|
||||||
|
* {@link Action}.
|
||||||
|
*
|
||||||
* @param pageReq
|
* @param pageReq
|
||||||
|
* parameters
|
||||||
* @param action
|
* @param action
|
||||||
* @return
|
* of the status entries
|
||||||
|
* @return pages list of {@link ActionStatus} entries
|
||||||
*/
|
*/
|
||||||
Page<ActionStatus> findByAction(Pageable pageReq, Action action);
|
Page<ActionStatus> findByAction(Pageable pageReq, Action action);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param pageReq
|
* Finds all status updates for the defined action and target including
|
||||||
* @param action
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
Page<ActionStatus> findByActionOrderByIdDesc(Pageable pageReq, Action action);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finds all status updates for the defined action and target order by
|
|
||||||
* {@link ActionStatus#getId()} desc including
|
|
||||||
* {@link ActionStatus#getMessages()}.
|
* {@link ActionStatus#getMessages()}.
|
||||||
*
|
*
|
||||||
* @param pageReq
|
* @param pageReq
|
||||||
@@ -71,6 +73,6 @@ public interface ActionStatusRepository
|
|||||||
* @return Page with found targets
|
* @return Page with found targets
|
||||||
*/
|
*/
|
||||||
@EntityGraph(value = "ActionStatus.withMessages", type = EntityGraphType.LOAD)
|
@EntityGraph(value = "ActionStatus.withMessages", type = EntityGraphType.LOAD)
|
||||||
Page<ActionStatus> getByActionOrderByIdDesc(Pageable pageReq, Action action);
|
Page<ActionStatus> getByAction(Pageable pageReq, Action action);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -925,7 +925,7 @@ public class DeploymentManagement {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* retrieves all the {@link ActionStatus} entries of the given
|
* retrieves all the {@link ActionStatus} entries of the given
|
||||||
* {@link Action} and {@link Target} in the order latest first.
|
* {@link Action} and {@link Target}.
|
||||||
*
|
*
|
||||||
* @param pageReq
|
* @param pageReq
|
||||||
* pagination parameter
|
* pagination parameter
|
||||||
@@ -937,12 +937,12 @@ public class DeploymentManagement {
|
|||||||
* @return the corresponding {@link Page} of {@link ActionStatus}
|
* @return the corresponding {@link Page} of {@link ActionStatus}
|
||||||
*/
|
*/
|
||||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
|
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
|
||||||
public Page<ActionStatus> findActionStatusMessagesByActionInDescOrder(final Pageable pageReq, final Action action,
|
public Page<ActionStatus> findActionStatusByAction(final Pageable pageReq, final Action action,
|
||||||
final boolean withMessages) {
|
final boolean withMessages) {
|
||||||
if (withMessages) {
|
if (withMessages) {
|
||||||
return actionStatusRepository.getByActionOrderByIdDesc(pageReq, action);
|
return actionStatusRepository.getByAction(pageReq, action);
|
||||||
} else {
|
} else {
|
||||||
return actionStatusRepository.findByActionOrderByIdDesc(pageReq, action);
|
return actionStatusRepository.findByAction(pageReq, action);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -150,14 +150,14 @@ public class ArtifactManagementTest extends AbstractIntegrationTestWithMongoDB {
|
|||||||
|
|
||||||
ExternalArtifact result = artifactManagement.createExternalArtifact(provider, null, sm.getId());
|
ExternalArtifact result = artifactManagement.createExternalArtifact(provider, null, sm.getId());
|
||||||
|
|
||||||
assertNotNull(result);
|
assertNotNull("The result of an external artifact should not be null", result);
|
||||||
assertThat(externalArtifactRepository.findAll()).contains(result).hasSize(1);
|
assertThat(externalArtifactRepository.findAll()).contains(result).hasSize(1);
|
||||||
assertThat(result.getSoftwareModule().getId()).isEqualTo(sm.getId());
|
assertThat(result.getSoftwareModule().getId()).isEqualTo(sm.getId());
|
||||||
assertThat(result.getUrl()).isEqualTo("https://fhghdfjgh/{version}/");
|
assertThat(result.getUrl()).isEqualTo("https://fhghdfjgh/{version}/");
|
||||||
assertThat(result.getExternalArtifactProvider()).isEqualTo(provider);
|
assertThat(result.getExternalArtifactProvider()).isEqualTo(provider);
|
||||||
|
|
||||||
result = artifactManagement.createExternalArtifact(provider, "/test", sm2.getId());
|
result = artifactManagement.createExternalArtifact(provider, "/test", sm2.getId());
|
||||||
assertNotNull(result);
|
assertNotNull("The newly created external artifact should not be null", result);
|
||||||
assertThat(externalArtifactRepository.findAll()).contains(result).hasSize(2);
|
assertThat(externalArtifactRepository.findAll()).contains(result).hasSize(2);
|
||||||
assertThat(result.getUrl()).isEqualTo("https://fhghdfjgh/test");
|
assertThat(result.getUrl()).isEqualTo("https://fhghdfjgh/test");
|
||||||
assertThat(result.getExternalArtifactProvider()).isEqualTo(provider);
|
assertThat(result.getExternalArtifactProvider()).isEqualTo(provider);
|
||||||
@@ -176,7 +176,7 @@ public class ArtifactManagementTest extends AbstractIntegrationTestWithMongoDB {
|
|||||||
"https://fhghdfjgh", "/{version}/");
|
"https://fhghdfjgh", "/{version}/");
|
||||||
|
|
||||||
final ExternalArtifact result = artifactManagement.createExternalArtifact(provider, null, sm.getId());
|
final ExternalArtifact result = artifactManagement.createExternalArtifact(provider, null, sm.getId());
|
||||||
assertNotNull(result);
|
assertNotNull("The newly created external artifact should not be null", result);
|
||||||
assertThat(externalArtifactRepository.findAll()).contains(result).hasSize(1);
|
assertThat(externalArtifactRepository.findAll()).contains(result).hasSize(1);
|
||||||
|
|
||||||
artifactManagement.deleteExternalArtifact(result.getId());
|
artifactManagement.deleteExternalArtifact(result.getId());
|
||||||
@@ -348,7 +348,7 @@ public class ArtifactManagementTest extends AbstractIntegrationTestWithMongoDB {
|
|||||||
final LocalArtifact result = artifactManagement.createLocalArtifact(new ByteArrayInputStream(random),
|
final LocalArtifact result = artifactManagement.createLocalArtifact(new ByteArrayInputStream(random),
|
||||||
sm.getId(), "file1", false);
|
sm.getId(), "file1", false);
|
||||||
|
|
||||||
assertTrue(IOUtils.contentEquals(new ByteArrayInputStream(random),
|
assertTrue("The stored binary matches the given binary", IOUtils.contentEquals(new ByteArrayInputStream(random),
|
||||||
artifactManagement.loadLocalArtifactBinary(result).getFileInputStream()));
|
artifactManagement.loadLocalArtifactBinary(result).getFileInputStream()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -70,8 +70,8 @@ public class ControllerManagementTest extends AbstractIntegrationTest {
|
|||||||
.isEqualTo(TargetUpdateStatus.IN_SYNC);
|
.isEqualTo(TargetUpdateStatus.IN_SYNC);
|
||||||
|
|
||||||
assertThat(actionStatusRepository.findAll(pageReq).getNumberOfElements()).isEqualTo(3);
|
assertThat(actionStatusRepository.findAll(pageReq).getNumberOfElements()).isEqualTo(3);
|
||||||
assertThat(deploymentManagement.findActionStatusMessagesByActionInDescOrder(pageReq, savedAction, false)
|
assertThat(deploymentManagement.findActionStatusByAction(pageReq, savedAction, false).getNumberOfElements())
|
||||||
.getNumberOfElements()).isEqualTo(3);
|
.isEqualTo(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -766,12 +766,13 @@ public class DeploymentManagementTest extends AbstractIntegrationTest {
|
|||||||
distributionSetManagement.findDistributionSetByIdWithDetails(dsA.getId()).getOptLockRevision());
|
distributionSetManagement.findDistributionSetByIdWithDetails(dsA.getId()).getOptLockRevision());
|
||||||
|
|
||||||
// verifying that the assignment is correct
|
// verifying that the assignment is correct
|
||||||
assertEquals(1, deploymentManagement.findActiveActionsByTarget(targ).size());
|
assertEquals("Active target actions are wrong", 1, deploymentManagement.findActiveActionsByTarget(targ).size());
|
||||||
assertEquals(1, deploymentManagement.findActionsByTarget(targ).size());
|
assertEquals("Target actions are wrong", 1, deploymentManagement.findActionsByTarget(targ).size());
|
||||||
assertEquals(TargetUpdateStatus.PENDING, targ.getTargetInfo().getUpdateStatus());
|
assertEquals("Target status is wrong", TargetUpdateStatus.PENDING, targ.getTargetInfo().getUpdateStatus());
|
||||||
assertEquals(dsA, targ.getAssignedDistributionSet());
|
assertEquals("Assigned ds is wrong", dsA, targ.getAssignedDistributionSet());
|
||||||
assertEquals(dsA, deploymentManagement.findActiveActionsByTarget(targ).get(0).getDistributionSet());
|
assertEquals("Active ds is wrong", dsA,
|
||||||
assertNull(targ.getTargetInfo().getInstalledDistributionSet());
|
deploymentManagement.findActiveActionsByTarget(targ).get(0).getDistributionSet());
|
||||||
|
assertNull("Installed ds should be null", targ.getTargetInfo().getInstalledDistributionSet());
|
||||||
|
|
||||||
final Page<Action> updAct = actionRepository.findByDistributionSet(pageReq, dsA);
|
final Page<Action> updAct = actionRepository.findByDistributionSet(pageReq, dsA);
|
||||||
final Action action = updAct.getContent().get(0);
|
final Action action = updAct.getContent().get(0);
|
||||||
@@ -782,12 +783,8 @@ public class DeploymentManagementTest extends AbstractIntegrationTest {
|
|||||||
targ = targetManagement.findTargetByControllerID(targ.getControllerId());
|
targ = targetManagement.findTargetByControllerID(targ.getControllerId());
|
||||||
|
|
||||||
assertEquals(0, deploymentManagement.findActiveActionsByTarget(targ).size());
|
assertEquals(0, deploymentManagement.findActiveActionsByTarget(targ).size());
|
||||||
// try {
|
|
||||||
assertEquals(1, deploymentManagement.findInActiveActionsByTarget(targ).size());
|
assertEquals(1, deploymentManagement.findInActiveActionsByTarget(targ).size());
|
||||||
// }
|
|
||||||
// catch( final LazyInitializationException ex ) {
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
assertEquals(TargetUpdateStatus.IN_SYNC, targ.getTargetInfo().getUpdateStatus());
|
assertEquals(TargetUpdateStatus.IN_SYNC, targ.getTargetInfo().getUpdateStatus());
|
||||||
assertEquals(dsA, targ.getAssignedDistributionSet());
|
assertEquals(dsA, targ.getAssignedDistributionSet());
|
||||||
assertEquals(dsA, targ.getTargetInfo().getInstalledDistributionSet());
|
assertEquals(dsA, targ.getTargetInfo().getInstalledDistributionSet());
|
||||||
@@ -797,13 +794,15 @@ public class DeploymentManagementTest extends AbstractIntegrationTest {
|
|||||||
|
|
||||||
targ = targs.iterator().next();
|
targ = targs.iterator().next();
|
||||||
|
|
||||||
assertEquals(1, deploymentManagement.findActiveActionsByTarget(targ).size());
|
assertEquals("active actions are wrong", 1, deploymentManagement.findActiveActionsByTarget(targ).size());
|
||||||
assertEquals(TargetUpdateStatus.PENDING,
|
assertEquals("target status is wrong", TargetUpdateStatus.PENDING,
|
||||||
targetManagement.findTargetByControllerID(targ.getControllerId()).getTargetInfo().getUpdateStatus());
|
targetManagement.findTargetByControllerID(targ.getControllerId()).getTargetInfo().getUpdateStatus());
|
||||||
assertEquals(dsB, targ.getAssignedDistributionSet());
|
assertEquals(dsB, targ.getAssignedDistributionSet());
|
||||||
assertEquals(dsA.getId(), targetManagement.findTargetByControllerIDWithDetails(targ.getControllerId())
|
assertEquals("Installed ds is wrong", dsA.getId(),
|
||||||
.getTargetInfo().getInstalledDistributionSet().getId());
|
targetManagement.findTargetByControllerIDWithDetails(targ.getControllerId()).getTargetInfo()
|
||||||
assertEquals(dsB, deploymentManagement.findActiveActionsByTarget(targ).get(0).getDistributionSet());
|
.getInstalledDistributionSet().getId());
|
||||||
|
assertEquals("Active ds is wrong", dsB,
|
||||||
|
deploymentManagement.findActiveActionsByTarget(targ).get(0).getDistributionSet());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -159,10 +159,10 @@ public class SoftwareManagementTest extends AbstractIntegrationTestWithMongoDB {
|
|||||||
public void hardDeleteOfNotAssignedArtifact() {
|
public void hardDeleteOfNotAssignedArtifact() {
|
||||||
|
|
||||||
// [STEP1]: Create SoftwareModuleX with Artifacts
|
// [STEP1]: Create SoftwareModuleX with Artifacts
|
||||||
SoftwareModule unassignedModule = createSoftwareModuleWithArtifacts(osType, "moduleX", "3.0.2", 2);
|
final SoftwareModule unassignedModule = createSoftwareModuleWithArtifacts(osType, "moduleX", "3.0.2", 2);
|
||||||
Iterator<Artifact> artifactsIt = unassignedModule.getArtifacts().iterator();
|
final Iterator<Artifact> artifactsIt = unassignedModule.getArtifacts().iterator();
|
||||||
Artifact artifact1 = artifactsIt.next();
|
final Artifact artifact1 = artifactsIt.next();
|
||||||
Artifact artifact2 = artifactsIt.next();
|
final Artifact artifact2 = artifactsIt.next();
|
||||||
|
|
||||||
// [STEP2]: Delete unassigned SoftwareModule
|
// [STEP2]: Delete unassigned SoftwareModule
|
||||||
softwareManagement.deleteSoftwareModule(unassignedModule);
|
softwareManagement.deleteSoftwareModule(unassignedModule);
|
||||||
@@ -185,7 +185,7 @@ public class SoftwareManagementTest extends AbstractIntegrationTestWithMongoDB {
|
|||||||
public void softDeleteOfAssignedArtifact() {
|
public void softDeleteOfAssignedArtifact() {
|
||||||
|
|
||||||
// Init DistributionSet
|
// Init DistributionSet
|
||||||
DistributionSet disSet = distributionSetManagement
|
final DistributionSet disSet = distributionSetManagement
|
||||||
.createDistributionSet(new DistributionSet("ds1", "v1.0", "test ds", standardDsType, null));
|
.createDistributionSet(new DistributionSet("ds1", "v1.0", "test ds", standardDsType, null));
|
||||||
|
|
||||||
// [STEP1]: Create SoftwareModuleX with ArtifactX
|
// [STEP1]: Create SoftwareModuleX with ArtifactX
|
||||||
@@ -200,14 +200,14 @@ public class SoftwareManagementTest extends AbstractIntegrationTestWithMongoDB {
|
|||||||
// [VERIFY EXPECTED RESULT]:
|
// [VERIFY EXPECTED RESULT]:
|
||||||
// verify: assignedModule is marked as deleted
|
// verify: assignedModule is marked as deleted
|
||||||
assignedModule = softwareManagement.findSoftwareModuleById(assignedModule.getId());
|
assignedModule = softwareManagement.findSoftwareModuleById(assignedModule.getId());
|
||||||
assertTrue(assignedModule.isDeleted());
|
assertTrue("The module should be flagged as deleted", assignedModule.isDeleted());
|
||||||
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0);
|
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0);
|
||||||
assertThat(softwareModuleRepository.findAll()).hasSize(1);
|
assertThat(softwareModuleRepository.findAll()).hasSize(1);
|
||||||
|
|
||||||
// verify: binary data is deleted
|
// verify: binary data is deleted
|
||||||
Iterator<Artifact> artifactsIt = assignedModule.getArtifacts().iterator();
|
final Iterator<Artifact> artifactsIt = assignedModule.getArtifacts().iterator();
|
||||||
Artifact artifact1 = artifactsIt.next();
|
final Artifact artifact1 = artifactsIt.next();
|
||||||
Artifact artifact2 = artifactsIt.next();
|
final Artifact artifact2 = artifactsIt.next();
|
||||||
assertArtfiactNull(artifact1, artifact2);
|
assertArtfiactNull(artifact1, artifact2);
|
||||||
|
|
||||||
// verify: artifact meta data is still available
|
// verify: artifact meta data is still available
|
||||||
@@ -221,7 +221,7 @@ public class SoftwareManagementTest extends AbstractIntegrationTestWithMongoDB {
|
|||||||
|
|
||||||
// Init target and DistributionSet
|
// Init target and DistributionSet
|
||||||
final Target target = targetManagement.createTarget(new Target("test123"));
|
final Target target = targetManagement.createTarget(new Target("test123"));
|
||||||
DistributionSet disSet = distributionSetManagement
|
final DistributionSet disSet = distributionSetManagement
|
||||||
.createDistributionSet(new DistributionSet("ds1", "v1.0", "test ds", standardDsType, null));
|
.createDistributionSet(new DistributionSet("ds1", "v1.0", "test ds", standardDsType, null));
|
||||||
|
|
||||||
// [STEP1]: Create SoftwareModuleX and include the new ArtifactX
|
// [STEP1]: Create SoftwareModuleX and include the new ArtifactX
|
||||||
@@ -242,14 +242,14 @@ public class SoftwareManagementTest extends AbstractIntegrationTestWithMongoDB {
|
|||||||
// [VERIFY EXPECTED RESULT]:
|
// [VERIFY EXPECTED RESULT]:
|
||||||
// verify: assignedModule is marked as deleted
|
// verify: assignedModule is marked as deleted
|
||||||
assignedModule = softwareManagement.findSoftwareModuleById(assignedModule.getId());
|
assignedModule = softwareManagement.findSoftwareModuleById(assignedModule.getId());
|
||||||
assertTrue(assignedModule.isDeleted());
|
assertTrue("The found module should be flagged deleted", assignedModule.isDeleted());
|
||||||
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0);
|
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0);
|
||||||
assertThat(softwareModuleRepository.findAll()).hasSize(1);
|
assertThat(softwareModuleRepository.findAll()).hasSize(1);
|
||||||
|
|
||||||
// verify: binary data is deleted
|
// verify: binary data is deleted
|
||||||
Iterator<Artifact> artifactsIt = assignedModule.getArtifacts().iterator();
|
final Iterator<Artifact> artifactsIt = assignedModule.getArtifacts().iterator();
|
||||||
Artifact artifact1 = artifactsIt.next();
|
final Artifact artifact1 = artifactsIt.next();
|
||||||
Artifact artifact2 = artifactsIt.next();
|
final Artifact artifact2 = artifactsIt.next();
|
||||||
assertArtfiactNull(artifact1, artifact2);
|
assertArtfiactNull(artifact1, artifact2);
|
||||||
|
|
||||||
// verify: artifact meta data is still available
|
// verify: artifact meta data is still available
|
||||||
@@ -265,7 +265,7 @@ public class SoftwareManagementTest extends AbstractIntegrationTestWithMongoDB {
|
|||||||
assertThat(operations.find(new Query())).hasSize(0);
|
assertThat(operations.find(new Query())).hasSize(0);
|
||||||
|
|
||||||
// Init artifact binary data, target and DistributionSets
|
// Init artifact binary data, target and DistributionSets
|
||||||
byte[] source = RandomUtils.nextBytes(1024);
|
final byte[] source = RandomUtils.nextBytes(1024);
|
||||||
|
|
||||||
// [STEP1]: Create SoftwareModuleX and add a new ArtifactX
|
// [STEP1]: Create SoftwareModuleX and add a new ArtifactX
|
||||||
SoftwareModule moduleX = createSoftwareModuleWithArtifacts(osType, "modulex", "v1.0", 0);
|
SoftwareModule moduleX = createSoftwareModuleWithArtifacts(osType, "modulex", "v1.0", 0);
|
||||||
@@ -273,7 +273,7 @@ public class SoftwareManagementTest extends AbstractIntegrationTestWithMongoDB {
|
|||||||
// [STEP2]: Create newArtifactX and add it to SoftwareModuleX
|
// [STEP2]: Create newArtifactX and add it to SoftwareModuleX
|
||||||
artifactManagement.createLocalArtifact(new ByteArrayInputStream(source), moduleX.getId(), "artifactx", false);
|
artifactManagement.createLocalArtifact(new ByteArrayInputStream(source), moduleX.getId(), "artifactx", false);
|
||||||
moduleX = softwareManagement.findSoftwareModuleWithDetails(moduleX.getId());
|
moduleX = softwareManagement.findSoftwareModuleWithDetails(moduleX.getId());
|
||||||
Artifact artifactX = moduleX.getArtifacts().iterator().next();
|
final Artifact artifactX = moduleX.getArtifacts().iterator().next();
|
||||||
|
|
||||||
// [STEP3]: Create SoftwareModuleY and add the same ArtifactX
|
// [STEP3]: Create SoftwareModuleY and add the same ArtifactX
|
||||||
SoftwareModule moduleY = createSoftwareModuleWithArtifacts(osType, "moduley", "v1.0", 0);
|
SoftwareModule moduleY = createSoftwareModuleWithArtifacts(osType, "moduley", "v1.0", 0);
|
||||||
@@ -281,7 +281,7 @@ public class SoftwareManagementTest extends AbstractIntegrationTestWithMongoDB {
|
|||||||
// [STEP4]: Assign the same ArtifactX to SoftwareModuleY
|
// [STEP4]: Assign the same ArtifactX to SoftwareModuleY
|
||||||
artifactManagement.createLocalArtifact(new ByteArrayInputStream(source), moduleY.getId(), "artifactx", false);
|
artifactManagement.createLocalArtifact(new ByteArrayInputStream(source), moduleY.getId(), "artifactx", false);
|
||||||
moduleY = softwareManagement.findSoftwareModuleWithDetails(moduleY.getId());
|
moduleY = softwareManagement.findSoftwareModuleWithDetails(moduleY.getId());
|
||||||
Artifact artifactY = moduleY.getArtifacts().iterator().next();
|
final Artifact artifactY = moduleY.getArtifacts().iterator().next();
|
||||||
|
|
||||||
// verify: that only one entry was created in mongoDB
|
// verify: that only one entry was created in mongoDB
|
||||||
assertThat(operations.find(new Query())).hasSize(1);
|
assertThat(operations.find(new Query())).hasSize(1);
|
||||||
@@ -325,14 +325,14 @@ public class SoftwareManagementTest extends AbstractIntegrationTestWithMongoDB {
|
|||||||
|
|
||||||
artifactManagement.createLocalArtifact(new ByteArrayInputStream(source), moduleX.getId(), "artifactx", false);
|
artifactManagement.createLocalArtifact(new ByteArrayInputStream(source), moduleX.getId(), "artifactx", false);
|
||||||
moduleX = softwareManagement.findSoftwareModuleWithDetails(moduleX.getId());
|
moduleX = softwareManagement.findSoftwareModuleWithDetails(moduleX.getId());
|
||||||
Artifact artifactX = moduleX.getArtifacts().iterator().next();
|
final Artifact artifactX = moduleX.getArtifacts().iterator().next();
|
||||||
|
|
||||||
// [STEP2]: Create SoftwareModuleY and add the same ArtifactX
|
// [STEP2]: Create SoftwareModuleY and add the same ArtifactX
|
||||||
SoftwareModule moduleY = createSoftwareModuleWithArtifacts(osType, "moduley", "v1.0", 0);
|
SoftwareModule moduleY = createSoftwareModuleWithArtifacts(osType, "moduley", "v1.0", 0);
|
||||||
|
|
||||||
artifactManagement.createLocalArtifact(new ByteArrayInputStream(source), moduleY.getId(), "artifactx", false);
|
artifactManagement.createLocalArtifact(new ByteArrayInputStream(source), moduleY.getId(), "artifactx", false);
|
||||||
moduleY = softwareManagement.findSoftwareModuleWithDetails(moduleY.getId());
|
moduleY = softwareManagement.findSoftwareModuleWithDetails(moduleY.getId());
|
||||||
Artifact artifactY = moduleY.getArtifacts().iterator().next();
|
final Artifact artifactY = moduleY.getArtifacts().iterator().next();
|
||||||
|
|
||||||
// verify: that only one entry was created in mongoDB
|
// verify: that only one entry was created in mongoDB
|
||||||
assertThat(operations.find(new Query())).hasSize(1);
|
assertThat(operations.find(new Query())).hasSize(1);
|
||||||
@@ -358,8 +358,8 @@ public class SoftwareManagementTest extends AbstractIntegrationTestWithMongoDB {
|
|||||||
// verify: SoftwareModuleX and SofwtareModule are marked as deleted
|
// verify: SoftwareModuleX and SofwtareModule are marked as deleted
|
||||||
assertThat(moduleX).isNotNull();
|
assertThat(moduleX).isNotNull();
|
||||||
assertThat(moduleY).isNotNull();
|
assertThat(moduleY).isNotNull();
|
||||||
assertTrue(moduleX.isDeleted());
|
assertTrue("The module should be flagged deleted", moduleX.isDeleted());
|
||||||
assertTrue(moduleY.isDeleted());
|
assertTrue("The module should be flagged deleted", moduleY.isDeleted());
|
||||||
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0);
|
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0);
|
||||||
assertThat(softwareModuleRepository.findAll()).hasSize(2);
|
assertThat(softwareModuleRepository.findAll()).hasSize(2);
|
||||||
|
|
||||||
@@ -370,10 +370,10 @@ public class SoftwareManagementTest extends AbstractIntegrationTestWithMongoDB {
|
|||||||
assertThat(artifactRepository.findOne(artifactY.getId())).isNotNull();
|
assertThat(artifactRepository.findOne(artifactY.getId())).isNotNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
private SoftwareModule createSoftwareModuleWithArtifacts(SoftwareModuleType type, String name, String version,
|
private SoftwareModule createSoftwareModuleWithArtifacts(final SoftwareModuleType type, final String name,
|
||||||
int numberArtifacts) {
|
final String version, final int numberArtifacts) {
|
||||||
|
|
||||||
long countSoftwareModule = softwareModuleRepository.count();
|
final long countSoftwareModule = softwareModuleRepository.count();
|
||||||
|
|
||||||
// create SoftwareModule
|
// create SoftwareModule
|
||||||
SoftwareModule softwareModule = softwareManagement
|
SoftwareModule softwareModule = softwareManagement
|
||||||
@@ -388,7 +388,7 @@ public class SoftwareManagementTest extends AbstractIntegrationTestWithMongoDB {
|
|||||||
softwareModule = softwareManagement.findSoftwareModuleWithDetails(softwareModule.getId());
|
softwareModule = softwareManagement.findSoftwareModuleWithDetails(softwareModule.getId());
|
||||||
assertThat(softwareModuleRepository.findAll()).hasSize((int) countSoftwareModule + 1);
|
assertThat(softwareModuleRepository.findAll()).hasSize((int) countSoftwareModule + 1);
|
||||||
|
|
||||||
List<Artifact> artifacts = softwareModule.getArtifacts();
|
final List<Artifact> artifacts = softwareModule.getArtifacts();
|
||||||
|
|
||||||
assertThat(artifacts).hasSize(numberArtifacts);
|
assertThat(artifacts).hasSize(numberArtifacts);
|
||||||
if (numberArtifacts != 0) {
|
if (numberArtifacts != 0) {
|
||||||
|
|||||||
@@ -96,24 +96,26 @@ public class TargetManagementTest extends AbstractIntegrationTest {
|
|||||||
final TargetTag targetTag = tagManagement.createTargetTag(new TargetTag("Tag1"));
|
final TargetTag targetTag = tagManagement.createTargetTag(new TargetTag("Tag1"));
|
||||||
|
|
||||||
final List<Target> assignedTargets = targetManagement.assignTag(assignTarget, targetTag);
|
final List<Target> assignedTargets = targetManagement.assignTag(assignTarget, targetTag);
|
||||||
assertThat(assignedTargets.size()).isEqualTo(4);
|
assertThat(assignedTargets.size()).as("Assigned targets are wrong").isEqualTo(4);
|
||||||
assignedTargets.forEach(target -> assertThat(target.getTags().size()).isEqualTo(1));
|
assignedTargets.forEach(target -> assertThat(target.getTags().size()).isEqualTo(1));
|
||||||
|
|
||||||
TargetTag findTargetTag = tagManagement.findTargetTag("Tag1");
|
TargetTag findTargetTag = tagManagement.findTargetTag("Tag1");
|
||||||
assertThat(assignedTargets.size()).isEqualTo(findTargetTag.getAssignedToTargets().size());
|
assertThat(assignedTargets.size()).as("Assigned targets are wrong")
|
||||||
|
.isEqualTo(findTargetTag.getAssignedToTargets().size());
|
||||||
|
|
||||||
assertThat(targetManagement.unAssignTag("NotExist", findTargetTag)).isNull();
|
assertThat(targetManagement.unAssignTag("NotExist", findTargetTag)).as("Unassign target does not work")
|
||||||
|
.isNull();
|
||||||
|
|
||||||
final Target unAssignTarget = targetManagement.unAssignTag("targetId123", findTargetTag);
|
final Target unAssignTarget = targetManagement.unAssignTag("targetId123", findTargetTag);
|
||||||
assertThat(unAssignTarget.getControllerId()).isEqualTo("targetId123");
|
assertThat(unAssignTarget.getControllerId()).as("Controller id is wrong").isEqualTo("targetId123");
|
||||||
assertThat(unAssignTarget.getTags().size()).isEqualTo(0);
|
assertThat(unAssignTarget.getTags()).as("Tag size is wrong").isEmpty();
|
||||||
findTargetTag = tagManagement.findTargetTag("Tag1");
|
findTargetTag = tagManagement.findTargetTag("Tag1");
|
||||||
assertThat(findTargetTag.getAssignedToTargets().size()).isEqualTo(3);
|
assertThat(findTargetTag.getAssignedToTargets()).as("Assigned targets are wrong").hasSize(3);
|
||||||
|
|
||||||
final List<Target> unAssignTargets = targetManagement.unAssignAllTargetsByTag(findTargetTag);
|
final List<Target> unAssignTargets = targetManagement.unAssignAllTargetsByTag(findTargetTag);
|
||||||
findTargetTag = tagManagement.findTargetTag("Tag1");
|
findTargetTag = tagManagement.findTargetTag("Tag1");
|
||||||
assertThat(findTargetTag.getAssignedToTargets().size()).isEqualTo(0);
|
assertThat(findTargetTag.getAssignedToTargets()).as("Unassigned targets are wrong").isEmpty();
|
||||||
assertThat(unAssignTargets.size()).isEqualTo(3);
|
assertThat(unAssignTargets).as("Unassigned targets are wrong").hasSize(3);
|
||||||
unAssignTargets.forEach(target -> assertThat(target.getTags().size()).isEqualTo(0));
|
unAssignTargets.forEach(target -> assertThat(target.getTags().size()).isEqualTo(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,14 +123,14 @@ public class TargetManagementTest extends AbstractIntegrationTest {
|
|||||||
@Description("Ensures that targets can deleted e.g. test all cascades")
|
@Description("Ensures that targets can deleted e.g. test all cascades")
|
||||||
public void deleteAndCreateTargets() {
|
public void deleteAndCreateTargets() {
|
||||||
Target target = targetManagement.createTarget(new Target("targetId123"));
|
Target target = targetManagement.createTarget(new Target("targetId123"));
|
||||||
assertThat(targetManagement.countTargetsAll()).isEqualTo(1);
|
assertThat(targetManagement.countTargetsAll()).as("target count is wrong").isEqualTo(1);
|
||||||
targetManagement.deleteTargets(target.getId());
|
targetManagement.deleteTargets(target.getId());
|
||||||
assertThat(targetManagement.countTargetsAll()).isEqualTo(0);
|
assertThat(targetManagement.countTargetsAll()).as("target count is wrong").isEqualTo(0);
|
||||||
|
|
||||||
target = createTargetWithAttributes("4711");
|
target = createTargetWithAttributes("4711");
|
||||||
assertThat(targetManagement.countTargetsAll()).isEqualTo(1);
|
assertThat(targetManagement.countTargetsAll()).as("target count is wrong").isEqualTo(1);
|
||||||
targetManagement.deleteTargets(target.getId());
|
targetManagement.deleteTargets(target.getId());
|
||||||
assertThat(targetManagement.countTargetsAll()).isEqualTo(0);
|
assertThat(targetManagement.countTargetsAll()).as("target count is wrong").isEqualTo(0);
|
||||||
|
|
||||||
final List<Long> targets = new ArrayList<Long>();
|
final List<Long> targets = new ArrayList<Long>();
|
||||||
for (int i = 0; i < 5; i++) {
|
for (int i = 0; i < 5; i++) {
|
||||||
@@ -136,9 +138,9 @@ public class TargetManagementTest extends AbstractIntegrationTest {
|
|||||||
targets.add(target.getId());
|
targets.add(target.getId());
|
||||||
targets.add(createTargetWithAttributes("" + (i * i + 1000)).getId());
|
targets.add(createTargetWithAttributes("" + (i * i + 1000)).getId());
|
||||||
}
|
}
|
||||||
assertThat(targetManagement.countTargetsAll()).isEqualTo(10);
|
assertThat(targetManagement.countTargetsAll()).as("target count is wrong").isEqualTo(10);
|
||||||
targetManagement.deleteTargets(targets.toArray(new Long[targets.size()]));
|
targetManagement.deleteTargets(targets.toArray(new Long[targets.size()]));
|
||||||
assertThat(targetManagement.countTargetsAll()).isEqualTo(0);
|
assertThat(targetManagement.countTargetsAll()).as("target count is wrong").isEqualTo(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Target createTargetWithAttributes(final String controllerId) {
|
private Target createTargetWithAttributes(final String controllerId) {
|
||||||
@@ -150,7 +152,8 @@ public class TargetManagementTest extends AbstractIntegrationTest {
|
|||||||
target = controllerManagament.updateControllerAttributes(controllerId, testData);
|
target = controllerManagament.updateControllerAttributes(controllerId, testData);
|
||||||
|
|
||||||
target = targetManagement.findTargetByControllerIDWithDetails(controllerId);
|
target = targetManagement.findTargetByControllerIDWithDetails(controllerId);
|
||||||
assertThat(target.getTargetInfo().getControllerAttributes()).isEqualTo(testData);
|
assertThat(target.getTargetInfo().getControllerAttributes()).as("Controller Attributes are wrong")
|
||||||
|
.isEqualTo(testData);
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,10 +165,14 @@ public class TargetManagementTest extends AbstractIntegrationTest {
|
|||||||
final DistributionSet set2 = TestDataUtil.generateDistributionSet("test2", softwareManagement,
|
final DistributionSet set2 = TestDataUtil.generateDistributionSet("test2", softwareManagement,
|
||||||
distributionSetManagement);
|
distributionSetManagement);
|
||||||
|
|
||||||
assertThat(targetManagement.countTargetByAssignedDistributionSet(set.getId())).isEqualTo(0);
|
assertThat(targetManagement.countTargetByAssignedDistributionSet(set.getId())).as("Target count is wrong")
|
||||||
assertThat(targetManagement.countTargetByInstalledDistributionSet(set.getId())).isEqualTo(0);
|
.isEqualTo(0);
|
||||||
assertThat(targetManagement.countTargetByAssignedDistributionSet(set2.getId())).isEqualTo(0);
|
assertThat(targetManagement.countTargetByInstalledDistributionSet(set.getId())).as("Target count is wrong")
|
||||||
assertThat(targetManagement.countTargetByInstalledDistributionSet(set2.getId())).isEqualTo(0);
|
.isEqualTo(0);
|
||||||
|
assertThat(targetManagement.countTargetByAssignedDistributionSet(set2.getId())).as("Target count is wrong")
|
||||||
|
.isEqualTo(0);
|
||||||
|
assertThat(targetManagement.countTargetByInstalledDistributionSet(set2.getId())).as("Target count is wrong")
|
||||||
|
.isEqualTo(0);
|
||||||
|
|
||||||
Target target = createTargetWithAttributes("4711");
|
Target target = createTargetWithAttributes("4711");
|
||||||
|
|
||||||
@@ -183,13 +190,19 @@ public class TargetManagementTest extends AbstractIntegrationTest {
|
|||||||
target = targetManagement.findTargetByControllerIDWithDetails("4711");
|
target = targetManagement.findTargetByControllerIDWithDetails("4711");
|
||||||
// read data
|
// read data
|
||||||
|
|
||||||
assertThat(targetManagement.countTargetByAssignedDistributionSet(set.getId())).isEqualTo(0);
|
assertThat(targetManagement.countTargetByAssignedDistributionSet(set.getId())).as("Target count is wrong")
|
||||||
assertThat(targetManagement.countTargetByInstalledDistributionSet(set.getId())).isEqualTo(1);
|
.isEqualTo(0);
|
||||||
assertThat(targetManagement.countTargetByAssignedDistributionSet(set2.getId())).isEqualTo(1);
|
assertThat(targetManagement.countTargetByInstalledDistributionSet(set.getId())).as("Target count is wrong")
|
||||||
assertThat(targetManagement.countTargetByInstalledDistributionSet(set2.getId())).isEqualTo(0);
|
.isEqualTo(1);
|
||||||
assertThat(target.getTargetInfo().getLastTargetQuery()).isGreaterThanOrEqualTo(current);
|
assertThat(targetManagement.countTargetByAssignedDistributionSet(set2.getId())).as("Target count is wrong")
|
||||||
assertThat(target.getAssignedDistributionSet()).isEqualTo(set2);
|
.isEqualTo(1);
|
||||||
assertThat(target.getTargetInfo().getInstalledDistributionSet().getId()).isEqualTo(set.getId());
|
assertThat(targetManagement.countTargetByInstalledDistributionSet(set2.getId())).as("Target count is wrong")
|
||||||
|
.isEqualTo(0);
|
||||||
|
assertThat(target.getTargetInfo().getLastTargetQuery()).as("Target query is not work")
|
||||||
|
.isGreaterThanOrEqualTo(current);
|
||||||
|
assertThat(target.getAssignedDistributionSet()).as("Assigned ds size is wrong").isEqualTo(set2);
|
||||||
|
assertThat(target.getTargetInfo().getInstalledDistributionSet().getId()).as("Installed ds is wrong")
|
||||||
|
.isEqualTo(set.getId());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -373,8 +386,7 @@ public class TargetManagementTest extends AbstractIntegrationTest {
|
|||||||
assertThat(firstSaved.spliterator().getExactSizeIfKnown() - nr2Del).as("Size of splited list")
|
assertThat(firstSaved.spliterator().getExactSizeIfKnown() - nr2Del).as("Size of splited list")
|
||||||
.isEqualTo(allFound.spliterator().getExactSizeIfKnown());
|
.isEqualTo(allFound.spliterator().getExactSizeIfKnown());
|
||||||
|
|
||||||
// verify that all undeleted are still found
|
assertThat(allFound).as("Not all undeleted found").doesNotContain(deletedTargets);
|
||||||
assertThat(allFound).doesNotContain(deletedTargets);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -404,7 +416,7 @@ public class TargetManagementTest extends AbstractIntegrationTest {
|
|||||||
targetInfo = targetInfoRepository.save(targetInfo);
|
targetInfo = targetInfoRepository.save(targetInfo);
|
||||||
}
|
}
|
||||||
final Query qry = entityManager.createNativeQuery("select * from sp_target_attributes ta");
|
final Query qry = entityManager.createNativeQuery("select * from sp_target_attributes ta");
|
||||||
final List result = qry.getResultList();
|
final List<?> result = qry.getResultList();
|
||||||
|
|
||||||
assertThat(attribs.size() * ts.spliterator().getExactSizeIfKnown()).as("Amount of all target attributes")
|
assertThat(attribs.size() * ts.spliterator().getExactSizeIfKnown()).as("Amount of all target attributes")
|
||||||
.isEqualTo(result.size());
|
.isEqualTo(result.size());
|
||||||
@@ -467,7 +479,8 @@ public class TargetManagementTest extends AbstractIntegrationTest {
|
|||||||
final Target tNoAttrib = targetManagement.findTargetByControllerID(tNoAttribl.getControllerId());
|
final Target tNoAttrib = targetManagement.findTargetByControllerID(tNoAttribl.getControllerId());
|
||||||
|
|
||||||
if (tNoAttrib.getControllerId().equals(target.getControllerId())) {
|
if (tNoAttrib.getControllerId().equals(target.getControllerId())) {
|
||||||
assertThat(target.getTargetInfo().getControllerAttributes()).isEmpty();
|
assertThat(target.getTargetInfo().getControllerAttributes())
|
||||||
|
.as("Controller attributes should be empty").isEmpty();
|
||||||
continue restTarget_;
|
continue restTarget_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -479,7 +492,7 @@ public class TargetManagementTest extends AbstractIntegrationTest {
|
|||||||
|
|
||||||
if (tNoAttrib.getControllerId().equals(target.getControllerId())) {
|
if (tNoAttrib.getControllerId().equals(target.getControllerId())) {
|
||||||
assertThat(target.getTargetInfo().getControllerAttributes().keySet().toArray())
|
assertThat(target.getTargetInfo().getControllerAttributes().keySet().toArray())
|
||||||
.doesNotContain(attribs2Del.toArray());
|
.as("Controller attributes are wrong").doesNotContain(attribs2Del.toArray());
|
||||||
continue restTarget_;
|
continue restTarget_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -504,12 +517,14 @@ public class TargetManagementTest extends AbstractIntegrationTest {
|
|||||||
t2 = targetManagement.createTarget(t2);
|
t2 = targetManagement.createTarget(t2);
|
||||||
|
|
||||||
t1 = targetManagement.findTargetByControllerID(t1.getControllerId());
|
t1 = targetManagement.findTargetByControllerID(t1.getControllerId());
|
||||||
assertThat(t1.getTags()).hasSize(noT1Tags).containsAll(t1Tags);
|
assertThat(t1.getTags()).as("Tag size is wrong").hasSize(noT1Tags).containsAll(t1Tags);
|
||||||
assertThat(t1.getTags()).hasSize(noT1Tags).doesNotContain(Iterables.toArray(t2Tags, TargetTag.class));
|
assertThat(t1.getTags()).as("Tag size is wrong").hasSize(noT1Tags)
|
||||||
|
.doesNotContain(Iterables.toArray(t2Tags, TargetTag.class));
|
||||||
|
|
||||||
t2 = targetManagement.findTargetByControllerID(t2.getControllerId());
|
t2 = targetManagement.findTargetByControllerID(t2.getControllerId());
|
||||||
assertThat(t2.getTags()).hasSize(noT2Tags).containsAll(t2Tags);
|
assertThat(t2.getTags()).as("Tag size is wrong").hasSize(noT2Tags).containsAll(t2Tags);
|
||||||
assertThat(t2.getTags()).hasSize(noT2Tags).doesNotContain(Iterables.toArray(t1Tags, TargetTag.class));
|
assertThat(t2.getTags()).as("Tag size is wrong").hasSize(noT2Tags)
|
||||||
|
.doesNotContain(Iterables.toArray(t1Tags, TargetTag.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -531,7 +546,7 @@ public class TargetManagementTest extends AbstractIntegrationTest {
|
|||||||
final TargetTag tagA = tagManagement.createTargetTag(new TargetTag("A"));
|
final TargetTag tagA = tagManagement.createTargetTag(new TargetTag("A"));
|
||||||
final TargetTag tagB = tagManagement.createTargetTag(new TargetTag("B"));
|
final TargetTag tagB = tagManagement.createTargetTag(new TargetTag("B"));
|
||||||
final TargetTag tagC = tagManagement.createTargetTag(new TargetTag("C"));
|
final TargetTag tagC = tagManagement.createTargetTag(new TargetTag("C"));
|
||||||
final TargetTag tagX = tagManagement.createTargetTag(new TargetTag("X"));
|
tagManagement.createTargetTag(new TargetTag("X"));
|
||||||
|
|
||||||
// doing different assignments
|
// doing different assignments
|
||||||
targetManagement.toggleTagAssignment(tagATargets, tagA);
|
targetManagement.toggleTagAssignment(tagATargets, tagA);
|
||||||
@@ -545,7 +560,8 @@ public class TargetManagementTest extends AbstractIntegrationTest {
|
|||||||
targetManagement.toggleTagAssignment(tagABCTargets, tagB);
|
targetManagement.toggleTagAssignment(tagABCTargets, tagB);
|
||||||
targetManagement.toggleTagAssignment(tagABCTargets, tagC);
|
targetManagement.toggleTagAssignment(tagABCTargets, tagC);
|
||||||
|
|
||||||
assertThat(targetManagement.countTargetByFilters(null, null, null, Boolean.FALSE, "X")).isEqualTo(0);
|
assertThat(targetManagement.countTargetByFilters(null, null, null, Boolean.FALSE, "X"))
|
||||||
|
.as("Target count is wrong").isEqualTo(0);
|
||||||
|
|
||||||
// search for targets with tag tagA
|
// search for targets with tag tagA
|
||||||
final List<Target> targetWithTagA = new ArrayList<Target>();
|
final List<Target> targetWithTagA = new ArrayList<Target>();
|
||||||
@@ -575,11 +591,11 @@ public class TargetManagementTest extends AbstractIntegrationTest {
|
|||||||
|
|
||||||
// check again target lists refreshed from DB
|
// check again target lists refreshed from DB
|
||||||
assertThat(targetManagement.countTargetByFilters(null, null, null, Boolean.FALSE, "A"))
|
assertThat(targetManagement.countTargetByFilters(null, null, null, Boolean.FALSE, "A"))
|
||||||
.isEqualTo(targetWithTagA.size());
|
.as("Target count is wrong").isEqualTo(targetWithTagA.size());
|
||||||
assertThat(targetManagement.countTargetByFilters(null, null, null, Boolean.FALSE, "B"))
|
assertThat(targetManagement.countTargetByFilters(null, null, null, Boolean.FALSE, "B"))
|
||||||
.isEqualTo(targetWithTagB.size());
|
.as("Target count is wrong").isEqualTo(targetWithTagB.size());
|
||||||
assertThat(targetManagement.countTargetByFilters(null, null, null, Boolean.FALSE, "C"))
|
assertThat(targetManagement.countTargetByFilters(null, null, null, Boolean.FALSE, "C"))
|
||||||
.isEqualTo(targetWithTagC.size());
|
.as("Target count is wrong").isEqualTo(targetWithTagC.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -656,14 +672,15 @@ public class TargetManagementTest extends AbstractIntegrationTest {
|
|||||||
targetManagement.toggleTagAssignment(targAs, targTagA);
|
targetManagement.toggleTagAssignment(targAs, targTagA);
|
||||||
|
|
||||||
assertThat(targetManagement.findTargetsByControllerIDsWithTags(
|
assertThat(targetManagement.findTargetsByControllerIDsWithTags(
|
||||||
targAs.stream().map(target -> target.getControllerId()).collect(Collectors.toList()))).hasSize(25);
|
targAs.stream().map(target -> target.getControllerId()).collect(Collectors.toList())))
|
||||||
|
.as("Target count is wrong").hasSize(25);
|
||||||
|
|
||||||
// no lazy loading exception and tag correctly assigned
|
// no lazy loading exception and tag correctly assigned
|
||||||
assertThat(targetManagement
|
assertThat(targetManagement
|
||||||
.findTargetsByControllerIDsWithTags(
|
.findTargetsByControllerIDsWithTags(
|
||||||
targAs.stream().map(target -> target.getControllerId()).collect(Collectors.toList()))
|
targAs.stream().map(target -> target.getControllerId()).collect(Collectors.toList()))
|
||||||
.stream().map(target -> target.getTags().contains(targTagA)).collect(Collectors.toList()))
|
.stream().map(target -> target.getTags().contains(targTagA)).collect(Collectors.toList()))
|
||||||
.containsOnly(true);
|
.as("Tags not correctly assigned").containsOnly(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -678,7 +695,7 @@ public class TargetManagementTest extends AbstractIntegrationTest {
|
|||||||
final List<String> findAllTargetIds = findAllTargetIdNames.stream().map(TargetIdName::getControllerId)
|
final List<String> findAllTargetIds = findAllTargetIdNames.stream().map(TargetIdName::getControllerId)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
assertThat(findAllTargetIds).containsOnly(createdTargetIds);
|
assertThat(findAllTargetIds).as("Target list has wrong content").containsOnly(createdTargetIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ public class RSQLActionFieldsTest extends AbstractIntegrationTest {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
assertRSQLQuery(ActionFields.STATUS.name() + "==true", 5);
|
assertRSQLQuery(ActionFields.STATUS.name() + "==true", 5);
|
||||||
fail();
|
fail("Missing expected RSQLParameterUnsupportedFieldException because status cannot be compared with 'true'");
|
||||||
} catch (final RSQLParameterUnsupportedFieldException e) {
|
} catch (final RSQLParameterUnsupportedFieldException e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ public class RSQLDistributionSetFieldTest extends AbstractIntegrationTest {
|
|||||||
final Page<DistributionSet> find = distributionSetManagement.findDistributionSetsAll(
|
final Page<DistributionSet> find = distributionSetManagement.findDistributionSetsAll(
|
||||||
RSQLUtility.parse(rsqlParam, DistributionSetFields.class), new PageRequest(0, 100), false);
|
RSQLUtility.parse(rsqlParam, DistributionSetFields.class), new PageRequest(0, 100), false);
|
||||||
final long countAll = find.getTotalElements();
|
final long countAll = find.getTotalElements();
|
||||||
assertThat(find).isNotNull();
|
assertThat(find).as("Founded entity is should not be null").isNotNull();
|
||||||
assertThat(countAll).isEqualTo(excpectedEntity);
|
assertThat(countAll).as("Founded entity size is wrong").isEqualTo(excpectedEntity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ public class RSQLUtilityTest {
|
|||||||
try {
|
try {
|
||||||
RSQLUtility.parse(wrongRSQL, SoftwareModuleFields.class).toPredicate(baseSoftwareModuleRootMock,
|
RSQLUtility.parse(wrongRSQL, SoftwareModuleFields.class).toPredicate(baseSoftwareModuleRootMock,
|
||||||
criteriaQueryMock, criteriaBuilderMock);
|
criteriaQueryMock, criteriaBuilderMock);
|
||||||
fail();
|
fail("Missing expected RSQLParameterSyntaxException because of wrong RSQL syntax");
|
||||||
} catch (final RSQLParameterSyntaxException e) {
|
} catch (final RSQLParameterSyntaxException e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -75,7 +75,7 @@ public class RSQLUtilityTest {
|
|||||||
try {
|
try {
|
||||||
RSQLUtility.parse(wrongRSQL, SoftwareModuleFields.class).toPredicate(baseSoftwareModuleRootMock,
|
RSQLUtility.parse(wrongRSQL, SoftwareModuleFields.class).toPredicate(baseSoftwareModuleRootMock,
|
||||||
criteriaQueryMock, criteriaBuilderMock);
|
criteriaQueryMock, criteriaBuilderMock);
|
||||||
fail();
|
fail("Missing an expected RSQLParameterUnsupportedFieldException because of unknown RSQL field");
|
||||||
} catch (final RSQLParameterUnsupportedFieldException e) {
|
} catch (final RSQLParameterUnsupportedFieldException e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,7 +87,7 @@ public class RSQLUtilityTest {
|
|||||||
try {
|
try {
|
||||||
RSQLUtility.parse(wrongRSQL, TargetFields.class).toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock,
|
RSQLUtility.parse(wrongRSQL, TargetFields.class).toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock,
|
||||||
criteriaBuilderMock);
|
criteriaBuilderMock);
|
||||||
fail();
|
fail("Missing expected RSQLParameterSyntaxException because of wrong RSQL syntax");
|
||||||
} catch (final RSQLParameterUnsupportedFieldException e) {
|
} catch (final RSQLParameterUnsupportedFieldException e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,7 +95,7 @@ public class RSQLUtilityTest {
|
|||||||
try {
|
try {
|
||||||
RSQLUtility.parse(wrongRSQL, TargetFields.class).toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock,
|
RSQLUtility.parse(wrongRSQL, TargetFields.class).toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock,
|
||||||
criteriaBuilderMock);
|
criteriaBuilderMock);
|
||||||
fail();
|
fail("Missing expected RSQLParameterSyntaxException because of wrong RSQL syntax");
|
||||||
} catch (final RSQLParameterUnsupportedFieldException e) {
|
} catch (final RSQLParameterUnsupportedFieldException e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,7 +103,7 @@ public class RSQLUtilityTest {
|
|||||||
try {
|
try {
|
||||||
RSQLUtility.parse(wrongRSQL, DistributionSetFields.class).toPredicate(baseSoftwareModuleRootMock,
|
RSQLUtility.parse(wrongRSQL, DistributionSetFields.class).toPredicate(baseSoftwareModuleRootMock,
|
||||||
criteriaQueryMock, criteriaBuilderMock);
|
criteriaQueryMock, criteriaBuilderMock);
|
||||||
fail();
|
fail("Missing expected RSQLParameterSyntaxException because of wrong RSQL syntax");
|
||||||
} catch (final RSQLParameterUnsupportedFieldException e) {
|
} catch (final RSQLParameterUnsupportedFieldException e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,7 +115,7 @@ public class RSQLUtilityTest {
|
|||||||
try {
|
try {
|
||||||
RSQLUtility.parse(wrongRSQL, TargetFields.class).toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock,
|
RSQLUtility.parse(wrongRSQL, TargetFields.class).toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock,
|
||||||
criteriaBuilderMock);
|
criteriaBuilderMock);
|
||||||
fail();
|
fail("Missing expected RSQLParameterSyntaxException because of wrong RSQL syntax");
|
||||||
} catch (final RSQLParameterUnsupportedFieldException e) {
|
} catch (final RSQLParameterUnsupportedFieldException e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,7 +123,7 @@ public class RSQLUtilityTest {
|
|||||||
try {
|
try {
|
||||||
RSQLUtility.parse(wrongRSQL, TargetFields.class).toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock,
|
RSQLUtility.parse(wrongRSQL, TargetFields.class).toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock,
|
||||||
criteriaBuilderMock);
|
criteriaBuilderMock);
|
||||||
fail();
|
fail("Missing expected RSQLParameterSyntaxException because of wrong RSQL syntax");
|
||||||
} catch (final RSQLParameterUnsupportedFieldException e) {
|
} catch (final RSQLParameterUnsupportedFieldException e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,7 +131,7 @@ public class RSQLUtilityTest {
|
|||||||
try {
|
try {
|
||||||
RSQLUtility.parse(wrongRSQL, TargetFields.class).toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock,
|
RSQLUtility.parse(wrongRSQL, TargetFields.class).toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock,
|
||||||
criteriaBuilderMock);
|
criteriaBuilderMock);
|
||||||
fail();
|
fail("Missing expected RSQLParameterSyntaxException because of wrong RSQL syntax");
|
||||||
} catch (final RSQLParameterUnsupportedFieldException e) {
|
} catch (final RSQLParameterUnsupportedFieldException e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,11 +23,6 @@ import org.springframework.data.domain.Sort.Direction;
|
|||||||
/**
|
/**
|
||||||
* Utility class for for paged body generation.
|
* Utility class for for paged body generation.
|
||||||
*
|
*
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public final class PagingUtility {
|
public final class PagingUtility {
|
||||||
/*
|
/*
|
||||||
@@ -90,8 +85,9 @@ public final class PagingUtility {
|
|||||||
if (sortParam != null) {
|
if (sortParam != null) {
|
||||||
sorting = new Sort(SortUtility.parse(ActionFields.class, sortParam));
|
sorting = new Sort(SortUtility.parse(ActionFields.class, sortParam));
|
||||||
} else {
|
} else {
|
||||||
// default sort
|
// default sort is DESC in case of action to match behavior
|
||||||
sorting = new Sort(Direction.ASC, ActionFields.ID.getFieldName());
|
// of management UI (last entry on top)
|
||||||
|
sorting = new Sort(Direction.DESC, ActionFields.ID.getFieldName());
|
||||||
}
|
}
|
||||||
return sorting;
|
return sorting;
|
||||||
}
|
}
|
||||||
@@ -101,8 +97,9 @@ public final class PagingUtility {
|
|||||||
if (sortParam != null) {
|
if (sortParam != null) {
|
||||||
sorting = new Sort(SortUtility.parse(ActionStatusFields.class, sortParam));
|
sorting = new Sort(SortUtility.parse(ActionStatusFields.class, sortParam));
|
||||||
} else {
|
} else {
|
||||||
// default sort
|
// default sort is DESC in case of action status to match behavior
|
||||||
sorting = new Sort(Direction.ASC, ActionStatusFields.ID.getFieldName());
|
// of management UI (last entry on top)
|
||||||
|
sorting = new Sort(Direction.DESC, ActionStatusFields.ID.getFieldName());
|
||||||
}
|
}
|
||||||
return sorting;
|
return sorting;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,52 +99,6 @@ public class SoftwareModuleResource implements SoftwareModuleRestAPI {
|
|||||||
return new ResponseEntity<>(SoftwareModuleMapper.artifactsToResponse(module.getArtifacts()), HttpStatus.OK);
|
return new ResponseEntity<>(SoftwareModuleMapper.artifactsToResponse(module.getArtifacts()), HttpStatus.OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles the GET request for downloading an artifact.
|
|
||||||
*
|
|
||||||
* @param softwareModuleId
|
|
||||||
* of the parent SoftwareModule
|
|
||||||
* @param artifactId
|
|
||||||
* of the related LocalArtifact
|
|
||||||
* @param servletResponse
|
|
||||||
* of the servlet
|
|
||||||
* @param request
|
|
||||||
* of the client
|
|
||||||
*
|
|
||||||
* @return responseEntity with status ok if successful
|
|
||||||
*/
|
|
||||||
// @RequestMapping(method = RequestMethod.GET, value =
|
|
||||||
// RestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING
|
|
||||||
// + "/{softwareModuleId}/artifacts/{artifactId}/download")
|
|
||||||
// @ResponseBody
|
|
||||||
// public ResponseEntity<Void> downloadArtifact(@PathVariable final Long
|
|
||||||
// softwareModuleId,
|
|
||||||
// @PathVariable final Long artifactId, final HttpServletResponse
|
|
||||||
// servletResponse,
|
|
||||||
// final HttpServletRequest request) {
|
|
||||||
// final SoftwareModule module =
|
|
||||||
// findSoftwareModuleWithExceptionIfNotFound(softwareModuleId, artifactId);
|
|
||||||
//
|
|
||||||
// if (null == module || !module.getLocalArtifact(artifactId).isPresent()) {
|
|
||||||
// return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// final LocalArtifact artifact = module.getLocalArtifact(artifactId).get();
|
|
||||||
// final DbArtifact file =
|
|
||||||
// artifactManagement.loadLocalArtifactBinary(artifact);
|
|
||||||
//
|
|
||||||
// final String ifMatch = request.getHeader("If-Match");
|
|
||||||
// if (ifMatch != null &&
|
|
||||||
// !RestResourceConversionHelper.matchesHttpHeader(ifMatch,
|
|
||||||
// artifact.getSha1Hash())) {
|
|
||||||
// return new ResponseEntity<>(HttpStatus.PRECONDITION_FAILED);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return RestResourceConversionHelper.writeFileResponse(artifact,
|
|
||||||
// servletResponse, request, file);
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResponseEntity<ArtifactRest> getArtifact(@PathVariable final Long softwareModuleId,
|
public ResponseEntity<ArtifactRest> getArtifact(@PathVariable final Long softwareModuleId,
|
||||||
@PathVariable final Long artifactId) {
|
@PathVariable final Long artifactId) {
|
||||||
|
|||||||
@@ -297,8 +297,8 @@ final public class TargetMapper {
|
|||||||
final ActionStatusRest result = new ActionStatusRest();
|
final ActionStatusRest result = new ActionStatusRest();
|
||||||
|
|
||||||
result.setMessages(actionStatus.getMessages());
|
result.setMessages(actionStatus.getMessages());
|
||||||
result.setReportedAt(action.getCreatedAt());
|
result.setReportedAt(actionStatus.getCreatedAt());
|
||||||
result.setStatusId(action.getId());
|
result.setStatusId(actionStatus.getId());
|
||||||
result.setType(getNameOfActionStatusType(actionStatus.getStatus()));
|
result.setType(getNameOfActionStatusType(actionStatus.getStatus()));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -235,7 +235,7 @@ public class TargetResource implements TargetRestApi {
|
|||||||
final int sanitizedLimitParam = PagingUtility.sanitizePageLimitParam(pagingLimitParam);
|
final int sanitizedLimitParam = PagingUtility.sanitizePageLimitParam(pagingLimitParam);
|
||||||
final Sort sorting = PagingUtility.sanitizeActionStatusSortParam(sortParam);
|
final Sort sorting = PagingUtility.sanitizeActionStatusSortParam(sortParam);
|
||||||
|
|
||||||
final Page<ActionStatus> statusList = this.deploymentManagement.findActionStatusMessagesByActionInDescOrder(
|
final Page<ActionStatus> statusList = this.deploymentManagement.findActionStatusByAction(
|
||||||
new OffsetBasedPageRequest(sanitizedOffsetParam, sanitizedLimitParam, sorting), action, true);
|
new OffsetBasedPageRequest(sanitizedOffsetParam, sanitizedLimitParam, sorting), action, true);
|
||||||
|
|
||||||
return new ResponseEntity<>(
|
return new ResponseEntity<>(
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
|||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -49,6 +50,7 @@ import org.eclipse.hawkbit.rest.resource.model.artifact.ArtifactRest;
|
|||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.mock.web.MockMultipartFile;
|
import org.springframework.mock.web.MockMultipartFile;
|
||||||
@@ -69,6 +71,13 @@ import ru.yandex.qatools.allure.annotations.Stories;
|
|||||||
@Stories("Software Module Resource")
|
@Stories("Software Module Resource")
|
||||||
public class SoftwareModuleResourceTest extends AbstractIntegrationTestWithMongoDB {
|
public class SoftwareModuleResourceTest extends AbstractIntegrationTestWithMongoDB {
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void assertPreparationOfRepo() {
|
||||||
|
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).as("no softwaremodule should be founded")
|
||||||
|
.hasSize(0);
|
||||||
|
assertThat(artifactRepository.findAll()).as("no artifacts should be founded").hasSize(0);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Tests the update of software module metadata. It is verfied that only the selected fields for the update are really updated and the modification values are filled (i.e. updated by and at).")
|
@Description("Tests the update of software module metadata. It is verfied that only the selected fields for the update are really updated and the modification values are filled (i.e. updated by and at).")
|
||||||
@WithUser(principal = "smUpdateTester", allSpPermissions = true)
|
@WithUser(principal = "smUpdateTester", allSpPermissions = true)
|
||||||
@@ -81,18 +90,14 @@ public class SoftwareModuleResourceTest extends AbstractIntegrationTestWithMongo
|
|||||||
final String updateVendor = "newVendor1";
|
final String updateVendor = "newVendor1";
|
||||||
final String updateDescription = "newDescription1";
|
final String updateDescription = "newDescription1";
|
||||||
|
|
||||||
final SoftwareModule ah = softwareManagement
|
softwareManagement.createSoftwareModule(new SoftwareModule(appType, "agent-hub", "1.0.1", null, ""));
|
||||||
.createSoftwareModule(new SoftwareModule(appType, "agent-hub", "1.0.1", null, ""));
|
softwareManagement.createSoftwareModule(new SoftwareModule(runtimeType, "oracle-jre", "1.7.2", null, ""));
|
||||||
final SoftwareModule jvm = softwareManagement
|
softwareManagement.createSoftwareModule(new SoftwareModule(osType, "poky", "3.0.2", null, ""));
|
||||||
.createSoftwareModule(new SoftwareModule(runtimeType, "oracle-jre", "1.7.2", null, ""));
|
|
||||||
final SoftwareModule os = softwareManagement
|
|
||||||
.createSoftwareModule(new SoftwareModule(osType, "poky", "3.0.2", null, ""));
|
|
||||||
|
|
||||||
SoftwareModule sm = new SoftwareModule(osType, knownSWName, knownSWVersion, knownSWDescription, knownSWVendor);
|
SoftwareModule sm = new SoftwareModule(osType, knownSWName, knownSWVersion, knownSWDescription, knownSWVendor);
|
||||||
sm = softwareManagement.createSoftwareModule(sm);
|
sm = softwareManagement.createSoftwareModule(sm);
|
||||||
|
|
||||||
assertThat(sm.getName()).isEqualTo(knownSWName);
|
assertThat(sm.getName()).as("Wrong name of the software module").isEqualTo(knownSWName);
|
||||||
assertThat(sm.getName()).isEqualTo(knownSWName);
|
|
||||||
|
|
||||||
final String body = new JSONObject().put("vendor", updateVendor).put("description", updateDescription)
|
final String body = new JSONObject().put("vendor", updateVendor).put("description", updateDescription)
|
||||||
.put("name", "nameShouldNotBeChanged").toString();
|
.put("name", "nameShouldNotBeChanged").toString();
|
||||||
@@ -123,9 +128,6 @@ public class SoftwareModuleResourceTest extends AbstractIntegrationTestWithMongo
|
|||||||
@Test
|
@Test
|
||||||
@Description("Tests the uppload of an artifact binary. The upload is executed and the content checked in the repository for completenes.")
|
@Description("Tests the uppload of an artifact binary. The upload is executed and the content checked in the repository for completenes.")
|
||||||
public void uploadArtifact() throws Exception {
|
public void uploadArtifact() throws Exception {
|
||||||
// prepare repo
|
|
||||||
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0);
|
|
||||||
assertThat(artifactRepository.findAll()).hasSize(0);
|
|
||||||
SoftwareModule sm = new SoftwareModule(osType, "name 1", "version 1", null, null);
|
SoftwareModule sm = new SoftwareModule(osType, "name 1", "version 1", null, null);
|
||||||
sm = softwareManagement.createSoftwareModule(sm);
|
sm = softwareManagement.createSoftwareModule(sm);
|
||||||
assertThat(artifactRepository.findAll()).hasSize(0);
|
assertThat(artifactRepository.findAll()).hasSize(0);
|
||||||
@@ -152,36 +154,41 @@ public class SoftwareModuleResourceTest extends AbstractIntegrationTestWithMongo
|
|||||||
.convertArtifactResponse(mvcResult.getResponse().getContentAsString());
|
.convertArtifactResponse(mvcResult.getResponse().getContentAsString());
|
||||||
final Long artId = ((LocalArtifact) softwareManagement.findSoftwareModuleWithDetails(sm.getId()).getArtifacts()
|
final Long artId = ((LocalArtifact) softwareManagement.findSoftwareModuleWithDetails(sm.getId()).getArtifacts()
|
||||||
.get(0)).getId();
|
.get(0)).getId();
|
||||||
assertThat(artResult.getArtifactId()).isEqualTo(artId);
|
assertThat(artResult.getArtifactId()).as("Wrong artifact id").isEqualTo(artId);
|
||||||
assertThat(JsonPath.compile("$_links.self.href").read(mvcResult.getResponse().getContentAsString()).toString())
|
assertThat(JsonPath.compile("$_links.self.href").read(mvcResult.getResponse().getContentAsString()).toString())
|
||||||
|
.as("Link contains no self url")
|
||||||
.isEqualTo("http://localhost/rest/v1/softwaremodules/" + sm.getId() + "/artifacts/" + artId);
|
.isEqualTo("http://localhost/rest/v1/softwaremodules/" + sm.getId() + "/artifacts/" + artId);
|
||||||
assertThat(
|
assertThat(
|
||||||
JsonPath.compile("$_links.download.href").read(mvcResult.getResponse().getContentAsString()).toString())
|
JsonPath.compile("$_links.download.href").read(mvcResult.getResponse().getContentAsString()).toString())
|
||||||
.isEqualTo("http://localhost/rest/v1/softwaremodules/" + sm.getId() + "/artifacts/" + artId
|
.as("response contains no download url ").isEqualTo("http://localhost/rest/v1/softwaremodules/"
|
||||||
+ "/download");
|
+ sm.getId() + "/artifacts/" + artId + "/download");
|
||||||
|
|
||||||
|
assertArtifact(sm, random);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertArtifact(final SoftwareModule sm, final byte[] random) throws IOException {
|
||||||
// check result in db...
|
// check result in db...
|
||||||
// repo
|
// repo
|
||||||
assertThat(artifactRepository.findAll()).hasSize(1);
|
assertThat(artifactRepository.findAll()).as("Wrong artifact size").hasSize(1);
|
||||||
|
|
||||||
// binary
|
// binary
|
||||||
assertTrue(IOUtils.contentEquals(new ByteArrayInputStream(random),
|
assertTrue("Wrong artifact content",
|
||||||
artifactManagement
|
IOUtils.contentEquals(new ByteArrayInputStream(random),
|
||||||
.loadLocalArtifactBinary((LocalArtifact) softwareManagement
|
artifactManagement
|
||||||
.findSoftwareModuleWithDetails(sm.getId()).getArtifacts().get(0))
|
.loadLocalArtifactBinary((LocalArtifact) softwareManagement
|
||||||
.getFileInputStream()));
|
.findSoftwareModuleWithDetails(sm.getId()).getArtifacts().get(0))
|
||||||
|
.getFileInputStream()));
|
||||||
|
|
||||||
// hashes
|
// hashes
|
||||||
assertThat(artifactManagement.findLocalArtifactByFilename("origFilename").get(0).getSha1Hash())
|
assertThat(artifactManagement.findLocalArtifactByFilename("origFilename").get(0).getSha1Hash())
|
||||||
.isEqualTo(HashGeneratorUtils.generateSHA1(random));
|
.as("Wrong sha1 hash").isEqualTo(HashGeneratorUtils.generateSHA1(random));
|
||||||
|
|
||||||
assertThat(artifactManagement.findLocalArtifactByFilename("origFilename").get(0).getMd5Hash())
|
assertThat(artifactManagement.findLocalArtifactByFilename("origFilename").get(0).getMd5Hash())
|
||||||
.isEqualTo(HashGeneratorUtils.generateMD5(random));
|
.as("Wrong md5 hash").isEqualTo(HashGeneratorUtils.generateMD5(random));
|
||||||
|
|
||||||
// metadata
|
// metadata
|
||||||
assertThat(((LocalArtifact) softwareManagement.findSoftwareModuleWithDetails(sm.getId()).getArtifacts().get(0))
|
assertThat(((LocalArtifact) softwareManagement.findSoftwareModuleWithDetails(sm.getId()).getArtifacts().get(0))
|
||||||
.getFilename()).isEqualTo("origFilename");
|
.getFilename()).as("wrong metadata of the filename").isEqualTo("origFilename");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -203,9 +210,6 @@ public class SoftwareModuleResourceTest extends AbstractIntegrationTestWithMongo
|
|||||||
@Test
|
@Test
|
||||||
@Description("Verfies that the system does not accept identical artifacts uploads for the same software module. Expected response: CONFLICT")
|
@Description("Verfies that the system does not accept identical artifacts uploads for the same software module. Expected response: CONFLICT")
|
||||||
public void duplicateUploadArtifact() throws Exception {
|
public void duplicateUploadArtifact() throws Exception {
|
||||||
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0);
|
|
||||||
assertThat(artifactRepository.findAll()).hasSize(0);
|
|
||||||
|
|
||||||
SoftwareModule sm = new SoftwareModule(osType, "name 1", "version 1", null, null);
|
SoftwareModule sm = new SoftwareModule(osType, "name 1", "version 1", null, null);
|
||||||
sm = softwareManagement.createSoftwareModule(sm);
|
sm = softwareManagement.createSoftwareModule(sm);
|
||||||
|
|
||||||
@@ -228,9 +232,6 @@ public class SoftwareModuleResourceTest extends AbstractIntegrationTestWithMongo
|
|||||||
@Test
|
@Test
|
||||||
@Description("verfies that option to upload artifacts with a custom defined by metadata, i.e. not the file name of the binary itself.")
|
@Description("verfies that option to upload artifacts with a custom defined by metadata, i.e. not the file name of the binary itself.")
|
||||||
public void uploadArtifactWithCustomName() throws Exception {
|
public void uploadArtifactWithCustomName() throws Exception {
|
||||||
// prepare repo
|
|
||||||
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0);
|
|
||||||
assertThat(artifactRepository.findAll()).hasSize(0);
|
|
||||||
SoftwareModule sm = new SoftwareModule(osType, "name 1", "version 1", null, null);
|
SoftwareModule sm = new SoftwareModule(osType, "name 1", "version 1", null, null);
|
||||||
sm = softwareManagement.createSoftwareModule(sm);
|
sm = softwareManagement.createSoftwareModule(sm);
|
||||||
assertThat(artifactRepository.findAll()).hasSize(0);
|
assertThat(artifactRepository.findAll()).hasSize(0);
|
||||||
@@ -245,22 +246,19 @@ public class SoftwareModuleResourceTest extends AbstractIntegrationTestWithMongo
|
|||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated())
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated())
|
||||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||||
.andExpect(jsonPath("$providedFilename", equalTo("customFilename"))).andExpect(status().isCreated());
|
.andExpect(jsonPath("$providedFilename", equalTo("customFilename"))).andExpect(status().isCreated());
|
||||||
;
|
|
||||||
|
|
||||||
// check result in db...
|
// check result in db...
|
||||||
// repo
|
// repo
|
||||||
assertThat(artifactRepository.findAll()).hasSize(1);
|
assertThat(artifactRepository.findAll()).as("Artifact size is wring").hasSize(1);
|
||||||
|
|
||||||
// hashes
|
// hashes
|
||||||
assertThat(artifactManagement.findLocalArtifactByFilename("customFilename")).hasSize(1);
|
assertThat(artifactManagement.findLocalArtifactByFilename("customFilename")).as("Local artifact is wrong")
|
||||||
|
.hasSize(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Verfies that the system refuses upload of an artifact where the provided hash sums do not match. Expected result: BAD REQUEST")
|
@Description("Verfies that the system refuses upload of an artifact where the provided hash sums do not match. Expected result: BAD REQUEST")
|
||||||
public void uploadArtifactWithHashCheck() throws Exception {
|
public void uploadArtifactWithHashCheck() throws Exception {
|
||||||
// prepare repo
|
|
||||||
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0);
|
|
||||||
assertThat(artifactRepository.findAll()).hasSize(0);
|
|
||||||
SoftwareModule sm = new SoftwareModule(osType, "name 1", "version 1", null, null);
|
SoftwareModule sm = new SoftwareModule(osType, "name 1", "version 1", null, null);
|
||||||
sm = softwareManagement.createSoftwareModule(sm);
|
sm = softwareManagement.createSoftwareModule(sm);
|
||||||
assertThat(artifactRepository.findAll()).hasSize(0);
|
assertThat(artifactRepository.findAll()).hasSize(0);
|
||||||
@@ -280,7 +278,8 @@ public class SoftwareModuleResourceTest extends AbstractIntegrationTestWithMongo
|
|||||||
|
|
||||||
// check error result
|
// check error result
|
||||||
ExceptionInfo exceptionInfo = ResourceUtility.convertException(mvcResult.getResponse().getContentAsString());
|
ExceptionInfo exceptionInfo = ResourceUtility.convertException(mvcResult.getResponse().getContentAsString());
|
||||||
assertThat(exceptionInfo.getErrorCode()).isEqualTo(SpServerError.SP_ARTIFACT_UPLOAD_FAILED_SHA1_MATCH.getKey());
|
assertThat(exceptionInfo.getErrorCode()).as("Exception contains wrong error code")
|
||||||
|
.isEqualTo(SpServerError.SP_ARTIFACT_UPLOAD_FAILED_SHA1_MATCH.getKey());
|
||||||
|
|
||||||
// wrong md5
|
// wrong md5
|
||||||
mvcResult = mvc
|
mvcResult = mvc
|
||||||
@@ -290,42 +289,20 @@ public class SoftwareModuleResourceTest extends AbstractIntegrationTestWithMongo
|
|||||||
|
|
||||||
// check error result
|
// check error result
|
||||||
exceptionInfo = ResourceUtility.convertException(mvcResult.getResponse().getContentAsString());
|
exceptionInfo = ResourceUtility.convertException(mvcResult.getResponse().getContentAsString());
|
||||||
assertThat(exceptionInfo.getErrorCode()).isEqualTo(SpServerError.SP_ARTIFACT_UPLOAD_FAILED_MD5_MATCH.getKey());
|
assertThat(exceptionInfo.getErrorCode()).as("Exception contains wrong error code")
|
||||||
|
.isEqualTo(SpServerError.SP_ARTIFACT_UPLOAD_FAILED_MD5_MATCH.getKey());
|
||||||
|
|
||||||
mvc.perform(fileUpload("/rest/v1/softwaremodules/{smId}/artifacts", sm.getId()).file(file)
|
mvc.perform(fileUpload("/rest/v1/softwaremodules/{smId}/artifacts", sm.getId()).file(file)
|
||||||
.param("md5sum", md5sum).param("sha1sum", sha1sum)).andDo(MockMvcResultPrinter.print())
|
.param("md5sum", md5sum).param("sha1sum", sha1sum)).andDo(MockMvcResultPrinter.print())
|
||||||
.andExpect(status().isCreated());
|
.andExpect(status().isCreated());
|
||||||
|
|
||||||
// check result...
|
assertArtifact(sm, random);
|
||||||
// repo
|
|
||||||
assertThat(artifactRepository.findAll()).hasSize(1);
|
|
||||||
|
|
||||||
// binary
|
|
||||||
assertTrue(IOUtils.contentEquals(new ByteArrayInputStream(random),
|
|
||||||
artifactManagement
|
|
||||||
.loadLocalArtifactBinary((LocalArtifact) softwareManagement
|
|
||||||
.findSoftwareModuleWithDetails(sm.getId()).getArtifacts().get(0))
|
|
||||||
.getFileInputStream()));
|
|
||||||
|
|
||||||
// hashes
|
|
||||||
assertThat(artifactManagement.findLocalArtifactByFilename("origFilename").get(0).getSha1Hash())
|
|
||||||
.isEqualTo(HashGeneratorUtils.generateSHA1(random));
|
|
||||||
|
|
||||||
assertThat(artifactManagement.findLocalArtifactByFilename("origFilename").get(0).getMd5Hash())
|
|
||||||
.isEqualTo(md5sum);
|
|
||||||
|
|
||||||
// metadata
|
|
||||||
assertThat(((LocalArtifact) softwareManagement.findSoftwareModuleWithDetails(sm.getId()).getArtifacts().get(0))
|
|
||||||
.getFilename()).isEqualTo("origFilename");
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Tests binary download of an artifact including verfication that the downloaded binary is consistent and that the etag header is as expected identical to the SHA1 hash of the file.")
|
@Description("Tests binary download of an artifact including verfication that the downloaded binary is consistent and that the etag header is as expected identical to the SHA1 hash of the file.")
|
||||||
public void downloadArtifact() throws Exception {
|
public void downloadArtifact() throws Exception {
|
||||||
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0);
|
|
||||||
assertThat(artifactRepository.findAll()).hasSize(0);
|
|
||||||
|
|
||||||
SoftwareModule sm = new SoftwareModule(osType, "name 1", "version 1", null, null);
|
SoftwareModule sm = new SoftwareModule(osType, "name 1", "version 1", null, null);
|
||||||
sm = softwareManagement.createSoftwareModule(sm);
|
sm = softwareManagement.createSoftwareModule(sm);
|
||||||
|
|
||||||
@@ -350,19 +327,16 @@ public class SoftwareModuleResourceTest extends AbstractIntegrationTestWithMongo
|
|||||||
.andExpect(header().string("ETag", artifact2.getSha1Hash()))
|
.andExpect(header().string("ETag", artifact2.getSha1Hash()))
|
||||||
.andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM)).andReturn();
|
.andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM)).andReturn();
|
||||||
|
|
||||||
assertTrue(Arrays.equals(result2.getResponse().getContentAsByteArray(), random));
|
assertTrue("Response has wrong response content",
|
||||||
|
Arrays.equals(result2.getResponse().getContentAsByteArray(), random));
|
||||||
|
|
||||||
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(1);
|
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).as("Softwaremodule size is wrong").hasSize(1);
|
||||||
assertThat(artifactRepository.findAll()).hasSize(2);
|
assertThat(artifactRepository.findAll()).as("Wrong artifact repostiory").hasSize(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Verifies the listing of one defined artifact assigned to a given software module. That includes the artifact metadata and download links.")
|
@Description("Verifies the listing of one defined artifact assigned to a given software module. That includes the artifact metadata and download links.")
|
||||||
public void getArtifact() throws Exception {
|
public void getArtifact() throws Exception {
|
||||||
// check baseline
|
|
||||||
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0);
|
|
||||||
assertThat(artifactRepository.findAll()).hasSize(0);
|
|
||||||
|
|
||||||
// prepare data for test
|
// prepare data for test
|
||||||
SoftwareModule sm = new SoftwareModule(osType, "name 1", "version 1", null, null);
|
SoftwareModule sm = new SoftwareModule(osType, "name 1", "version 1", null, null);
|
||||||
sm = softwareManagement.createSoftwareModule(sm);
|
sm = softwareManagement.createSoftwareModule(sm);
|
||||||
@@ -548,8 +522,6 @@ public class SoftwareModuleResourceTest extends AbstractIntegrationTestWithMongo
|
|||||||
@WithUser(principal = "uploadTester", allSpPermissions = true)
|
@WithUser(principal = "uploadTester", allSpPermissions = true)
|
||||||
@Description("Test retrieval of all software modules the user has access to.")
|
@Description("Test retrieval of all software modules the user has access to.")
|
||||||
public void getSoftwareModules() throws Exception {
|
public void getSoftwareModules() throws Exception {
|
||||||
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0);
|
|
||||||
|
|
||||||
SoftwareModule os = new SoftwareModule(osType, "name1", "version1", "description1", "vendor1");
|
SoftwareModule os = new SoftwareModule(osType, "name1", "version1", "description1", "vendor1");
|
||||||
os = softwareManagement.createSoftwareModule(os);
|
os = softwareManagement.createSoftwareModule(os);
|
||||||
|
|
||||||
@@ -612,14 +584,12 @@ public class SoftwareModuleResourceTest extends AbstractIntegrationTestWithMongo
|
|||||||
.andExpect(jsonPath("$content.[?(@.id==" + ah.getId() + ")][0]._links.self.href",
|
.andExpect(jsonPath("$content.[?(@.id==" + ah.getId() + ")][0]._links.self.href",
|
||||||
equalTo("http://localhost/rest/v1/softwaremodules/" + ah.getId())));
|
equalTo("http://localhost/rest/v1/softwaremodules/" + ah.getId())));
|
||||||
|
|
||||||
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(3);
|
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).as("Softwaremodule size is wrong").hasSize(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Test the various filter parameters, e.g. filter by name or type of the module.")
|
@Description("Test the various filter parameters, e.g. filter by name or type of the module.")
|
||||||
public void getSoftwareModulesWithFilterParameters() throws Exception {
|
public void getSoftwareModulesWithFilterParameters() throws Exception {
|
||||||
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0);
|
|
||||||
|
|
||||||
SoftwareModule os1 = new SoftwareModule(osType, "osName1", "1.0.0", "description1", "vendor1");
|
SoftwareModule os1 = new SoftwareModule(osType, "osName1", "1.0.0", "description1", "vendor1");
|
||||||
os1 = softwareManagement.createSoftwareModule(os1);
|
os1 = softwareManagement.createSoftwareModule(os1);
|
||||||
|
|
||||||
@@ -712,8 +682,6 @@ public class SoftwareModuleResourceTest extends AbstractIntegrationTestWithMongo
|
|||||||
@WithUser(principal = "uploadTester", allSpPermissions = true)
|
@WithUser(principal = "uploadTester", allSpPermissions = true)
|
||||||
@Description("Tests GET request on /rest/v1/softwaremodules/{smId}.")
|
@Description("Tests GET request on /rest/v1/softwaremodules/{smId}.")
|
||||||
public void getSoftareModule() throws Exception {
|
public void getSoftareModule() throws Exception {
|
||||||
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0);
|
|
||||||
|
|
||||||
SoftwareModule os = new SoftwareModule(osType, "name1", "version1", "description1", "vendor1");
|
SoftwareModule os = new SoftwareModule(osType, "name1", "version1", "description1", "vendor1");
|
||||||
os = softwareManagement.createSoftwareModule(os);
|
os = softwareManagement.createSoftwareModule(os);
|
||||||
|
|
||||||
@@ -771,15 +739,13 @@ public class SoftwareModuleResourceTest extends AbstractIntegrationTestWithMongo
|
|||||||
.andExpect(jsonPath("$_links.artifacts.href",
|
.andExpect(jsonPath("$_links.artifacts.href",
|
||||||
equalTo("http://localhost/rest/v1/softwaremodules/" + ah.getId() + "/artifacts")));
|
equalTo("http://localhost/rest/v1/softwaremodules/" + ah.getId() + "/artifacts")));
|
||||||
|
|
||||||
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(3);
|
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).as("Softwaremodule size is wrong").hasSize(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@WithUser(principal = "uploadTester", allSpPermissions = true)
|
@WithUser(principal = "uploadTester", allSpPermissions = true)
|
||||||
@Description("Verfies that the create request actually results in the creation of the modules in the repository.")
|
@Description("Verfies that the create request actually results in the creation of the modules in the repository.")
|
||||||
public void createSoftwareModules() throws JSONException, Exception {
|
public void createSoftwareModules() throws JSONException, Exception {
|
||||||
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0);
|
|
||||||
|
|
||||||
final SoftwareModule os = new SoftwareModule(osType, "name1", "version1", "description1", "vendor1");
|
final SoftwareModule os = new SoftwareModule(osType, "name1", "version1", "description1", "vendor1");
|
||||||
final SoftwareModule jvm = new SoftwareModule(runtimeType, "name2", "version1", "description1", "vendor1");
|
final SoftwareModule jvm = new SoftwareModule(runtimeType, "name2", "version1", "description1", "vendor1");
|
||||||
final SoftwareModule ah = new SoftwareModule(appType, "name3", "version1", "description1", "vendor1");
|
final SoftwareModule ah = new SoftwareModule(appType, "name3", "version1", "description1", "vendor1");
|
||||||
@@ -824,74 +790,75 @@ public class SoftwareModuleResourceTest extends AbstractIntegrationTestWithMongo
|
|||||||
|
|
||||||
assertThat(
|
assertThat(
|
||||||
JsonPath.compile("[0]_links.self.href").read(mvcResult.getResponse().getContentAsString()).toString())
|
JsonPath.compile("[0]_links.self.href").read(mvcResult.getResponse().getContentAsString()).toString())
|
||||||
|
.as("Response contains invalid self href")
|
||||||
.isEqualTo("http://localhost/rest/v1/softwaremodules/" + osCreated.getId());
|
.isEqualTo("http://localhost/rest/v1/softwaremodules/" + osCreated.getId());
|
||||||
assertThat(JsonPath.compile("[0]_links.artifacts.href").read(mvcResult.getResponse().getContentAsString())
|
assertThat(JsonPath.compile("[0]_links.artifacts.href").read(mvcResult.getResponse().getContentAsString())
|
||||||
.toString()).isEqualTo("http://localhost/rest/v1/softwaremodules/" + osCreated.getId() + "/artifacts");
|
.toString()).as("Response contains invalid artifacts href")
|
||||||
|
.isEqualTo("http://localhost/rest/v1/softwaremodules/" + osCreated.getId() + "/artifacts");
|
||||||
|
|
||||||
assertThat(
|
assertThat(
|
||||||
JsonPath.compile("[1]_links.self.href").read(mvcResult.getResponse().getContentAsString()).toString())
|
JsonPath.compile("[1]_links.self.href").read(mvcResult.getResponse().getContentAsString()).toString())
|
||||||
|
.as("Response contains invalid self href")
|
||||||
.isEqualTo("http://localhost/rest/v1/softwaremodules/" + jvmCreated.getId());
|
.isEqualTo("http://localhost/rest/v1/softwaremodules/" + jvmCreated.getId());
|
||||||
assertThat(JsonPath.compile("[1]_links.artifacts.href").read(mvcResult.getResponse().getContentAsString())
|
assertThat(JsonPath.compile("[1]_links.artifacts.href").read(mvcResult.getResponse().getContentAsString())
|
||||||
.toString()).isEqualTo("http://localhost/rest/v1/softwaremodules/" + jvmCreated.getId() + "/artifacts");
|
.toString()).as("Response contains invalid artfacts href")
|
||||||
|
.isEqualTo("http://localhost/rest/v1/softwaremodules/" + jvmCreated.getId() + "/artifacts");
|
||||||
|
|
||||||
assertThat(
|
assertThat(
|
||||||
JsonPath.compile("[2]_links.self.href").read(mvcResult.getResponse().getContentAsString()).toString())
|
JsonPath.compile("[2]_links.self.href").read(mvcResult.getResponse().getContentAsString()).toString())
|
||||||
|
.as("Response contains links self href")
|
||||||
.isEqualTo("http://localhost/rest/v1/softwaremodules/" + ahCreated.getId());
|
.isEqualTo("http://localhost/rest/v1/softwaremodules/" + ahCreated.getId());
|
||||||
assertThat(JsonPath.compile("[2]_links.artifacts.href").read(mvcResult.getResponse().getContentAsString())
|
assertThat(JsonPath.compile("[2]_links.artifacts.href").read(mvcResult.getResponse().getContentAsString())
|
||||||
.toString()).isEqualTo("http://localhost/rest/v1/softwaremodules/" + ahCreated.getId() + "/artifacts");
|
.toString()).as("Response contains invalid artifacts href")
|
||||||
|
.isEqualTo("http://localhost/rest/v1/softwaremodules/" + ahCreated.getId() + "/artifacts");
|
||||||
|
|
||||||
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(3);
|
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).as("Wrong softwaremodule size").hasSize(3);
|
||||||
assertThat(softwareManagement.findSoftwareModulesByType(pageReq, osType).getContent().get(0).getName())
|
assertThat(softwareManagement.findSoftwareModulesByType(pageReq, osType).getContent().get(0).getName())
|
||||||
.isEqualTo(os.getName());
|
.as("Softwaremoudle name is wrong").isEqualTo(os.getName());
|
||||||
assertThat(softwareManagement.findSoftwareModulesByType(pageReq, osType).getContent().get(0).getCreatedBy())
|
assertThat(softwareManagement.findSoftwareModulesByType(pageReq, osType).getContent().get(0).getCreatedBy())
|
||||||
.isEqualTo("uploadTester");
|
.as("Softwaremoudle created by is wrong").isEqualTo("uploadTester");
|
||||||
assertThat(softwareManagement.findSoftwareModulesByType(pageReq, osType).getContent().get(0).getCreatedAt())
|
assertThat(softwareManagement.findSoftwareModulesByType(pageReq, osType).getContent().get(0).getCreatedAt())
|
||||||
.isGreaterThanOrEqualTo(current);
|
.as("Softwaremoudle created at is wrong").isGreaterThanOrEqualTo(current);
|
||||||
assertThat(softwareManagement.findSoftwareModulesByType(pageReq, runtimeType).getContent().get(0).getName())
|
assertThat(softwareManagement.findSoftwareModulesByType(pageReq, runtimeType).getContent().get(0).getName())
|
||||||
.isEqualTo(jvm.getName());
|
.as("Softwaremoudle name is wrong").isEqualTo(jvm.getName());
|
||||||
assertThat(softwareManagement.findSoftwareModulesByType(pageReq, appType).getContent().get(0).getName())
|
assertThat(softwareManagement.findSoftwareModulesByType(pageReq, appType).getContent().get(0).getName())
|
||||||
.isEqualTo(ah.getName());
|
.as("Softwaremoudle name is wrong").isEqualTo(ah.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Verifies successfull deletion of software modules that are not in use, i.e. assigned to a DS.")
|
@Description("Verifies successfull deletion of software modules that are not in use, i.e. assigned to a DS.")
|
||||||
public void deleteUnassignedSoftwareModule() throws Exception {
|
public void deleteUnassignedSoftwareModule() throws Exception {
|
||||||
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).isEmpty();
|
|
||||||
assertThat(artifactRepository.findAll()).isEmpty();
|
|
||||||
|
|
||||||
SoftwareModule sm = new SoftwareModule(osType, "name 1", "version 1", null, null);
|
SoftwareModule sm = new SoftwareModule(osType, "name 1", "version 1", null, null);
|
||||||
sm = softwareManagement.createSoftwareModule(sm);
|
sm = softwareManagement.createSoftwareModule(sm);
|
||||||
|
|
||||||
final byte random[] = RandomStringUtils.random(5 * 1024).getBytes();
|
final byte random[] = RandomStringUtils.random(5 * 1024).getBytes();
|
||||||
|
|
||||||
final Artifact artifact = artifactManagement.createLocalArtifact(new ByteArrayInputStream(random), sm.getId(),
|
artifactManagement.createLocalArtifact(new ByteArrayInputStream(random), sm.getId(), "file1", false);
|
||||||
"file1", false);
|
|
||||||
|
|
||||||
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(1);
|
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).as("Softwaremoudle size is wrong").hasSize(1);
|
||||||
assertThat(artifactRepository.findAll()).hasSize(1);
|
assertThat(artifactRepository.findAll()).as("artifact site is wrong").hasSize(1);
|
||||||
assertThat(softwareModuleRepository.findAll()).hasSize(1);
|
assertThat(softwareModuleRepository.findAll()).as("Softwaremoudle size is wrong").hasSize(1);
|
||||||
|
|
||||||
mvc.perform(delete("/rest/v1/softwaremodules/{smId}", sm.getId())).andDo(MockMvcResultPrinter.print())
|
mvc.perform(delete("/rest/v1/softwaremodules/{smId}", sm.getId())).andDo(MockMvcResultPrinter.print())
|
||||||
.andExpect(status().isOk());
|
.andExpect(status().isOk());
|
||||||
|
|
||||||
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).isEmpty();
|
assertThat(softwareManagement.findSoftwareModulesAll(pageReq))
|
||||||
assertThat(softwareModuleRepository.findAll()).isEmpty();
|
.as("After delete no softwarmodule should be available").isEmpty();
|
||||||
assertThat(artifactRepository.findAll()).isEmpty();
|
assertThat(softwareModuleRepository.findAll()).as("After delete no softwarmodule should be available")
|
||||||
|
.isEmpty();
|
||||||
|
assertThat(artifactRepository.findAll()).as("After delete no artifact should be available").isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Verifies successfull deletion of software modules that are in use, i.e. assigned to a DS which should result in movinf the module to the archive.")
|
@Description("Verifies successfull deletion of software modules that are in use, i.e. assigned to a DS which should result in movinf the module to the archive.")
|
||||||
public void deleteAssignedSoftwareModule() throws Exception {
|
public void deleteAssignedSoftwareModule() throws Exception {
|
||||||
// check baseline
|
|
||||||
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).isEmpty();
|
|
||||||
assertThat(artifactRepository.findAll()).isEmpty();
|
|
||||||
|
|
||||||
final DistributionSet ds1 = TestDataUtil.generateDistributionSet("a", softwareManagement,
|
final DistributionSet ds1 = TestDataUtil.generateDistributionSet("a", softwareManagement,
|
||||||
distributionSetManagement);
|
distributionSetManagement);
|
||||||
|
|
||||||
final byte random[] = RandomStringUtils.random(5 * 1024).getBytes();
|
final byte random[] = RandomStringUtils.random(5 * 1024).getBytes();
|
||||||
|
|
||||||
final LocalArtifact artifact = artifactManagement.createLocalArtifact(new ByteArrayInputStream(random),
|
artifactManagement.createLocalArtifact(new ByteArrayInputStream(random),
|
||||||
ds1.findFirstModuleByType(appType).getId(), "file1", false);
|
ds1.findFirstModuleByType(appType).getId(), "file1", false);
|
||||||
|
|
||||||
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(3);
|
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(3);
|
||||||
@@ -906,17 +873,17 @@ public class SoftwareModuleResourceTest extends AbstractIntegrationTestWithMongo
|
|||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||||
|
|
||||||
// all 3 are now marked as deleted
|
// all 3 are now marked as deleted
|
||||||
assertThat(softwareManagement.findSoftwareModulesAll(pageReq).getNumber()).isEqualTo(0);
|
assertThat(softwareManagement.findSoftwareModulesAll(pageReq).getNumber())
|
||||||
assertThat(softwareModuleRepository.findAll()).hasSize(3);
|
.as("After delete no softwarmodule should be available").isEqualTo(0);
|
||||||
assertThat(artifactRepository.findAll()).hasSize(1);
|
assertThat(softwareModuleRepository.findAll()).as("After delete no softwarmodule should marked as deleted")
|
||||||
|
.hasSize(3);
|
||||||
|
assertThat(artifactRepository.findAll()).as("After delete artifact should available for marked as deleted sm's")
|
||||||
|
.hasSize(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Tests the deletion of an artifact including verfication that the artifact is actually erased in the repository and removed from the software module.")
|
@Description("Tests the deletion of an artifact including verfication that the artifact is actually erased in the repository and removed from the software module.")
|
||||||
public void deleteArtifact() throws Exception {
|
public void deleteArtifact() throws Exception {
|
||||||
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).isEmpty();
|
|
||||||
assertThat(artifactRepository.findAll()).isEmpty();
|
|
||||||
|
|
||||||
// Create 1 SM
|
// Create 1 SM
|
||||||
SoftwareModule sm = new SoftwareModule(osType, "name 1", "version 1", null, null);
|
SoftwareModule sm = new SoftwareModule(osType, "name 1", "version 1", null, null);
|
||||||
sm = softwareManagement.createSoftwareModule(sm);
|
sm = softwareManagement.createSoftwareModule(sm);
|
||||||
@@ -926,8 +893,7 @@ public class SoftwareModuleResourceTest extends AbstractIntegrationTestWithMongo
|
|||||||
// Create 2 artifacts
|
// Create 2 artifacts
|
||||||
final LocalArtifact artifact = artifactManagement.createLocalArtifact(new ByteArrayInputStream(random),
|
final LocalArtifact artifact = artifactManagement.createLocalArtifact(new ByteArrayInputStream(random),
|
||||||
sm.getId(), "file1", false);
|
sm.getId(), "file1", false);
|
||||||
final LocalArtifact artifact2 = artifactManagement.createLocalArtifact(new ByteArrayInputStream(random),
|
artifactManagement.createLocalArtifact(new ByteArrayInputStream(random), sm.getId(), "file2", false);
|
||||||
sm.getId(), "file2", false);
|
|
||||||
|
|
||||||
// check repo before delete
|
// check repo before delete
|
||||||
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(1);
|
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(1);
|
||||||
@@ -940,9 +906,12 @@ public class SoftwareModuleResourceTest extends AbstractIntegrationTestWithMongo
|
|||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||||
|
|
||||||
// check that only one artifact is still alive and still assigned
|
// check that only one artifact is still alive and still assigned
|
||||||
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(1);
|
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).as("After the sm should be marked as deleted")
|
||||||
assertThat(artifactRepository.findAll()).hasSize(1);
|
.hasSize(1);
|
||||||
assertThat(softwareManagement.findSoftwareModuleWithDetails(sm.getId()).getArtifacts()).hasSize(1);
|
assertThat(artifactRepository.findAll()).as("After delete artifact should available for marked as deleted sm's")
|
||||||
|
.hasSize(1);
|
||||||
|
assertThat(softwareManagement.findSoftwareModuleWithDetails(sm.getId()).getArtifacts())
|
||||||
|
.as("After delete artifact should available for marked as deleted sm's").hasSize(1);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -972,8 +941,8 @@ public class SoftwareModuleResourceTest extends AbstractIntegrationTestWithMongo
|
|||||||
final SoftwareModuleMetadata metaKey1 = softwareManagement.findOne(new SwMetadataCompositeKey(sm, knownKey1));
|
final SoftwareModuleMetadata metaKey1 = softwareManagement.findOne(new SwMetadataCompositeKey(sm, knownKey1));
|
||||||
final SoftwareModuleMetadata metaKey2 = softwareManagement.findOne(new SwMetadataCompositeKey(sm, knownKey2));
|
final SoftwareModuleMetadata metaKey2 = softwareManagement.findOne(new SwMetadataCompositeKey(sm, knownKey2));
|
||||||
|
|
||||||
assertThat(metaKey1.getValue()).isEqualTo(knownValue1);
|
assertThat(metaKey1.getValue()).as("Metadata key is wrong").isEqualTo(knownValue1);
|
||||||
assertThat(metaKey2.getValue()).isEqualTo(knownValue2);
|
assertThat(metaKey2.getValue()).as("Metadata key is wrong").isEqualTo(knownValue2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -997,7 +966,7 @@ public class SoftwareModuleResourceTest extends AbstractIntegrationTestWithMongo
|
|||||||
.andExpect(jsonPath("key", equalTo(knownKey))).andExpect(jsonPath("value", equalTo(updateValue)));
|
.andExpect(jsonPath("key", equalTo(knownKey))).andExpect(jsonPath("value", equalTo(updateValue)));
|
||||||
|
|
||||||
final SoftwareModuleMetadata assertDS = softwareManagement.findOne(new SwMetadataCompositeKey(sm, knownKey));
|
final SoftwareModuleMetadata assertDS = softwareManagement.findOne(new SwMetadataCompositeKey(sm, knownKey));
|
||||||
assertThat(assertDS.getValue()).isEqualTo(updateValue);
|
assertThat(assertDS.getValue()).as("Metadata is wrong").isEqualTo(updateValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ package org.eclipse.hawkbit.rest.resource;
|
|||||||
import static org.fest.assertions.api.Assertions.assertThat;
|
import static org.fest.assertions.api.Assertions.assertThat;
|
||||||
import static org.hamcrest.CoreMatchers.equalTo;
|
import static org.hamcrest.CoreMatchers.equalTo;
|
||||||
import static org.hamcrest.CoreMatchers.not;
|
import static org.hamcrest.CoreMatchers.not;
|
||||||
|
import static org.hamcrest.Matchers.hasItem;
|
||||||
import static org.hamcrest.Matchers.hasKey;
|
import static org.hamcrest.Matchers.hasKey;
|
||||||
import static org.hamcrest.Matchers.hasSize;
|
import static org.hamcrest.Matchers.hasSize;
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
|
||||||
@@ -34,6 +35,7 @@ import org.eclipse.hawkbit.TestDataUtil;
|
|||||||
import org.eclipse.hawkbit.WithUser;
|
import org.eclipse.hawkbit.WithUser;
|
||||||
import org.eclipse.hawkbit.exception.SpServerError;
|
import org.eclipse.hawkbit.exception.SpServerError;
|
||||||
import org.eclipse.hawkbit.im.authentication.SpPermission;
|
import org.eclipse.hawkbit.im.authentication.SpPermission;
|
||||||
|
import org.eclipse.hawkbit.repository.ActionFields;
|
||||||
import org.eclipse.hawkbit.repository.ActionStatusFields;
|
import org.eclipse.hawkbit.repository.ActionStatusFields;
|
||||||
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
|
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
|
||||||
import org.eclipse.hawkbit.repository.model.Action;
|
import org.eclipse.hawkbit.repository.model.Action;
|
||||||
@@ -116,27 +118,24 @@ public class TargetResourceTest extends AbstractIntegrationTest {
|
|||||||
new ActionStatus(actions.get(0), Status.FINISHED, System.currentTimeMillis(), "testmessage"),
|
new ActionStatus(actions.get(0), Status.FINISHED, System.currentTimeMillis(), "testmessage"),
|
||||||
actions.get(0));
|
actions.get(0));
|
||||||
|
|
||||||
final PageRequest pageRequest = new PageRequest(0, 1000, Direction.ASC, ActionStatusFields.ID.getFieldName());
|
final PageRequest pageRequest = new PageRequest(0, 1000, Direction.ASC, ActionFields.ID.getFieldName());
|
||||||
|
final ActionStatus status = deploymentManagement
|
||||||
|
.findActionsByTarget(pageRequest, targetManagement.findTargetByControllerID(knownTargetId)).getContent()
|
||||||
|
.get(0).getActionStatus().stream().sorted((e1, e2) -> Long.compare(e2.getId(), e1.getId()))
|
||||||
|
.collect(Collectors.toList()).get(0);
|
||||||
|
|
||||||
// limit to 1 - first page -> standard cancel message
|
|
||||||
final Long reportAt = deploymentManagement
|
|
||||||
.findActionsByTarget(pageRequest, targetManagement.findTargetByControllerID(knownTargetId)).getContent()
|
|
||||||
.get(0).getCreatedAt();
|
|
||||||
final Long id = deploymentManagement
|
|
||||||
.findActionsByTarget(pageRequest, targetManagement.findTargetByControllerID(knownTargetId)).getContent()
|
|
||||||
.get(0).getId();
|
|
||||||
mvc.perform(get(RestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId + "/"
|
mvc.perform(get(RestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId + "/"
|
||||||
+ RestConstants.TARGET_V1_ACTIONS + "/" + actions.get(0).getId() + "/status")
|
+ RestConstants.TARGET_V1_ACTIONS + "/" + actions.get(0).getId() + "/status")
|
||||||
.param(RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, String.valueOf(limitSize))
|
.param(RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, String.valueOf(limitSize))
|
||||||
.param(RestConstants.REQUEST_PARAMETER_SORTING, "ID:ASC"))
|
.param(RestConstants.REQUEST_PARAMETER_SORTING, "ID:DESC"))
|
||||||
.andExpect(status().isOk()).andDo(MockMvcResultPrinter.print())
|
.andExpect(status().isOk()).andDo(MockMvcResultPrinter.print())
|
||||||
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_TOTAL, equalTo(3)))
|
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_TOTAL, equalTo(3)))
|
||||||
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_SIZE, equalTo(limitSize)))
|
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_SIZE, equalTo(limitSize)))
|
||||||
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_CONTENT, hasSize(limitSize)))
|
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_CONTENT, hasSize(limitSize)))
|
||||||
.andExpect(jsonPath("content.[0].id", equalTo(id.intValue())))
|
.andExpect(jsonPath("content.[0].id", equalTo(status.getId().intValue())))
|
||||||
.andExpect(jsonPath("content.[0].type", equalTo("finished")))
|
.andExpect(jsonPath("content.[0].type", equalTo("finished")))
|
||||||
.andExpect(jsonPath("content.[0].messages", hasSize(1)))
|
.andExpect(jsonPath("content.[0].messages", hasSize(1)))
|
||||||
.andExpect(jsonPath("content.[0].reportedAt", equalTo(reportAt)))
|
.andExpect(jsonPath("content.[0].reportedAt", equalTo(status.getCreatedAt().longValue())))
|
||||||
.andExpect(jsonPath("content.[1].type", equalTo("canceling")));
|
.andExpect(jsonPath("content.[1].type", equalTo("canceling")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,7 +228,7 @@ public class TargetResourceTest extends AbstractIntegrationTest {
|
|||||||
@Test
|
@Test
|
||||||
public void cancelActionOK() throws Exception {
|
public void cancelActionOK() throws Exception {
|
||||||
// prepare test
|
// prepare test
|
||||||
Target tA = createTargetAndStartAction();
|
final Target tA = createTargetAndStartAction();
|
||||||
|
|
||||||
// test - cancel the active action
|
// test - cancel the active action
|
||||||
mvc.perform(delete(RestConstants.TARGET_V1_REQUEST_MAPPING + "/{targetId}/actions/{actionId}",
|
mvc.perform(delete(RestConstants.TARGET_V1_REQUEST_MAPPING + "/{targetId}/actions/{actionId}",
|
||||||
@@ -252,7 +251,7 @@ public class TargetResourceTest extends AbstractIntegrationTest {
|
|||||||
@Test
|
@Test
|
||||||
public void cancelAnCancelActionIsNotAllowed() throws Exception {
|
public void cancelAnCancelActionIsNotAllowed() throws Exception {
|
||||||
// prepare test
|
// prepare test
|
||||||
Target tA = createTargetAndStartAction();
|
final Target tA = createTargetAndStartAction();
|
||||||
|
|
||||||
// cancel the active action
|
// cancel the active action
|
||||||
deploymentManagement.cancelAction(tA.getActions().get(0), tA);
|
deploymentManagement.cancelAction(tA.getActions().get(0), tA);
|
||||||
@@ -272,7 +271,7 @@ public class TargetResourceTest extends AbstractIntegrationTest {
|
|||||||
@Description("Force Quit an Action, which is already canceled. Expected Result is an HTTP response code 204.")
|
@Description("Force Quit an Action, which is already canceled. Expected Result is an HTTP response code 204.")
|
||||||
public void forceQuitAnCanceledActionReturnsOk() throws Exception {
|
public void forceQuitAnCanceledActionReturnsOk() throws Exception {
|
||||||
|
|
||||||
Target tA = createTargetAndStartAction();
|
final Target tA = createTargetAndStartAction();
|
||||||
|
|
||||||
// cancel the active action
|
// cancel the active action
|
||||||
deploymentManagement.cancelAction(tA.getActions().get(0), tA);
|
deploymentManagement.cancelAction(tA.getActions().get(0), tA);
|
||||||
@@ -293,7 +292,7 @@ public class TargetResourceTest extends AbstractIntegrationTest {
|
|||||||
@Description("Force Quit an Action, which is not canceled. Expected Result is an HTTP response code 405.")
|
@Description("Force Quit an Action, which is not canceled. Expected Result is an HTTP response code 405.")
|
||||||
public void forceQuitAnNotCanceledActionReturnsMethodNotAllowed() throws Exception {
|
public void forceQuitAnNotCanceledActionReturnsMethodNotAllowed() throws Exception {
|
||||||
|
|
||||||
Target tA = createTargetAndStartAction();
|
final Target tA = createTargetAndStartAction();
|
||||||
|
|
||||||
// test - cancel an cancel action returns forbidden
|
// test - cancel an cancel action returns forbidden
|
||||||
mvc.perform(delete(RestConstants.TARGET_V1_REQUEST_MAPPING + "/{targetId}/actions/{actionId}?force=true",
|
mvc.perform(delete(RestConstants.TARGET_V1_REQUEST_MAPPING + "/{targetId}/actions/{actionId}?force=true",
|
||||||
@@ -834,7 +833,8 @@ public class TargetResourceTest extends AbstractIntegrationTest {
|
|||||||
final List<Action> actions = generateTargetWithTwoUpdatesWithOneOverride(knownTargetId);
|
final List<Action> actions = generateTargetWithTwoUpdatesWithOneOverride(knownTargetId);
|
||||||
|
|
||||||
mvc.perform(get(
|
mvc.perform(get(
|
||||||
RestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId + "/" + RestConstants.TARGET_V1_ACTIONS))
|
RestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId + "/" + RestConstants.TARGET_V1_ACTIONS)
|
||||||
|
.param(RestConstants.REQUEST_PARAMETER_SORTING, "ID:ASC"))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
.andExpect(jsonPath("content.[1].id", equalTo(actions.get(1).getId().intValue())))
|
.andExpect(jsonPath("content.[1].id", equalTo(actions.get(1).getId().intValue())))
|
||||||
.andExpect(jsonPath("content.[1].type", equalTo("update")))
|
.andExpect(jsonPath("content.[1].type", equalTo("update")))
|
||||||
@@ -851,6 +851,108 @@ public class TargetResourceTest extends AbstractIntegrationTest {
|
|||||||
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_CONTENT, hasSize(2)));
|
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_CONTENT, hasSize(2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Description("Verfies that the API returns the status list with expected content.")
|
||||||
|
public void getMultipleActionStatus() throws Exception {
|
||||||
|
final String knownTargetId = "targetId";
|
||||||
|
final Action action = generateTargetWithTwoUpdatesWithOneOverride(knownTargetId).get(0);
|
||||||
|
// retrieve list in default descending order for actionstaus entries
|
||||||
|
final List<ActionStatus> actionStatus = action.getActionStatus().stream()
|
||||||
|
.sorted((e1, e2) -> Long.compare(e2.getId(), e1.getId())).collect(Collectors.toList());
|
||||||
|
|
||||||
|
// sort is default descending order, latest status first
|
||||||
|
mvc.perform(get(RestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId + "/"
|
||||||
|
+ RestConstants.TARGET_V1_ACTIONS + "/" + action.getId() + "/" + RestConstants.TARGET_V1_ACTION_STATUS))
|
||||||
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("content.[0].id", equalTo(actionStatus.get(0).getId().intValue())))
|
||||||
|
.andExpect(jsonPath("content.[0].type", equalTo("canceling")))
|
||||||
|
.andExpect(jsonPath("content.[0].messages", hasItem("manual cancelation requested")))
|
||||||
|
.andExpect(jsonPath("content.[0].reportedAt", equalTo(actionStatus.get(0).getCreatedAt())))
|
||||||
|
.andExpect(jsonPath("content.[1].id", equalTo(actionStatus.get(1).getId().intValue())))
|
||||||
|
.andExpect(jsonPath("content.[1].type", equalTo("running")))
|
||||||
|
.andExpect(jsonPath("content.[1].reportedAt", equalTo(actionStatus.get(1).getCreatedAt())))
|
||||||
|
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_TOTAL, equalTo(2)))
|
||||||
|
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_SIZE, equalTo(2)))
|
||||||
|
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_CONTENT, hasSize(2)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Description("Verfies that the API returns the status list with expected content sorted by reportedAt field.")
|
||||||
|
public void getMultipleActionStatusSortedByReportedAt() throws Exception {
|
||||||
|
final String knownTargetId = "targetId";
|
||||||
|
final Action action = generateTargetWithTwoUpdatesWithOneOverride(knownTargetId).get(0);
|
||||||
|
final List<ActionStatus> actionStatus = action.getActionStatus().stream()
|
||||||
|
.sorted((e1, e2) -> Long.compare(e1.getId(), e2.getId())).collect(Collectors.toList());
|
||||||
|
|
||||||
|
// descending order
|
||||||
|
mvc.perform(get(RestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId + "/"
|
||||||
|
+ RestConstants.TARGET_V1_ACTIONS + "/" + action.getId() + "/" + RestConstants.TARGET_V1_ACTION_STATUS)
|
||||||
|
.param(RestConstants.REQUEST_PARAMETER_SORTING, "REPORTEDAT:DESC"))
|
||||||
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("content.[0].id", equalTo(actionStatus.get(1).getId().intValue())))
|
||||||
|
.andExpect(jsonPath("content.[0].type", equalTo("canceling")))
|
||||||
|
.andExpect(jsonPath("content.[0].messages", hasItem("manual cancelation requested")))
|
||||||
|
.andExpect(jsonPath("content.[0].reportedAt", equalTo(actionStatus.get(1).getCreatedAt())))
|
||||||
|
.andExpect(jsonPath("content.[1].id", equalTo(actionStatus.get(0).getId().intValue())))
|
||||||
|
.andExpect(jsonPath("content.[1].type", equalTo("running")))
|
||||||
|
.andExpect(jsonPath("content.[1].reportedAt", equalTo(actionStatus.get(0).getCreatedAt())))
|
||||||
|
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_TOTAL, equalTo(2)))
|
||||||
|
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_SIZE, equalTo(2)))
|
||||||
|
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_CONTENT, hasSize(2)));
|
||||||
|
|
||||||
|
// ascending order
|
||||||
|
mvc.perform(get(RestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId + "/"
|
||||||
|
+ RestConstants.TARGET_V1_ACTIONS + "/" + action.getId() + "/" + RestConstants.TARGET_V1_ACTION_STATUS)
|
||||||
|
.param(RestConstants.REQUEST_PARAMETER_SORTING, "REPORTEDAT:ASC"))
|
||||||
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("content.[1].id", equalTo(actionStatus.get(1).getId().intValue())))
|
||||||
|
.andExpect(jsonPath("content.[1].type", equalTo("canceling")))
|
||||||
|
.andExpect(jsonPath("content.[1].messages", hasItem("manual cancelation requested")))
|
||||||
|
.andExpect(jsonPath("content.[1].reportedAt", equalTo(actionStatus.get(1).getCreatedAt())))
|
||||||
|
.andExpect(jsonPath("content.[0].id", equalTo(actionStatus.get(0).getId().intValue())))
|
||||||
|
.andExpect(jsonPath("content.[0].type", equalTo("running")))
|
||||||
|
.andExpect(jsonPath("content.[0].reportedAt", equalTo(actionStatus.get(0).getCreatedAt())))
|
||||||
|
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_TOTAL, equalTo(2)))
|
||||||
|
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_SIZE, equalTo(2)))
|
||||||
|
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_CONTENT, hasSize(2)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Description("Verfies that the API returns the status list with expected content split into two pages.")
|
||||||
|
public void getMultipleActionStatusWithPagingLimitRequestParameter() throws Exception {
|
||||||
|
final String knownTargetId = "targetId";
|
||||||
|
|
||||||
|
final Action action = generateTargetWithTwoUpdatesWithOneOverride(knownTargetId).get(0);
|
||||||
|
final List<ActionStatus> actionStatus = action.getActionStatus().stream()
|
||||||
|
.sorted((e1, e2) -> Long.compare(e1.getId(), e2.getId())).collect(Collectors.toList());
|
||||||
|
|
||||||
|
// Page 1
|
||||||
|
mvc.perform(get(RestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId + "/"
|
||||||
|
+ RestConstants.TARGET_V1_ACTIONS + "/" + action.getId() + "/" + RestConstants.TARGET_V1_ACTION_STATUS)
|
||||||
|
.param(RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, String.valueOf(1)))
|
||||||
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("content.[0].id", equalTo(actionStatus.get(1).getId().intValue())))
|
||||||
|
.andExpect(jsonPath("content.[0].type", equalTo("canceling")))
|
||||||
|
.andExpect(jsonPath("content.[0].messages", hasItem("manual cancelation requested")))
|
||||||
|
.andExpect(jsonPath("content.[0].reportedAt", equalTo(actionStatus.get(1).getCreatedAt())))
|
||||||
|
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_TOTAL, equalTo(2)))
|
||||||
|
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_SIZE, equalTo(1)))
|
||||||
|
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_CONTENT, hasSize(1)));
|
||||||
|
|
||||||
|
// Page 2
|
||||||
|
mvc.perform(get(RestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId + "/"
|
||||||
|
+ RestConstants.TARGET_V1_ACTIONS + "/" + action.getId() + "/" + RestConstants.TARGET_V1_ACTION_STATUS)
|
||||||
|
.param(RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, String.valueOf(1))
|
||||||
|
.param(RestConstants.REQUEST_PARAMETER_PAGING_OFFSET, String.valueOf(1)))
|
||||||
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("content.[0].id", equalTo(actionStatus.get(0).getId().intValue())))
|
||||||
|
.andExpect(jsonPath("content.[0].type", equalTo("running")))
|
||||||
|
.andExpect(jsonPath("content.[0].reportedAt", equalTo(actionStatus.get(0).getCreatedAt())))
|
||||||
|
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_TOTAL, equalTo(2)))
|
||||||
|
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_SIZE, equalTo(1)))
|
||||||
|
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_CONTENT, hasSize(1)));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getMultipleActionsWithPagingLimitRequestParameter() throws Exception {
|
public void getMultipleActionsWithPagingLimitRequestParameter() throws Exception {
|
||||||
final String knownTargetId = "targetId";
|
final String knownTargetId = "targetId";
|
||||||
@@ -859,7 +961,8 @@ public class TargetResourceTest extends AbstractIntegrationTest {
|
|||||||
// page 1: one entry
|
// page 1: one entry
|
||||||
mvc.perform(get(
|
mvc.perform(get(
|
||||||
RestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId + "/" + RestConstants.TARGET_V1_ACTIONS)
|
RestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId + "/" + RestConstants.TARGET_V1_ACTIONS)
|
||||||
.param(RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, String.valueOf(1)))
|
.param(RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, String.valueOf(1))
|
||||||
|
.param(RestConstants.REQUEST_PARAMETER_SORTING, "ID:ASC"))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
.andExpect(jsonPath("content.[0].id", equalTo(actions.get(0).getId().intValue())))
|
.andExpect(jsonPath("content.[0].id", equalTo(actions.get(0).getId().intValue())))
|
||||||
.andExpect(jsonPath("content.[0].type", equalTo("cancel")))
|
.andExpect(jsonPath("content.[0].type", equalTo("cancel")))
|
||||||
@@ -874,7 +977,9 @@ public class TargetResourceTest extends AbstractIntegrationTest {
|
|||||||
mvc.perform(get(
|
mvc.perform(get(
|
||||||
RestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId + "/" + RestConstants.TARGET_V1_ACTIONS)
|
RestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId + "/" + RestConstants.TARGET_V1_ACTIONS)
|
||||||
.param(RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, String.valueOf(1))
|
.param(RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, String.valueOf(1))
|
||||||
.param(RestConstants.REQUEST_PARAMETER_PAGING_OFFSET, String.valueOf(1)))
|
.param(RestConstants.REQUEST_PARAMETER_PAGING_OFFSET, String.valueOf(1))
|
||||||
|
.param(RestConstants.REQUEST_PARAMETER_PAGING_OFFSET, String.valueOf(1))
|
||||||
|
.param(RestConstants.REQUEST_PARAMETER_SORTING, "ID:ASC"))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
.andExpect(jsonPath("content.[0].id", equalTo(actions.get(1).getId().intValue())))
|
.andExpect(jsonPath("content.[0].id", equalTo(actions.get(1).getId().intValue())))
|
||||||
.andExpect(jsonPath("content.[0].type", equalTo("update")))
|
.andExpect(jsonPath("content.[0].type", equalTo("update")))
|
||||||
@@ -902,7 +1007,8 @@ public class TargetResourceTest extends AbstractIntegrationTest {
|
|||||||
+ "?offset=0&limit=50&sort=id:DESC";
|
+ "?offset=0&limit=50&sort=id:DESC";
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Action> generateTargetWithTwoUpdatesWithOneOverride(final String knownTargetId) {
|
private List<Action> generateTargetWithTwoUpdatesWithOneOverride(final String knownTargetId)
|
||||||
|
throws InterruptedException {
|
||||||
|
|
||||||
final PageRequest pageRequest = new PageRequest(0, 100, Direction.ASC, ActionStatusFields.ID.getFieldName());
|
final PageRequest pageRequest = new PageRequest(0, 100, Direction.ASC, ActionStatusFields.ID.getFieldName());
|
||||||
|
|
||||||
@@ -920,6 +1026,8 @@ public class TargetResourceTest extends AbstractIntegrationTest {
|
|||||||
final List<Target> updatedTargets = deploymentManagement.assignDistributionSet(one, targets)
|
final List<Target> updatedTargets = deploymentManagement.assignDistributionSet(one, targets)
|
||||||
.getAssignedTargets();
|
.getAssignedTargets();
|
||||||
// 2nd update
|
// 2nd update
|
||||||
|
// sleep 10ms to ensure that we can sort by reportedAt
|
||||||
|
Thread.sleep(10);
|
||||||
deploymentManagement.assignDistributionSet(two, updatedTargets);
|
deploymentManagement.assignDistributionSet(two, updatedTargets);
|
||||||
|
|
||||||
// two updates, one cancelation
|
// two updates, one cancelation
|
||||||
@@ -946,54 +1054,6 @@ public class TargetResourceTest extends AbstractIntegrationTest {
|
|||||||
equalTo(generateStatusreferenceLink(knownTargetId, actions.get(1)))));
|
equalTo(generateStatusreferenceLink(knownTargetId, actions.get(1)))));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getActionStatusWithMultipleResultsWithPagingLimitRequestParameter() throws Exception {
|
|
||||||
final int limitSize = 1;
|
|
||||||
final String knownTargetId = "targetId";
|
|
||||||
final List<Action> actions = generateTargetWithTwoUpdatesWithOneOverride(knownTargetId);
|
|
||||||
actions.get(0).setStatus(Status.RUNNING);
|
|
||||||
controllerManagament.addUpdateActionStatus(
|
|
||||||
new ActionStatus(actions.get(0), Status.RUNNING, System.currentTimeMillis(), "testmessage"),
|
|
||||||
actions.get(0));
|
|
||||||
|
|
||||||
final PageRequest pageRequest = new PageRequest(0, 1000, Direction.ASC, ActionStatusFields.ID.getFieldName());
|
|
||||||
|
|
||||||
// limit to 1 - first page -> standard cancel message
|
|
||||||
Long reportAt = deploymentManagement
|
|
||||||
.findActionsByTarget(pageRequest, targetManagement.findTargetByControllerID(knownTargetId)).getContent()
|
|
||||||
.get(0).getCreatedAt();
|
|
||||||
Long id = deploymentManagement
|
|
||||||
.findActionsByTarget(pageRequest, targetManagement.findTargetByControllerID(knownTargetId)).getContent()
|
|
||||||
.get(0).getId();
|
|
||||||
mvc.perform(get(RestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId + "/"
|
|
||||||
+ RestConstants.TARGET_V1_ACTIONS + "/" + actions.get(0).getId() + "/status")
|
|
||||||
.param(RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, String.valueOf(limitSize)))
|
|
||||||
.andExpect(status().isOk()).andDo(MockMvcResultPrinter.print())
|
|
||||||
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_TOTAL, equalTo(3)))
|
|
||||||
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_SIZE, equalTo(limitSize)))
|
|
||||||
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_CONTENT, hasSize(limitSize)))
|
|
||||||
.andExpect(jsonPath("content.[0].id", equalTo(id.intValue())))
|
|
||||||
.andExpect(jsonPath("content.[0].type", equalTo("running")))
|
|
||||||
.andExpect(jsonPath("content.[0].messages", hasSize(1)))
|
|
||||||
.andExpect(jsonPath("content.[0].reportedAt", equalTo(reportAt)));
|
|
||||||
|
|
||||||
// limit to 1 - first page -> added custom message
|
|
||||||
reportAt = deploymentManagement
|
|
||||||
.findActionsByTarget(pageRequest, targetManagement.findTargetByControllerID(knownTargetId)).getContent()
|
|
||||||
.get(1).getCreatedAt();
|
|
||||||
id = deploymentManagement
|
|
||||||
.findActionsByTarget(pageRequest, targetManagement.findTargetByControllerID(knownTargetId)).getContent()
|
|
||||||
.get(1).getCreatedAt();
|
|
||||||
|
|
||||||
mvc.perform(get(RestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId + "/"
|
|
||||||
+ RestConstants.TARGET_V1_ACTIONS + "/" + actions.get(0).getId() + "/status")
|
|
||||||
.param(RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, String.valueOf(limitSize))
|
|
||||||
.param(RestConstants.REQUEST_PARAMETER_PAGING_OFFSET, String.valueOf(1)))
|
|
||||||
.andExpect(status().isOk()).andDo(MockMvcResultPrinter.print())
|
|
||||||
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_TOTAL, equalTo(3)))
|
|
||||||
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_SIZE, equalTo(1)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void assignDistributionSetToTarget() throws Exception {
|
public void assignDistributionSetToTarget() throws Exception {
|
||||||
|
|
||||||
@@ -1232,7 +1292,8 @@ public class TargetResourceTest extends AbstractIntegrationTest {
|
|||||||
// prepare test
|
// prepare test
|
||||||
final DistributionSet dsA = TestDataUtil.generateDistributionSet("", softwareManagement,
|
final DistributionSet dsA = TestDataUtil.generateDistributionSet("", softwareManagement,
|
||||||
distributionSetManagement);
|
distributionSetManagement);
|
||||||
Target tA = targetManagement.createTarget(TestDataUtil.buildTargetFixture("target-id-A", "first description"));
|
final Target tA = targetManagement
|
||||||
|
.createTarget(TestDataUtil.buildTargetFixture("target-id-A", "first description"));
|
||||||
// assign a distribution set so we get an active update action
|
// assign a distribution set so we get an active update action
|
||||||
deploymentManagement.assignDistributionSet(dsA, Lists.newArrayList(tA));
|
deploymentManagement.assignDistributionSet(dsA, Lists.newArrayList(tA));
|
||||||
// verify active action
|
// verify active action
|
||||||
|
|||||||
@@ -32,10 +32,15 @@ public class ExceptionInfoTest {
|
|||||||
underTest.setMessage(knownMessage);
|
underTest.setMessage(knownMessage);
|
||||||
underTest.setParameters(knownParameters);
|
underTest.setParameters(knownParameters);
|
||||||
|
|
||||||
assertThat(underTest.getErrorCode()).isEqualTo(knownErrorCode);
|
assertThat(underTest.getErrorCode()).as("The error code should match with the known error code in the test")
|
||||||
assertThat(underTest.getExceptionClass()).isEqualTo(knownExceptionClass);
|
.isEqualTo(knownErrorCode);
|
||||||
assertThat(underTest.getMessage()).isEqualTo(knownMessage);
|
assertThat(underTest.getExceptionClass())
|
||||||
assertThat(underTest.getParameters()).isEqualTo(knownParameters);
|
.as("The exception class should match with the known error code in the test")
|
||||||
|
.isEqualTo(knownExceptionClass);
|
||||||
|
assertThat(underTest.getMessage()).as("The message should match with the known error code in the test")
|
||||||
|
.isEqualTo(knownMessage);
|
||||||
|
assertThat(underTest.getParameters()).as("The parameters should match with the known error code in the test")
|
||||||
|
.isEqualTo(knownParameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,10 +29,13 @@ public class PagedListTest {
|
|||||||
knownContentList.add("content1");
|
knownContentList.add("content1");
|
||||||
knownContentList.add("content2");
|
knownContentList.add("content2");
|
||||||
|
|
||||||
final PagedList<String> pagedList = new PagedList<>(knownContentList, knownTotal);
|
assertListSize(knownTotal, knownContentList);
|
||||||
|
}
|
||||||
|
|
||||||
assertThat(pagedList.getTotal()).isEqualTo(knownTotal);
|
private void assertListSize(final long knownTotal, final List<String> knownContentList) {
|
||||||
assertThat(pagedList.getSize()).isEqualTo(knownContentList.size());
|
final PagedList<String> pagedList = new PagedList<>(knownContentList, knownTotal);
|
||||||
|
assertThat(pagedList.getTotal()).as("total size is wrong").isEqualTo(knownTotal);
|
||||||
|
assertThat(pagedList.getSize()).as("list size is wrong").isEqualTo(knownContentList.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -42,9 +45,7 @@ public class PagedListTest {
|
|||||||
knownContentList.add("content1");
|
knownContentList.add("content1");
|
||||||
knownContentList.add("content2");
|
knownContentList.add("content2");
|
||||||
|
|
||||||
final PagedList<String> pagedList = new PagedList<>(knownContentList, knownTotal);
|
assertListSize(knownTotal, knownContentList);
|
||||||
assertThat(pagedList.getTotal()).isEqualTo(knownTotal);
|
|
||||||
assertThat(pagedList.getSize()).isEqualTo(knownContentList.size());
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
</Console>
|
</Console>
|
||||||
</Appenders>
|
</Appenders>
|
||||||
<Loggers>
|
<Loggers>
|
||||||
<Logger name="org.eclipse.hawkbit.MockMvcResultPrinter" level="debug" />
|
<Logger name="org.eclipse.hawkbit.MockMvcResultPrinter" level="error" />
|
||||||
|
|
||||||
<Root level="error">
|
<Root level="error">
|
||||||
<AppenderRef ref="Console"/>
|
<AppenderRef ref="Console"/>
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import java.util.concurrent.Callable;
|
|||||||
|
|
||||||
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
|
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
|
||||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||||
import org.eclipse.hawkbit.tenancy.TenantAware.TenantRunner;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -30,8 +29,7 @@ import org.springframework.stereotype.Service;
|
|||||||
import com.google.common.base.Throwables;
|
import com.google.common.base.Throwables;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Michael Hirsch
|
*
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class SystemSecurityContext {
|
public class SystemSecurityContext {
|
||||||
@@ -45,15 +43,12 @@ public class SystemSecurityContext {
|
|||||||
final SecurityContext oldContext = SecurityContextHolder.getContext();
|
final SecurityContext oldContext = SecurityContextHolder.getContext();
|
||||||
try {
|
try {
|
||||||
logger.debug("entering system code execution");
|
logger.debug("entering system code execution");
|
||||||
return tenantAware.runAsTenant(tenantAware.getCurrentTenant(), new TenantRunner<T>() {
|
return tenantAware.runAsTenant(tenantAware.getCurrentTenant(), () -> {
|
||||||
@Override
|
try {
|
||||||
public T run() {
|
setSystemContext();
|
||||||
try {
|
return callable.call();
|
||||||
setSystemContext();
|
} catch (final Exception e) {
|
||||||
return callable.call();
|
throw Throwables.propagate(e);
|
||||||
} catch (final Exception e) {
|
|
||||||
throw Throwables.propagate(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -106,7 +101,8 @@ public class SystemSecurityContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setAuthenticated(final boolean isAuthenticated) throws IllegalArgumentException {
|
public void setAuthenticated(final boolean isAuthenticated) {
|
||||||
|
// not needed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,9 +20,6 @@ import com.google.common.net.HttpHeaders;
|
|||||||
/**
|
/**
|
||||||
* A utility which determines the correct IP of a connected {@link Target}. E.g
|
* A utility which determines the correct IP of a connected {@link Target}. E.g
|
||||||
* from a {@link HttpServletRequest}.
|
* from a {@link HttpServletRequest}.
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public final class IpUtil {
|
public final class IpUtil {
|
||||||
@@ -95,7 +92,6 @@ public final class IpUtil {
|
|||||||
if (isIpV6) {
|
if (isIpV6) {
|
||||||
return URI.create(scheme + SCHEME_SEPERATOR + "[" + host + "]");
|
return URI.create(scheme + SCHEME_SEPERATOR + "[" + host + "]");
|
||||||
}
|
}
|
||||||
|
|
||||||
return URI.create(scheme + SCHEME_SEPERATOR + host);
|
return URI.create(scheme + SCHEME_SEPERATOR + host);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,12 +100,14 @@ public final class IpUtil {
|
|||||||
*
|
*
|
||||||
* @param host
|
* @param host
|
||||||
* the host
|
* the host
|
||||||
|
* @param exchange
|
||||||
|
* the exchange will store in the path
|
||||||
* @return the {@link URI}
|
* @return the {@link URI}
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
* If the given string not parsable
|
* If the given string not parsable
|
||||||
*/
|
*/
|
||||||
public static URI createAmqpUri(final String host) {
|
public static URI createAmqpUri(final String host, final String exchange) {
|
||||||
return createUri(AMPQP_SCHEME, host);
|
return createUri(AMPQP_SCHEME, host).resolve("/" + exchange);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -56,7 +56,8 @@ public class ExcludePathAwareShallowETagFilterTest {
|
|||||||
filterUnderTest.doFilterInternal(servletRequestMock, servletResponseMock, filterChainMock);
|
filterUnderTest.doFilterInternal(servletRequestMock, servletResponseMock, filterChainMock);
|
||||||
|
|
||||||
// verify no eTag header is set and response has not been changed
|
// verify no eTag header is set and response has not been changed
|
||||||
assertThat(servletResponseMock.getHeader("ETag")).isNull();
|
assertThat(servletResponseMock.getHeader("ETag"))
|
||||||
|
.as("ETag header should not be set during downloading, too expensive").isNull();
|
||||||
// the servlet response must be the same mock!
|
// the servlet response must be the same mock!
|
||||||
verify(filterChainMock, times(1)).doFilter(servletRequestMock, servletResponseMock);
|
verify(filterChainMock, times(1)).doFilter(servletRequestMock, servletResponseMock);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,7 +53,8 @@ public class IpUtilTest {
|
|||||||
final URI remoteAddr = IpUtil.getClientIpFromRequest(requestMock, "bumlux");
|
final URI remoteAddr = IpUtil.getClientIpFromRequest(requestMock, "bumlux");
|
||||||
|
|
||||||
// verify
|
// verify
|
||||||
assertThat(remoteAddr).isEqualTo(knownRemoteClientIP);
|
assertThat(remoteAddr).as("The remote address should be as the known client IP address")
|
||||||
|
.isEqualTo(knownRemoteClientIP);
|
||||||
verify(requestMock, times(1)).getHeader("bumlux");
|
verify(requestMock, times(1)).getHeader("bumlux");
|
||||||
verify(requestMock, times(1)).getRemoteAddr();
|
verify(requestMock, times(1)).getRemoteAddr();
|
||||||
}
|
}
|
||||||
@@ -71,7 +72,8 @@ public class IpUtilTest {
|
|||||||
final URI remoteAddr = IpUtil.getClientIpFromRequest(requestMock, "X-Forwarded-For");
|
final URI remoteAddr = IpUtil.getClientIpFromRequest(requestMock, "X-Forwarded-For");
|
||||||
|
|
||||||
// verify
|
// verify
|
||||||
assertThat(remoteAddr).isEqualTo(knownRemoteClientIP);
|
assertThat(remoteAddr).as("The remote address should be as the known client IP address")
|
||||||
|
.isEqualTo(knownRemoteClientIP);
|
||||||
verify(requestMock, times(1)).getHeader(HttpHeaders.X_FORWARDED_FOR);
|
verify(requestMock, times(1)).getHeader(HttpHeaders.X_FORWARDED_FOR);
|
||||||
verify(requestMock, times(0)).getRemoteAddr();
|
verify(requestMock, times(0)).getRemoteAddr();
|
||||||
}
|
}
|
||||||
@@ -94,45 +96,50 @@ public class IpUtilTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void assertHttpUri(final String host, final URI httpUri) {
|
private void assertHttpUri(final String host, final URI httpUri) {
|
||||||
assertTrue(IpUtil.isHttpUri(httpUri));
|
assertTrue("The given URI has an http scheme", IpUtil.isHttpUri(httpUri));
|
||||||
assertFalse(IpUtil.isAmqpUri(httpUri));
|
assertFalse("The given URI is not an AMQP scheme", IpUtil.isAmqpUri(httpUri));
|
||||||
assertEquals(host, httpUri.getHost());
|
assertEquals("The URI hosts matches the given host", host, httpUri.getHost());
|
||||||
assertEquals("http", httpUri.getScheme());
|
assertEquals("The given URI scheme is http", "http", httpUri.getScheme());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Tests create amqp uri ipv4 and ipv6")
|
@Description("Tests create amqp uri ipv4 and ipv6")
|
||||||
public void testCreateAmqpUri() {
|
public void testCreateAmqpUri() {
|
||||||
final String ipv4 = "10.99.99.1";
|
final String ipv4 = "10.99.99.1";
|
||||||
URI amqpUri = IpUtil.createAmqpUri(ipv4);
|
URI amqpUri = IpUtil.createAmqpUri(ipv4, "path");
|
||||||
assertAmqpUri(ipv4, amqpUri);
|
assertAmqpUri(ipv4, amqpUri);
|
||||||
|
|
||||||
final String host = "myhost";
|
final String host = "myhost";
|
||||||
amqpUri = IpUtil.createAmqpUri(host);
|
amqpUri = IpUtil.createAmqpUri(host, "path");
|
||||||
assertAmqpUri(host, amqpUri);
|
assertAmqpUri(host, amqpUri);
|
||||||
|
|
||||||
final String ipv6 = "0:0:0:0:0:0:0:1";
|
final String ipv6 = "0:0:0:0:0:0:0:1";
|
||||||
amqpUri = IpUtil.createAmqpUri(ipv6);
|
amqpUri = IpUtil.createAmqpUri(ipv6, "path");
|
||||||
assertAmqpUri("[" + ipv6 + "]", amqpUri);
|
assertAmqpUri("[" + ipv6 + "]", amqpUri);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertAmqpUri(final String host, final URI httpUri) {
|
private void assertAmqpUri(final String host, final URI amqpUri) {
|
||||||
assertTrue(IpUtil.isAmqpUri(httpUri));
|
assertTrue("The given URI is an AMQP scheme", IpUtil.isAmqpUri(amqpUri));
|
||||||
assertFalse(IpUtil.isHttpUri(httpUri));
|
assertFalse("The given URI is not an HTTP scheme", IpUtil.isHttpUri(amqpUri));
|
||||||
assertEquals(host, httpUri.getHost());
|
assertEquals("The given host matches the URI host", host, amqpUri.getHost());
|
||||||
assertEquals("amqp", httpUri.getScheme());
|
assertEquals("The given URI has an AMQP scheme", "amqp", amqpUri.getScheme());
|
||||||
|
assertEquals("The given URI has an AMQP path", "/path", amqpUri.getRawPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test
|
||||||
@Description("Tests create invalid uri")
|
@Description("Tests create invalid uri")
|
||||||
public void testCreateInvalidUri() {
|
public void testCreateInvalidUri() {
|
||||||
final String host = "10.99.99.1";
|
final String host = "10.99.99.1";
|
||||||
final URI testUri = IpUtil.createUri("test", host);
|
final URI testUri = IpUtil.createUri("test", host);
|
||||||
assertFalse(IpUtil.isAmqpUri(testUri));
|
assertFalse("The given URI is not an AMQP address", IpUtil.isAmqpUri(testUri));
|
||||||
assertFalse(IpUtil.isHttpUri(testUri));
|
assertFalse("The given URI is not an HTTP address", IpUtil.isHttpUri(testUri));
|
||||||
assertEquals(host, testUri.getHost());
|
assertEquals("The given host matches the URI host", host, testUri.getHost());
|
||||||
IpUtil.createUri(":/", host);
|
try {
|
||||||
fail();
|
IpUtil.createUri(":/", host);
|
||||||
|
fail("Missing expected IllegalArgumentException due invalid URI");
|
||||||
|
} catch (final IllegalArgumentException e) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,12 +14,11 @@ import java.util.Set;
|
|||||||
|
|
||||||
import javax.servlet.http.Cookie;
|
import javax.servlet.http.Cookie;
|
||||||
|
|
||||||
import org.eclipse.hawkbit.eventbus.event.EntityEvent;
|
|
||||||
import org.eclipse.hawkbit.im.authentication.TenantAwareAuthenticationDetails;
|
|
||||||
import org.eclipse.hawkbit.ui.components.SPUIErrorHandler;
|
import org.eclipse.hawkbit.ui.components.SPUIErrorHandler;
|
||||||
import org.eclipse.hawkbit.ui.menu.DashboardEvent.PostViewChangeEvent;
|
import org.eclipse.hawkbit.ui.menu.DashboardEvent.PostViewChangeEvent;
|
||||||
import org.eclipse.hawkbit.ui.menu.DashboardMenu;
|
import org.eclipse.hawkbit.ui.menu.DashboardMenu;
|
||||||
import org.eclipse.hawkbit.ui.menu.DashboardMenuItem;
|
import org.eclipse.hawkbit.ui.menu.DashboardMenuItem;
|
||||||
|
import org.eclipse.hawkbit.ui.push.EventPushStrategy;
|
||||||
import org.eclipse.hawkbit.ui.utils.I18N;
|
import org.eclipse.hawkbit.ui.utils.I18N;
|
||||||
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
||||||
import org.eclipse.hawkbit.ui.utils.SpringContextHelper;
|
import org.eclipse.hawkbit.ui.utils.SpringContextHelper;
|
||||||
@@ -28,14 +27,8 @@ import org.slf4j.LoggerFactory;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.security.core.context.SecurityContext;
|
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
|
||||||
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
|
|
||||||
import org.vaadin.spring.events.EventBus;
|
import org.vaadin.spring.events.EventBus;
|
||||||
import org.vaadin.spring.events.EventBus.SessionEventBus;
|
|
||||||
|
|
||||||
import com.google.common.eventbus.AllowConcurrentEvents;
|
|
||||||
import com.google.common.eventbus.Subscribe;
|
|
||||||
import com.vaadin.annotations.Title;
|
import com.vaadin.annotations.Title;
|
||||||
import com.vaadin.navigator.Navigator;
|
import com.vaadin.navigator.Navigator;
|
||||||
import com.vaadin.navigator.View;
|
import com.vaadin.navigator.View;
|
||||||
@@ -45,9 +38,6 @@ import com.vaadin.server.ClientConnector.DetachListener;
|
|||||||
import com.vaadin.server.Responsive;
|
import com.vaadin.server.Responsive;
|
||||||
import com.vaadin.server.VaadinRequest;
|
import com.vaadin.server.VaadinRequest;
|
||||||
import com.vaadin.server.VaadinService;
|
import com.vaadin.server.VaadinService;
|
||||||
import com.vaadin.server.VaadinSession;
|
|
||||||
import com.vaadin.server.VaadinSession.State;
|
|
||||||
import com.vaadin.server.WrappedSession;
|
|
||||||
import com.vaadin.spring.navigator.SpringViewProvider;
|
import com.vaadin.spring.navigator.SpringViewProvider;
|
||||||
import com.vaadin.ui.Component;
|
import com.vaadin.ui.Component;
|
||||||
import com.vaadin.ui.CssLayout;
|
import com.vaadin.ui.CssLayout;
|
||||||
@@ -71,6 +61,8 @@ public class HawkbitUI extends DefaultHawkbitUI implements DetachListener {
|
|||||||
|
|
||||||
private static final String EMPTY_VIEW = "";
|
private static final String EMPTY_VIEW = "";
|
||||||
|
|
||||||
|
private EventPushStrategy pushStrategy;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private SpringViewProvider viewProvider;
|
private SpringViewProvider viewProvider;
|
||||||
|
|
||||||
@@ -92,69 +84,37 @@ public class HawkbitUI extends DefaultHawkbitUI implements DetachListener {
|
|||||||
protected transient EventBus.SessionEventBus eventBus;
|
protected transient EventBus.SessionEventBus eventBus;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An {@link com.google.common.eventbus.EventBus} subscriber which
|
* Default constructor.
|
||||||
* subscribes {@link EntityEvent} from the repository to dispatch these
|
|
||||||
* events to the UI {@link SessionEventBus}.
|
|
||||||
*
|
|
||||||
* @param event
|
|
||||||
* the entity event which has been published from the repository
|
|
||||||
*/
|
*/
|
||||||
@Subscribe
|
public HawkbitUI() {
|
||||||
@AllowConcurrentEvents
|
// is empty, is ok.
|
||||||
public void dispatch(final org.eclipse.hawkbit.eventbus.event.Event event) {
|
|
||||||
final VaadinSession session = getSession();
|
|
||||||
if (session == null || session.getState() != State.OPEN) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final WrappedSession wrappedSession = session.getSession();
|
|
||||||
if (wrappedSession == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final SecurityContext userContext = (SecurityContext) wrappedSession
|
|
||||||
.getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
|
|
||||||
if (!eventSecurityCheck(userContext, event)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final SecurityContext oldContext = SecurityContextHolder.getContext();
|
|
||||||
try {
|
|
||||||
access(new DispatcherRunnable(eventBus, session, userContext, event));
|
|
||||||
} finally {
|
|
||||||
SecurityContextHolder.setContext(oldContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean eventSecurityCheck(final SecurityContext userContext,
|
/**
|
||||||
final org.eclipse.hawkbit.eventbus.event.Event event) {
|
* Constructor taking the push strategy.
|
||||||
if (userContext != null && userContext.getAuthentication() != null) {
|
*
|
||||||
final Object tenantAuthenticationDetails = userContext.getAuthentication().getDetails();
|
* @param pushStrategy
|
||||||
if (tenantAuthenticationDetails instanceof TenantAwareAuthenticationDetails) {
|
* the strategy to push events from the backend to the UI
|
||||||
return ((TenantAwareAuthenticationDetails) tenantAuthenticationDetails).getTenant()
|
*/
|
||||||
.equalsIgnoreCase(event.getTenant());
|
public HawkbitUI(final EventPushStrategy pushStrategy) {
|
||||||
}
|
this.pushStrategy = pushStrategy;
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
*
|
|
||||||
* @see
|
|
||||||
* com.vaadin.server.ClientConnector.DetachListener#detach(com.vaadin.server
|
|
||||||
* .ClientConnector. DetachEvent)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void detach(final DetachEvent event) {
|
public void detach(final DetachEvent event) {
|
||||||
LOG.info("ManagementUI is detached uiid - {}", getUIId());
|
LOG.info("ManagementUI is detached uiid - {}", getUIId());
|
||||||
|
eventBus.unsubscribe(this);
|
||||||
|
if (pushStrategy != null) {
|
||||||
|
pushStrategy.clean();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void init(final VaadinRequest vaadinRequest) {
|
protected void init(final VaadinRequest vaadinRequest) {
|
||||||
LOG.info("ManagementUI init starts uiid - {}", getUI().getUIId());
|
LOG.info("ManagementUI init starts uiid - {}", getUI().getUIId());
|
||||||
|
if (pushStrategy != null) {
|
||||||
|
pushStrategy.init(getUI());
|
||||||
|
}
|
||||||
addDetachListener(this);
|
addDetachListener(this);
|
||||||
SpringContextHelper.setContext(context);
|
SpringContextHelper.setContext(context);
|
||||||
|
|
||||||
|
|||||||
@@ -108,8 +108,10 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene
|
|||||||
public OutputStream receiveUpload(final String fileName, final String mimeType) {
|
public OutputStream receiveUpload(final String fileName, final String mimeType) {
|
||||||
this.fileName = fileName;
|
this.fileName = fileName;
|
||||||
this.mimeType = mimeType;
|
this.mimeType = mimeType;
|
||||||
|
//reset has directory flag before upload
|
||||||
|
view.setHasDirectory(false);
|
||||||
try {
|
try {
|
||||||
if (view.validate()) {
|
if (view.checkIfSoftwareModuleIsSelected()) {
|
||||||
if (view.checkForDuplicate(fileName)) {
|
if (view.checkForDuplicate(fileName)) {
|
||||||
view.showDuplicateMessage();
|
view.showDuplicateMessage();
|
||||||
} else {
|
} else {
|
||||||
@@ -167,7 +169,7 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene
|
|||||||
view.updateActionCount();
|
view.updateActionCount();
|
||||||
|
|
||||||
// display the duplicate message after streaming all files
|
// display the duplicate message after streaming all files
|
||||||
view.displayDuplicateMessageAfterStreamingAll();
|
view.displayDuplicateValidationMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -292,7 +294,7 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene
|
|||||||
if (view.enableProcessBtn()) {
|
if (view.enableProcessBtn()) {
|
||||||
infoWindow.uploadSessionFinished();
|
infoWindow.uploadSessionFinished();
|
||||||
}
|
}
|
||||||
view.displayDuplicateMessageAfterStreamingAll();
|
view.displayDuplicateValidationMessage();
|
||||||
|
|
||||||
LOG.info("Streaming failed due to :{}", event.getException());
|
LOG.info("Streaming failed due to :{}", event.getException());
|
||||||
}
|
}
|
||||||
@@ -316,7 +318,6 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene
|
|||||||
}
|
}
|
||||||
view.updateActionCount();
|
view.updateActionCount();
|
||||||
infoWindow.uploadFailed(event.getFilename(), failureReason);
|
infoWindow.uploadFailed(event.getFilename(), failureReason);
|
||||||
|
|
||||||
LOG.info("Upload failed for file :{}", event.getReason());
|
LOG.info("Upload failed for file :{}", event.getReason());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ import org.vaadin.spring.events.EventBus;
|
|||||||
import org.vaadin.spring.events.EventScope;
|
import org.vaadin.spring.events.EventScope;
|
||||||
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
|
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
|
||||||
|
|
||||||
|
import com.google.common.base.Strings;
|
||||||
import com.vaadin.event.dd.DragAndDropEvent;
|
import com.vaadin.event.dd.DragAndDropEvent;
|
||||||
import com.vaadin.event.dd.DropHandler;
|
import com.vaadin.event.dd.DropHandler;
|
||||||
import com.vaadin.event.dd.acceptcriteria.AcceptAll;
|
import com.vaadin.event.dd.acceptcriteria.AcceptAll;
|
||||||
@@ -116,6 +117,8 @@ public class UploadLayout extends VerticalLayout {
|
|||||||
|
|
||||||
private DragAndDropWrapper dropAreaWrapper;
|
private DragAndDropWrapper dropAreaWrapper;
|
||||||
|
|
||||||
|
private Boolean hasDirectory = Boolean.FALSE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the upload layout.
|
* Initialize the upload layout.
|
||||||
*/
|
*/
|
||||||
@@ -182,27 +185,60 @@ public class UploadLayout extends VerticalLayout {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void drop(final DragAndDropEvent event) {
|
public void drop(final DragAndDropEvent event) {
|
||||||
if (validate()) {
|
if (validate(event)) {
|
||||||
|
|
||||||
final Html5File[] files = ((WrapperTransferable) event.getTransferable()).getFiles();
|
final Html5File[] files = ((WrapperTransferable) event.getTransferable()).getFiles();
|
||||||
if (files != null) {
|
// reset the flag
|
||||||
for (final Html5File file : files) {
|
hasDirectory = Boolean.FALSE;
|
||||||
if (!checkForDuplicate(file.getFileName())) {
|
for (final Html5File file : files) {
|
||||||
numberOfFileUploadsExpected.incrementAndGet();
|
processFile(file);
|
||||||
file.setStreamVariable(createStreamVariable(file));
|
}
|
||||||
}
|
if (numberOfFileUploadsExpected.get() > 0) {
|
||||||
}
|
processBtn.setEnabled(false);
|
||||||
if (numberOfFileUploadsExpected.get() > 0) {
|
// reset before we start
|
||||||
processBtn.setEnabled(false);
|
uploadInfoWindow.uploadSessionStarted();
|
||||||
// reset before we start
|
} else {
|
||||||
uploadInfoWindow.uploadSessionStarted();
|
// If the upload is not started, it signifies all
|
||||||
}
|
// dropped files as either duplicate or directory.So
|
||||||
// in case if all selected files are duplicate ,then display
|
// display message accordingly
|
||||||
// message
|
displayCompositeMessage();
|
||||||
displayDuplicateMessageAfterStreamingAll();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void processFile(final Html5File file) {
|
||||||
|
if (!isDirectory(file)) {
|
||||||
|
if (!checkForDuplicate(file.getFileName())) {
|
||||||
|
numberOfFileUploadsExpected.incrementAndGet();
|
||||||
|
file.setStreamVariable(createStreamVariable(file));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
hasDirectory = Boolean.TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isDirectory(final Html5File file) {
|
||||||
|
if (Strings.isNullOrEmpty(file.getType()) && file.getFileSize() % 4096 == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void displayCompositeMessage() {
|
||||||
|
final String duplicateMessage = getDuplicateFileValidationMessage();
|
||||||
|
final StringBuilder compositeMessage = new StringBuilder();
|
||||||
|
if (!Strings.isNullOrEmpty(duplicateMessage)) {
|
||||||
|
compositeMessage.append(duplicateMessage);
|
||||||
|
}
|
||||||
|
if (hasDirectory) {
|
||||||
|
if (compositeMessage.length() > 0) {
|
||||||
|
compositeMessage.append("<br>");
|
||||||
|
}
|
||||||
|
compositeMessage.append(i18n.get("message.no.directory.upload"));
|
||||||
|
}
|
||||||
|
if (!compositeMessage.toString().isEmpty()) {
|
||||||
|
uiNotification.displayValidationError(compositeMessage.toString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private VerticalLayout createDropAreaLayout() {
|
private VerticalLayout createDropAreaLayout() {
|
||||||
@@ -313,10 +349,33 @@ public class UploadLayout extends VerticalLayout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Boolean validate() {
|
Boolean validate(DragAndDropEvent event) {
|
||||||
|
// check if drop is valid.If valid ,check if software module is
|
||||||
|
// selected.
|
||||||
|
if(!isFilesDropped(event)){
|
||||||
|
uiNotification.displayValidationError(i18n.get("message.action.not.allowed"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return checkIfSoftwareModuleIsSelected();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isFilesDropped(DragAndDropEvent event) {
|
||||||
|
if (event.getTransferable() instanceof WrapperTransferable) {
|
||||||
|
final Html5File[] files = ((WrapperTransferable) event.getTransferable()).getFiles();
|
||||||
|
// other components can also be wrapped in WrapperTransferable , so
|
||||||
|
// additional check on files
|
||||||
|
if (files == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Boolean checkIfSoftwareModuleIsSelected() {
|
||||||
if (!isSoftwareModuleSelected()) {
|
if (!isSoftwareModuleSelected()) {
|
||||||
uiNotification.displayValidationError(i18n.get("message.error.noSwModuleSelected"));
|
uiNotification.displayValidationError(i18n.get("message.error.noSwModuleSelected"));
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -381,27 +440,30 @@ public class UploadLayout extends VerticalLayout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void displayDuplicateMessageAfterStreamingAll() {
|
void displayDuplicateValidationMessage() {
|
||||||
// check if streaming of all dropped files are completed
|
// check if streaming of all dropped files are completed
|
||||||
if (numberOfFilesActuallyUpload.intValue() == numberOfFileUploadsExpected.intValue()) {
|
if (numberOfFilesActuallyUpload.intValue() == numberOfFileUploadsExpected.intValue()) {
|
||||||
showDuplicateMessage();
|
displayCompositeMessage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private String getDuplicateFileValidationMessage() {
|
||||||
* Show duplicate file selected message.
|
StringBuilder message = new StringBuilder();
|
||||||
*/
|
|
||||||
public void showDuplicateMessage() {
|
|
||||||
if (!duplicateFileNamesList.isEmpty()) {
|
if (!duplicateFileNamesList.isEmpty()) {
|
||||||
final String fileNames = StringUtils.collectionToCommaDelimitedString(duplicateFileNamesList);
|
final String fileNames = StringUtils.collectionToCommaDelimitedString(duplicateFileNamesList);
|
||||||
if (duplicateFileNamesList.size() == 1) {
|
if (duplicateFileNamesList.size() == 1) {
|
||||||
uiNotification.displayValidationError(i18n.get("message.no.duplicateFile") + fileNames);
|
message.append(i18n.get("message.no.duplicateFile") + fileNames);
|
||||||
|
|
||||||
} else if (duplicateFileNamesList.size() > 1) {
|
} else if (duplicateFileNamesList.size() > 1) {
|
||||||
uiNotification.displayValidationError(i18n.get("message.no.duplicateFiles"));
|
message.append(i18n.get("message.no.duplicateFiles"));
|
||||||
}
|
}
|
||||||
duplicateFileNamesList.clear();
|
duplicateFileNamesList.clear();
|
||||||
}
|
}
|
||||||
|
return message.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void showDuplicateMessage() {
|
||||||
|
uiNotification.displayValidationError(getDuplicateFileValidationMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
void increaseNumberOfFileUploadsExpected() {
|
void increaseNumberOfFileUploadsExpected() {
|
||||||
@@ -593,4 +655,8 @@ public class UploadLayout extends VerticalLayout {
|
|||||||
return uiNotification;
|
return uiNotification;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setHasDirectory(Boolean hasDirectory) {
|
||||||
|
this.hasDirectory = hasDirectory;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ public class TargetTagToken extends AbstractTargetTagToken {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private TargetTagAssigmentResult toggleAssignment(final String tagNameSelected) {
|
private TargetTagAssigmentResult toggleAssignment(final String tagNameSelected) {
|
||||||
final Set<String> targetList = new HashSet<String>();
|
final Set<String> targetList = new HashSet<>();
|
||||||
targetList.add(selectedTarget.getControllerId());
|
targetList.add(selectedTarget.getControllerId());
|
||||||
final TargetTagAssigmentResult result = targetManagement.toggleTagAssignment(targetList, tagNameSelected);
|
final TargetTagAssigmentResult result = targetManagement.toggleTagAssignment(targetList, tagNameSelected);
|
||||||
uinotification.displaySuccess(HawkbitCommonUtil.getTargetTagAssigmentMsg(tagNameSelected, result, i18n));
|
uinotification.displaySuccess(HawkbitCommonUtil.getTargetTagAssigmentMsg(tagNameSelected, result, i18n));
|
||||||
@@ -102,7 +102,7 @@ public class TargetTagToken extends AbstractTargetTagToken {
|
|||||||
|
|
||||||
/* To Be Done : this implementation will vary in views */
|
/* To Be Done : this implementation will vary in views */
|
||||||
private List<String> getClickedTagList() {
|
private List<String> getClickedTagList() {
|
||||||
return new ArrayList<String>();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import java.util.StringJoiner;
|
|||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
import javax.annotation.PreDestroy;
|
import javax.annotation.PreDestroy;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.repository.ActionStatusFields;
|
||||||
import org.eclipse.hawkbit.repository.DeploymentManagement;
|
import org.eclipse.hawkbit.repository.DeploymentManagement;
|
||||||
import org.eclipse.hawkbit.repository.exception.CancelActionNotAllowedException;
|
import org.eclipse.hawkbit.repository.exception.CancelActionNotAllowedException;
|
||||||
import org.eclipse.hawkbit.repository.model.Action;
|
import org.eclipse.hawkbit.repository.model.Action;
|
||||||
@@ -43,6 +44,8 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.PageRequest;
|
import org.springframework.data.domain.PageRequest;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
|
import org.springframework.data.domain.Sort;
|
||||||
|
import org.springframework.data.domain.Sort.Direction;
|
||||||
import org.vaadin.spring.events.EventBus;
|
import org.vaadin.spring.events.EventBus;
|
||||||
import org.vaadin.spring.events.EventScope;
|
import org.vaadin.spring.events.EventScope;
|
||||||
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
|
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
|
||||||
@@ -417,10 +420,10 @@ public class ActionHistoryTable extends TreeTable implements Handler {
|
|||||||
|
|
||||||
final org.eclipse.hawkbit.repository.model.Action action = deploymentManagement
|
final org.eclipse.hawkbit.repository.model.Action action = deploymentManagement
|
||||||
.findActionWithDetails(actionId);
|
.findActionWithDetails(actionId);
|
||||||
final Pageable pageReq = new PageRequest(0, 1000);
|
final Pageable pageReq = new PageRequest(0, 1000,
|
||||||
final Page<ActionStatus> actionStatusList = deploymentManagement
|
new Sort(Direction.DESC, ActionStatusFields.ID.getFieldName()));
|
||||||
.findActionStatusMessagesByActionInDescOrder(pageReq, action,
|
final Page<ActionStatus> actionStatusList = deploymentManagement.findActionStatusByAction(pageReq, action,
|
||||||
managementUIState.isActionHistoryMaximized());
|
managementUIState.isActionHistoryMaximized());
|
||||||
final List<ActionStatus> content = actionStatusList.getContent();
|
final List<ActionStatus> content = actionStatusList.getContent();
|
||||||
/*
|
/*
|
||||||
* Since the recent action status and messages are already
|
* Since the recent action status and messages are already
|
||||||
|
|||||||
@@ -107,32 +107,15 @@ public class ManangementConfirmationWindowLayout extends AbstractConfirmationWin
|
|||||||
super.inittialize();
|
super.inittialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
*
|
|
||||||
* @see org.eclipse.hawkbit.server.ui.common.confirmwindow.layout.
|
|
||||||
* AbstractConfirmationWindowLayout# getConfimrationTabs()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
protected Map<String, ConfirmationTab> getConfimrationTabs() {
|
protected Map<String, ConfirmationTab> getConfimrationTabs() {
|
||||||
final Map<String, ConfirmationTab> tabs = new HashMap<String, ConfirmationTab>();
|
final Map<String, ConfirmationTab> tabs = new HashMap<>();
|
||||||
/**
|
|
||||||
* create tab for deleted distribution.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Create tab for SW Module Type delete */
|
|
||||||
if (!managementUIState.getDeletedDistributionList().isEmpty()) {
|
if (!managementUIState.getDeletedDistributionList().isEmpty()) {
|
||||||
tabs.put(i18n.get("caption.delete.dist.accordion.tab"), createDeletedDistributionTab());
|
tabs.put(i18n.get("caption.delete.dist.accordion.tab"), createDeletedDistributionTab());
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* create tab for deleted target.
|
|
||||||
*/
|
|
||||||
if (!managementUIState.getDeletedTargetList().isEmpty()) {
|
if (!managementUIState.getDeletedTargetList().isEmpty()) {
|
||||||
tabs.put(i18n.get("caption.delete.target.accordion.tab"), createDeletedTargetTab());
|
tabs.put(i18n.get("caption.delete.target.accordion.tab"), createDeletedTargetTab());
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* create tab for assignment.
|
|
||||||
*/
|
|
||||||
if (!managementUIState.getAssignedList().isEmpty()) {
|
if (!managementUIState.getAssignedList().isEmpty()) {
|
||||||
tabs.put(i18n.get("caption.assign.dist.accordion.tab"), createAssignmentTab());
|
tabs.put(i18n.get("caption.assign.dist.accordion.tab"), createAssignmentTab());
|
||||||
}
|
}
|
||||||
@@ -196,8 +179,8 @@ public class ManangementConfirmationWindowLayout extends AbstractConfirmationWin
|
|||||||
private void saveAllAssignments(final ConfirmationTab tab) {
|
private void saveAllAssignments(final ConfirmationTab tab) {
|
||||||
final Set<TargetIdName> itemIds = managementUIState.getAssignedList().keySet();
|
final Set<TargetIdName> itemIds = managementUIState.getAssignedList().keySet();
|
||||||
Long distId;
|
Long distId;
|
||||||
List<TargetIdName> targetIdSetList = null;
|
List<TargetIdName> targetIdSetList;
|
||||||
List<TargetIdName> tempIdList = null;
|
List<TargetIdName> tempIdList;
|
||||||
final ActionType actionType = ((ActionTypeOptionGroupLayout.ActionTypeOption) actionTypeOptionGroupLayout
|
final ActionType actionType = ((ActionTypeOptionGroupLayout.ActionTypeOption) actionTypeOptionGroupLayout
|
||||||
.getActionTypeOptionGroup().getValue()).getActionType();
|
.getActionTypeOptionGroup().getValue()).getActionType();
|
||||||
final long forcedTimeStamp = (((ActionTypeOptionGroupLayout.ActionTypeOption) actionTypeOptionGroupLayout
|
final long forcedTimeStamp = (((ActionTypeOptionGroupLayout.ActionTypeOption) actionTypeOptionGroupLayout
|
||||||
@@ -205,7 +188,7 @@ public class ManangementConfirmationWindowLayout extends AbstractConfirmationWin
|
|||||||
? actionTypeOptionGroupLayout.getForcedTimeDateField().getValue().getTime()
|
? actionTypeOptionGroupLayout.getForcedTimeDateField().getValue().getTime()
|
||||||
: Action.NO_FORCE_TIME;
|
: Action.NO_FORCE_TIME;
|
||||||
|
|
||||||
final Map<Long, ArrayList<TargetIdName>> saveAssignedList = new HashMap<Long, ArrayList<TargetIdName>>();
|
final Map<Long, ArrayList<TargetIdName>> saveAssignedList = new HashMap<>();
|
||||||
|
|
||||||
int successAssignmentCount = 0;
|
int successAssignmentCount = 0;
|
||||||
int duplicateAssignmentCount = 0;
|
int duplicateAssignmentCount = 0;
|
||||||
@@ -216,7 +199,7 @@ public class ManangementConfirmationWindowLayout extends AbstractConfirmationWin
|
|||||||
if (saveAssignedList.containsKey(distId)) {
|
if (saveAssignedList.containsKey(distId)) {
|
||||||
targetIdSetList = saveAssignedList.get(distId);
|
targetIdSetList = saveAssignedList.get(distId);
|
||||||
} else {
|
} else {
|
||||||
targetIdSetList = new ArrayList<TargetIdName>();
|
targetIdSetList = new ArrayList<>();
|
||||||
}
|
}
|
||||||
targetIdSetList.add(itemId);
|
targetIdSetList.add(itemId);
|
||||||
saveAssignedList.put(distId, (ArrayList<TargetIdName>) targetIdSetList);
|
saveAssignedList.put(distId, (ArrayList<TargetIdName>) targetIdSetList);
|
||||||
@@ -275,15 +258,13 @@ public class ManangementConfirmationWindowLayout extends AbstractConfirmationWin
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String getAssigmentSuccessMessage(final int assignedCount) {
|
private String getAssigmentSuccessMessage(final int assignedCount) {
|
||||||
final String assignment = FontAwesome.TASKS.getHtml() + SPUILabelDefinitions.HTML_SPACE
|
return FontAwesome.TASKS.getHtml() + SPUILabelDefinitions.HTML_SPACE
|
||||||
+ i18n.get("message.target.assignment", new Object[] { assignedCount });
|
+ i18n.get("message.target.assignment", new Object[] { assignedCount });
|
||||||
return assignment;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getDuplicateAssignmentMessage(final int alreadyAssignedCount) {
|
private String getDuplicateAssignmentMessage(final int alreadyAssignedCount) {
|
||||||
final String alreadyAssigned = FontAwesome.TASKS.getHtml() + SPUILabelDefinitions.HTML_SPACE
|
return FontAwesome.TASKS.getHtml() + SPUILabelDefinitions.HTML_SPACE
|
||||||
+ i18n.get("message.target.alreadyAssigned", new Object[] { alreadyAssignedCount });
|
+ i18n.get("message.target.alreadyAssigned", new Object[] { alreadyAssignedCount });
|
||||||
return alreadyAssigned;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void discardAllAssignments(final ConfirmationTab tab) {
|
private void discardAllAssignments(final ConfirmationTab tab) {
|
||||||
@@ -456,7 +437,7 @@ public class ManangementConfirmationWindowLayout extends AbstractConfirmationWin
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void deleteAllDistributions(final ConfirmationTab tab) {
|
private void deleteAllDistributions(final ConfirmationTab tab) {
|
||||||
final Set<Long> deletedIds = new HashSet<Long>();
|
final Set<Long> deletedIds = new HashSet<>();
|
||||||
managementUIState.getDeletedDistributionList().forEach(distIdName -> deletedIds.add(distIdName.getId()));
|
managementUIState.getDeletedDistributionList().forEach(distIdName -> deletedIds.add(distIdName.getId()));
|
||||||
distributionSetManagement.deleteDistributionSet(deletedIds.toArray(new Long[deletedIds.size()]));
|
distributionSetManagement.deleteDistributionSet(deletedIds.toArray(new Long[deletedIds.size()]));
|
||||||
addToConsolitatedMsg(FontAwesome.TRASH_O.getHtml() + SPUILabelDefinitions.HTML_SPACE
|
addToConsolitatedMsg(FontAwesome.TRASH_O.getHtml() + SPUILabelDefinitions.HTML_SPACE
|
||||||
@@ -516,7 +497,7 @@ public class ManangementConfirmationWindowLayout extends AbstractConfirmationWin
|
|||||||
final IndexedContainer contactContainer = new IndexedContainer();
|
final IndexedContainer contactContainer = new IndexedContainer();
|
||||||
contactContainer.addContainerProperty(TARGET_ID, String.class, "");
|
contactContainer.addContainerProperty(TARGET_ID, String.class, "");
|
||||||
contactContainer.addContainerProperty(TARGET_NAME, String.class, "");
|
contactContainer.addContainerProperty(TARGET_NAME, String.class, "");
|
||||||
Item item = null;
|
Item item;
|
||||||
for (final TargetIdName targteId : managementUIState.getDeletedTargetList()) {
|
for (final TargetIdName targteId : managementUIState.getDeletedTargetList()) {
|
||||||
item = contactContainer.addItem(targteId);
|
item = contactContainer.addItem(targteId);
|
||||||
item.getItemProperty(TARGET_ID).setValue(targteId.getControllerId());
|
item.getItemProperty(TARGET_ID).setValue(targteId.getControllerId());
|
||||||
|
|||||||
@@ -0,0 +1,244 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*/
|
||||||
|
package org.eclipse.hawkbit.ui.push;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.BlockingDeque;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.LinkedBlockingDeque;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.ScheduledFuture;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.eventbus.event.DistributionSetTagCreatedBulkEvent;
|
||||||
|
import org.eclipse.hawkbit.eventbus.event.EntityEvent;
|
||||||
|
import org.eclipse.hawkbit.eventbus.event.RolloutChangeEvent;
|
||||||
|
import org.eclipse.hawkbit.eventbus.event.RolloutGroupChangeEvent;
|
||||||
|
import org.eclipse.hawkbit.eventbus.event.TargetCreatedEvent;
|
||||||
|
import org.eclipse.hawkbit.eventbus.event.TargetDeletedEvent;
|
||||||
|
import org.eclipse.hawkbit.eventbus.event.TargetInfoUpdateEvent;
|
||||||
|
import org.eclipse.hawkbit.eventbus.event.TargetTagCreatedBulkEvent;
|
||||||
|
import org.eclipse.hawkbit.im.authentication.TenantAwareAuthenticationDetails;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.security.core.context.SecurityContext;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
|
||||||
|
import org.vaadin.spring.events.EventBus;
|
||||||
|
import org.vaadin.spring.events.EventBus.SessionEventBus;
|
||||||
|
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
import com.google.common.eventbus.AllowConcurrentEvents;
|
||||||
|
import com.google.common.eventbus.Subscribe;
|
||||||
|
import com.vaadin.server.VaadinSession;
|
||||||
|
import com.vaadin.server.VaadinSession.State;
|
||||||
|
import com.vaadin.server.WrappedSession;
|
||||||
|
import com.vaadin.ui.UI;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link EventPushStrategy} implementation which retrieves events from
|
||||||
|
* {@link com.google.common.eventbus.EventBus} and store them first in an queue
|
||||||
|
* where they will dispatched every 2 seconds to the {@link EventBus} in a
|
||||||
|
* Vaadin access thread {@link UI#access(Runnable)}.
|
||||||
|
*
|
||||||
|
* This strategy avoids blocking UIs when too many events are fired and
|
||||||
|
* dispatched to the UI thread. The UI will freeze in the time. To avoid that
|
||||||
|
* all events are collected first and same events are merged to a list of events
|
||||||
|
* before they dispatched to the UI thread.
|
||||||
|
*
|
||||||
|
* The strategy also verifies the current tenant in the session with the tenant
|
||||||
|
* in the event and only forwards event from the right tenant to the UI.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class DelayedEventBusPushStrategy implements EventPushStrategy {
|
||||||
|
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(DelayedEventBusPushStrategy.class);
|
||||||
|
|
||||||
|
private static final int BLOCK_SIZE = 10_000;
|
||||||
|
private final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
|
||||||
|
private final BlockingDeque<org.eclipse.hawkbit.eventbus.event.Event> queue = new LinkedBlockingDeque<>(BLOCK_SIZE);
|
||||||
|
private final EventBus.SessionEventBus eventBus;
|
||||||
|
private final com.google.common.eventbus.EventBus systemEventBus;
|
||||||
|
|
||||||
|
private ScheduledFuture<?> jobHandle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* only events defined in the set are dispatched to the session event bus.
|
||||||
|
*/
|
||||||
|
private static final Set<Class<?>> UI_EVENTS = Sets.newHashSet(TargetInfoUpdateEvent.class,
|
||||||
|
TargetCreatedEvent.class, TargetDeletedEvent.class, RolloutChangeEvent.class, RolloutGroupChangeEvent.class,
|
||||||
|
TargetTagCreatedBulkEvent.class, DistributionSetTagCreatedBulkEvent.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param eventBus
|
||||||
|
* the session event bus to where the events should be dispatched
|
||||||
|
* @param systemEventBus
|
||||||
|
* the system event bus where to retrieve the events from the
|
||||||
|
* back-end
|
||||||
|
*/
|
||||||
|
public DelayedEventBusPushStrategy(final SessionEventBus eventBus,
|
||||||
|
final com.google.common.eventbus.EventBus systemEventBus) {
|
||||||
|
this.eventBus = eventBus;
|
||||||
|
this.systemEventBus = systemEventBus;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An {@link com.google.common.eventbus.EventBus} subscriber which
|
||||||
|
* subscribes {@link EntityEvent} from the repository to dispatch these
|
||||||
|
* events to the UI {@link SessionEventBus}.
|
||||||
|
*
|
||||||
|
* @param event
|
||||||
|
* the entity event which has been published from the repository
|
||||||
|
*/
|
||||||
|
@Subscribe
|
||||||
|
@AllowConcurrentEvents
|
||||||
|
public void dispatch(final org.eclipse.hawkbit.eventbus.event.Event event) {
|
||||||
|
// to dispatch too many events which are not interested on the UI
|
||||||
|
if (UI_EVENTS.contains(event.getClass()) && !queue.offer(event)) {
|
||||||
|
LOG.warn("Deque limit is reached, cannot add more events!!! Dropped event is {}", event);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(final UI vaadinUI) {
|
||||||
|
LOG.debug("Initialize delayed event push strategy");
|
||||||
|
jobHandle = executorService.scheduleWithFixedDelay(new DispatchRunnable(vaadinUI, vaadinUI.getSession()), 500,
|
||||||
|
2000, TimeUnit.MILLISECONDS);
|
||||||
|
systemEventBus.register(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clean() {
|
||||||
|
LOG.debug("Cleanup resources");
|
||||||
|
jobHandle.cancel(true);
|
||||||
|
systemEventBus.unregister(this);
|
||||||
|
executorService.shutdownNow();
|
||||||
|
queue.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the tenant within the event is equal with the current tenant in
|
||||||
|
* the context.
|
||||||
|
*
|
||||||
|
* @param userContext
|
||||||
|
* the security context of the current session
|
||||||
|
* @param event
|
||||||
|
* the event to dispatch to the UI
|
||||||
|
* @return {@code true} if the event can be dispatched to the UI otherwise
|
||||||
|
* {@code false}
|
||||||
|
*/
|
||||||
|
protected boolean eventSecurityCheck(final SecurityContext userContext,
|
||||||
|
final org.eclipse.hawkbit.eventbus.event.Event event) {
|
||||||
|
if (userContext == null || userContext.getAuthentication() == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final Object tenantAuthenticationDetails = userContext.getAuthentication().getDetails();
|
||||||
|
if (tenantAuthenticationDetails instanceof TenantAwareAuthenticationDetails) {
|
||||||
|
return ((TenantAwareAuthenticationDetails) tenantAuthenticationDetails).getTenant()
|
||||||
|
.equalsIgnoreCase(event.getTenant());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final class DispatchRunnable implements Runnable {
|
||||||
|
|
||||||
|
private final UI vaadinUI;
|
||||||
|
private final VaadinSession vaadinSession;
|
||||||
|
|
||||||
|
private DispatchRunnable(final UI ui, final VaadinSession session) {
|
||||||
|
vaadinUI = ui;
|
||||||
|
vaadinSession = session;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
LOG.debug("UI EventBus aggregator started");
|
||||||
|
final long timestamp = System.currentTimeMillis();
|
||||||
|
final List<org.eclipse.hawkbit.eventbus.event.Event> events = new LinkedList<>();
|
||||||
|
for (int i = 0; i < BLOCK_SIZE; i++) {
|
||||||
|
final org.eclipse.hawkbit.eventbus.event.Event pollEvent = queue.poll();
|
||||||
|
if (pollEvent == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
events.add(pollEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (events.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vaadinSession == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG.debug("UI EventBus aggregator session: {}", vaadinSession);
|
||||||
|
|
||||||
|
final WrappedSession wrappedSession = vaadinSession.getSession();
|
||||||
|
if (wrappedSession == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int eventsSize = events.size();
|
||||||
|
|
||||||
|
doDispatch(events, wrappedSession);
|
||||||
|
|
||||||
|
LOG.debug("UI EventBus aggregator done with sending {} events in {} ms", eventsSize,
|
||||||
|
System.currentTimeMillis() - timestamp);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doDispatch(final List<org.eclipse.hawkbit.eventbus.event.Event> events,
|
||||||
|
final WrappedSession wrappedSession) {
|
||||||
|
final SecurityContext userContext = (SecurityContext) wrappedSession
|
||||||
|
.getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
|
||||||
|
final SecurityContext oldContext = SecurityContextHolder.getContext();
|
||||||
|
try {
|
||||||
|
SecurityContextHolder.setContext(userContext);
|
||||||
|
vaadinUI.access(() -> {
|
||||||
|
if (vaadinSession.getState() != State.OPEN) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fowardEvents(events, userContext);
|
||||||
|
|
||||||
|
// send a list of events, because ui performance issues
|
||||||
|
publishEventAsList(events, userContext, TargetInfoUpdateEvent.class);
|
||||||
|
publishEventAsList(events, userContext, TargetCreatedEvent.class);
|
||||||
|
publishEventAsList(events, userContext, TargetDeletedEvent.class);
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
SecurityContextHolder.setContext(oldContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void publishEventAsList(final List<org.eclipse.hawkbit.eventbus.event.Event> events,
|
||||||
|
final SecurityContext userContext, final Class<?> eventType) {
|
||||||
|
final List<org.eclipse.hawkbit.eventbus.event.Event> bulkEvents = events.stream()
|
||||||
|
.filter(event -> DelayedEventBusPushStrategy.this.eventSecurityCheck(userContext, event)
|
||||||
|
&& eventType.isInstance(event))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
if (bulkEvents.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
eventBus.publish(vaadinUI, bulkEvents);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fowardEvents(final List<org.eclipse.hawkbit.eventbus.event.Event> events,
|
||||||
|
final SecurityContext userContext) {
|
||||||
|
events.stream().filter(event -> DelayedEventBusPushStrategy.this.eventSecurityCheck(userContext, event))
|
||||||
|
.forEach(event -> eventBus.publish(vaadinUI, event));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*/
|
||||||
|
package org.eclipse.hawkbit.ui.push;
|
||||||
|
|
||||||
|
import com.vaadin.ui.UI;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface declaring a strategy to push events from the back-end to the UI.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface EventPushStrategy {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the event push strategy, this is bound to the life-cycle of
|
||||||
|
* the {@link UI} so the strategy can be initialized based a {@link UI}.
|
||||||
|
*
|
||||||
|
* @param vaadinUI
|
||||||
|
* the {@link UI}
|
||||||
|
*/
|
||||||
|
void init(UI vaadinUI);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cleans up resources when the strategy is not be used anymore e.g.
|
||||||
|
* {@link UI#detach()}.
|
||||||
|
*/
|
||||||
|
void clean();
|
||||||
|
}
|
||||||
@@ -313,7 +313,7 @@ soft.module.os =OS
|
|||||||
message.error.noFileSelected = No file selected for upload
|
message.error.noFileSelected = No file selected for upload
|
||||||
message.error.noProvidedName = Please provide custom file name
|
message.error.noProvidedName = Please provide custom file name
|
||||||
message.error.noSwModuleSelected = Please select a software module
|
message.error.noSwModuleSelected = Please select a software module
|
||||||
message.no.duplicateFiles = duplicate files selected
|
message.no.duplicateFiles = Duplicate files selected
|
||||||
message.no.duplicateFile = Duplicate file selected :
|
message.no.duplicateFile = Duplicate file selected :
|
||||||
message.delete.artifact = Are you sure that you want to delete artifact {0} ?
|
message.delete.artifact = Are you sure that you want to delete artifact {0} ?
|
||||||
message.duplicate.filename = Duplicate file name
|
message.duplicate.filename = Duplicate file name
|
||||||
|
|||||||
@@ -310,7 +310,7 @@ soft.module.os =OS
|
|||||||
message.error.noFileSelected = No file selected for upload
|
message.error.noFileSelected = No file selected for upload
|
||||||
message.error.noProvidedName = Please provide custom file name
|
message.error.noProvidedName = Please provide custom file name
|
||||||
message.error.noSwModuleSelected = Please select a software module
|
message.error.noSwModuleSelected = Please select a software module
|
||||||
message.no.duplicateFiles = duplicate files selected
|
message.no.duplicateFiles = Duplicate files selected
|
||||||
message.no.duplicateFile = Duplicate file selected :
|
message.no.duplicateFile = Duplicate file selected :
|
||||||
message.delete.artifact = Are you sure that you want to delete artifact {0} ?
|
message.delete.artifact = Are you sure that you want to delete artifact {0} ?
|
||||||
message.duplicate.filename = Duplicate file name
|
message.duplicate.filename = Duplicate file name
|
||||||
|
|||||||
@@ -305,7 +305,7 @@ soft.module.os =OS
|
|||||||
message.error.noFileSelected = No file selected for upload
|
message.error.noFileSelected = No file selected for upload
|
||||||
message.error.noProvidedName = Please provide custom file name
|
message.error.noProvidedName = Please provide custom file name
|
||||||
message.error.noSwModuleSelected = Please select a software module
|
message.error.noSwModuleSelected = Please select a software module
|
||||||
message.no.duplicateFiles = duplicate files selected
|
message.no.duplicateFiles = Duplicate files selected
|
||||||
message.no.duplicateFile = Duplicate file selected :
|
message.no.duplicateFile = Duplicate file selected :
|
||||||
message.delete.artifact = Are you sure that you want to delete artifact {0} ?
|
message.delete.artifact = Are you sure that you want to delete artifact {0} ?
|
||||||
message.duplicate.filename = Duplicate file name
|
message.duplicate.filename = Duplicate file name
|
||||||
|
|||||||
Reference in New Issue
Block a user