Skip to content

Commit a5f3ef3

Browse files
committed
refactor(image): add image reference interface
- Add image.Reference interface and SimpleReference implementation as parameters of image.Registry methods (in place of strings) - Refactor image.Registry tests into suite - Add registry implementation notes - Remove buildah from builds (Note: should be re-added once it's complete)
1 parent f666f9d commit a5f3ef3

File tree

45 files changed

+392
-1150
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+392
-1150
lines changed

.gitignore

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -454,5 +454,10 @@ bin
454454
# Ignore vscode
455455
.vscode
456456

457-
# Igore apprclient meta
457+
# Ignore apprclient meta
458458
pkg/apprclient/openapi/git_push.sh
459+
460+
# Never ignore testdata
461+
!pkg/**/testdata/**
462+
!test/**testdata/**
463+

go.mod

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,40 +3,50 @@ module github.com/operator-framework/operator-registry
33
go 1.13
44

55
require (
6+
github.com/Microsoft/hcsshim v0.8.7 // indirect
67
github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6
78
github.com/blang/semver v3.5.0+incompatible
89
github.com/containerd/containerd v1.3.2
910
github.com/containerd/continuity v0.0.0-20200228182428-0f16d7a0959c // indirect
10-
github.com/containers/buildah v1.14.3
1111
github.com/docker/cli v0.0.0-20200130152716-5d0cf8839492
1212
github.com/docker/distribution v2.7.1+incompatible
1313
github.com/docker/docker v1.4.2-0.20200203170920-46ec8731fbce
14+
github.com/docker/docker-credential-helpers v0.6.3 // indirect
1415
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect
16+
github.com/docker/go-metrics v0.0.1 // indirect
17+
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 // indirect
1518
github.com/ghodss/yaml v1.0.0
1619
github.com/gogo/protobuf v1.3.1 // indirect
1720
github.com/golang-migrate/migrate/v4 v4.6.2
1821
github.com/golang/mock v1.3.1
1922
github.com/golang/protobuf v1.3.2
23+
github.com/google/go-cmp v0.4.0 // indirect
24+
github.com/gorilla/mux v1.7.4 // indirect
2025
github.com/grpc-ecosystem/grpc-health-probe v0.2.1-0.20181220223928-2bf0a5b182db
26+
github.com/imdario/mergo v0.3.8 // indirect
2127
github.com/mattn/go-sqlite3 v1.10.0
2228
github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2
2329
github.com/morikuni/aec v1.0.0 // indirect
2430
github.com/onsi/ginkgo v1.12.0
2531
github.com/onsi/gomega v1.9.0
2632
github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6
33+
github.com/opencontainers/runc v1.0.0-rc9 // indirect
34+
github.com/opencontainers/runtime-spec v0.1.2-0.20190618234442-a950415649c7 // indirect
2735
github.com/operator-framework/api v0.1.1
2836
github.com/otiai10/copy v1.0.2
2937
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2
3038
github.com/pkg/errors v0.9.1
3139
github.com/sirupsen/logrus v1.4.2
3240
github.com/spf13/cobra v0.0.6
3341
github.com/stretchr/testify v1.5.1
34-
go.etcd.io/bbolt v1.3.3
42+
go.etcd.io/bbolt v1.3.4
43+
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975 // indirect
3544
golang.org/x/mod v0.2.0
3645
golang.org/x/net v0.0.0-20191028085509-fe3aa8a45271
3746
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45
3847
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e // indirect
3948
google.golang.org/grpc v1.24.0
49+
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
4050
gopkg.in/yaml.v2 v2.2.8
4151
k8s.io/api v0.17.3
4252
k8s.io/apiextensions-apiserver v0.17.3

go.sum

Lines changed: 34 additions & 76 deletions
Large diffs are not rendered by default.

pkg/image/buildahregistry/options.go renamed to pkg/image/buildahregistry/_options.go

Lines changed: 31 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,15 @@
1+
// +build ignore
12
package buildahregistry
23

34
import (
4-
"github.com/containers/storage"
5-
"github.com/containers/storage/pkg/idtools"
65
"io/ioutil"
76
"os"
87
"path"
98
"path/filepath"
109
"sync"
1110

12-
//"sync"
13-
//
14-
//contentlocal "github.com/containerd/containerd/content/local"
15-
//"github.com/containerd/containerd/metadata"
16-
//"github.com/containerd/containerd/platforms"
11+
"github.com/containers/storage"
1712
"github.com/sirupsen/logrus"
18-
//bolt "go.etcd.io/bbolt"
1913
)
2014

2115
type RegistryConfig struct {
@@ -55,53 +49,47 @@ func defaultConfig() *RegistryConfig {
5549
return config
5650
}
5751

58-
func NewRegistry(options ...RegistryOption) (*Registry, error) {
52+
func NewRegistry(options ...RegistryOption) (registry *Registry, destroy func() error, err error) {
5953
config := defaultConfig()
6054
config.apply(options)
61-
if err := config.complete(); err != nil {
62-
return nil, err
55+
if err = config.complete(); err != nil {
56+
return
6357
}
6458

65-
var (
66-
once sync.Once
67-
closed bool
68-
)
69-
closeFunc := func() error {
70-
defer func() {
71-
once.Do(func() {
72-
closed = true
73-
})
74-
}()
75-
if closed {
76-
// Already closed, no-op
77-
return nil
78-
}
79-
80-
if config.PreserveCache {
81-
return nil
82-
}
83-
return os.RemoveAll(config.CacheDir)
59+
var once sync.Once
60+
destroy = func() (destroyErr error) {
61+
once.Do(func() {
62+
if config.PreserveCache {
63+
return
64+
}
65+
66+
destroyErr = os.RemoveAll(config.CacheDir)
67+
})
68+
69+
return
8470
}
8571

8672
// TODO: at this point we've overwritten all the defaults, may as well not use this
87-
storeOpts, err := storage.DefaultStoreOptionsAutoDetectUID()
73+
var storeOpts storage.StoreOptions
74+
storeOpts, err = storage.DefaultStoreOptionsAutoDetectUID()
8875
if err != nil {
89-
return nil, err
76+
return
9077
}
9178
storeOpts.RootlessStoragePath = config.CacheDir
9279
storeOpts.RunRoot = config.CacheDir
9380
storeOpts.GraphRoot = config.CacheDir
9481
storeOpts.GraphDriverName = "vfs"
95-
storeOpts.UIDMap = []idtools.IDMap{
96-
{ContainerID: 0, HostID: os.Getuid()},
97-
}
98-
storeOpts.GIDMap = []idtools.IDMap{
99-
{ContainerID: 0, HostID: os.Getgid()},
100-
}
101-
102-
store, err := storage.GetStore(storeOpts)
82+
// storeOpts.UIDMap = []idtools.IDMap{
83+
// {ContainerID: 0, HostID: os.Getuid()},
84+
// }
85+
// storeOpts.GIDMap = []idtools.IDMap{
86+
// {ContainerID: 0, HostID: os.Getgid()},
87+
// }
88+
89+
var store storage.Store
90+
store, err = storage.GetStore(storeOpts)
10391
if err != nil {
104-
return nil, err
92+
return
10593
}
10694

10795
// TODO: probably don't want the signature policy to be here
@@ -122,13 +110,12 @@ func NewRegistry(options ...RegistryOption) (*Registry, error) {
122110
}
123111
`), os.ModePerm)
124112

125-
r := &Registry{
113+
registry = &Registry{
126114
Store: store,
127115
CacheDir: config.CacheDir,
128116
log: config.Log,
129-
close: closeFunc,
130117
}
131-
return r, nil
118+
return
132119
}
133120

134121
type RegistryOption func(config *RegistryConfig)
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// +build ignore
2+
package buildahregistry
3+
4+
import (
5+
"context"
6+
"path"
7+
8+
"github.com/containers/buildah"
9+
"github.com/containers/image/v5/types"
10+
"github.com/containers/storage"
11+
"github.com/sirupsen/logrus"
12+
13+
"github.com/operator-framework/operator-registry/pkg/image"
14+
)
15+
16+
// Registry enables manipulation of images via containerd modules.
17+
// TODO: Finish buildah Registry implementation.
18+
type Registry struct {
19+
storage.Store
20+
21+
CacheDir string
22+
SkipTLS bool
23+
24+
log *logrus.Entry
25+
}
26+
27+
var _ image.Registry = &Registry{}
28+
29+
// Pull fetches and stores an image by reference.
30+
func (r *Registry) Pull(ctx context.Context, ref image.Reference) error {
31+
img, err := buildah.Pull(ctx, ref.String(), buildah.PullOptions{
32+
SignaturePolicyPath: path.Join(r.CacheDir, "policy.json"),
33+
ReportWriter: r.log.Writer(),
34+
Store: r.Store,
35+
SystemContext: &types.SystemContext{
36+
// TODO: auth stuff goes here too
37+
// TODO: if we're okay with buildah's cobra args, there's a function to build this from the standard args
38+
SignaturePolicyPath: path.Join(r.CacheDir, "policy.json"),
39+
OCIInsecureSkipTLSVerify: r.SkipTLS,
40+
DockerInsecureSkipTLSVerify: types.NewOptionalBool(r.SkipTLS),
41+
},
42+
BlobDirectory: r.CacheDir,
43+
AllTags: false,
44+
RemoveSignatures: false,
45+
MaxRetries: 0,
46+
RetryDelay: 0,
47+
})
48+
49+
r.log.Info(img)
50+
return err
51+
}
52+
53+
// Unpack writes the unpackaged content of an image to a directory.
54+
// If the referenced image does not exist in the registry, an error is returned.
55+
func (r *Registry) Unpack(ctx context.Context, ref image.Reference, dir string) error {
56+
img, err := r.Image(ref.String())
57+
if err != nil {
58+
return err
59+
}
60+
61+
r.log.Infof("img: %v", img)
62+
63+
return nil
64+
}

pkg/image/buildahregistry/notes.md

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# Daemonless Notes
2+
3+
## Goal
4+
5+
Drive the following stories:
6+
7+
- [OLM-1666](https://issues.redhat.com/browse/OLM-1666)
8+
- [OLM-1679](https://issues.redhat.com/browse/OLM-167://issues.redhat.com/browse/OLM-1679)
9+
10+
TL;DR, we want a supportable way to pull and unpack container images:
11+
12+
- in an unprivileged containerized environment (CI constraint)
13+
- without relying on a external tool (docker, podman, buildah, etc.)
14+
15+
## How does oc unpack images?
16+
17+
The `oc` client needs to pull and unpack images. So we thought it would be useful to see how it achieves this and if we can make use of it.
18+
19+
A quick check of the [extract command](https://github.com/openshift/oc/blob/master/pkg/cli/image/extract/extract.go) reveals several imports relating to images:
20+
21+
```go
22+
import (
23+
//...
24+
"github.com/docker/distribution"
25+
dockerarchive "github.com/docker/docker/pkg/archive"
26+
digest "github.com/opencontainers/go-digest"
27+
//...
28+
"github.com/openshift/library-go/pkg/image/dockerv1client"
29+
"github.com/openshift/library-go/pkg/image/registryclient"
30+
"github.com/openshift/oc/pkg/cli/image/archive"
31+
"github.com/openshift/oc/pkg/cli/image/imagesource"
32+
imagemanifest "github.com/openshift/oc/pkg/cli/image/manifest"
33+
"github.com/openshift/oc/pkg/cli/image/workqueue"
34+
)
35+
```
36+
37+
Right off the bat we can see some direct use of `docker` packages.
38+
39+
Also interesting are a set of private [utility functions for modifying tar headers](https://github.com/openshift/oc/blob/e97def4832ab6489a4237633652ac049f09e685b/pkg/cli/image/extract/extract.go#L554) as well as some for [pulling, walking, and unpacking image layers](https://github.com/openshift/oc/blob/e97def4832ab6489a4237633652ac049f09e685b/pkg/cli/image/extract/extract.go#L326).
40+
41+
The `opencontainers` module is imported for go-digest type.
42+
43+
There are also some OpenShift-specific library packages pulled in. The `openshift/library-go` module provides clients for docker and OpenShift registries as well as some helper types for expressing image manifests for each registry. It also contains various types and utilities for parsing image references.
44+
45+
Some layer unpacking functions [are copied directly from docker](https://github.com/openshift/oc/blob/master/pkg/cli/image/archive/archive.go#L82).
46+
47+
`oc` does support [referencing images from non-registry sources](https://github.com/openshift/oc/blob/e97def4832ab6489a4237633652ac049f09e685b/pkg/cli/image/imagesource/options.go#L22) such as `file` and `s3`, but it's questionable whether we need this in `opm`.
48+
49+
`containers/image`, an upstream module for manipulating images, is used in [image signature verification](https://github.com/openshift/oc/blob/9fd38891f0/pkg/cli/admin/verifyimagesignature/verify-signature.go), though I can't find any indication it's being used for signing in `oc`.
50+
51+
## Options
52+
53+
In lieu of importing `oc` or `openshift/library-go` as a dependency, we took a look at several upstream options.
54+
55+
### Containers Packages
56+
57+
- Serious RedHat presence
58+
- Can be quickly patched by involded RedHatters
59+
- Interfaces feel fine-grained, require glue
60+
61+
### Buildah Packages
62+
63+
[Buildah](https://github.com/containers/buildah) builds on the core `containers` modules. Pulling seems to require some special `chmod`, and may require more investigation.
64+
65+
### Containerd Packages
66+
67+
- No serious RedHat presence
68+
- May need staging repo or in-tree patches for CVEs
69+
- Implements CRI (https://kubernetes.io/docs/setup/production-environment/container-runtimes/#containerd)
70+
- Widespread use/adoption
71+
- Relatively simple interfaces
72+
- Already implemented and working in an [opm branch](https://github.com/njhale/operator-registry/blob/daemonless/pkg/image/containerdregistry/registry.go)
73+
74+
## CRI-O
75+
76+
[CRI-O](https://github.com/cri-o/cri-o/blob/master/server/image_pull.go) needs to pull images and set up container filesystems as well. We haven't looked at this closely yet.

pkg/image/buildahregistry/registry.go

Lines changed: 0 additions & 57 deletions
This file was deleted.

0 commit comments

Comments
 (0)