mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
First integration of runtime with repositories & tags
This commit is contained in:
parent
680f40c37e
commit
44faa07b6c
5 changed files with 113 additions and 96 deletions
144
commands.go
144
commands.go
|
@ -12,7 +12,6 @@ import (
|
|||
"math/rand"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
@ -356,32 +355,26 @@ func (srv *Server) CmdKill(stdin io.ReadCloser, stdout io.Writer, args ...string
|
|||
}
|
||||
|
||||
func (srv *Server) CmdImport(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
|
||||
cmd := rcli.Subcmd(stdout, "import", "[OPTIONS] NAME", "Create a new filesystem image from the contents of a tarball")
|
||||
fl_stdin := cmd.Bool("stdin", false, "Read tarball from stdin")
|
||||
cmd := rcli.Subcmd(stdout, "import", "[OPTIONS] URL|- [REPOSITORY [TAG]]", "Create a new filesystem image from the contents of a tarball")
|
||||
var archive io.Reader
|
||||
var resp *http.Response
|
||||
|
||||
if err := cmd.Parse(args); err != nil {
|
||||
return nil
|
||||
}
|
||||
name := cmd.Arg(0)
|
||||
if name == "" {
|
||||
src := cmd.Arg(0)
|
||||
if src == "" {
|
||||
return errors.New("Not enough arguments")
|
||||
}
|
||||
if *fl_stdin {
|
||||
} else if src == "-" {
|
||||
archive = stdin
|
||||
} else {
|
||||
u, err := url.Parse(name)
|
||||
u, err := url.Parse(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if u.Scheme == "" {
|
||||
u.Scheme = "http"
|
||||
}
|
||||
if u.Host == "" {
|
||||
u.Host = "get.docker.io"
|
||||
u.Path = path.Join("/images", u.Path)
|
||||
}
|
||||
fmt.Fprintf(stdout, "Downloading from %s\n", u.String())
|
||||
// Download with curl (pretty progress bar)
|
||||
// If curl is not available, fallback to http.Get()
|
||||
|
@ -391,11 +384,17 @@ func (srv *Server) CmdImport(stdin io.ReadCloser, stdout io.Writer, args ...stri
|
|||
}
|
||||
archive = ProgressReader(resp.Body, int(resp.ContentLength), stdout)
|
||||
}
|
||||
fmt.Fprintf(stdout, "Unpacking to %s\n", name)
|
||||
img, err := srv.runtime.graph.Create(archive, "", "")
|
||||
img, err := srv.runtime.graph.Create(archive, "", "Imported from "+src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Optionally register the image at REPO/TAG
|
||||
if repository := cmd.Arg(1); repository != "" {
|
||||
tag := cmd.Arg(2) // Repository will handle an empty tag properly
|
||||
if err := srv.runtime.repositories.Set(repository, tag, img.Id); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
fmt.Fprintln(stdout, img.Id)
|
||||
return nil
|
||||
}
|
||||
|
@ -411,68 +410,75 @@ func (srv *Server) CmdImages(stdin io.ReadCloser, stdout io.Writer, args ...stri
|
|||
cmd.Usage()
|
||||
return nil
|
||||
}
|
||||
/*
|
||||
var nameFilter string
|
||||
if cmd.NArg() == 1 {
|
||||
nameFilter = cmd.Arg(0)
|
||||
}
|
||||
*/
|
||||
var nameFilter string
|
||||
if cmd.NArg() == 1 {
|
||||
nameFilter = cmd.Arg(0)
|
||||
}
|
||||
w := tabwriter.NewWriter(stdout, 20, 1, 3, ' ', 0)
|
||||
if !*quiet {
|
||||
fmt.Fprintf(w, "NAME\tID\tCREATED\tPARENT\n")
|
||||
fmt.Fprintf(w, "REPOSITORY\tTAG\tID\tCREATED\tPARENT\n")
|
||||
}
|
||||
if *quiet {
|
||||
images, err := srv.runtime.graph.All()
|
||||
if err != nil {
|
||||
return err
|
||||
allImages, err := srv.runtime.graph.Map()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for name, repository := range srv.runtime.repositories.Repositories {
|
||||
if nameFilter != "" && name != nameFilter {
|
||||
continue
|
||||
}
|
||||
for _, image := range images {
|
||||
fmt.Fprintln(stdout, image.Id)
|
||||
for tag, id := range repository {
|
||||
image, err := srv.runtime.graph.Get(id)
|
||||
if err != nil {
|
||||
log.Printf("Warning: couldn't load %s from %s/%s: %s", id, name, tag, err)
|
||||
continue
|
||||
}
|
||||
delete(allImages, id)
|
||||
if !*quiet {
|
||||
for idx, field := range []string{
|
||||
/* REPOSITORY */ name,
|
||||
/* TAG */ tag,
|
||||
/* ID */ id,
|
||||
/* CREATED */ HumanDuration(time.Now().Sub(image.Created)) + " ago",
|
||||
/* PARENT */ image.Parent,
|
||||
} {
|
||||
if idx == 0 {
|
||||
w.Write([]byte(field))
|
||||
} else {
|
||||
w.Write([]byte("\t" + field))
|
||||
}
|
||||
}
|
||||
w.Write([]byte{'\n'})
|
||||
} else {
|
||||
stdout.Write([]byte(image.Id + "\n"))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// FIXME:
|
||||
// paths, err := srv.images.Paths()
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// for _, name := range paths {
|
||||
// if nameFilter != "" && nameFilter != name {
|
||||
// continue
|
||||
// }
|
||||
// ids, err := srv.images.List(name)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// for idx, img := range ids {
|
||||
// if *limit > 0 && idx >= *limit {
|
||||
// break
|
||||
// }
|
||||
// if !*quiet {
|
||||
// for idx, field := range []string{
|
||||
// /* NAME */ name,
|
||||
// /* ID */ img.Id,
|
||||
// /* CREATED */ HumanDuration(time.Now().Sub(time.Unix(img.Created, 0))) + " ago",
|
||||
// /* PARENT */ img.Parent,
|
||||
// } {
|
||||
// if idx == 0 {
|
||||
// w.Write([]byte(field))
|
||||
// } else {
|
||||
// w.Write([]byte("\t" + field))
|
||||
// }
|
||||
// }
|
||||
// w.Write([]byte{'\n'})
|
||||
// } else {
|
||||
// stdout.Write([]byte(img.Id + "\n"))
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// if !*quiet {
|
||||
// w.Flush()
|
||||
// }
|
||||
//
|
||||
}
|
||||
// Display images which aren't part of a
|
||||
if nameFilter != "" {
|
||||
for id, image := range allImages {
|
||||
if !*quiet {
|
||||
for idx, field := range []string{
|
||||
/* REPOSITORY */ "",
|
||||
/* TAG */ "",
|
||||
/* ID */ id,
|
||||
/* CREATED */ HumanDuration(time.Now().Sub(image.Created)) + " ago",
|
||||
/* PARENT */ image.Parent,
|
||||
} {
|
||||
if idx == 0 {
|
||||
w.Write([]byte(field))
|
||||
} else {
|
||||
w.Write([]byte("\t" + field))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
stdout.Write([]byte(image.Id + "\n"))
|
||||
}
|
||||
}
|
||||
}
|
||||
if !*quiet {
|
||||
w.Flush()
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func (srv *Server) CmdPs(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
|
||||
|
|
|
@ -122,6 +122,19 @@ func (graph *Graph) GarbageCollect() error {
|
|||
return os.RemoveAll(garbage.Root)
|
||||
}
|
||||
|
||||
func (graph *Graph) Map() (map[string]*Image, error) {
|
||||
// FIXME: this should replace All()
|
||||
all, err := graph.All()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
images := make(map[string]*Image, len(all))
|
||||
for _, image := range all {
|
||||
images[image.Id] = image
|
||||
}
|
||||
return images, nil
|
||||
}
|
||||
|
||||
func (graph *Graph) All() ([]*Image, error) {
|
||||
files, err := ioutil.ReadDir(graph.Root)
|
||||
if err != nil {
|
||||
|
|
|
@ -6,33 +6,31 @@ import (
|
|||
"path/filepath"
|
||||
)
|
||||
|
||||
type RepoStore struct {
|
||||
type TagStore struct {
|
||||
path string
|
||||
graph *Graph
|
||||
Repositories map[string]*Repository
|
||||
Repositories map[string]Repository
|
||||
}
|
||||
|
||||
type Repository struct {
|
||||
Tags map[string]string
|
||||
}
|
||||
type Repository map[string]string
|
||||
|
||||
func NewRepoStore(path string, graph *Graph) (*RepoStore, error) {
|
||||
func NewTagStore(path string, graph *Graph) (*TagStore, error) {
|
||||
abspath, err := filepath.Abs(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
store := &RepoStore{
|
||||
store := &TagStore{
|
||||
path: abspath,
|
||||
graph: graph,
|
||||
Repositories: make(map[string]*Repository),
|
||||
Repositories: make(map[string]Repository),
|
||||
}
|
||||
if err := store.Reload(); err != nil {
|
||||
if err := store.Save(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return store, nil
|
||||
}
|
||||
|
||||
func (store *RepoStore) Save() error {
|
||||
func (store *TagStore) Save() error {
|
||||
// Store the json ball
|
||||
jsonData, err := json.Marshal(store)
|
||||
if err != nil {
|
||||
|
@ -44,7 +42,7 @@ func (store *RepoStore) Save() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (store *RepoStore) Reload() error {
|
||||
func (store *TagStore) Reload() error {
|
||||
jsonData, err := ioutil.ReadFile(store.path)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -55,22 +53,22 @@ func (store *RepoStore) Reload() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (store *RepoStore) SetTag(repoName, tag, revision string) error {
|
||||
func (store *TagStore) Set(repoName, tag, revision string) error {
|
||||
if err := store.Reload(); err != nil {
|
||||
return err
|
||||
}
|
||||
var repo *Repository
|
||||
var repo Repository
|
||||
if r, exists := store.Repositories[repoName]; exists {
|
||||
repo = r
|
||||
} else {
|
||||
repo = NewRepository()
|
||||
repo = make(map[string]string)
|
||||
store.Repositories[repoName] = repo
|
||||
}
|
||||
repo.Tags[tag] = revision
|
||||
repo[tag] = revision
|
||||
return store.Save()
|
||||
}
|
||||
|
||||
func (store *RepoStore) Get(repoName string) (*Repository, error) {
|
||||
func (store *TagStore) Get(repoName string) (Repository, error) {
|
||||
if err := store.Reload(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -80,21 +78,15 @@ func (store *RepoStore) Get(repoName string) (*Repository, error) {
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func (store *RepoStore) GetImage(repoName, tag string) (*Image, error) {
|
||||
func (store *TagStore) GetImage(repoName, tag string) (*Image, error) {
|
||||
repo, err := store.Get(repoName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if repo == nil {
|
||||
return nil, nil
|
||||
}
|
||||
if revision, exists := repo.Tags[tag]; exists {
|
||||
if revision, exists := repo[tag]; exists {
|
||||
return store.graph.Get(revision)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func NewRepository() *Repository {
|
||||
return &Repository{
|
||||
Tags: make(map[string]string),
|
||||
}
|
||||
}
|
||||
|
|
10
runtime.go
10
runtime.go
|
@ -20,6 +20,7 @@ type Runtime struct {
|
|||
containers *list.List
|
||||
networkManager *NetworkManager
|
||||
graph *graph.Graph
|
||||
repositories *graph.TagStore
|
||||
}
|
||||
|
||||
var sysInitPath string
|
||||
|
@ -201,10 +202,14 @@ func NewFromDirectory(root string) (*Runtime, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
graph, err := graph.New(path.Join(root, "graph"))
|
||||
g, err := graph.New(path.Join(root, "graph"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
repositories, err := graph.NewTagStore(path.Join(root, "repositories"), g)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Couldn't create Tag store: %s", err)
|
||||
}
|
||||
netManager, err := newNetworkManager(networkBridgeIface)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -215,7 +220,8 @@ func NewFromDirectory(root string) (*Runtime, error) {
|
|||
repository: runtime_repo,
|
||||
containers: list.New(),
|
||||
networkManager: netManager,
|
||||
graph: graph,
|
||||
graph: g,
|
||||
repositories: repositories,
|
||||
}
|
||||
|
||||
if err := runtime.restore(); err != nil {
|
||||
|
|
|
@ -11,7 +11,7 @@ import (
|
|||
)
|
||||
|
||||
const testLayerPath string = "/var/lib/docker/docker-ut.tar"
|
||||
const unitTestImageName string = "busybox"
|
||||
const unitTestImageName string = "http://get.docker.io/images/busybox"
|
||||
|
||||
var unitTestStoreBase string
|
||||
var srv *Server
|
||||
|
|
Loading…
Add table
Reference in a new issue