Files
containerd/cmd/dist/main.go
Stephen J Day cec8578ff0 cmd/dist: add ability to edit content
This allows one to edit content in the content store with their favorite
editor. It is as simple as this:

```console
$ dist content edit sha256:58e1a1bb75db1b5a24a462dd5e2915277ea06438c3f105138f97eb53149673c4
```

The above will pop up your $EDITOR, where you can make changes to the content.
When you are done, save and the new version will be added to the content store.
The digest of the new content will be printed to stdout:

```console
sha256:247f30ac320db65f3314b63b908a3aeaac5813eade6cabc9198b5883b22807bc
```

We can then retrieve the content quite easily:

```console
$ dist content get sha256:247f30ac320db65f3314b63b908a3aeaac5813eade6cabc9198b5883b22807bc
{
   "schemaVersion": 2,
   "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
   "config": {
      "mediaType": "application/vnd.docker.container.image.v1+json",
      "size": 1278,
      "digest": "sha256:4a415e3663882fbc554ee830889c68a33b3585503892cc718a4698e91ef2a526"
   },
   "annotations": {},
   "layers": [
      {
         "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
         "size": 1905270,
         "digest": "sha256:627beaf3eaaff1c0bc3311d60fb933c17ad04fe377e1043d9593646d8ae3bfe1"
      }
   ]
}

```

In this case, an annotations field was added to the original manifest.

While this implementation is very simple, we can add all sorts of validation
and tooling to allow one to edit images inline. Coupled with declaring the
mediatype, we could return specific errors that can allow a user to craft
valid, working modifications to images for testing and profit.

Signed-off-by: Stephen J Day <stephen.day@docker.com>
2017-05-02 11:05:14 -07:00

113 lines
2.1 KiB
Go

package main
import (
contextpkg "context"
"fmt"
"os"
"github.com/Sirupsen/logrus"
"github.com/containerd/containerd"
"github.com/urfave/cli"
)
var (
background = contextpkg.Background()
)
func init() {
cli.VersionPrinter = func(c *cli.Context) {
fmt.Println(c.App.Name, containerd.Package, c.App.Version)
}
}
func main() {
app := cli.NewApp()
app.Name = "dist"
app.Version = containerd.Version
app.Usage = `
___ __
____/ (_)____/ /_
/ __ / / ___/ __/
/ /_/ / (__ ) /_
\__,_/_/____/\__/
distribution tool
`
app.Flags = []cli.Flag{
cli.BoolFlag{
Name: "debug",
Usage: "enable debug output in logs",
},
cli.DurationFlag{
Name: "timeout",
Usage: "total timeout for dist commands",
},
cli.DurationFlag{
Name: "connect-timeout",
Usage: "timeout for connecting to containerd",
},
cli.StringFlag{
// TODO(stevvooe): for now, we allow circumventing the GRPC. Once
// we have clear separation, this will likely go away.
Name: "root",
Usage: "path to content store root",
Value: "/var/lib/containerd",
},
cli.StringFlag{
Name: "address, a",
Usage: "address for containerd's GRPC server",
Value: "/run/containerd/containerd.sock",
},
}
app.Commands = []cli.Command{
imageCommand,
contentCommand,
pullCommand,
fetchCommand,
fetchObjectCommand,
applyCommand,
rootfsCommand,
}
app.Before = func(context *cli.Context) error {
var (
debug = context.GlobalBool("debug")
timeout = context.GlobalDuration("timeout")
)
if debug {
logrus.SetLevel(logrus.DebugLevel)
}
if timeout > 0 {
background, _ = contextpkg.WithTimeout(background, timeout)
}
return nil
}
if err := app.Run(os.Args); err != nil {
fmt.Fprintf(os.Stderr, "dist: %s\n", err)
os.Exit(1)
}
}
var imageCommand = cli.Command{
Name: "image",
Usage: "image management",
Subcommands: cli.Commands{
imagesListCommand,
rmiCommand,
},
}
var contentCommand = cli.Command{
Name: "content",
Usage: "content management",
Subcommands: cli.Commands{
listCommand,
ingestCommand,
activeCommand,
getCommand,
editCommand,
deleteCommand,
},
}