Merge pull request #117717 from saschagrunert/invalid-signature-error
Add support for CRI `ErrSignatureValidationFailed`
This commit is contained in:
		| @@ -29,6 +29,7 @@ import ( | ||||
| 	"k8s.io/klog/v2" | ||||
|  | ||||
| 	runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1" | ||||
| 	crierrors "k8s.io/cri-api/pkg/errors" | ||||
| 	kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" | ||||
| 	"k8s.io/kubernetes/pkg/kubelet/events" | ||||
| ) | ||||
| @@ -158,14 +159,8 @@ func (m *imageManager) EnsureImageExists(ctx context.Context, pod *v1.Pod, conta | ||||
| 		m.logIt(ref, v1.EventTypeWarning, events.FailedToPullImage, logPrefix, fmt.Sprintf("Failed to pull image %q: %v", container.Image, imagePullResult.err), klog.Warning) | ||||
| 		m.backOff.Next(backOffKey, m.backOff.Clock.Now()) | ||||
|  | ||||
| 		// Error assertions via errors.Is is not supported by gRPC (remote runtime) errors right now. | ||||
| 		// See https://github.com/grpc/grpc-go/issues/3616 | ||||
| 		if imagePullResult.err.Error() == ErrRegistryUnavailable.Error() { | ||||
| 			msg := fmt.Sprintf("image pull failed for %s because the registry is unavailable.", container.Image) | ||||
| 			return "", msg, imagePullResult.err | ||||
| 		} | ||||
|  | ||||
| 		return "", imagePullResult.err.Error(), ErrImagePull | ||||
| 		msg, err := evalCRIPullErr(container, imagePullResult.err) | ||||
| 		return "", msg, err | ||||
| 	} | ||||
| 	m.podPullingTimeRecorder.RecordImageFinishedPulling(pod.UID) | ||||
| 	m.logIt(ref, v1.EventTypeNormal, events.PulledImage, logPrefix, fmt.Sprintf("Successfully pulled image %q in %v (%v including waiting)", | ||||
| @@ -174,6 +169,23 @@ func (m *imageManager) EnsureImageExists(ctx context.Context, pod *v1.Pod, conta | ||||
| 	return imagePullResult.imageRef, "", nil | ||||
| } | ||||
|  | ||||
| func evalCRIPullErr(container *v1.Container, err error) (errMsg string, errRes error) { | ||||
| 	// Error assertions via errors.Is is not supported by gRPC (remote runtime) errors right now. | ||||
| 	// See https://github.com/grpc/grpc-go/issues/3616 | ||||
| 	if err.Error() == crierrors.ErrRegistryUnavailable.Error() { | ||||
| 		errMsg = fmt.Sprintf("image pull failed for %s because the registry is unavailable.", container.Image) | ||||
| 		return errMsg, crierrors.ErrRegistryUnavailable | ||||
| 	} | ||||
|  | ||||
| 	if err.Error() == crierrors.ErrSignatureValidationFailed.Error() { | ||||
| 		errMsg = fmt.Sprintf("image pull failed for %s because the signature validation failed.", container.Image) | ||||
| 		return errMsg, crierrors.ErrSignatureValidationFailed | ||||
| 	} | ||||
|  | ||||
| 	// Fallback for no specific error | ||||
| 	return err.Error(), ErrImagePull | ||||
| } | ||||
|  | ||||
| // applyDefaultImageTag parses a docker image string, if it doesn't contain any tag or digest, | ||||
| // a default tag will be applied. | ||||
| func applyDefaultImageTag(image string) (string, error) { | ||||
|   | ||||
| @@ -29,6 +29,7 @@ import ( | ||||
| 	"k8s.io/apimachinery/pkg/types" | ||||
| 	"k8s.io/client-go/tools/record" | ||||
| 	"k8s.io/client-go/util/flowcontrol" | ||||
| 	crierrors "k8s.io/cri-api/pkg/errors" | ||||
| 	. "k8s.io/kubernetes/pkg/kubelet/container" | ||||
| 	ctest "k8s.io/kubernetes/pkg/kubelet/container/testing" | ||||
| 	testingclock "k8s.io/utils/clock/testing" | ||||
| @@ -413,3 +414,46 @@ func TestMaxParallelImagePullsLimit(t *testing.T) { | ||||
| 	wg.Wait() | ||||
| 	fakeRuntime.AssertCallCounts("PullImage", 7) | ||||
| } | ||||
|  | ||||
| func TestEvalCRIPullErr(t *testing.T) { | ||||
| 	t.Parallel() | ||||
| 	for _, tc := range []struct { | ||||
| 		name   string | ||||
| 		input  error | ||||
| 		assert func(string, error) | ||||
| 	}{ | ||||
| 		{ | ||||
| 			name:  "fallback error", | ||||
| 			input: errors.New("test"), | ||||
| 			assert: func(msg string, err error) { | ||||
| 				assert.ErrorIs(t, err, ErrImagePull) | ||||
| 				assert.Contains(t, msg, "test") | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name:  "registry is unavailable", | ||||
| 			input: crierrors.ErrRegistryUnavailable, | ||||
| 			assert: func(msg string, err error) { | ||||
| 				assert.ErrorIs(t, err, crierrors.ErrRegistryUnavailable) | ||||
| 				assert.Contains(t, msg, "registry is unavailable") | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name:  "signature is invalid", | ||||
| 			input: crierrors.ErrSignatureValidationFailed, | ||||
| 			assert: func(msg string, err error) { | ||||
| 				assert.ErrorIs(t, err, crierrors.ErrSignatureValidationFailed) | ||||
| 				assert.Contains(t, msg, "signature validation failed") | ||||
| 			}, | ||||
| 		}, | ||||
| 	} { | ||||
| 		testInput := tc.input | ||||
| 		testAssert := tc.assert | ||||
|  | ||||
| 		t.Run(tc.name, func(t *testing.T) { | ||||
| 			t.Parallel() | ||||
| 			msg, err := evalCRIPullErr(&v1.Container{}, testInput) | ||||
| 			testAssert(msg, err) | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -37,9 +37,6 @@ var ( | ||||
| 	// ErrImageNeverPull - Required Image is absent on host and PullPolicy is NeverPullImage | ||||
| 	ErrImageNeverPull = errors.New("ErrImageNeverPull") | ||||
|  | ||||
| 	// ErrRegistryUnavailable - Get http error when pulling image from registry | ||||
| 	ErrRegistryUnavailable = errors.New("RegistryUnavailable") | ||||
|  | ||||
| 	// ErrInvalidImageName - Unable to parse the image name. | ||||
| 	ErrInvalidImageName = errors.New("InvalidImageName") | ||||
| ) | ||||
|   | ||||
| @@ -17,10 +17,20 @@ limitations under the License. | ||||
| package errors | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
|  | ||||
| 	"google.golang.org/grpc/codes" | ||||
| 	"google.golang.org/grpc/status" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	// ErrRegistryUnavailable - Get http error on the PullImage RPC call. | ||||
| 	ErrRegistryUnavailable = errors.New("RegistryUnavailable") | ||||
|  | ||||
| 	// ErrSignatureValidationFailed - Unable to validate the image signature on the PullImage RPC call. | ||||
| 	ErrSignatureValidationFailed = errors.New("SignatureValidationFailed") | ||||
| ) | ||||
|  | ||||
| // IsNotFound returns a boolean indicating whether the error | ||||
| // is grpc not found error. | ||||
| // See https://github.com/grpc/grpc/blob/master/doc/statuscodes.md | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Kubernetes Prow Robot
					Kubernetes Prow Robot