@@ -22,21 +22,27 @@ const (
2222 labelImagePullPolicy = "ImagePullPolicy"
2323)
2424
25+ type Parameters struct {
26+ AllNamespace bool
27+ Namespace string
28+ Columns string
29+ KubeConfig string
30+ Context string
31+ Unique bool
32+ }
33+
2534// KubeImage is the representation of a container image used in the cluster.
2635type KubeImage struct {
27- entities []* ImageEntity
28- allNamespace bool
29- namespace string
30- columns []string
31- kubeconfig string
32- context string
33- regx * regexp.Regexp
36+ entities []* ImageEntity
37+ columns []string
38+ regx * regexp.Regexp
39+ params Parameters
3440}
3541
3642// NewKubeImage creates a new KubeImage instance.
37- func NewKubeImage (regx * regexp.Regexp , allNamespace bool , namespace , columns , kubeconfig , context string ) * KubeImage {
43+ func NewKubeImage (regx * regexp.Regexp , params Parameters ) * KubeImage {
3844 names := make ([]string , 0 )
39- for _ , c := range stringSplit (columns , "," ) {
45+ for _ , c := range stringSplit (params . Columns , "," ) {
4046 switch c {
4147 case "0" :
4248 names = append (names , labelNamespace )
@@ -52,12 +58,9 @@ func NewKubeImage(regx *regexp.Regexp, allNamespace bool, namespace, columns, ku
5258 }
5359
5460 return & KubeImage {
55- allNamespace : allNamespace ,
56- columns : names ,
57- namespace : namespace ,
58- kubeconfig : kubeconfig ,
59- context : context ,
60- regx : regx ,
61+ columns : names ,
62+ params : params ,
63+ regx : regx ,
6164 }
6265}
6366
@@ -142,23 +145,23 @@ func stringSplit(in, sep string) []string {
142145// Commands builds the command to be executed based on user input.
143146func (ki * KubeImage ) Commands () []string {
144147 kubecfg := make ([]string , 0 )
145- if ki .kubeconfig != "" {
146- kubecfg = append (kubecfg , "--kubeconfig" , ki .kubeconfig )
148+ if ki .params . KubeConfig != "" {
149+ kubecfg = append (kubecfg , "--kubeconfig" , ki .params . KubeConfig )
147150 }
148151
149- if ki .context != "" {
150- kubecfg = append (kubecfg , "--context" , ki .context )
152+ if ki .params . Context != "" {
153+ kubecfg = append (kubecfg , "--context" , ki .params . Context )
151154 }
152155
153- if ki .allNamespace {
156+ if ki .params . AllNamespace {
154157 return append ([]string {"get" , "pods" , "--all-namespaces" , "-o" , gotemplate }, kubecfg ... )
155- } else if ki .namespace != "" {
156- return append ([]string {"get" , "pods" , "-n" , ki .namespace , "-o" , gotemplate }, kubecfg ... )
158+ } else if ki .params . Namespace != "" {
159+ return append ([]string {"get" , "pods" , "-n" , ki .params . Namespace , "-o" , gotemplate }, kubecfg ... )
157160 }
158161 return append ([]string {"get" , "pods" , "-o" , gotemplate }, kubecfg ... )
159162}
160163
161- func (ki * KubeImage ) run () {
164+ func (ki * KubeImage ) exec () {
162165 process := exec .Command ("kubectl" , ki .Commands ()... )
163166 bs , err := process .CombinedOutput ()
164167 if err != nil {
@@ -206,6 +209,26 @@ func (ki *KubeImage) run() {
206209 }
207210}
208211
212+ func (ki * KubeImage ) groupBy () []* ImageEntity {
213+ if ! ki .params .Unique {
214+ return ki .entities
215+ }
216+
217+ set := make (map [string ]struct {})
218+ entities := make ([]* ImageEntity , 0 )
219+
220+ for i , entity := range ki .entities {
221+ k := fmt .Sprintf ("%s/%s/%s/%s" , entity .Namespace , entity .Container , entity .Image , entity .ImagePullPolicy )
222+ if _ , ok := set [k ]; ok {
223+ continue
224+ }
225+
226+ set [k ] = struct {}{}
227+ entities = append (entities , ki .entities [i ])
228+ }
229+ return entities
230+ }
231+
209232func (ki * KubeImage ) summary () {
210233 namespaceCnt := NewCounter ()
211234 podCnt := NewCounter ()
@@ -230,15 +253,18 @@ func (ki *KubeImage) tableRender() {
230253 table .SetAutoFormatHeaders (false )
231254 table .SetAutoMergeCells (true )
232255 table .SetRowLine (true )
233- for _ , entity := range ki .entities {
256+
257+ entities := ki .groupBy ()
258+ for _ , entity := range entities {
234259 table .Append (entity .selectBy (ki .columns ))
235260 }
236261 table .Render ()
237262}
238263
239264func (ki * KubeImage ) jsonRender () {
240- records := make ([]ImageEntity , 0 , len (ki .entities ))
241- for _ , entity := range ki .entities {
265+ entities := ki .groupBy ()
266+ records := make ([]ImageEntity , 0 , len (entities ))
267+ for _ , entity := range entities {
242268 records = append (records , entity .filterBy (ki .columns ))
243269 }
244270
@@ -251,8 +277,9 @@ func (ki *KubeImage) jsonRender() {
251277}
252278
253279func (ki * KubeImage ) yamlRender () {
254- records := make ([]ImageEntity , 0 , len (ki .entities ))
255- for _ , entity := range ki .entities {
280+ entities := ki .groupBy ()
281+ records := make ([]ImageEntity , 0 , len (entities ))
282+ for _ , entity := range entities {
256283 records = append (records , entity .filterBy (ki .columns ))
257284 }
258285
@@ -266,7 +293,7 @@ func (ki *KubeImage) yamlRender() {
266293
267294// Render renders and displays the table output.
268295func (ki * KubeImage ) Render (format string ) {
269- ki .run ()
296+ ki .exec ()
270297
271298 if len (ki .entities ) == 0 {
272299 fmt .Fprintln (os .Stdout , "[Oh...] No images matched!" )
0 commit comments