2017-01-10 22:57:22 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"os"
|
|
|
|
|
|
|
|
"github.com/containers/image/copy"
|
|
|
|
"github.com/containers/image/signature"
|
|
|
|
"github.com/containers/image/storage"
|
2017-03-13 15:16:03 +00:00
|
|
|
"github.com/containers/image/transports/alltransports"
|
2017-01-10 22:57:22 +00:00
|
|
|
"github.com/containers/image/types"
|
2017-05-17 17:18:35 +00:00
|
|
|
sstorage "github.com/containers/storage"
|
2017-01-10 22:57:22 +00:00
|
|
|
"github.com/containers/storage/pkg/reexec"
|
2017-08-05 11:40:46 +00:00
|
|
|
"github.com/sirupsen/logrus"
|
2017-01-10 22:57:22 +00:00
|
|
|
"github.com/urfave/cli"
|
|
|
|
)
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
if reexec.Init() {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
app := cli.NewApp()
|
|
|
|
app.Name = "copyimg"
|
|
|
|
app.Usage = "barebones image copier"
|
|
|
|
app.Version = "0.0.1"
|
|
|
|
|
|
|
|
app.Flags = []cli.Flag{
|
|
|
|
cli.BoolFlag{
|
|
|
|
Name: "debug",
|
|
|
|
Usage: "turn on debug logging",
|
|
|
|
},
|
|
|
|
cli.StringFlag{
|
|
|
|
Name: "root",
|
|
|
|
Usage: "graph root directory",
|
|
|
|
},
|
|
|
|
cli.StringFlag{
|
|
|
|
Name: "runroot",
|
|
|
|
Usage: "run root directory",
|
|
|
|
},
|
|
|
|
cli.StringFlag{
|
|
|
|
Name: "storage-driver",
|
|
|
|
Usage: "storage driver",
|
|
|
|
},
|
|
|
|
cli.StringSliceFlag{
|
2017-02-24 22:05:07 +00:00
|
|
|
Name: "storage-opt",
|
2017-01-10 22:57:22 +00:00
|
|
|
Usage: "storage option",
|
|
|
|
},
|
|
|
|
cli.StringFlag{
|
|
|
|
Name: "signature-policy",
|
|
|
|
Usage: "signature policy",
|
|
|
|
},
|
|
|
|
cli.StringFlag{
|
|
|
|
Name: "image-name",
|
|
|
|
Usage: "set image name",
|
|
|
|
},
|
|
|
|
cli.StringFlag{
|
|
|
|
Name: "add-name",
|
|
|
|
Usage: "name to add to image",
|
|
|
|
},
|
|
|
|
cli.StringFlag{
|
|
|
|
Name: "import-from",
|
|
|
|
Usage: "import source",
|
|
|
|
},
|
|
|
|
cli.StringFlag{
|
|
|
|
Name: "export-to",
|
|
|
|
Usage: "export target",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
app.Action = func(c *cli.Context) error {
|
|
|
|
var store sstorage.Store
|
|
|
|
var ref, importRef, exportRef types.ImageReference
|
|
|
|
var err error
|
|
|
|
|
|
|
|
debug := c.GlobalBool("debug")
|
|
|
|
rootDir := c.GlobalString("root")
|
|
|
|
runrootDir := c.GlobalString("runroot")
|
|
|
|
storageDriver := c.GlobalString("storage-driver")
|
2017-02-24 22:05:07 +00:00
|
|
|
storageOptions := c.GlobalStringSlice("storage-opt")
|
2017-01-10 22:57:22 +00:00
|
|
|
signaturePolicy := c.GlobalString("signature-policy")
|
|
|
|
imageName := c.GlobalString("image-name")
|
|
|
|
addName := c.GlobalString("add-name")
|
|
|
|
importFrom := c.GlobalString("import-from")
|
|
|
|
exportTo := c.GlobalString("export-to")
|
|
|
|
|
|
|
|
if debug {
|
|
|
|
logrus.SetLevel(logrus.DebugLevel)
|
|
|
|
} else {
|
|
|
|
logrus.SetLevel(logrus.ErrorLevel)
|
|
|
|
}
|
|
|
|
|
|
|
|
if imageName != "" {
|
|
|
|
if rootDir == "" && runrootDir != "" {
|
|
|
|
logrus.Errorf("must set --root and --runroot, or neither")
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
if rootDir != "" && runrootDir == "" {
|
|
|
|
logrus.Errorf("must set --root and --runroot, or neither")
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
storeOptions := sstorage.DefaultStoreOptions
|
|
|
|
if rootDir != "" && runrootDir != "" {
|
|
|
|
storeOptions.GraphDriverName = storageDriver
|
|
|
|
storeOptions.GraphDriverOptions = storageOptions
|
|
|
|
storeOptions.GraphRoot = rootDir
|
|
|
|
storeOptions.RunRoot = runrootDir
|
|
|
|
}
|
|
|
|
store, err = sstorage.GetStore(storeOptions)
|
|
|
|
if err != nil {
|
|
|
|
logrus.Errorf("error opening storage: %v", err)
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
2017-03-27 17:14:11 +00:00
|
|
|
defer func() {
|
|
|
|
_, _ = store.Shutdown(false)
|
|
|
|
}()
|
2017-01-10 22:57:22 +00:00
|
|
|
|
|
|
|
storage.Transport.SetStore(store)
|
|
|
|
ref, err = storage.Transport.ParseStoreReference(store, imageName)
|
|
|
|
if err != nil {
|
|
|
|
logrus.Errorf("error parsing image name: %v", err)
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
systemContext := types.SystemContext{
|
|
|
|
SignaturePolicyPath: signaturePolicy,
|
|
|
|
}
|
|
|
|
policy, err := signature.DefaultPolicy(&systemContext)
|
|
|
|
if err != nil {
|
|
|
|
logrus.Errorf("error loading signature policy: %v", err)
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
policyContext, err := signature.NewPolicyContext(policy)
|
|
|
|
if err != nil {
|
|
|
|
logrus.Errorf("error loading signature policy: %v", err)
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
2017-03-27 17:14:11 +00:00
|
|
|
defer func() {
|
|
|
|
_ = policyContext.Destroy()
|
|
|
|
}()
|
2017-01-10 22:57:22 +00:00
|
|
|
options := ©.Options{}
|
|
|
|
|
|
|
|
if importFrom != "" {
|
2017-03-13 15:16:03 +00:00
|
|
|
importRef, err = alltransports.ParseImageName(importFrom)
|
2017-01-10 22:57:22 +00:00
|
|
|
if err != nil {
|
|
|
|
logrus.Errorf("error parsing image name %v: %v", importFrom, err)
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if exportTo != "" {
|
2017-03-13 15:16:03 +00:00
|
|
|
exportRef, err = alltransports.ParseImageName(exportTo)
|
2017-01-10 22:57:22 +00:00
|
|
|
if err != nil {
|
|
|
|
logrus.Errorf("error parsing image name %v: %v", exportTo, err)
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if imageName != "" {
|
|
|
|
if importFrom != "" {
|
|
|
|
err = copy.Image(policyContext, ref, importRef, options)
|
|
|
|
if err != nil {
|
|
|
|
logrus.Errorf("error importing %s: %v", importFrom, err)
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if addName != "" {
|
2017-03-27 17:14:11 +00:00
|
|
|
destImage, err1 := storage.Transport.GetStoreImage(store, ref)
|
|
|
|
if err1 != nil {
|
|
|
|
logrus.Errorf("error finding image: %v", err1)
|
2017-01-10 22:57:22 +00:00
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
names := append(destImage.Names, imageName, addName)
|
|
|
|
err = store.SetNames(destImage.ID, names)
|
|
|
|
if err != nil {
|
|
|
|
logrus.Errorf("error adding name to %s: %v", imageName, err)
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if exportTo != "" {
|
|
|
|
err = copy.Image(policyContext, exportRef, ref, options)
|
|
|
|
if err != nil {
|
|
|
|
logrus.Errorf("error exporting %s: %v", exportTo, err)
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if importFrom != "" && exportTo != "" {
|
|
|
|
err = copy.Image(policyContext, exportRef, importRef, options)
|
|
|
|
if err != nil {
|
|
|
|
logrus.Errorf("error copying %s to %s: %v", importFrom, exportTo, err)
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := app.Run(os.Args); err != nil {
|
|
|
|
logrus.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|