Merge pull request #1257 from navi-infra/INFRA-3970

INFRA-3970 | Dhruv | Adds support for CR in outbound
This commit is contained in:
Dhruv Joshi
2024-12-16 22:01:01 +05:30
committed by GitHub
31 changed files with 794 additions and 173 deletions

Submodule kutegen updated: 0bb5b971c9...7e3941e08a

View File

@@ -0,0 +1,11 @@
package com.navi.infra.portal.domain.manifest;
public interface ManifestInfo {
String getName();
String getEnvironment();
String getTeam();
}

View File

@@ -1,8 +1,10 @@
package com.navi.infra.portal.repository;
import com.navi.infra.portal.domain.manifest.Manifest;
import com.navi.infra.portal.domain.manifest.ManifestInfo;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
@@ -35,7 +37,10 @@ public interface ManifestRepository extends JpaRepository<Manifest, Long> {
+ "JOIN manifest m ON e.manifest_id = m.id "
+ "WHERE jsonb_extract_path_text(CAST(e.data AS jsonb), 'database', 'instanceName') = :instanceName and m.environment = :environment",
nativeQuery = true)
Optional<Long> findIdByInstanceName(@Param("instanceName") String instanceName, @Param("environment") String environment);
Optional<Long> findIdByInstanceName(
@Param("instanceName") String instanceName,
@Param("environment") String environment
);
@Query(value = "SELECT * "
+ "FROM manifest m "
@@ -68,4 +73,7 @@ public interface ManifestRepository extends JpaRepository<Manifest, Long> {
@Param("privileges") List<String> privileges,
Pageable pageable
);
@Query(value = "SELECT m.name, m.environment, m.data -> 'team' ->> 'name' as team from manifest m", nativeQuery = true)
Set<ManifestInfo> getManifestInfo();
}

View File

