/
list.go
113 lines (95 loc) · 3.03 KB
/
list.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package outdated
import (
"fmt"
"strings"
"github.com/minio/minio/pkg/wildcard"
"github.com/pkg/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/client-go/kubernetes"
)
type RunningImage struct {
Namespace string
Pod string
InitContainer *string
Container *string
Image string
PullableImage string
}
func (o Outdated) ListImages(configFlags *genericclioptions.ConfigFlags, imageNameCh chan string, ignoreNs []string) ([]RunningImage, error) {
config, err := configFlags.ToRESTConfig()
if err != nil {
return nil, errors.Wrap(err, "failed to read kubeconfig")
}
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
return nil, errors.Wrap(err, "failed to create clientset")
}
namespaces, err := clientset.CoreV1().Namespaces().List(metav1.ListOptions{})
if err != nil {
return nil, errors.Wrap(err, "failed to list namespaces")
}
runningImages := []RunningImage{}
for _, namespace := range namespaces.Items {
if isNamespaceExcluded(namespace.Name, ignoreNs) {
continue
}
imageNameCh <- fmt.Sprintf("%s/", namespace.Name)
pods, err := clientset.CoreV1().Pods(namespace.Name).List(metav1.ListOptions{})
if err != nil {
return nil, errors.Wrap(err, "failed to list pods")
}
for _, pod := range pods.Items {
for _, initContainerStatus := range pod.Status.InitContainerStatuses {
pullable := initContainerStatus.ImageID
if strings.HasPrefix(pullable, "docker-pullable://") {
pullable = strings.TrimPrefix(pullable, "docker-pullable://")
}
runningImage := RunningImage{
Pod: pod.Name,
Namespace: pod.Namespace,
InitContainer: &initContainerStatus.Name,
Image: initContainerStatus.Image,
PullableImage: pullable,
}
imageNameCh <- fmt.Sprintf("%s/%s", namespace.Name, runningImage.Image)
runningImages = append(runningImages, runningImage)
}
for _, containerStatus := range pod.Status.ContainerStatuses {
pullable := containerStatus.ImageID
if strings.HasPrefix(pullable, "docker-pullable://") {
pullable = strings.TrimPrefix(pullable, "docker-pullable://")
}
runningImage := RunningImage{
Pod: pod.Name,
Namespace: pod.Namespace,
Container: &containerStatus.Name,
Image: containerStatus.Image,
PullableImage: pullable,
}
imageNameCh <- fmt.Sprintf("%s/%s", namespace.Name, runningImage.Image)
runningImages = append(runningImages, runningImage)
}
}
}
// Remove exact duplicates
cleanedImages := []RunningImage{}
for _, runningImage := range runningImages {
for _, cleanedImage := range cleanedImages {
if cleanedImage.PullableImage == runningImage.PullableImage {
goto NextImage
}
}
cleanedImages = append(cleanedImages, runningImage)
NextImage:
}
return cleanedImages, nil
}
func isNamespaceExcluded(namespace string, excluded []string) bool {
for _, ex := range excluded {
if wildcard.Match(ex, namespace) {
return true
}
}
return false
}