package kube import ( "context" "strings" "github.com/apex/log" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" appsv1 "k8s.io/client-go/kubernetes/typed/apps/v1" batchv1 "k8s.io/client-go/kubernetes/typed/batch/v1" "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" ) type Client struct { provider ClientProvider } type Options func(*Client) func WithKubeConfigProvider(kubeconfig string) func(c *Client) { return func(c *Client) { c.provider = &DefaultProvider{provider: &PathConfigProvider{kubecfg: kubeconfig}} } } func New(opts ...Options) *Client { c := &Client{provider: &DefaultProvider{provider: &InClusterProvider{}}} for _, opt := range opts { opt(c) } return c } func (c *Client) GetImages(ctx context.Context, logger log.Interface, namespaces []string) (map[string][]string, error) { client, err := c.provider.Provide() if err != nil { return nil, err } collector := NewImageCollector() for _, ns := range namespaces { deployments, err := client.AppsV1().Deployments(ns).List(ctx, metav1.ListOptions{}) if err != nil { return nil, err } for _, deployment := range deployments.Items { for _, container := range deployment.Spec.Template.Spec.Containers { if strings.HasPrefix(container.Image, "registry.gitlab.com") { logger.Infof("Found image '%s' in deployment %s.%s", container.Image[20:], ns, deployment.Name) collector.Add(container.Image) } } } cronjobs, err := client.BatchV1().CronJobs(ns).List(ctx, metav1.ListOptions{}) if err != nil { return nil, err } for _, cronjob := range cronjobs.Items { for _, container := range cronjob.Spec.JobTemplate.Spec.Template.Spec.Containers { if strings.HasPrefix(container.Image, "registry.gitlab.com") { logger.Infof("Found image '%s' in cronjob %s.%s", container.Image[20:], ns, cronjob.Name) collector.Add(container.Image) } } } } return collector.Images(), nil } type APIClient interface { AppsV1() appsv1.AppsV1Interface BatchV1() batchv1.BatchV1Interface } type ClientProvider interface { Provide() (APIClient, error) } type DefaultProvider struct { provider ConfigProvider } func (d DefaultProvider) Provide() (APIClient, error) { config, err := d.provider.Provide() if err != nil { return nil, err } return kubernetes.NewForConfig(config) } var _ ClientProvider = &DefaultProvider{} type ConfigProvider interface { Provide() (*rest.Config, error) } type InClusterProvider struct{} func (i InClusterProvider) Provide() (*rest.Config, error) { return rest.InClusterConfig() } var _ ConfigProvider = &InClusterProvider{} type PathConfigProvider struct { kubecfg string } func (k PathConfigProvider) Provide() (*rest.Config, error) { return clientcmd.BuildConfigFromFlags("", k.kubecfg) } var _ ConfigProvider = &PathConfigProvider{}