Skip to content

Commit 45edc27

Browse files
Merge pull request #237 from devtron-labs/chore-rc-main-sync-25-apr
chore: main merged into rc
2 parents 674fc28 + c5daeae commit 45edc27

9 files changed

Lines changed: 493 additions & 205 deletions

File tree

kubelink/internals/middleware/instrument.go

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,10 @@ import (
2727

2828
// metrics name constant
2929
const (
30-
KUBELINK_HTTP_DURATION_SECONDS = "kubelink_http_duration_seconds"
31-
KUBELINK_HTTP_REQUESTS_TOTAL = "kubelink_http_requests_total"
32-
KUBELINK_HTTP_REQUESTS_CURRENT = "kubelink_http_requests_current"
30+
KUBELINK_HTTP_DURATION_SECONDS = "kubelink_http_duration_seconds"
31+
KUBELINK_HTTP_REQUESTS_TOTAL = "kubelink_http_requests_total"
32+
KUBELINK_HTTP_REQUESTS_CURRENT = "kubelink_http_requests_current"
33+
KUBELINK_INFORMER_DATA_TRANSFORM_DURATION_SECONDS = "kubelink_informer_data_transform_duration_seconds"
3334
)
3435

3536
// metrics labels constants
@@ -57,6 +58,17 @@ var currentRequestGauge = promauto.NewGaugeVec(prometheus.GaugeOpts{
5758
Help: "no of request being served currently",
5859
}, []string{PATH, METHOD})
5960

61+
var InformerDataTransformDuration = promauto.NewHistogramVec(prometheus.HistogramOpts{
62+
Name: KUBELINK_INFORMER_DATA_TRANSFORM_DURATION_SECONDS,
63+
Help: "Duration of informer data transform request",
64+
}, []string{CLUSTER_NAME, NAMESPACE, RELEASE_NAME})
65+
66+
const (
67+
CLUSTER_NAME = "clusterName"
68+
NAMESPACE = "namespace"
69+
RELEASE_NAME = "releaseName"
70+
)
71+
6072
// prometheusMiddleware implements mux.MiddlewareFunc.
6173
func PrometheusMiddleware(next http.Handler) http.Handler {
6274
// prometheus.MustRegister(requestCounter)

kubelink/pkg/k8sInformer/K8sInformer.go

Lines changed: 146 additions & 111 deletions
Large diffs are not rendered by default.

kubelink/pkg/k8sInformer/bean.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright (c) 2024. Devtron Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package k8sInformer
18+
19+
import (
20+
"fmt"
21+
client "github.com/devtron-labs/kubelink/grpc"
22+
)
23+
24+
const (
25+
secretKeyAppDetailKey = "appDetail"
26+
)
27+
28+
type DeployedAppDetailDto struct {
29+
*client.DeployedAppDetail
30+
}
31+
32+
func NewDeployedAppDetailDto(appDetail *client.DeployedAppDetail) *DeployedAppDetailDto {
33+
return &DeployedAppDetailDto{DeployedAppDetail: appDetail}
34+
}
35+
36+
func (r *DeployedAppDetailDto) getUniqueReleaseIdentifier() string {
37+
if r == nil || r.EnvironmentDetail == nil {
38+
return ""
39+
}
40+
// adding cluster id with release name and namespace because there can be case when two cluster or two namespaces have release with same name
41+
return fmt.Sprintf("%s_%s_%d", r.EnvironmentDetail.Namespace, r.AppName, r.EnvironmentDetail.ClusterId)
42+
}
Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,13 @@ package k8sInformer
1818

1919
import (
2020
"errors"
21-
"helm.sh/helm/v3/pkg/release"
2221
)
2322

24-
type ReleaseDto struct {
25-
*release.Release
26-
}
27-
28-
func (r *ReleaseDto) getUniqueReleaseIdentifier() string {
29-
return r.Namespace + "_" + r.Name
30-
}
31-
3223
var (
24+
// ErrorCacheMissReleaseNotFound is returned when a release is not found in the cache
3325
ErrorCacheMissReleaseNotFound = errors.New("release not found in cache")
26+
// InformerAlreadyExistError is returned when an informer already exists
27+
InformerAlreadyExistError = errors.New(INFORMER_ALREADY_EXIST_MESSAGE)
3428
)
3529

3630
const (

kubelink/pkg/k8sInformer/util.go

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*
2+
* Copyright (c) 2024. Devtron Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package k8sInformer
18+
19+
import (
20+
"bytes"
21+
"compress/gzip"
22+
"encoding/base64"
23+
"encoding/json"
24+
"errors"
25+
client "github.com/devtron-labs/kubelink/grpc"
26+
"github.com/devtron-labs/kubelink/pkg/service/helmApplicationService/release"
27+
"io"
28+
)
29+
30+
func parseSecretDataForDeployedAppDetail(appDetail *client.DeployedAppDetail) (map[string][]byte, error) {
31+
appDetailBytes, err := json.Marshal(appDetail)
32+
if err != nil {
33+
return nil, err
34+
}
35+
data := make(map[string][]byte)
36+
data[secretKeyAppDetailKey] = appDetailBytes
37+
return data, nil
38+
}
39+
40+
func getDeployedAppDetailFromSecretData(data map[string][]byte) (*client.DeployedAppDetail, error) {
41+
if appDetailBytes, ok := data[secretKeyAppDetailKey]; ok {
42+
var appDetail client.DeployedAppDetail
43+
err := json.Unmarshal(appDetailBytes, &appDetail)
44+
if err != nil {
45+
return nil, err
46+
}
47+
return &appDetail, nil
48+
}
49+
return nil, errors.New("app detail not found in secret data")
50+
}
51+
52+
func decodeHelmReleaseData(data string) (*release.Release, error) {
53+
// base64 decode string
54+
b64 := base64.StdEncoding
55+
b, err := b64.DecodeString(data)
56+
if err != nil {
57+
return nil, err
58+
}
59+
60+
var magicGzip = []byte{0x1f, 0x8b, 0x08}
61+
62+
// For backwards compatibility with releases that were stored before
63+
// compression was introduced we skip decompression if the
64+
// gzip magic header is not found
65+
if len(b) > 3 && bytes.Equal(b[0:3], magicGzip) {
66+
r, err := gzip.NewReader(bytes.NewReader(b))
67+
if err != nil {
68+
return nil, err
69+
}
70+
defer r.Close()
71+
b2, err := io.ReadAll(r)
72+
if err != nil {
73+
return nil, err
74+
}
75+
b = b2
76+
}
77+
78+
var rls release.Release
79+
// unmarshal release object bytes
80+
if err := json.Unmarshal(b, &rls); err != nil {
81+
return nil, err
82+
}
83+
return &rls, nil
84+
}

kubelink/pkg/service/helmApplicationService/adapter/adapter.go

Lines changed: 57 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ package adapter
22

33
import (
44
"github.com/devtron-labs/common-lib/helmLib/registry"
5-
"github.com/devtron-labs/common-lib/utils/remoteConnection/bean"
5+
remoteConnection "github.com/devtron-labs/common-lib/utils/remoteConnection/bean"
66
client "github.com/devtron-labs/kubelink/grpc"
7+
"github.com/devtron-labs/kubelink/pkg/service/helmApplicationService/release"
78
"github.com/devtron-labs/kubelink/pkg/util"
89
"google.golang.org/protobuf/types/known/timestamppb"
9-
"helm.sh/helm/v3/pkg/release"
10+
helmChart "helm.sh/helm/v3/pkg/chart"
11+
helmRelease "helm.sh/helm/v3/pkg/release"
1012
)
1113

1214
func NewRegistryConfig(credential *client.RegistryCredential) (*registry.Configuration, error) {
@@ -37,36 +39,36 @@ func NewRegistryConfig(credential *client.RegistryCredential) (*registry.Configu
3739

3840
connectionConfig := credential.RemoteConnectionConfig
3941
if connectionConfig != nil {
40-
registryConfig.RemoteConnectionConfig = &bean.RemoteConnectionConfigBean{}
42+
registryConfig.RemoteConnectionConfig = &remoteConnection.RemoteConnectionConfigBean{}
4143
switch connectionConfig.RemoteConnectionMethod {
4244
case client.RemoteConnectionMethod_DIRECT:
43-
registryConfig.RemoteConnectionConfig.ConnectionMethod = bean.RemoteConnectionMethodDirect
45+
registryConfig.RemoteConnectionConfig.ConnectionMethod = remoteConnection.RemoteConnectionMethodDirect
4446
case client.RemoteConnectionMethod_PROXY:
45-
registryConfig.RemoteConnectionConfig.ConnectionMethod = bean.RemoteConnectionMethodProxy
47+
registryConfig.RemoteConnectionConfig.ConnectionMethod = remoteConnection.RemoteConnectionMethodProxy
4648
registryConfig.RemoteConnectionConfig.ProxyConfig = ConvertConfigToProxyConfig(connectionConfig)
4749
case client.RemoteConnectionMethod_SSH:
48-
registryConfig.RemoteConnectionConfig.ConnectionMethod = bean.RemoteConnectionMethodSSH
50+
registryConfig.RemoteConnectionConfig.ConnectionMethod = remoteConnection.RemoteConnectionMethodSSH
4951
registryConfig.RemoteConnectionConfig.SSHTunnelConfig = ConvertConfigToSSHTunnelConfig(connectionConfig)
5052
}
5153
}
5254
}
5355
return registryConfig, nil
5456
}
5557

56-
func ConvertConfigToProxyConfig(config *client.RemoteConnectionConfig) *bean.ProxyConfig {
57-
var proxyConfig *bean.ProxyConfig
58+
func ConvertConfigToProxyConfig(config *client.RemoteConnectionConfig) *remoteConnection.ProxyConfig {
59+
var proxyConfig *remoteConnection.ProxyConfig
5860
if config.ProxyConfig != nil {
59-
proxyConfig = &bean.ProxyConfig{
61+
proxyConfig = &remoteConnection.ProxyConfig{
6062
ProxyUrl: config.ProxyConfig.ProxyUrl,
6163
}
6264
}
6365
return proxyConfig
6466
}
6567

66-
func ConvertConfigToSSHTunnelConfig(config *client.RemoteConnectionConfig) *bean.SSHTunnelConfig {
67-
var sshConfig *bean.SSHTunnelConfig
68+
func ConvertConfigToSSHTunnelConfig(config *client.RemoteConnectionConfig) *remoteConnection.SSHTunnelConfig {
69+
var sshConfig *remoteConnection.SSHTunnelConfig
6870
if config.SSHTunnelConfig != nil {
69-
sshConfig = &bean.SSHTunnelConfig{
71+
sshConfig = &remoteConnection.SSHTunnelConfig{
7072
SSHUsername: config.SSHTunnelConfig.SSHUsername,
7173
SSHPassword: config.SSHTunnelConfig.SSHPassword,
7274
SSHAuthKey: config.SSHTunnelConfig.SSHAuthKey,
@@ -120,3 +122,46 @@ func GetAppDetailRequestFromGetResourceTreeRequest(req *client.GetResourceTreeRe
120122
CacheConfig: req.CacheConfig,
121123
}
122124
}
125+
126+
func NewRelease(helmRelease *helmRelease.Release) *release.Release {
127+
if helmRelease == nil {
128+
return nil
129+
}
130+
return &release.Release{
131+
Name: helmRelease.Name,
132+
Namespace: helmRelease.Namespace,
133+
Info: NewReleaseInfo(helmRelease.Info),
134+
Chart: NewChart(helmRelease.Chart),
135+
}
136+
}
137+
138+
func NewReleaseInfo(helmReleaseInfo *helmRelease.Info) *release.Info {
139+
if helmReleaseInfo == nil {
140+
return nil
141+
}
142+
return &release.Info{
143+
LastDeployed: helmReleaseInfo.LastDeployed,
144+
Status: helmReleaseInfo.Status,
145+
}
146+
}
147+
148+
func NewChart(helmChart *helmChart.Chart) *release.Chart {
149+
if helmChart == nil {
150+
return nil
151+
}
152+
return &release.Chart{
153+
Metadata: NewChartMetadata(helmChart.Metadata),
154+
}
155+
}
156+
157+
func NewChartMetadata(helmChartMetadata *helmChart.Metadata) *release.Metadata {
158+
if helmChartMetadata == nil {
159+
return nil
160+
}
161+
return &release.Metadata{
162+
Name: helmChartMetadata.Name,
163+
Version: helmChartMetadata.Version,
164+
Icon: helmChartMetadata.Icon,
165+
Home: helmChartMetadata.Home,
166+
}
167+
}

0 commit comments

Comments
 (0)