Skip to content
This repository has been archived by the owner on Sep 2, 2024. It is now read-only.

Commit

Permalink
Merge pull request #18 from dweomer/fix/2/pull-from-private
Browse files Browse the repository at this point in the history
pull: leverage local credentials
  • Loading branch information
dweomer authored Feb 10, 2021
2 parents e4e0313 + 04c4a9c commit 21fae46
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 30 deletions.
17 changes: 16 additions & 1 deletion pkg/client/image/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"io"
"os"

"github.com/containerd/containerd/platforms"
"github.com/docker/distribution/reference"
"github.com/pkg/errors"
imagesv1 "github.com/rancher/kim/pkg/apis/services/images/v1alpha1"
Expand All @@ -18,6 +19,7 @@ import (

type Pull struct {
Platform string `usage:"Set platform if server is multi-platform capable"`
Cri bool `usage:"Use the CRI backend to pull instead of containerd"`
}

func (s *Pull) Do(ctx context.Context, k8s *client.Interface, image string) error {
Expand Down Expand Up @@ -56,9 +58,22 @@ func (s *Pull) Do(ctx context.Context, k8s *client.Interface, image string) erro
eg.Go(func() error {
req := &imagesv1.ImagePullRequest{
Image: &criv1.ImageSpec{
Image: image,
Image: image,
Annotations: map[string]string{},
},
}
if s.Platform != "" {
platform, err := platforms.Parse(s.Platform)
switch {
case err != nil:
logrus.Warnf("Failed to parse platform: %v", err)
default:
req.Image.Annotations["images.cattle.io/pull-platform"] = platforms.Format(platform)
}
}
if s.Cri {
req.Image.Annotations["images.cattle.io/pull-backend"] = "cri"
}
keyring := credentialprovider.NewDockerKeyring()
if auth, ok := keyring.Lookup(image); ok {
req.Auth = &criv1.AuthConfig{
Expand Down
2 changes: 1 addition & 1 deletion pkg/client/image/tag.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func (s *Tag) Do(ctx context.Context, k8s *client.Interface, image string, tags
if err != nil {
return err
}
logrus.Debugf("%#v", res)
logrus.Debugf("image-tag: %#v", res)
return nil
})
}
28 changes: 26 additions & 2 deletions pkg/server/images/images.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
package images

import (
"fmt"
"net/http"
"sync"

criv1 "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"

"github.com/containerd/containerd"
"github.com/containerd/containerd/remotes"
"github.com/containerd/containerd/remotes/docker"
buildkit "github.com/moby/buildkit/client"
imagesv1 "github.com/rancher/kim/pkg/apis/services/images/v1alpha1"
"github.com/rancher/kim/pkg/auth"
"github.com/rancher/kim/pkg/client"
"github.com/rancher/kim/pkg/version"
"github.com/sirupsen/logrus"
criv1 "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
)

var _ imagesv1.ImagesServer = &Server{}
Expand Down Expand Up @@ -46,3 +51,22 @@ func (s *Server) Close() {
}
}
}

func Resolver(authConfig *criv1.AuthConfig, statusTracker docker.StatusTracker) remotes.Resolver {
authorizer := docker.NewDockerAuthorizer(
docker.WithAuthClient(http.DefaultClient),
docker.WithAuthCreds(func(host string) (string, string, error) {
return auth.Parse(authConfig, host)
}),
docker.WithAuthHeader(http.Header{
"User-Agent": []string{fmt.Sprintf("rancher-kim/%s", version.Version)},
}),
)
return docker.NewResolver(docker.ResolverOptions{
Tracker: statusTracker,
Hosts: docker.ConfigureDefaultRegistries(
docker.WithAuthorizer(authorizer),
),
})

}
46 changes: 41 additions & 5 deletions pkg/server/images/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,66 @@ package images

import (
"context"
"fmt"
"time"

"github.com/containerd/containerd"
"github.com/containerd/containerd/namespaces"
"github.com/containerd/containerd/platforms"
imagesv1 "github.com/rancher/kim/pkg/apis/services/images/v1alpha1"
"github.com/rancher/kim/pkg/version"
"github.com/sirupsen/logrus"
criv1 "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
)

// Pull server-side impl
func (s *Server) Pull(ctx context.Context, req *imagesv1.ImagePullRequest) (*imagesv1.ImagePullResponse, error) {
// TODO implement pull using native containerd with resolver as is done with push
res, err := s.ImageService().PullImage(ctx, &criv1.PullImageRequest{
Image: req.Image,
})
logrus.Debugf("image-pull: %#v", req)
var err error
if req.Image.Annotations != nil && req.Image.Annotations["images.cattle.io/pull-backend"] == "cri" {
err = s.pullCRI(ctx, req.Image, req.Auth)
} else {
err = s.pullCTD(ctx, req.Image, req.Auth)
}
if err != nil {
return nil, err
}
return &imagesv1.ImagePullResponse{
Image: res.ImageRef,
Image: req.Image.Image,
}, nil
}

// pullCTD attempts to pull via containerd directly
func (s *Server) pullCTD(ctx context.Context, image *criv1.ImageSpec, auth *criv1.AuthConfig) error {
ctx = namespaces.WithNamespace(ctx, "k8s.io")
resolver := Resolver(auth, nil)
platform := platforms.DefaultString()
if image.Annotations != nil {
platform = image.Annotations["images.cattle.io/pull-platform"]
}
_, err := s.Containerd.Pull(ctx, image.Image,
containerd.WithPullUnpack,
containerd.WithSchema1Conversion,
containerd.WithPullLabel("io.cattle.images/client", fmt.Sprintf("kim/%s", version.Version)),
containerd.WithResolver(resolver),
containerd.WithPlatform(platform),
)
return err
}

// pullCRI attempts to pull via CRI
func (s *Server) pullCRI(ctx context.Context, image *criv1.ImageSpec, auth *criv1.AuthConfig) error {
logrus.Debugf("image-pull-cri: %#v", image)
_, err := s.ImageService().PullImage(ctx, &criv1.PullImageRequest{
Auth: auth,
Image: image,
})
return err
}

// PullProgress server-side impl
func (s *Server) PullProgress(req *imagesv1.ImageProgressRequest, srv imagesv1.Images_PullProgressServer) error {
logrus.Debugf("image-pull-progress: %#v", req)
ctx := namespaces.WithNamespace(srv.Context(), "k8s.io")

for {
Expand Down
24 changes: 3 additions & 21 deletions pkg/server/images/push.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ package images

import (
"context"
"fmt"
"net/http"
"time"

"github.com/containerd/containerd"
Expand All @@ -13,9 +11,7 @@ import (
"github.com/containerd/containerd/remotes/docker"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
imagesv1 "github.com/rancher/kim/pkg/apis/services/images/v1alpha1"
"github.com/rancher/kim/pkg/auth"
"github.com/rancher/kim/pkg/progress"
"github.com/rancher/kim/pkg/version"
"github.com/sirupsen/logrus"
)

Expand All @@ -24,28 +20,14 @@ var (
)

// Push server-side impl
func (s *Server) Push(ctx context.Context, request *imagesv1.ImagePushRequest) (*imagesv1.ImagePushResponse, error) {
func (s *Server) Push(ctx context.Context, req *imagesv1.ImagePushRequest) (*imagesv1.ImagePushResponse, error) {
ctx = namespaces.WithNamespace(ctx, "k8s.io")
img, err := s.Containerd.ImageService().Get(ctx, request.Image.Image)
img, err := s.Containerd.ImageService().Get(ctx, req.Image.Image)
if err != nil {
return nil, err
}

authorizer := docker.NewDockerAuthorizer(
docker.WithAuthClient(http.DefaultClient),
docker.WithAuthCreds(func(host string) (string, string, error) {
return auth.Parse(request.Auth, host)
}),
docker.WithAuthHeader(http.Header{
"User-Agent": []string{fmt.Sprintf("rancher-kim/%s", version.Version)},
}),
)
resolver := docker.NewResolver(docker.ResolverOptions{
Tracker: PushTracker,
Hosts: docker.ConfigureDefaultRegistries(
docker.WithAuthorizer(authorizer),
),
})
resolver := Resolver(req.Auth, PushTracker)
tracker := progress.NewTracker(ctx, PushTracker)
s.pushJobs.Store(img.Name, tracker)
handler := images.HandlerFunc(func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
Expand Down

0 comments on commit 21fae46

Please sign in to comment.