moved configuration to fetcher object.

This commit is contained in:
Erik Brakkee 2025-03-02 17:03:03 +01:00
parent 58ef7f76e4
commit 1688aa6dea
2 changed files with 31 additions and 30 deletions

View File

@ -13,7 +13,15 @@ import (
"time"
)
func canonicalizeImageName(image string) string {
type Fetcher struct {
KubernetesNamespace string
SocketPath string
ContainerdNamespace string
Nodename string
ReadyDuration time.Duration
}
func (fetcher *Fetcher) canonicalizeImageName(image string) string {
pattern := `^(?:(?P<registry>[a-zA-Z0-9][-a-zA-Z0-9.]*[a-zA-Z0-9](?::[0-9]+)?)/)?(?P<repository>(?:[a-z0-9]+(?:(?:[._]|__|[-]+)[a-z0-9]+)*(?:/[a-z0-9]+(?:(?:[._]|__|[-]+)[a-z0-9]+)*)*)?)?(?::(?P<tag>[\w][\w.-]{0,127}))?(?:@(?P<digest>[a-z][a-z0-9]*(?:[+.-][a-z][a-z0-9]*)*:[a-zA-Z0-9*+,-./:;=@_]{32,}))?$`
re := regexp.MustCompile(pattern)
matches := re.FindStringSubmatch(image)
@ -64,11 +72,11 @@ func canonicalizeImageName(image string) string {
return fullimage
}
func isReadyForSomeTime(pod *v1.Pod, duration time.Duration) bool {
func (fetcher *Fetcher) isReadyForSomeTime(pod *v1.Pod) bool {
ready := false
for _, condition := range pod.Status.Conditions {
if condition.Type == corev1.PodReady && condition.Status == corev1.ConditionTrue {
if time.Now().Sub(condition.LastTransitionTime.Time) > duration {
if time.Now().Sub(condition.LastTransitionTime.Time) > fetcher.ReadyDuration {
ready = true
}
}
@ -79,9 +87,8 @@ func isReadyForSomeTime(pod *v1.Pod, duration time.Duration) bool {
return ready
}
func getContainers(clientset *kubernetes.Clientset, kubernetesNamespace, nodename string,
readyDuration time.Duration) map[string]bool {
pods, err := clientset.CoreV1().Pods(kubernetesNamespace).List(context.Background(),
func (fetcher *Fetcher) getContainers(clientset *kubernetes.Clientset) map[string]bool {
pods, err := clientset.CoreV1().Pods(fetcher.KubernetesNamespace).List(context.Background(),
metav1.ListOptions{})
if err != nil {
panic(err)
@ -94,21 +101,21 @@ func getContainers(clientset *kubernetes.Clientset, kubernetesNamespace, nodenam
klog.V(3).Infof("%s/%s\n", pod.Namespace, pod.Name)
for _, container := range pod.Spec.InitContainers {
klog.V(3).Infof(" %s\n", container.Image)
if pod.Spec.NodeName == nodename {
containersOnCurrentNode[canonicalizeImageName(container.Image)] = true
if pod.Spec.NodeName == fetcher.Nodename {
containersOnCurrentNode[fetcher.canonicalizeImageName(container.Image)] = true
} else {
if isReadyForSomeTime(&pod, readyDuration) {
containers[canonicalizeImageName(container.Image)] = true
if fetcher.isReadyForSomeTime(&pod) {
containers[fetcher.canonicalizeImageName(container.Image)] = true
}
}
}
for _, container := range pod.Spec.Containers {
klog.V(3).Infof(" %s\n", container.Image)
if pod.Spec.NodeName == nodename {
containersOnCurrentNode[canonicalizeImageName(container.Image)] = true
if pod.Spec.NodeName == fetcher.Nodename {
containersOnCurrentNode[fetcher.canonicalizeImageName(container.Image)] = true
} else {
if isReadyForSomeTime(&pod, readyDuration) {
containers[canonicalizeImageName(container.Image)] = true
if fetcher.isReadyForSomeTime(&pod) {
containers[fetcher.canonicalizeImageName(container.Image)] = true
}
}
}
@ -120,11 +127,10 @@ func getContainers(clientset *kubernetes.Clientset, kubernetesNamespace, nodenam
return containers
}
func pullAndPin(kubernetesNamespace, socketPath, containerdNamespace, nodename string,
readyDuration time.Duration) error {
func (fetcher *Fetcher) pullAndPin() error {
// Create the image manager
containerd, err := NewContainerd(socketPath, containerdNamespace)
containerd, err := NewContainerd(fetcher.SocketPath, fetcher.ContainerdNamespace)
if err != nil {
klog.Fatalf("Failed to create image manager: %v", err)
}
@ -136,7 +142,7 @@ func pullAndPin(kubernetesNamespace, socketPath, containerdNamespace, nodename s
clientset, _ := GetKubernetesConnection()
containers := getContainers(clientset, kubernetesNamespace, nodename, readyDuration)
containers := fetcher.getContainers(clientset)
for container, _ := range containers {
klog.V(3).Infof("Found container %s\n", container)
}

View File

@ -12,11 +12,7 @@ func main() {
klogFlags := goflags.NewFlagSet("", goflags.PanicOnError)
klog.InitFlags(klogFlags)
var kubernetesNamespace string
var socketPath string
var containerdNamespace string
var nodename string
var readyDuration time.Duration
fetcher := Fetcher{}
cmd := &cobra.Command{
Use: "kube-fetcher",
@ -26,21 +22,20 @@ Queries k8s for all running pods and makes sure that all
images referenced in pods are made available on the local k8s node and pinned
so they don't get garbage collected'`,
RunE: func(cmd *cobra.Command, args []string) error {
err := pullAndPin(kubernetesNamespace, socketPath, containerdNamespace, nodename,
readyDuration)
err := fetcher.pullAndPin()
return err
},
}
cmd.PersistentFlags().StringVar(&kubernetesNamespace, "kubernetes-namespace",
cmd.PersistentFlags().StringVar(&fetcher.KubernetesNamespace, "kubernetes-namespace",
"", "Kubernetes containerdNamespace to inspect (default is all namespaces)")
cmd.PersistentFlags().StringVar(&socketPath, "socket",
cmd.PersistentFlags().StringVar(&fetcher.SocketPath, "socket",
"/run/containerd/containerd.sock", "Containerd socket")
cmd.PersistentFlags().StringVar(&containerdNamespace, "containerd-namespace",
cmd.PersistentFlags().StringVar(&fetcher.ContainerdNamespace, "containerd-namespace",
"k8s.io", "Containerd namespace to use")
cmd.PersistentFlags().StringVar(&nodename, "nodename", "",
cmd.PersistentFlags().StringVar(&fetcher.Nodename, "nodename", "",
"Kubernetes node name the fetcher is running on, it will only fetch images running on other nodes")
cmd.PersistentFlags().DurationVar(&readyDuration, "ready-duration",
cmd.PersistentFlags().DurationVar(&fetcher.ReadyDuration, "ready-duration",
1*time.Hour, "Time a pod must be ready before its image will be fetched")
cmd.Flags().AddGoFlagSet(klogFlags)