Skip to content
Snippets Groups Projects
Commit fc102ad0 authored by Lukasz Lopatowski's avatar Lukasz Lopatowski
Browse files

Merge branch '303-domain-removal' into 'develop'

One Webhook for all Domain actions

See merge request !269
parents 117014d7 ba70c127
No related branches found
No related tags found
2 merge requests!273Release 1.8.0 update,!269One Webhook for all Domain actions
Pipeline #95386 passed
Showing
with 42 additions and 88 deletions
......@@ -7,6 +7,7 @@ import lombok.NoArgsConstructor;
import lombok.Setter;
import net.geant.nmaas.kubernetes.remote.entities.KClusterState;
import java.io.Serializable;
import java.time.OffsetDateTime;
import java.util.List;
......@@ -15,7 +16,7 @@ import java.util.List;
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class RemoteClusterView {
public class RemoteClusterView implements Serializable {
private Long id;
......
......@@ -2,7 +2,7 @@ package net.geant.nmaas.orchestration.jobs;
import lombok.extern.slf4j.Slf4j;
import net.geant.nmaas.orchestration.exceptions.WebServiceCommunicationException;
import net.geant.nmaas.portal.api.domain.DomainRemovalDto;
import net.geant.nmaas.portal.api.domain.DomainActionDto;
import net.geant.nmaas.portal.api.domain.DomainView;
import net.geant.nmaas.portal.api.domain.WebhookEventDto;
import net.geant.nmaas.portal.api.exceptions.MissingElementException;
......@@ -20,10 +20,10 @@ import java.security.GeneralSecurityException;
@Slf4j
@Component
public class DomainRemovalJob extends WebhookJob {
public class DomainActionJob extends WebhookJob {
@Autowired
public DomainRemovalJob(RestClient restClient, WebhookEventService webhookEventService, ModelMapper modelMapper) {
public DomainActionJob(RestClient restClient, WebhookEventService webhookEventService, ModelMapper modelMapper) {
super(restClient, webhookEventService, modelMapper);
}
......@@ -32,24 +32,24 @@ public class DomainRemovalJob extends WebhookJob {
log.debug("Started DomainRemovalJob ...");
JobDataMap dataMap = context.getJobDetail().getJobDataMap();
Long webhookId = dataMap.getLong("webhookId");
boolean hardRemoval = dataMap.getBoolean("hardRemoval");
String action = dataMap.getString("action");
DomainView domain = (DomainView) dataMap.get("domain");
try {
WebhookEventDto webhook = webhookEventService.getById(webhookId);
if (!WebhookEventType.DOMAIN_REMOVAL.equals(webhook.getEventType())) {
log.warn("Webhook's event type with id {} has been updated. DomainRemovalJob is abandoned", webhookId);
if (!WebhookEventType.DOMAIN_ACTION.equals(webhook.getEventType())) {
log.warn("Webhook's event type with id {} has been updated. DomainActionJob is abandoned", webhookId);
return;
}
callWebhook(webhook, new DomainRemovalDto(domain, hardRemoval));
callWebhook(webhook, new DomainActionDto(domain, action));
} catch (GeneralSecurityException e) {
log.error("Failed to decrypt webhook with id {}", webhookId);
throw new JobExecutionException("Failed webhook decryption");
} catch (MissingElementException e) {
log.warn("Webhook does not exist. DomainRemovalJob is abandoned");
log.warn("Webhook does not exist. DomainActionJob is abandoned");
} catch (WebServiceCommunicationException e) {
log.error("Failed to communicate with external system for the webhook of domain removal with id {}", domain.getId());
log.error("Failed to communicate with external system for the webhook of domain action with id {}", domain.getId());
throw new JobExecutionException("Failed communication with external system");
}
}
......
package net.geant.nmaas.orchestration.jobs;
import lombok.extern.slf4j.Slf4j;
import net.geant.nmaas.orchestration.exceptions.WebServiceCommunicationException;
import net.geant.nmaas.portal.api.domain.DomainView;
import net.geant.nmaas.portal.api.domain.WebhookEventDto;
import net.geant.nmaas.portal.api.exceptions.MissingElementException;
import net.geant.nmaas.portal.persistent.entity.Domain;
import net.geant.nmaas.portal.persistent.entity.WebhookEventType;
import net.geant.nmaas.portal.service.DomainService;
import net.geant.nmaas.portal.service.impl.WebhookEventService;
import org.modelmapper.ModelMapper;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestClient;
import java.security.GeneralSecurityException;
@Slf4j
@Component
public class DomainCreationJob extends WebhookJob {
private final DomainService domainService;
@Autowired
public DomainCreationJob(RestClient restClient, WebhookEventService webhookEventService, ModelMapper modelMapper, DomainService domainService) {
super(restClient, webhookEventService, modelMapper);
this.domainService = domainService;
}
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
JobDataMap dataMap = context.getJobDetail().getJobDataMap();
Long webhookId = dataMap.getLong("webhookId");
Long domainId = dataMap.getLong("domainId");
try {
WebhookEventDto webhook = webhookEventService.getById(webhookId);
if (!WebhookEventType.DOMAIN_CREATION.equals(webhook.getEventType())) {
log.warn("Webhook's event type with id {} has been updated. DomainCreationJob is abandoned", webhookId);
return;
}
Domain domain = domainService.findDomain(domainId).orElseThrow(() -> new MissingElementException(String.format("Domain with id: %d cannot be found", domainId)));
callWebhook(webhook, modelMapper.map(domain, DomainView.class));
} catch (GeneralSecurityException e) {
log.error("Failed to decrypt webhook with id {}", webhookId);
throw new JobExecutionException("Failed webhook decryption");
} catch (MissingElementException e) {
log.warn("Webhook or domain does not exist. DomainCreationJob is abandoned");
} catch (WebServiceCommunicationException e) {
log.error("Failed to communicate with external system for the webhook of domain creation with id {}", domainId);
throw new JobExecutionException("Failed communication with external system");
}
}
}
......@@ -7,8 +7,8 @@ import lombok.Setter;
@AllArgsConstructor
@Getter
@Setter
public class DomainRemovalDto {
public class DomainActionDto {
private DomainView domainView;
private boolean hardRemoval;
private String action;
}
package net.geant.nmaas.portal.api.domain;
import java.io.Serializable;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Getter;
......@@ -11,7 +12,7 @@ import net.geant.nmaas.dcn.deployment.DcnDeploymentType;
@NoArgsConstructor
@Getter
@Setter
public class DomainDcnDetailsView {
public class DomainDcnDetailsView implements Serializable {
private Long id;
......
......@@ -7,11 +7,13 @@ import lombok.Setter;
import jakarta.validation.constraints.NotNull;
import java.io.Serializable;
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
public class DomainGroupViewS {
public class DomainGroupViewS implements Serializable {
@NotNull
private Long id;
......
......@@ -6,12 +6,14 @@ import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.io.Serializable;
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@Builder
public class DomainTechDetailsView {
public class DomainTechDetailsView implements Serializable {
private Long id;
......
......@@ -2,8 +2,7 @@ package net.geant.nmaas.portal.persistent.entity;
public enum WebhookEventType {
DOMAIN_CREATION,
DOMAIN_REMOVAL,
DOMAIN_ACTION,
APPLICATION_DEPLOYMENT,
USER_ASSIGNMENT,
DOMAIN_GROUP_CHANGE
......
......@@ -3,9 +3,8 @@ package net.geant.nmaas.portal.service.impl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.geant.nmaas.orchestration.jobs.AppDeploymentJob;
import net.geant.nmaas.orchestration.jobs.DomainCreationJob;
import net.geant.nmaas.orchestration.jobs.DomainGroupJob;
import net.geant.nmaas.orchestration.jobs.DomainRemovalJob;
import net.geant.nmaas.orchestration.jobs.DomainActionJob;
import net.geant.nmaas.orchestration.jobs.UserDomainAssignmentJob;
import net.geant.nmaas.portal.api.domain.DomainGroupView;
import net.geant.nmaas.portal.api.domain.DomainView;
......@@ -20,6 +19,7 @@ import net.geant.nmaas.portal.persistent.repositories.WebhookEventRepository;
import net.geant.nmaas.scheduling.ScheduleManager;
import net.geant.nmaas.utils.logging.LogLevel;
import net.geant.nmaas.utils.logging.Loggable;
import org.modelmapper.ModelMapper;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
......@@ -35,14 +35,15 @@ public class WebhooksEventListener {
private final WebhookEventRepository webhookEventRepository;
private final ScheduleManager scheduleManager;
private final ModelMapper modelMapper;
@EventListener
@Loggable(LogLevel.INFO)
@Transactional
public void trigger(DomainCreatedEvent event) {
final Domain domain = event.getDomainEntity();
webhookEventRepository.findIdByEventType(WebhookEventType.DOMAIN_CREATION)
.forEach(id -> scheduleManager.createOneTimeJob(DomainCreationJob.class, "DomainCreation_" + id + "_" + domain.getId(), Map.of("webhookId", id, "domainId", domain.getId())));
webhookEventRepository.findIdByEventType(WebhookEventType.DOMAIN_ACTION)
.forEach(id -> scheduleManager.createOneTimeJob(DomainActionJob.class, "DomainCreate_"+ event.getDomain()+"_" + id + "_" + domain.getId(), Map.of("webhookId", id, "domain", modelMapper.map(domain, DomainView.class), "action", "create")));
}
@EventListener
......@@ -50,8 +51,9 @@ public class WebhooksEventListener {
@Transactional
public void trigger(DomainRemovalEvent event) {
final DomainView domainView = event.getDomainView();
webhookEventRepository.findIdByEventType(WebhookEventType.DOMAIN_REMOVAL)
.forEach(id -> scheduleManager.createOneTimeJob(DomainRemovalJob.class, "DomainRemoval_" + id + "_" + domainView.getId(), Map.of("webhookId", id, "domain", domainView, "hardRemoval", event.isHardRemoval())));
String action = event.isHardRemoval() ? "delete" : "softDelete";
webhookEventRepository.findIdByEventType(WebhookEventType.DOMAIN_ACTION)
.forEach(id -> scheduleManager.createOneTimeJob(DomainActionJob.class, "Domain" +action+"_"+ event.getDomainView()+"_" + id + "_" + domainView.getId(), Map.of("webhookId", id, "domain", domainView, "action", action)));
}
@EventListener
......
package net.geant.nmaas.orchestration.jobs;
import net.geant.nmaas.portal.api.domain.DomainView;
import net.geant.nmaas.portal.api.domain.WebhookEventDto;
import net.geant.nmaas.portal.persistent.entity.Domain;
import net.geant.nmaas.portal.persistent.entity.WebhookEventType;
......@@ -20,7 +21,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class DomainCreationJobTest {
public class DomainActionJobTest {
private final RestClient restClient = RestClient.create();
private final WebhookEventService webhookEventService = mock(WebhookEventService.class);
......@@ -30,17 +31,22 @@ public class DomainCreationJobTest {
void shouldExecuteSampleJob() throws GeneralSecurityException {
JobDataMap dataMap = new JobDataMap();
dataMap.put("webhookId", 10L);
dataMap.put("domainId", 1L);
DomainView domain = new DomainView();
domain.setId(1L);
domain.setName("name");
domain.setCodename("codename");
dataMap.put("domain", domain);
dataMap.put("action", "create");
JobDetail jobDetail = mock(JobDetail.class);
when(jobDetail.getJobDataMap()).thenReturn(dataMap);
JobExecutionContext jobExecutionContext = mock(JobExecutionContext.class);
when(jobExecutionContext.getJobDetail()).thenReturn(jobDetail);
when(webhookEventService.getById(10L)).thenReturn(
new WebhookEventDto(10L, "webhook-name", "https://example.webhook-url.pl", WebhookEventType.DOMAIN_CREATION));
new WebhookEventDto(10L, "webhook-name", "https://example.webhook-url.pl", WebhookEventType.DOMAIN_ACTION));
when(domainService.findDomain(1L)).thenReturn(Optional.of(new Domain("name", "codename")));
assertThrows(JobExecutionException.class, () -> {
DomainCreationJob job = new DomainCreationJob(restClient, webhookEventService, new ModelMapper(), domainService);
DomainActionJob job = new DomainActionJob(restClient, webhookEventService, new ModelMapper());
job.execute(jobExecutionContext);
});
}
......
......@@ -45,8 +45,8 @@ class WebhookEventServiceTest {
@Test
void crudWebhookEvent() throws GeneralSecurityException {
webhookEventDto = new WebhookEventDto(2L, "webhook2", "https://example.com/webhook2", WebhookEventType.DOMAIN_CREATION, "xxxxyyyy", "Authorization");
webhookEvent = new WebhookEvent(2L, "webhook2", "https://example.com/webhook2", WebhookEventType.DOMAIN_CREATION, "sjxV/ytRIoHjXy+CtXMzD4T+bntbqzQX25eztXbJ9r4gIZXT", "Authorization");
webhookEventDto = new WebhookEventDto(2L, "webhook2", "https://example.com/webhook2", WebhookEventType.DOMAIN_ACTION, "xxxxyyyy", "Authorization");
webhookEvent = new WebhookEvent(2L, "webhook2", "https://example.com/webhook2", WebhookEventType.DOMAIN_ACTION, "sjxV/ytRIoHjXy+CtXMzD4T+bntbqzQX25eztXbJ9r4gIZXT", "Authorization");
when(webhookEventRepository.save(isA(WebhookEvent.class))).thenReturn(webhookEvent);
when(encryptionService.encrypt(anyString())).thenAnswer(i -> "sjxV/ytRIoHjXy+CtXMzD4T+bntbqzQX25eztXbJ9r4gIZXT");
when(encryptionService.decrypt(anyString())).thenAnswer(i -> "xxxxyyyy");
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment