mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-08 19:47:56 +00:00
Merge pull request #117717 from saschagrunert/invalid-signature-error
Add support for CRI `ErrSignatureValidationFailed`
This commit is contained in:
commit
af92da5cb7
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user