Skip to content

Commit a43cbfa

Browse files
authored
feat: Generate config and secret hash for application mounting external k8s secrets (#5626)
* feat: Generate config and secret hash for application mounting external k8s secrets * feat: reverted changes in charts file * chore: refactoring * updated: common-lib version * updated: run with ctx * updated common-lib version * fix: invalid request * feat: handling for KubernetesSecret only. excluding KubernetesExternalSecret * chore: skipping error * common-lib version upgrade and hash creation from data fileds only
1 parent ba29cfe commit a43cbfa

File tree

12 files changed

+351
-68
lines changed

12 files changed

+351
-68
lines changed

api/bean/ConfigMapAndSecret.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ type ConfigMapJson struct {
3232
type ConfigSecretRootJson struct {
3333
ConfigSecretJson ConfigSecretJson `json:"ConfigSecrets"`
3434
}
35+
3536
type ConfigSecretJson struct {
3637
Enabled bool `json:"enabled"`
3738
Secrets []*ConfigSecretMap `json:"secrets"`

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ require (
2222
github.com/davecgh/go-spew v1.1.1
2323
github.com/deckarep/golang-set v1.8.0
2424
github.com/devtron-labs/authenticator v0.4.35-0.20240809073103-6e11da8083f8
25-
github.com/devtron-labs/common-lib v0.0.25-0.20240809073131-5cefb0e8a93a
25+
github.com/devtron-labs/common-lib v0.0.25-0.20240812080926-4926120ea08d
2626
github.com/devtron-labs/go-bitbucket v0.9.60-beta
2727
github.com/devtron-labs/protos v0.0.3-0.20240802105333-92ee9bb85d80
2828
github.com/evanphx/json-patch v5.7.0+incompatible

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,8 +195,8 @@ github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc h1:VRRKCwnzq
195195
github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
196196
github.com/devtron-labs/authenticator v0.4.35-0.20240809073103-6e11da8083f8 h1:2+Q7Jdhpo/uMiaQiZZzAh+ZX7wEJIFuMFG6DEiMuo64=
197197
github.com/devtron-labs/authenticator v0.4.35-0.20240809073103-6e11da8083f8/go.mod h1:702R6WIf5y9UzKGoCGxQ+x3l5Ws+l0fXg2xlCpSGFZI=
198-
github.com/devtron-labs/common-lib v0.0.25-0.20240809073131-5cefb0e8a93a h1:VebYW3ZIz85sZedsG1wRAaV3V4B2Bx26XXpG8T9VfAA=
199-
github.com/devtron-labs/common-lib v0.0.25-0.20240809073131-5cefb0e8a93a/go.mod h1:a7aCClaxYfnyYEENSe1RnkQCeW2AwmCAPYsuvgk0aW0=
198+
github.com/devtron-labs/common-lib v0.0.25-0.20240812080926-4926120ea08d h1:/HZhYZVP+zQfbohq9Mxz3IX4rDjt0tokPll5zhh5gC8=
199+
github.com/devtron-labs/common-lib v0.0.25-0.20240812080926-4926120ea08d/go.mod h1:a7aCClaxYfnyYEENSe1RnkQCeW2AwmCAPYsuvgk0aW0=
200200
github.com/devtron-labs/go-bitbucket v0.9.60-beta h1:VEx1jvDgdtDPS6A1uUFoaEi0l1/oLhbr+90xOwr6sDU=
201201
github.com/devtron-labs/go-bitbucket v0.9.60-beta/go.mod h1:GnuiCesvh8xyHeMCb+twm8lBR/kQzJYSKL28ZfObp1Y=
202202
github.com/devtron-labs/protos v0.0.3-0.20240802105333-92ee9bb85d80 h1:xwbTeijNTf4/j1v+tSfwVqwLVnReas/NqEKeQHvSTys=

pkg/bean/app.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -948,3 +948,12 @@ const CustomAutoScalingEnabledPathKey = "CUSTOM_AUTOSCALING_ENABLED_PATH"
948948
const CustomAutoscalingReplicaCountPathKey = "CUSTOM_AUTOSCALING_REPLICA_COUNT_PATH"
949949
const CustomAutoscalingMinPathKey = "CUSTOM_AUTOSCALING_MIN_PATH"
950950
const CustomAutoscalingMaxPathKey = "CUSTOM_AUTOSCALING_MAX_PATH"
951+
952+
type JsonPath string
953+
954+
func (j JsonPath) String() string {
955+
return string(j)
956+
}
957+
958+
const ConfigHashPathKey JsonPath = "devtronInternal.containerSpecs.ConfigHash"
959+
const SecretHashPathKey JsonPath = "devtronInternal.containerSpecs.SecretHash"

pkg/deployment/manifest/ManifestCreationService.go

Lines changed: 175 additions & 52 deletions
Large diffs are not rendered by default.

pkg/deployment/manifest/bean/bean.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ const (
3333
ProjectNameDevtronLabel = "api.devtron.ai/project"
3434
)
3535

36-
type ConfigMapAndSecretJsonV2 struct {
36+
type GetMergedCmAndCsJsonV2Request struct {
3737
AppId int
3838
EnvId int
3939
PipeLineId int
@@ -42,3 +42,9 @@ type ConfigMapAndSecretJsonV2 struct {
4242
WfrIdForDeploymentWithSpecificTrigger int
4343
Scope resourceQualifiers.Scope
4444
}
45+
46+
type MergedCmAndCsJsonV2Response struct {
47+
MergedJson []byte
48+
ExternalCmList []string
49+
ExternalCsList []string
50+
}

pkg/deployment/manifest/helper/helper.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,8 @@ func GetAutoScalingReplicaCount(templateMap map[string]interface{}, appName stri
152152

153153
}
154154

155-
func CreateConfigMapAndSecretJsonRequest(overrideRequest *bean.ValuesOverrideRequest, envOverride *chartConfig.EnvConfigOverride, chartVersion string, scope resourceQualifiers.Scope) bean3.ConfigMapAndSecretJsonV2 {
156-
request := bean3.ConfigMapAndSecretJsonV2{
155+
func NewMergedCmAndCsJsonV2Request(overrideRequest *bean.ValuesOverrideRequest, envOverride *chartConfig.EnvConfigOverride, chartVersion string, scope resourceQualifiers.Scope) bean3.GetMergedCmAndCsJsonV2Request {
156+
request := bean3.GetMergedCmAndCsJsonV2Request{
157157
AppId: overrideRequest.AppId,
158158
EnvId: envOverride.TargetEnvironment,
159159
PipeLineId: overrideRequest.PipelineId,
@@ -165,6 +165,14 @@ func CreateConfigMapAndSecretJsonRequest(overrideRequest *bean.ValuesOverrideReq
165165
return request
166166
}
167167

168+
func NewMergedCmAndCsJsonV2Response() *bean3.MergedCmAndCsJsonV2Response {
169+
return &bean3.MergedCmAndCsJsonV2Response{
170+
MergedJson: []byte("{}"),
171+
ExternalCsList: make([]string, 0),
172+
ExternalCmList: make([]string, 0),
173+
}
174+
}
175+
168176
func GetScopeForVariables(overrideRequest *bean.ValuesOverrideRequest, envOverride *chartConfig.EnvConfigOverride) resourceQualifiers.Scope {
169177
scope := resourceQualifiers.Scope{
170178
AppId: overrideRequest.AppId,

pkg/k8s/K8sCommonService.go

Lines changed: 58 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,20 @@ import (
2424
k8sCommonBean "github.com/devtron-labs/common-lib/utils/k8s/commonBean"
2525
"github.com/devtron-labs/devtron/api/bean"
2626
helmBean "github.com/devtron-labs/devtron/api/helm-app/service/bean"
27-
util2 "github.com/devtron-labs/devtron/internal/util"
27+
internalUtil "github.com/devtron-labs/devtron/internal/util"
2828
"github.com/devtron-labs/devtron/pkg/argoApplication"
2929
"github.com/devtron-labs/devtron/pkg/cluster"
3030
bean3 "github.com/devtron-labs/devtron/pkg/k8s/application/bean"
3131
"github.com/devtron-labs/devtron/util"
3232
"go.opentelemetry.io/otel"
3333
"go.uber.org/zap"
34+
apiV1 "k8s.io/api/core/v1"
3435
"k8s.io/apimachinery/pkg/api/errors"
3536
"k8s.io/apimachinery/pkg/runtime/schema"
3637
"k8s.io/apimachinery/pkg/types"
3738
"k8s.io/apimachinery/pkg/version"
3839
"k8s.io/client-go/kubernetes"
39-
v1 "k8s.io/client-go/kubernetes/typed/core/v1"
40+
clientV1 "k8s.io/client-go/kubernetes/typed/core/v1"
4041
"k8s.io/client-go/rest"
4142
"net/http"
4243
"strconv"
@@ -46,15 +47,17 @@ import (
4647

4748
type K8sCommonService interface {
4849
GetResource(ctx context.Context, request *ResourceRequestBean) (resp *ResourceGetResponse, err error)
50+
GetDataFromConfigMaps(ctx context.Context, request *CmCsRequestBean) (map[string]*apiV1.ConfigMap, error)
51+
GetDataFromSecrets(ctx context.Context, request *CmCsRequestBean) (map[string]*apiV1.Secret, error)
4952
UpdateResource(ctx context.Context, request *ResourceRequestBean) (resp *k8s.ManifestResponse, err error)
5053
DeleteResource(ctx context.Context, request *ResourceRequestBean) (resp *k8s.ManifestResponse, err error)
5154
ListEvents(ctx context.Context, request *ResourceRequestBean) (*k8s.EventsResponse, error)
5255
GetRestConfigByClusterId(ctx context.Context, clusterId int) (*rest.Config, error, *cluster.ClusterBean)
5356
GetManifestsByBatch(ctx context.Context, request []ResourceRequestBean) ([]BatchResourceResponse, error)
5457
FilterK8sResources(ctx context.Context, resourceTreeInf map[string]interface{}, appDetail bean.AppDetailContainer, appId string, kindsToBeFiltered []string, externalArgoAppName string) []ResourceRequestBean
5558
RotatePods(ctx context.Context, request *RotatePodRequest) (*RotatePodResponse, error)
56-
GetCoreClientByClusterId(clusterId int) (*kubernetes.Clientset, *v1.CoreV1Client, error)
57-
GetCoreClientByClusterIdForExternalArgoApps(req *cluster.EphemeralContainerRequest) (*kubernetes.Clientset, *v1.CoreV1Client, error)
59+
GetCoreClientByClusterId(clusterId int) (*kubernetes.Clientset, *clientV1.CoreV1Client, error)
60+
GetCoreClientByClusterIdForExternalArgoApps(req *cluster.EphemeralContainerRequest) (*kubernetes.Clientset, *clientV1.CoreV1Client, error)
5861
GetK8sServerVersion(clusterId int) (*version.Info, error)
5962
PortNumberExtraction(resp []BatchResourceResponse, resourceTree map[string]interface{}) map[string]interface{}
6063
GetRestConfigOfCluster(ctx context.Context, request *ResourceRequestBean) (*rest.Config, error)
@@ -113,6 +116,54 @@ func (impl *K8sCommonServiceImpl) GetResource(ctx context.Context, request *Reso
113116
return response, nil
114117
}
115118

119+
func (impl *K8sCommonServiceImpl) GetDataFromConfigMaps(ctx context.Context, request *CmCsRequestBean) (map[string]*apiV1.ConfigMap, error) {
120+
newCtx, span := otel.Tracer("orchestrator").Start(ctx, "K8sCommonServiceImpl.GetDataFromConfigMaps")
121+
defer span.End()
122+
response := make(map[string]*apiV1.ConfigMap, len(request.GetExternalCmList()))
123+
if len(request.GetExternalCmList()) == 0 {
124+
return response, nil
125+
}
126+
_, v1Client, err := impl.GetCoreClientByClusterId(request.GetClusterId())
127+
if err != nil {
128+
impl.logger.Errorw("error in getting coreV1 client by clusterId", "clusterId", request.clusterId, "err", err)
129+
return nil, err
130+
}
131+
// using for loop instead of getting all configMaps at once since request.GetExternalCmList() will be small
132+
for _, cmName := range request.GetExternalCmList() {
133+
configMap, err := impl.K8sUtil.GetConfigMapWithCtx(newCtx, request.GetNamespace(), cmName, v1Client)
134+
if err != nil {
135+
impl.logger.Errorw("error in getting configMap", "namespace", request.GetNamespace(), "cmName", cmName, "err", err)
136+
return nil, err
137+
}
138+
response[cmName] = configMap
139+
}
140+
return response, nil
141+
}
142+
143+
func (impl *K8sCommonServiceImpl) GetDataFromSecrets(ctx context.Context, request *CmCsRequestBean) (map[string]*apiV1.Secret, error) {
144+
newCtx, span := otel.Tracer("orchestrator").Start(ctx, "K8sCommonServiceImpl.GetDataFromConfigMaps")
145+
defer span.End()
146+
response := make(map[string]*apiV1.Secret, len(request.GetExternalCmList()))
147+
if len(request.GetExternalCsList()) == 0 {
148+
return response, nil
149+
}
150+
_, v1Client, err := impl.GetCoreClientByClusterId(request.GetClusterId())
151+
if err != nil {
152+
impl.logger.Errorw("error in getting coreV1 client by clusterId", "clusterId", request.clusterId, "err", err)
153+
return nil, err
154+
}
155+
// using for loop instead of getting all secrets at once since request.GetExternalCsList() will be small
156+
for _, csName := range request.GetExternalCsList() {
157+
secret, err := impl.K8sUtil.GetSecretWithCtx(newCtx, request.GetNamespace(), csName, v1Client)
158+
if err != nil {
159+
impl.logger.Errorw("error in getting configMap", "namespace", request.namespace, "csName", csName, "err", err)
160+
return nil, err
161+
}
162+
response[csName] = secret
163+
}
164+
return response, nil
165+
}
166+
116167
func (impl *K8sCommonServiceImpl) UpdateResource(ctx context.Context, request *ResourceRequestBean) (*k8s.ManifestResponse, error) {
117168
//getting rest config by clusterId
118169
clusterId := request.ClusterId
@@ -129,7 +180,7 @@ func (impl *K8sCommonServiceImpl) UpdateResource(ctx context.Context, request *R
129180
impl.logger.Errorw("error in updating resource", "err", err, "clusterId", clusterId)
130181
statusError, ok := err.(*errors.StatusError)
131182
if ok {
132-
err = &util2.ApiError{Code: "400", HttpStatusCode: int(statusError.ErrStatus.Code), UserMessage: statusError.Error()}
183+
err = &internalUtil.ApiError{Code: "400", HttpStatusCode: int(statusError.ErrStatus.Code), UserMessage: statusError.Error()}
133184
}
134185
return nil, err
135186
}
@@ -382,7 +433,7 @@ func (impl *K8sCommonServiceImpl) GetK8sServerVersion(clusterId int) (*version.I
382433
return k8sVersion, err
383434
}
384435

385-
func (impl *K8sCommonServiceImpl) GetCoreClientByClusterId(clusterId int) (*kubernetes.Clientset, *v1.CoreV1Client, error) {
436+
func (impl *K8sCommonServiceImpl) GetCoreClientByClusterId(clusterId int) (*kubernetes.Clientset, *clientV1.CoreV1Client, error) {
386437
clusterBean, err := impl.clusterService.FindById(clusterId)
387438
if err != nil {
388439
impl.logger.Errorw("error occurred in finding clusterBean by Id", "clusterId", clusterId, "err", err)
@@ -405,7 +456,7 @@ func (impl *K8sCommonServiceImpl) GetCoreClientByClusterId(clusterId int) (*kube
405456
return clientSet, v1Client, nil
406457
}
407458

408-
func (impl *K8sCommonServiceImpl) GetCoreClientByClusterIdForExternalArgoApps(req *cluster.EphemeralContainerRequest) (*kubernetes.Clientset, *v1.CoreV1Client, error) {
459+
func (impl *K8sCommonServiceImpl) GetCoreClientByClusterIdForExternalArgoApps(req *cluster.EphemeralContainerRequest) (*kubernetes.Clientset, *clientV1.CoreV1Client, error) {
409460
restConfig, err := impl.argoApplicationService.GetRestConfigForExternalArgo(context.Background(), req.ClusterId, req.ExternalArgoApplicationName)
410461
if err != nil {
411462
impl.logger.Errorw("error in getting rest config", "err", err, "clusterId", req.ClusterId, "externalArgoApplicationName", req.ExternalArgoApplicationName)

pkg/k8s/bean.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,55 @@ func (r *ResourceRequestBean) IsValidDeploymentType() bool {
4343
return r.DeploymentType == bean.HelmInstalledType || r.DeploymentType == bean.ArgoInstalledType || r.DeploymentType == bean.FluxInstalledType
4444
}
4545

46+
type CmCsRequestBean struct {
47+
clusterId int
48+
namespace string
49+
externalCmList []string
50+
externalCsList []string
51+
}
52+
53+
func (req *CmCsRequestBean) SetClusterId(clusterId int) *CmCsRequestBean {
54+
req.clusterId = clusterId
55+
return req
56+
}
57+
58+
func (req *CmCsRequestBean) SetNamespace(namespace string) *CmCsRequestBean {
59+
req.namespace = namespace
60+
return req
61+
}
62+
63+
func (req *CmCsRequestBean) SetExternalCmList(externalCmList ...string) *CmCsRequestBean {
64+
if len(externalCmList) == 0 {
65+
return req
66+
}
67+
req.externalCmList = append(req.externalCmList, externalCmList...)
68+
return req
69+
}
70+
71+
func (req *CmCsRequestBean) SetExternalCsList(externalCsList ...string) *CmCsRequestBean {
72+
if len(externalCsList) == 0 {
73+
return req
74+
}
75+
req.externalCsList = append(req.externalCsList, externalCsList...)
76+
return req
77+
}
78+
79+
func (req *CmCsRequestBean) GetClusterId() int {
80+
return req.clusterId
81+
}
82+
83+
func (req *CmCsRequestBean) GetNamespace() string {
84+
return req.namespace
85+
}
86+
87+
func (req *CmCsRequestBean) GetExternalCmList() []string {
88+
return req.externalCmList
89+
}
90+
91+
func (req *CmCsRequestBean) GetExternalCsList() []string {
92+
return req.externalCsList
93+
}
94+
4695
type LogsDownloadBean struct {
4796
FileName string `json:"fileName"`
4897
LogsData string `json:"data"`

pkg/k8s/helper.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"errors"
2121
"fmt"
2222
"github.com/Masterminds/semver"
23+
"github.com/devtron-labs/devtron/internal/util"
2324
"github.com/devtron-labs/devtron/pkg/fluxApplication"
2425
k8sErrors "k8s.io/apimachinery/pkg/api/errors"
2526
"strings"
@@ -44,6 +45,24 @@ func GetClientErrorMessage(err error) string {
4445
return err.Error()
4546
}
4647

48+
func ParseK8sClientErrorToApiError(err error) *util.ApiError {
49+
if apiErr := (&util.ApiError{}); errors.As(err, &apiErr) {
50+
// do not change the error if it is already an ApiError
51+
return apiErr
52+
}
53+
// if error is of type k8sErrors.APIStatus, then extract the message from it
54+
if status, ok := err.(k8sErrors.APIStatus); ok || errors.As(err, &status) {
55+
return util.NewApiError().
56+
WithHttpStatusCode(int(status.Status().Code)).
57+
WithUserDetailMessage(status.Status().Message).
58+
WithInternalMessage(status.Status().Message)
59+
}
60+
// generic error
61+
return util.NewApiError().
62+
WithUserDetailMessage(err.Error()).
63+
WithInternalMessage(err.Error())
64+
}
65+
4766
// StripPrereleaseFromK8sVersion takes in k8sVersion and stripe pre-release from semver version and return sanitized k8sVersion
4867
// or error if invalid version provided, e.g. if k8sVersion = "1.25.16-eks-b9c9ed7", then it returns "1.25.16".
4968
func StripPrereleaseFromK8sVersion(k8sVersion string) string {
@@ -59,6 +78,11 @@ func StripPrereleaseFromK8sVersion(k8sVersion string) string {
5978
return k8sVersion
6079
}
6180

81+
func NewCmCsRequestBean(clusterId int, namespace string) *CmCsRequestBean {
82+
req := &CmCsRequestBean{}
83+
return req.SetClusterId(clusterId).SetNamespace(namespace)
84+
}
85+
6286
func IsClusterStringContainsFluxField(str string) bool {
6387
_, err := fluxApplication.DecodeFluxExternalAppId(str)
6488
if err != nil {

vendor/github.com/devtron-labs/common-lib/utils/k8s/K8sUtil.go

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

vendor/modules.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ github.com/devtron-labs/authenticator/jwt
401401
github.com/devtron-labs/authenticator/middleware
402402
github.com/devtron-labs/authenticator/oidc
403403
github.com/devtron-labs/authenticator/password
404-
# github.com/devtron-labs/common-lib v0.0.25-0.20240809073131-5cefb0e8a93a
404+
# github.com/devtron-labs/common-lib v0.0.25-0.20240812080926-4926120ea08d
405405
## explicit; go 1.21
406406
github.com/devtron-labs/common-lib/async
407407
github.com/devtron-labs/common-lib/blob-storage

0 commit comments

Comments
 (0)