提交 4cc3990c 编写于 作者: O openeuler-ci-bot 提交者: Gitee

!70 exporter: refactor exporter

Merge pull request !70 from holyfei/master
......@@ -495,6 +495,7 @@ func (b *Builder) export(imageID string) error {
Ctx: b.ctx,
SystemContext: image.GetSystemContext(),
ReportWriter: b.cliLog,
ExportID: b.buildID,
}
if exErr := exporter.Export(imageID, o, exOpts, b.localStore); exErr != nil {
b.Logger().Errorf("Image %s output to %s failed with: %v", imageID, o, exErr)
......
......@@ -40,6 +40,7 @@ type saveOptions struct {
store store.Store
imageName string
imageID string
saveID string
runDir string
output string
imageInfo string
......@@ -130,6 +131,7 @@ func (b *Backend) preSave(req *pb.SaveRequest) (*saveOptions, error) {
pipeWrapper: pipeWrapper,
imageName: imageName,
imageID: imageID,
saveID: req.GetSaveID(),
store: localStore,
runDir: runDir,
output: output,
......@@ -167,6 +169,7 @@ func exportHandler(ctx context.Context, opts *saveOptions, cliLogger *logger.Log
SystemContext: image.GetSystemContext(),
Ctx: ctx,
ReportWriter: cliLogger,
ExportID: opts.saveID,
}
if err := exporter.Export(opts.imageID, opts.output, exOpts, opts.store); err != nil {
......
......@@ -50,29 +50,31 @@ const (
// ExportOptions is a struct for exporter
type ExportOptions struct {
SystemContext *types.SystemContext
ExportID string
ManifestType string
Ctx context.Context
ReportWriter io.Writer
ManifestType string
}
// Export export an archive to the client
func Export(src, destSpec string, iopts ExportOptions, localStore store.Store) error {
eLog := logrus.WithField(util.LogKeySessionID, iopts.Ctx.Value(util.LogFieldKey(util.LogKeySessionID)))
func Export(src, destSpec string, opts ExportOptions, localStore store.Store) error {
eLog := logrus.WithField(util.LogKeySessionID, opts.Ctx.Value(util.LogFieldKey(util.LogKeySessionID)))
if destSpec == "" {
return nil
}
epter, err := parseExporter(src, destSpec, localStore)
epter, err := parseExporter(opts.ExportID, src, destSpec, localStore)
if err != nil {
return err
}
defer epter.Remove(opts.ExportID)
options := newCopyOptions(iopts)
options := newCopyOptions(opts)
policyContext, err := newPolicyContext(iopts.SystemContext)
policyContext, err := newPolicyContext(opts.SystemContext)
if err != nil {
return err
}
ref, digest, err := export(iopts.Ctx, epter, policyContext, options)
ref, digest, err := export(opts, epter, policyContext, options)
if err != nil {
return errors.Errorf("export image from %s to %s failed, got error: %s", src, destSpec, err)
}
......@@ -84,7 +86,7 @@ func Export(src, destSpec string, iopts ExportOptions, localStore store.Store) e
return nil
}
func export(ctx context.Context, e Exporter, policyContext *signature.PolicyContext, opts *cp.Options) (reference.Canonical, digest.Digest, error) {
func export(exOpts ExportOptions, e Exporter, policyContext *signature.PolicyContext, cpOpts *cp.Options) (reference.Canonical, digest.Digest, error) {
var (
err error
ref reference.Canonical
......@@ -100,8 +102,11 @@ func export(ctx context.Context, e Exporter, policyContext *signature.PolicyCont
}
}()
destRef, srcRef := e.GetDestRef(), e.GetSrcRef()
if manifestBytes, err = cp.Image(ctx, policyContext, destRef, srcRef, opts); err != nil {
destRef, srcRef := e.GetDestRef(exOpts.ExportID), e.GetSrcRef(exOpts.ExportID)
if destRef == nil || srcRef == nil {
return nil, "", errors.Wrapf(err, "get dest or src reference by export ID %v failed", exOpts.ExportID)
}
if manifestBytes, err = cp.Image(exOpts.Ctx, policyContext, destRef, srcRef, cpOpts); err != nil {
return nil, "", errors.Wrap(err, "copying layers and metadata failed")
}
if manifestDigest, err = manifest.Digest(manifestBytes); err != nil {
......@@ -117,7 +122,7 @@ func export(ctx context.Context, e Exporter, policyContext *signature.PolicyCont
}
// parseExporter parses an exporter instance and inits it with the src and dest reference.
func parseExporter(src, destSpec string, localStore store.Store) (Exporter, error) {
func parseExporter(exportID, src, destSpec string, localStore store.Store) (Exporter, error) {
const partsNum = 2
// 1. parse exporter
parts := strings.SplitN(destSpec, ":", partsNum)
......@@ -146,7 +151,7 @@ func parseExporter(src, destSpec string, localStore store.Store) (Exporter, erro
}
// 4. init exporter with src reference and dest reference
ept.Init(srcReference, destReference)
ept.Init(exportID, srcReference, destReference)
return ept, nil
}
......
......@@ -15,6 +15,8 @@
package archive
import (
"sync"
"github.com/containers/image/v5/types"
"isula.org/isula-build/exporter"
......@@ -25,24 +27,51 @@ func init() {
}
type dockerArchiveExporter struct {
exporter.Bus
items map[string]exporter.Bus
sync.RWMutex
}
var _dockerArchiveExporter = dockerArchiveExporter{}
var _dockerArchiveExporter = dockerArchiveExporter{
items: make(map[string]exporter.Bus),
}
func (d *dockerArchiveExporter) Name() string {
return "docker-archive"
}
func (d *dockerArchiveExporter) Init(src, dest types.ImageReference) {
d.SrcRef = src
d.DestRef = dest
func (d *dockerArchiveExporter) Init(exportID string, src, dest types.ImageReference) {
d.Lock()
d.items[exportID] = exporter.Bus{
SrcRef: src,
DestRef: dest,
}
d.Unlock()
}
func (d *dockerArchiveExporter) GetSrcRef(exportID string) types.ImageReference {
d.RLock()
defer d.RUnlock()
if _, ok := d.items[exportID]; ok {
return d.items[exportID].SrcRef
}
return nil
}
func (d *dockerArchiveExporter) GetSrcRef() types.ImageReference {
return d.SrcRef
func (d *dockerArchiveExporter) GetDestRef(exportID string) types.ImageReference {
d.RLock()
defer d.RUnlock()
if _, ok := d.items[exportID]; ok {
return d.items[exportID].DestRef
}
return nil
}
func (d *dockerArchiveExporter) GetDestRef() types.ImageReference {
return d.DestRef
func (d *dockerArchiveExporter) Remove(exportID string) {
d.Lock()
delete(d.items, exportID)
d.Unlock()
}
......@@ -15,6 +15,8 @@
package daemon
import (
"sync"
"github.com/containers/image/v5/types"
"isula.org/isula-build/exporter"
......@@ -25,24 +27,51 @@ func init() {
}
type dockerDaemonExporter struct {
exporter.Bus
items map[string]exporter.Bus
sync.RWMutex
}
var _dockerDaemonExporter = dockerDaemonExporter{}
var _dockerDaemonExporter = dockerDaemonExporter{
items: make(map[string]exporter.Bus),
}
func (d *dockerDaemonExporter) Name() string {
return "docker-daemon"
}
func (d *dockerDaemonExporter) Init(src, dest types.ImageReference) {
d.SrcRef = src
d.DestRef = dest
func (d *dockerDaemonExporter) Init(exportID string, src, dest types.ImageReference) {
d.Lock()
d.items[exportID] = exporter.Bus{
SrcRef: src,
DestRef: dest,
}
d.Unlock()
}
func (d *dockerDaemonExporter) GetSrcRef(exportID string) types.ImageReference {
d.RLock()
defer d.RUnlock()
if _, ok := d.items[exportID]; ok {
return d.items[exportID].SrcRef
}
return nil
}
func (d *dockerDaemonExporter) GetSrcRef() types.ImageReference {
return d.SrcRef
func (d *dockerDaemonExporter) GetDestRef(exportID string) types.ImageReference {
d.RLock()
defer d.RUnlock()
if _, ok := d.items[exportID]; ok {
return d.items[exportID].DestRef
}
return nil
}
func (d *dockerDaemonExporter) GetDestRef() types.ImageReference {
return d.DestRef
func (d *dockerDaemonExporter) Remove(exportID string) {
d.Lock()
delete(d.items, exportID)
d.Unlock()
}
......@@ -15,6 +15,8 @@
package daemon
import (
"sync"
"github.com/containers/image/v5/types"
"isula.org/isula-build/exporter"
......@@ -25,24 +27,51 @@ func init() {
}
type dockerExporter struct {
exporter.Bus
items map[string]exporter.Bus
sync.RWMutex
}
var _dockerExporter = dockerExporter{}
var _dockerExporter = dockerExporter{
items: make(map[string]exporter.Bus),
}
func (d *dockerExporter) Name() string {
return "docker"
}
func (d *dockerExporter) Init(src, dest types.ImageReference) {
d.SrcRef = src
d.DestRef = dest
func (d *dockerExporter) Init(exportID string, src, dest types.ImageReference) {
d.Lock()
d.items[exportID] = exporter.Bus{
SrcRef: src,
DestRef: dest,
}
d.Unlock()
}
func (d *dockerExporter) GetSrcRef(exportID string) types.ImageReference {
d.RLock()
defer d.RUnlock()
if _, ok := d.items[exportID]; ok {
return d.items[exportID].SrcRef
}
return nil
}
func (d *dockerExporter) GetSrcRef() types.ImageReference {
return d.SrcRef
func (d *dockerExporter) GetDestRef(exportID string) types.ImageReference {
d.RLock()
defer d.RUnlock()
if _, ok := d.items[exportID]; ok {
return d.items[exportID].DestRef
}
return nil
}
func (d *dockerExporter) GetDestRef() types.ImageReference {
return d.DestRef
func (d *dockerExporter) Remove(exportID string) {
d.Lock()
delete(d.items, exportID)
d.Unlock()
}
......@@ -14,10 +14,17 @@
package exporter
import (
"sync"
"github.com/containers/image/v5/types"
)
var exporters map[string]Exporter
type exportHub struct {
items map[string]Exporter
sync.RWMutex
}
var hub exportHub
// Bus is an struct for SrcRef and DestRef
type Bus struct {
......@@ -26,33 +33,43 @@ type Bus struct {
}
func init() {
exporters = make(map[string]Exporter)
hub.items = make(map[string]Exporter)
}
// Exporter is an interface
type Exporter interface {
Name() string
Init(src, dest types.ImageReference)
GetSrcRef() types.ImageReference
GetDestRef() types.ImageReference
Init(exportID string, src, dest types.ImageReference)
GetSrcRef(exportID string) types.ImageReference
GetDestRef(exportID string) types.ImageReference
Remove(exportID string)
}
// Register register an exporter
// Register registers an exporter
func Register(e Exporter) {
hub.Lock()
defer hub.Unlock()
name := e.Name()
if _, ok := exporters[name]; ok {
if _, ok := hub.items[name]; ok {
return
}
exporters[name] = e
hub.items[name] = e
}
// GetAnExporter an Exporter for the given name
// GetAnExporter returns an Exporter for the given name
func GetAnExporter(name string) Exporter {
return exporters[name]
hub.RLock()
defer hub.RUnlock()
return hub.items[name]
}
// IsSupport return a bool whether a exporter is support
// IsSupport returns true when the specific exporter is supported
func IsSupport(name string) bool {
_, ok := exporters[name]
hub.RLock()
defer hub.RUnlock()
_, ok := hub.items[name]
return ok
}
......@@ -15,6 +15,8 @@
package isulad
import (
"sync"
"github.com/containers/image/v5/types"
"isula.org/isula-build/exporter"
......@@ -25,24 +27,51 @@ func init() {
}
type isuladExporter struct {
exporter.Bus
items map[string]exporter.Bus
sync.RWMutex
}
var _isuladExporter = isuladExporter{}
var _isuladExporter = isuladExporter{
items: make(map[string]exporter.Bus),
}
func (d *isuladExporter) Name() string {
return "isulad"
}
func (d *isuladExporter) Init(src, dest types.ImageReference) {
d.SrcRef = src
d.DestRef = dest
func (d *isuladExporter) Init(exportID string, src, dest types.ImageReference) {
d.Lock()
d.items[exportID] = exporter.Bus{
SrcRef: src,
DestRef: dest,
}
d.Unlock()
}
func (d *isuladExporter) GetSrcRef(exportID string) types.ImageReference {
d.RLock()
defer d.RUnlock()
if _, ok := d.items[exportID]; ok {
return d.items[exportID].SrcRef
}
return nil
}
func (d *isuladExporter) GetSrcRef() types.ImageReference {
return d.SrcRef
func (d *isuladExporter) GetDestRef(exportID string) types.ImageReference {
d.RLock()
defer d.RUnlock()
if _, ok := d.items[exportID]; ok {
return d.items[exportID].DestRef
}
return nil
}
func (d *isuladExporter) GetDestRef() types.ImageReference {
return d.DestRef
func (d *isuladExporter) Remove(exportID string) {
d.Lock()
delete(d.items, exportID)
d.Unlock()
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册