Skip to content

Commit 9bd59a2

Browse files
iamayushmAsh-exp
andauthored
feat: using image digest in deployment (#4515)
* wip: pull image using digest support * api spec for saving digest enforcement config * wip * adding get api for digest config * wip * policy save and use code * removing unused code * dev testing fixes * refactoring transaction * imageDigest service name change * fixing json nam * removing hard coded config * removing unnecessary space * marking images superseded and duplicate flag * marking image superseded - dev testing changes * adding in precd-postcd * wip * wip * digest support in app clone * updating cd-pipeline api * removing superseded code * refactoring policy configuration code * refactoring * wip * refactoring * pr review changes * removing unused method * metadata in logs * refactoring and code cleanuo * migration script refactoring * migration script refactoring * wip: fixing create flow id * wip * wire fix * wip * wip --------- Co-authored-by: Ash-exp <[email protected]>
1 parent d714166 commit 9bd59a2

17 files changed

+347
-22
lines changed

Wire.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ import (
107107
"github.com/devtron-labs/devtron/pkg/generateManifest"
108108
"github.com/devtron-labs/devtron/pkg/git"
109109
"github.com/devtron-labs/devtron/pkg/gitops"
110+
"github.com/devtron-labs/devtron/pkg/imageDigestPolicy"
110111
"github.com/devtron-labs/devtron/pkg/kubernetesResourceAuditLogs"
111112
repository7 "github.com/devtron-labs/devtron/pkg/kubernetesResourceAuditLogs/repository"
112113
"github.com/devtron-labs/devtron/pkg/notifier"
@@ -942,6 +943,9 @@ func InitializeApp() (*App, error) {
942943
pipeline.NewPipelineConfigListenerServiceImpl,
943944
wire.Bind(new(pipeline.PipelineConfigListenerService), new(*pipeline.PipelineConfigListenerServiceImpl)),
944945
cron2.NewCronLoggerImpl,
946+
947+
imageDigestPolicy.NewImageDigestPolicyServiceImpl,
948+
wire.Bind(new(imageDigestPolicy.ImageDigestPolicyService), new(*imageDigestPolicy.ImageDigestPolicyServiceImpl)),
945949
)
946950
return &App{}, nil
947951
}

cmd/external-app/wire_gen.go

Lines changed: 6 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/appClone/AppCloneService.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,6 +1021,7 @@ func (impl *AppCloneServiceImpl) CreateCdPipeline(req *cloneCdPipelineRequest, c
10211021
SourceToNewPipelineId: refCdPipeline.SourceToNewPipelineId,
10221022
RefPipelineId: refCdPipeline.Id,
10231023
ParentPipelineType: refCdPipeline.ParentPipelineType,
1024+
IsDigestEnforcedForPipeline: refCdPipeline.IsDigestEnforcedForPipeline,
10241025
}
10251026
if refCdPipeline.ParentPipelineType == "WEBHOOK" {
10261027
cdPipeline.CiPipelineId = 0

pkg/bean/app.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,8 @@ type CDPipelineConfigObject struct {
590590
SwitchFromCiPipelineId int `json:"switchFromCiPipelineId"`
591591
CDPipelineAddType CDPipelineAddType `json:"addType"`
592592
ChildPipelineId int `json:"childPipelineId"`
593+
IsDigestEnforcedForPipeline bool `json:"isDigestEnforcedForPipeline"`
594+
IsDigestEnforcedForEnv bool `json:"isDigestEnforcedForEnv"`
593595
}
594596

595597
type CDPipelineAddType string

pkg/cluster/EnvironmentService.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ type EnvironmentBean struct {
5353
AppCount int `json:"appCount"`
5454
IsVirtualEnvironment bool `json:"isVirtualEnvironment"`
5555
AllowedDeploymentTypes []string `json:"allowedDeploymentTypes"`
56+
IsDigestEnforcedForEnv bool `json:"isDigestEnforcedForEnv"`
5657
}
5758

5859
type EnvDto struct {

pkg/devtronResource/bean/bean.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const (
1111
DEVTRON_RESOURCE_SEARCHABLE_KEY_APP_ID DevtronResourceSearchableKeyName = "APP_ID"
1212
DEVTRON_RESOURCE_SEARCHABLE_KEY_ENV_ID DevtronResourceSearchableKeyName = "ENV_ID"
1313
DEVTRON_RESOURCE_SEARCHABLE_KEY_CLUSTER_ID DevtronResourceSearchableKeyName = "CLUSTER_ID"
14+
DEVTRON_RESOURCE_SEARCHABLE_KEY_PIPELINE_ID DevtronResourceSearchableKeyName = "PIPELINE_ID"
1415
)
1516

1617
func (n DevtronResourceSearchableKeyName) ToString() string {

pkg/imageDigestPolicy/bean.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package imageDigestPolicy
2+
3+
import (
4+
"github.com/devtron-labs/devtron/pkg/resourceQualifiers"
5+
"github.com/devtron-labs/devtron/pkg/sql"
6+
"time"
7+
)
8+
9+
func QualifierMappingDao(qualifierId, identifierKey, IdentifierValueInt int, identifierValueName string, userId int32) *resourceQualifiers.QualifierMapping {
10+
return &resourceQualifiers.QualifierMapping{
11+
ResourceId: resourceQualifiers.ImageDigestResourceId,
12+
ResourceType: resourceQualifiers.ImageDigest,
13+
QualifierId: qualifierId,
14+
IdentifierKey: identifierKey,
15+
IdentifierValueInt: IdentifierValueInt,
16+
IdentifierValueString: identifierValueName,
17+
Active: true,
18+
AuditLog: sql.AuditLog{
19+
CreatedOn: time.Now(),
20+
CreatedBy: userId,
21+
UpdatedOn: time.Now(),
22+
UpdatedBy: userId,
23+
},
24+
}
25+
}
26+
27+
type DigestPolicyConfigurationRequest struct {
28+
PipelineId int
29+
ClusterId int
30+
EnvironmentId int
31+
}
32+
33+
func (request DigestPolicyConfigurationRequest) getQualifierMappingScope() *resourceQualifiers.Scope {
34+
return &resourceQualifiers.Scope{
35+
EnvId: request.EnvironmentId,
36+
ClusterId: request.ClusterId,
37+
PipelineId: request.PipelineId,
38+
}
39+
}
40+
41+
type DigestPolicyConfigurationResponse struct {
42+
DigestConfiguredForPipeline bool
43+
DigestConfiguredForEnvOrCluster bool
44+
}
45+
46+
func (config DigestPolicyConfigurationResponse) UseDigestForTrigger() bool {
47+
return config.DigestConfiguredForPipeline
48+
}
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
package imageDigestPolicy
2+
3+
import (
4+
"github.com/devtron-labs/devtron/pkg/devtronResource"
5+
"github.com/devtron-labs/devtron/pkg/devtronResource/bean"
6+
"github.com/devtron-labs/devtron/pkg/resourceQualifiers"
7+
"github.com/devtron-labs/devtron/pkg/sql"
8+
"github.com/go-pg/pg"
9+
"go.uber.org/zap"
10+
"time"
11+
)
12+
13+
type ImageDigestPolicyService interface {
14+
15+
//CreatePolicyForPipeline creates image digest policy for pipeline
16+
CreatePolicyForPipeline(tx *pg.Tx, pipelineId int, pipelineName string, UserId int32) (int, error)
17+
18+
//CreatePolicyForPipelineIfNotExist creates image digest policy for pipeline if not already created
19+
CreatePolicyForPipelineIfNotExist(tx *pg.Tx, pipelineId int, pipelineName string, UserId int32) (int, error)
20+
21+
//GetDigestPolicyConfigurations returns true if pipeline or env or cluster has image digest policy enabled
22+
GetDigestPolicyConfigurations(digestConfigurationRequest DigestPolicyConfigurationRequest) (digestPolicyConfiguration DigestPolicyConfigurationResponse, err error)
23+
24+
//DeletePolicyForPipeline deletes image digest policy for a pipeline
25+
DeletePolicyForPipeline(tx *pg.Tx, pipelineId int, userId int32) (int, error)
26+
}
27+
28+
type ImageDigestPolicyServiceImpl struct {
29+
logger *zap.SugaredLogger
30+
qualifierMappingService resourceQualifiers.QualifierMappingService
31+
devtronResourceSearchableKey devtronResource.DevtronResourceSearchableKeyService
32+
}
33+
34+
func NewImageDigestPolicyServiceImpl(
35+
logger *zap.SugaredLogger,
36+
qualifierMappingService resourceQualifiers.QualifierMappingService,
37+
devtronResourceSearchableKey devtronResource.DevtronResourceSearchableKeyService,
38+
) *ImageDigestPolicyServiceImpl {
39+
return &ImageDigestPolicyServiceImpl{
40+
logger: logger,
41+
qualifierMappingService: qualifierMappingService,
42+
devtronResourceSearchableKey: devtronResourceSearchableKey,
43+
}
44+
}
45+
46+
func (impl ImageDigestPolicyServiceImpl) CreatePolicyForPipeline(tx *pg.Tx, pipelineId int, pipelineName string, UserId int32) (int, error) {
47+
48+
var qualifierMappingId int
49+
50+
devtronResourceSearchableKeyMap := impl.devtronResourceSearchableKey.GetAllSearchableKeyNameIdMap()
51+
52+
identifierKey := devtronResourceSearchableKeyMap[bean.DEVTRON_RESOURCE_SEARCHABLE_KEY_PIPELINE_ID]
53+
identifierValue := pipelineId
54+
qualifierMapping := QualifierMappingDao(int(resourceQualifiers.PIPELINE_QUALIFIER), identifierKey, identifierValue, pipelineName, UserId)
55+
_, err := impl.qualifierMappingService.CreateQualifierMappings([]*resourceQualifiers.QualifierMapping{qualifierMapping}, tx)
56+
if err != nil {
57+
impl.logger.Errorw("error in creating image digest policy for pipeline", "err", err, "pipelineId", pipelineId)
58+
return qualifierMapping.Id, err
59+
}
60+
qualifierMappingId = qualifierMapping.Id
61+
62+
return qualifierMappingId, nil
63+
}
64+
65+
func (impl ImageDigestPolicyServiceImpl) CreatePolicyForPipelineIfNotExist(tx *pg.Tx, pipelineId int, pipelineName string, UserId int32) (int, error) {
66+
67+
var qualifierMappingId int
68+
69+
policyConfigurationRequest := DigestPolicyConfigurationRequest{PipelineId: pipelineId}
70+
digestPolicyConfigurations, err := impl.GetDigestPolicyConfigurations(policyConfigurationRequest)
71+
if err != nil {
72+
impl.logger.Errorw("Error in checking if isDigestPolicyConfiguredForPipeline", "err", err, "pipelineId", pipelineId)
73+
return 0, err
74+
}
75+
76+
if !digestPolicyConfigurations.DigestConfiguredForPipeline {
77+
qualifierMappingId, err = impl.CreatePolicyForPipeline(tx, pipelineId, pipelineName, UserId)
78+
if err != nil {
79+
impl.logger.Errorw("error in creating policy for pipeline", "err", "pipelineId", pipelineId)
80+
return qualifierMappingId, nil
81+
}
82+
}
83+
return qualifierMappingId, nil
84+
}
85+
86+
func (impl ImageDigestPolicyServiceImpl) GetDigestPolicyConfigurations(digestConfigurationRequest DigestPolicyConfigurationRequest) (digestPolicyConfiguration DigestPolicyConfigurationResponse, err error) {
87+
88+
resourceIds := []int{resourceQualifiers.ImageDigestResourceId}
89+
90+
scope := digestConfigurationRequest.getQualifierMappingScope()
91+
92+
policyMappings, err := impl.qualifierMappingService.GetQualifierMappings(resourceQualifiers.ImageDigest, scope, resourceIds)
93+
if err != nil && err != pg.ErrNoRows {
94+
return digestPolicyConfiguration, err
95+
}
96+
if err == pg.ErrNoRows || len(policyMappings) == 0 {
97+
return digestPolicyConfiguration, nil
98+
}
99+
100+
devtronResourceSearchableKeyMap := impl.devtronResourceSearchableKey.GetAllSearchableKeyNameIdMap()
101+
clusterIdentifierKey := devtronResourceSearchableKeyMap[bean.DEVTRON_RESOURCE_SEARCHABLE_KEY_CLUSTER_ID]
102+
envIdentifierKey := devtronResourceSearchableKeyMap[bean.DEVTRON_RESOURCE_SEARCHABLE_KEY_ENV_ID]
103+
pipelineIdentifierKey := devtronResourceSearchableKeyMap[bean.DEVTRON_RESOURCE_SEARCHABLE_KEY_PIPELINE_ID]
104+
105+
for _, policy := range policyMappings {
106+
switch policy.IdentifierKey {
107+
case clusterIdentifierKey, envIdentifierKey:
108+
digestPolicyConfiguration.DigestConfiguredForEnvOrCluster = true
109+
case pipelineIdentifierKey:
110+
digestPolicyConfiguration.DigestConfiguredForPipeline = true
111+
}
112+
}
113+
114+
return digestPolicyConfiguration, nil
115+
}
116+
117+
func (impl ImageDigestPolicyServiceImpl) DeletePolicyForPipeline(tx *pg.Tx, pipelineId int, userId int32) (int, error) {
118+
auditLog := sql.AuditLog{
119+
CreatedOn: time.Now(),
120+
CreatedBy: userId,
121+
UpdatedOn: time.Now(),
122+
UpdatedBy: userId,
123+
}
124+
devtronResourceSearchableKeyMap := impl.devtronResourceSearchableKey.GetAllSearchableKeyNameIdMap()
125+
err := impl.qualifierMappingService.DeleteByIdentifierKeyValue(resourceQualifiers.ImageDigest, devtronResourceSearchableKeyMap[bean.DEVTRON_RESOURCE_SEARCHABLE_KEY_PIPELINE_ID], pipelineId, auditLog, tx)
126+
if err != nil {
127+
impl.logger.Errorw("error in deleting image digest policy for pipeline", "err", err, "pipelineId", pipelineId)
128+
return pipelineId, err
129+
}
130+
return pipelineId, nil
131+
}

0 commit comments

Comments
 (0)