INFRA-2701 | Dhruv | Add acl for pipeline generation

This commit is contained in:
dhruvjoshi
2024-05-24 15:23:49 +05:30
parent 0795d7474c
commit 8c29cfa37a
7 changed files with 43 additions and 52 deletions

View File

@@ -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()),

View File

@@ -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;
}

View File

@@ -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
) {

View File

@@ -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()) {

View File

@@ -1,5 +0,0 @@
package com.navi.infra.portal.v2.pipeline.service;
public interface PipelineGenerationService {
}

View File

@@ -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;
}
}

View File

@@ -40,6 +40,7 @@ public class PipelineManifestServiceTest extends ExternalIntegrationProvider {
null,
null,
null,
null,
null
);
}