Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
181 changes: 113 additions & 68 deletions pkg/appClone/AppCloneService.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ type AppCloneServiceImpl struct {
pipelineStageService pipeline.PipelineStageService
ciTemplateService pipeline.CiTemplateService
appRepository app2.AppRepository
ciPipelineRepository pipelineConfig.CiPipelineRepository
pipelineRepository pipelineConfig.PipelineRepository
appWorkflowRepository appWorkflow2.AppWorkflowRepository
}

func NewAppCloneServiceImpl(logger *zap.SugaredLogger,
Expand All @@ -65,7 +68,8 @@ func NewAppCloneServiceImpl(logger *zap.SugaredLogger,
propertiesConfigService pipeline.PropertiesConfigService,
ciTemplateOverrideRepository pipelineConfig.CiTemplateOverrideRepository,
pipelineStageService pipeline.PipelineStageService, ciTemplateService pipeline.CiTemplateService,
appRepository app2.AppRepository) *AppCloneServiceImpl {
appRepository app2.AppRepository, ciPipelineRepository pipelineConfig.CiPipelineRepository,
pipelineRepository pipelineConfig.PipelineRepository, appWorkflowRepository appWorkflow2.AppWorkflowRepository) *AppCloneServiceImpl {
return &AppCloneServiceImpl{
logger: logger,
pipelineBuilder: pipelineBuilder,
Expand All @@ -78,6 +82,9 @@ func NewAppCloneServiceImpl(logger *zap.SugaredLogger,
pipelineStageService: pipelineStageService,
ciTemplateService: ciTemplateService,
appRepository: appRepository,
ciPipelineRepository: ciPipelineRepository,
pipelineRepository: pipelineRepository,
appWorkflowRepository: appWorkflowRepository,
}
}

Expand All @@ -90,6 +97,16 @@ type CloneRequest struct {
AppType helper.AppType `json:"appType"`
}

type CreateWorkflowMappingDto struct {
oldAppId int
newAppId int
userId int32
newWfId int
gitMaterialMapping map[int]int
isSameProject bool
externalCiPipelineId int
}

func (impl *AppCloneServiceImpl) CloneApp(createReq *bean.CreateAppDTO, context context.Context) (*bean.CreateAppDTO, error) {
//validate template app
templateApp, err := impl.appRepository.FindById(createReq.TemplateId)
Expand Down Expand Up @@ -586,6 +603,7 @@ func (impl *AppCloneServiceImpl) CreateWf(oldAppId, newAppId int, userId int32,
return nil, err
}
impl.logger.Debugw("workflow found", "wf", refAppWFs)

for _, refAppWF := range refAppWFs {
thisWf := appWorkflow.AppWorkflowDto{
Id: 0,
Expand All @@ -594,24 +612,38 @@ func (impl *AppCloneServiceImpl) CreateWf(oldAppId, newAppId int, userId int32,
AppWorkflowMappingDto: nil, //first create new mapping then add it
UserId: userId,
}
thisWf, err = impl.appWorkflowService.CreateAppWorkflow(thisWf)
if err != nil {
impl.logger.Errorw("error in creating workflow without external-ci", "err", err)
return nil, err
}

isExternalCiPresent := false
for _, awm := range refAppWF.AppWorkflowMappingDto {
if awm.Type == appWorkflow2.WEBHOOK {
isExternalCiPresent = true
break
}
}

if !isExternalCiPresent {
thisWf, err = impl.appWorkflowService.CreateAppWorkflow(thisWf)
impl.logger.Debugw("workflow found", thisWf)
createWorkflowMappingDto := CreateWorkflowMappingDto{
newAppId: newAppId,
oldAppId: oldAppId,
newWfId: thisWf.Id,
userId: userId,
}
var externalCiPipelineId int
if isExternalCiPresent {
externalCiPipelineId, err = impl.createExternalCiAndAppWorkflowMapping(createWorkflowMappingDto)
if err != nil {
impl.logger.Errorw("errir in creating workflow without extenal-ci", "err", err)
impl.logger.Errorw("error in createExternalCiAndAppWorkflowMapping", "err", err)
return nil, err
}
}
createWorkflowMappingDto.gitMaterialMapping = gitMaterialMapping
createWorkflowMappingDto.isSameProject = isSameProject
createWorkflowMappingDto.externalCiPipelineId = externalCiPipelineId

err = impl.createWfMappings(refAppWF.AppWorkflowMappingDto, oldAppId, newAppId, userId, thisWf.Id, gitMaterialMapping, ctx, isSameProject)
err = impl.createWfInstances(refAppWF.AppWorkflowMappingDto, createWorkflowMappingDto, ctx)
if err != nil {
impl.logger.Errorw("error in creating workflow mapping", "err", err)
return nil, err
Expand All @@ -620,7 +652,28 @@ func (impl *AppCloneServiceImpl) CreateWf(oldAppId, newAppId int, userId int32,
return nil, nil
}

func (impl *AppCloneServiceImpl) createWfMappings(refWfMappings []appWorkflow.AppWorkflowMappingDto, oldAppId, newAppId int, userId int32, thisWfId int, gitMaterialMapping map[int]int, ctx context.Context, isSameProject bool) error {
func (impl *AppCloneServiceImpl) createExternalCiAndAppWorkflowMapping(createWorkflowMappingDto CreateWorkflowMappingDto) (int, error) {
dbConnection := impl.pipelineRepository.GetConnection()
tx, err := dbConnection.Begin()
if err != nil {
impl.logger.Errorw("error in beginning transaction", "err", err)
return 0, err
}
// Rollback tx on error.
defer tx.Rollback()
externalCiPipelineId, err := impl.pipelineBuilder.CreateExternalCiAndAppWorkflowMapping(createWorkflowMappingDto.newAppId, createWorkflowMappingDto.newWfId, createWorkflowMappingDto.userId, tx)
if err != nil {
impl.logger.Errorw("error in creating new external ci pipeline and new app workflow mapping", "refAppId", createWorkflowMappingDto.oldAppId, "newAppId", createWorkflowMappingDto.newAppId, "err", err)
return 0, err
}
err = tx.Commit()
if err != nil {
return 0, err
}
return externalCiPipelineId, nil
}

func (impl *AppCloneServiceImpl) createWfInstances(refWfMappings []appWorkflow.AppWorkflowMappingDto, createWorkflowMappingDto CreateWorkflowMappingDto, ctx context.Context) error {
impl.logger.Debugw("wf mapping cloning", "refWfMappings", refWfMappings)
var ciMapping []appWorkflow.AppWorkflowMappingDto
var cdMappings []appWorkflow.AppWorkflowMappingDto
Expand All @@ -636,23 +689,30 @@ func (impl *AppCloneServiceImpl) createWfMappings(refWfMappings []appWorkflow.Ap
return fmt.Errorf("unsupported wf type: %s", appWf.Type)
}
}
refApp, err := impl.pipelineBuilder.GetApp(oldAppId)
sourceToNewPipelineIdMapping := make(map[int]int)
refApp, err := impl.pipelineBuilder.GetApp(createWorkflowMappingDto.oldAppId)
if err != nil {
impl.logger.Errorw("error in getting app from refAppId", "refAppId", createWorkflowMappingDto.oldAppId)
return err
}
if len(webhookMappings) > 0 {
if isSameProject {
if createWorkflowMappingDto.isSameProject {
for _, refwebhookMappings := range cdMappings {
cdCloneReq := &cloneCdPipelineRequest{
refCdPipelineId: refwebhookMappings.ComponentId,
refAppId: oldAppId,
appId: newAppId,
userId: userId,
ciPipelineId: 0,
appWfId: thisWfId,
refAppName: refApp.AppName,
refCdPipelineId: refwebhookMappings.ComponentId,
refAppId: createWorkflowMappingDto.oldAppId,
appId: createWorkflowMappingDto.newAppId,
userId: createWorkflowMappingDto.userId,
ciPipelineId: 0,
appWfId: createWorkflowMappingDto.newWfId,
refAppName: refApp.AppName,
sourceToNewPipelineId: sourceToNewPipelineIdMapping,
externalCiPipelineId: createWorkflowMappingDto.externalCiPipelineId,
}
pipeline, err := impl.CreateCdPipeline(cdCloneReq, ctx)
impl.logger.Debugw("cd pipeline created", "pipeline", pipeline)
if err != nil {
impl.logger.Errorw("error in getting cd-pipeling", "err", err)
impl.logger.Errorw("error in getting cd-pipeline", "refAppId", createWorkflowMappingDto.oldAppId, "newAppId", createWorkflowMappingDto.newAppId, "err", err)
return err
}
}
Expand All @@ -666,7 +726,7 @@ func (impl *AppCloneServiceImpl) createWfMappings(refWfMappings []appWorkflow.Ap
impl.logger.Warn("no ci pipeline found")
return nil
} else if len(ciMapping) != 1 {
impl.logger.Warn("more than one cd pipeline not supported")
impl.logger.Warn("more than one ci pipeline not supported")
return nil
}

Expand All @@ -678,12 +738,12 @@ func (impl *AppCloneServiceImpl) createWfMappings(refWfMappings []appWorkflow.Ap
impl.logger.Debugw("creating ci", "ref", refCiMapping)

cloneCiPipelineRequest := &cloneCiPipelineRequest{
refAppId: oldAppId,
refAppId: createWorkflowMappingDto.oldAppId,
refCiPipelineId: refCiMapping.ComponentId,
userId: userId,
appId: newAppId,
wfId: thisWfId,
gitMaterialMapping: gitMaterialMapping,
userId: createWorkflowMappingDto.userId,
appId: createWorkflowMappingDto.newAppId,
wfId: createWorkflowMappingDto.newWfId,
gitMaterialMapping: createWorkflowMappingDto.gitMaterialMapping,
refAppName: refApp.AppName,
}
ci, err = impl.CreateCiPipeline(cloneCiPipelineRequest)
Expand All @@ -693,16 +753,18 @@ func (impl *AppCloneServiceImpl) createWfMappings(refWfMappings []appWorkflow.Ap
}
impl.logger.Debugw("ci created", "ci", ci)
}
if isSameProject {

if createWorkflowMappingDto.isSameProject {
for _, refCdMapping := range cdMappings {
cdCloneReq := &cloneCdPipelineRequest{
refCdPipelineId: refCdMapping.ComponentId,
refAppId: oldAppId,
appId: newAppId,
userId: userId,
ciPipelineId: ci.CiPipelines[0].Id,
appWfId: thisWfId,
refAppName: refApp.AppName,
refCdPipelineId: refCdMapping.ComponentId,
refAppId: createWorkflowMappingDto.oldAppId,
appId: createWorkflowMappingDto.newAppId,
userId: createWorkflowMappingDto.userId,
ciPipelineId: ci.CiPipelines[0].Id,
appWfId: createWorkflowMappingDto.newWfId,
refAppName: refApp.AppName,
sourceToNewPipelineId: sourceToNewPipelineIdMapping,
}
pipeline, err := impl.CreateCdPipeline(cdCloneReq, ctx)
if err != nil {
Expand Down Expand Up @@ -866,13 +928,15 @@ func (impl *AppCloneServiceImpl) CreateCiPipeline(req *cloneCiPipelineRequest) (
}

type cloneCdPipelineRequest struct {
refCdPipelineId int
refAppId int
appId int
userId int32
ciPipelineId int
appWfId int
refAppName string
refCdPipelineId int
refAppId int
appId int
userId int32
ciPipelineId int
appWfId int
refAppName string
sourceToNewPipelineId map[int]int
externalCiPipelineId int
}

func (impl *AppCloneServiceImpl) CreateCdPipeline(req *cloneCdPipelineRequest, ctx context.Context) (*bean.CdPipelines, error) {
Expand All @@ -890,6 +954,7 @@ func (impl *AppCloneServiceImpl) CreateCdPipeline(req *cloneCdPipelineRequest, c
if refCdPipeline == nil {
return nil, fmt.Errorf("no cd pipeline found")
}
refCdPipeline.SourceToNewPipelineId = req.sourceToNewPipelineId
pipelineName := refCdPipeline.Name
if strings.HasPrefix(pipelineName, req.refAppName) {
pipelineName = strings.Replace(pipelineName, req.refAppName+"-", "", 1)
Expand Down Expand Up @@ -920,35 +985,6 @@ func (impl *AppCloneServiceImpl) CreateCdPipeline(req *cloneCdPipelineRequest, c
deploymentAppType = util.PIPELINE_DEPLOYMENT_TYPE_HELM
}

if refCdPipeline.ParentPipelineType == "WEBHOOK" {
cdPipeline := &bean.CDPipelineConfigObject{
Id: 0,
EnvironmentId: refCdPipeline.EnvironmentId,
CiPipelineId: 0,
TriggerType: refCdPipeline.TriggerType,
Name: pipelineName,
Strategies: refCdPipeline.Strategies,
Namespace: refCdPipeline.Namespace,
AppWorkflowId: 0,
DeploymentTemplate: refCdPipeline.DeploymentTemplate,
PreStage: refCdPipeline.PreStage, //FIXME
PostStage: refCdPipeline.PostStage,
PreStageConfigMapSecretNames: refCdPipeline.PreStageConfigMapSecretNames,
PostStageConfigMapSecretNames: refCdPipeline.PostStageConfigMapSecretNames,
RunPostStageInEnv: refCdPipeline.RunPostStageInEnv,
RunPreStageInEnv: refCdPipeline.RunPreStageInEnv,
DeploymentAppType: refCdPipeline.DeploymentAppType,
ParentPipelineId: 0,
ParentPipelineType: refCdPipeline.ParentPipelineType,
}
cdPipelineReq := &bean.CdPipelines{
Pipelines: []*bean.CDPipelineConfigObject{cdPipeline},
AppId: req.appId,
UserId: req.userId,
}
cdPipelineRes, err := impl.pipelineBuilder.CreateCdPipelines(cdPipelineReq, ctx)
return cdPipelineRes, err
}
cdPipeline := &bean.CDPipelineConfigObject{
Id: 0,
EnvironmentId: refCdPipeline.EnvironmentId,
Expand All @@ -968,6 +1004,15 @@ func (impl *AppCloneServiceImpl) CreateCdPipeline(req *cloneCdPipelineRequest, c
DeploymentAppType: deploymentAppType,
PreDeployStage: refCdPipeline.PreDeployStage,
PostDeployStage: refCdPipeline.PostDeployStage,
SourceToNewPipelineId: refCdPipeline.SourceToNewPipelineId,
RefPipelineId: refCdPipeline.Id,
ParentPipelineType: refCdPipeline.ParentPipelineType,
}
if refCdPipeline.ParentPipelineType == "WEBHOOK" {
cdPipeline.CiPipelineId = 0
cdPipeline.ParentPipelineId = req.externalCiPipelineId
} else if refCdPipeline.ParentPipelineType != appWorkflow.CI_PIPELINE_TYPE {
cdPipeline.ParentPipelineId = refCdPipeline.ParentPipelineId
}
cdPipelineReq := &bean.CdPipelines{
Pipelines: []*bean.CDPipelineConfigObject{cdPipeline},
Expand Down
3 changes: 3 additions & 0 deletions pkg/bean/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,9 @@ type CDPipelineConfigObject struct {
ManifestStorageType string `json:"manifestStorageType"`
PreDeployStage *bean.PipelineStageDto `json:"preDeployStage,omitempty"`
PostDeployStage *bean.PipelineStageDto `json:"postDeployStage,omitempty"`
SourceToNewPipelineId map[int]int `json:"sourceToNewPipelineId,omitempty"`
RefPipelineId int `json:"refPipelineId,omitempty"`
ExternalCiPipelineId int `json:"externalCiPipelineId,omitempty"`
}

type PreStageConfigMapSecretNames struct {
Expand Down
Loading