diff --git a/go.mod b/go.mod index 04e826aca8..4570029193 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/davecgh/go-spew v1.1.1 github.com/deckarep/golang-set v1.8.0 github.com/devtron-labs/authenticator v0.4.35-0.20240405091826-a91813c53470 - github.com/devtron-labs/common-lib v0.0.16-0.20240503082245-7ab933f8381f + github.com/devtron-labs/common-lib v0.0.18-0.20240520084257-237319ab2bed github.com/devtron-labs/protos v0.0.3-0.20240326053929-48e42d9d4534 github.com/evanphx/json-patch v5.6.0+incompatible github.com/gammazero/workerpool v1.1.3 @@ -34,7 +34,7 @@ require ( github.com/google/go-cmp v0.6.0 github.com/google/go-github v17.0.0+incompatible github.com/google/uuid v1.3.1 - github.com/google/wire v0.5.0 + github.com/google/wire v0.6.0 github.com/gorilla/mux v1.8.0 github.com/gorilla/schema v1.1.0 github.com/gorilla/sessions v1.2.1 diff --git a/go.sum b/go.sum index 7b1545b64c..2cfb8a5ced 100644 --- a/go.sum +++ b/go.sum @@ -207,8 +207,8 @@ github.com/denisenkom/go-mssqldb v0.0.0-20190707035753-2be1aa521ff4 h1:YcpmyvADG github.com/denisenkom/go-mssqldb v0.0.0-20190707035753-2be1aa521ff4/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM= github.com/devtron-labs/authenticator v0.4.35-0.20240405091826-a91813c53470 h1:AUTYcDnL6w6Ux+264VldYaOUQAP6pDZ5Tq8wCKJyiEg= github.com/devtron-labs/authenticator v0.4.35-0.20240405091826-a91813c53470/go.mod h1:JQxTCMmQisrpjzETJr0tzVadV+wW23rHEZAY7JVyK3s= -github.com/devtron-labs/common-lib v0.0.16-0.20240503082245-7ab933f8381f h1:DcnCVtWaqwL6rptUD2eMaSwQEIL4/VaRWBfjyJbXy4U= -github.com/devtron-labs/common-lib v0.0.16-0.20240503082245-7ab933f8381f/go.mod h1:mzEk3pf4JDXsOPNvCxjoSnsMBTwmt4A73Qc2tobLkZM= +github.com/devtron-labs/common-lib v0.0.18-0.20240520084257-237319ab2bed h1:Jt9dHdE+sYoH1N2v3Se9Tgnr/7YrpCKYmB+nDcI73B4= +github.com/devtron-labs/common-lib v0.0.18-0.20240520084257-237319ab2bed/go.mod h1:deAcJ5IjUjM6ozZQLJEgPWDUA0mKa632LBsKx8uM9TE= github.com/devtron-labs/protos v0.0.3-0.20240326053929-48e42d9d4534 h1:TElPRU69QedW7DIQiiQxtjwSQ6cK0fCTAMGvSLhP0ac= github.com/devtron-labs/protos v0.0.3-0.20240326053929-48e42d9d4534/go.mod h1:ypUknVph8Ph4dxSlrFoouf7wLedQxHku2LQwgRrdgS4= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= @@ -423,14 +423,14 @@ github.com/google/s2a-go v0.1.4 h1:1kZ/sQM3srePvKs3tXAvQzo66XfcReoqFpIpIccE7Oc= github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= -github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= +github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/wire v0.5.0 h1:I7ELFeVBr3yfPIcc8+MWvrjk+3VjbcSzoXm3JVa+jD8= -github.com/google/wire v0.5.0/go.mod h1:ngWDr9Qvq3yZA10YrxfyGELY/AFWGVpy9c1LTRi1EoU= +github.com/google/wire v0.6.0 h1:HBkoIh4BdSxoyo9PveV8giw7ZsaBOvzWKfcg/6MrVwI= +github.com/google/wire v0.6.0/go.mod h1:F4QhpQ9EDIdJ1Mbop/NZBRB+5yrR6qg3BnctaoUk6NA= github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k= github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= @@ -921,6 +921,8 @@ golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58 golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -961,6 +963,8 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91 golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8= golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180406214816-61147c48b25b/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1021,6 +1025,8 @@ golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ= +golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1045,6 +1051,7 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1115,6 +1122,8 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1127,6 +1136,8 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo= +golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1145,6 +1156,7 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1160,7 +1172,6 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190422233926-fe54fb35175b/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= @@ -1209,6 +1220,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ= golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/pkg/argoApplication/ArgoApplicationService.go b/pkg/argoApplication/ArgoApplicationService.go index f0afbf0d3d..ebf61f9906 100644 --- a/pkg/argoApplication/ArgoApplicationService.go +++ b/pkg/argoApplication/ArgoApplicationService.go @@ -56,7 +56,7 @@ func (impl *ArgoApplicationServiceImpl) ListApplications(clusterIds []int) ([]*b var clusters []clusterRepository.Cluster var err error if len(clusterIds) > 0 { - //getting cluster details by ids + // getting cluster details by ids clusters, err = impl.clusterRepository.FindByIds(clusterIds) if err != nil { impl.logger.Errorw("error in getting clusters by ids", "err", err, "clusterIds", clusterIds) @@ -70,7 +70,7 @@ func (impl *ArgoApplicationServiceImpl) ListApplications(clusterIds []int) ([]*b } } - //TODO: make goroutine and channel for optimization + // TODO: make goroutine and channel for optimization appListFinal := make([]*bean.ArgoApplicationListDto, 0) for _, cluster := range clusters { clusterObj := cluster @@ -84,11 +84,11 @@ func (impl *ArgoApplicationServiceImpl) ListApplications(clusterIds []int) ([]*b impl.logger.Errorw("error in getting rest config by cluster Id", "err", err, "clusterId", clusterObj.Id) return nil, err } - resp, _, err := impl.k8sUtil.GetResourceList(context.Background(), restConfig, bean.GvkForArgoApplication, bean.AllNamespaces) + resp, _, err := impl.k8sUtil.GetResourceList(context.Background(), restConfig, bean.GvkForArgoApplication, bean.AllNamespaces, true, nil) if err != nil { if errStatus, ok := err.(*errors.StatusError); ok { if errStatus.Status().Code == 404 { - //no argo apps found, not sending error + // no argo apps found, not sending error impl.logger.Warnw("error in getting external argo app list, no apps found", "err", err, "clusterId", clusterObj.Id) continue } @@ -158,7 +158,7 @@ func (impl *ArgoApplicationServiceImpl) GetAppDetail(resourceName, resourceNames } var configOfClusterWhereAppIsDeployed bean.ArgoClusterConfigObj if appDeployedOnClusterId < 1 { - //cluster is not added on devtron, need to get server config from secret which argo-cd saved + // cluster is not added on devtron, need to get server config from secret which argo-cd saved coreV1Client, err := impl.k8sUtil.GetCoreV1ClientByRestConfig(restConfig) secrets, err := coreV1Client.Secrets(bean.AllNamespaces).List(context.Background(), v1.ListOptions{ LabelSelector: labels.SelectorFromSet(labels.Set{"argocd.argoproj.io/secret-type": "cluster"}).String(), @@ -226,7 +226,7 @@ func (impl *ArgoApplicationServiceImpl) getResourceTreeForExternalCluster(cluste func getApplicationListDtos(manifestObj map[string]interface{}, clusterName string, clusterId int) []*bean.ArgoApplicationListDto { appLists := make([]*bean.ArgoApplicationListDto, 0) - //map of keys and index in row cells, initially set as 0 will be updated by object + // map of keys and index in row cells, initially set as 0 will be updated by object keysToBeFetchedFromColumnDefinitions := map[string]int{k8sCommonBean.K8sResourceColumnDefinitionName: 0, k8sCommonBean.K8sResourceColumnDefinitionHealthStatus: 0, k8sCommonBean.K8sResourceColumnDefinitionSyncStatus: 0} keysToBeFetchedFromRawObject := []string{k8sCommonBean.K8sClusterResourceNamespaceKey} @@ -350,7 +350,7 @@ func (impl *ArgoApplicationServiceImpl) GetServerConfigIfClusterIsNotAddedOnDevt } var configOfClusterWhereAppIsDeployed *bean.ArgoClusterConfigObj if appDeployedOnClusterId < 1 { - //cluster is not added on devtron, need to get server config from secret which argo-cd saved + // cluster is not added on devtron, need to get server config from secret which argo-cd saved coreV1Client, err := impl.k8sUtil.GetCoreV1ClientByRestConfig(restConfig) secrets, err := coreV1Client.Secrets(bean.AllNamespaces).List(context.Background(), v1.ListOptions{ LabelSelector: labels.SelectorFromSet(labels.Set{"argocd.argoproj.io/secret-type": "cluster"}).String(), diff --git a/pkg/k8s/application/k8sApplicationService.go b/pkg/k8s/application/k8sApplicationService.go index 8b9d092223..2f57c29e36 100644 --- a/pkg/k8s/application/k8sApplicationService.go +++ b/pkg/k8s/application/k8sApplicationService.go @@ -456,21 +456,21 @@ func (impl *K8sApplicationServiceImpl) validateContainerNameIfReqd(valid bool, r for _, pod := range app.ResourceTreeResponse.PodMetadata { if pod.Name == podName { - //finding the container name in main Containers + // finding the container name in main Containers for _, container := range pod.Containers { if container == requestContainerName { return true } } - //finding the container name in init containers + // finding the container name in init containers for _, initContainer := range pod.InitContainers { if initContainer == requestContainerName { return true } } - //finding the container name in ephemeral containers + // finding the container name in ephemeral containers for _, ephemeralContainer := range pod.EphemeralContainers { if ephemeralContainer.Name == requestContainerName { return true @@ -627,9 +627,9 @@ func (impl *K8sApplicationServiceImpl) GetResourceList(ctx context.Context, toke return resourceList, err } k8sRequest := request.K8sRequest - //store the copy of requested resource identifier + // store the copy of requested resource identifier resourceIdentifierCloned := k8sRequest.ResourceIdentifier - resp, namespaced, err := impl.K8sUtil.GetResourceList(ctx, restConfig, resourceIdentifierCloned.GroupVersionKind, resourceIdentifierCloned.Namespace) + resp, namespaced, err := impl.K8sUtil.GetResourceList(ctx, restConfig, resourceIdentifierCloned.GroupVersionKind, resourceIdentifierCloned.Namespace, true, nil) if err != nil { impl.logger.Errorw("error in getting resource list", "err", err, "request", request) return resourceList, err @@ -644,7 +644,7 @@ func (impl *K8sApplicationServiceImpl) GetResourceList(ctx context.Context, toke k8sRequest.ResourceIdentifier = resourceIdentifier return validateResourceAccess(token, clusterBean.ClusterName, *request, casbin.ActionGet) } - resourceList, err = impl.K8sUtil.BuildK8sObjectListTableData(&resp.Resources, namespaced, request.K8sRequest.ResourceIdentifier.GroupVersionKind, checkForResourceCallback) + resourceList, err = impl.K8sUtil.BuildK8sObjectListTableData(&resp.Resources, namespaced, request.K8sRequest.ResourceIdentifier.GroupVersionKind, false, checkForResourceCallback) if err != nil { impl.logger.Errorw("error on parsing for k8s resource", "err", err) return resourceList, err @@ -652,7 +652,7 @@ func (impl *K8sApplicationServiceImpl) GetResourceList(ctx context.Context, toke k8sServerVersion, err := impl.k8sCommonService.GetK8sServerVersion(clusterId) if err != nil { impl.logger.Errorw("error in getting k8s server version", "clusterId", clusterId, "err", err) - //return nil, err + // return nil, err } else { resourceList.ServerVersion = k8sServerVersion.String() } @@ -666,7 +666,7 @@ func (impl *K8sApplicationServiceImpl) ApplyResources(ctx context.Context, token return nil, err } - //getting rest config by clusterId + // getting rest config by clusterId clusterId := request.ClusterId restConfig, err, clusterBean := impl.k8sCommonService.GetRestConfigByClusterId(ctx, clusterId) if err != nil { @@ -830,7 +830,7 @@ func (impl *K8sApplicationServiceImpl) CreatePodEphemeralContainers(req *cluster impl.logger.Errorw("error occured while trying to create epehemral containers with legacy API", "err", err) return fmt.Errorf("error creating JSON 6902 patch for old /ephemeralcontainers API: %s", err) } - //try with legacy API + // try with legacy API result := v1Client.RESTClient().Patch(types.JSONPatchType). Namespace(pod.Namespace). Resource("pods"). @@ -963,7 +963,7 @@ func (impl *K8sApplicationServiceImpl) GetPodContainersList(clusterId int, names } ephemeralContainerStatusMap := make(map[string]bool) for _, c := range pod.Status.EphemeralContainerStatuses { - //c.state contains three states running,waiting and terminated + // c.state contains three states running,waiting and terminated // at any point of time only one state will be there if c.State.Running != nil { ephemeralContainerStatusMap[c.Name] = true @@ -1027,7 +1027,7 @@ func (impl *K8sApplicationServiceImpl) RecreateResource(ctx context.Context, req return nil, fmt.Errorf("no manifest found for this request") } - //getting rest config by clusterId + // getting rest config by clusterId restConfig, err, _ := impl.k8sCommonService.GetRestConfigByClusterId(ctx, request.AppIdentifier.ClusterId) if err != nil { impl.logger.Errorw("error in getting rest config by cluster Id", "err", err, "clusterId", request.AppIdentifier.ClusterId) @@ -1150,8 +1150,8 @@ func (impl K8sApplicationServiceImpl) K8sServerVersionCheckForEphemeralContainer return false, err } - //ephemeral containers feature is introduced in version v1.23 of kubernetes, it is stable from version v1.25 - //https://kubernetes.io/docs/concepts/workloads/pods/ephemeral-containers/ + // ephemeral containers feature is introduced in version v1.23 of kubernetes, it is stable from version v1.25 + // https://kubernetes.io/docs/concepts/workloads/pods/ephemeral-containers/ ephemeralRegex := impl.ephemeralContainerConfig.EphemeralServerVersionRegex matched, err := util2.MatchRegexExpression(ephemeralRegex, k8sServerVersion.String()) if err != nil { diff --git a/scripts/sql/248_auto_remediation.down.sql b/scripts/sql/248_auto_remediation.down.sql new file mode 100644 index 0000000000..d08409bb00 --- /dev/null +++ b/scripts/sql/248_auto_remediation.down.sql @@ -0,0 +1,41 @@ +-- Drop indexes +DROP INDEX IF EXISTS idx_unique_k8s_event_watcher_name; + +-- Drop foreign key constraints +ALTER TABLE "public"."intercepted_event_execution" DROP CONSTRAINT IF EXISTS intercepted_events_auto_remediation_trigger_id_fkey; +ALTER TABLE "public"."intercepted_event_execution" DROP CONSTRAINT IF EXISTS intercepted_events_cluster_id_fkey; +ALTER TABLE "public"."auto_remediation_trigger" DROP CONSTRAINT IF EXISTS auto_remediation_trigger_k8s_event_watcher_id_fkey; + +-- Drop tables +DROP TABLE IF EXISTS "public"."intercepted_event_execution"; +DROP TABLE IF EXISTS "public"."auto_remediation_trigger"; +DROP TABLE IF EXISTS "public"."k8s_event_watcher"; + +-- Drop sequences +DROP SEQUENCE IF EXISTS id_seq_intercepted_events; +DROP SEQUENCE IF EXISTS id_seq_auto_remediation_trigger; +DROP SEQUENCE IF EXISTS id_seq_k8s_event_watcher; + + +-- PLUGIN DOWN SCRIPT + + +DELETE FROM plugin_step_variable WHERE plugin_step_id =(SELECT ps.id FROM plugin_metadata p inner JOIN plugin_step ps on ps.plugin_id=p.id WHERE p.name='Custom Email Notifier v1.0.0' and ps."index"=1 and ps.deleted=false); +DELETE FROM plugin_step WHERE plugin_id=(SELECT id FROM plugin_metadata WHERE name='Custom Email Notifier v1.0.0'); +DELETE FROM plugin_stage_mapping WHERE plugin_id =(SELECT id FROM plugin_metadata WHERE name='Custom Email Notifier v1.0.0'); +DELETE FROM pipeline_stage_step_variable WHERE pipeline_stage_step_id in (SELECT id FROM pipeline_stage_step where ref_plugin_id =(SELECT id from plugin_metadata WHERE name ='Custom Email Notifier v1.0.0')); +DELETE FROM pipeline_stage_step where ref_plugin_id in (SELECT id from plugin_metadata WHERE name ='Custom Email Notifier v1.0.0'); +DELETE FROM plugin_metadata WHERE name ='Custom Email Notifier v1.0.0'; + + +DELETE FROM plugin_step_variable WHERE plugin_step_id =(SELECT ps.id FROM plugin_metadata p inner JOIN plugin_step ps on ps.plugin_id=p.id WHERE p.name='Custom Webhook Notifier v1.0.0' and ps."index"=1 and ps.deleted=false); +DELETE FROM plugin_step WHERE plugin_id=(SELECT id FROM plugin_metadata WHERE name='Custom Webhook Notifier v1.0.0'); +DELETE FROM plugin_stage_mapping WHERE plugin_id =(SELECT id FROM plugin_metadata WHERE name='Custom Webhook Notifier v1.0.0'); +DELETE FROM pipeline_stage_step_variable WHERE pipeline_stage_step_id in (SELECT id FROM pipeline_stage_step where ref_plugin_id =(SELECT id from plugin_metadata WHERE name ='Custom Webhook Notifier v1.0.0')); +DELETE FROM pipeline_stage_step where ref_plugin_id in (SELECT id from plugin_metadata WHERE name ='Custom Webhook Notifier v1.0.0'); +DELETE FROM plugin_metadata WHERE name ='Custom Webhook Notifier v1.0.0'; + +-- DELETE EVENTs +DELETE FROM event WHERE id = 9; +DELETE FROM notification_templates WHERE event_type_id = 9; + diff --git a/scripts/sql/248_auto_remediation.up.sql b/scripts/sql/248_auto_remediation.up.sql new file mode 100644 index 0000000000..d8d033f114 --- /dev/null +++ b/scripts/sql/248_auto_remediation.up.sql @@ -0,0 +1,195 @@ +CREATE SEQUENCE IF NOT EXISTS id_seq_k8s_event_watcher; +CREATE TABLE "public"."k8s_event_watcher" ( + "id" integer NOT NULL default nextval('id_seq_k8s_event_watcher'::regclass), + "name" varchar(50) NOT NULL, + "description" text , + "filter_expression" text NOT NULL, + "gvks" text, + "selected_actions" varchar(15)[], + "selectors" text, + "active" bool NOT NULL, + "created_on" timestamptz NOT NULL, + "created_by" int4 NOT NULL, + "updated_on" timestamptz, + "updated_by" int4, + + PRIMARY KEY ("id") + +); + +CREATE UNIQUE INDEX "idx_unique_k8s_event_watcher_name" + ON k8s_event_watcher(name) + WHERE k8s_event_watcher.active =true; + +CREATE SEQUENCE IF NOT EXISTS id_seq_auto_remediation_trigger; +CREATE TABLE "public"."auto_remediation_trigger"( + "id" integer NOT NULL default nextval('id_seq_auto_remediation_trigger'::regclass), + "type" varchar(50) , -- DEVTRON_JOB + "watcher_id" integer , + "data" text, + "active" bool NOT NULL, + "created_on" timestamptz NOT NULL, + "created_by" int4 NOT NULL, + "updated_on" timestamptz, + "updated_by" int4, + + CONSTRAINT auto_remediation_trigger_k8s_event_watcher_id_fkey FOREIGN KEY ("watcher_id") REFERENCES "public"."k8s_event_watcher" ("id"), + PRIMARY KEY ("id") + +); + +CREATE SEQUENCE IF NOT EXISTS id_seq_intercepted_event_execution; +CREATE TABLE "public"."intercepted_event_execution"( + "id" integer NOT NULL default nextval('id_seq_intercepted_event_execution'::regclass), + "cluster_id" int , + "namespace" character varying(250) NOT NULL, + "metadata" text, + "search_data" text, + "execution_message" text, + "action" varchar(20), + "involved_objects" text, + "intercepted_at" timestamptz, + "status" varchar(32) , -- failure,success,inprogress + "trigger_id" integer, + "trigger_execution_id" integer, + "created_on" timestamptz NOT NULL, + "created_by" int4 NOT NULL, + "updated_on" timestamptz, + "updated_by" int4, + + CONSTRAINT intercepted_events_auto_remediation_trigger_id_fkey FOREIGN KEY ("trigger_id") REFERENCES "public"."auto_remediation_trigger" ("id"), + CONSTRAINT intercepted_events_cluster_id_fkey FOREIGN KEY ("cluster_id") REFERENCES "public"."cluster" ("id"), + PRIMARY KEY ("id") +); + + +-- PLUGIN SCRIPT + +-- Insert Plugin Metadata +INSERT INTO "plugin_metadata" ("id", "name", "description", "type", "icon", "deleted", "created_on", "created_by", "updated_on", "updated_by") +VALUES (nextval('id_seq_plugin_metadata'), 'Custom Email Notifier v1.0.0', 'Send email notifications', 'PRESET', 'https://t4.ftcdn.net/jpg/04/76/40/09/240_F_476400965_iYkCpMeqvQwaICySZBgyP5IErlyAgeZu.jpg', 'f', 'now()', 1, 'now()', 1); + +-- Insert Plugin Stage Mapping +INSERT INTO "plugin_stage_mapping" ("plugin_id", "stage_type", "created_on", "created_by", "updated_on", "updated_by") +VALUES ((SELECT id FROM plugin_metadata WHERE name = 'Custom Email Notifier v1.0.0'), 0, 'now()', 1, 'now()', 1); + +-- Insert Plugin Script +INSERT INTO "plugin_pipeline_script" ("id", "script", "type", "deleted", "created_on", "created_by", "updated_on", "updated_by") +VALUES ( + nextval('id_seq_plugin_pipeline_script'), + E'#!/bin/sh + + # URL and token from environment variables + echo "------------STARTING PLUGIN CUSTOM EMAIL NOTIFIER------------" + # Make the API call + STRINGIFIED_JSON=$(echo "$NOTIFICATION_DATA" | jq -c .) +# Replace backslashes with escaped backslashes and double quotes with escaped double quotes +ESCAPED_JSON="${STRINGIFIED_JSON//\\\\/\\\\\\\\}" # Replace backslashes +ESCAPED_JSON="${ESCAPED_JSON//\\"/\\\\\\"}" # Replace double quotes + curl -X POST ${NOTIFICATION_URL} -H "token: ${NOTIFICATION_TOKEN}" -H "Content-Type: application/json" -d ''{"configType": "\'${CONFIG_TYPE}\'","configName":"\'${CONFIG_NAME}\'","emailIds":"\'${EMAIL_IDS}\'","data":"\'${ESCAPED_JSON}\'"}'' + echo "------------FINISHING PLUGIN CUSTOM EMAIL NOTIFIER------------" + ', + 'SHELL', + 'f', + 'now()', + 1, + 'now()', + 1 + ); + +-- Insert Plugin Step +INSERT INTO "plugin_step" ("id", "plugin_id", "name", "description", "index", "step_type", "script_id", "deleted", "created_on", "created_by", "updated_on", "updated_by") +VALUES ( + nextval('id_seq_plugin_step'), + (SELECT id FROM plugin_metadata WHERE name = 'Custom Email Notifier v1.0.0'), + 'Step 1', + 'Custom email notifier', + 1, + 'INLINE', + (SELECT last_value FROM id_seq_plugin_pipeline_script), + 'f', + 'now()', + 1, + 'now()', + 1 + ); + +-- Insert Plugin Step Variables +INSERT INTO plugin_step_variable (id,plugin_step_id,name,format, description,is_exposed,allow_empty_value,default_value,value,variable_type,value_type,previous_step_index,variable_step_index,variable_step_index_in_plugin,reference_variable_name,deleted,created_on,created_by,updated_on,updated_by)VALUES + (nextval('id_seq_plugin_step_variable'),(SELECT ps.id FROM plugin_metadata p inner JOIN plugin_step ps on ps.plugin_id=p.id WHERE p.name='Custom Email Notifier v1.0.0' and ps."index"=1 and ps.deleted=false),'CONFIG_TYPE','STRING','Type of the configuration','t','f',null,null,'INPUT','NEW',null,1,null,null,'f','now()',1,'now()',1), + (nextval('id_seq_plugin_step_variable'),(SELECT ps.id FROM plugin_metadata p inner JOIN plugin_step ps on ps.plugin_id=p.id WHERE p.name='Custom Email Notifier v1.0.0' and ps."index"=1 and ps.deleted=false),'CONFIG_NAME','STRING','Name of the configuration','t','f',null,null,'INPUT','NEW',null,1,null,null,'f','now()',1,'now()',1), + (nextval('id_seq_plugin_step_variable'),(SELECT ps.id FROM plugin_metadata p inner JOIN plugin_step ps on ps.plugin_id=p.id WHERE p.name='Custom Email Notifier v1.0.0' and ps."index"=1 and ps.deleted=false),'EMAIL_IDS','STRING','Email IDs to notify','t','t',null,null,'INPUT','NEW',null,1,null,null,'f','now()',1,'now()',1); + + +-- Insert Plugin Metadata +INSERT INTO "plugin_metadata" ("id", "name", "description", "type", "icon", "deleted", "created_on", "created_by", "updated_on", "updated_by") +VALUES (nextval('id_seq_plugin_metadata'), 'Custom Webhook Notifier v1.0.0', 'Send webhook notifications', 'PRESET', 'https://seeklogo.com/images/W/webhooks-logo-04229CC4AE-seeklogo.com.png', 'f', 'now()', 1, 'now()', 1); + +-- Insert Plugin Stage Mapping +INSERT INTO "plugin_stage_mapping" ("plugin_id", "stage_type", "created_on", "created_by", "updated_on", "updated_by") +VALUES ((SELECT id FROM plugin_metadata WHERE name = 'Custom Webhook Notifier v1.0.0'), 0, 'now()', 1, 'now()', 1); + +-- Insert Plugin Script +INSERT INTO "plugin_pipeline_script" ("id", "script", "type", "deleted", "created_on", "created_by", "updated_on", "updated_by") +VALUES ( + nextval('id_seq_plugin_pipeline_script'), + E'#!/bin/sh + + # URL and token from environment variables + echo "------------STARTING PLUGIN CUSTOM WEBHOOK NOTIFIER------------" + # Make the API call + STRINGIFIED_JSON=$(echo "$NOTIFICATION_DATA" | jq -c .) + # Replace backslashes with escaped backslashes and double quotes with escaped double quotes + ESCAPED_JSON="${STRINGIFIED_JSON//\\\\/\\\\\\\\}" # Replace backslashes + ESCAPED_JSON="${ESCAPED_JSON//\\"/\\\\\\"}" # Replace double quotes + curl -X POST ${NOTIFICATION_URL} -H "token: $NOTIFICATION_TOKEN" -H "Content-Type: application/json" -d ''{"configType": "\'${CONFIG_TYPE}\'","configName":"\'${CONFIG_NAME}\'","data":"\'${ESCAPED_JSON}\'"}'' + echo "------------FINISHING PLUGIN CUSTOM WEBHOOK NOTIFIER------------" + ', + 'SHELL', + 'f', + 'now()', + 1, + 'now()', + 1 + ); + +-- Insert Plugin Step +INSERT INTO "plugin_step" ("id", "plugin_id", "name", "description", "index", "step_type", "script_id", "deleted", "created_on", "created_by", "updated_on", "updated_by") +VALUES ( + nextval('id_seq_plugin_step'), + (SELECT id FROM plugin_metadata WHERE name = 'Custom Webhook Notifier v1.0.0'), + 'Step 1', + 'Custom webhook notifier', + 1, + 'INLINE', + (SELECT last_value FROM id_seq_plugin_pipeline_script), + 'f', + 'now()', + 1, + 'now()', + 1 + ); + +-- Insert Plugin Step Variables +INSERT INTO plugin_step_variable (id,plugin_step_id,name,format, description,is_exposed,allow_empty_value,default_value,value,variable_type,value_type,previous_step_index,variable_step_index,variable_step_index_in_plugin,reference_variable_name,deleted,created_on,created_by,updated_on,updated_by)VALUES + (nextval('id_seq_plugin_step_variable'),(SELECT ps.id FROM plugin_metadata p inner JOIN plugin_step ps on ps.plugin_id=p.id WHERE p.name='Custom Webhook Notifier v1.0.0' and ps."index"=1 and ps.deleted=false),'CONFIG_TYPE','STRING','Type of the configuration','t','f',null,null,'INPUT','NEW',null,1,null,null,'f','now()',1,'now()',1), + (nextval('id_seq_plugin_step_variable'),(SELECT ps.id FROM plugin_metadata p inner JOIN plugin_step ps on ps.plugin_id=p.id WHERE p.name='Custom Webhook Notifier v1.0.0' and ps."index"=1 and ps.deleted=false),'CONFIG_NAME','STRING','Name of the configuration','t','f',null,null,'INPUT','NEW',null,1,null,null,'f','now()',1,'now()',1); + + +-- insert notification templates +INSERT INTO public.event (id, event_type, description) VALUES (9, 'SCOOP RESOURCE INTERCEPT EVENT', ''); + INSERT INTO "public"."notification_templates" (channel_type, node_type, event_type_id, template_name, template_payload) +VALUES ('ses', 'CD', 9, 'scoop event ses template', '{ + "from": "{{fromEmail}}", + "to": "{{toEmail}}", + "subject": "🛎️ Change in resource intercepted | Resource {{action}} | Resource: {{kind}}/{{resourceName}}", + "html": "\n \n \n \n \n \n\n \n\t \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n
\n
\n \"ci-triggered\"\n
\n
\n
\n
\n
{{heading}}
\n {{kind}}/{{resourceName}}\n
\n {{interceptedAt}}\n
\n\t\t\t\t\n\t\t\t\t
\n \n
\n
\n \n
\n\t\t\t
\n View resource manifest\n\t\t\t\t
\n \n
\n
\n
\n
Details\n
\n
\n
Cluster
\n
\n
Namespace
\n
\n
{{clusterName}}
\n
\n
{{namespace}}
\n
\n
\n
\n
Intercepted by watcher
\n
\n
{{watcherName}}\n
\n
\n
\n
Runbook (Job pipeline)
\n
\n
{{pipelineName}}\n
\n
\n
\n \n \n
\n \n
\n
\n
\n \n \n
\n \n
\n
\n
\n \n \n Blog\n \n \n \n \n Website\n \n \n
\n
\n © Devtron Labs 2020\n
\n
" +}'); + +INSERT INTO "public"."notification_templates" (channel_type, node_type, event_type_id, template_name, template_payload) +VALUES ('smtp', 'CD', 9, 'scoop event smtp template', '{ + "from": "{{fromEmail}}", + "to": "{{toEmail}}", + "subject": "🛎️ Change in resource intercepted | Resource {{action}} | Resource: {{kind}}/{{resourceName}}", + "html": "\n \n \n \n \n \n\n \n\t \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n
\n
\n \"ci-triggered\"\n
\n
\n
\n
\n
{{heading}}
\n {{kind}}/{{resourceName}}\n
\n {{interceptedAt}}\n
\n\t\t\t\t\n\t\t\t\t
\n \n
\n
\n \n
\n\t\t\t
\n View resource manifest\n\t\t\t\t
\n \n
\n
\n
\n
Details\n
\n
\n
Cluster
\n
\n
Namespace
\n
\n
{{clusterName}}
\n
\n
{{namespace}}
\n
\n
\n
\n
Intercepted by watcher
\n
\n
{{watcherName}}\n
\n
\n
\n
Runbook (Job pipeline)
\n
\n
{{pipelineName}}\n
\n
\n
\n \n \n
\n \n
\n
\n
\n \n \n
\n \n
\n
\n
\n \n \n Blog\n \n \n \n \n Website\n \n \n
\n
\n © Devtron Labs 2020\n
\n
" +}'); \ No newline at end of file diff --git a/vendor/github.com/devtron-labs/common-lib/constants/constants.go b/vendor/github.com/devtron-labs/common-lib/constants/constants.go index a7e41944da..6ea4e161dc 100644 --- a/vendor/github.com/devtron-labs/common-lib/constants/constants.go +++ b/vendor/github.com/devtron-labs/common-lib/constants/constants.go @@ -1,3 +1,25 @@ package constants const PanicLogIdentifier = "DEVTRON_PANIC_RECOVER" + +// metrics name constants + +const ( + NATS_PUBLISH_COUNT = "Nats_Publish_Count" + NATS_CONSUMPTION_COUNT = "Nats_Consumption_Count" + NATS_CONSUMING_COUNT = "Nats_Consuming_Count" + NATS_EVENT_CONSUMPTION_TIME = "Nats_Event_Consumption_Time" + NATS_EVENT_PUBLISH_TIME = "Nats_Event_Publish_Time" + NATS_EVENT_DELIVERY_COUNT = "Nats_Event_Delivery_Count" + PANIC_RECOVERY_COUNT = "Panic_Recovery_Count" +) + +// metrcis lables constant +const ( + PANIC_TYPE = "panicType" + HOST = "host" + METHOD = "method" + PATH = "path" + TOPIC = "topic" + STATUS = "status" +) diff --git a/vendor/github.com/devtron-labs/common-lib/middlewares/recovery.go b/vendor/github.com/devtron-labs/common-lib/middlewares/recovery.go index 6834f61727..804fbcb5b9 100644 --- a/vendor/github.com/devtron-labs/common-lib/middlewares/recovery.go +++ b/vendor/github.com/devtron-labs/common-lib/middlewares/recovery.go @@ -3,6 +3,7 @@ package middlewares import ( "encoding/json" "github.com/devtron-labs/common-lib/constants" + "github.com/devtron-labs/common-lib/pubsub-lib/metrics" "log" "net/http" "runtime/debug" @@ -14,6 +15,7 @@ func Recovery(next http.Handler) http.Handler { defer func() { err := recover() if err != nil { + metrics.IncPanicRecoveryCount("handler", r.Host, r.Method, r.RequestURI) log.Print(constants.PanicLogIdentifier, "recovered from panic", "err", err, "stack", string(debug.Stack())) jsonBody, _ := json.Marshal(map[string]string{ "error": "internal server error", diff --git a/vendor/github.com/devtron-labs/common-lib/pubsub-lib/JetStreamUtil.go b/vendor/github.com/devtron-labs/common-lib/pubsub-lib/JetStreamUtil.go index 711316cba1..93af19e669 100644 --- a/vendor/github.com/devtron-labs/common-lib/pubsub-lib/JetStreamUtil.go +++ b/vendor/github.com/devtron-labs/common-lib/pubsub-lib/JetStreamUtil.go @@ -101,6 +101,9 @@ const ( CD_PIPELINE_DELETE_EVENT_TOPIC string = "CD-PIPELINE-DELETE-EVENT" CD_PIPELINE_DELETE_EVENT_GROUP string = "CD-PIPELINE-DELETE-EVENT-GROUP" CD_PIPELINE_DELETE_EVENT_DURABLE string = "CD-PIPELINE-DELETE-EVENT-DURABLE" + CHART_SCAN_TOPIC string = "CHART-SCAN-TOPIC" + CHART_SCAN_GROUP string = "CHART-SCAN-GROUP" + CHART_SCAN_DURABLE string = "CHART-SCAN-DURABLE" ) type NatsTopic struct { @@ -147,6 +150,7 @@ var natsTopicMapping = map[string]NatsTopic{ CD_STAGE_SUCCESS_EVENT_TOPIC: {topicName: CD_STAGE_SUCCESS_EVENT_TOPIC, streamName: ORCHESTRATOR_STREAM, queueName: CD_STAGE_SUCCESS_EVENT_GROUP, consumerName: CD_STAGE_SUCCESS_EVENT_DURABLE}, CD_PIPELINE_DELETE_EVENT_TOPIC: {topicName: CD_PIPELINE_DELETE_EVENT_TOPIC, streamName: ORCHESTRATOR_STREAM, queueName: CD_PIPELINE_DELETE_EVENT_GROUP, consumerName: CD_PIPELINE_DELETE_EVENT_DURABLE}, + CHART_SCAN_TOPIC: {topicName: CHART_SCAN_TOPIC, streamName: ORCHESTRATOR_STREAM, queueName: CHART_SCAN_GROUP, consumerName: CHART_SCAN_DURABLE}, } var NatsStreamWiseConfigMapping = map[string]NatsStreamConfig{ @@ -242,6 +246,7 @@ func ParseAndFillStreamWiseAndConsumerWiseConfigMaps() error { err = env.Parse(&defaultConfig) if err != nil { log.Print("error while parsing config from environment params", "err", err) + return err } // default stream and consumer config values diff --git a/vendor/github.com/devtron-labs/common-lib/pubsub-lib/PubSubClientService.go b/vendor/github.com/devtron-labs/common-lib/pubsub-lib/PubSubClientService.go index 88bb276984..e53d2aaef5 100644 --- a/vendor/github.com/devtron-labs/common-lib/pubsub-lib/PubSubClientService.go +++ b/vendor/github.com/devtron-labs/common-lib/pubsub-lib/PubSubClientService.go @@ -62,7 +62,9 @@ func NewPubSubClientServiceImpl(logger *zap.SugaredLogger) (*PubSubClientService func (impl PubSubClientServiceImpl) Publish(topic string, msg string) error { impl.Logger.Debugw("Published message on pubsub client", "topic", topic, "msg", msg) status := model.PUBLISH_FAILURE - defer metrics.IncPublishCount(topic, status) + defer func() { + metrics.IncPublishCount(topic, status) + }() natsClient := impl.NatsClient jetStrCtxt := natsClient.JetStrCtxt natsTopic := GetNatsTopic(topic) @@ -211,13 +213,14 @@ func (impl PubSubClientServiceImpl) TryCatchCallBack(msg *nats.Msg, callback fun // publish metrics for msg delivery count if msgDeliveryCount > 1 if msgDeliveryCount > 1 { - metrics.NatsEventDeliveryCount.WithLabelValues(msg.Subject, natsMsgId).Observe(float64(msgDeliveryCount)) + metrics.NatsEventDeliveryCount.WithLabelValues(msg.Subject).Observe(float64(msgDeliveryCount)) } // Panic recovery handling if panicInfo := recover(); panicInfo != nil { impl.Logger.Warnw(fmt.Sprintf("%s: found panic error", NATS_PANIC_MSG_LOG_PREFIX), "subject", msg.Subject, "payload", string(msg.Data), "logs", string(debug.Stack())) err = fmt.Errorf("%v\nPanic Logs:\n%s", panicInfo, string(debug.Stack())) + metrics.IncPanicRecoveryCount("nats", msg.Subject, "", "") // Publish the panic info to PANIC_ON_PROCESSING_TOPIC publishErr := impl.publishPanicError(msg, err) if publishErr != nil { diff --git a/vendor/github.com/devtron-labs/common-lib/pubsub-lib/metrics/metrics.go b/vendor/github.com/devtron-labs/common-lib/pubsub-lib/metrics/metrics.go index fd7c41e5a7..337217a1dc 100644 --- a/vendor/github.com/devtron-labs/common-lib/pubsub-lib/metrics/metrics.go +++ b/vendor/github.com/devtron-labs/common-lib/pubsub-lib/metrics/metrics.go @@ -1,36 +1,41 @@ package metrics import ( + "github.com/devtron-labs/common-lib/constants" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" ) var NatsPublishingCount = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "nats_publish_count", + Name: constants.NATS_PUBLISH_COUNT, Help: "count of successfully published events on nats", -}, []string{"topic", "status"}) +}, []string{constants.TOPIC, constants.STATUS}) var NatsConsumptionCount = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "nats_consumption_count", + Name: constants.NATS_CONSUMPTION_COUNT, Help: "count of consumed events on nats ", -}, []string{"topic"}) +}, []string{constants.TOPIC}) var NatsConsumingCount = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "nats_consuming_count", + Name: constants.NATS_CONSUMING_COUNT, Help: "count of nats events whose consumption is in progress", -}, []string{"topic"}) +}, []string{constants.TOPIC}) var NatsEventConsumptionTime = promauto.NewHistogramVec(prometheus.HistogramOpts{ - Name: "nats_event_consumption_time", -}, []string{"topic"}) + Name: constants.NATS_EVENT_CONSUMPTION_TIME, +}, []string{constants.TOPIC}) var NatsEventPublishTime = promauto.NewHistogramVec(prometheus.HistogramOpts{ - Name: "nats_event_publish_time", -}, []string{"topic"}) + Name: constants.NATS_EVENT_PUBLISH_TIME, +}, []string{constants.TOPIC}) var NatsEventDeliveryCount = promauto.NewHistogramVec(prometheus.HistogramOpts{ - Name: "nats_event_delivery_count", -}, []string{"topic", "msg_id"}) + Name: constants.NATS_EVENT_DELIVERY_COUNT, +}, []string{constants.TOPIC}) + +var PanicRecoveryCount = promauto.NewCounterVec(prometheus.CounterOpts{ + Name: constants.PANIC_RECOVERY_COUNT, +}, []string{constants.PANIC_TYPE, constants.HOST, constants.METHOD, constants.PATH}) func IncPublishCount(topic, status string) { NatsPublishingCount.WithLabelValues(topic, status).Inc() @@ -43,3 +48,6 @@ func IncConsumptionCount(topic string) { func IncConsumingCount(topic string) { NatsConsumingCount.WithLabelValues(topic).Inc() } +func IncPanicRecoveryCount(panicType, host, method, path string) { + PanicRecoveryCount.WithLabelValues(panicType, host, method, path).Inc() +} diff --git a/vendor/github.com/devtron-labs/common-lib/utils/CommonUtils.go b/vendor/github.com/devtron-labs/common-lib/utils/CommonUtils.go index a51f41bcdc..7aea2c4e15 100644 --- a/vendor/github.com/devtron-labs/common-lib/utils/CommonUtils.go +++ b/vendor/github.com/devtron-labs/common-lib/utils/CommonUtils.go @@ -17,6 +17,7 @@ limitations under the License. package utils import ( + "fmt" "math/rand" "strings" "time" @@ -34,3 +35,15 @@ func Generate(size int) string { str := b.String() return str } + +func hasScheme(url string) bool { + return len(url) >= 7 && (url[:7] == "http://" || url[:8] == "https://") +} + +func GetUrlWithScheme(url string) (urlWithScheme string) { + urlWithScheme = url + if !hasScheme(url) { + urlWithScheme = fmt.Sprintf("https://%s", url) + } + return urlWithScheme +} diff --git a/vendor/github.com/devtron-labs/common-lib/utils/k8s/K8sUtil.go b/vendor/github.com/devtron-labs/common-lib/utils/k8s/K8sUtil.go index 1900c5452a..ac06485384 100644 --- a/vendor/github.com/devtron-labs/common-lib/utils/k8s/K8sUtil.go +++ b/vendor/github.com/devtron-labs/common-lib/utils/k8s/K8sUtil.go @@ -85,7 +85,8 @@ type K8sService interface { GetCoreV1ClientInCluster() (*v12.CoreV1Client, error) GetKubeVersion() (*version.Info, error) ValidateResource(resourceObj map[string]interface{}, gvk schema.GroupVersionKind, validateCallback func(namespace string, group string, kind string, resourceName string) bool) bool - BuildK8sObjectListTableData(manifest *unstructured.UnstructuredList, namespaced bool, gvk schema.GroupVersionKind, validateResourceAccess func(namespace string, group string, kind string, resourceName string) bool) (*ClusterResourceListMap, error) + BuildK8sObjectListTableData(manifest *unstructured.UnstructuredList, namespaced bool, gvk schema.GroupVersionKind, includeMetadata bool, validateResourceAccess func(namespace string, group string, kind string, resourceName string) bool) (*ClusterResourceListMap, error) + ValidateForResource(namespace string, resourceRef interface{}, validateCallback func(namespace string, group string, kind string, resourceName string) bool) bool GetPodByName(namespace string, name string, client *v12.CoreV1Client) (*v1.Pod, error) GetK8sInClusterRestConfig() (*rest.Config, error) GetResourceInfoByLabelSelector(ctx context.Context, namespace string, labelSelector string) (*v1.Pod, error) @@ -128,8 +129,8 @@ type K8sService interface { GetApiResources(restConfig *rest.Config, includeOnlyVerb string) ([]*K8sApiResource, error) CreateResources(ctx context.Context, restConfig *rest.Config, manifest string, gvk schema.GroupVersionKind, namespace string) (*ManifestResponse, error) PatchResourceRequest(ctx context.Context, restConfig *rest.Config, pt types.PatchType, manifest string, name string, namespace string, gvk schema.GroupVersionKind) (*ManifestResponse, error) - GetResourceList(ctx context.Context, restConfig *rest.Config, gvk schema.GroupVersionKind, namespace string) (*ResourceListResponse, bool, error) - GetResourceIfWithAcceptHeader(restConfig *rest.Config, groupVersionKind schema.GroupVersionKind) (resourceIf dynamic.NamespaceableResourceInterface, namespaced bool, err error) + GetResourceList(ctx context.Context, restConfig *rest.Config, gvk schema.GroupVersionKind, namespace string, asTable bool, listOptions *metav1.ListOptions) (*ResourceListResponse, bool, error) + GetResourceIfWithAcceptHeader(restConfig *rest.Config, groupVersionKind schema.GroupVersionKind, asTable bool) (resourceIf dynamic.NamespaceableResourceInterface, namespaced bool, err error) GetPodLogs(ctx context.Context, restConfig *rest.Config, name string, namespace string, sinceTime *metav1.Time, tailLines int, sinceSeconds int, follow bool, containerName string, isPrevContainerLogsEnabled bool) (io.ReadCloser, error) ListEvents(restConfig *rest.Config, namespace string, groupVersionKind schema.GroupVersionKind, ctx context.Context, name string) (*v1.EventList, error) GetResourceIf(restConfig *rest.Config, groupVersionKind schema.GroupVersionKind) (resourceIf dynamic.NamespaceableResourceInterface, namespaced bool, err error) @@ -719,7 +720,7 @@ func (impl K8sServiceImpl) GetPodByName(namespace string, name string, client *v } } -func (impl K8sServiceImpl) BuildK8sObjectListTableData(manifest *unstructured.UnstructuredList, namespaced bool, gvk schema.GroupVersionKind, validateResourceAccess func(namespace string, group string, kind string, resourceName string) bool) (*ClusterResourceListMap, error) { +func (impl K8sServiceImpl) BuildK8sObjectListTableData(manifest *unstructured.UnstructuredList, namespaced bool, gvk schema.GroupVersionKind, includeMetadata bool, validateResourceAccess func(namespace string, group string, kind string, resourceName string) bool) (*ClusterResourceListMap, error) { clusterResourceListMap := &ClusterResourceListMap{} // build headers var headers []string @@ -798,6 +799,9 @@ func (impl K8sServiceImpl) BuildK8sObjectListTableData(manifest *unstructured.Un rowIndex[commonBean.K8sClusterResourceNamespaceKey] = namespace } } + if includeMetadata { + rowIndex[commonBean.K8sClusterResourceMetadataKey] = metadata + } } } allowed = impl.ValidateResource(cellObj, gvk, validateResourceAccess) @@ -834,7 +838,7 @@ func (impl K8sServiceImpl) ValidateResource(resourceObj map[string]interface{}, } if len(ownerReferences) > 0 { for _, ownerRef := range ownerReferences { - allowed := impl.validateForResource(namespace, ownerRef, validateCallback) + allowed := impl.ValidateForResource(namespace, ownerRef, validateCallback) if allowed { return allowed } @@ -844,7 +848,7 @@ func (impl K8sServiceImpl) ValidateResource(resourceObj map[string]interface{}, return validateCallback(namespace, groupName, resKind, resourceName) } -func (impl K8sServiceImpl) validateForResource(namespace string, resourceRef interface{}, validateCallback func(namespace string, group string, kind string, resourceName string) bool) bool { +func (impl K8sServiceImpl) ValidateForResource(namespace string, resourceRef interface{}, validateCallback func(namespace string, group string, kind string, resourceName string) bool) bool { resourceReference := resourceRef.(map[string]interface{}) resKind := resourceReference[commonBean.K8sClusterResourceKindKey].(string) apiVersion := resourceReference[commonBean.K8sClusterResourceApiVersionKey].(string) @@ -1243,7 +1247,7 @@ func (impl K8sServiceImpl) GetPodLogs(ctx context.Context, restConfig *rest.Conf } return stream, nil } -func (impl K8sServiceImpl) GetResourceIfWithAcceptHeader(restConfig *rest.Config, groupVersionKind schema.GroupVersionKind) (resourceIf dynamic.NamespaceableResourceInterface, namespaced bool, err error) { +func (impl K8sServiceImpl) GetResourceIfWithAcceptHeader(restConfig *rest.Config, groupVersionKind schema.GroupVersionKind, asTable bool) (resourceIf dynamic.NamespaceableResourceInterface, namespaced bool, err error) { httpClient, err := OverrideK8sHttpClientWithTracer(restConfig) if err != nil { impl.logger.Errorw("error in getting http client", "err", err) @@ -1261,12 +1265,14 @@ func (impl K8sServiceImpl) GetResourceIfWithAcceptHeader(restConfig *rest.Config } resource := groupVersionKind.GroupVersion().WithResource(apiResource.Name) wt := restConfig.WrapTransport // Reference: https://github.com/kubernetes/client-go/issues/407 - restConfig.WrapTransport = func(rt http.RoundTripper) http.RoundTripper { - if wt != nil { - rt = wt(rt) - } - return &http2.HeaderAdder{ - Rt: rt, + if asTable { + restConfig.WrapTransport = func(rt http.RoundTripper) http.RoundTripper { + if wt != nil { + rt = wt(rt) + } + return &http2.HeaderAdder{ + Rt: rt, + } } } httpClient, err = OverrideK8sHttpClientWithTracer(restConfig) @@ -1294,23 +1300,25 @@ func ServerResourceForGroupVersionKind(discoveryClient discovery.DiscoveryInterf } return nil, errors.NewNotFound(schema.GroupResource{Group: gvk.Group, Resource: gvk.Kind}, "") } -func (impl K8sServiceImpl) GetResourceList(ctx context.Context, restConfig *rest.Config, gvk schema.GroupVersionKind, namespace string) (*ResourceListResponse, bool, error) { - resourceIf, namespaced, err := impl.GetResourceIfWithAcceptHeader(restConfig, gvk) +func (impl K8sServiceImpl) GetResourceList(ctx context.Context, restConfig *rest.Config, gvk schema.GroupVersionKind, namespace string, asTable bool, listOptions *metav1.ListOptions) (*ResourceListResponse, bool, error) { + resourceIf, namespaced, err := impl.GetResourceIfWithAcceptHeader(restConfig, gvk, asTable) if err != nil { impl.logger.Errorw("error in getting dynamic interface for resource", "err", err, "namespace", namespace) return nil, namespaced, err } var resp *unstructured.UnstructuredList - listOptions := metav1.ListOptions{ - TypeMeta: metav1.TypeMeta{ - Kind: gvk.Kind, - APIVersion: gvk.GroupVersion().String(), - }, + if listOptions == nil { + listOptions = &metav1.ListOptions{ + TypeMeta: metav1.TypeMeta{ + Kind: gvk.Kind, + APIVersion: gvk.GroupVersion().String(), + }, + } } if len(namespace) > 0 && namespaced { - resp, err = resourceIf.Namespace(namespace).List(ctx, listOptions) + resp, err = resourceIf.Namespace(namespace).List(ctx, *listOptions) } else { - resp, err = resourceIf.List(ctx, listOptions) + resp, err = resourceIf.List(ctx, *listOptions) } if err != nil { impl.logger.Errorw("error in getting resource", "err", err, "namespace", namespace) diff --git a/vendor/github.com/devtron-labs/common-lib/utils/k8s/bean.go b/vendor/github.com/devtron-labs/common-lib/utils/k8s/bean.go index 75938f4ff7..0e5b8da2c7 100644 --- a/vendor/github.com/devtron-labs/common-lib/utils/k8s/bean.go +++ b/vendor/github.com/devtron-labs/common-lib/utils/k8s/bean.go @@ -3,6 +3,7 @@ package k8s import ( "fmt" "github.com/devtron-labs/common-lib/utils/k8sObjectsUtil" + "github.com/devtron-labs/common-lib/utils/remoteConnection/bean" v1 "k8s.io/api/core/v1" v12 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" @@ -35,13 +36,8 @@ type ClusterConfig struct { CertData string CAData string ClusterId int - ProxyUrl string ToConnectForClusterVerification bool - ToConnectWithSSHTunnel bool - SSHTunnelUser string - SSHTunnelPassword string - SSHTunnelAuthKey string - SSHTunnelServerAddress string + RemoteConnectionConfig *bean.RemoteConnectionConfigBean } type ClusterResourceListMap struct { diff --git a/vendor/github.com/devtron-labs/common-lib/utils/k8s/commonBean/bean.go b/vendor/github.com/devtron-labs/common-lib/utils/k8s/commonBean/bean.go index cea57955fa..a5ef4afc54 100644 --- a/vendor/github.com/devtron-labs/common-lib/utils/k8s/commonBean/bean.go +++ b/vendor/github.com/devtron-labs/common-lib/utils/k8s/commonBean/bean.go @@ -24,12 +24,34 @@ const ( NamespaceKind = "Namespace" HorizontalPodAutoscalerKind = "HorizontalPodAutoscaler" Spec = "spec" + Template = "template" + JobTemplate = "jobTemplate" Ports = "ports" Port = "port" Subsets = "subsets" Nodes = "nodes" + Containers = "containers" + InitContainers = "initContainers" + EphemeralContainers = "ephemeralContainers" + Image = "image" ) +var defaultContainerPath = []string{Spec, Template, Spec} +var cronJobContainerPath = []string{Spec, JobTemplate, Spec, Template, Spec} +var podContainerPath = []string{Spec} + +var kindToPath = map[string][]string{ + PodKind: podContainerPath, + K8sClusterResourceCronJobKind: cronJobContainerPath, +} + +func GetContainerSubPathForKind(kind string) []string { + if path, ok := kindToPath[kind]; ok { + return path + } + return defaultContainerPath +} + const ( PersistentVolumeClaimsResourceType = "persistentvolumeclaims" StatefulSetsResourceType = "statefulsets" diff --git a/vendor/github.com/devtron-labs/common-lib/utils/k8sObjectsUtil/DockerImageFinder.go b/vendor/github.com/devtron-labs/common-lib/utils/k8sObjectsUtil/DockerImageFinder.go new file mode 100644 index 0000000000..e4a858d51f --- /dev/null +++ b/vendor/github.com/devtron-labs/common-lib/utils/k8sObjectsUtil/DockerImageFinder.go @@ -0,0 +1,121 @@ +package k8sObjectsUtil + +import ( + k8sCommonBean "github.com/devtron-labs/common-lib/utils/k8s/commonBean" + appsV1 "k8s.io/api/apps/v1" + batchV1 "k8s.io/api/batch/v1" + coreV1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +func ExtractAllDockerImages(manifests []unstructured.Unstructured) ([]string, error) { + var dockerImages []string + for _, manifest := range manifests { + switch manifest.GroupVersionKind() { + case schema.GroupVersionKind{Group: "", Version: "v1", Kind: k8sCommonBean.PodKind}: + var pod coreV1.Pod + err := runtime.DefaultUnstructuredConverter.FromUnstructured(manifest.UnstructuredContent(), &pod) + if err != nil { + return nil, err + } + dockerImages = append(dockerImages, extractImagesFromPodTemplate(pod.Spec)...) + case schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: k8sCommonBean.DeploymentKind}: + var deployment appsV1.Deployment + err := runtime.DefaultUnstructuredConverter.FromUnstructured(manifest.UnstructuredContent(), &deployment) + if err != nil { + return nil, err + } + dockerImages = append(dockerImages, extractImagesFromPodTemplate(deployment.Spec.Template.Spec)...) + case schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: k8sCommonBean.ReplicaSetKind}: + var replicaSet appsV1.ReplicaSet + err := runtime.DefaultUnstructuredConverter.FromUnstructured(manifest.UnstructuredContent(), &replicaSet) + if err != nil { + return nil, err + } + dockerImages = append(dockerImages, extractImagesFromPodTemplate(replicaSet.Spec.Template.Spec)...) + case schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: k8sCommonBean.StatefulSetKind}: + var statefulSet appsV1.StatefulSet + err := runtime.DefaultUnstructuredConverter.FromUnstructured(manifest.UnstructuredContent(), &statefulSet) + if err != nil { + return nil, err + } + dockerImages = append(dockerImages, extractImagesFromPodTemplate(statefulSet.Spec.Template.Spec)...) + case schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: k8sCommonBean.DaemonSetKind}: + var daemonSet appsV1.DaemonSet + err := runtime.DefaultUnstructuredConverter.FromUnstructured(manifest.UnstructuredContent(), &daemonSet) + if err != nil { + return nil, err + } + dockerImages = append(dockerImages, extractImagesFromPodTemplate(daemonSet.Spec.Template.Spec)...) + case schema.GroupVersionKind{Group: "batch", Version: "v1", Kind: k8sCommonBean.JobKind}: + var job batchV1.Job + err := runtime.DefaultUnstructuredConverter.FromUnstructured(manifest.UnstructuredContent(), &job) + if err != nil { + return nil, err + } + dockerImages = append(dockerImages, extractImagesFromPodTemplate(job.Spec.Template.Spec)...) + case schema.GroupVersionKind{Group: "batch", Version: "v1", Kind: "CronJob"}: + var cronJob batchV1.CronJob + err := runtime.DefaultUnstructuredConverter.FromUnstructured(manifest.UnstructuredContent(), &cronJob) + if err != nil { + return nil, err + } + dockerImages = append(dockerImages, extractImagesFromPodTemplate(cronJob.Spec.JobTemplate.Spec.Template.Spec)...) + case schema.GroupVersionKind{Group: "", Version: "v1", Kind: "ReplicationController"}: + var replicationController coreV1.ReplicationController + err := runtime.DefaultUnstructuredConverter.FromUnstructured(manifest.UnstructuredContent(), &replicationController) + if err != nil { + return nil, err + } + dockerImages = append(dockerImages, extractImagesFromPodTemplate(replicationController.Spec.Template.Spec)...) + case schema.GroupVersionKind{Group: "argoproj.io", Version: "v1alpha1", Kind: "Rollout"}: + var rolloutSpec map[string]interface{} + err := runtime.DefaultUnstructuredConverter.FromUnstructured(manifest.UnstructuredContent(), &rolloutSpec) + if err != nil { + return nil, err + } + dockerImages = append(dockerImages, extractImagesFromRolloutTemplate(rolloutSpec)...) + } + } + + return dockerImages, nil +} + +func extractImagesFromPodTemplate(podSpec coreV1.PodSpec) []string { + var dockerImages []string + for _, container := range podSpec.Containers { + dockerImages = append(dockerImages, container.Image) + } + for _, initContainer := range podSpec.InitContainers { + dockerImages = append(dockerImages, initContainer.Image) + } + for _, ephContainer := range podSpec.EphemeralContainers { + dockerImages = append(dockerImages, ephContainer.Image) + } + + return dockerImages +} + +func extractImagesFromRolloutTemplate(rolloutSpec map[string]interface{}) []string { + var dockerImages []string + if rolloutSpec != nil && rolloutSpec["spec"] != nil { + spec := rolloutSpec["spec"].(map[string]interface{}) + if spec != nil && spec["template"] != nil { + template := spec["template"].(map[string]interface{}) + if template != nil && template["spec"] != nil { + templateSpec := template["spec"].(map[string]interface{}) + if templateSpec != nil && templateSpec["containers"] != nil { + containers := templateSpec["containers"].([]interface{}) + for _, item := range containers { + container := item.(map[string]interface{}) + images := container["image"].(interface{}) + dockerImages = append(dockerImages, images.(string)) + } + } + } + } + } + return dockerImages +} diff --git a/vendor/github.com/devtron-labs/common-lib/utils/k8sObjectsUtil/ImageUtil.go b/vendor/github.com/devtron-labs/common-lib/utils/k8sObjectsUtil/ImageUtil.go new file mode 100644 index 0000000000..54700f2433 --- /dev/null +++ b/vendor/github.com/devtron-labs/common-lib/utils/k8sObjectsUtil/ImageUtil.go @@ -0,0 +1,51 @@ +package k8sObjectsUtil + +import ( + "github.com/devtron-labs/common-lib/utils/k8s/commonBean" + yamlUtil "github.com/devtron-labs/common-lib/utils/yaml" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" +) + +func getPath(item string, path []string) []string { + return append(path, item) +} + +func ExtractImages(obj unstructured.Unstructured) []string { + images := make([]string, 0) + + subPath := commonBean.GetContainerSubPathForKind(obj.GetKind()) + allContainers := make([]interface{}, 0) + containers, _, _ := unstructured.NestedSlice(obj.Object, getPath(commonBean.Containers, subPath)...) + if len(containers) > 0 { + allContainers = append(allContainers, containers...) + } + iContainers, _, _ := unstructured.NestedSlice(obj.Object, getPath(commonBean.InitContainers, subPath)...) + if len(iContainers) > 0 { + allContainers = append(allContainers, iContainers...) + } + ephContainers, _, _ := unstructured.NestedSlice(obj.Object, getPath(commonBean.EphemeralContainers, subPath)...) + if len(ephContainers) > 0 { + allContainers = append(allContainers, ephContainers...) + } + for _, container := range allContainers { + containerMap := container.(map[string]interface{}) + if image, ok := containerMap[commonBean.Image].(string); ok { + images = append(images, image) + } + } + return images +} + +func ExtractImageFromManifestYaml(manifestYaml string) []string { + var dockerImagesFinal []string + parsedManifests, err := yamlUtil.SplitYAMLs([]byte(manifestYaml)) + if err != nil { + + return dockerImagesFinal + } + for _, manifest := range parsedManifests { + dockerImages := ExtractImages(manifest) + dockerImagesFinal = append(dockerImagesFinal, dockerImages...) + } + return dockerImagesFinal +} diff --git a/vendor/github.com/devtron-labs/common-lib/utils/remoteConnection/bean/bean.go b/vendor/github.com/devtron-labs/common-lib/utils/remoteConnection/bean/bean.go new file mode 100644 index 0000000000..9c1aff33f5 --- /dev/null +++ b/vendor/github.com/devtron-labs/common-lib/utils/remoteConnection/bean/bean.go @@ -0,0 +1,47 @@ +package bean + +type RemoteConnectionMethod string + +const ( + RemoteConnectionMethodProxy RemoteConnectionMethod = "PROXY" + RemoteConnectionMethodSSH RemoteConnectionMethod = "SSH" +) + +type ConnectionMethod string + +const ( + ConnectionMethod_Proxy ConnectionMethod = "PROXY" + ConnectionMethod_SSH ConnectionMethod = "SSH" +) + +type ProxyConfig struct { + ProxyUrl string `json:"proxyUrl,omitempty"` +} + +type SSHTunnelConfig struct { + SSHServerAddress string `json:"sshServerAddress,omitempty"` + SSHUsername string `json:"sshUsername,omitempty"` + SSHPassword string `json:"sshPassword,omitempty"` + SSHAuthKey string `json:"sshAuthKey,omitempty"` +} + +type RemoteConnectionConfigBean struct { + RemoteConnectionConfigId int `json:"remoteConnectionConfigId"` + ConnectionMethod RemoteConnectionMethod `json:"connectionMethod,omitempty"` + ProxyConfig *ProxyConfig `json:"proxyConfig,omitempty"` + SSHTunnelConfig *SSHTunnelConfig `json:"sshConfig,omitempty"` +} + +type RegistryConfig struct { + RegistryId string + RegistryUrl string + RegistryUsername string + RegistryPassword string + RegistryConnectionType string //secure, insecure, secure-with-cert + RegistryCertificateString string + RegistryCAFilePath string + IsPublicRegistry bool + ConnectionMethod ConnectionMethod //ssh, proxy + ProxyConfig *ProxyConfig + SSHConfig *SSHTunnelConfig +} diff --git a/vendor/github.com/google/wire/.gitattributes b/vendor/github.com/google/wire/.gitattributes new file mode 100644 index 0000000000..fcadb2cf97 --- /dev/null +++ b/vendor/github.com/google/wire/.gitattributes @@ -0,0 +1 @@ +* text eol=lf diff --git a/vendor/github.com/google/wire/.travis.yml b/vendor/github.com/google/wire/.travis.yml deleted file mode 100644 index 680a5003ac..0000000000 --- a/vendor/github.com/google/wire/.travis.yml +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright 2018 The Wire Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -language: go -go_import_path: github.com/google/wire - -before_install: - # The Bash that comes with OS X is ancient. - # grep is similar: it's not GNU grep, which means commands aren't portable. - # Homebrew installs grep as ggrep if you don't build from source, so it needs - # moving so it takes precedence in the PATH. - - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then - HOMEBREW_NO_AUTO_UPDATE=1 brew install bash grep; - mv $(brew --prefix)/bin/ggrep $(brew --prefix)/bin/grep; - fi - -install: - # Re-checkout files preserving line feeds. This prevents Windows builds from - # converting \n to \r\n. - - "git config --global core.autocrlf input" - - "git checkout -- ." - -script: - - 'internal/runtests.sh' - -env: - global: - - GO111MODULE=on - - GOPROXY=https://proxy.golang.org - -# When updating Go versions: -# In addition to changing the "go:" versions below, edit the version -# test in internal/runtests.sh. - -jobs: - include: - - go: "1.13.x" - os: linux - - go: "1.13.x" - os: osx - - go: "1.13.x" - os: windows diff --git a/vendor/github.com/google/wire/CONTRIBUTING.md b/vendor/github.com/google/wire/CONTRIBUTING.md index 68445fc463..ee19499f4e 100644 --- a/vendor/github.com/google/wire/CONTRIBUTING.md +++ b/vendor/github.com/google/wire/CONTRIBUTING.md @@ -78,11 +78,11 @@ again. If you are submitting code on behalf of your employer, there's a single commit before merging your change. * Check the diffs, write a useful description (including something like `Fixes #123` if it's fixing a bug) and send the PR out. -* [Travis CI](http://travis-ci.com) will run tests against the PR. This should +* Github will run tests against the PR. This should happen within 10 minutes or so. If a test fails, go back to the coding stage and try to fix the test and push the same branch again. You won't need to make a new pull request, the changes will be rolled directly into the PR you - already opened. Wait for Travis again. There is no need to assign a reviewer + already opened. Wait for the tests again. There is no need to assign a reviewer to the PR, the project team will assign someone for review during the standard [triage](#triaging) process. diff --git a/vendor/github.com/google/wire/README.md b/vendor/github.com/google/wire/README.md index 10983be0f0..ccafb0e27f 100644 --- a/vendor/github.com/google/wire/README.md +++ b/vendor/github.com/google/wire/README.md @@ -1,6 +1,6 @@ # Wire: Automated Initialization in Go -[![Build Status](https://travis-ci.com/google/wire.svg?branch=master)][travis] +[![Build Status](https://github.com/google/wire/actions/workflows/tests.yml/badge.svg?branch=main)](https://github.com/google/wire/actions) [![godoc](https://godoc.org/github.com/google/wire?status.svg)][godoc] [![Coverage](https://codecov.io/gh/google/wire/branch/master/graph/badge.svg)](https://codecov.io/gh/google/wire) @@ -24,7 +24,7 @@ For an overview, see the [introductory blog post][]. Install Wire by running: ```shell -go get github.com/google/wire/cmd/wire +go install github.com/google/wire/cmd/wire@latest ``` and ensuring that `$GOPATH/bin` is added to your `$PATH`. diff --git a/vendor/github.com/google/wire/wire.go b/vendor/github.com/google/wire/wire.go index fe8edc8c8a..6af91dda6c 100644 --- a/vendor/github.com/google/wire/wire.go +++ b/vendor/github.com/google/wire/wire.go @@ -156,12 +156,12 @@ type StructProvider struct{} // // For example: // -// type S struct { -// MyFoo *Foo -// MyBar *Bar -// } -// var Set = wire.NewSet(wire.Struct(new(S), "MyFoo")) -> inject only S.MyFoo -// var Set = wire.NewSet(wire.Struct(new(S), "*")) -> inject all fields +// type S struct { +// MyFoo *Foo +// MyBar *Bar +// } +// var Set = wire.NewSet(wire.Struct(new(S), "MyFoo")) -> inject only S.MyFoo +// var Set = wire.NewSet(wire.Struct(new(S), "*")) -> inject all fields func Struct(structType interface{}, fieldNames ...string) StructProvider { return StructProvider{} } @@ -175,22 +175,22 @@ type StructFields struct{} // // The following example would provide Foo and Bar using S.MyFoo and S.MyBar respectively: // -// type S struct { -// MyFoo Foo -// MyBar Bar -// } +// type S struct { +// MyFoo Foo +// MyBar Bar +// } // -// func NewStruct() S { /* ... */ } -// var Set = wire.NewSet(wire.FieldsOf(new(S), "MyFoo", "MyBar")) +// func NewStruct() S { /* ... */ } +// var Set = wire.NewSet(wire.FieldsOf(new(S), "MyFoo", "MyBar")) // -// or +// or // -// func NewStruct() *S { /* ... */ } -// var Set = wire.NewSet(wire.FieldsOf(new(*S), "MyFoo", "MyBar")) +// func NewStruct() *S { /* ... */ } +// var Set = wire.NewSet(wire.FieldsOf(new(*S), "MyFoo", "MyBar")) // -// If the structType argument is a pointer to a pointer to a struct, then FieldsOf -// additionally provides a pointer to each field type (e.g., *Foo and *Bar in the -// example above). +// If the structType argument is a pointer to a pointer to a struct, then FieldsOf +// additionally provides a pointer to each field type (e.g., *Foo and *Bar in the +// example above). func FieldsOf(structType interface{}, fieldNames ...string) StructFields { return StructFields{} } diff --git a/vendor/modules.txt b/vendor/modules.txt index f3932c1126..eeaa31716b 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -377,7 +377,7 @@ github.com/devtron-labs/authenticator/jwt github.com/devtron-labs/authenticator/middleware github.com/devtron-labs/authenticator/oidc github.com/devtron-labs/authenticator/password -# github.com/devtron-labs/common-lib v0.0.16-0.20240503082245-7ab933f8381f +# github.com/devtron-labs/common-lib v0.0.18-0.20240520084257-237319ab2bed ## explicit; go 1.20 github.com/devtron-labs/common-lib/blob-storage github.com/devtron-labs/common-lib/cloud-provider-identifier @@ -395,6 +395,7 @@ github.com/devtron-labs/common-lib/utils/k8s github.com/devtron-labs/common-lib/utils/k8s/commonBean github.com/devtron-labs/common-lib/utils/k8s/health github.com/devtron-labs/common-lib/utils/k8sObjectsUtil +github.com/devtron-labs/common-lib/utils/remoteConnection/bean github.com/devtron-labs/common-lib/utils/yaml # github.com/devtron-labs/protos v0.0.3-0.20240326053929-48e42d9d4534 ## explicit; go 1.17 @@ -649,7 +650,7 @@ github.com/google/shlex # github.com/google/uuid v1.3.1 ## explicit github.com/google/uuid -# github.com/google/wire v0.5.0 +# github.com/google/wire v0.6.0 ## explicit; go 1.12 github.com/google/wire # github.com/googleapis/enterprise-certificate-proxy v0.2.3