Skip to content

Commit b66bbee

Browse files
committed
feature: add pouch history functionality
Signed-off-by: xiechengsheng <[email protected]>
1 parent 4e23bf1 commit b66bbee

File tree

13 files changed

+579
-3
lines changed

13 files changed

+579
-3
lines changed

apis/server/image_bridge.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,3 +172,15 @@ func (s *Server) saveImage(ctx context.Context, rw http.ResponseWriter, req *htt
172172

173173
return nil
174174
}
175+
176+
// imageHistory gets image history.
177+
func (s *Server) imageHistory(ctx context.Context, rw http.ResponseWriter, req *http.Request) error {
178+
imageName := mux.Vars(req)["name"]
179+
180+
history, err := s.ImageMgr.ImageHistory(ctx, imageName)
181+
if err != nil {
182+
return err
183+
}
184+
185+
return EncodeResponse(rw, http.StatusOK, history)
186+
}

apis/server/router.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ func initRoute(s *Server) http.Handler {
6464
s.addRoute(r, http.MethodPost, "/images/{name:.*}/tag", s.postImageTag)
6565
s.addRoute(r, http.MethodPost, "/images/load", withCancelHandler(s.loadImage))
6666
s.addRoute(r, http.MethodGet, "/images/save", withCancelHandler(s.saveImage))
67+
s.addRoute(r, http.MethodGet, "/images/{name:.*}/history", s.imageHistory)
6768

6869
// volume
6970
s.addRoute(r, http.MethodGet, "/volumes", s.listVolume)

apis/swagger.yml

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ paths:
197197

198198
/images/{imageid}/json:
199199
get:
200-
summary: "Inspect a image"
200+
summary: "Inspect an image"
201201
description: "Return the information about image"
202202
operationId: "ImageInspect"
203203
produces:
@@ -227,6 +227,53 @@ paths:
227227
parameters:
228228
- $ref: "#/parameters/imageid"
229229

230+
/images/{imageid}/history:
231+
get:
232+
summary: "Get an image's history"
233+
description: "Return the parent layers about image"
234+
operationId: "ImageHistory"
235+
produces:
236+
- "application/json"
237+
responses:
238+
200:
239+
description: "no error"
240+
schema:
241+
type: "array"
242+
items:
243+
type: "object"
244+
x-go-name: HistoryResultItem
245+
required: [ID, Created, CreatedBy, Author, Comment, EmptyLayer, Size]
246+
properties:
247+
ID:
248+
type: "string"
249+
x-nullable: false
250+
Created:
251+
type: "integer"
252+
format: "int64"
253+
x-nullable: false
254+
CreatedBy:
255+
type: "string"
256+
x-nullable: false
257+
Author:
258+
type: "string"
259+
x-nullable: false
260+
Comment:
261+
type: "string"
262+
x-nullable: false
263+
EmptyLayer:
264+
type: "boolean"
265+
x-nullable: false
266+
Size:
267+
type: "integer"
268+
format: "int64"
269+
x-nullable: false
270+
404:
271+
$ref: "#/responses/404ErrorResponse"
272+
500:
273+
$ref: "#/responses/500ErrorResponse"
274+
parameters:
275+
- $ref: "#/parameters/imageid"
276+
230277
/images/json:
231278
get:
232279
summary: "List Images"

apis/types/history_result_item.go

Lines changed: 173 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cli/history.go

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"strconv"
6+
"strings"
7+
"time"
8+
9+
"github.com/alibaba/pouch/pkg/utils"
10+
11+
"github.com/docker/docker/pkg/stringid"
12+
"github.com/spf13/cobra"
13+
)
14+
15+
// historyDescription is used to describe history command in detail and auto generate command doc.
16+
var historyDescription = "Return the history information on Pouch image"
17+
18+
// HistoryCommand is used to implement 'image history' command.
19+
type HistoryCommand struct {
20+
baseCommand
21+
22+
// flags for history command
23+
flagHuman bool
24+
flagQuiet bool
25+
flagNoTrunc bool
26+
}
27+
28+
// Init initialize "image history" command.
29+
func (h *HistoryCommand) Init(c *Cli) {
30+
h.cli = c
31+
h.cmd = &cobra.Command{
32+
Use: "history [OPTIONS] IMAGE",
33+
Short: "Display history information on image",
34+
Long: historyDescription,
35+
Args: cobra.ExactArgs(1),
36+
RunE: func(cmd *cobra.Command, args []string) error {
37+
return h.runHistory(args)
38+
},
39+
Example: h.example(),
40+
}
41+
h.addFlags()
42+
}
43+
44+
// addFlags adds flags for specific command.
45+
func (h *HistoryCommand) addFlags() {
46+
flagSet := h.cmd.Flags()
47+
flagSet.BoolVar(&h.flagHuman, "human", true, "Print information in human readable format")
48+
flagSet.BoolVarP(&h.flagQuiet, "quiet", "q", false, "Only show image numeric ID")
49+
flagSet.BoolVar(&h.flagNoTrunc, "no-trunc", false, "Do not truncate output")
50+
}
51+
52+
// runHistory is used to get history of an image.
53+
func (h *HistoryCommand) runHistory(args []string) error {
54+
name := args[0]
55+
56+
ctx := context.Background()
57+
apiClient := h.cli.Client()
58+
59+
history, err := apiClient.ImageHistory(ctx, name)
60+
if err != nil {
61+
return err
62+
}
63+
64+
display := h.cli.NewTableDisplay()
65+
if h.flagQuiet {
66+
for _, entry := range history {
67+
if h.flagNoTrunc {
68+
display.AddRow([]string{entry.ID})
69+
} else {
70+
display.AddRow([]string{stringid.TruncateID(entry.ID)})
71+
}
72+
}
73+
display.Flush()
74+
return nil
75+
}
76+
77+
var (
78+
imageID string
79+
createdBy string
80+
created string
81+
size string
82+
)
83+
84+
display.AddRow([]string{"IMAGE", "CREATED", "CREATED BY", "SIZE", "COMMENT"})
85+
for _, entry := range history {
86+
imageID = entry.ID
87+
createdBy = strings.Replace(entry.CreatedBy, "\t", " ", -1)
88+
if !h.flagNoTrunc {
89+
createdBy = ellipsis(createdBy, 45)
90+
imageID = stringid.TruncateID(entry.ID)
91+
}
92+
93+
if h.flagHuman {
94+
created, err = utils.FormatTimeInterval(entry.Created)
95+
if err != nil {
96+
return err
97+
}
98+
created = created + " ago"
99+
size = utils.FormatSize(entry.Size)
100+
} else {
101+
created = time.Unix(0, entry.Created).Format(time.RFC3339)
102+
size = strconv.FormatInt(entry.Size, 10)
103+
}
104+
105+
display.AddRow([]string{imageID, created, createdBy, size, entry.Comment})
106+
}
107+
display.Flush()
108+
return nil
109+
}
110+
111+
// example shows examples in history command, and is used in auto-generated cli docs.
112+
func (h *HistoryCommand) example() string {
113+
return `pouch history busybox:1.28
114+
IMAGE CREATED CREATED BY SIZE COMMENT
115+
8c811b4aec35 2 months ago /bin/sh -c #(nop) CMD ["sh"] 710.81 KB
116+
<missing> 2 months ago /bin/sh -c #(nop) ADD file:5f0439d8328ab58... 0.00 B `
117+
}
118+
119+
// ellipsis truncates a string to fit within maxlen, and appends ellipsis (...).
120+
// For maxlen of 3 and lower, no ellipsis is appended.
121+
func ellipsis(s string, maxlen int) string {
122+
r := []rune(s)
123+
if len(r) <= maxlen {
124+
return s
125+
}
126+
if maxlen <= 3 {
127+
return string(r[:maxlen])
128+
}
129+
return string(r[:maxlen-3]) + "..."
130+
}

cli/main.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ func main() {
3232
cli.AddCommand(base, &TagCommand{})
3333
cli.AddCommand(base, &LoadCommand{})
3434
cli.AddCommand(base, &SaveCommand{})
35+
cli.AddCommand(base, &HistoryCommand{})
3536

3637
cli.AddCommand(base, &InspectCommand{})
3738
cli.AddCommand(base, &RenameCommand{})

0 commit comments

Comments
 (0)