Skip to content

Commit ee90461

Browse files
committed
fix: resource tree gvk resource not found error
1 parent 9fa1fd0 commit ee90461

5 files changed

Lines changed: 125 additions & 69 deletions

File tree

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
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 errors
18+
19+
import (
20+
"google.golang.org/grpc/codes"
21+
)
22+
23+
// list of error strings from Helm. These are part of the errors we check for presence in Helm's error messages.
24+
const (
25+
ClusterUnreachableErrorMsg = "cluster unreachable"
26+
CrdPreconditionErrorMsg = "ensure crds are installed first"
27+
ArrayStringMismatchErrorMsg = "got array expected string"
28+
NotFoundErrorMsg = "not found" //this is a generic type constant, an error could be namespace "ns1" not found or service "ser1" not found.
29+
InvalidValueErrorMsg = "invalid value"
30+
OperationInProgressErrorMsg = "another operation (install/upgrade/rollback) is in progress"
31+
ForbiddenErrorMsg = "forbidden"
32+
)
33+
34+
// list of internal errors, these errors are easy for the users to understand
35+
const (
36+
InternalClusterUnreachableErrorMsg = "cluster unreachable"
37+
InternalOperationInProgressErrorMsg = "another operation (install/upgrade/rollback) is in progress"
38+
)
39+
40+
type errorGrpcCodeTuple struct {
41+
errorMsg string
42+
grpcCode codes.Code
43+
}
44+
45+
var helmErrorInternalErrorMap = map[string]errorGrpcCodeTuple{
46+
ClusterUnreachableErrorMsg: {errorMsg: InternalClusterUnreachableErrorMsg, grpcCode: codes.DeadlineExceeded},
47+
OperationInProgressErrorMsg: {errorMsg: InternalOperationInProgressErrorMsg, grpcCode: codes.FailedPrecondition},
48+
}
49+
50+
var DynamicErrorMapping = map[string]codes.Code{
51+
NotFoundErrorMsg: codes.NotFound,
52+
ForbiddenErrorMsg: codes.PermissionDenied,
53+
InvalidValueErrorMsg: codes.InvalidArgument,
54+
ArrayStringMismatchErrorMsg: codes.InvalidArgument,
55+
CrdPreconditionErrorMsg: codes.FailedPrecondition,
56+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
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 errors
18+
19+
import (
20+
"google.golang.org/grpc/status"
21+
"strings"
22+
)
23+
24+
// ConvertHelmErrorToInternalError converts known error message from helm to internal error and also maps it with proper grpc code
25+
func ConvertHelmErrorToInternalError(err error) error {
26+
genericError := getInternalErrorForGenericErrorTypes(err)
27+
if genericError != nil {
28+
return genericError
29+
}
30+
var internalError error
31+
for helmErrMsg, internalErr := range helmErrorInternalErrorMap {
32+
if strings.Contains(err.Error(), helmErrMsg) {
33+
internalError = status.New(internalErr.grpcCode, internalErr.errorMsg).Err()
34+
}
35+
}
36+
return internalError
37+
}
38+
39+
// getInternalErrorForGenericErrorTypes returns all those kinds of errors which are generic in nature and also dynamic, make sure to return all generic and dynamic errors from this func. instead of putting them in helmErrorInternalErrorMap
40+
func getInternalErrorForGenericErrorTypes(err error) error {
41+
/*
42+
for example:-
43+
1. if namespace is not found err is:- namespace "ns1" not found,
44+
2. in case ingress class not found error is of type ingress class: IngressClass.networking.k8s.io "ingress1" not found,
45+
3. when some resource is forbidden then err can be of many formats one of which is:- Unable to continue with install: could not get information about the resource Ingress "prakash-1-prakash-env3-ingress" in namespace "prakash-ns3": ingresses.networking.k8s.io "prakash-1-prakash-env3-ingress" is forbidden...
46+
etc..
47+
*/
48+
for errorMsg, code := range DynamicErrorMapping {
49+
if strings.Contains(strings.ToLower(err.Error()), errorMsg) {
50+
return status.New(code, err.Error()).Err()
51+
}
52+
}
53+
54+
return nil
55+
}

common-lib/k8sResource/listChildObjects.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ package k8sResource
33
import (
44
"context"
55
"errors"
6+
customErr "github.com/devtron-labs/common-lib/k8sResource/errors"
67
k8sUtils "github.com/devtron-labs/common-lib/utils/k8s"
78
k8sCommonBean "github.com/devtron-labs/common-lib/utils/k8s/commonBean"
89
coreV1 "k8s.io/api/core/v1"
10+
errors2 "k8s.io/apimachinery/pkg/api/errors"
911
"k8s.io/apimachinery/pkg/api/meta"
1012
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1113
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
@@ -196,8 +198,15 @@ func (impl *K8sServiceImpl) getChildObject(client *dynamicClient.DynamicClient,
196198
filterListStartTime := time.Now()
197199
childrenObjectsList, k8sErr := childResourceClient.List(context.Background(), options)
198200
if k8sErr != nil {
199-
impl.logger.Errorw("error in getting child listObjects", filterObjRequest.GetLoggerMetadata("counter", counter, "timeTaken", time.Since(filterListStartTime).Seconds(), "err", k8sErr)...)
200-
return nil, k8sErr
201+
statusError, matched := k8sErr.(*errors2.StatusError)
202+
if !matched || statusError.ErrStatus.Reason != metaV1.StatusReasonNotFound {
203+
internalErr := customErr.ConvertHelmErrorToInternalError(k8sErr)
204+
if internalErr != nil {
205+
k8sErr = internalErr
206+
}
207+
impl.logger.Errorw("error in getting child listObjects", filterObjRequest.GetLoggerMetadata("counter", counter, "timeTaken", time.Since(filterListStartTime).Seconds(), "err", k8sErr)...)
208+
return nil, k8sErr
209+
}
201210
}
202211
impl.logger.Debugw("listing child objects", filterObjRequest.GetLoggerMetadata("counter", counter, "timeTaken", time.Since(filterListStartTime).Seconds())...)
203212
filterObjRequest = filterObjRequest.WithListObjects(childrenObjectsList)

kubelink/error/constants.go

Lines changed: 1 addition & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -16,42 +16,7 @@
1616

1717
package error
1818

19-
import (
20-
"google.golang.org/grpc/codes"
21-
)
22-
2319
// list of error strings from Helm. These are part of the errors we check for presence in Helm's error messages.
2420
const (
25-
YAMLToJSONConversionError = "error converting YAML to JSON"
26-
ClusterUnreachableErrorMsg = "cluster unreachable"
27-
CrdPreconditionErrorMsg = "ensure crds are installed first"
28-
ArrayStringMismatchErrorMsg = "got array expected string"
29-
NotFoundErrorMsg = "not found" //this is a generic type constant, an error could be namespace "ns1" not found or service "ser1" not found.
30-
InvalidValueErrorMsg = "invalid value"
31-
OperationInProgressErrorMsg = "another operation (install/upgrade/rollback) is in progress"
32-
ForbiddenErrorMsg = "forbidden"
33-
)
34-
35-
// list of internal errors, these errors are easy for the users to understand
36-
const (
37-
InternalClusterUnreachableErrorMsg = "cluster unreachable"
38-
InternalOperationInProgressErrorMsg = "another operation (install/upgrade/rollback) is in progress"
21+
YAMLToJSONConversionError = "error converting YAML to JSON"
3922
)
40-
41-
type errorGrpcCodeTuple struct {
42-
errorMsg string
43-
grpcCode codes.Code
44-
}
45-
46-
var helmErrorInternalErrorMap = map[string]errorGrpcCodeTuple{
47-
ClusterUnreachableErrorMsg: {errorMsg: InternalClusterUnreachableErrorMsg, grpcCode: codes.DeadlineExceeded},
48-
OperationInProgressErrorMsg: {errorMsg: InternalOperationInProgressErrorMsg, grpcCode: codes.FailedPrecondition},
49-
}
50-
51-
var DynamicErrorMapping = map[string]codes.Code{
52-
NotFoundErrorMsg: codes.NotFound,
53-
ForbiddenErrorMsg: codes.PermissionDenied,
54-
InvalidValueErrorMsg: codes.InvalidArgument,
55-
ArrayStringMismatchErrorMsg: codes.InvalidArgument,
56-
CrdPreconditionErrorMsg: codes.FailedPrecondition,
57-
}

kubelink/error/utils.go

Lines changed: 2 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -17,39 +17,10 @@
1717
package error
1818

1919
import (
20-
"google.golang.org/grpc/status"
21-
"strings"
20+
customErr "github.com/devtron-labs/common-lib/k8sResource/errors"
2221
)
2322

2423
// ConvertHelmErrorToInternalError converts known error message from helm to internal error and also maps it with proper grpc code
2524
func ConvertHelmErrorToInternalError(err error) error {
26-
genericError := getInternalErrorForGenericErrorTypes(err)
27-
if genericError != nil {
28-
return genericError
29-
}
30-
var internalError error
31-
for helmErrMsg, internalErr := range helmErrorInternalErrorMap {
32-
if strings.Contains(err.Error(), helmErrMsg) {
33-
internalError = status.New(internalErr.grpcCode, internalErr.errorMsg).Err()
34-
}
35-
}
36-
return internalError
37-
}
38-
39-
// getInternalErrorForGenericErrorTypes returns all those kinds of errors which are generic in nature and also dynamic, make sure to return all generic and dynamic errors from this func. instead of putting them in helmErrorInternalErrorMap
40-
func getInternalErrorForGenericErrorTypes(err error) error {
41-
/*
42-
for example:-
43-
1. if namespace is not found err is:- namespace "ns1" not found,
44-
2. in case ingress class not found error is of type ingress class: IngressClass.networking.k8s.io "ingress1" not found,
45-
3. when some resource is forbidden then err can be of many formats one of which is:- Unable to continue with install: could not get information about the resource Ingress "prakash-1-prakash-env3-ingress" in namespace "prakash-ns3": ingresses.networking.k8s.io "prakash-1-prakash-env3-ingress" is forbidden...
46-
etc..
47-
*/
48-
for errorMsg, code := range DynamicErrorMapping {
49-
if strings.Contains(strings.ToLower(err.Error()), errorMsg) {
50-
return status.New(code, err.Error()).Err()
51-
}
52-
}
53-
54-
return nil
25+
return customErr.ConvertHelmErrorToInternalError(err)
5526
}

0 commit comments

Comments
 (0)