mirror of
				https://github.com/moby/moby.git
				synced 2022-11-09 12:21:53 -05:00 
			
		
		
		
	Fix inconsistent date formats in API
Prior to this patch, the response of - GET /images/json - GET /containers/json - GET /images/(name)/history display the Created Time as UNIX format which doesn't make sense. These should be more readable as CLI command `docker inspect` shows. Due to the case that an older client with a newer version daemon, we need the version check for now. Signed-off-by: Hu Keping <hukeping@huawei.com>
This commit is contained in:
		
							parent
							
								
									36d995a291
								
							
						
					
					
						commit
						945fc9d882
					
				
					 10 changed files with 135 additions and 22 deletions
				
			
		| 
						 | 
				
			
			@ -47,9 +47,9 @@ func (cli *DockerCli) CmdHistory(args ...string) error {
 | 
			
		|||
		}
 | 
			
		||||
		if !*quiet {
 | 
			
		||||
			if *human {
 | 
			
		||||
				fmt.Fprintf(w, "\t%s ago\t", units.HumanDuration(time.Now().UTC().Sub(time.Unix(entry.Created, 0))))
 | 
			
		||||
				fmt.Fprintf(w, "\t%s ago\t", units.HumanDuration(time.Now().UTC().Sub(entry.Created)))
 | 
			
		||||
			} else {
 | 
			
		||||
				fmt.Fprintf(w, "\t%s\t", time.Unix(entry.Created, 0).Format(time.RFC3339))
 | 
			
		||||
				fmt.Fprintf(w, "\t%s\t", entry.Created.Format(time.RFC3339))
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if *noTrunc {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -109,9 +109,9 @@ func (cli *DockerCli) CmdImages(args ...string) error {
 | 
			
		|||
 | 
			
		||||
			if !*quiet {
 | 
			
		||||
				if *showDigests {
 | 
			
		||||
					fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s ago\t%s\n", repo, tag, digest, ID, units.HumanDuration(time.Now().UTC().Sub(time.Unix(int64(image.Created), 0))), units.HumanSize(float64(image.VirtualSize)))
 | 
			
		||||
					fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s ago\t%s\n", repo, tag, digest, ID, units.HumanDuration(time.Now().UTC().Sub(image.Created)), units.HumanSize(float64(image.VirtualSize)))
 | 
			
		||||
				} else {
 | 
			
		||||
					fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\n", repo, tag, ID, units.HumanDuration(time.Now().UTC().Sub(time.Unix(int64(image.Created), 0))), units.HumanSize(float64(image.VirtualSize)))
 | 
			
		||||
					fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\n", repo, tag, ID, units.HumanDuration(time.Now().UTC().Sub(image.Created)), units.HumanSize(float64(image.VirtualSize)))
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				fmt.Fprintln(w, ID)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -151,7 +151,7 @@ func (cli *DockerCli) CmdPs(args ...string) error {
 | 
			
		|||
		}
 | 
			
		||||
 | 
			
		||||
		fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\t%s\t%s\t", ID, image, command,
 | 
			
		||||
			units.HumanDuration(time.Now().UTC().Sub(time.Unix(int64(container.Created), 0))),
 | 
			
		||||
			units.HumanDuration(time.Now().UTC().Sub(container.Created)),
 | 
			
		||||
			container.Status, api.DisplayablePorts(container.Ports), strings.Join(names, ","))
 | 
			
		||||
 | 
			
		||||
		if *size {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -353,6 +353,37 @@ func (s *Server) getImagesJSON(version version.Version, w http.ResponseWriter, r
 | 
			
		|||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// For version >= 1.19 the Created filed of image will change
 | 
			
		||||
	// from int64 to time.Time.
 | 
			
		||||
	// This is for legacy data format.
 | 
			
		||||
	if version.LessThan("1.19") {
 | 
			
		||||
		type legacyImage struct {
 | 
			
		||||
			ID          string `json:"Id"`
 | 
			
		||||
			ParentId    string
 | 
			
		||||
			RepoTags    []string
 | 
			
		||||
			RepoDigests []string
 | 
			
		||||
			Created     int64
 | 
			
		||||
			Size        int
 | 
			
		||||
			VirtualSize int
 | 
			
		||||
			Labels      map[string]string
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		legacy := []*legacyImage{}
 | 
			
		||||
		for _, img := range images {
 | 
			
		||||
			l := &legacyImage{
 | 
			
		||||
				ID:          img.ID,
 | 
			
		||||
				ParentId:    img.ParentId,
 | 
			
		||||
				RepoTags:    img.RepoTags,
 | 
			
		||||
				RepoDigests: img.RepoDigests,
 | 
			
		||||
				Created:     img.Created.Unix(),
 | 
			
		||||
				Size:        img.Size,
 | 
			
		||||
				VirtualSize: img.VirtualSize,
 | 
			
		||||
				Labels:      img.Labels,
 | 
			
		||||
			}
 | 
			
		||||
			legacy = append(legacy, l)
 | 
			
		||||
		}
 | 
			
		||||
		return writeJSON(w, http.StatusOK, legacy)
 | 
			
		||||
	}
 | 
			
		||||
	return writeJSON(w, http.StatusOK, images)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -482,6 +513,34 @@ func (s *Server) getImagesHistory(version version.Version, w http.ResponseWriter
 | 
			
		|||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// For version >= 1.19 the Created filed of image will change
 | 
			
		||||
	// from int64 to time.Time.
 | 
			
		||||
	// This is for legacy data format.
 | 
			
		||||
	if version.LessThan("1.19") {
 | 
			
		||||
		type legacyImageHistory struct {
 | 
			
		||||
			ID        string `json:"Id"`
 | 
			
		||||
			Created   int64
 | 
			
		||||
			CreatedBy string
 | 
			
		||||
			Tags      []string
 | 
			
		||||
			Size      int64
 | 
			
		||||
			Comment   string
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		legacy := []*legacyImageHistory{}
 | 
			
		||||
		for _, img := range history {
 | 
			
		||||
			l := &legacyImageHistory{
 | 
			
		||||
				ID:        img.ID,
 | 
			
		||||
				Created:   img.Created.Unix(),
 | 
			
		||||
				CreatedBy: img.CreatedBy,
 | 
			
		||||
				Tags:      img.Tags,
 | 
			
		||||
				Size:      img.Size,
 | 
			
		||||
				Comment:   img.Comment,
 | 
			
		||||
			}
 | 
			
		||||
			legacy = append(legacy, l)
 | 
			
		||||
		}
 | 
			
		||||
		return writeJSON(w, http.StatusOK, legacy)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return writeJSON(w, http.StatusOK, history)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -541,6 +600,42 @@ func (s *Server) getContainersJSON(version version.Version, w http.ResponseWrite
 | 
			
		|||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// For version >= 1.19 the Created filed of container will change
 | 
			
		||||
	// from int64 to time.Time.
 | 
			
		||||
	// This is for legacy data format.
 | 
			
		||||
	if version.LessThan("1.19") {
 | 
			
		||||
		type legacyContainer struct {
 | 
			
		||||
			ID         string            `json:"Id"`
 | 
			
		||||
			Names      []string          `json:",omitempty"`
 | 
			
		||||
			Image      string            `json:",omitempty"`
 | 
			
		||||
			Command    string            `json:",omitempty"`
 | 
			
		||||
			Created    int64             `json:",omitempty"`
 | 
			
		||||
			Ports      []types.Port      `json:",omitempty"`
 | 
			
		||||
			SizeRw     int               `json:",omitempty"`
 | 
			
		||||
			SizeRootFs int               `json:",omitempty"`
 | 
			
		||||
			Labels     map[string]string `json:",omitempty"`
 | 
			
		||||
			Status     string            `json:",omitempty"`
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		legacyContainers := []*legacyContainer{}
 | 
			
		||||
		for _, c := range containers {
 | 
			
		||||
			lc := &legacyContainer{
 | 
			
		||||
				ID:         c.ID,
 | 
			
		||||
				Names:      c.Names,
 | 
			
		||||
				Image:      c.Image,
 | 
			
		||||
				Command:    c.Command,
 | 
			
		||||
				Created:    c.Created.Unix(),
 | 
			
		||||
				Ports:      c.Ports,
 | 
			
		||||
				SizeRw:     c.SizeRw,
 | 
			
		||||
				SizeRootFs: c.SizeRootFs,
 | 
			
		||||
				Labels:     c.Labels,
 | 
			
		||||
				Status:     c.Status,
 | 
			
		||||
			}
 | 
			
		||||
			legacyContainers = append(legacyContainers, lc)
 | 
			
		||||
		}
 | 
			
		||||
		return writeJSON(w, http.StatusOK, legacyContainers)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return writeJSON(w, http.StatusOK, containers)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -50,7 +50,7 @@ type ContainerChange struct {
 | 
			
		|||
// GET "/images/{name:.*}/history"
 | 
			
		||||
type ImageHistory struct {
 | 
			
		||||
	ID        string `json:"Id"`
 | 
			
		||||
	Created   int64
 | 
			
		||||
	Created   time.Time
 | 
			
		||||
	CreatedBy string
 | 
			
		||||
	Tags      []string
 | 
			
		||||
	Size      int64
 | 
			
		||||
| 
						 | 
				
			
			@ -69,7 +69,7 @@ type Image struct {
 | 
			
		|||
	ParentId    string
 | 
			
		||||
	RepoTags    []string
 | 
			
		||||
	RepoDigests []string
 | 
			
		||||
	Created     int
 | 
			
		||||
	Created     time.Time
 | 
			
		||||
	Size        int
 | 
			
		||||
	VirtualSize int
 | 
			
		||||
	Labels      map[string]string
 | 
			
		||||
| 
						 | 
				
			
			@ -105,7 +105,7 @@ type Container struct {
 | 
			
		|||
	Names      []string          `json:",omitempty"`
 | 
			
		||||
	Image      string            `json:",omitempty"`
 | 
			
		||||
	Command    string            `json:",omitempty"`
 | 
			
		||||
	Created    int               `json:",omitempty"`
 | 
			
		||||
	Created    time.Time         `json:",omitempty"`
 | 
			
		||||
	Ports      []Port            `json:",omitempty"`
 | 
			
		||||
	SizeRw     int               `json:",omitempty"`
 | 
			
		||||
	SizeRootFs int               `json:",omitempty"`
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -149,7 +149,7 @@ func (daemon *Daemon) Containers(config *ContainersConfig) ([]*types.Container,
 | 
			
		|||
		} else {
 | 
			
		||||
			newC.Command = fmt.Sprintf("%s", container.Path)
 | 
			
		||||
		}
 | 
			
		||||
		newC.Created = int(container.Created.Unix())
 | 
			
		||||
		newC.Created = container.Created.UTC()
 | 
			
		||||
		newC.Status = container.State.String()
 | 
			
		||||
 | 
			
		||||
		newC.Ports = []types.Port{}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -58,6 +58,24 @@ disconnect
 | 
			
		|||
 | 
			
		||||
This endpoint now accepts a `since` timestamp parameter.
 | 
			
		||||
 | 
			
		||||
`GET /images/json`
 | 
			
		||||
 | 
			
		||||
**New!**
 | 
			
		||||
The `Created` field is now formatted as a RFC3339 string instead of a UNIX
 | 
			
		||||
timestamp, to be consistent with other parts of the API.
 | 
			
		||||
 | 
			
		||||
`GET /containers/json`
 | 
			
		||||
 | 
			
		||||
**New!**
 | 
			
		||||
The `Created` field is now formatted as a RFC3339 string instead of a UNIX
 | 
			
		||||
timestamp, to be consistent with other parts of the API.
 | 
			
		||||
 | 
			
		||||
`GET /images/(name)/history`
 | 
			
		||||
 | 
			
		||||
**New!**
 | 
			
		||||
The `Created` field is now formatted as a RFC3339 string instead of a UNIX
 | 
			
		||||
timestamp, to be consistent with other parts of the API.
 | 
			
		||||
 | 
			
		||||
## v1.18
 | 
			
		||||
 | 
			
		||||
### Full documentation
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -38,7 +38,7 @@ List containers
 | 
			
		|||
                     "Id": "8dfafdbc3a40",
 | 
			
		||||
                     "Image": "ubuntu:latest",
 | 
			
		||||
                     "Command": "echo 1",
 | 
			
		||||
                     "Created": 1367854155,
 | 
			
		||||
                     "Created": "2015-03-28T08:19:30.820225442Z",
 | 
			
		||||
                     "Status": "Exit 0",
 | 
			
		||||
                     "Ports": [{"PrivatePort": 2222, "PublicPort": 3333, "Type": "tcp"}],
 | 
			
		||||
                     "SizeRw": 12288,
 | 
			
		||||
| 
						 | 
				
			
			@ -48,7 +48,7 @@ List containers
 | 
			
		|||
                     "Id": "9cd87474be90",
 | 
			
		||||
                     "Image": "ubuntu:latest",
 | 
			
		||||
                     "Command": "echo 222222",
 | 
			
		||||
                     "Created": 1367854155,
 | 
			
		||||
                     "Created": "2015-01-05T19:42:44.334772611Z",
 | 
			
		||||
                     "Status": "Exit 0",
 | 
			
		||||
                     "Ports": [],
 | 
			
		||||
                     "SizeRw": 12288,
 | 
			
		||||
| 
						 | 
				
			
			@ -58,7 +58,7 @@ List containers
 | 
			
		|||
                     "Id": "3176a2479c92",
 | 
			
		||||
                     "Image": "ubuntu:latest",
 | 
			
		||||
                     "Command": "echo 3333333333333333",
 | 
			
		||||
                     "Created": 1367854154,
 | 
			
		||||
                     "Created": "2014-11-26T20:35:41.514880809Z",
 | 
			
		||||
                     "Status": "Exit 0",
 | 
			
		||||
                     "Ports":[],
 | 
			
		||||
                     "SizeRw":12288,
 | 
			
		||||
| 
						 | 
				
			
			@ -68,7 +68,7 @@ List containers
 | 
			
		|||
                     "Id": "4cb07b47f9fb",
 | 
			
		||||
                     "Image": "ubuntu:latest",
 | 
			
		||||
                     "Command": "echo 444444444444444444444444444444444",
 | 
			
		||||
                     "Created": 1367854152,
 | 
			
		||||
                     "Created": "2014-11-26T15:35:05.538305907Z",
 | 
			
		||||
                     "Status": "Exit 0",
 | 
			
		||||
                     "Ports": [],
 | 
			
		||||
                     "SizeRw": 12288,
 | 
			
		||||
| 
						 | 
				
			
			@ -1148,7 +1148,7 @@ Status Codes:
 | 
			
		|||
               "ubuntu:latest"
 | 
			
		||||
             ],
 | 
			
		||||
             "Id": "8dbd9e392a964056420e5d58ca5cc376ef18e2de93b5cc90e868a1bbc8318c1c",
 | 
			
		||||
             "Created": 1365714795,
 | 
			
		||||
             "Created": "2014-11-26T15:35:05.538305907Z",
 | 
			
		||||
             "Size": 131506275,
 | 
			
		||||
             "VirtualSize": 131506275
 | 
			
		||||
          },
 | 
			
		||||
| 
						 | 
				
			
			@ -1159,7 +1159,7 @@ Status Codes:
 | 
			
		|||
             ],
 | 
			
		||||
             "ParentId": "27cf784147099545",
 | 
			
		||||
             "Id": "b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc",
 | 
			
		||||
             "Created": 1364102658,
 | 
			
		||||
             "Created": "2014-11-21T10:18:46.654545839Z",
 | 
			
		||||
             "Size": 24653,
 | 
			
		||||
             "VirtualSize": 180116135
 | 
			
		||||
          }
 | 
			
		||||
| 
						 | 
				
			
			@ -1176,7 +1176,7 @@ Status Codes:
 | 
			
		|||
 | 
			
		||||
        [
 | 
			
		||||
          {
 | 
			
		||||
            "Created": 1420064636,
 | 
			
		||||
            "Created": "2015-03-23T15:58:07.610802612Z",
 | 
			
		||||
            "Id": "4986bf8c15363d1c5d15512d5266f8777bfba4974ac56e3270e7760f6f0a8125",
 | 
			
		||||
            "ParentId": "ea13149945cb6b1e746bf28032f02e9b5a793523481a0a18645fc77ad53c4ea2",
 | 
			
		||||
            "RepoDigests": [
 | 
			
		||||
| 
						 | 
				
			
			@ -1392,12 +1392,12 @@ Return the history of the image `name`
 | 
			
		|||
        [
 | 
			
		||||
             {
 | 
			
		||||
                     "Id": "b750fe79269d",
 | 
			
		||||
                     "Created": 1364102658,
 | 
			
		||||
                     "Created": "2014-12-15T19:52:48.480875289Z",
 | 
			
		||||
                     "CreatedBy": "/bin/bash"
 | 
			
		||||
             },
 | 
			
		||||
             {
 | 
			
		||||
                     "Id": "27cf78414709",
 | 
			
		||||
                     "Created": 1364068391,
 | 
			
		||||
                     "Created": "2013-06-13T21:03:50.821769Z",
 | 
			
		||||
                     "CreatedBy": ""
 | 
			
		||||
             }
 | 
			
		||||
        ]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,7 +30,7 @@ func (s *TagStore) History(name string) ([]*types.ImageHistory, error) {
 | 
			
		|||
	err = foundImage.WalkHistory(func(img *image.Image) error {
 | 
			
		||||
		history = append(history, &types.ImageHistory{
 | 
			
		||||
			ID:        img.ID,
 | 
			
		||||
			Created:   img.Created.Unix(),
 | 
			
		||||
			Created:   img.Created.UTC(),
 | 
			
		||||
			CreatedBy: strings.Join(img.ContainerConfig.Cmd.Slice(), " "),
 | 
			
		||||
			Tags:      lookupMap[img.ID],
 | 
			
		||||
			Size:      img.Size,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,7 +28,7 @@ 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) Less(i, j int) bool { return r[i].Created.Before(r[j].Created) }
 | 
			
		||||
 | 
			
		||||
func (s *TagStore) Images(config *ImagesConfig) ([]*types.Image, error) {
 | 
			
		||||
	var (
 | 
			
		||||
| 
						 | 
				
			
			@ -101,7 +101,7 @@ func (s *TagStore) Images(config *ImagesConfig) ([]*types.Image, error) {
 | 
			
		|||
					newImage := new(types.Image)
 | 
			
		||||
					newImage.ParentId = image.Parent
 | 
			
		||||
					newImage.ID = image.ID
 | 
			
		||||
					newImage.Created = int(image.Created.Unix())
 | 
			
		||||
					newImage.Created = image.Created.UTC()
 | 
			
		||||
					newImage.Size = int(image.Size)
 | 
			
		||||
					newImage.VirtualSize = int(image.GetParentsSize(0) + image.Size)
 | 
			
		||||
					newImage.Labels = image.ContainerConfig.Labels
 | 
			
		||||
| 
						 | 
				
			
			@ -138,7 +138,7 @@ func (s *TagStore) Images(config *ImagesConfig) ([]*types.Image, error) {
 | 
			
		|||
			newImage.RepoTags = []string{"<none>:<none>"}
 | 
			
		||||
			newImage.RepoDigests = []string{"<none>@<none>"}
 | 
			
		||||
			newImage.ID = image.ID
 | 
			
		||||
			newImage.Created = int(image.Created.Unix())
 | 
			
		||||
			newImage.Created = image.Created.UTC()
 | 
			
		||||
			newImage.Size = int(image.Size)
 | 
			
		||||
			newImage.VirtualSize = int(image.GetParentsSize(0) + image.Size)
 | 
			
		||||
			newImage.Labels = image.ContainerConfig.Labels
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue