/graph fix lin errors/warnings

Addresses #14756
Signed-off-by: Srini Brahmaroutu <srbrahma@us.ibm.com>
This commit is contained in:
Srini Brahmaroutu 2015-07-21 16:21:45 +00:00 committed by Srini Brahmaroutu
parent 0f85fadb4e
commit 1d6e443119
21 changed files with 140 additions and 87 deletions

View file

@ -27,7 +27,7 @@ func (daemon *Daemon) ContainerCreate(name string, config *runconfig.Config, hos
if daemon.Graph().IsNotExist(err, config.Image) {
_, tag := parsers.ParseRepositoryTag(config.Image)
if tag == "" {
tag = graph.DEFAULTTAG
tag = graph.DefaultTag
}
return "", warnings, fmt.Errorf("No such image: %s (tag: %s)", config.Image, tag)
}

View file

@ -36,7 +36,7 @@ func (daemon *Daemon) imgDeleteHelper(name string, list *[]types.ImageDelete, fi
// FIXME: please respect DRY and centralize repo+tag parsing in a single central place! -- shykes
repoName, tag = parsers.ParseRepositoryTag(name)
if tag == "" {
tag = graph.DEFAULTTAG
tag = graph.DefaultTag
}
if name == "" {

View file

@ -13,16 +13,19 @@ import (
"github.com/docker/docker/registry"
)
// CmdImageExport exports all images with the given tag. All versions
// ImageExportConfig holds list of names to be exported to a output stream.
// All images with the given tag and all versions
// containing the same tag are exported. The resulting output is an
// uncompressed tar ball.
// name is the set of tags to export.
// out is the writer where the images are written to.
type ImageExportConfig struct {
Names []string
// Names is the set of tags to export.
Names []string
// OutStream is the writer where the images are written to.
Outstream io.Writer
}
// ImageExport exports list of images to a output stream specified in the config.
// The exported images are archived into a tar when written to the output stream.
func (s *TagStore) ImageExport(imageExportConfig *ImageExportConfig) error {
// get image json
@ -135,7 +138,7 @@ func (s *TagStore) exportImage(name, tempdir string) error {
if err != nil {
return err
}
imageInspectRaw, err := s.LookupRaw(n)
imageInspectRaw, err := s.lookupRaw(n)
if err != nil {
return err
}

View file

@ -152,6 +152,7 @@ func (graph *Graph) restore() error {
return nil
}
// IsNotExist detects whether an image exists by parsing the incoming error message.
// FIXME: Implement error subclass instead of looking at the error text
// Note: This is the way golang implements os.IsNotExists on Plan9
func (graph *Graph) IsNotExist(err error, id string) bool {
@ -414,7 +415,7 @@ func (graph *Graph) ByParent() map[string][]*image.Image {
return byParent
}
// If the images and layers are in pulling chain, retain them.
// Retain keeps the images and layers that are in pulling chain so that they are not deleted.
// If not, they may be deleted by rmi with dangling condition.
func (graph *Graph) Retain(sessionID string, layerIDs ...string) {
graph.retained.Add(sessionID, layerIDs)

View file

@ -16,10 +16,9 @@ import (
"github.com/docker/docker/pkg/system"
)
// setupInitLayer populates a directory with mountpoints suitable
// SetupInitLayer populates a directory with mountpoints suitable
// for bind-mounting dockerinit into the container. The mountpoint is simply an
// empty file at /.dockerinit
//
// This extra layer is used by all containers as the top-most ro layer. It protects
// the container from unwanted side-effects on the rw layer.
func SetupInitLayer(initLayer string) error {

View file

@ -13,7 +13,7 @@ import (
"github.com/docker/docker/pkg/archive"
)
// setupInitLayer populates a directory with mountpoints suitable
// SetupInitLayer populates a directory with mountpoints suitable
// for bind-mounting dockerinit into the container. T
func SetupInitLayer(initLayer string) error {
return nil
@ -106,33 +106,32 @@ func (graph *Graph) storeImage(img *image.Image, layerData archive.ArchiveReader
defer f.Close()
return json.NewEncoder(f).Encode(img)
} else {
// We keep this functionality here so that we can still work with the
// VFS driver during development. This will not be used for actual running
// of Windows containers. Without this code, it would not be possible to
// docker pull using the VFS driver.
// Store the layer. If layerData is not nil, unpack it into the new layer
if layerData != nil {
if err := graph.disassembleAndApplyTarLayer(img, layerData, root); err != nil {
return err
}
}
if err := graph.saveSize(root, int(img.Size)); err != nil {
return err
}
f, err := os.OpenFile(jsonPath(root), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.FileMode(0600))
if err != nil {
return err
}
defer f.Close()
return json.NewEncoder(f).Encode(img)
}
// We keep this functionality here so that we can still work with the
// VFS driver during development. This will not be used for actual running
// of Windows containers. Without this code, it would not be possible to
// docker pull using the VFS driver.
// Store the layer. If layerData is not nil, unpack it into the new layer
if layerData != nil {
if err := graph.disassembleAndApplyTarLayer(img, layerData, root); err != nil {
return err
}
}
if err := graph.saveSize(root, int(img.Size)); err != nil {
return err
}
f, err := os.OpenFile(jsonPath(root), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.FileMode(0600))
if err != nil {
return err
}
defer f.Close()
return json.NewEncoder(f).Encode(img)
}
// TarLayer returns a tar archive of the image's filesystem layer.
@ -152,15 +151,14 @@ func (graph *Graph) TarLayer(img *image.Image) (arch archive.Archive, err error)
}
return wd.Export(img.ID, wd.LayerIdsToPaths(ids))
} else {
// We keep this functionality here so that we can still work with the VFS
// driver during development. VFS is not supported (and just will not work)
// for Windows containers.
rdr, err := graph.assembleTarLayer(img)
if err != nil {
logrus.Debugf("[graph] TarLayer with traditional differ: %s", img.ID)
return graph.driver.Diff(img.ID, img.Parent)
}
return rdr, nil
}
// We keep this functionality here so that we can still work with the VFS
// driver during development. VFS is not supported (and just will not work)
// for Windows containers.
rdr, err := graph.assembleTarLayer(img)
if err != nil {
logrus.Debugf("[graph] TarLayer with traditional differ: %s", img.ID)
return graph.driver.Diff(img.ID, img.Parent)
}
return rdr, nil
}

View file

@ -67,6 +67,7 @@ func (graph *Graph) CheckDepth(img *image.Image) error {
return nil
}
// History returns a list of ImageHistory for the specified image name by walking the image lineage.
func (s *TagStore) History(name string) ([]*types.ImageHistory, error) {
foundImage, err := s.LookupImage(name)
if err != nil {
@ -101,6 +102,7 @@ func (s *TagStore) History(name string) ([]*types.ImageHistory, error) {
return history, err
}
// GetParent returns the parent image.
func (graph *Graph) GetParent(img *image.Image) (*image.Image, error) {
if img.Parent == "" {
return nil, nil
@ -108,6 +110,7 @@ func (graph *Graph) GetParent(img *image.Image) (*image.Image, error) {
return graph.Get(img.Parent)
}
// GetParentsSize returns the size of the parent.
func (graph *Graph) GetParentsSize(img *image.Image, size int64) int64 {
parentImage, err := graph.GetParent(img)
if err != nil || parentImage == nil {

View file

@ -13,13 +13,21 @@ import (
"github.com/docker/docker/utils"
)
// ImageImportConfig holds configuration to import a image.
type ImageImportConfig struct {
Changes []string
InConfig io.ReadCloser
OutStream io.Writer
// Changes are the container changes written to top layer.
Changes []string
// InConfig is the input stream containers layered data.
InConfig io.ReadCloser
// OutStream is the output stream where the image is written.
OutStream io.Writer
// ContainerConfig is the configuration of commit container.
ContainerConfig *runconfig.Config
}
// Import allows to download image from a archive.
// If the src is a URL, the content is downloaded from the archive. If the source is '-' then the imageImportConfig.InConfig
// reader will be used to load the image. Once all the layers required are loaded locally, image is then tagged using the tag specified.
func (s *TagStore) Import(src string, repo string, tag string, imageImportConfig *ImageImportConfig) error {
var (
sf = streamformatter.NewJSONStreamFormatter()

View file

@ -18,18 +18,24 @@ var acceptedImageFilterTags = map[string]struct{}{
"label": {},
}
// ImagesConfig defines the criteria to obtain a list of images.
type ImagesConfig struct {
// Filters is supported list of filters used to get list of images.
Filters string
Filter string
All bool
// Filter the list of images by name.
Filter string
// All inditest that all the images will be returned in the list, if set to true.
All bool
}
type ByCreated []*types.Image
// byCreated is a temporary type used to sort list of images on their field 'Created'.
type byCreated []*types.Image
func (r ByCreated) Len() int { return len(r) }
func (r ByCreated) Swap(i, j int) { r[i], r[j] = r[j], r[i] }
func (r ByCreated) Less(i, j int) bool { return r[i].Created < r[j].Created }
func (r byCreated) Len() int { return len(r) }
func (r byCreated) Swap(i, j int) { r[i], r[j] = r[j], r[i] }
func (r byCreated) Less(i, j int) bool { return r[i].Created < r[j].Created }
// Images provide list of images based on selection criteria.
func (s *TagStore) Images(config *ImagesConfig) ([]*types.Image, error) {
var (
allImages map[string]*image.Image
@ -144,7 +150,7 @@ func (s *TagStore) Images(config *ImagesConfig) ([]*types.Image, error) {
}
}
sort.Sort(sort.Reverse(ByCreated(images)))
sort.Sort(sort.Reverse(byCreated(images)))
return images, nil
}

View file

@ -15,7 +15,7 @@ import (
"github.com/docker/docker/pkg/chrootarchive"
)
// Loads a set of images into the repository. This is the complementary of ImageExport.
// Load uploads a set of images into the repository. This is the complementary of ImageExport.
// The input stream is an uncompressed tar ball containing images and metadata.
func (s *TagStore) Load(inTar io.ReadCloser, outStream io.Writer) error {
tmpImageDir, err := ioutil.TempDir("", "docker-import-")
@ -84,7 +84,7 @@ func (s *TagStore) recursiveLoad(address, tmpImageDir string) error {
if _, err := s.LookupImage(address); err != nil {
logrus.Debugf("Loading %s", address)
imageJson, err := ioutil.ReadFile(filepath.Join(tmpImageDir, "repo", address, "json"))
imageJSON, err := ioutil.ReadFile(filepath.Join(tmpImageDir, "repo", address, "json"))
if err != nil {
logrus.Debugf("Error reading json: %v", err)
return err
@ -95,7 +95,7 @@ func (s *TagStore) recursiveLoad(address, tmpImageDir string) error {
logrus.Debugf("Error reading embedded tar: %v", err)
return err
}
img, err := image.NewImgJSON(imageJson)
img, err := image.NewImgJSON(imageJSON)
if err != nil {
logrus.Debugf("Error unmarshalling json: %v", err)
return err

View file

@ -7,6 +7,8 @@ import (
"io"
)
// Load method is implemented here for non-linux and non-windows platforms and
// may return an error indicating that image load is not supported on other platforms.
func (s *TagStore) Load(inTar io.ReadCloser, outStream io.Writer) error {
return fmt.Errorf("Load is not supported on this platform")
}

View file

@ -11,12 +11,17 @@ import (
"github.com/docker/docker/utils"
)
// ImagePullConfig stores pull configuration.
type ImagePullConfig struct {
// MetaHeaders store meta data about the image (DockerHeaders with prefix X-Meta- in the request).
MetaHeaders map[string][]string
AuthConfig *cliconfig.AuthConfig
OutStream io.Writer
// AuthConfig holds authentication information for authorizing with the registry.
AuthConfig *cliconfig.AuthConfig
// OutStream is the output writer for showing the status of the pull operation.
OutStream io.Writer
}
// Puller is an interface to define Pull behavior.
type Puller interface {
// Pull tries to pull the image referenced by `tag`
// Pull returns an error if any, as well as a boolean that determines whether to retry Pull on the next configured endpoint.
@ -25,6 +30,7 @@ type Puller interface {
Pull(tag string) (fallback bool, err error)
}
// NewPuller returns a new instance of an implementation conforming to Puller interface.
func NewPuller(s *TagStore, endpoint registry.APIEndpoint, repoInfo *registry.RepositoryInfo, imagePullConfig *ImagePullConfig, sf *streamformatter.StreamFormatter) (Puller, error) {
switch endpoint.Version {
case registry.APIVersion2:
@ -47,6 +53,7 @@ func NewPuller(s *TagStore, endpoint registry.APIEndpoint, repoInfo *registry.Re
return nil, fmt.Errorf("unknown version %d for registry %s", endpoint.Version, endpoint.URL)
}
// Pull downloads a image with specified name and tag from the repo.
func (s *TagStore) Pull(image string, tag string, imagePullConfig *ImagePullConfig) error {
var sf = streamformatter.NewJSONStreamFormatter()
@ -126,7 +133,8 @@ func (s *TagStore) Pull(image string, tag string, imagePullConfig *ImagePullConf
return lastErr
}
func WriteStatus(requestedTag string, out io.Writer, sf *streamformatter.StreamFormatter, layersDownloaded bool) {
// writeStatus shows status of the pull command.
func writeStatus(requestedTag string, out io.Writer, sf *streamformatter.StreamFormatter, layersDownloaded bool) {
if layersDownloaded {
out.Write(sf.FormatStatus("", "Status: Downloaded newer image for %s", requestedTag))
} else {

View file

@ -80,9 +80,9 @@ func (p *v1Puller) pullRepository(askedTag string) error {
if askedTag == "" {
tagsList, err = p.session.GetRemoteTags(repoData.Endpoints, p.repoInfo.RemoteName)
} else {
var tagId string
tagId, err = p.session.GetRemoteTag(repoData.Endpoints, p.repoInfo.RemoteName, askedTag)
tagsList[askedTag] = tagId
var tagID string
tagID, err = p.session.GetRemoteTag(repoData.Endpoints, p.repoInfo.RemoteName, askedTag)
tagsList[askedTag] = tagID
}
if err != nil {
if err == registry.ErrRepoNotFound && askedTag != "" {
@ -222,7 +222,7 @@ func (p *v1Puller) pullRepository(askedTag string) error {
if len(askedTag) > 0 {
requestedTag = utils.ImageReference(p.repoInfo.LocalName, askedTag)
}
WriteStatus(requestedTag, out, p.sf, layersDownloaded)
writeStatus(requestedTag, out, p.sf, layersDownloaded)
return nil
}

View file

@ -95,7 +95,7 @@ func (p *v2Puller) pullV2Repository(tag string) (err error) {
layersDownloaded = layersDownloaded || pulledNew
}
WriteStatus(taggedName, p.config.OutStream, p.sf, layersDownloaded)
writeStatus(taggedName, p.config.OutStream, p.sf, layersDownloaded)
return nil
}

View file

@ -10,13 +10,19 @@ import (
"github.com/docker/docker/registry"
)
// ImagePushConfig stores push configuration.
type ImagePushConfig struct {
// MetaHeaders store meta data about the image (DockerHeaders with prefix X-Meta- in the request).
MetaHeaders map[string][]string
AuthConfig *cliconfig.AuthConfig
Tag string
OutStream io.Writer
// AuthConfig holds authentication information for authorizing with the registry.
AuthConfig *cliconfig.AuthConfig
// Tag is the specific variant of the image to be pushed, this tag used when image is pushed. If no tag is provided, all tags will be pushed.
Tag string
// OutStream is the output writer for showing the status of the push operation.
OutStream io.Writer
}
// Pusher is an interface to define Push behavior.
type Pusher interface {
// Push tries to push the image configured at the creation of Pusher.
// Push returns an error if any, as well as a boolean that determines whether to retry Push on the next configured endpoint.
@ -25,6 +31,7 @@ type Pusher interface {
Push() (fallback bool, err error)
}
// NewPusher returns a new instance of an implementation conforming to Pusher interface.
func (s *TagStore) NewPusher(endpoint registry.APIEndpoint, localRepo Repository, repoInfo *registry.RepositoryInfo, imagePushConfig *ImagePushConfig, sf *streamformatter.StreamFormatter) (Pusher, error) {
switch endpoint.Version {
case registry.APIVersion2:
@ -51,6 +58,8 @@ func (s *TagStore) NewPusher(endpoint registry.APIEndpoint, localRepo Repository
}
// FIXME: Allow to interrupt current push when new push of same image is done.
// Push a image to the repo.
func (s *TagStore) Push(localName string, imagePushConfig *ImagePushConfig) error {
var sf = streamformatter.NewJSONStreamFormatter()

View file

@ -87,12 +87,12 @@ func (p *v2Pusher) pushV2Repository(tag string) error {
func (p *v2Pusher) pushV2Tag(tag string) error {
logrus.Debugf("Pushing repository: %s:%s", p.repo.Name(), tag)
layerId, exists := p.localRepo[tag]
layerID, exists := p.localRepo[tag]
if !exists {
return fmt.Errorf("tag does not exist: %s", tag)
}
layer, err := p.graph.Get(layerId)
layer, err := p.graph.Get(layerID)
if err != nil {
return err
}

View file

@ -27,7 +27,7 @@ func (dcs dumbCredentialStore) Basic(*url.URL) (string, string) {
return dcs.auth.Username, dcs.auth.Password
}
// v2 only
// NewV2Repository creates a v2 only repository.
func NewV2Repository(repoInfo *registry.RepositoryInfo, endpoint registry.APIEndpoint, metaHeaders http.Header, authConfig *cliconfig.AuthConfig) (distribution.Repository, error) {
ctx := context.Background()

View file

@ -10,7 +10,7 @@ import (
"github.com/docker/docker/api/types"
)
func (s *TagStore) LookupRaw(name string) ([]byte, error) {
func (s *TagStore) lookupRaw(name string) ([]byte, error) {
image, err := s.LookupImage(name)
if err != nil || image == nil {
return nil, fmt.Errorf("No such image %s", name)

View file

@ -24,8 +24,10 @@ import (
"github.com/docker/libtrust"
)
const DEFAULTTAG = "latest"
// DefaultTag defines the default tag used when performing images related actions and no tag string is specified
const DefaultTag = "latest"
// TagStore contains information to push and pull to the repo.
type TagStore struct {
path string
graph *Graph
@ -41,16 +43,17 @@ type TagStore struct {
trustService *trust.TrustStore
}
// Repository maps image id to image tag.
type Repository map[string]string
// update Repository mapping with content of u
// Update updates repository mapping with content of repository 'u'.
func (r Repository) Update(u Repository) {
for k, v := range u {
r[k] = v
}
}
// return true if the contents of u Repository, are wholly contained in r Repository
// Contains returns true if the contents of u Repository, are wholly contained in r Repository.
func (r Repository) Contains(u Repository) bool {
for k, v := range u {
// if u's key is not present in r OR u's key is present, but not the same value
@ -61,6 +64,7 @@ func (r Repository) Contains(u Repository) bool {
return true
}
// TagStoreConfig holds tag store configuration.
type TagStoreConfig struct {
Graph *Graph
Key libtrust.PrivateKey
@ -69,6 +73,7 @@ type TagStoreConfig struct {
Trust *trust.TrustStore
}
// NewTagStore creates a tag store to specified path.
func NewTagStore(path string, cfg *TagStoreConfig) (*TagStore, error) {
abspath, err := filepath.Abs(path)
if err != nil {
@ -121,12 +126,13 @@ func (store *TagStore) reload() error {
return nil
}
// LookupImage returns the image from the store.
func (store *TagStore) LookupImage(name string) (*image.Image, error) {
// FIXME: standardize on returning nil when the image doesn't exist, and err for everything else
// (so we can pass all errors here)
repoName, ref := parsers.ParseRepositoryTag(name)
if ref == "" {
ref = DEFAULTTAG
ref = DefaultTag
}
var (
err error
@ -152,7 +158,7 @@ func (store *TagStore) LookupImage(name string) (*image.Image, error) {
return img, nil
}
// Return a reverse-lookup table of all the names which refer to each image
// ByID returns a reverse-lookup table of all the names which refer to each image.
// Eg. {"43b5f19b10584": {"base:latest", "base:v1"}}
func (store *TagStore) ByID() map[string][]string {
store.Lock()
@ -172,6 +178,7 @@ func (store *TagStore) ByID() map[string][]string {
return byID
}
// ImageName returns name of the image.
func (store *TagStore) ImageName(id string) string {
if names, exists := store.ByID()[id]; exists && len(names) > 0 {
return names[0]
@ -179,6 +186,7 @@ func (store *TagStore) ImageName(id string) string {
return stringid.TruncateID(id)
}
// DeleteAll removes images identified by a specific id from the store.
func (store *TagStore) DeleteAll(id string) error {
names, exists := store.ByID()[id]
if !exists || len(names) == 0 {
@ -199,6 +207,7 @@ func (store *TagStore) DeleteAll(id string) error {
return nil
}
// Delete removes a repo identified by a given name from the store
func (store *TagStore) Delete(repoName, ref string) (bool, error) {
store.Lock()
defer store.Unlock()
@ -231,10 +240,13 @@ func (store *TagStore) Delete(repoName, ref string) (bool, error) {
return deleted, store.save()
}
// Tag adds a new tag to an existing image.
func (store *TagStore) Tag(repoName, tag, imageName string, force bool) error {
return store.SetLoad(repoName, tag, imageName, force, nil)
}
// SetLoad stores the image to the store.
// If the imageName is already in the repo then a '-f' flag should be used to replace existing image.
func (store *TagStore) SetLoad(repoName, tag, imageName string, force bool, out io.Writer) error {
img, err := store.LookupImage(imageName)
store.Lock()
@ -319,6 +331,7 @@ func (store *TagStore) SetDigest(repoName, digest, imageName string) error {
return store.save()
}
// Get returns a repo from the store.
func (store *TagStore) Get(repoName string) (Repository, error) {
store.Lock()
defer store.Unlock()
@ -332,6 +345,7 @@ func (store *TagStore) Get(repoName string) (Repository, error) {
return nil, nil
}
// GetImage returns an image from a given repo from the store.
func (store *TagStore) GetImage(repoName, refOrID string) (*image.Image, error) {
repo, err := store.Get(repoName)
@ -361,6 +375,7 @@ func (store *TagStore) GetImage(repoName, refOrID string) (*image.Image, error)
return nil, nil
}
// GetRepoRefs returns list of repos.
func (store *TagStore) GetRepoRefs() map[string][]string {
store.Lock()
reporefs := make(map[string][]string)
@ -375,7 +390,7 @@ func (store *TagStore) GetRepoRefs() map[string][]string {
return reporefs
}
// Validate the name of a repository
// validateRepoName validates the name of a repository.
func validateRepoName(name string) error {
if name == "" {
return fmt.Errorf("Repository name can't be empty")

View file

@ -119,17 +119,17 @@ func TestLookupImage(t *testing.T) {
testOfficialImageName + ":" + testOfficialImageID,
testOfficialImageName + ":" + testOfficialImageIDShort,
testOfficialImageName,
testOfficialImageName + ":" + DEFAULTTAG,
testOfficialImageName + ":" + DefaultTag,
"docker.io/" + testOfficialImageName,
"docker.io/" + testOfficialImageName + ":" + DEFAULTTAG,
"docker.io/" + testOfficialImageName + ":" + DefaultTag,
"index.docker.io/" + testOfficialImageName,
"index.docker.io/" + testOfficialImageName + ":" + DEFAULTTAG,
"index.docker.io/" + testOfficialImageName + ":" + DefaultTag,
"library/" + testOfficialImageName,
"library/" + testOfficialImageName + ":" + DEFAULTTAG,
"library/" + testOfficialImageName + ":" + DefaultTag,
"docker.io/library/" + testOfficialImageName,
"docker.io/library/" + testOfficialImageName + ":" + DEFAULTTAG,
"docker.io/library/" + testOfficialImageName + ":" + DefaultTag,
"index.docker.io/library/" + testOfficialImageName,
"index.docker.io/library/" + testOfficialImageName + ":" + DEFAULTTAG,
"index.docker.io/library/" + testOfficialImageName + ":" + DefaultTag,
}
privateLookups := []string{
@ -138,7 +138,7 @@ func TestLookupImage(t *testing.T) {
testPrivateImageName + ":" + testPrivateImageID,
testPrivateImageName + ":" + testPrivateImageIDShort,
testPrivateImageName,
testPrivateImageName + ":" + DEFAULTTAG,
testPrivateImageName + ":" + DefaultTag,
}
invalidLookups := []string{

View file

@ -25,6 +25,7 @@ packages=(
daemon/network
docker
dockerinit
graph
image
integration-cli
pkg/chrootarchive