<p>In bash scripts, I normally use 'kubectl wait' to block until a certain pod resource is ready, e.g. something similar to this:</p>
<pre><code>kubectl wait --for=condition=Ready --timeout=2m -n mynamespace pod -l myselector
</code></pre>
<p>This works well because often times I don't know the exact name of the pod I need to wait for, and 'kubectl wait' allows me to locate the pod based on selectors and then block until it's ready.</p>
<p>Now I need to do something similar in golang code. I have seen examples of using the <a href="https://github.com/kubernetes/client-go/tree/master/examples/out-of-cluster-client-configuration" rel="nofollow noreferrer">client-go</a> library to authenticate and 'get' a specific pod by name. But I have a few questions on how to best adapt this example to my needs...</p>
<ol>
<li><p>I do not know the exact/full name of the pod to be able to 'Get()' it, which is why 'kubectl wait' is perfect as it allows me to find the pod using selectors. I assume that I should use client-go library to instead do a CoreV1().Pods().List() call instead of a Get() in order to allow me to find the pod I want using selectors?</p>
</li>
<li><p>Also, the pod may not exist immediately and might be created only after 1 minute or so, which 'kubectl wait' handles for me. In code, do I need to loop/sleep and keep performing List() until the pod exists?</p>
</li>
<li><p>Similar question to #2...once the List() does return a pod name, what is the best way in golang to 'wait' for that pod to be in a 'ready' state? I do not want to do any ugly polls with sleeps if avoidable...so is there is a better option using golang 'wait' package or similar? What do you recommend?</p>
</li>
</ol>

DaveUK
<p>How about doing it exactly the way <code>kubectl</code> does it? Basically, using <a href="https://github.com/kubernetes/kubectl/blob/master/pkg/cmd/wait/wait.go#L266" rel="noreferrer">List(...)</a> to list based on a field selector and then <a href="https://github.com/kubernetes/kubectl/blob/master/pkg/cmd/wait/wait.go#L292" rel="noreferrer"><code>Watch(...)</code></a></p>
<p>Snippet:</p>
<pre class="lang-golang prettyprint-override"><code>...
        // List with a name field selector to get the current resourceVersion to watch from (not the object's resourceVersion)
        gottenObjList, err := o.DynamicClient.Resource(info.Mapping.Resource).Namespace(info.Namespace).List(context.TODO(), metav1.ListOptions{FieldSelector: nameSelector})
        if apierrors.IsNotFound(err) {
            return info.Object, true, nil
        }
        if err != nil {
            // TODO this could do something slightly fancier if we wish
            return info.Object, false, err
        }
        if len(gottenObjList.Items) != 1 {
            return info.Object, true, nil
        }
        gottenObj := &amp;gottenObjList.Items[0]
        resourceLocation := ResourceLocation{
            GroupResource: info.Mapping.Resource.GroupResource(),
            Namespace:     gottenObj.GetNamespace(),
            Name:          gottenObj.GetName(),
        }
        if uid, ok := o.UIDMap[resourceLocation]; ok {
            if gottenObj.GetUID() != uid {
                return gottenObj, true, nil
            }
        }

        watchOptions := metav1.ListOptions{}
        watchOptions.FieldSelector = nameSelector
        watchOptions.ResourceVersion = gottenObjList.GetResourceVersion()
        objWatch, err := o.DynamicClient.Resource(info.Mapping.Resource).Namespace(info.Namespace).Watch(context.TODO(), watchOptions)
        if err != nil {
            return gottenObj, false, err
        }
...
</code></pre>
<p>✌️</p>
