@@ -6,20 +6,24 @@ import (
66 "os"
77 "os/exec"
88 "regexp"
9+ "strconv"
910 "strings"
1011
12+ "github.com/dustin/go-humanize"
1113 "github.com/olekukonko/tablewriter"
1214 "gopkg.in/yaml.v2"
1315)
1416
1517const (
16- gotemplate = `go-template={{range .items}} {{.metadata.namespace}} {{","}} {{.metadata.name}} {{","}} {{range .spec.containers}} {{.name}} {{","}} {{.image}} {{","}} {{.imagePullPolicy}} {{"\n"}} {{end}} {{range .spec.initContainers}} {{"(init)"}} {{.name}} {{","}} {{.image}} {{","}} {{.imagePullPolicy}} {{"\n"}} {{end}} {{end}}`
18+ podTemplate = `go-template={{range .items}} {{.metadata.namespace}} {{","}} {{.metadata.name}} {{","}} {{range .spec.containers}} {{.name}} {{","}} {{.image}} {{","}} {{.imagePullPolicy}} {{"\n"}} {{end}} {{range .spec.initContainers}} {{"(init)"}} {{.name}} {{","}} {{.image}} {{","}} {{.imagePullPolicy}} {{"\n"}} {{end}} {{end}}`
19+ nodeTemplate = `go-template={{range .items}} {{range .status.images}} {{range .names}} {{.}} {{","}} {{end}} {{.sizeBytes}} {{"\n"}} {{end}} {{end}}`
1720
1821 labelNamespace = "Namespace"
1922 labelPod = "Pod"
2023 labelContainer = "Container"
2124 labelImage = "Image"
2225 labelImagePullPolicy = "ImagePullPolicy"
26+ labelImageSize = "ImageSize"
2327)
2428
2529type Parameters struct {
@@ -33,14 +37,17 @@ type Parameters struct {
3337
3438// KubeImage is the representation of a container image used in the cluster.
3539type KubeImage struct {
36- entities []* ImageEntity
37- columns []string
38- regx * regexp.Regexp
39- params Parameters
40+ entities []* ImageEntity
41+ columns []string
42+ regx * regexp.Regexp
43+ params Parameters
44+ imageSize map [string ]int
45+ needNodeInfo bool
4046}
4147
4248// NewKubeImage creates a new KubeImage instance.
4349func NewKubeImage (regx * regexp.Regexp , params Parameters ) * KubeImage {
50+ var needNodeInfo bool
4451 names := make ([]string , 0 )
4552 for _ , c := range stringSplit (params .Columns , "," ) {
4653 switch c {
@@ -54,13 +61,18 @@ func NewKubeImage(regx *regexp.Regexp, params Parameters) *KubeImage {
5461 names = append (names , labelImage )
5562 case "4" :
5663 names = append (names , labelImagePullPolicy )
64+ case "5" :
65+ names = append (names , labelImageSize )
66+ needNodeInfo = true
5767 }
5868 }
5969
6070 return & KubeImage {
61- columns : names ,
62- params : params ,
63- regx : regx ,
71+ columns : names ,
72+ params : params ,
73+ regx : regx ,
74+ imageSize : make (map [string ]int ),
75+ needNodeInfo : needNodeInfo ,
6476 }
6577}
6678
@@ -71,6 +83,7 @@ type ImageEntity struct {
7183 Container string `json:"container,omitempty" yaml:"container,omitempty"`
7284 Image string `json:"image,omitempty" yaml:"image,omitempty"`
7385 ImagePullPolicy string `json:"imagePullPolicy,omitempty" yaml:"imagePullPolicy,omitempty"`
86+ ImageSize string `json:"imageSize,omitempty" yaml:"imageSize,omitempty"`
7487}
7588
7689func (ie * ImageEntity ) selectBy (columns []string ) []string {
@@ -87,6 +100,8 @@ func (ie *ImageEntity) selectBy(columns []string) []string {
87100 result = append (result , ie .Image )
88101 case labelImagePullPolicy :
89102 result = append (result , ie .ImagePullPolicy )
103+ case labelImageSize :
104+ result = append (result , ie .ImageSize )
90105 }
91106 }
92107 return result
@@ -106,6 +121,8 @@ func (ie *ImageEntity) filterBy(columns []string) ImageEntity {
106121 entity .Image = ie .Image
107122 case labelImagePullPolicy :
108123 entity .ImagePullPolicy = ie .ImagePullPolicy
124+ case labelImageSize :
125+ entity .ImageSize = ie .ImageSize
109126 }
110127 }
111128 return entity
@@ -142,8 +159,8 @@ func stringSplit(in, sep string) []string {
142159 return out
143160}
144161
145- // Commands builds the command to be executed based on user input.
146- func (ki * KubeImage ) Commands () []string {
162+ // podCommands builds the command to be executed based on user input.
163+ func (ki * KubeImage ) podCommands () []string {
147164 kubecfg := make ([]string , 0 )
148165 if ki .params .KubeConfig != "" {
149166 kubecfg = append (kubecfg , "--kubeconfig" , ki .params .KubeConfig )
@@ -154,18 +171,60 @@ func (ki *KubeImage) Commands() []string {
154171 }
155172
156173 if ki .params .AllNamespace {
157- return append ([]string {"get" , "pods" , "--all-namespaces" , "-o" , gotemplate }, kubecfg ... )
174+ return append ([]string {"get" , "pods" , "--all-namespaces" , "-o" , podTemplate }, kubecfg ... )
158175 } else if ki .params .Namespace != "" {
159- return append ([]string {"get" , "pods" , "-n" , ki .params .Namespace , "-o" , gotemplate }, kubecfg ... )
176+ return append ([]string {"get" , "pods" , "-n" , ki .params .Namespace , "-o" , podTemplate }, kubecfg ... )
160177 }
161- return append ([]string {"get" , "pods" , "-o" , gotemplate }, kubecfg ... )
178+ return append ([]string {"get" , "pods" , "-o" , podTemplate }, kubecfg ... )
162179}
163180
164- func (ki * KubeImage ) exec () {
165- process := exec .Command ("kubectl" , ki .Commands ()... )
181+ func (ki * KubeImage ) nodeCommands () []string {
182+ kubecfg := make ([]string , 0 )
183+ if ki .params .KubeConfig != "" {
184+ kubecfg = append (kubecfg , "--kubeconfig" , ki .params .KubeConfig )
185+ }
186+
187+ if ki .params .Context != "" {
188+ kubecfg = append (kubecfg , "--context" , ki .params .Context )
189+ }
190+
191+ return append ([]string {"get" , "nodes" , "-o" , nodeTemplate }, kubecfg ... )
192+ }
193+
194+ func (ki * KubeImage ) execNodeCommand () {
195+ process := exec .Command ("kubectl" , ki .nodeCommands ()... )
196+ bs , err := process .CombinedOutput ()
197+ if err != nil {
198+ fmt .Fprintf (os .Stderr , "[Oh...] Execute nodes command error: %v, %s" , err , string (bs ))
199+ os .Exit (1 )
200+ }
201+
202+ for _ , line := range stringSplit (string (bs ), "\n " ) {
203+ items := stringSplit (line , "," )
204+ switch len (items ) {
205+ case 3 :
206+ size , err := strconv .Atoi (items [2 ])
207+ if err != nil {
208+ continue
209+ }
210+ ki .imageSize [items [0 ]] = size
211+ ki .imageSize [items [1 ]] = size
212+ }
213+ }
214+
215+ for _ , entity := range ki .entities {
216+ size , ok := ki .imageSize [entity .Image ]
217+ if ok {
218+ entity .ImageSize = humanize .IBytes (uint64 (size ))
219+ }
220+ }
221+ }
222+
223+ func (ki * KubeImage ) execPodCommand () {
224+ process := exec .Command ("kubectl" , ki .podCommands ()... )
166225 bs , err := process .CombinedOutput ()
167226 if err != nil {
168- fmt .Fprintf (os .Stderr , "[Oh...] Execute command error: %v, %s" , err , string (bs ))
227+ fmt .Fprintf (os .Stderr , "[Oh...] Execute pods command error: %v, %s" , err , string (bs ))
169228 os .Exit (1 )
170229 }
171230
@@ -293,7 +352,10 @@ func (ki *KubeImage) yamlRender() {
293352
294353// Render renders and displays the table output.
295354func (ki * KubeImage ) Render (format string ) {
296- ki .exec ()
355+ ki .execPodCommand ()
356+ if ki .needNodeInfo {
357+ ki .execNodeCommand ()
358+ }
297359
298360 if len (ki .entities ) == 0 {
299361 fmt .Fprintln (os .Stdout , "[Oh...] No images matched!" )
0 commit comments