github.com/dean7474/operator-registry@v1.21.1-0.20220418203638-d4717f98c2e5/pkg/image/containerdregistry/options.go (about) 1 package containerdregistry 2 3 import ( 4 "crypto/x509" 5 "os" 6 "path/filepath" 7 "sync" 8 9 contentlocal "github.com/containerd/containerd/content/local" 10 "github.com/containerd/containerd/metadata" 11 "github.com/containerd/containerd/platforms" 12 "github.com/containerd/containerd/remotes" 13 specs "github.com/opencontainers/image-spec/specs-go/v1" 14 "github.com/sirupsen/logrus" 15 bolt "go.etcd.io/bbolt" 16 ) 17 18 type RegistryConfig struct { 19 Log *logrus.Entry 20 ResolverConfigDir string 21 DBPath string 22 CacheDir string 23 PreserveCache bool 24 SkipTLSVerify bool 25 PlainHTTP bool 26 Roots *x509.CertPool 27 } 28 29 func (r *RegistryConfig) apply(options []RegistryOption) { 30 for _, option := range options { 31 option(r) 32 } 33 } 34 35 func (r *RegistryConfig) complete() error { 36 if err := os.Mkdir(r.CacheDir, os.ModePerm); err != nil && !os.IsExist(err) { 37 return err 38 } 39 40 if r.DBPath == "" { 41 r.DBPath = filepath.Join(r.CacheDir, "metadata.db") 42 } 43 44 return nil 45 } 46 47 func defaultConfig() *RegistryConfig { 48 config := &RegistryConfig{ 49 Log: logrus.NewEntry(logrus.New()), 50 ResolverConfigDir: "", 51 CacheDir: "cache", 52 } 53 54 return config 55 } 56 57 // NewRegistry returns a new containerd Registry and a function to destroy it after use. 58 // The destroy function is safe to call more than once, but is a no-op after the first call. 59 func NewRegistry(options ...RegistryOption) (registry *Registry, err error) { 60 config := defaultConfig() 61 config.apply(options) 62 if err = config.complete(); err != nil { 63 return 64 } 65 66 cs, err := contentlocal.NewStore(config.CacheDir) 67 if err != nil { 68 return 69 } 70 71 var bdb *bolt.DB 72 bdb, err = bolt.Open(config.DBPath, 0644, nil) 73 if err != nil { 74 return 75 } 76 77 var once sync.Once 78 destroy := func() (destroyErr error) { 79 once.Do(func() { 80 if destroyErr = bdb.Close(); destroyErr != nil { 81 return 82 } 83 if config.PreserveCache { 84 return 85 } 86 87 destroyErr = os.RemoveAll(config.CacheDir) 88 }) 89 90 return 91 } 92 93 var resolver remotes.Resolver 94 resolver, err = NewResolver(config.ResolverConfigDir, config.SkipTLSVerify, config.PlainHTTP, config.Roots) 95 if err != nil { 96 return 97 } 98 99 registry = &Registry{ 100 Store: newStore(metadata.NewDB(bdb, cs, nil)), 101 destroy: destroy, 102 log: config.Log, 103 resolver: resolver, 104 platform: platforms.Ordered(platforms.DefaultSpec(), specs.Platform{ 105 OS: "linux", 106 Architecture: "amd64", 107 }), 108 } 109 return 110 } 111 112 type RegistryOption func(config *RegistryConfig) 113 114 func WithLog(log *logrus.Entry) RegistryOption { 115 return func(config *RegistryConfig) { 116 config.Log = log 117 } 118 } 119 120 func WithResolverConfigDir(path string) RegistryOption { 121 return func(config *RegistryConfig) { 122 config.ResolverConfigDir = path 123 } 124 } 125 126 func WithCacheDir(dir string) RegistryOption { 127 return func(config *RegistryConfig) { 128 config.CacheDir = dir 129 } 130 } 131 132 func WithRootCAs(pool *x509.CertPool) RegistryOption { 133 return func(config *RegistryConfig) { 134 config.Roots = pool 135 } 136 } 137 138 func PreserveCache(preserve bool) RegistryOption { 139 return func(config *RegistryConfig) { 140 config.PreserveCache = preserve 141 } 142 } 143 144 func SkipTLSVerify(skip bool) RegistryOption { 145 return func(config *RegistryConfig) { 146 config.SkipTLSVerify = skip 147 } 148 } 149 150 func WithPlainHTTP(insecure bool) RegistryOption { 151 return func(config *RegistryConfig) { 152 config.PlainHTTP = insecure 153 } 154 }