<p>I have this ansible (working) playbook that looks at the output of <code>kubectl get pods -o json</code> until the pod is in the <code>Running</code> state.  Now I want to extend this to multiple pods.  The core issue is that the json result of the kubectl query is a list, I know how to access the first item, but not all of the items... </p>

<pre><code>- name: wait for pods to come up
  shell: kubectl get pods -o json
  register: kubectl_get_pods
  until: kubectl_get_pods.stdout|from_json|json_query('items[0].status.phase') == "Running"
  retries: 20
</code></pre>

<p>The json object looks like,</p>

<pre><code>[  { ...  "status": { "phase": "Running" } },
   { ...  "status": { "phase": "Running" } },
   ...
]
</code></pre>

<p>Using <code>[0]</code> to access the first item worked for handling one object in the list, but I can't figure out how to extend it to multiple items.  I tried <code>[*]</code> which did not work.</p>

Martin Guthrie
<h2>The <code>kubectl wait</code> command</h2>

<p>Kubernetes introduced the <code>kubectl wait</code> in <code>v1.11</code> version:</p>

<p><a href="https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.11.md" rel="noreferrer">CHANGELOG-1.11:</a></p>

<blockquote>
  <ul>
  <li><code>kubectl wait</code> is a new command that allows waiting for one or more
  resources to be deleted or to reach a specific condition. It adds a
  <code>kubectl wait --for=[delete|condition=condition-name]</code> resource/string
  command.</li>
  </ul>
</blockquote>

<p><a href="https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.13.md" rel="noreferrer">CHANGELOG-1.13:</a></p>

<blockquote>
  <ul>
  <li><code>kubectl wait</code> now supports condition value checks other than true
  using <code>--for condition=available=false</code></li>
  </ul>
</blockquote>

<p><a href="https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.14.md" rel="noreferrer">CHANGELOG-1.14:</a></p>

<blockquote>
  <ul>
  <li>Expanded <code>kubectl wait</code> to work with more types of selectors.</li>
  <li><code>kubectl wait</code> command now supports the <code>--all</code> flag to select all
  resources in the namespace of the specified resource types.</li>
  </ul>
</blockquote>

<p>It is not intended to wait for <em>phases</em>, but for <em>conditions</em>. I think that waiting for conditions is much more assertive than waiting for phases. See the following <a href="https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-conditions" rel="noreferrer"><em>conditions</em></a>:</p>

<blockquote>
  <ul>
  <li><strong>PodScheduled</strong>: the Pod has been scheduled to a node; </li>
  <li><strong>Ready</strong>: the Pod is able to serve requests and should be added to the load balancing pools of all matching Services;</li>
  <li><strong>Initialized</strong>: all init containers have started successfully;</li>
  <li><strong>ContainersReady</strong>: all containers in the Pod are ready.</li>
  </ul>
</blockquote>

<hr>

<h2>Using <code>kubectl wait</code> with Ansible</h2>

<p>Suppose that you are automating a Kubernetes install with <code>kubeadm</code> + Ansible, and need to wait for the installation to complete:</p>

<pre><code>- name: Wait for all control-plane pods become created
  shell: "kubectl get po --namespace=kube-system --selector tier=control-plane --output=jsonpath='{.items[*].metadata.name}'"
  register: control_plane_pods_created
  until: item in control_plane_pods_created.stdout
  retries: 10
  delay: 30
  with_items:
    - etcd
    - kube-apiserver
    - kube-controller-manager
    - kube-scheduler

- name: Wait for control-plane pods become ready
  shell: "kubectl wait --namespace=kube-system --for=condition=Ready pods --selector tier=control-plane --timeout=600s"
  register: control_plane_pods_ready

- debug: var=control_plane_pods_ready.stdout_lines
</code></pre>

<p><strong>Result Example:</strong></p>

<pre><code>TASK [Wait for all control-plane pods become created] ******************************
FAILED - RETRYING: Wait all control-plane pods become created (10 retries left).
FAILED - RETRYING: Wait all control-plane pods become created (9 retries left).
FAILED - RETRYING: Wait all control-plane pods become created (8 retries left).
changed: [localhost -&gt; localhost] =&gt; (item=etcd)
changed: [localhost -&gt; localhost] =&gt; (item=kube-apiserver)
changed: [localhost -&gt; localhost] =&gt; (item=kube-controller-manager)
changed: [localhost -&gt; localhost] =&gt; (item=kube-scheduler)

TASK [Wait for control-plane pods become ready] ********************************
changed: [localhost -&gt; localhost]

TASK [debug] *******************************************************************
ok: [localhost] =&gt; {
    "control_plane_pods_ready.stdout_lines": [
        "pod/etcd-localhost.localdomain condition met", 
        "pod/kube-apiserver-localhost.localdomain condition met", 
        "pod/kube-controller-manager-localhost.localdomain condition met", 
        "pod/kube-scheduler-localhost.localdomain condition met"
    ]    
}
</code></pre>
