<p><em>goal and the issue</em></p>

<p>To have a container/Pod deployment that can be continously running. The command the container should execute is: <code>/usr/local/bin/python3</code> and the args to the command are: <code>"-c $'import time\\nwhile (True):\\n print(\".\");time.sleep(5);'"</code>. However, when I execute <code>kubectl apply -f "PATH_TO_THE_KUBERNETES_YAML_FILE"</code> the deployment errs with this Python exception: <code>IndentationError: unexpected indent</code>.</p>

<p>A screenshot of the error: <a href="https://i.stack.imgur.com/BACwn.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/BACwn.png" alt="enter image description here"></a></p>

<p>The Pod deployment is used as the medium for calling Python code that interacts with the <strong>Certbot</strong> client as part of tasks when using LetsEncrypt certificates.</p>

<p>See the project <a href="https://github.com/larssb/LetsEncryptIT" rel="nofollow noreferrer">here</a></p>

<p>So it should be possible to deploy the Pod >> do a <code>kubectl exec ...</code> into the container running as part of the Kubernetes deployment.</p>

<p><em>tried:</em></p>

<p>Various ways of defining the Kubernetes command args line.</p>

<ol>
<li>Via the <strong>exec</strong> Python option. E.g.: <code>python3 -c exec(\"import time\nwhile True: print(\".\");time.sleep(5);\")</code></li>
<li>Enclosing the code to execute with different combinations of <strong>`</strong> and <strong>"</strong>.</li>
<li><code>$'textwrap.dedent("""import time while True: print(".") time.sleep(5)""")'</code>...</li>
<li><p>tried using:</p>

<pre><code>args:
 - "-c $'import time\\nwhile (True):\\n print(\".\");time.sleep(5);'"
</code></pre>

<p>as an alternative to <code>args: ["-c $'import time\\nwhile (True):\\n print(\".\");time.sleep(5);'"]</code></p></li>
<li><p>confirmed that the Python code itself works.</p></li>
<li>both by using <code>Python3 -c "..."</code> directly and by calling it via a <code>docker run</code> command <a href="https://github.com/larssb/LetsEncryptIT/blob/develop/docker/LetsencryptIT/dockerfile" rel="nofollow noreferrer">to a container from this Dockerfile</a></li>
<li>I have done the usual Googling, Stack* search and so forth. I've also been on the official Kubernetes GitHub repo page and search through the issues there. Closed as well as open. And I have not seen any issue matching this one.</li>
<li><strong>Kubectl</strong> does not complain when doing <code>...apply -f YAML_FILE</code>, in regards to the format of the YAML file and to the adherence of the Pod deployment specification.</li>
<li>Tried with some bash code instead: <code>["/bin/bash", "-ecx", "while :; do printf '.'; sleep 5 ; done"]</code>&lt;-- that works.</li>
</ol>

<p><em>further info</em></p>

<ul>
<li>Python is v3.7.2</li>
<li>Kubernetes is v1.12.5-gke.10</li>
</ul>

<hr>

<p>It seems to be the combination of specifying the Python code in a Kubernetes Pod deployment YAML file ... that doesn't go well with Pythons requirement of significant whitespace and indentation. As you can read in the #tried section, it works when calling Python directly or via a Docker run/exec command.</p>

<p>How can I troubleshoot this?</p>

Lars Bingchong
<p>So I was able to get help on this on the Kubernetes Slack channel. It was a YAML syntax issue. </p>

<h2>The following in the Pod deployment YAML file solved it</h2>

<pre><code>  args:
    - |-
      -c
      import time
      while True:
          print('.')
          time.sleep(5)
</code></pre>

<p>this works in combination with the Dockerfile's....</p>

<pre><code>FROM larssb/certbot-dns-cloudflare-python3
LABEL author="https://github.com/larssb"

#
# Container config
#
WORKDIR /letsencryptit

#
# COPY IN DATA
#
COPY ./scripts /scripts/
COPY ./letsencryptit /letsencryptit/

#
# INSTALL
#
RUN pip install --upgrade google-api-python-client --disable-pip-version-check --no-cache-dir \
    &amp;&amp; pip install --upgrade oauth2client --disable-pip-version-check --no-cache-dir \
    &amp;&amp; pip install --upgrade sty --disable-pip-version-check --no-cache-dir \
    &amp;&amp; chmod +x /scripts/deploy-hook-runner.sh

# Set an ENTRYPOINT to override the entrypoint specified in certbot/certbot
ENTRYPOINT ["/usr/local/bin/python3"]
CMD ["-c"]
</code></pre>

<p><code>ENTRYPOINT</code>, as this is re-used by the Pod deployment. However, the Dockerfile's <code>CMD</code> is overwritten by the <code>args</code> property in the Pod deployment YAML file.</p>

<h2>The args property explained in detail</h2>

<ul>
<li>The <code>-c</code> is a parameter to the Python binary</li>
<li>The rest is std. Python code, to have the container, deployed via the Pod deployment, continuously run so that it can be on standby for command calls to it via <code>kubectl exec</code></li>
</ul>

<h2>The key</h2>

<p>This part of the <code>args</code> property > <code>- |-</code>. It strips the line feed and any trailing blank lines. Making it possible to state a multi-line Python block of code</p>

<h2>Documentation</h2>

<ul>
<li>A gist with example code on the required syntax in the <code>args</code> property. Find it <a href="https://gist.github.com/grampelberg/f4d2b2f17e037d303c07ac585dd52781" rel="nofollow noreferrer">here</a>.</li>
<li>The <a href="https://github.com/larssb/LetsEncryptIT/blob/develop/docker/LetsencryptIT/dockerfile" rel="nofollow noreferrer">Dockerfile</a> used</li>
<li>The Kubernetes Pod deployment YAML file. Check it out <a href="https://github.com/larssb/LetsEncryptIT/blob/develop/kubernetes/deploys/letsencryptit-pod.yml" rel="nofollow noreferrer">here</a></li>
<li><a href="https://stackoverflow.com/a/21699210/2191231">On the YAML "strip" syntax</a></li>
</ul>

<hr>

<p>Kudos to @wizzwizz4, @a_guest for your comments and suggestions. They helped me troubleshoot this, narrow in on a solution.
Also a big thank you to Mr. @grampelberg on the Kubernetes Slack channel for assisting me and providing the solution.</p>
