Skip to content

Commit 55c6c1d

Browse files
Dan Gerdesmeierknative-prow-robot
Dan Gerdesmeier
authored andcommitted
Add '.status.imageDigest' to Revision (knative#2197)
* Add '.status.imageDigest' to Revision This change moves image digest resolution from Deployment creation to Revision reconciliation, and introduces a new field on Revision status. This change preseves the option to list registries to skip in which case the imageDigest field will not be populated. When the imageDigest field is populated, it is used for Deployment creation. Fixes knative#2064 * Resolve comments * Update spec documentation and change Resolve interface * Update deploy test and add conformance test * Fix rebase test error and typo
1 parent 5b1e03a commit 55c6c1d

File tree

11 files changed

+307
-182
lines changed

11 files changed

+307
-182
lines changed

docs/spec/spec.md

+4
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,10 @@ status:
304304
# revision. Typically, the name will be the same as the name of the
305305
# revision.
306306
serviceName: myservice-a1e34
307+
308+
# imageDigest: The imageDigest is the spec.container.image field resolved
309+
# to a particular digest at revision creation.
310+
imageDigest: gcr.io/my-project/...@sha256:60ab5...
307311
```
308312
309313

pkg/apis/serving/v1alpha1/revision_types.go

+8
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,14 @@ type RevisionStatus struct {
224224
// based on the revision url template specified in the controller's config.
225225
// +optional
226226
LogURL string `json:"logUrl,omitempty"`
227+
228+
// ImageDigest holds the resolved digest for the image specified
229+
// within .Spec.Container.Image. The digest is resolved during the creation
230+
// of Revision. This field holds the digest value regardless of whether
231+
// a tag or digest was originally specified in the Container object. It
232+
// may be empty if the image comes from a registry listed to skip resolution.
233+
// +optional
234+
ImageDigest string `json:"imageDigest,omitempty"`
227235
}
228236

229237
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

pkg/reconciler/v1alpha1/revision/cruds.go

-10
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ package revision
1818

1919
import (
2020
"context"
21-
"fmt"
2221

2322
"github.com/google/go-cmp/cmp"
2423

@@ -28,14 +27,12 @@ import (
2827
"github.com/knative/serving/pkg/apis/serving/v1alpha1"
2928
"github.com/knative/serving/pkg/reconciler/v1alpha1/revision/config"
3029
"github.com/knative/serving/pkg/reconciler/v1alpha1/revision/resources"
31-
"go.uber.org/zap"
3230
appsv1 "k8s.io/api/apps/v1"
3331
corev1 "k8s.io/api/core/v1"
3432
"k8s.io/apimachinery/pkg/api/equality"
3533
)
3634

3735
func (c *Reconciler) createDeployment(ctx context.Context, rev *v1alpha1.Revision) (*appsv1.Deployment, error) {
38-
logger := logging.FromContext(ctx)
3936
cfgs := config.FromContext(ctx)
4037

4138
deployment := resources.MakeDeployment(
@@ -47,13 +44,6 @@ func (c *Reconciler) createDeployment(ctx context.Context, rev *v1alpha1.Revisio
4744
cfgs.Controller,
4845
)
4946

50-
// Resolve tag image references to digests.
51-
if err := c.resolver.Resolve(deployment, cfgs.Controller.RegistriesSkippingTagResolving); err != nil {
52-
logger.Error("Error resolving deployment", zap.Error(err))
53-
rev.Status.MarkContainerMissing(err.Error())
54-
return nil, fmt.Errorf("Error resolving container to digest: %v", err)
55-
}
56-
5747
return c.KubeClientSet.AppsV1().Deployments(deployment.Namespace).Create(deployment)
5848
}
5949

pkg/reconciler/v1alpha1/revision/queueing_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"testing"
2121
"time"
2222

23+
"github.com/google/go-containerregistry/pkg/authn/k8schain"
2324
fakecachingclientset "github.com/knative/caching/pkg/client/clientset/versioned/fake"
2425
cachinginformers "github.com/knative/caching/pkg/client/informers/externalversions"
2526
"github.com/knative/pkg/apis/duck"
@@ -34,7 +35,6 @@ import (
3435
rclr "github.com/knative/serving/pkg/reconciler"
3536
"github.com/knative/serving/pkg/reconciler/v1alpha1/revision/config"
3637
"github.com/knative/serving/pkg/system"
37-
appsv1 "k8s.io/api/apps/v1"
3838
corev1 "k8s.io/api/core/v1"
3939
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
4040
"k8s.io/apimachinery/pkg/runtime"
@@ -47,8 +47,8 @@ import (
4747

4848
type nopResolver struct{}
4949

50-
func (r *nopResolver) Resolve(*appsv1.Deployment, map[string]struct{}) error {
51-
return nil
50+
func (r *nopResolver) Resolve(_ string, _ k8schain.Options, _ map[string]struct{}) (string, error) {
51+
return "", nil
5252
}
5353

5454
const (

pkg/reconciler/v1alpha1/revision/resolve.go

+24-33
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import (
2424
"github.com/google/go-containerregistry/pkg/name"
2525
"github.com/google/go-containerregistry/pkg/v1/remote"
2626

27-
appsv1 "k8s.io/api/apps/v1"
2827
"k8s.io/client-go/kubernetes"
2928
)
3029

@@ -35,44 +34,36 @@ type digestResolver struct {
3534

3635
// Resolve resolves the image references that use tags to digests.
3736
func (r *digestResolver) Resolve(
38-
deploy *appsv1.Deployment,
37+
image string,
38+
opt k8schain.Options,
3939
registriesToSkip map[string]struct{},
40-
) error {
41-
pod := deploy.Spec.Template.Spec
42-
opt := k8schain.Options{
43-
Namespace: deploy.Namespace,
44-
ServiceAccountName: pod.ServiceAccountName,
45-
// ImagePullSecrets: Not possible via RevisionSpec, since we
46-
// don't expose such a field.
47-
}
40+
) (string, error) {
4841
kc, err := k8schain.New(r.client, opt)
4942
if err != nil {
50-
return err
43+
return "", err
5144
}
5245

53-
for i := range pod.Containers {
54-
if _, err := name.NewDigest(pod.Containers[i].Image, name.WeakValidation); err == nil {
55-
// Already a digest
56-
continue
57-
}
58-
tag, err := name.NewTag(pod.Containers[i].Image, name.WeakValidation)
59-
if err != nil {
60-
return err
61-
}
46+
if _, err := name.NewDigest(image, name.WeakValidation); err == nil {
47+
// Already a digest
48+
return image, nil
49+
}
6250

63-
if _, ok := registriesToSkip[tag.Registry.RegistryStr()]; ok {
64-
continue
65-
}
51+
tag, err := name.NewTag(image, name.WeakValidation)
52+
if err != nil {
53+
return "", err
54+
}
6655

67-
img, err := remote.Image(tag, remote.WithTransport(r.transport), remote.WithAuthFromKeychain(kc))
68-
if err != nil {
69-
return err
70-
}
71-
digest, err := img.Digest()
72-
if err != nil {
73-
return err
74-
}
75-
pod.Containers[i].Image = fmt.Sprintf("%s@%s", tag.Repository.String(), digest)
56+
if _, ok := registriesToSkip[tag.Registry.RegistryStr()]; ok {
57+
return "", nil
58+
}
59+
60+
img, err := remote.Image(tag, remote.WithTransport(r.transport), remote.WithAuthFromKeychain(kc))
61+
if err != nil {
62+
return "", err
63+
}
64+
digest, err := img.Digest()
65+
if err != nil {
66+
return "", err
7667
}
77-
return nil
68+
return fmt.Sprintf("%s@%s", tag.Repository.String(), digest), nil
7869
}

0 commit comments

Comments
 (0)