@@ -24,6 +24,7 @@ import com.navi.infra.portal.domain.manifest.ExtraResources;
import com.navi.infra.portal.domain.manifest.LoadBalancer;
import com.navi.infra.portal.domain.manifest.Manifest;
import com.navi.infra.portal.domain.manifest.ManifestAudit;
import com.navi.infra.portal.domain.manifest.ManifestInfo;
import com.navi.infra.portal.domain.manifest.SecretConfig;
import com.navi.infra.portal.domain.manifest.StatusMarker;
import com.navi.infra.portal.domain.user.User;
@@ -891,7 +892,7 @@ public class ManifestService {
public Map<String, Object> exportManifestByIdAndVersion(Long id, Long version) {
final Set<String> keysToExclude = Set.of("version", "id", "infraVertical", "cluster",
"groupName", "kmsKeyId", "product", "internalCommonApiGatewayUrl",
"groupName", "kmsKeyId", "product", "internalCommonApiGatewayUrl", "hashedIdentifier",
"commonApiGatewayUrl");
final Map keysToReplace = Map.of("isDeployed", false, "ids", emptyList());
var manifest = version == null ? fetchById(id) : fetchByIdAndVersion(id, version);
@@ -931,6 +932,10 @@ public class ManifestService {
}
public Set<ManifestInfo> fetchManifestInfo() {
return manifestRepository.getManifestInfo();
}
public List<Manifest> fetchAllManifests() {
return manifestRepository.findAll();
}

View File

@@ -17,6 +17,19 @@ import org.springframework.stereotype.Component;
@Component
public class MapUtil {
public static final String INSERT_IN_END_IDENTIFIER = "*";
@SuppressWarnings("unchecked")
private static String getHashedIdentifierValue(Object obj) {
return (String) ((Map<String, Object>) obj).get("hashedIdentifier");
}
private static boolean isNewEntry(List<Object> list, Object value) {
String hashedIdentifier = getHashedIdentifierValue(value);
return list.stream().noneMatch(
obj -> hashedIdentifier.equals(getHashedIdentifierValue(obj)));
}
private static boolean isInteger(String s) {
try {
Integer.parseInt(s);
@@ -104,7 +117,10 @@ public class MapUtil {
}
if (tmpMap.get(s) instanceof List) {
final var tmpList = (List<Object>) tmpMap.get(s);
final int index = Integer.valueOf(splitPath[++i], 10);
if (splitPath[++i].equals(INSERT_IN_END_IDENTIFIER)) {
throw new IndexOutOfBoundsException("New entry is being added to the list");
}
final int index = Integer.valueOf(splitPath[i], 10);
if (i == splitPath.length - 1) {
return tmpList.get(index);
}
@@ -165,6 +181,14 @@ public class MapUtil {
try {
idx = Integer.parseInt(paths.get(0));
} catch (NumberFormatException e) {
if (INSERT_IN_END_IDENTIFIER.equals(paths.get(0))) {
if (isNewEntry(list, value)) {
populateList(list, list.size());
return list.set(list.size() - 1, value);
} else {
return null;
}
}
throw new RuntimeException(format("Failed json path is wrong: %s", join(", ", paths)),
e);
}

View File

@@ -1,8 +1,11 @@
package com.navi.infra.portal.util.manifest;
import static com.navi.infra.portal.util.EncoderDecoderUtil.base64Encode;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Maps;
import com.navi.infra.portal.v2.changerequest.entity.ChangeRequest;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
@@ -10,6 +13,8 @@ import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.IntStream;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@@ -18,6 +23,18 @@ import org.springframework.stereotype.Component;
public class ChangeRequestUtils {
private static final ObjectMapper objectMapper = new ObjectMapper();
private static final Map<String, Function<Map<String, Object>, String>> identifierPopulatorForlimitPath =
Map.of(
"/deployment/allowEndpoint", ChangeRequestUtils::getIdentifierForAllowEndpoint
);
@SuppressWarnings("unchecked")
private static String getIdentifierForAllowEndpoint(Map<String, Object> value) {
var endpointValue = (Map<String, String>) value.get("value");
var decodedIdentifier = String.format("%s:%s", endpointValue.get("host"),
endpointValue.get("port"));
return base64Encode(decodedIdentifier);
}
@SuppressWarnings("unchecked")
public static Object safeMapAccess(Object obj, String key) {
@@ -42,6 +59,17 @@ public class ChangeRequestUtils {
.orElse(null);
}
@SuppressWarnings("unchecked")
public static Object safeListAccess(Object obj, String uniqueIdentifier) {
if (!(obj instanceof List)) {
return null;
}
return Optional.of(obj).flatMap(list -> ((List<Object>) list).stream()
.filter(map -> ((Map<String, Object>) map).containsValue(uniqueIdentifier))
.findAny())
.orElse(null);
}
public static boolean isMap(Object obj) {
return obj instanceof Map;
}
@@ -165,7 +193,7 @@ public class ChangeRequestUtils {
break;
}
}
return currentWeight != null && (previousWeight == null || currentWeight > previousWeight);
}
@@ -238,17 +266,8 @@ public class ChangeRequestUtils {
var curPreManifestObj = safeMapAccess(preManifestObject, key);
if (isTarget(currentLimitObj) && isMap(currentLimitObj)) {
var mapCurrentLimitObject = (Map<String, Object>) currentLimitObj;
if (mapCurrentLimitObject.get("forEach") != null && currentManifestObj != null) {
var listCurrentManifestValue = (List<Map<String, Object>>) currentManifestObj;
for (var i = 0; i < listCurrentManifestValue.size(); i++) {
if (hasBreachedAndIsDifferent(
(Map<String, Object>) mapCurrentLimitObject.get("forEach"),
listCurrentManifestValue.get(i), safeListAccess(curPreManifestObj, i),
manifestEnv)) {
keysCausingChangeRequest.add(key);
}
}
}
handleForEach(mapCurrentLimitObject, currentManifestObj, curPreManifestObj, key,
manifestEnv, keysCausingChangeRequest);
if (hasBreachedAndIsDifferent(mapCurrentLimitObject, currentManifestObj,
curPreManifestObj, manifestEnv)) {
keysCausingChangeRequest.add(key);
@@ -258,6 +277,37 @@ public class ChangeRequestUtils {
curPreManifestObj, manifestEnv, keysCausingChangeRequest);
}
@SuppressWarnings("unchecked")
private static void handleForEach(
Map<String, Object> mapCurrentLimitObject, Object currentManifestObj,
Object curPreManifestObj, String key, String manifestEnv,
List<String> keysCausingChangeRequest
) {
if (mapCurrentLimitObject.get("forEach") != null && currentManifestObj != null) {
var listCurrentManifestValue = (List<Map<String, Object>>) currentManifestObj;
IntStream.range(0, listCurrentManifestValue.size()).forEach(i -> {
var currentManifestValue = listCurrentManifestValue.get(i);
Object preManifestValue = null;
if (Boolean.TRUE.equals(mapCurrentLimitObject.get("hasHashedIdentifier"))) {
var hashedIdentifier = (String) currentManifestValue.get("hashedIdentifier");
if (hashedIdentifier == null) {
keysCausingChangeRequest.add(String.format("%s[%d]", key, i));
return;
}
preManifestValue = safeListAccess(curPreManifestObj, hashedIdentifier);
} else {
preManifestValue = safeListAccess(curPreManifestObj, i);
}
if (hasBreachedAndIsDifferent(
(Map<String, Object>) mapCurrentLimitObject.get("forEach"),
currentManifestValue, preManifestValue, manifestEnv)) {
keysCausingChangeRequest.add(String.format("%s[%d]", key, i));
}
});
}
}
private static List<String> checkTriggersChangeRequest(
Map<String, Object> limitObject,
Map<String, Object> manifestObject,
@@ -411,4 +461,16 @@ public class ChangeRequestUtils {
return previousValue == null && ((List<?>) limit.get("environments")).contains(manifestEnv);
}
@SuppressWarnings("unchecked")
public static ChangeRequest populateIdentifier(ChangeRequest changeRequest) {
changeRequest.getDiff().forEach(diff -> {
var limitPath = (String) diff.get("limitPath");
if (identifierPopulatorForlimitPath.containsKey(limitPath)) {
var identifierValue = identifierPopulatorForlimitPath.get(limitPath).apply(diff);
((Map<String, Object>) diff.get("value")).put("hashedIdentifier", identifierValue);
}
});
return changeRequest;
}
}

View File

@@ -14,7 +14,7 @@ import static java.util.stream.Collectors.toUnmodifiableSet;
import com.navi.infra.portal.domain.manifest.Manifest;
import com.navi.infra.portal.domain.user.Team;
import com.navi.infra.portal.repository.ManifestRepository;
import com.navi.infra.portal.service.manifest.ManifestService;
import com.navi.infra.portal.service.user.PrivilegeUtilService;
import com.navi.infra.portal.service.user.UserService;
import com.navi.infra.portal.util.MapUtil;
@@ -24,6 +24,7 @@ import com.navi.infra.portal.v2.approvalflow.entity.ApprovalRequest;
import com.navi.infra.portal.v2.approvalflow.entity.ApprovalRequestBuilder;
import com.navi.infra.portal.v2.approvalflow.entity.RequestType;
import com.navi.infra.portal.v2.approvalflow.repository.ApprovalRequestRepository;
import com.navi.infra.portal.v2.approvalflow.util.ApprovalRequestUtil;
import com.navi.infra.portal.v2.changerequest.entity.ChangeRequest;
import com.navi.infra.portal.v2.changerequest.service.ChangeRequestService;
import com.navi.infra.portal.v2.changerequest.service.ManifestLimitService;
@@ -55,35 +56,37 @@ public class ApprovalRequestServiceImpl implements ApprovalRequestService {
private final ApprovalRequestRepository repository;
private final TeamService teamService;
private final UserService userService;
// todo: use manifest service after the initial merge
private final ManifestRepository manifestRepository;
private final ManifestService manifestService;
private final ManifestLimitService manifestLimitService;
private final ChangeRequestService changeRequestService;
private final TokenRequestService tokenRequestService;
private final PrivilegeUtilService privilegeUtilService;
private final ChangeRequestSlackService changeRequestSlackService;
private final ApprovalRequestUtil approvalRequestUtil;
private final MapUtil mapUtil;
public ApprovalRequestServiceImpl(
ApprovalRequestRepository repository,
TeamService teamService,
UserService userService,
ManifestRepository manifestRepository,
ManifestService manifestService,
ManifestLimitService manifestLimitService,
@Lazy ChangeRequestService changeRequestService,
@Lazy TokenRequestService tokenRequestService, PrivilegeUtilService privilegeUtilService,
@Lazy ChangeRequestSlackService changeRequestSlackService,
ApprovalRequestUtil approvalRequestUtil,
MapUtil mapUtil
) {
this.repository = repository;
this.teamService = teamService;
this.userService = userService;
this.manifestRepository = manifestRepository;
this.manifestService = manifestService;
this.manifestLimitService = manifestLimitService;
this.changeRequestService = changeRequestService;
this.tokenRequestService = tokenRequestService;
this.privilegeUtilService = privilegeUtilService;
this.changeRequestSlackService = changeRequestSlackService;
this.approvalRequestUtil = approvalRequestUtil;
this.mapUtil = mapUtil;
}
@@ -129,7 +132,7 @@ public class ApprovalRequestServiceImpl implements ApprovalRequestService {
@SuppressWarnings("unchecked")
@Transactional
public Iterable<ApprovalRequest> createApprovals(ChangeRequest changeRequest) {
final var manifest = findManifestById(changeRequest.getManifestId());
final var manifest = manifestService.fetchById(changeRequest.getManifestId());
final var oldApprovalList = repository.findByRequestIdAndType(changeRequest.getId(),
CHANGE_REQUEST.code);
@@ -153,7 +156,7 @@ public class ApprovalRequestServiceImpl implements ApprovalRequestService {
var additionalApprovals = new ArrayList<>(approvalList);
additionalApprovals.removeAll(oldApprovalList);
try {
changeRequestSlackService.updateApprovalStatusesInBulk(PENDING.code, extractedData);
if (!oldApprovalList.isEmpty()) {
log.info(
@@ -180,7 +183,7 @@ public class ApprovalRequestServiceImpl implements ApprovalRequestService {
.orElseThrow(() -> new IllegalStateException(
format("No manifest id is found in this token request: %d", tokenRequest.getId())));
final var manifest = findManifestById(manifestId);
final var manifest = manifestService.fetchById(manifestId);
final var approverTeamSet = new HashSet<String>();
approverTeamSet.add(
(String) ((HashMap<String, Object>) manifest.getData().get("team")).get("name"));
@@ -330,10 +333,10 @@ public class ApprovalRequestServiceImpl implements ApprovalRequestService {
format("No manifest is associated with this Token Request: %d", requestId)));
}
return Optional.ofNullable(manifestId)
.map(manifestRepository::findById)
return Optional.ofNullable(Optional.ofNullable(manifestId)
.map(manifestService::fetchById)
.orElseThrow(() -> new IllegalStateException(
format("No manifest is associated with this request: %d", requestId)));
format("No manifest is associated with this request: %d", requestId))));
}
private boolean userHasSameTeamAsApprovalRequest(Long teamId, Long userId) {
@@ -349,12 +352,6 @@ public class ApprovalRequestServiceImpl implements ApprovalRequestService {
return allPendingByCrId.isEmpty();
}
private Manifest findManifestById(Long manifestId) {
return manifestRepository.findById(manifestId).orElseThrow(
() -> new NotFoundException("Manifest not found for CR, id: " + manifestId)
);
}
private List<ApprovalRequest> getRequiredApprovalList(
ChangeRequest changeRequest,
String env,
@@ -367,7 +364,7 @@ public class ApprovalRequestServiceImpl implements ApprovalRequestService {
.map(diffMap -> (String) diffMap.get("limitPath"))
.collect(toUnmodifiableList());
final var approverTeams = Stream.of(
getApproverTeamsByPaths(limitMap, pathsOfChangedComponents),
getApproverTeamsByPaths(changeRequest.getDiff(), limitMap, pathsOfChangedComponents),
singletonList(manifestTeam)
).flatMap(List::stream)
.collect(toUnmodifiableSet());
@@ -391,10 +388,16 @@ public class ApprovalRequestServiceImpl implements ApprovalRequestService {
.collect(toUnmodifiableList());
}
@SuppressWarnings("unchecked")
private List<String> getApproverTeamsByPaths(Map<String, Object> limitMap, List<String> paths) {
private List<String> getApproverTeamsByPaths(
List<Map<String, Object>> diff, Map<String, Object> limitMap, List<String> paths
) {
var pathDiffMap = diff.stream().collect(
Collectors.groupingBy(
breach -> (String) breach.get("limitPath")
)
);
return paths.stream()
.map(path -> (List<String>) mapUtil.getValueAtPath(limitMap, path, "approvalFrom"))
.map(path -> approvalRequestUtil.getApprovers(pathDiffMap.get(path), limitMap, path))
.flatMap(Collection::stream)
.distinct()
.collect(toUnmodifiableList());

View File

@@ -0,0 +1,38 @@
package com.navi.infra.portal.v2.approvalflow.util;
import com.navi.infra.portal.v2.egress.Egress;
import com.navi.infra.portal.v2.egress.EgressService;
import com.navi.infra.portal.v2.team.TeamService;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@RequiredArgsConstructor
@Component
@Slf4j
public class AdditionalApproverTeam {
private final TeamService teamService;
private final EgressService egressService;
@SuppressWarnings("unchecked")
public List<String> getAllowEndpointAdditionalTeam(
List<Map<String, Object>> allowEndpointBreachData
) {
log.info("Allowing endpoint additional team");
return allowEndpointBreachData.stream()
.flatMap(egressData -> {
var endpointData = (Map<String, String>) egressData.get("value");
return egressService.getEgress(
endpointData.get("host"), endpointData.get("port"))
.stream().map(Egress::getTeam)
.filter(team -> teamService.findByName(team).getName() != null);
})
.collect(Collectors.toList());
}
}

View File

@@ -0,0 +1,52 @@
package com.navi.infra.portal.v2.approvalflow.util;
import com.navi.infra.portal.util.MapUtil;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.util.Pair;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class ApprovalRequestUtil {
private final AdditionalApproverTeam additionalApproverTeam;
private final MapUtil mapUtil;
private final Map<String, Pair<String, Function<Object, List<String>>>> pathAdditionalApprover;
@SuppressWarnings("unchecked")
public ApprovalRequestUtil(
AdditionalApproverTeam additionalApproverTeam,
MapUtil mapUtil
) {
this.additionalApproverTeam = additionalApproverTeam;
this.mapUtil = mapUtil;
this.pathAdditionalApprover = Map.of("/deployment/allowEndpoint",
Pair.of("ENDPOINT_OWNER_TEAM",
obj -> this.additionalApproverTeam.getAllowEndpointAdditionalTeam(
(List<Map<String, Object>>) obj))
);
}
@SuppressWarnings("unchecked")
public List<String> getApprovers(
List<Map<String, Object>> pathDiff,
Map<String, Object> limitMap,
String path
) {
var teams = (List<String>) mapUtil.getValueAtPath(limitMap, path, "approvalFrom");
return teams.stream()
.flatMap(team -> {
if (pathAdditionalApprover.containsKey(path)
&& team.equals(pathAdditionalApprover.get(path).getFirst())) {
return pathAdditionalApprover.get(path).getSecond().apply(pathDiff).stream();
}
return Stream.of(team);
})
.collect(Collectors.toList());
}
}

View File

@@ -1,5 +1,6 @@
package com.navi.infra.portal.v2.changerequest.service;
import static com.navi.infra.portal.util.MapUtil.INSERT_IN_END_IDENTIFIER;
import static com.navi.infra.portal.v2.changerequest.entity.RequestStatus.APPROVED;
import static com.navi.infra.portal.v2.changerequest.entity.RequestStatus.CLOSED;
import static com.navi.infra.portal.v2.changerequest.entity.RequestStatus.PENDING;
@@ -23,6 +24,7 @@ import com.navi.infra.portal.security.authorization.AuthorizationContext;
import com.navi.infra.portal.service.manifest.ManifestService;
import com.navi.infra.portal.service.user.UserService;
import com.navi.infra.portal.util.MapUtil;
import com.navi.infra.portal.util.manifest.ChangeRequestUtils;
import com.navi.infra.portal.v2.approvalflow.dto.ApprovalRequestDto;
import com.navi.infra.portal.v2.approvalflow.entity.ApprovalRequest;
import com.navi.infra.portal.v2.approvalflow.entity.ApprovalRequestBuilder;
@@ -93,9 +95,10 @@ public class ChangeRequestServiceImpl implements ChangeRequestService {
@Override
@Transactional
public ChangeRequest create(final ChangeRequest newCr) {
final var oldCr = repository.findFirstPendingByManifestId(newCr.getManifestId())
final var identifierPopulatedCr = ChangeRequestUtils.populateIdentifier(newCr);
final var oldCr = repository.findFirstPendingByManifestId(identifierPopulatedCr.getManifestId())
.orElse(null);
final var finalCr = mergeCr(newCr, oldCr);
final var finalCr = mergeCr(identifierPopulatedCr, oldCr);
final ChangeRequest savedCr;
try {
@@ -401,9 +404,12 @@ public class ChangeRequestServiceImpl implements ChangeRequestService {
final var list = new ArrayList<>(oldDiffList);
for (final var newDiff : newDiffList) {
var newPath = newDiff.get("path");
var newPath = (String) newDiff.get("path");
if (newPath.endsWith(INSERT_IN_END_IDENTIFIER)) {
list.add(newDiff);
continue;
}
var isFound = false;
for (final var oldDiff : list) {
var oldPath = oldDiff.get("path");

View File

@@ -8,6 +8,8 @@ import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@@ -16,9 +18,11 @@ import lombok.Setter;
@Entity
@Setter
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "egress")
class Egress extends BaseEntity {
public class Egress extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@@ -27,6 +31,23 @@ class Egress extends BaseEntity {
private String host;
private String port;
private String cluster;
private String vertical;
private String team;
private String manifestName;
private String manifestEnvironment;
public Egress(
String host, String port, String cluster, String vertical, String team,
String manifestName, String manifestEnvironment
) {
this.host = host;
this.port = port;
this.cluster = cluster;
this.vertical = vertical;
this.team = team;
this.manifestName = manifestName;
this.manifestEnvironment = manifestEnvironment;
}
@Override
public boolean equals(Object o) {
@@ -42,6 +63,23 @@ class Egress extends BaseEntity {
&& Objects.equals(cluster, egress.cluster);
}
public boolean equalsAllFields(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Egress egress = (Egress) o;
return port.equals(egress.port)
&& host.equals(egress.host)
&& cluster.equals(egress.cluster)
&& vertical.equals(egress.vertical)
&& team.equals(egress.team)
&& manifestName.equals(egress.manifestName)
&& manifestEnvironment.equals(egress.manifestEnvironment);
}
@Override
public int hashCode() {
return Objects.hash(host, port, cluster);
@@ -49,6 +87,8 @@ class Egress extends BaseEntity {
@Override
public String toString() {
return cluster + ":" + host + ":" + port;
return String.format("Egress{host='%s', port='%s', cluster='%s', vertical='%s', team='%s', "
+ "manifestName='%s', manifestEnvironment='%s'}",
host, port, cluster, vertical, team, manifestName, manifestEnvironment);
}
}

View File

@@ -22,6 +22,7 @@ import org.springframework.web.bind.annotation.RestController;
@Validated
@RequestMapping("/api/egress")
class EgressController {
private final EgressService egressService;
@GetMapping()
@@ -38,8 +39,10 @@ class EgressController {
}
@PostMapping()
public ResponseEntity<EgressUpdateResponse> updateEgress(@RequestParam Boolean dryRun,
@RequestBody @Valid EgressUpdateRequest egressUpdateRequest) {
public ResponseEntity<EgressUpdateResponse> updateEgress(
@RequestParam Boolean dryRun,
@RequestBody @Valid EgressUpdateRequest egressUpdateRequest
) {
try {
log.info("Request received to update egresses with dryRun: {}",
dryRun);
@@ -57,4 +60,24 @@ class EgressController {
return ResponseEntity.status(INTERNAL_SERVER_ERROR).build();
}
}
@PostMapping("/validate-tags")
public ResponseEntity<EgressTagValidationResponse> validateTags(
@RequestBody @Valid EgressTagValidationDto egressTagInfo
) {
try {
log.info("Request received to validate egress tags");
final EgressTagValidationResponse tagValidationResponse = egressService.validateTags(
egressTagInfo.getEgressTagData());
if (tagValidationResponse.getConflictingTags().isEmpty()) {
return ResponseEntity.ok(tagValidationResponse);
} else {
log.info("Egress have outdated or deleted manifest tags");
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(tagValidationResponse);
}
} catch (Exception e) {
log.error("Failed to validate egress tags", e);
return ResponseEntity.status(INTERNAL_SERVER_ERROR).build();
}
}
}

View File

@@ -1,7 +1,9 @@
package com.navi.infra.portal.v2.egress;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@@ -10,8 +12,11 @@ import lombok.Setter;
@Getter
@Setter
@RequiredArgsConstructor
@EqualsAndHashCode
class EgressDto {
@AllArgsConstructor
@EqualsAndHashCode(callSuper = false)
@JsonIgnoreProperties(ignoreUnknown = true)
public class EgressDto extends EgressTagDto {
@NotNull
@Pattern(regexp = "(^([-a-zA-Z0-9_*]+[.]?)+$)|"
+ "(^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(?:25[0-5]|2[0-4][0-9]|"
@@ -28,4 +33,22 @@ class EgressDto {
private String host;
@NotNull
private String port;
public EgressDto(Egress egress) {
this.host = egress.getHost();
this.port = egress.getPort();
}
public EgressDto(
String host,
String port,
String team,
String vertical,
String manifestEnvironment,
String manifestName
) {
super(team, manifestName, vertical, manifestEnvironment);
this.host = host;
this.port = port;
}
}

View File

@@ -10,20 +10,7 @@ import org.springframework.stereotype.Repository;
@Repository
interface EgressRepository extends JpaRepository<Egress, Long> {
@Query(value = "SELECT e.host, e.port FROM Egress e where e.cluster = :cluster",
nativeQuery = true)
List<Object[]> findByClusterName(String cluster);
List<Egress> findByCluster(String cluster);
default List<EgressDto> findByCluster(String cluster) {
var objs = findByClusterName(cluster);
return objs
.stream()
.map(obj -> {
var egress = new EgressDto();
egress.setHost((String) obj[0]);
egress.setPort((String) obj[1]);
return egress;
})
.collect(toList());
}
List<Egress> findByHostAndPort(String host, String zone);
}

View File

@@ -2,8 +2,14 @@ package com.navi.infra.portal.v2.egress;
import java.util.List;
interface EgressService {
public interface EgressService {
List<EgressDto> getEgresses(String cluster);
List<Egress> getEgress(String host, String zone);
EgressUpdateResponse updateEgresses(List<EgressUpdateRequestData> egresses, Boolean dryRun);
EgressTagValidationResponse validateTags(List<EgressTagDto> egressTags);
}

View File

@@ -13,6 +13,7 @@ import com.navi.infra.portal.service.manifest.ManifestService;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
@@ -21,48 +22,97 @@ import org.springframework.stereotype.Service;
@Slf4j
@Service
class EgressServiceImpl implements EgressService {
private final EgressRepository egressRepository;
private final ObjectMapper objectMapper;
private final ManifestService manifestService;
public EgressServiceImpl(EgressRepository egressRepository,
ManifestService manifestService, ObjectMapper objectMapper) {
public EgressServiceImpl(
EgressRepository egressRepository,
ManifestService manifestService, ObjectMapper objectMapper
) {
this.egressRepository = egressRepository;
this.manifestService = manifestService;
this.objectMapper = objectMapper;
}
public List<Egress> getEgress(String host, String zone) {
return egressRepository.findByHostAndPort(host, zone);
}
public List<EgressDto> getEgresses(String cluster) {
return egressRepository.findByCluster(cluster);
return egressRepository.findByCluster(cluster)
.stream()
.map(EgressDto::new)
.collect(toList());
}
private List<Egress> flattenEgresses(List<EgressUpdateRequestData> egressUpdateRequests) {
return egressUpdateRequests.stream()
.flatMap(clusterData -> clusterData.getEgressData().stream()
.map(egressDto -> {
Egress egress = new Egress();
egress.setHost(egressDto.getHost());
egress.setPort(egressDto.getPort());
egress.setCluster(clusterData.getCluster());
return egress;
return Egress.builder()
.team(egressDto.getTeam())
.vertical(egressDto.getVertical())
.manifestEnvironment(egressDto.getManifestEnvironment())
.manifestName(egressDto.getManifestName())
.host(egressDto.getHost())
.port(egressDto.getPort())
.cluster(clusterData.getCluster())
.build();
}))
.collect(toList());
}
public EgressUpdateResponse updateEgresses(List<EgressUpdateRequestData> egresses,
Boolean dryRun) {
private Set<Egress> getUpdatedEgresses(
Set<Egress> existingEgresses,
List<Egress> flattenedEgresses
) {
Map<String, Egress> flattenedEgressMap = flattenedEgresses.stream()
.collect(Collectors.toMap(
egress -> egress.getHost() + ":" + egress.getPort() + ":" + egress.getCluster(),
egress -> egress
));
return existingEgresses.stream()
.map(egress -> {
String key = egress.getHost() + ":" + egress.getPort() + ":" + egress.getCluster();
Egress flattenedEgress = flattenedEgressMap.get(key);
if (flattenedEgress != null && !flattenedEgress.equalsAllFields(egress)) {
return Egress.builder()
.id(egress.getId())
.host(flattenedEgress.getHost())
.port(flattenedEgress.getPort())
.cluster(flattenedEgress.getCluster())
.team(flattenedEgress.getTeam())
.vertical(flattenedEgress.getVertical())
.manifestEnvironment(flattenedEgress.getManifestEnvironment())
.manifestName(flattenedEgress.getManifestName())
.build();
}
return null;
})
.filter(Objects::nonNull)
.collect(Collectors.toSet());
}
public EgressUpdateResponse updateEgresses(
List<EgressUpdateRequestData> egresses,
Boolean dryRun
) {
log.info("Updating egresses with dryRun: {}", dryRun);
List<Egress> flattenedEgresses = flattenEgresses(egresses);
Set<Egress> existingEgresses = new HashSet<>(egressRepository.findAll());
Set<Egress> updatedEgresses = getUpdatedEgresses(existingEgresses, flattenedEgresses);
Set<Egress> newEgresses = flattenedEgresses.stream()
.filter(egress -> !existingEgresses.contains(egress)).collect(toSet());
Set<Egress> removedEgresses = existingEgresses.stream()
.filter(egress -> !flattenedEgresses.contains(egress)).collect(toSet());
log.info("Egresses to be updated: {}",
updatedEgresses.stream().map(Egress::toString).collect(toList()));
log.info("New Egress to be added egresses: {}",
newEgresses.stream().map(Egress::toString).collect(toList()));
@@ -74,6 +124,7 @@ class EgressServiceImpl implements EgressService {
if (!dryRun) {
egressRepository.saveAll(newEgresses);
egressRepository.saveAll(updatedEgresses);
egressRepository.deleteAll(removedEgresses);
} else {
log.info("Dry run enabled, Skipping adding new egresses and "
@@ -85,6 +136,21 @@ class EgressServiceImpl implements EgressService {
return new EgressUpdateResponse(Map.of(), updatedEgress, dryRun);
}
@Override
public EgressTagValidationResponse validateTags(List<EgressTagDto> egressTags) {
var manifestInfo = manifestService.fetchManifestInfo();
var manifestInfoSet = manifestInfo.stream().map(
manifest -> String.format("%s:%s:%s", manifest.getName(), manifest.getTeam(),
manifest.getEnvironment())).collect(toSet());
var missingEgressTags = egressTags.stream().filter(
egressTag -> {
var manifestKey = String.format("%s:%s:%s", egressTag.getManifestName(),
egressTag.getTeam(), egressTag.getManifestEnvironment());
return !manifestInfoSet.contains(manifestKey);
}).distinct().collect(toList());
return new EgressTagValidationResponse(missingEgressTags);
}
private Map<String, List<Egress>> validateDeleteEgress(Set<Egress> removedEgresses) {
log.info("Validating egress list to be deleted: {}",
removedEgresses.stream().map(Egress::toString).collect(toList()));
@@ -98,7 +164,8 @@ class EgressServiceImpl implements EgressService {
private Map.Entry<String, List<Egress>> filterConflictingEgresses(
Map.Entry<String, List<Egress>> manifestWithEgressList,
Set<Egress> removedEgresses) {
Set<Egress> removedEgresses
) {
List<Egress> conflictingEgresses = manifestWithEgressList.getValue().stream()
.filter(removedEgresses::contains)
.collect(toList());
@@ -106,16 +173,17 @@ class EgressServiceImpl implements EgressService {
}
private Map<String, List<Egress>> fetchConflictingManifestsWithEgressHostList(
Map<String, List<Egress>> manifestWithEgressMap, Set<Egress> removedEgresses) {
Map<String, List<Egress>> manifestWithEgressMap, Set<Egress> removedEgresses
) {
log.info("Fetching conflicting manifests with egress");
return manifestWithEgressMap
.entrySet()
.stream()
.map(manifestWithEgressList ->
.map(manifestWithEgressList ->
filterConflictingEgresses(manifestWithEgressList, removedEgresses))
.filter(entry -> !entry.getValue().isEmpty())
.peek(entry -> log.info("Manifest: {} contains following egress which are being "
+ "deleted: {}", entry.getKey(), entry.getValue().stream().map(Egress::toString)
+ "deleted: {}", entry.getKey(), entry.getValue().stream().map(Egress::toString)
.collect(Collectors.toList())))
.collect(toMap(Map.Entry::getKey, Map.Entry::getValue));
}
@@ -129,13 +197,14 @@ class EgressServiceImpl implements EgressService {
Manifest::fullName,
manifest -> {
EgressUpdateRequestData egressUpdateRequestData = new EgressUpdateRequestData();
egressUpdateRequestData.setEgressData(convertEgressObjectToEgressDtoList(manifest.getEgress()));
egressUpdateRequestData.setEgressData(
convertEgressObjectToEgressDtoList(manifest.getEgress()));
egressUpdateRequestData.setCluster(manifest.getCluster());
return flattenEgresses(List.of(egressUpdateRequestData));
}));
}
private List<EgressDto> convertEgressObjectToEgressDtoList(Object egressList) {
return objectMapper.convertValue(egressList, new TypeReference<List<EgressDto>>(){});
return objectMapper.convertValue(egressList, new TypeReference<List<EgressDto>>() {});
}
}

View File

@@ -0,0 +1,36 @@
package com.navi.infra.portal.v2.egress;
import com.fasterxml.jackson.annotation.JsonProperty;
import javax.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@Getter
@Builder
@RequiredArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
public class EgressTagDto {
@JsonProperty("owner_team")
@NotNull
private String team;
@JsonProperty("owner_manifest_name")
@NotNull
private String manifestName;
@JsonProperty("owner_vertical")
@NotNull
private String vertical;
@JsonProperty("owner_environment")
@NotNull
private String manifestEnvironment;
}

View File

@@ -0,0 +1,18 @@
package com.navi.infra.portal.v2.egress;
import java.util.List;
import javax.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
@Getter
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode
public class EgressTagValidationDto {
@NotNull
private List<EgressTagDto> egressTagData;
}

View File

@@ -0,0 +1,15 @@
package com.navi.infra.portal.v2.egress;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
@Getter
@AllArgsConstructor
@EqualsAndHashCode
public class EgressTagValidationResponse {
private List<EgressTagDto> conflictingTags;
}

View File

@@ -16,7 +16,7 @@ public interface JitRequestsRepository extends JpaRepository<JitRequest, Long> {
+ "AND (resource_type NOT IN ('AWS','GOCD','KUBERNETES') OR vertical = :vertical) "
+ "AND team_id = :teamId "
+ "AND ( (aws_resource_type is NULL AND :awsResourceType is NULL) OR aws_resource_type = CAST(:awsResourceType AS VARCHAR)) "
+ "AND :grantAt BETWEEN grant_at AND grant_at + interval '1 hour' * grant_window "
+ "AND ( :grantAt BETWEEN grant_at AND grant_at + interval '1 hour' * grant_window ) "
+ "AND status IN ('PENDING','APPROVED')",
nativeQuery = true)
List<JitRequest> getDuplicateRequestsByUser(

View File

@@ -5,6 +5,12 @@ metadata:
values:
- tier-0
deployment:
allowEndpoint:
approvalFrom:
- ENDPOINT_OWNER_TEAM
forEach: {}
hasHashedIdentifier: true
isVpaEnabled:
approvalFrom: []
values:

View File

@@ -0,0 +1,4 @@
ALTER TABLE egress ADD COLUMN IF NOT EXISTS vertical VARCHAR(255) NOT NULL DEFAULT 'NA';
ALTER TABLE egress ADD COLUMN IF NOT EXISTS team VARCHAR(255) NOT NULL DEFAULT 'Shared';
ALTER TABLE egress ADD COLUMN IF NOT EXISTS manifest_name VARCHAR(255) NOT NULL DEFAULT 'NA';
ALTER TABLE egress ADD COLUMN IF NOT EXISTS manifest_environment VARCHAR(255) NOT NULL DEFAULT 'NA';

View File

@@ -1,13 +1,17 @@
package com.navi.infra.portal.util;
import static com.navi.infra.portal.util.ListEqualIgnoringOrder.listEqualIgnoringOrder;
import static com.navi.infra.portal.v2.changerequest.entity.RequestStatus.PENDING;
import static org.junit.jupiter.api.Assertions.assertEquals;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.navi.infra.portal.domain.user.User;
import com.navi.infra.portal.util.manifest.ChangeRequestUtils;
import com.navi.infra.portal.v2.changerequest.entity.ChangeRequestBuilder;
import com.navi.infra.portal.v2.changerequest.service.ManifestLimitService;
import com.navi.infra.portal.v2.changerequest.service.ManifestLimitServiceImpl;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.hamcrest.MatcherAssert;
@@ -61,7 +65,7 @@ class ChangeRequestUtilTest {
List<String> breachedList = ChangeRequestUtils.getChangeRequestTriggers(limitMap, null,
mapWithAlreadyExceededLimits);
var expectedViolations = List.of("maxAllocatedStorageInGb", "sizeInGb",
"storageType", "iops", "multiAZDisabled", "loadBalancers", "database", "minCPU",
"storageType", "iops", "multiAZDisabled", "loadBalancers[0]", "database", "minCPU",
"isVpaEnabled", "minMemory", "maxReplicas", "minReplicas", "awsInstanceClass",
"awsInstanceClass");
MatcherAssert.assertThat(breachedList, listEqualIgnoringOrder(expectedViolations));
@@ -84,7 +88,40 @@ class ChangeRequestUtilTest {
mapWithNonBreaching,
mapWithChangedLoadBalancerType);
assertEquals(1, breachedList.size());
assertEquals("loadBalancers", breachedList.get(0));
assertEquals("loadBalancers[0]", breachedList.get(0));
}
@Test
@SuppressWarnings("unchecked")
@DisplayName("Should populate hashedIdentifier")
void shouldPopulateHashedIdentifier() {
Map<String, Object> diff = new HashMap<>();
diff.put("path", "/deployment/allowEndpoint/*");
diff.put("op", "op");
diff.put("limitPath", "/deployment/allowEndpoint");
Map<String, Object> valueMap = new HashMap<>();
valueMap.put("host", "endpoint.one");
valueMap.put("port", "4321");
diff.put("value", valueMap);
final User user1 = new User();
user1.setId(1L);
user1.setName("foo");
user1.setEmail("foo@bar.com");
final var changeRequest = new ChangeRequestBuilder()
.setId(1L)
.setManifestId(1L)
.setStatus(PENDING)
.setCreatedBy(user1.getId())
.setUpdatedBy(user1.getId())
.setDiff(List.of(diff))
.createChangeRequest();
var result = ChangeRequestUtils.populateIdentifier(changeRequest);
var populatedDiffValue = (Map<String, Object>) result.getDiff().get(0).get("value");
var expectedIdentifier = "ZW5kcG9pbnQub25lOjQzMjE=";
assertEquals(populatedDiffValue.get("hashedIdentifier"),
expectedIdentifier);
}

View File

@@ -16,7 +16,7 @@ import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.navi.infra.portal.domain.manifest.Manifest;
import com.navi.infra.portal.domain.user.Team;
import com.navi.infra.portal.domain.user.User;
import com.navi.infra.portal.repository.ManifestRepository;
import com.navi.infra.portal.service.manifest.ManifestService;
import com.navi.infra.portal.service.user.PrivilegeUtilService;
import com.navi.infra.portal.service.user.UserService;
import com.navi.infra.portal.util.MapUtil;
@@ -26,6 +26,8 @@ import com.navi.infra.portal.v2.approvalflow.entity.RequestType;
import com.navi.infra.portal.v2.approvalflow.repository.ApprovalRequestRepository;
import com.navi.infra.portal.v2.approvalflow.service.ApprovalRequestService;
import com.navi.infra.portal.v2.approvalflow.service.ApprovalRequestServiceImpl;
import com.navi.infra.portal.v2.approvalflow.util.AdditionalApproverTeam;
import com.navi.infra.portal.v2.approvalflow.util.ApprovalRequestUtil;
import com.navi.infra.portal.v2.changerequest.entity.ChangeRequestBuilder;
import com.navi.infra.portal.v2.exception.NotFoundException;
import com.navi.infra.portal.v2.jit.service.ChangeRequestSlackService;
@@ -65,19 +67,21 @@ public class ApprovalRequestServiceImplTest {
@Mock
private TeamService teamService;
@Mock
private AdditionalApproverTeam additionalApproverTeam;
private final ApprovalRequestUtil approvalRequestUtil = new ApprovalRequestUtil(
additionalApproverTeam, mapUtil);
@Mock
private UserService userService;
@Mock
private ManifestService manifestService;
@Mock
private ApprovalRequestRepository repo;
@Mock
private PrivilegeUtilService privilegeUtilService;
@Mock
private ManifestLimitService manifestLimitService;
@Mock
private ManifestRepository manifestRepository;
@Mock
private ChangeRequestService changeRequestService;
@Mock
private TokenRequestService tokenRequestService;
@@ -109,8 +113,9 @@ public class ApprovalRequestServiceImplTest {
.setRequestType(RequestType.CHANGE_REQUEST).setTeamId(team2.getId())
.createApprovalRequest();
service = new ApprovalRequestServiceImpl(repo, teamService, userService, manifestRepository, null, changeRequestService, null,
privilegeUtilService, changeRequestSlackService,null);
service = new ApprovalRequestServiceImpl(repo, teamService, userService, manifestService,
null, changeRequestService, null,
privilegeUtilService, changeRequestSlackService, null, null);
}
@Test
@@ -118,8 +123,9 @@ public class ApprovalRequestServiceImplTest {
void approvalShouldFailIfAllApprovalsAreAlreadyDone() {
when(repo.findPendingByRequestId(crId1)).thenReturn(Optional.empty());
service = new ApprovalRequestServiceImpl(repo, teamService, userService, null, null, null, null,
privilegeUtilService, changeRequestSlackService, null);
service = new ApprovalRequestServiceImpl(repo, teamService, userService, null, null, null,
null,
privilegeUtilService, changeRequestSlackService, null, null);
final var exception = assertThrows(NotFoundException.class,
() -> service.allowApproveRequest(arId1, user1.getId()));
@@ -147,11 +153,13 @@ public class ApprovalRequestServiceImplTest {
when(repo.save(toBeSavedRequestApproval)).thenReturn(toBeSavedRequestApproval);
when(repo.findAllPendingByRequestTypeAndRequestId(RequestType.CHANGE_REQUEST.code,
requestApproval.getRequestId())).thenReturn(singletonList(new ApprovalRequest()));
when(manifestRepository.findById(1L)).thenReturn(Optional.of(manifest));
when(manifestService.fetchById(1L)).thenReturn(manifest);
when(changeRequestService.findById(1L)).thenReturn(Optional.of(changeRequest));
service = new ApprovalRequestServiceImpl(repo, teamService,userService, manifestRepository, null,
changeRequestService, tokenRequestService, privilegeUtilService, changeRequestSlackService, null);
service = new ApprovalRequestServiceImpl(repo, teamService, userService, manifestService,
null,
changeRequestService, tokenRequestService, privilegeUtilService,
changeRequestSlackService, null, null);
final var approvedRequest = service.allowApproveRequest(requestApproval.getId(),
user1.getId());
@@ -187,10 +195,10 @@ public class ApprovalRequestServiceImplTest {
Optional.of(requestApproval1));
when(changeRequestService.findById(requestApproval1.getId())).thenReturn(
Optional.of(changeRequest));
when(manifestRepository.findById(changeRequest.getManifestId())).thenReturn(
Optional.of(manifest));
when(changeRequestService.reject(requestApproval1.getRequestId())).thenReturn(changeRequest);
when(manifestRepository.findById(1L)).thenReturn(Optional.of(manifest));
when(manifestService.fetchById(changeRequest.getManifestId())).thenReturn(manifest);
when(changeRequestService.reject(requestApproval1.getRequestId())).thenReturn(
changeRequest);
when(manifestService.fetchById(1L)).thenReturn(manifest);
when(changeRequestService.findById(1L)).thenReturn(Optional.of(changeRequest));
final var rejectedRequest = service.reject(requestApproval1.getId(),
user1.getId());
@@ -223,7 +231,6 @@ public class ApprovalRequestServiceImplTest {
final var oldApprovals = List.of(existingApprovalRequest1, existingApprovalRequest2);
final var newApprovalRequest2 = new ApprovalRequestBuilder().from(ar1).setId(null)
.setTeamId(team2.getId()).setRequestType(RequestType.CHANGE_REQUEST)
.createApprovalRequest();
@@ -231,16 +238,15 @@ public class ApprovalRequestServiceImplTest {
final var savedNewApprovalRequest2 = new ApprovalRequestBuilder().from(newApprovalRequest2)
.setId(3L).createApprovalRequest();
when(repo.findByRequestIdAndType(changeRequest.getId(), RequestType.CHANGE_REQUEST.code)).thenReturn(oldApprovals);
when(repo.findByRequestIdAndType(changeRequest.getId(),
RequestType.CHANGE_REQUEST.code)).thenReturn(oldApprovals);
when(teamService.findByNames(argThat(
listMatches(List.of(team1.getName(), team2.getName(), team3.getName()))))).thenReturn(
List.of(team1, team2, team3));
when(manifestRepository.findById(changeRequest.getManifestId())).thenReturn(
Optional.of(manifest));
when(manifestService.fetchById(changeRequest.getManifestId())).thenReturn(manifest);
when(manifestRepository.findById(changeRequest.getManifestId())).thenReturn(
Optional.of(manifest));
when(manifestService.fetchById(changeRequest.getManifestId())).thenReturn(manifest);
//noinspection unchecked
when(manifestLimitService.getLimit(manifest.getEnvironment())).thenReturn(limitMap);
@@ -249,15 +255,16 @@ public class ApprovalRequestServiceImplTest {
newApprovalRequest2))))).thenReturn(
List.of(existingApprovalRequest1, existingApprovalRequest2, savedNewApprovalRequest2));
service = new ApprovalRequestServiceImpl(repo, teamService,userService, manifestRepository,
manifestLimitService, null, null, privilegeUtilService, changeRequestSlackService, mapUtil);
service = new ApprovalRequestServiceImpl(repo, teamService, userService, manifestService,
manifestLimitService, null, null, privilegeUtilService, changeRequestSlackService,
approvalRequestUtil, mapUtil);
service.createApprovals(changeRequest);
verify(repo).findByRequestIdAndType(changeRequest.getId(), RequestType.CHANGE_REQUEST.code);
verify(teamService).findByNames(argThat(
listMatches(List.of(team1.getName(), team2.getName(), team3.getName()))));
verify(manifestRepository).findById(changeRequest.getManifestId());
verify(manifestService).fetchById(changeRequest.getManifestId());
verify(manifestLimitService).getLimit(manifest.getEnvironment());
verify(repo).saveAll(
argThat(listMatches(List.of(existingApprovalRequest1, existingApprovalRequest2,
@@ -265,6 +272,7 @@ public class ApprovalRequestServiceImplTest {
}
// Custom argument matcher to check if the lists have the same content, disregarding order
private <T> ArgumentMatcher<List<T>> listMatches(List<T> expectedList) {
return actualList -> expectedList.containsAll(actualList) && actualList.containsAll(

View File

@@ -197,10 +197,14 @@ class ChangeRequestServiceImplTest {
approval2ChangeRequest2
);
final var approvalDto1 = new ApprovalRequestDto(1L, "teamname", user1.getEmail(), new Date(), 1L, PENDING);
final var approvalDto2 = new ApprovalRequestDto(2L, "teamname", user1.getEmail(), new Date(), 1L, APPROVED);
final var approvalDto3 = new ApprovalRequestDto(3L, "teamname", user2.getEmail(), new Date(), 2L, PENDING);
final var approvalDto4 = new ApprovalRequestDto(4L, "teamname", user2.getEmail(), new Date(), 2L, PENDING);
final var approvalDto1 = new ApprovalRequestDto(1L, "teamname", user1.getEmail(),
new Date(), 1L, PENDING);
final var approvalDto2 = new ApprovalRequestDto(2L, "teamname", user1.getEmail(),
new Date(), 1L, APPROVED);
final var approvalDto3 = new ApprovalRequestDto(3L, "teamname", user2.getEmail(),
new Date(), 2L, PENDING);
final var approvalDto4 = new ApprovalRequestDto(4L, "teamname", user2.getEmail(),
new Date(), 2L, PENDING);
final var approvalDtoList = List.of(
approvalDto1,
approvalDto2,
@@ -215,7 +219,8 @@ class ChangeRequestServiceImplTest {
manifest2.setId(2L);
manifest2.setData(data);
when(approvalRequestService.findAllByRequestTypeAndTeamIds(RequestType.CHANGE_REQUEST,teamIds)).thenReturn(List.of(
when(approvalRequestService.findAllByRequestTypeAndTeamIds(RequestType.CHANGE_REQUEST,
teamIds)).thenReturn(List.of(
approvedApproval,
approval1ChangeRequest1,
approval2ChangeRequest1,
@@ -224,7 +229,8 @@ class ChangeRequestServiceImplTest {
));
when(repo.findPendingByIds(changeRequestList)).thenReturn(
List.of(changeRequest1, changeRequest2));
when(approvalRequestService.findAllByRequestTypeAndRequestIds(RequestType.CHANGE_REQUEST,changeRequestList)).thenReturn(
when(approvalRequestService.findAllByRequestTypeAndRequestIds(RequestType.CHANGE_REQUEST,
changeRequestList)).thenReturn(
approvalList);
when(manifestService.fetchById(changeRequest1.getManifestId())).thenReturn(manifest1);
when(manifestService.fetchById(changeRequest2.getManifestId())).thenReturn(manifest2);
@@ -294,10 +300,14 @@ class ChangeRequestServiceImplTest {
approval2ChangeRequest2
);
final var approvalDto1 = new ApprovalRequestDto(1L, "teamname", user1.getEmail(), new Date(),1L, PENDING);
final var approvalDto2 = new ApprovalRequestDto(2L, "teamname",user1.getEmail(), new Date(), 1L, APPROVED);
final var approvalDto3 = new ApprovalRequestDto(3L, "teamname", user2.getEmail(), new Date(),2L, PENDING);
final var approvalDto4 = new ApprovalRequestDto(4L, "teamname", user2.getEmail(), new Date(),2L, PENDING);
final var approvalDto1 = new ApprovalRequestDto(1L, "teamname", user1.getEmail(),
new Date(), 1L, PENDING);
final var approvalDto2 = new ApprovalRequestDto(2L, "teamname", user1.getEmail(),
new Date(), 1L, APPROVED);
final var approvalDto3 = new ApprovalRequestDto(3L, "teamname", user2.getEmail(),
new Date(), 2L, PENDING);
final var approvalDto4 = new ApprovalRequestDto(4L, "teamname", user2.getEmail(),
new Date(), 2L, PENDING);
final var approvalDtoList = List.of(
approvalDto1,
approvalDto2,
@@ -315,7 +325,8 @@ class ChangeRequestServiceImplTest {
when(repo.findById(sampleCrId)).thenReturn(Optional.of(sampleChangeRequest1));
when(repo.findById(changeRequest1.getId())).thenReturn(Optional.of(changeRequest1));
when(repo.findById(changeRequest2.getId())).thenReturn(Optional.of(changeRequest2));
when(approvalRequestService.findAllByRequestTypeAndRequestIds(RequestType.CHANGE_REQUEST,changeRequestList)).thenReturn(
when(approvalRequestService.findAllByRequestTypeAndRequestIds(RequestType.CHANGE_REQUEST,
changeRequestList)).thenReturn(
approvalList);
when(manifestService.fetchById(changeRequest1.getManifestId())).thenReturn(manifest1);
when(manifestService.fetchById(changeRequest2.getManifestId())).thenReturn(manifest2);
@@ -355,7 +366,8 @@ class ChangeRequestServiceImplTest {
.setUpdatedBy(user1.getId())
.setDiff(List.of(diff))
.createChangeRequest();
final var changeRequestList = List.of(changeRequestApproved.getId(), changeRequest1.getId());
final var changeRequestList = List.of(changeRequestApproved.getId(),
changeRequest1.getId());
final var approvedApproval = new ApprovalRequestBuilder()
.setId(0L)
.setStatus(APPROVED)
@@ -388,12 +400,14 @@ class ChangeRequestServiceImplTest {
manifest2.setId(2L);
manifest2.setData(data);
when(approvalRequestService.findAllByRequestTypeAndTeamIds(RequestType.CHANGE_REQUEST,teamIds)).thenReturn(List.of(
when(approvalRequestService.findAllByRequestTypeAndTeamIds(RequestType.CHANGE_REQUEST,
teamIds)).thenReturn(List.of(
approvedApproval,
approval1ChangeRequest1,
approval2ChangeRequest1
));
when(approvalRequestService.findAllByRequestTypeAndRequestIds(RequestType.CHANGE_REQUEST,changeRequestList)).thenReturn(
when(approvalRequestService.findAllByRequestTypeAndRequestIds(RequestType.CHANGE_REQUEST,
changeRequestList)).thenReturn(
approvalList);
when(securityContext.getAuthentication()).thenReturn(authentication);
SecurityContextHolder.setContext(securityContext);
@@ -469,10 +483,14 @@ class ChangeRequestServiceImplTest {
approval2ChangeRequest2
);
final var approvalDto1 = new ApprovalRequestDto(1L, "teamname", user1.getEmail(), new Date(), 1L, PENDING);
final var approvalDto2 = new ApprovalRequestDto(2L, "teamname", user1.getEmail(), new Date(), 1L, APPROVED);
final var approvalDto3 = new ApprovalRequestDto(3L, "teamname", user2.getEmail(), new Date(), 2L, PENDING);
final var approvalDto4 = new ApprovalRequestDto(4L, "teamname", user2.getEmail(), new Date(), 2L, PENDING);
final var approvalDto1 = new ApprovalRequestDto(1L, "teamname", user1.getEmail(),
new Date(), 1L, PENDING);
final var approvalDto2 = new ApprovalRequestDto(2L, "teamname", user1.getEmail(),
new Date(), 1L, APPROVED);
final var approvalDto3 = new ApprovalRequestDto(3L, "teamname", user2.getEmail(),
new Date(), 2L, PENDING);
final var approvalDto4 = new ApprovalRequestDto(4L, "teamname", user2.getEmail(),
new Date(), 2L, PENDING);
final var approvalDtoList = List.of(
approvalDto1,
approvalDto2,
@@ -487,7 +505,8 @@ class ChangeRequestServiceImplTest {
manifest2.setId(2L);
manifest2.setData(data);
when(approvalRequestService.findAllByRequestTypeAndTeamIds(RequestType.CHANGE_REQUEST,teamIds)).thenReturn(List.of(
when(approvalRequestService.findAllByRequestTypeAndTeamIds(RequestType.CHANGE_REQUEST,
teamIds)).thenReturn(List.of(
approvedApproval,
approval1ChangeRequest1,
approval2ChangeRequest1,
@@ -496,7 +515,8 @@ class ChangeRequestServiceImplTest {
));
when(repo.findPendingByIds(changeRequestList)).thenReturn(
List.of(changeRequest1, changeRequest2));
when(approvalRequestService.findAllByRequestTypeAndRequestIds(RequestType.CHANGE_REQUEST,changeRequestList)).thenReturn(
when(approvalRequestService.findAllByRequestTypeAndRequestIds(RequestType.CHANGE_REQUEST,
changeRequestList)).thenReturn(
approvalList);
when(manifestService.fetchById(changeRequest1.getManifestId())).thenReturn(manifest1);
when(manifestService.fetchById(changeRequest2.getManifestId())).thenThrow(

View File

@@ -24,6 +24,7 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders;
@ExtendWith(MockitoExtension.class)
class EgressControllerTest {
private MockMvc mockMvc;
@Mock
@@ -38,32 +39,66 @@ class EgressControllerTest {
return egressDto;
}
private static EgressUpdateRequestData getEgressUpdateRequestData(String cluster,
List<EgressDto> egressData) {
private static EgressDto getEgressDto(
String host, String port, String team,
String vertical, String manifestEnvironment, String manifestName
) {
return new EgressDto(
host, port, team, vertical, manifestEnvironment, manifestName);
}
private static EgressUpdateRequestData getEgressUpdateRequestData(
String cluster,
List<EgressDto> egressData
) {
EgressUpdateRequestData egressUpdateRequestData = new EgressUpdateRequestData();
egressUpdateRequestData.setCluster(cluster);
egressUpdateRequestData.setEgressData(egressData);
return egressUpdateRequestData;
}
private static List<EgressDto> getEgressDtoList() {
private static List<EgressDto> getRequestEgressDtoList() {
return List.of(getEgressDto("test1.com", "8080", "team1", "vertical1", "env1",
"manifest1"),
getEgressDto("test2.com", "8081", "team2", "vertical2", "evn2",
"manifest2"),
getEgressDto("test3.com", "8082", "team3", "vertical3", "env3",
"manifest3"));
}
private static List<EgressDto> getResponseEgressDtoList() {
return List.of(getEgressDto("test1.com", "8080"),
getEgressDto("test2.com", "8081"),
getEgressDto("test3.com", "8082"));
}
private static Egress getEgress(String host, String port, String cluster) {
private static Egress getEgress(
String host, String port, String cluster, String team,
String vertical, String manifestEnvironment, String manifestName
) {
Egress egress = new Egress();
egress.setHost(host);
egress.setPort(port);
egress.setCluster(cluster);
egress.setTeam(team);
egress.setVertical(vertical);
egress.setManifestEnvironment(manifestEnvironment);
egress.setManifestName(manifestName);
return egress;
}
private static List<Egress> getEgressList() {
return List.of(getEgress("test1.com", "8080", "spike.np.navi-tech.in"),
getEgress("test2.com", "8081", "spike.np.navi-tech.in"),
getEgress("test3.com", "8082", "spike.np.navi-tech.in"));
private static List<Egress> getEgressList() {
return List.of(
getEgress("test1.com", "8080", "spike.np.navi-tech.in",
"team1", "vertical1", "env1",
"manifest1"),
getEgress("test2.com", "8081", "prod.cmd.navi-tech.in",
"team2", "vertical2", "evn2",
"manifest2"),
getEgress("test3.com", "8082", "aps1.prod.navi-tech.in",
"team3", "vertical3", "env3",
"manifest3"));
}
@BeforeEach
@@ -78,10 +113,11 @@ class EgressControllerTest {
@Nested
@DisplayName("GET /api/egress")
class GetEgressTest {
@Test
@DisplayName("GET /api/egress - 200")
void shouldGetEgress() throws Exception {
List<EgressDto> egresses = getEgressDtoList();
List<EgressDto> egresses = getResponseEgressDtoList();
String expectedJson = objectMapper.writeValueAsString(egresses);
final String cluster = "test-cluster";
when(egressService.getEgresses("test-cluster")).thenReturn(egresses);
@@ -113,7 +149,7 @@ class EgressControllerTest {
@Test
@DisplayName("POST /api/egress - 200")
void shouldUpdateEgress() throws Exception {
List<EgressDto> egresses = getEgressDtoList();
List<EgressDto> egresses = getRequestEgressDtoList();
EgressUpdateRequest egressUpdateRequest = new EgressUpdateRequest();
List<EgressUpdateRequestData> egressUpdateRequestData =
List.of(getEgressUpdateRequestData("spike.np.navi-tech.in", egresses));
@@ -136,7 +172,7 @@ class EgressControllerTest {
@Test
@DisplayName("POST /api/egress - 400 Bad Request Reason: Invalid cluster name")
void shouldThrowBadRequestOnInvalidCluster() throws Exception {
List<EgressDto> egresses = getEgressDtoList();
List<EgressDto> egresses = getRequestEgressDtoList();
List<EgressUpdateRequestData> egressUpdateRequestData =
List.of(getEgressUpdateRequestData("spke.np.navi-tech.in", egresses));
EgressUpdateRequest egressUpdateRequest = new EgressUpdateRequest();
@@ -165,7 +201,7 @@ class EgressControllerTest {
@Test
@DisplayName("POST /api/egress - 500 Internal Server Error")
void shouldUpdateEgressInterServerError() throws Exception {
List<EgressDto> egresses = getEgressDtoList();
List<EgressDto> egresses = getRequestEgressDtoList();
List<EgressUpdateRequestData> egressUpdateRequestData =
List.of(getEgressUpdateRequestData("spike.np.navi-tech.in", egresses));
EgressUpdateRequest egressUpdateRequest = new EgressUpdateRequest();
@@ -173,8 +209,6 @@ class EgressControllerTest {
boolean dryRun = true;
when(egressService.updateEgresses(egressUpdateRequestData, dryRun))
.thenThrow(new RuntimeException());
String expectedJson = objectMapper.writeValueAsString(egressUpdateRequest);
mockMvc.perform(MockMvcRequestBuilders.post("/api/egress?dryRun=" + dryRun)
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(egressUpdateRequest)))

View File

@@ -1,6 +1,5 @@
package com.navi.infra.portal.v2.egress;
import static java.util.stream.Collectors.toSet;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -9,10 +8,12 @@ import static org.mockito.Mockito.when;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.navi.infra.portal.service.manifest.ManifestService;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
@@ -34,41 +35,58 @@ class EgressServiceImplTest {
private EgressService egressService;
private static EgressDto getEgressDto(String host, String port) {
EgressDto egressDto = new EgressDto();
egressDto.setHost(host);
egressDto.setPort(port);
return egressDto;
private static EgressDto getEgressDto(
String host, String port, String team,
String vertical, String manifestEnvironment, String manifestName
) {
return new EgressDto(
host, port, team, vertical, manifestEnvironment, manifestName);
}
private static EgressUpdateRequestData getEgressUpdateRequestData(String cluster,
List<EgressDto> egressData) {
private static EgressUpdateRequestData getEgressUpdateRequestData(
String cluster,
List<EgressDto> egressData
) {
EgressUpdateRequestData egressUpdateRequestData = new EgressUpdateRequestData();
egressUpdateRequestData.setCluster(cluster);
egressUpdateRequestData.setEgressData(egressData);
return egressUpdateRequestData;
}
private static List<EgressDto> getEgressDtoList() {
return List.of(getEgressDto("test1.com", "8080"),
getEgressDto("test2.com", "8081"),
getEgressDto("test3.com", "8082"));
}
private static Egress getEgress(String host, String port, String cluster) {
private static Egress getEgress(
String host, String port, String cluster, String team,
String vertical, String manifestEnvironment, String manifestName
) {
Egress egress = new Egress();
egress.setHost(host);
egress.setPort(port);
egress.setCluster(cluster);
egress.setTeam(team);
egress.setVertical(vertical);
egress.setManifestEnvironment(manifestEnvironment);
egress.setManifestName(manifestName);
return egress;
}
private static List<Egress> getEgressList() {
return List.of(getEgress("test1.com", "8080", "spike.np.navi-tech.in"),
getEgress("test2.com", "8081", "prod.cmd.navi-tech.in"),
getEgress("test3.com", "8082", "aps1.prod.navi-tech.in"));
private static List<Egress> getEgressList() {
return List.of(
getEgress("test1.com", "8080", "spike.np.navi-tech.in",
"team1", "vertical1", "env1",
"manifest1"),
getEgress("test2.com", "8081", "prod.cmd.navi-tech.in",
"team2", "vertical2", "evn2",
"manifest2"),
getEgress("test3.com", "8082", "aps1.prod.navi-tech.in",
"team3", "vertical3", "env3",
"manifest3"));
}
private static Egress getEgress(EgressDto egressDto, String cluster) {
return new Egress(egressDto.getHost(), egressDto.getPort(), cluster,
egressDto.getVertical(), egressDto.getTeam(), egressDto.getManifestName(),
egressDto.getManifestEnvironment());
}
@BeforeEach
void setup() {
@@ -79,13 +97,12 @@ class EgressServiceImplTest {
@DisplayName("should get egresses")
void shouldGetEgresses() {
String cluster = "test-cluster";
List<EgressDto> egresses = List.of(getEgressDto("test1.com", "8080"),
getEgressDto("test2.com", "8081"),
getEgressDto("test3.com", "8082"));
var egresses = getEgressList();
var egressDtos = egresses.stream().map(EgressDto::new).collect(Collectors.toList());
when(egressRepository.findByCluster(cluster)).thenReturn(egresses);
List<EgressDto> result = egressService.getEgresses(cluster);
verify(egressRepository, times(1)).findByCluster(cluster);
assertEquals(egresses, result);
assertEquals(egressDtos, result);
}
@Test
@@ -93,11 +110,14 @@ class EgressServiceImplTest {
void shouldAddEgresses() {
List<EgressUpdateRequestData> egressUpdateRequestData = new ArrayList<>();
egressUpdateRequestData.add(getEgressUpdateRequestData("spike.np.navi-tech.in",
List.of(getEgressDto("test1.com", "8080"))));
List.of(getEgressDto("test1.com", "8080", "team1", "vertical1", "env1",
"manifest1"))));
egressUpdateRequestData.add(getEgressUpdateRequestData("prod.cmd.navi-tech.in",
List.of(getEgressDto("test2.com", "8081"))));
List.of(getEgressDto("test2.com", "8081", "team2", "vertical2", "evn2",
"manifest2"))));
egressUpdateRequestData.add(getEgressUpdateRequestData("aps1.prod.navi-tech.in",
List.of(getEgressDto("test3.com", "8082"))));
List.of(getEgressDto("test3.com", "8082", "team3", "vertical3", "env3",
"manifest3"))));
List<Egress> egresses = getEgressList();
Set<Egress> newEgresses = new HashSet<>(egresses);
boolean dryRun = false;
@@ -106,7 +126,8 @@ class EgressServiceImplTest {
verify(egressRepository, times(1)).saveAll(newEgresses);
verify(egressRepository, times(1)).deleteAll(Set.of());
verify(egressRepository, times(2)).findAll();
EgressUpdateResponse egressUpdateResponse = new EgressUpdateResponse(Map.of(), egresses, dryRun);
EgressUpdateResponse egressUpdateResponse = new EgressUpdateResponse(Map.of(), egresses,
dryRun);
assertEquals(egressUpdateResponse, result);
}
@@ -115,11 +136,14 @@ class EgressServiceImplTest {
void shouldNotUpdateRepositoryWhenDryRunIsTrue() {
List<EgressUpdateRequestData> egressUpdateRequestData = new ArrayList<>();
egressUpdateRequestData.add(getEgressUpdateRequestData("spike.np.navi-tech.in",
List.of(getEgressDto("test1.com", "8080"))));
List.of(getEgressDto("test1.com", "8080", "team1", "vertical1", "env1",
"manifest1"))));
egressUpdateRequestData.add(getEgressUpdateRequestData("prod.cmd.navi-tech.in",
List.of(getEgressDto("test2.com", "8081"))));
List.of(getEgressDto("test2.com", "8081", "team2", "vertical2", "evn2",
"manifest2"))));
egressUpdateRequestData.add(getEgressUpdateRequestData("aps1.prod.navi-tech.in",
List.of(getEgressDto("test3.com", "8082"))));
List.of(getEgressDto("test3.com", "8082", "team3", "vertical3", "env3",
"manifest3"))));
List<Egress> egresses = getEgressList();
Set<Egress> newEgresses = new HashSet<>(egresses);
boolean dryRun = true;
@@ -128,7 +152,43 @@ class EgressServiceImplTest {
verify(egressRepository, times(0)).saveAll(newEgresses);
verify(egressRepository, times(0)).deleteAll(Set.of());
verify(egressRepository, times(1)).findAll();
EgressUpdateResponse egressUpdateResponse = new EgressUpdateResponse(Map.of(), List.of(), dryRun);
EgressUpdateResponse egressUpdateResponse = new EgressUpdateResponse(Map.of(), List.of(),
dryRun);
assertEquals(egressUpdateResponse, result);
}
@Test
@DisplayName("should update egress which differs in fields other than host, port, cluster")
void shouldUpdateEgressWhichDiffersInFieldsOtherThanHostPortCluster() {
List<EgressUpdateRequestData> egressUpdateRequestData = new ArrayList<>();
var updatedEgressDto1 = getEgressDto("test1.com", "8080", "team4", "vertical1", "env1",
"manifest1");
var updatedEgressDto2 = getEgressDto("test2.com", "8081", "team6", "vertical2", "evn2",
"manifest6");
var updatedEgressDto3 = getEgressDto("test3.com", "8082", "team7", "vertical3", "env3",
"manifest7");
egressUpdateRequestData.add(getEgressUpdateRequestData("spike.np.navi-tech.in",
List.of(updatedEgressDto1)));
egressUpdateRequestData.add(getEgressUpdateRequestData("prod.cmd.navi-tech.in",
List.of(updatedEgressDto2)));
egressUpdateRequestData.add(getEgressUpdateRequestData("aps1.prod.navi-tech.in",
List.of(updatedEgressDto3)));
Set<Egress> newEgresses = new HashSet<>(List.of(
getEgress(updatedEgressDto1, "spike.np.navi-tech.in"),
getEgress(updatedEgressDto2, "prod.cmd.navi-tech.in"),
getEgress(updatedEgressDto3, "aps1.prod.navi-tech.in")
));
List<Egress> egresses = getEgressList();
boolean dryRun = false;
when(egressRepository.findAll()).thenReturn(egresses);
EgressUpdateResponse result = egressService.updateEgresses(egressUpdateRequestData, dryRun);
verify(egressRepository, times(1)).saveAll(Collections.emptySet());
verify(egressRepository, times(1)).saveAll(newEgresses);
verify(egressRepository, times(1)).deleteAll(Set.of());
verify(egressRepository, times(2)).findAll();
EgressUpdateResponse egressUpdateResponse = new EgressUpdateResponse(Map.of(), egresses,
dryRun);
assertEquals(egressUpdateResponse, result);
}
}

View File

@@ -4,6 +4,11 @@ deployment:
- Infra
values:
- false
allowEndpoint:
approvalFrom:
- ENDPOINT_OWNER_TEAM
forEach: {}
hasHashedIdentifier: true
instance:
minCPU:
approvalFrom:

View File

@@ -4,6 +4,11 @@ deployment:
- Infra
values:
- false
allowEndpoint:
approvalFrom:
- ENDPOINT_OWNER_TEAM
forEach: {}
hasHashedIdentifier: true
instance:
minCPU:
approvalFrom:

View File

@@ -0,0 +1,11 @@
[
{
"op": "op",
"path": "/deployment/allowEndpoint/*",
"limitPath": "/deployment/allowEndpoint",
"value": {
"host": "endpoint.one",
"port": "4321"
}
}
]

View File

@@ -15,3 +15,8 @@ deployment:
- team2
values:
- 0.0.0.0/0
allowEndpoint:
approvalFrom:
- ENDPOINT_OWNER_TEAM
forEach: { }
hasHashedIdentifier: true