
This patch updates the whole code to use the latest Go version 1.21 and also updates the dependencies to the latest versions. Change-Id: Ie0b346e4622c56825aeda176f63ae4e55f06a2ce
112 lines
2.9 KiB
Go
112 lines
2.9 KiB
Go
package pod
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
|
|
v1 "k8s.io/api/core/v1"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
|
|
entry "opendev.org/airship/kubernetes-entrypoint/entrypoint"
|
|
"opendev.org/airship/kubernetes-entrypoint/logger"
|
|
"opendev.org/airship/kubernetes-entrypoint/util/env"
|
|
)
|
|
|
|
const (
|
|
PodNameEnvVar = "POD_NAME"
|
|
PodNameNotSetErrorFormat = "env POD_NAME not set, pod dependency in namespace %s will be ignored"
|
|
)
|
|
|
|
type Pod struct {
|
|
namespace string
|
|
labels map[string]string
|
|
requireSameNode bool
|
|
podName string
|
|
}
|
|
|
|
func init() {
|
|
podEnv := fmt.Sprintf("%sPOD%s", entry.DependencyPrefix, entry.JsonSuffix)
|
|
podDeps := env.SplitPodEnvToDeps(podEnv)
|
|
for _, dep := range podDeps {
|
|
pod, err := NewPod(dep.Labels, dep.Namespace, dep.RequireSameNode)
|
|
if err != nil {
|
|
logger.Error.Printf("Cannot initialize pod: %v", err)
|
|
continue
|
|
}
|
|
entry.Register(pod)
|
|
}
|
|
}
|
|
|
|
func NewPod(labels map[string]string, namespace string, requireSameNode bool) (*Pod, error) {
|
|
if os.Getenv(PodNameEnvVar) == "" {
|
|
return nil, fmt.Errorf(PodNameNotSetErrorFormat, namespace)
|
|
}
|
|
return &Pod{
|
|
labels: labels,
|
|
namespace: namespace,
|
|
requireSameNode: requireSameNode,
|
|
podName: os.Getenv(PodNameEnvVar),
|
|
}, nil
|
|
}
|
|
|
|
func (p Pod) IsResolved(ctx context.Context, entrypoint entry.EntrypointInterface) (bool, error) {
|
|
myPod, err := entrypoint.Client().Pods(env.GetBaseNamespace()).Get(ctx, p.podName, metav1.GetOptions{})
|
|
if err != nil {
|
|
return false, fmt.Errorf("getting POD: %v failed : %v", p.podName, err)
|
|
}
|
|
myHost := myPod.Status.HostIP
|
|
|
|
labelSelector := &metav1.LabelSelector{MatchLabels: p.labels}
|
|
label := metav1.FormatLabelSelector(labelSelector)
|
|
opts := metav1.ListOptions{LabelSelector: label}
|
|
|
|
matchingPodList, err := entrypoint.Client().Pods(p.namespace).List(ctx, opts)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
matchingPods := matchingPodList.Items
|
|
if len(matchingPods) == 0 {
|
|
return false, fmt.Errorf("found no pods matching labels: %v", p.labels)
|
|
}
|
|
|
|
podCount := 0
|
|
for _, pod := range matchingPods {
|
|
podCount++
|
|
pod := pod // pinning
|
|
if p.requireSameNode && !isPodOnHost(&pod, myHost) {
|
|
continue
|
|
}
|
|
if isPodReady(pod) {
|
|
return true, nil
|
|
}
|
|
}
|
|
onHostClause := ""
|
|
if p.requireSameNode {
|
|
onHostClause = " on host"
|
|
}
|
|
if podCount == 0 {
|
|
return false, fmt.Errorf("found no pods%v matching labels: %v", onHostClause, p.labels)
|
|
} else {
|
|
return false, fmt.Errorf("found %v pods%v, but none ready, matching labels: %v", podCount, onHostClause, p.labels)
|
|
}
|
|
}
|
|
|
|
func isPodOnHost(pod *v1.Pod, hostIP string) bool {
|
|
return pod.Status.HostIP == hostIP
|
|
}
|
|
|
|
func isPodReady(pod v1.Pod) bool {
|
|
for _, condition := range pod.Status.Conditions {
|
|
if condition.Type == v1.PodReady && condition.Status == "True" {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func (p Pod) String() string {
|
|
return fmt.Sprintf("Pod on same host with labels %v in namespace %s", p.labels, p.namespace)
|
|
}
|