Skip to content

Commit

Permalink
KUDO init --wait checks statefulset instead of pod (#1637)
Browse files Browse the repository at this point in the history
  • Loading branch information
alenkacz authored Aug 21, 2020
1 parent c063a82 commit 6b10260
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 55 deletions.
1 change: 1 addition & 0 deletions pkg/kudoctl/cmd/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ func (initCmd *initCmd) run() error {
if err != nil {
return errors.New("watch timed out, readiness uncertain")
}
clog.Printf("✅ KUDO is ready!")
}

return nil
Expand Down
64 changes: 9 additions & 55 deletions pkg/kudoctl/kudoinit/setup/wait.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,81 +2,35 @@ package setup

import (
"context"
"errors"
"time"

"github.com/kudobuilder/kudo/pkg/engine/health"

"k8s.io/apimachinery/pkg/util/wait"

v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/kubernetes"
corev1 "k8s.io/client-go/kubernetes/typed/core/v1"
appsv1 "k8s.io/client-go/kubernetes/typed/apps/v1"

"github.com/kudobuilder/kudo/pkg/kudoctl/kudoinit"
"github.com/kudobuilder/kudo/pkg/kudoctl/kudoinit/manager"
)

// WatchKUDOUntilReady waits for the KUDO pod to become available.
//
// Returns true if it exists. If the timeout was reached and it could not find the pod, it returns false.
// Returns no error if it exists. If the timeout was reached and it could not find the pod, it returns error.
func WatchKUDOUntilReady(client kubernetes.Interface, opts kudoinit.Options, timeout int64) error {
return wait.PollImmediate(500*time.Millisecond, time.Duration(timeout)*time.Second,
func() (bool, error) { return verifyKudoDeployment(client.CoreV1(), opts.Namespace) })
func() (bool, error) { return verifyKudoStatefulset(client.AppsV1(), opts.Namespace) })
}

func verifyKudoDeployment(client corev1.PodsGetter, namespace string) (bool, error) {
ready, err := isKUDOPodReady(client, namespace)
if err == nil && ready {
return true, nil
}
return false, nil
}

// isKUDOPodReady fetches the KUDO pod running in the given namespace and returns true if Ready Condition has a status of true
func isKUDOPodReady(client corev1.PodsGetter, namespace string) (bool, error) {
selector := manager.GenerateLabels().AsSelector()
pod, err := getFirstRunningPod(client, namespace, selector)
if err != nil {
func verifyKudoStatefulset(client appsv1.StatefulSetsGetter, namespace string) (bool, error) {
ss, err := client.StatefulSets(namespace).Get(context.TODO(), kudoinit.DefaultManagerName, metav1.GetOptions{})
if err != nil || ss == nil {
return false, err
}

s, err := managerContainerStatus(pod)
err = health.IsHealthy(ss)
if err != nil {
return false, err
}

// status.containerStatues[.name == manager].ready == true
return s.Ready, nil
}

// managerContainerStatus returns containerstatus for manager container or error if no manager or status discovered
func managerContainerStatus(pod *v1.Pod) (*v1.ContainerStatus, error) {
for _, s := range pod.Status.ContainerStatuses {
if s.Name == kudoinit.ManagerContainerName {
return &s, nil
}
}
return nil, errors.New("could not find a KUDO pod")
}

func getFirstRunningPod(client corev1.PodsGetter, namespace string, selector labels.Selector) (*v1.Pod, error) { //nolint:interfacer
options := metav1.ListOptions{LabelSelector: selector.String()}
pods, err := client.Pods(namespace).List(context.TODO(), options)
if err != nil {
return nil, err
}
if len(pods.Items) < 1 {
return nil, errors.New("could not find KUDO manager")
}
for _, p := range pods.Items {
p := p

if health.IsHealthy(&p) == nil {
return &p, nil
}
return false, nil
}
return nil, errors.New("could not find a ready KUDO pod")
return true, nil
}

0 comments on commit 6b10260

Please sign in to comment.