INFRA-2701 | Dhruv | Add acl for pipeline generation
This commit is contained in:
@@ -31,11 +31,15 @@ public class PipelineManifestController {
|
||||
|
||||
private PipelineManifestService pipelineManifestService;
|
||||
|
||||
@PostMapping()
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
public ResponseEntity<?> generatePipelines(@RequestBody PipelineManifest pipelineRequest) {
|
||||
@PostMapping("/{environment}")
|
||||
public ResponseEntity<?> generatePipelines(
|
||||
@PathVariable String environment,
|
||||
@RequestBody PipelineManifest pipelineRequest
|
||||
) {
|
||||
try {
|
||||
JSONObject pipelineJson = pipelineManifestService.generateGocdPipeline(pipelineRequest);
|
||||
JSONObject pipelineJson = pipelineManifestService.generateGocdPipeline(pipelineRequest,
|
||||
environment);
|
||||
return new ResponseEntity<>(pipelineJson, HttpStatus.OK);
|
||||
} catch (GocdValidationException | PipelineDifferenceException e) {
|
||||
return new ResponseEntity<>(new ExceptionResponse<>(e.getMessage()),
|
||||
|
||||
@@ -3,10 +3,14 @@ package com.navi.infra.portal.service.gocd;
|
||||
import static com.navi.infra.portal.security.authorization.AuthorizationContext.getUserEmail;
|
||||
import static com.navi.infra.portal.util.EncoderDecoderUtil.base64Decode;
|
||||
import static com.navi.infra.portal.util.EncoderDecoderUtil.base64Encode;
|
||||
import static com.navi.infra.portal.v2.privilege.Action.MANIFEST_WRITE;
|
||||
import static com.navi.infra.portal.v2.privilege.ResourceType.MANIFEST;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.navi.infra.portal.domain.gocd.PipelineManifest;
|
||||
import com.navi.infra.portal.domain.manifest.Manifest;
|
||||
import com.navi.infra.portal.repository.PipelineManifestRepository;
|
||||
import com.navi.infra.portal.security.authorization.AuthorizationService;
|
||||
import com.navi.infra.portal.service.manifest.ManifestService;
|
||||
import com.navi.infra.portal.util.KubernetesManifestGenerator;
|
||||
import com.navi.infra.portal.util.MapDiffUtil;
|
||||
@@ -35,8 +39,8 @@ import org.json.simple.parser.JSONParser;
|
||||
import org.json.simple.parser.ParseException;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@@ -52,13 +56,13 @@ public class PipelineManifestService {
|
||||
private final ObjectMapper yamlMapper;
|
||||
|
||||
private final PipelineManifestRepository pipelineManifestRepository;
|
||||
private final ManifestService manifestService;
|
||||
|
||||
private final KubernetesManifestGenerator kubernetesManifestGenerator;
|
||||
private final GitHubClient gitHubClient;
|
||||
private final PipelineValidator pipelineValidator;
|
||||
private final AuthorizationService authorizationFilter;
|
||||
private final ManifestService manifestService;
|
||||
private final GocdConfigValidator gocdConfigValidator;
|
||||
private final PipelineValidator pipelineValidator;
|
||||
private final MapDiffUtil mapDiffUtil;
|
||||
private final GitHubClient gitHubClient;
|
||||
|
||||
PipelineManifestService(
|
||||
ObjectMapper objectMapper,
|
||||
@@ -66,6 +70,7 @@ public class PipelineManifestService {
|
||||
PipelineManifestRepository pipelineManifestRepository,
|
||||
KubernetesManifestGenerator kubernetesManifestGenerator,
|
||||
ManifestService manifestService,
|
||||
AuthorizationService authorizationFilter,
|
||||
GitHubClient gitHubClient,
|
||||
PipelineValidator pipelineValidator,
|
||||
GocdConfigValidator gocdConfigValidator,
|
||||
@@ -78,6 +83,7 @@ public class PipelineManifestService {
|
||||
this.pipelineManifestRepository = pipelineManifestRepository;
|
||||
this.kubernetesManifestGenerator = kubernetesManifestGenerator;
|
||||
this.manifestService = manifestService;
|
||||
this.authorizationFilter = authorizationFilter;
|
||||
this.gitHubClient = gitHubClient;
|
||||
this.pipelineValidator = pipelineValidator;
|
||||
this.gocdConfigValidator = gocdConfigValidator;
|
||||
@@ -100,8 +106,7 @@ public class PipelineManifestService {
|
||||
Map<String, Object> deployedPipeline = yamlMapper.readValue(deployedPipelineString,
|
||||
Map.class);
|
||||
Map<String, Object> pipelineMap = objectMapper.convertValue(pipelineJson, Map.class);
|
||||
var diff = mapDiffUtil.diff(pipelineMap, deployedPipeline);
|
||||
return !diff.addedEntries.isEmpty() || !diff.deletedEntries.isEmpty();
|
||||
return mapDiffUtil.areEqual(pipelineMap, deployedPipeline);
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage());
|
||||
return true;
|
||||
@@ -138,12 +143,12 @@ public class PipelineManifestService {
|
||||
}
|
||||
|
||||
private void validatePipelineDifference(
|
||||
PipelineManifest existingPipelineManifest, String content
|
||||
String pipelineName, PipelineManifest existingPipelineManifest, String content
|
||||
) {
|
||||
if (manualChangesInPipeline(existingPipelineManifest, content)) {
|
||||
throw new PipelineDifferenceException(String.format(
|
||||
"Manual changes in pipeline %s detected. Please update the pipeline manually",
|
||||
existingPipelineManifest.getName()));
|
||||
pipelineName));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,26 +174,40 @@ public class PipelineManifestService {
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public JSONObject generateGocdPipeline(PipelineManifest pipelineManifest) {
|
||||
public JSONObject generateGocdPipeline(PipelineManifest pipelineManifest, String environment) {
|
||||
|
||||
Manifest manifest = manifestService.fetchByNameAndEnvironment(pipelineManifest.getName(),
|
||||
environment);
|
||||
if (!authorizationFilter.hasPermissions(MANIFEST, manifest, MANIFEST_WRITE)) {
|
||||
throw new AccessDeniedException("User does not have permission to create pipeline");
|
||||
}
|
||||
if (!pipelineValidator.isValidPipeline(pipelineManifest)) {
|
||||
throw new InvalidRequestStateException(
|
||||
String.format("Invalid pipeline manifest request for %s",
|
||||
pipelineManifest.getName()));
|
||||
}
|
||||
return generateGocdPipeline(pipelineManifest);
|
||||
}
|
||||
|
||||
private JSONObject generateGocdPipeline(PipelineManifest pipelineManifest) {
|
||||
String filePath = String.format("%s.gocd.yaml", pipelineManifest.getName());
|
||||
GitHubApiResponse fileContent = gitHubClient.getFileContent(orgName, filePath);
|
||||
PipelineManifest existingPipelineManifest = getPipelineManifest(
|
||||
pipelineManifest.getName());
|
||||
if (fileContent != null) {
|
||||
validatePipelineDifference(existingPipelineManifest, fileContent.getContent());
|
||||
validatePipelineDifference(pipelineManifest.getName(), existingPipelineManifest,
|
||||
fileContent.getContent());
|
||||
}
|
||||
JSONObject pipelineJson = generatePipelineJson(pipelineManifest);
|
||||
generatePipelineYaml(pipelineManifest, pipelineJson);
|
||||
validateGocdConfig(pipelineManifest);
|
||||
createOrUpdatePipelineInGitHub(filePath, fileContent, pipelineJson);
|
||||
existingPipelineManifest.setData(pipelineManifest.getData());
|
||||
pipelineManifestRepository.save(existingPipelineManifest);
|
||||
if (existingPipelineManifest == null) {
|
||||
pipelineManifestRepository.save(pipelineManifest);
|
||||
} else {
|
||||
existingPipelineManifest.setData(pipelineManifest.getData());
|
||||
pipelineManifestRepository.save(existingPipelineManifest);
|
||||
}
|
||||
return pipelineJson;
|
||||
}
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ public class MapDiffUtil {
|
||||
return diff(processedMaps.getFirst(), processedMaps.getSecond());
|
||||
}
|
||||
|
||||
public boolean areMapEqual(
|
||||
public boolean areEqual(
|
||||
final Map<String, Object> oldMap,
|
||||
final Map<String, Object> newMap
|
||||
) {
|
||||
|
||||
@@ -53,7 +53,7 @@ public class GitHubClient {
|
||||
HttpResponse<String> response = httpClient.send(request,
|
||||
HttpResponse.BodyHandlers.ofString());
|
||||
if (response.statusCode() == HttpStatus.OK.value()) {
|
||||
log.info("Successfully retrieved file content from GitHub.");
|
||||
log.info("Successfully retrieved file content from GitHub for {}", filePath);
|
||||
return objectMapper.readValue(response.body(), GitHubApiResponse.class);
|
||||
}
|
||||
if (response.statusCode() == HttpStatus.NOT_FOUND.value()) {
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
package com.navi.infra.portal.v2.pipeline.service;
|
||||
|
||||
public interface PipelineGenerationService {
|
||||
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package com.navi.infra.portal.v2.pipeline.service;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.navi.infra.portal.v2.client.github.GitHubClient;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class PipelineGenerationServiceImpl implements PipelineGenerationService {
|
||||
|
||||
private final GitHubClient gitHubClient;
|
||||
private final ObjectMapper yamlMapper;
|
||||
private final ObjectMapper jsonMapper;
|
||||
|
||||
public PipelineGenerationServiceImpl(
|
||||
GitHubClient gitHubClient,
|
||||
@Qualifier("jsonMapper") ObjectMapper jsonMapper,
|
||||
@Qualifier("yamlMapper") ObjectMapper yamlMapper
|
||||
) {
|
||||
this.gitHubClient = gitHubClient;
|
||||
this.jsonMapper = jsonMapper;
|
||||
this.yamlMapper = yamlMapper;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -40,6 +40,7 @@ public class PipelineManifestServiceTest extends ExternalIntegrationProvider {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user