<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/"><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://mehmandarov.com/tag/field-notes/feed.xml" rel="self" type="application/atom+xml"/><link href="https://mehmandarov.com/tag/field-notes/" rel="alternate" type="text/html"/><updated>2019-03-01T07:01:00+01:00</updated><id>https://mehmandarov.com/tag/field-notes/feed.xml</id><title type="html">Rustam Mehmandarov - tag: field notes</title><subtitle type="text">Posts tagged &quot;field notes&quot; on Rustam Mehmandarov.</subtitle><author><name>Rustam Mehmandarov</name></author><entry><title type="html">Configuring Slack Notifications for Google Cloud Build</title><link href="https://mehmandarov.com/slack-notifications-for-cloud-build/" rel="alternate" type="text/html" title="Configuring Slack Notifications for Google Cloud Build"/><published>2019-03-01T07:01:00+01:00</published><updated>2019-03-01T07:01:00+01:00</updated><id>https://mehmandarov.com/slack-notifications-for-cloud-build</id><content type="html" xml:base="https://mehmandarov.com/slack-notifications-for-cloud-build/"><![CDATA[<p><em>Adding Slack notifications for your Google Cloud Build jobs explained with code examples and screenshots.</em></p>

<ul>
  <li><a href="#intro">Intro</a></li>
  <li><a href="#1-before-you-begin">1. Before you begin</a></li>
  <li><a href="#2-create-a-cloud-function">2. Create a Cloud Function</a></li>
  <li><a href="#3-deploy-the-cloud-function">3. Deploy the Cloud Function</a></li>
</ul>

<hr />

<h2 id="intro">Intro</h2>

<p>Recently we decided to migrate our builds from Travis CI to Google Cloud Build to speed up the builds. The process was quite easy and flawless; however, we were still missing a few minor things. One of them was the notifications from Cloud Build to our <code class="language-plaintext highlighter-rouge">#ops</code> channel in Slack. This was slightly annoying because you would not know if the build was finished and the site was deployed, or if it failed for some reason.</p>

<p>Integrating with Cloud Build was a bit more different than what you are used to from integrations with Jenkins or Travis CI. Normally you would just create a webhook that would call an interface in the Slack API. In Cloud Build, on the other hand, everything is getting posted to the Pub/Sub queue built into the platform, and here you would just need to subscribe to the specific queue and listen for the events. To achieve the latter, you would need a small serverless function to listen for these events and to call the Slack API.</p>

<p><img src="/assets/images/posts-images/2019-03-01-architecture.png" alt="The Architecture" class="bigger-image" /></p>
<figcaption class="caption">The Architecture.</figcaption>
<p><br /></p>

<p>Note that here we will, technically, be using paid services on Google Cloud Platform, as both Cloud Build, Cloud Pub/Sub, and Cloud Functions are billable components. However, since all the components above provide a generous free tier, you will need to work hard to get passed the free tier with this setup.</p>

<ul>
  <li><strong>Cloud Build:</strong> Free first 120 builds-minutes per day for <code class="language-plaintext highlighter-rouge">Basic</code> machine type (<code class="language-plaintext highlighter-rouge">n1-standard-1</code>).</li>
  <li><strong>Cloud Pub/Sub:</strong> Free first 10GB per month (<a href="https://cloud.google.com/pubsub/pricing">pricing</a>).</li>
  <li><strong>Cloud Functions:</strong> Free first 2 million invocations per month (<a href="https://cloud.google.com/functions/pricing">pricing</a>).</li>
</ul>

<h2 id="1-before-you-begin">1. Before you begin</h2>

<h3 id="11-prepare-your-gcp-project">1.1 Prepare your GCP project</h3>

<p><em>I assume you have a Google Cloud Account, and that you have signed in to your account.</em></p>

<ol>
  <li>Select or create a Google Cloud Platform project, e.g. from the <a href="https://console.cloud.google.com/cloud-resource-manager">Manage resources page</a>.</li>
  <li>Make sure that <a href="https://cloud.google.com/billing/docs/how-to/modify-project">billing is enabled</a> for your Google Cloud Platform project.</li>
  <li>Enable the Cloud Functions and Cloud Pub/Sub. You can also enable the APIs using this <a href="https://console.cloud.google.com/flows/enableapi?apiid=cloudfunctions,pubsub">link</a>.</li>
  <li>Use <a href="https://cloud.google.com/shell/docs/quickstart">Cloud Shell</a> right from the browser, or you can <a href="https://cloud.google.com/sdk/docs/">Install and initialize the Cloud SDK</a> on your own machine.</li>
  <li>If you have installed the Cloud SDK, update and install gcloud components:</li>
</ol>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">gcloud components update <span class="o">&amp;&amp;</span>
gcloud components <span class="nb">install </span>alpha beta</code></pre></figure>

<h3 id="12-prepare-your-slack-app">1.2 Prepare your Slack App</h3>

<p><em>I assume you have Slack installed and that you have created and signed-in to your account.</em></p>

<p>Create a <a href="https://api.slack.com/apps?new_app=1">new Slack app</a>:</p>

<ol>
  <li>Choose the app&#8217;s name and your Slack team. Click Create.</li>
  <li>Click Incoming Webhooks.</li>
  <li>Activate incoming webhooks.</li>
  <li>Click Add New Webhook to Workspace. An authorization page opens.</li>
  <li>From the drop-down menu, select the channel to which you would like notifications sent.</li>
  <li>Click Authorize.</li>
  <li>A webhook for your Slack application has been created. Copy the webhook URL and save it for later use.</li>
</ol>

<h2 id="2-create-a-cloud-function">2. Create a Cloud Function</h2>

<p>We need to create a Cloud Storage bucket to stage your Cloud Functions files. Use <code class="language-plaintext highlighter-rouge">[STAGING_BUCKET_NAME]</code> that is a globally-unique bucket name (such as <code class="language-plaintext highlighter-rouge">[PROJECT-ID]_cloudbuilds</code>):</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">gsutil mb gs://[STAGING_BUCKET_NAME]</code></pre></figure>

<p>You should see the following output:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">Creating gs://[PROJECT-ID]_cloudbuilds/[STAGING_BUCKET_NAME]...</code></pre></figure>

<p>Next, create a directory on your local system for the application code:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nb">mkdir</span> ~/gcb_slack
<span class="nb">cd</span> ~/gcb_slack</code></pre></figure>

<p>Then, create the following two files in the <code class="language-plaintext highlighter-rouge">gcb_slack</code> directory.</p>

<p><strong>File 1:</strong> <code class="language-plaintext highlighter-rouge">package.json</code></p>

<figure class="highlight"><pre><code class="language-json" data-lang="json"><span class="p">{</span><span class="w">
  </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"google-container-slack"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"version"</span><span class="p">:</span><span class="w"> </span><span class="s2">"0.0.1"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"description"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Slack integration for Google Cloud Build, using Google Cloud Functions"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"main"</span><span class="p">:</span><span class="w"> </span><span class="s2">"index.js"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"dependencies"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nl">"@slack/client"</span><span class="p">:</span><span class="w"> </span><span class="s2">"4.10.0"</span><span class="w">
  </span><span class="p">}</span><span class="w">
</span><span class="p">}</span></code></pre></figure>

<p><strong>File 2:</strong> <code class="language-plaintext highlighter-rouge">index.js</code></p>

<p><em>Note: Make sure to update <code class="language-plaintext highlighter-rouge">SLACK_WEBHOOK_URL</code> in the code below.</em></p>

<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="kd">const</span> <span class="nx">IncomingWebhook</span> <span class="o">=</span> <span class="nf">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">@slack/client</span><span class="dl">'</span><span class="p">).</span><span class="nx">IncomingWebhook</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">SLACK_WEBHOOK_URL</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">&lt;INSERT YOUR WEBHOOK FROM STEP 1.2&gt;</span><span class="dl">"</span>

<span class="kd">const</span> <span class="nx">webhook</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">IncomingWebhook</span><span class="p">(</span><span class="nx">SLACK_WEBHOOK_URL</span><span class="p">);</span>

<span class="c1">// subscribe is the main function called by Cloud Functions.</span>
<span class="nx">module</span><span class="p">.</span><span class="nx">exports</span><span class="p">.</span><span class="nx">subscribe</span> <span class="o">=</span> <span class="p">(</span><span class="nx">event</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
 <span class="kd">const</span> <span class="nx">build</span> <span class="o">=</span> <span class="nf">eventToBuild</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">data</span><span class="p">.</span><span class="nx">data</span><span class="p">);</span>

  <span class="c1">// Skip if the current status is not in the status list.</span>
  <span class="c1">// Add additional statues to list if you'd like:</span>
  <span class="c1">// QUEUED, WORKING, SUCCESS, FAILURE,</span>
  <span class="c1">// INTERNAL_ERROR, TIMEOUT, CANCELLED</span>
  <span class="kd">const</span> <span class="nx">status</span> <span class="o">=</span> <span class="p">[</span><span class="dl">'</span><span class="s1">SUCCESS</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">FAILURE</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">INTERNAL_ERROR</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">TIMEOUT</span><span class="dl">'</span><span class="p">];</span>
  <span class="k">if </span><span class="p">(</span><span class="nx">status</span><span class="p">.</span><span class="nf">indexOf</span><span class="p">(</span><span class="nx">build</span><span class="p">.</span><span class="nx">status</span><span class="p">)</span> <span class="o">===</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="nf">callback</span><span class="p">();</span>
  <span class="p">}</span>

  <span class="c1">// Send message to Slack.</span>
  <span class="kd">const</span> <span class="nx">message</span> <span class="o">=</span> <span class="nf">createSlackMessage</span><span class="p">(</span><span class="nx">build</span><span class="p">);</span>
  <span class="nx">webhook</span><span class="p">.</span><span class="nf">send</span><span class="p">(</span><span class="nx">message</span><span class="p">,</span> <span class="nx">callback</span><span class="p">);</span>
<span class="p">};</span>

<span class="c1">// eventToBuild transforms pubsub event message to a build object.</span>
<span class="kd">const</span> <span class="nx">eventToBuild</span> <span class="o">=</span> <span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="k">return</span> <span class="nx">JSON</span><span class="p">.</span><span class="nf">parse</span><span class="p">(</span><span class="k">new</span> <span class="nc">Buffer</span><span class="p">(</span><span class="nx">data</span><span class="p">,</span> <span class="dl">'</span><span class="s1">base64</span><span class="dl">'</span><span class="p">).</span><span class="nf">toString</span><span class="p">());</span>
<span class="p">}</span>

<span class="c1">// createSlackMessage create a message from a build object.</span>
<span class="kd">const</span> <span class="nx">createSlackMessage</span> <span class="o">=</span> <span class="p">(</span><span class="nx">build</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="kd">let</span> <span class="nx">message</span> <span class="o">=</span> <span class="p">{</span>
   <span class="na">text</span><span class="p">:</span> <span class="s2">`Build </span><span class="se">\`</span><span class="p">${</span><span class="nx">build</span><span class="p">.</span><span class="nx">id</span><span class="p">}</span><span class="se">\`</span><span class="s2">`</span><span class="p">,</span>
    <span class="na">mrkdwn</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
    <span class="na">attachments</span><span class="p">:</span> <span class="p">[</span>
      <span class="p">{</span>
        <span class="na">title</span><span class="p">:</span> <span class="dl">'</span><span class="s1">Build logs - Your Custom Message Goes Here</span><span class="dl">'</span><span class="p">,</span>
        <span class="na">title_link</span><span class="p">:</span> <span class="nx">build</span><span class="p">.</span><span class="nx">logUrl</span><span class="p">,</span>
        <span class="na">fields</span><span class="p">:</span> <span class="p">[{</span>
          <span class="na">title</span><span class="p">:</span> <span class="dl">'</span><span class="s1">Status</span><span class="dl">'</span><span class="p">,</span>
          <span class="na">value</span><span class="p">:</span> <span class="nx">build</span><span class="p">.</span><span class="nx">status</span>
        <span class="p">}]</span>
      <span class="p">}</span>
    <span class="p">]</span>
  <span class="p">};</span>
  <span class="k">return</span> <span class="nx">message</span>
<span class="p">}</span></code></pre></figure>

<h2 id="3-deploy-the-cloud-function">3. Deploy the Cloud Function</h2>

<p>To deploy the subscribe function with a Cloud Pub/Sub trigger, run the following command in the <code class="language-plaintext highlighter-rouge">gcb_slack</code> directory:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">gcloud functions deploy subscribe <span class="nt">--stage-bucket</span> <span class="o">[</span>STAGING_BUCKET_NAME] <span class="se">\</span>
    <span class="nt">--trigger-topic</span> cloud-builds</code></pre></figure>

<p>where <code class="language-plaintext highlighter-rouge">[STAGING_BUCKET_NAME]</code> is the name of your staging Cloud Storage Bucket that you defined earlier.</p>

<p>You should see an output confirming the creation of the cloud function and <code class="language-plaintext highlighter-rouge">status: READY</code>.</p>

<p>After you&#8217;ve completed deployment of the Cloud Function, when a build event occurs, you will receive a Slack notification.</p>

<p><img src="/assets/images/posts-images/2019-03-01-slack-app.png" alt="The Slack App in action" /></p>
<figcaption class="caption">The Slack App in action.</figcaption>
<p><br /></p>

<p>Also, feel free to customize your app, like adding a custom icon, as I did with mine. &#9757;&#65039;</p>

<hr />]]></content><author><name>Rustam Mehmandarov</name></author><summary type="html">Setting up Slack notifications for Google Cloud Build jobs with code examples and screenshots.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://mehmandarov.com/assets/images/posts-images/lego-bots.jpg"/><category term="blog"/><category term="field notes"/><category term="automation"/><category term="cloud"/><category term="english"/></entry><entry><title type="html">Disposable Docker Containers</title><link href="https://mehmandarov.com/disposable-docker-containers/" rel="alternate" type="text/html" title="Disposable Docker Containers"/><published>2019-01-01T11:01:00+01:00</published><updated>2019-01-01T11:01:00+01:00</updated><id>https://mehmandarov.com/disposable-docker-containers</id><content type="html" xml:base="https://mehmandarov.com/disposable-docker-containers/"><![CDATA[<p><em>Disposable containers may sound like a tautology. However, here we will be looking into single-use, ephemeral containers &#8211; even in the context of the containers &#8211; that are used for building and testing applications, and disposing of them shortly after.</em></p>

<hr />

<p>Containers are something that we use to run our applications and, normally, we dispose of the whole container when we build a new version of the application or need to upgrade something in the setup. This means that containers are generally having a short lifespan.</p>

<p>However, in this case, I want to show you how to build something that exists for an even shorter period of time and that can be used as an alternative to a local setup for building and testing applications locally before pushing it to test, staging, production, etc.</p>

<p>This is a simplified example of what is being done on a much bigger scale with moving your CI/CD pipelines to such disposable containers, and with libraries like <a href="https://www.testcontainers.org/">Testcontainers</a>.</p>

<p>In this case, I would like to show you how to setup Jekyll applications, but this can be easily applied to any kind of applications written in any of your favorite languages, like Java or Python. Until recently, I have been running a Jekyll installation locally with all dependencies installed on my machine. However, it has been a bit challenging when moving between machines and reinstalling operating systems. To simplify the process, I decided to containerize the local build and test processes.</p>

<p>I wanted the following:</p>

<ul>
  <li>To build my code from and to the local folder on my (host) machine</li>
  <li>Run the application (in this case this blog) from a local folder on my (host) machine</li>
  <li>Avoid setting up the environment, or have a minimal and portable setup</li>
  <li>Avoid environment clean-up &#8211; I didn&#8217;t want to hold on to the unnecessary containers and container images</li>
</ul>

<h2 id="tldr-the-solution"><em><strong>TL;DR</strong></em>: The solution</h2>
<p><em><strong>(see next section for the explanation)</strong></em></p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span><span class="nb">export </span><span class="nv">JEKYLL_VERSION</span><span class="o">=</span>3.8
<span class="nv">$ </span>docker run <span class="nt">--rm</span> <span class="nt">--volume</span><span class="o">=</span><span class="s2">"</span><span class="nv">$PWD</span><span class="s2">:/srv/jekyll"</span> <span class="se">\</span>
       <span class="nt">-it</span> jekyll/jekyll:<span class="nv">$JEKYLL_VERSION</span> jekyll build
<span class="nv">$ </span>docker run <span class="nt">--name</span> newblog <span class="nt">--volume</span><span class="o">=</span><span class="s2">"</span><span class="nv">$PWD</span><span class="s2">:/srv/jekyll"</span> <span class="nt">-p</span> 4000:4000 <span class="se">\</span>
       <span class="nt">-it</span> jekyll/jekyll:<span class="nv">$JEKYLL_VERSION</span> jekyll serve <span class="nt">--watch</span> <span class="nt">--drafts</span></code></pre></figure>

<h2 id="explanation--line-by-line">Explanation &#8211; line by line</h2>

<p>So, let&#8217;s take a closer look at each of the lines:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">1: <span class="nb">export </span><span class="nv">JEKYLL_VERSION</span><span class="o">=</span>3.8</code></pre></figure>

<p>Just setting up versions that will be used later &#8211; a bit of housekeeping. Nothing exciting here.</p>

<hr />

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">2: docker run <span class="nt">--rm</span> <span class="nt">--volume</span><span class="o">=</span><span class="s2">"</span><span class="nv">$PWD</span><span class="s2">:/srv/jekyll"</span> <span class="se">\</span>
        <span class="nt">-it</span> jekyll/jekyll:<span class="nv">$JEKYLL_VERSION</span> jekyll build</code></pre></figure>

<p>Here, we build the code and output it to the same disk volume as the source code, i.e. the volume that is shared with my host machine. Now I have the built version on my machine without the hassle of setting up the local build environment. In addition to that, I will be doing some clean-up, by deleting the build container after the build job is finished.</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">--rm</code> &#8211; just execute the command and clean-up (remove the container, file system, etc.)</li>
  <li><code class="language-plaintext highlighter-rouge">--volume</code> &#8211; mapping the current directory to <code class="language-plaintext highlighter-rouge">/srv/jekyll</code> in the container</li>
  <li><code class="language-plaintext highlighter-rouge">-it</code> instructs Docker to allocate a pseudo-TTY connected to the container&#8217;s stdin; creating an interactive shell in the container
    <ul>
      <li><code class="language-plaintext highlighter-rouge">-i</code> &#8211; attach container&#8217;s STDIN</li>
      <li><code class="language-plaintext highlighter-rouge">-t</code> &#8211; allocate a pseudo-TTY</li>
    </ul>
  </li>
  <li><code class="language-plaintext highlighter-rouge">jekyll/jekyll:$JEKYLL_VERSION</code> &#8211; Docker <a href="https://github.com/envygeeks/jekyll-docker/blob/master/README.md">image</a> to use and the tag</li>
  <li><code class="language-plaintext highlighter-rouge">jekyll build</code> &#8211; command to run</li>
</ul>

<hr />

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">3. docker run <span class="nt">--name</span> newblog <span class="nt">--volume</span><span class="o">=</span><span class="s2">"</span><span class="nv">$PWD</span><span class="s2">:/srv/jekyll"</span> <span class="nt">-p</span> 4000:4000 <span class="se">\</span>
        <span class="nt">-it</span> jekyll/jekyll:<span class="nv">$JEKYLL_VERSION</span> jekyll serve <span class="nt">--watch</span> <span class="nt">--drafts</span></code></pre></figure>

<p>This will create another container that will be running our application. Here we will need to add a few other parameters &#8211; like mapping the container ports to the ports on the local machine and giving the container a name.</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">--name newblog</code> &#8211; give your container a name</li>
  <li><code class="language-plaintext highlighter-rouge">--volume</code> &#8211; mapping the current directory to <code class="language-plaintext highlighter-rouge">/srv/jekyll</code> in the container</li>
  <li><code class="language-plaintext highlighter-rouge">-p</code> &#8211; bind port 4000 of the container to TCP port 4000 (<code class="language-plaintext highlighter-rouge">-p host_machine:container</code>)</li>
  <li><code class="language-plaintext highlighter-rouge">-it</code> instructs Docker to allocate a pseudo-TTY connected to the container&#8217;s stdin; creating an interactive shell in the container
    <ul>
      <li><code class="language-plaintext highlighter-rouge">-i</code> &#8211; attach container&#8217;s STDIN</li>
      <li><code class="language-plaintext highlighter-rouge">-t</code> &#8211; allocate a pseudo-TTY</li>
    </ul>
  </li>
  <li><code class="language-plaintext highlighter-rouge">jekyll/jekyll:$JEKYLL_VERSION</code> &#8211; Docker <a href="https://github.com/envygeeks/jekyll-docker/blob/master/README.md">image</a> to use and the tag</li>
  <li><code class="language-plaintext highlighter-rouge">jekyll serve --watch --drafts</code> &#8211; command to run</li>
</ul>

<p>Now you can stop the container with <code class="language-plaintext highlighter-rouge">CTRL+c</code>, and restart it again with:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>docker start newblog <span class="nt">-i</span></code></pre></figure>

<p>If you don&#8217;t want the container being persistent on your system, you can simply add <code class="language-plaintext highlighter-rouge">--rm</code> as in the previous command:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>docker run <span class="nt">--rm</span> <span class="nt">--name</span> newblog <span class="nt">--volume</span><span class="o">=</span><span class="s2">"</span><span class="nv">$PWD</span><span class="s2">:/srv/jekyll"</span> <span class="nt">-p</span> 4000:4000 <span class="se">\</span>
       <span class="nt">-it</span> jekyll/jekyll:<span class="nv">$JEKYLL_VERSION</span> jekyll serve <span class="nt">--watch</span> <span class="nt">--drafts</span></code></pre></figure>

<hr />]]></content><author><name>Rustam Mehmandarov</name></author><summary type="html">Using single-use, ephemeral Docker containers for building and testing applications locally.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://mehmandarov.com/assets/images/posts-images/containers.jpg"/><category term="blog"/><category term="containers"/><category term="docker"/><category term="jekyll"/><category term="field notes"/><category term="english"/></entry><entry><title type="html">Navigating and Editing the Command Line &#8211;&#160;Bash Edition</title><link href="https://mehmandarov.com/navigating-and-editing-the-command-line/" rel="alternate" type="text/html" title="Navigating and Editing the Command Line &#8211;&#160;Bash Edition"/><published>2018-12-30T21:01:00+01:00</published><updated>2018-12-30T21:01:00+01:00</updated><id>https://mehmandarov.com/navigating-and-editing-the-command-line</id><content type="html" xml:base="https://mehmandarov.com/navigating-and-editing-the-command-line/"><![CDATA[<p><em>A cheat sheet for moving around and editing your command line &#8211;&#160;Bash Edition.</em></p>

<ul>
  <li><a href="#moving-around-the-command-line">Moving Around the Command Line</a></li>
  <li><a href="#editing-commands-in-the-command-line">Editing Commands in the Command Line</a></li>
  <li><a href="#bonus">Bonus</a></li>
</ul>

<hr />

<p>Using the command line can simplify and even automate many of the operations we do on a computer. However, using the command line can mean quite a bit of typing and a possibly large number of parameters. In this post, I would like to focus on how to navigate the cursor and edit the command line, while leaving all the other Bash tricks for the future posts.</p>

<p>I also have created simple graphics to illustrate some of the main shortcuts listed below. This (hi-res) image can be printed for future reference.</p>

<p><em>Note:</em> Please note that all commands containing <code class="language-plaintext highlighter-rouge">ALT</code> combinations might not work depending on your system configuration, and most definitely not work on MacOS. Normally, it is because these combinations are mapped to something else. However, you can still use the same shortcuts simply by replacing <code class="language-plaintext highlighter-rouge">ALT</code> with <code class="language-plaintext highlighter-rouge">ESC</code>.</p>

<p><img src="/assets/images/posts-images/2018-12-30-bash_navigation.png" alt="Navigating and Editing the Command Line (Bash Edition)" /></p>
<figcaption class="caption"> Navigating and Editing the Command Line (Bash Edition)</figcaption>

<hr />

<h2 id="moving-around-the-command-line">Moving Around the Command Line</h2>

<p>So, let&#8217;s first speak about how to move the cursor around &#8211; because using just arrow keys is often not the most optimal way of navigating. Sometimes you might want to go to the beginning of the line, to the end of the line, or simply jump from one <em>word</em> to another, where <em>word</em> &#8211; in this context &#8211; is set of characters separated by spaces (or sometimes other special characters), or as <a href="https://linux.die.net/man/1/bash">documentation</a> states it:</p>

<blockquote>
  <p>A sequence of characters considered as a single unit by the shell. Also known as a token.</p>
</blockquote>

<figure class="highlight"><pre><code class="language-text" data-lang="text"># Moving the cursor &#8211; fast
CTRL+a         Go to the beginning of the line (same as Home)
CTRL+e         Go to the End of the line (same as End)
ALT+b / ESC+b  Go one word back (to the left)
ALT+f / ESC+f  Go one word forward (to the right)

# Moving the cursor &#8211;&#160;one character at a time
CTRL+f         Go forward one character
CTRL+b         Go backward one character

# Using history
CTRL+r         Backwards search in previously executed commands (history)
CTRL+p         Previous command (same as Up arrow)
CTRL+n         Next command (same as Down arrow)</code></pre></figure>

<hr />

<h2 id="editing-commands-in-the-command-line">Editing Commands in the Command Line</h2>

<p>Now that we are able to navigate freely along the command line, it is time to do some modifications. Here, we will see how to delete, cut, paste, and swap words and characters.</p>

<figure class="highlight"><pre><code class="language-text" data-lang="text"># Deleting whole words
ALT+Del        Delete the word before (to the left of) the cursor
ALT+d / ESC+d  Delete the word after (to the right of) the cursor
CTRL+w         Cut the word before the cursor to the clipboard

# Deleting parts of the line
CTRL+k         Cut the line after the cursor to the clipboard
CTRL+u         Cut/delete the line before the cursor to the clipboard

# Deleting single characters
CTRL+d         Delete character under the cursor (same as Delete key)
CTRL+h         Delete character before the cursor (same as Backspace key)

# Paste, Undo, revert, and more
CTRL+l         Clear the screen (similar to the 'clear' command)
CTRL+y         Paste the last thing to be cut (yank)
CTRL+_         Undo
ALT+r / ESC+r  Revert the changes and replace with the line as it was 
                in History.

# Swap 'em!
CTRL+t         Swap the last two characters before the cursor
ALT+t / ESC+t  Swap current word with previous
 
# Convert to UPPER, lower, or Sentence case
ALT+u / ESC+u  Capitalise characters from the cursor to the end of 
                the current word and move to the end of the word.
ALT+l / ESC+l  Lower the case of characters from the cursor to the
                end of the current word and move to the end of the word.
ALT+c / ESC+c  Capitalize the character under the cursor position 
                and move to the end of the word.</code></pre></figure>

<hr />

<h2 id="bonus">Bonus</h2>

<p>First, the most obvious &#8211; you can always find more gems in the <code class="language-plaintext highlighter-rouge">man</code> pages for Bash both in your terminal and online (for instance on this <a href="https://linux.die.net/man/1/bash">mirror</a>). To view it in your terminal, type:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>man bash</code></pre></figure>

<p>Now, over to something different. Since we have been talking about the command line and shells it is worth mentioning some less-known (and sometimes <em>&#8220;as a curiosity&#8221;</em>) shortcuts in another terminal &#8211; Command Prompt, <code class="language-plaintext highlighter-rouge">cmd.exe</code>:</p>

<figure class="highlight"><pre><code class="language-text" data-lang="text">Function keys in cmd.exe:
  - F1: Pastes the last executed command (character by character)
  - F2: Pastes the last executed command (up to the entered character)
  - F3: Pastes the last executed command
  - F4: Deletes current prompt text up to the entered character
  - F5: Pastes recently executed commands (does not cycle)
  - F6: Pastes ^Z to the prompt
  - F7: Displays a selectable list of previously executed commands
  - F8: Pastes recently executed commands (cycles)
  - F9: Asks for the number of the command from the F7 list to paste</code></pre></figure>

<p><em>Good luck! Try them out and let me know how that goes!</em></p>

<hr />]]></content><author><name>Rustam Mehmandarov</name></author><summary type="html">A cheat sheet for navigating and editing the command line in Bash.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://mehmandarov.com/assets/images/posts-images/laptop.jpg"/><category term="blog"/><category term="command line"/><category term="bash"/><category term="field notes"/><category term="english"/></entry><entry><title type="html">Escaping Developer Nightmares</title><link href="https://mehmandarov.com/escaping-developer-nigthmares/" rel="alternate" type="text/html" title="Escaping Developer Nightmares"/><published>2017-12-01T07:23:00+01:00</published><updated>2017-12-01T07:23:00+01:00</updated><id>https://mehmandarov.com/escaping-developer-nigthmares</id><content type="html" xml:base="https://mehmandarov.com/escaping-developer-nigthmares/"><![CDATA[<p><em>A short write up of the bad things we do in software development and some suggestions on how to fix them.</em></p>

<ul>
  <li><a href="#the-existing-state-of-affairs">The Existing State of Affairs</a></li>
  <li><a href="#the-moving-parts">The Moving Parts</a></li>
  <li><a href="#conclusion">Conclusion</a></li>
</ul>

<hr />

<p>Let&#8217;s take a look into what we can do to achieve a better development environment than an average development project &#8211; a project that most of us have seen at some point in our professional lives, or maybe even are a part of right now. We will also look into some tools and patterns that will help us convert those projects into a paradise for the developers.</p>

<p>Just a few decades ago, we were working in ways that might look like unproductive, in the best case. Our development models were predominated by waterfalls, our IDEs were basic and we were compiling our projects by hand, using <code class="language-plaintext highlighter-rouge">javac</code>, or building up the <code class="language-plaintext highlighter-rouge">CLASSPATH</code> depending on the <code class="language-plaintext highlighter-rouge">GOTO</code> statements in a huge spaghetti code contained in countless <code class="language-plaintext highlighter-rouge">bat</code> files. Our code lived in a very simple versioning systems that were not distributed or supported branching strategies that are praised by the developers today. Our documentation lived in <code class="language-plaintext highlighter-rouge">doc</code> files on shared network drives, side by side with the simple issue tracking systems, that don&#8217;t even get close to what we have today.</p>

<p>Today, it is all different &#8211; we have Git, real issue tracking, IDEs, all that integrated with build servers and collaborative platforms. Yes, everything is much better, more effective and user-friendly, one might think that we are in the paradise already? Well&#8230; yes, things are fortunately getting better, however, we are still doing things in a way that might still give you nightmares, several decades from now.</p>

<p>Last years I have been working and invited to evaluate and help with an audit of various projects. Here are some of my observations and thoughts.</p>

<h2 id="the-existing-state-of-affairs">The Existing State of Affairs</h2>

<p>This <a href="https://twitter.com/brianwisti/status/503987766032494592?lang=en">tweet</a> describes it pretty well:</p>

<figure class="highlight"><pre><code class="language-text" data-lang="text">YOU ARE IN A LEGACY CODEBASE
&gt; RUN TESTS
YOU HAVE NO TESTS
&gt; READ SPEC
YOU HAVE NO SPEC
&gt; WRITE FIX
YOU ARE EATEN BY AN ELDER CODE HACK.</code></pre></figure>

<p>Some of the issues are, naturally, remnants of the past &#8211; the legacy systems; but even those systems and most of the other problems we see today can be avoided if we slightly change our view at some of the main parts of the development process. In most of the cases, we would be aware of those issues, but we might need to explain and motivate the others &#8211; often people are responsible for the projects and those who prioritize the development and maintenance backlog.</p>

<h2 id="the-moving-parts">The Moving Parts</h2>

<p>The road to a great nightmare-free future consists of three components: the code quality, the development and build tools, and a good documentation and collaboration systems. When evaluating systems I often start asking some simple questions listed below to get an idea of the system.</p>

<h3 id="1-the-code">1. The Code</h3>
<h4 id="the-code-quality">The Code Quality</h4>

<p>First thing off is the general code quality. I often start by asking about simple things &#8211; if the project has a coding standard, and if it is being followed. I also ask to take a quick peek at the code and check minor things like file encodings and MIME types. I also follow up with a question if the team is practicing code reviews, and how they are doing that.</p>

<p>While those things alone don&#8217;t have to mean anything, and are minor issues individually, together with other factors they still are initial indicators of possible neglect. This gives me a possibility to map areas where to look further.</p>

<p>In addition to that, there are also some more specific parts that will be listed as sub-sections below.</p>

<h4 id="the-third-party-libraries">The third-party libraries</h4>
<p>The role of the third party libraries and their use is often forgotten and neglected when considering code and system quality. This is quite unfortunate as this is the part of the code that you might not be able to patch easily, and is harder to maintain compared to your own codebase. Here are some simple questions that might help with getting a better grip on third-party libraries:</p>

<ul>
  <li>Do you keep track of your third-party libraries?</li>
  <li>Do you regularly check if there are known issues or vulnerabilities in them?</li>
  <li>Do you have a plan for keeping them updated?</li>
  <li>Are the libraries you are using being actively maintained by the authors?</li>
  <li>Are the libraries you are using compatible with each other?</li>
  <li>Do the libraries you are using have appropriate licenses that are compatible with your system? <em>(This also applies to the open source software licenses.)</em></li>
</ul>

<p>Issues and vulnerabilities are being found and patched all the time. As an example for this, let me point to Google&#8217;s <a href="https://github.com/google/oss-fuzz">OSS-Fuzz Project</a> that has found <a href="https://testing.googleblog.com/2017/05/oss-fuzz-five-months-later-and.html">numerous security vulnerabilities</a> in several critical open source projects. Unfortunately, even though many people are aware of the security issues in software in general, the library updates still often tend to be forgotten.</p>

<p>It is also worth noting that while most of the issues on my list above are security related, the last one might be of a legal sort, and probably is the most neglected of the issues listed.</p>

<h4 id="the-architecture">The Architecture</h4>

<p>I am often being asked to assess a system and tell something about its architecture compared to more modern systems. The different aspects of the system&#8217;s architecture will tell a lot about its maintainability both when it comes to further development, bug fixing, and keeping the system running. Some questions that might help with determining the state of the system would be:</p>

<ul>
  <li>Does your architecture support automated deployment?</li>
  <li>Does your architecture support continuous deploy and delivery?</li>
  <li>Does your architecture support load balancing?</li>
  <li>Does your architecture support microservices?</li>
  <li>How is the architecture implemented in the code?</li>
</ul>

<h4 id="tools-for-maintaining-the-code-quality">Tools for Maintaining the Code Quality</h4>

<p>Some of this might sound familiar to you when you think of one or several systems you had been working with and you might now be wondering what you can do to improve the code quality? Further steps here would be starting to use proper tools that will be able to tell more about the various aspects of your code. Some of them can be used as plugins to your build system (like Maven), and some could be stand-alone tools.</p>

<p>Stand-alone tools for code analysis:</p>
<ul>
  <li><a href="https://www.sonarqube.org/">SonarQube</a></li>
  <li><a href="https://pmd.github.io/">PMD</a></li>
  <li><a href="http://findbugs.sourceforge.net/">FindBugs</a></li>
</ul>

<p>Maven plugins to consider (more about plugins in my <a href="/five-pillars-of-a-good-maven-project/">previous post</a>):</p>
<ul>
  <li>Assembly</li>
  <li>Versions</li>
  <li>Dependency</li>
  <li>Enforcer</li>
  <li>Surefire</li>
  <li>Failsafe</li>
  <li>Sonar</li>
  <li>Findbugs</li>
  <li>pmd</li>
</ul>

<p><em><strong>Bonus:</strong></em> See this post on <a href="/cmd-tools-for-developers/">command line tools for Java projects</a>.</p>

<hr />

<h3 id="2-development-tools-and-strategies">2. Development Tools and Strategies</h3>

<p>Now, let&#8217;s talk about the development tools. All that fancy code and great architecture will not bring you any closer to a developer&#8217;s paradise if there will not be some proper tools to support the development. The code should live in a proper version control system that supports collaboration and things like branching and tagging. There should also be tools that help you with code quality analysis, static code analysis, etc. A good starting point here would be to start with answering the following about the project in question:</p>

<ul>
  <li>Do you use a proper code versioning tool &#8211; Git, or even SVN?</li>
  <li>Do you have a branching (and tagging) strategy?</li>
  <li>Do you have a way of measuring code complexity?</li>
  <li>Do you have a way of measuring test coverage and results?</li>
  <li>Do you run static code analysis?</li>
</ul>

<p>Some tools that can help you here (again, for Java-based systems):</p>

<ul>
  <li><strong>IDEs and IDE plug-ins</strong> that can do checks at commits, integrate with test and QA tools, etc.</li>
  <li><strong>Build tools:</strong> Maven, Gradle, etc.</li>
  <li><strong>Continuous integration tools:</strong> Jenkins, TeamCity, Bamboo, etc.</li>
  <li><strong>Frameworks and tools for testing</strong>: to run unit tests, integration tests, UI tests, and end-to-end tests.</li>
</ul>

<p>There are some further strategies and questions to consider:</p>

<ul>
  <li>Are your environments easy to reproduce with minimal efforts &#8211; can you rebuild it by simply running a script?</li>
  <li>Do you have a proper pipeline from <em>packaging</em>, to <em>delivery</em>, to <em>deploy</em>?</li>
  <li>To what environments can you deploy automatically? With the same script, or command?</li>
  <li>Are your environments (like <em>development</em>, <em>testing</em>, <em>staging</em>, <em>pre-prod</em>, <em>production</em>) similar to each other?</li>
  <li>Do you follow the same process to deploy to each environment?</li>
  <li>Are <em>QA</em> and <em>production</em> running on physically separate hardware?</li>
  <li>Are you monitoring all of the environments? (i.e. are you able to see errors before they make it to <em>QA</em> or even <em>production</em>?)</li>
</ul>

<hr />

<h3 id="3-documentation-and-collaboration-tools">3. Documentation and Collaboration Tools</h3>

<p>Last, but not least, we will need to talk about the tools for collaboration and documentation. Without these tools, we will be back to the way things were several decades ago &#8211; with documents on shared network drives and other horrors of the 90&#8217;s that I mentioned at the beginning of this post. However, good wikis, other collaboration tools, and proper issue tracking will bring your software to another level, encouraging continuous improvement of the system.</p>

<ul>
  <li>Wiki</li>
  <li>Collaboration &#8211; chat, etc.</li>
  <li>Issue tracking tools</li>
</ul>

<p>No matter how obvious it might seem, it is still important to note that one should avoid multiple documentation and issue tracking systems. Unfortunately, even though it might sound obvious, it is more common than you think &#8211; I have seen my share of systems for documentation and issue tracking resulting in fragmented information and confusion.</p>

<h2 id="conclusion">Conclusion</h2>

<p>There are several challenges connected with having and maintaining the good code quality. The first challenge is that a good code quality is not something you can achieve overnight. It takes time and energy to achieve that and it is a continuous process. You will need some tools, techniques, and methodology to prevail, and it will probably be easier to introduce all that from the beginning of a project.</p>

<p>The second challenge would be that it might be hard to convince the stakeholders of the project to invest time and resources into something that does not bring any visible improvements to the table &#8211; things like new features and bug fixes are more likely to get prioritized over something that cannot be easily measured.</p>

<p>Actually, while presenting on this topic at JavaOne 2017 in San Francisco, several of the attendees asked me about the ways of getting to a beautiful nightmare-free code and infrastructure, and the ways of convincing the stakeholders that this is the way to go. Unfortunately, there is no one simple solution to this, and the most valuable thing, in this case, would be to show the real value of the good quality code.</p>

<p>The measurements parameters to show the value can be:</p>

<ul>
  <li>time it takes from the code is written to deploy,</li>
  <li>system stability,</li>
  <li>how often bugs are reported compared to earlier, or</li>
  <li>frequency of errors in logs.</li>
</ul>

<p>So, what can you do as a developer on a project that might need some help, you might ask? You can just start by continuously suggesting improvements and showing their value to the customer, or the project manager. Now you just need to keep going and gradually improving the system, one small bit at a time.</p>

<hr />]]></content><author><name>Rustam Mehmandarov</name></author><summary type="html">Common pitfalls in software development and practical suggestions on how to fix them.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://mehmandarov.com/assets/images/posts-images/mindthegap.png"/><category term="blog"/><category term="java"/><category term="field notes"/><category term="software development"/><category term="english"/></entry><entry><title type="html">Docker Command Line Survival Guide: The Absolute Basics</title><link href="https://mehmandarov.com/docker-cmd-survival-guide/" rel="alternate" type="text/html" title="Docker Command Line Survival Guide: The Absolute Basics"/><published>2017-07-27T08:23:00+02:00</published><updated>2017-07-27T08:23:00+02:00</updated><id>https://mehmandarov.com/docker-cmd-survival-guide</id><content type="html" xml:base="https://mehmandarov.com/docker-cmd-survival-guide/"><![CDATA[<p><em>A brief introduction to ten essential and absolute basic Docker commands to get you started, and keep you going in the command-line interface.</em></p>

<ul>
  <li><a href="#getting-started">Getting Started</a></li>
  <li><a href="#commands-files-and-folders-inside-a-container">Commands, Files, and Folders Inside a Container</a></li>
  <li><a href="#cleanup">Cleanup</a></li>
</ul>

<hr />

<p>In this post, I decided to share some of the basic commands you might need to get started with Docker. This is neither an extensive list of the commands available, nor all of the commands you might need. This is merely me sharing a prettified list of my cheat sheet for Docker basics with <em>you</em>.</p>

<h2 id="getting-started">Getting Started</h2>

<p>Before we get started, it might be a good idea to note that all of the commands below are written without <code class="language-plaintext highlighter-rouge">sudo</code>. If your installation is not running without <code class="language-plaintext highlighter-rouge">sudo</code> (assuming that you are running Linux), you might want to check out the <a href="https://docs.docker.com/engine/installation/linux/linux-postinstall/" target="_blank">post-installation guide for Linux</a> in the Docker docs.</p>

<h4 id="1-check-if-everything-works">1. Check if Everything Works</h4>

<p>First things first, you can use this simple command to check that your installation is fine. <strong><em>Note:</em></strong> Make sure you have right CPU architecture for your images. Raspberry Pi (ARM) things will not run on x86 architecture, and vice versa.</p>

<p>For x86:</p>

<figure class="highlight"><pre><code class="language-shell_session" data-lang="shell_session"><span class="gp">$</span><span class="w"> </span>docker run docker/whalesay cowsay Hello World!</code></pre></figure>

<p>For Raspberry Pi / AMD:</p>

<figure class="highlight"><pre><code class="language-shell_session" data-lang="shell_session"><span class="gp">$</span><span class="w"> </span>docker run <span class="nt">-d</span> <span class="nt">-p</span> 80:80 hypriot/rpi-busybox-httpd</code></pre></figure>

<p><img src="/assets/images/posts-images/2017-07-27_helloworld-rpi.png" alt="Hello World" class="bigger-image" /></p>

<h4 id="2-list-containers">2. List Containers</h4>

<p>After creating containers, first thing you might want to do is to see what containers you have up and running. To list all running containers you can use:</p>

<figure class="highlight"><pre><code class="language-shell_session" data-lang="shell_session"><span class="gp">$</span><span class="w"> </span>docker ps</code></pre></figure>

<p>This command will give you a list similar to this:</p>

<figure class="highlight"><pre><code class="language-text" data-lang="text">CONTAINER ID        IMAGE                       COMMAND                  CREATED             STATUS                    PORTS                NAMES
e85753d57a67        easypi/dokuwiki-arm         "/bin/sh -c 'php-f..."   1 days ago          Up 23 hours               0.0.0.0:80-&gt;80/tcp   mywiki</code></pre></figure>

<p>However, it will not show you any stopped containers. To list <em>all</em> local containers use the <code class="language-plaintext highlighter-rouge">-a</code> option:</p>

<figure class="highlight"><pre><code class="language-shell_session" data-lang="shell_session"><span class="gp">$</span><span class="w"> </span>docker ps <span class="nt">-a</span></code></pre></figure>

<p>The output will be more like this (note that is shows also stopped, or even failed containers):</p>

<figure class="highlight"><pre><code class="language-text" data-lang="text">CONTAINER ID        IMAGE                       COMMAND                  CREATED             STATUS                    PORTS                NAMES
573193cf1d5e        hypriot/rpi-busybox-httpd   "/bin/busybox http..."   2 days ago          Exited (0) 5 hours ago                         mytest
e85753d57a67        easypi/dokuwiki-arm         "/bin/sh -c 'php-f..."   1 days ago          Up 23 hours               0.0.0.0:80-&gt;80/tcp   mywiki</code></pre></figure>

<p>More on <code class="language-plaintext highlighter-rouge">docker ps</code> in the <a href="https://docs.docker.com/engine/reference/commandline/ps/" target="_blank">Docker docs</a>.</p>

<h4 id="3-list-images">3. List Images</h4>

<p>To list all the images available on your system, simply do this:</p>

<figure class="highlight"><pre><code class="language-shell_session" data-lang="shell_session"><span class="gp">$</span><span class="w"> </span>docker images</code></pre></figure>

<h4 id="4-containers-vs-images">4. Containers vs. Images?</h4>

<p>What is the difference between containers and images, you might wonder? Well, I have a <a href="https://docs.docker.com/engine/userguide/storagedriver/imagesandcontainers/" target="_blank">link</a> for you. This will hopefully help you to understand how Docker manages the data within your images and containers.</p>

<h4 id="5-starting-and-stopping-containers">5. Starting and Stopping Containers</h4>

<p>Another two basic commands &#8211;&#160;<a href="https://docs.docker.com/engine/reference/commandline/start/" target="_blank">starting</a> and <a href="https://docs.docker.com/engine/reference/commandline/stop/" target="_blank">stopping</a> containers:</p>

<figure class="highlight"><pre><code class="language-shell_session" data-lang="shell_session"><span class="gp">$</span><span class="w"> </span>docker start &lt;container_id&gt;
<span class="gp">$</span><span class="w"> </span>docker stop &lt;container_id&gt;</code></pre></figure>

<p><strong><em>Note:</em></strong> The <code class="language-plaintext highlighter-rouge">docker run</code> command first creates a writeable container layer over the specified image, and then starts it using the specified command. That is, <code class="language-plaintext highlighter-rouge">docker run</code> is equivalent to the API&#8217;s <code class="language-plaintext highlighter-rouge">/containers/create</code>, and then <code class="language-plaintext highlighter-rouge">/containers/&lt;id&gt;/start</code>.</p>

<hr />

<h2 id="commands-files-and-folders-inside-a-container">Commands, Files, and Folders Inside a Container</h2>

<h4 id="6-run-any-command-from-a-container">6. Run Any Command from a Container</h4>
<p>You can <a href="https://docs.docker.com/engine/reference/commandline/exec/" target="_blank">run any command</a> in a running container just knowing its ID (or name):</p>

<figure class="highlight"><pre><code class="language-shell_session" data-lang="shell_session"><span class="gp">$</span><span class="w"> </span>docker <span class="nb">exec</span> <span class="nt">-it</span> &lt;container_id_or_name&gt; <span class="nb">echo</span> <span class="s2">"Hello from container!"</span></code></pre></figure>

<h4 id="7-getting-into-containers">7. Getting Into Containers</h4>

<p>Since you can run any command, then you can (obviously) also run a shell from a container; if you have any. This will be a bit similar to running an <code class="language-plaintext highlighter-rouge">ssh</code> command to connect remotely to a regular Linux box (given you have <code class="language-plaintext highlighter-rouge">bash</code> or <code class="language-plaintext highlighter-rouge">sh</code> in the container):</p>

<figure class="highlight"><pre><code class="language-shell_session" data-lang="shell_session"><span class="gp">$</span><span class="w"> </span>docker <span class="nb">exec</span> <span class="nt">-it</span> &lt;container_id_or_name&gt; bash
<span class="gp">$</span><span class="w"> </span><span class="c"># or:</span>
<span class="gp">$</span><span class="w"> </span>docker <span class="nb">exec</span> <span class="nt">-it</span> &lt;container_id_or_name&gt; sh</code></pre></figure>

<h4 id="8-copy-files-from-and-to-containers">8. Copy Files From and To Containers</h4>

<p>Another useful trick you might need is to copy some files to and from a container. Your friend here is the <code class="language-plaintext highlighter-rouge">docker cp</code> command (<a href="https://docs.docker.com/edge/engine/reference/commandline/cp/" target="_blank">link to the docs</a>):</p>

<figure class="highlight"><pre><code class="language-shell_session" data-lang="shell_session"><span class="gp">$</span><span class="w"> </span><span class="c"># To container:</span>
<span class="gp">$</span><span class="w"> </span>docker <span class="nb">cp </span>foo.txt &lt;container_name&gt;:/foo.txt
<span class="gp">$</span><span class="w"> </span><span class="c"># From container:</span>
<span class="gp">$</span><span class="w"> </span>docker <span class="nb">cp</span> &lt;container_name&gt;:/foo.txt foo.txt</code></pre></figure>

<hr />

<h2 id="cleanup">Cleanup</h2>

<p>After playing round with all the images and containers, you might realize that you have quite a collection of these on your drive, just taking up space.</p>

<h4 id="9-remove-containers">9. Remove Containers</h4>

<p>To remove the unused or unwanted containers, you can run the <code class="language-plaintext highlighter-rouge">docker rm</code> command with the IDs of those images. The IDs can be retrieved with the <code class="language-plaintext highlighter-rouge">docker ps -a</code> command, mentioned above.</p>

<figure class="highlight"><pre><code class="language-shell_session" data-lang="shell_session"><span class="gp">$</span><span class="w"> </span>docker <span class="nb">rm</span> &lt;container_id&gt;</code></pre></figure>

<h4 id="10-remove-images">10. Remove Images</h4>

<p>The <code class="language-plaintext highlighter-rouge">docker rmi</code> command followed by the IDs of images will help you to remove the unused or unwanted images. The abovementioned <code class="language-plaintext highlighter-rouge">docker images</code> command will help you finding the correct IDs for the images in question.</p>

<figure class="highlight"><pre><code class="language-shell_session" data-lang="shell_session"><span class="gp">$</span><span class="w"> </span>docker rmi &lt;container_id&gt;</code></pre></figure>

<p><em>Have fun!</em></p>

<hr />]]></content><author><name>Rustam Mehmandarov</name></author><summary type="html">Ten essential Docker commands to get you started with the command-line interface.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://mehmandarov.com/assets/images/posts-images/street-art-container_small.jpeg"/><category term="blog"/><category term="docker"/><category term="command line"/><category term="field notes"/><category term="english"/></entry><entry><title type="html">Start Docker Containers Automatically</title><link href="https://mehmandarov.com/start-docker-containers-automatically/" rel="alternate" type="text/html" title="Start Docker Containers Automatically"/><published>2017-07-09T10:50:00+02:00</published><updated>2017-07-09T10:50:00+02:00</updated><id>https://mehmandarov.com/start-docker-containers-automatically</id><content type="html" xml:base="https://mehmandarov.com/start-docker-containers-automatically/"><![CDATA[<p><em>Starting your Docker containers automatically using <code class="language-plaintext highlighter-rouge">systemd</code>.</em></p>

<ul>
  <li><a href="#introduction">Introduction</a></li>
  <li><a href="#create-the-service-file">Create the Service File</a></li>
  <li><a href="#activate-the-service">Activate the Service</a></li>
</ul>

<hr />

<h2 id="introduction">Introduction</h2>

<p>After your Docker containers are set up and running, you might need to be able to start some of them automatically on a reboot or a crash. There are several ways of getting this done.</p>

<p>One of them is to use <a href="https://docs.docker.com/engine/admin/start-containers-automatically/" target="_blank">restart policies</a> provided by Docker. They can be set to control whether your containers start automatically when they exit, or when Docker restarts.</p>

<p>Alternatively, you can use a process manager such as <code class="language-plaintext highlighter-rouge">upstart</code>, <code class="language-plaintext highlighter-rouge">systemd</code>, or <code class="language-plaintext highlighter-rouge">supervisor</code> instead. In this post, I want to show you how it is done with <a href="https://freedesktop.org/wiki/Software/systemd/" target="_blank"><code class="language-plaintext highlighter-rouge">systemd</code></a>.</p>

<h2 id="create-the-service-file">Create the Service File</h2>

<p>To create a service file that will be used by <code class="language-plaintext highlighter-rouge">systemd</code> (<code class="language-plaintext highlighter-rouge">systemctl</code> command), we will first need to get your container name. This can be done by running the following command in your shell:</p>

<figure class="highlight"><pre><code class="language-shell_session" data-lang="shell_session"><span class="gp">$</span><span class="w"> </span>docker ps <span class="nt">-a</span></code></pre></figure>

<p>The output will look something like this. Select the right container from the list, and note its name in the last column. In this example, we will be using <code class="language-plaintext highlighter-rouge">mywiki</code> container.</p>

<figure class="highlight"><pre><code class="language-text" data-lang="text">CONTAINER ID        IMAGE                       COMMAND                  CREATED             STATUS                    PORTS                NAMES
573193cf1d5e        hypriot/rpi-busybox-httpd   "/bin/busybox http..."   2 days ago          Exited (0) 5 hours ago                         mytest
e85753d57a67        easypi/dokuwiki-arm         "/bin/sh -c 'php-f..."   1 days ago          Up 23 hours               0.0.0.0:80-&gt;80/tcp   mywiki</code></pre></figure>

<p>Now, we will need to create a file (choose an appropriate file name for the service):</p>

<figure class="highlight"><pre><code class="language-shell_session" data-lang="shell_session"><span class="gp">$</span><span class="w"> </span><span class="nb">sudo </span>nano /etc/systemd/system/docker-dokuwiki.service</code></pre></figure>

<p>Paste the following into the file. Set a proper <code class="language-plaintext highlighter-rouge">Description</code>, and make sure to update the container name in <code class="language-plaintext highlighter-rouge">ExecStart</code> and <code class="language-plaintext highlighter-rouge">ExecStop</code>:</p>

<figure class="highlight"><pre><code class="language-yml" data-lang="yml"><span class="pi">[</span><span class="nv">Unit</span><span class="pi">]</span>
<span class="s">Description=DokuWiki Container</span>
<span class="s">Requires=docker.service</span>
<span class="s">After=docker.service</span>

<span class="pi">[</span><span class="nv">Service</span><span class="pi">]</span>
<span class="s">Restart=always</span>
<span class="s">ExecStart=/usr/bin/docker start -a mywiki</span>
<span class="s">ExecStop=/usr/bin/docker stop -t 2 mywiki</span>

<span class="pi">[</span><span class="nv">Install</span><span class="pi">]</span>
<span class="s">WantedBy=local.target</span></code></pre></figure>

<p>A couple of notes about the script above:</p>
<ol>
  <li>This file is called a <a href="https://www.freedesktop.org/software/systemd/man/systemd.unit.html" target="_blank">unit file</a> for <code class="language-plaintext highlighter-rouge">systemd</code>.</li>
  <li>Make sure you don&#8217;t have any extra line brakes within the sections, like <code class="language-plaintext highlighter-rouge">Unit</code>, or <code class="language-plaintext highlighter-rouge">Service</code>.</li>
  <li>The <code class="language-plaintext highlighter-rouge">-a</code> option in the Docker command for <code class="language-plaintext highlighter-rouge">ExecStart</code> makes sure it is running in attached mode, i.e., attaching STDOUT/STDERR and forwarding signals.</li>
  <li>The <code class="language-plaintext highlighter-rouge">-t</code> option in the Docker command for <code class="language-plaintext highlighter-rouge">ExecStop</code> specifies seconds to wait for it to stop before killing the container.</li>
</ol>

<h2 id="activate-the-service">Activate the Service</h2>

<p>Before we can activate the service we have created, we need to reload the unit file. You will also need to run this command anytime you do any modifications to the unit files:</p>

<figure class="highlight"><pre><code class="language-shell_session" data-lang="shell_session"><span class="gp">$</span><span class="w"> </span><span class="nb">sudo </span>systemctl daemon-reload</code></pre></figure>

<p>To activate the service run the following commands (<em>remember to change the service name</em>):</p>

<figure class="highlight"><pre><code class="language-shell_session" data-lang="shell_session"><span class="gp">$</span><span class="w"> </span><span class="nb">sudo </span>systemctl start docker-dokuwiki.service
<span class="gp">$</span><span class="w"> </span><span class="nb">sudo </span>systemctl <span class="nb">enable </span>docker-dokuwiki.service</code></pre></figure>

<p>To disable the service run the following commands (<em>remember to change the service name</em>):</p>

<figure class="highlight"><pre><code class="language-shell_session" data-lang="shell_session"><span class="gp">$</span><span class="w"> </span><span class="nb">sudo </span>systemctl stop docker-dokuwiki.service
<span class="gp">$</span><span class="w"> </span><span class="nb">sudo </span>systemctl disable docker-dokuwiki.service</code></pre></figure>

<p>Changes will come to effect on a reboot:</p>

<figure class="highlight"><pre><code class="language-shell_session" data-lang="shell_session"><span class="gp">$</span><span class="w"> </span><span class="nb">sudo </span>reboot</code></pre></figure>

<p>Now you should have a container that will start on a server reboot, Docker restart, or a crash. <em>Congratulations!</em></p>

<p>As a next step, you might want to look at (external documentation links):</p>

<ul>
  <li>Adding some more parameters to the <a href="https://www.freedesktop.org/software/systemd/man/systemd.unit.html" target="_blank">unit file</a>.</li>
  <li>Available <a href="https://docs.docker.com/engine/reference/commandline/start/" target="_blank"><code class="language-plaintext highlighter-rouge">docker start</code></a> options.</li>
  <li>Available <a href="https://docs.docker.com/engine/reference/commandline/start/" target="_blank"><code class="language-plaintext highlighter-rouge">docker start</code></a> options.</li>
</ul>

<hr />]]></content><author><name>Rustam Mehmandarov</name></author><summary type="html">Starting your Docker containers automatically using systemd.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://mehmandarov.com/assets/images/posts-images/whale_small.jpeg"/><category term="blog"/><category term="java"/><category term="docker"/><category term="field notes"/><category term="english"/></entry><entry><title type="html">Automating Confluence Posts with Amazon Cloud (AWS)</title><link href="https://mehmandarov.com/confluence-and-aws/" rel="alternate" type="text/html" title="Automating Confluence Posts with Amazon Cloud (AWS)"/><published>2017-01-29T09:26:00+01:00</published><updated>2017-01-29T09:26:00+01:00</updated><id>https://mehmandarov.com/confluence-and-aws</id><content type="html" xml:base="https://mehmandarov.com/confluence-and-aws/"><![CDATA[<p><em>How do you automate a job without setting up a dedicated machine?</em></p>

<ul>
  <li><a href="#posting-via-confluence-rest-api">Posting via Confluence REST API</a></li>
  <li><a href="#creating-a-lambda-function-in-aws">Creating a Lambda Function in AWS</a></li>
  <li><a href="#schedule-it">Schedule it!</a></li>
</ul>

<hr />

<p>Some mundane tasks can easily be automated. In my case, I needed something that could post to our Confluence instance at a specific time every week. This is because we use blog posts in Confluence for announcing our weekly volunteer meetings and as a simple attendance management.</p>

<hr />

<h2 id="posting-via-confluence-rest-api">Posting via Confluence REST API</h2>

<p><a href="https://en.wikipedia.org/wiki/Confluence_(software)" target="_blank">Confluence</a>, a team collaboration software written in Java and quite often used in corporate environments, offers a <a href="https://developer.atlassian.com/confdev/confluence-server-rest-api/confluence-rest-api-examples" target="_blank">REST API</a> that makes it possible to perform many operations on the content. In this case, I was interested in posting new content with some text, and I was getting tired of doing that manually every week. So, I thought: <a href="https://xkcd.com/1319/" target="_blank">&#8220;I spend a lot of time on this task. I should write a program automating it!&#8221;</a>.</p>

<p>The first take on that problem was a simple Python script:</p>

<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">import</span> <span class="n">json</span>
<span class="kn">import</span> <span class="n">requests</span>

<span class="n">url</span> <span class="o">=</span> <span class="sh">"</span><span class="s">https://some-confluence-url.com/rest/api/content/</span><span class="sh">"</span>
<span class="n">headers</span> <span class="o">=</span> <span class="p">{</span> <span class="sh">"</span><span class="s">content-type</span><span class="sh">"</span><span class="p">:</span> <span class="sh">"</span><span class="s">application/json</span><span class="sh">"</span> <span class="p">}</span>
<span class="n">payload</span> <span class="o">=</span> <span class="p">{</span> <span class="sh">"</span><span class="s">type</span><span class="sh">"</span><span class="p">:</span> <span class="sh">"</span><span class="s">blogpost</span><span class="sh">"</span><span class="p">,</span>
            <span class="sh">"</span><span class="s">title</span><span class="sh">"</span><span class="p">:</span> <span class="sh">"</span><span class="s">Fancy meeting title</span><span class="sh">"</span><span class="p">,</span>
            <span class="sh">"</span><span class="s">space</span><span class="sh">"</span><span class="p">:</span> <span class="p">{</span>
                <span class="sh">"</span><span class="s">key</span><span class="sh">"</span><span class="p">:</span> <span class="sh">"</span><span class="s">mySpaceNameGoesHere</span><span class="sh">"</span>
            <span class="p">},</span>
            <span class="sh">"</span><span class="s">body</span><span class="sh">"</span><span class="p">:</span> <span class="p">{</span>
                <span class="sh">"</span><span class="s">storage</span><span class="sh">"</span><span class="p">:</span> <span class="p">{</span>
                    <span class="sh">"</span><span class="s">representation</span><span class="sh">"</span><span class="p">:</span> <span class="sh">"</span><span class="s">storage</span><span class="sh">"</span><span class="p">,</span>
                    <span class="sh">"</span><span class="s">value</span><span class="sh">"</span><span class="p">:</span> <span class="sh">"</span><span class="s">Meeting description goes here.</span><span class="sh">"</span>
                <span class="p">}</span>
            <span class="p">}</span>
            <span class="c1">#"history": {
</span>            <span class="c1">#    "createdDate": '2017-01-10T14:00:00.000Z'
</span>            <span class="c1">#},
</span>
        <span class="p">}</span>

<span class="n">response</span> <span class="o">=</span> <span class="n">requests</span><span class="p">.</span><span class="nf">post</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> 
                         <span class="n">data</span><span class="o">=</span><span class="n">json</span><span class="p">.</span><span class="nf">dumps</span><span class="p">(</span><span class="n">payload</span><span class="p">),</span> 
                         <span class="n">headers</span><span class="o">=</span><span class="n">headers</span><span class="p">,</span> 
                         <span class="n">auth</span><span class="o">=</span><span class="p">(</span><span class="sh">"</span><span class="s">myUserName</span><span class="sh">"</span><span class="p">,</span> <span class="sh">"</span><span class="s">mySecretPassword</span><span class="sh">"</span><span class="p">))</span>
<span class="k">print</span> <span class="n">json</span><span class="p">.</span><span class="nf">dumps</span><span class="p">(</span><span class="n">response</span><span class="p">.</span><span class="nf">json</span><span class="p">(),</span> <span class="n">indent</span><span class="o">=</span><span class="mi">4</span><span class="p">,</span> <span class="n">sort_keys</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span></code></pre></figure>

<p>You should be able to run this script against your end-point and post your content. Just note that I used <code class="language-plaintext highlighter-rouge">requests</code> library here that needs to be installed separately, for instance, by using <code class="language-plaintext highlighter-rouge">pip</code>:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nb">sudo </span>pip <span class="nb">install </span>requests</code></pre></figure>

<p>Also, you will need to update the following values in the script:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">url</code> &#8211; the URL to your site</li>
  <li><code class="language-plaintext highlighter-rouge">type</code> &#8211; can be a <code class="language-plaintext highlighter-rouge">blogpost</code> or a <code class="language-plaintext highlighter-rouge">page</code></li>
  <li><code class="language-plaintext highlighter-rouge">title</code> &#8211;&#160;page or post title</li>
  <li><code class="language-plaintext highlighter-rouge">space</code> &#8211; a Confluence space where the post will belong</li>
  <li><code class="language-plaintext highlighter-rouge">value</code> &#8211; content of the page, can contain HTML tags</li>
  <li><code class="language-plaintext highlighter-rouge">auth</code> &#8211;&#160;username and password (please note that, for security reasons, it might be a good idea to create a separate user with restricted access rights just for posting specific content)</li>
  <li><code class="language-plaintext highlighter-rouge">createdDate</code> &#8211; you can also add the commented-out part to add a specific blog post date</li>
</ul>

<p>The script uses basic authentication to post the content and, if successful, returns metadata about the post as a response. If it fails, the response from Confluence end-point should point you in the right direction.</p>

<hr />

<h2 id="creating-a-lambda-function-in-aws">Creating a Lambda Function in AWS</h2>

<p>Now we are one step closer to automation. The script works, and we can post content with a simple push of a button. What now?</p>

<p>Well, now I needed something to run that script and something to trigger that action. The trigger is the time as I wanted to run our script weekly, but first I needed to deploy our script to the Cloud. Scheduling and triggers would come later.</p>

<p>Since we had some infrastructure on AWS already, I decided to deploy the script on the same platform. I wanted to deploy it as a simple stand-alone function in the Cloud &#8211; in AWS world it is called a <a href="http://docs.aws.amazon.com/lambda/latest/dg/welcome.html" target="_blank">Lambda function</a>.</p>

<p>I started by wrapping our code into a function and making it AWS Lambda function compatible &#8211; to define a function that takes two arguments: <code class="language-plaintext highlighter-rouge">event</code> and <code class="language-plaintext highlighter-rouge">context</code>. I choose to call the function <code class="language-plaintext highlighter-rouge">blogpost_handler</code>:</p>

<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="c1">#!/usr/bin/python
# -*- coding: utf-8 -*-
</span>
<span class="c1"># File name: poster.py
</span>
<span class="kn">import</span> <span class="n">requests</span>
<span class="kn">import</span> <span class="n">json</span>
<span class="kn">import</span> <span class="n">datetime</span>

<span class="k">def</span> <span class="nf">blogpost_handler</span><span class="p">(</span><span class="n">event</span><span class="p">,</span> <span class="n">context</span><span class="p">):</span> 

    <span class="c1"># Script is run on Sunday, need to use date for Tuesday
</span>    <span class="n">next_tue</span> <span class="o">=</span> <span class="p">(</span><span class="n">datetime</span><span class="p">.</span><span class="n">datetime</span><span class="p">.</span><span class="nf">now</span><span class="p">()</span>
                    <span class="o">+</span><span class="n">datetime</span><span class="p">.</span><span class="nf">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">2</span><span class="p">)).</span><span class="nf">strftime</span><span class="p">(</span><span class="sh">"</span><span class="s">%Y-%m-%d</span><span class="sh">"</span><span class="p">)</span>

    <span class="n">url</span> <span class="o">=</span> <span class="sh">"</span><span class="s">https://some-confluence-url.com/rest/api/content/</span><span class="sh">"</span>
    <span class="n">headers</span> <span class="o">=</span> <span class="p">{</span> <span class="sh">"</span><span class="s">content-type</span><span class="sh">"</span><span class="p">:</span> <span class="sh">"</span><span class="s">application/json</span><span class="sh">"</span> <span class="p">}</span>
    <span class="n">payload</span> <span class="o">=</span> <span class="p">{</span> <span class="sh">"</span><span class="s">type</span><span class="sh">"</span><span class="p">:</span> <span class="sh">"</span><span class="s">blogpost</span><span class="sh">"</span><span class="p">,</span>
                <span class="sh">"</span><span class="s">title</span><span class="sh">"</span><span class="p">:</span> <span class="sh">"</span><span class="s">Meeting: </span><span class="sh">"</span><span class="o">+</span><span class="n">next_tue</span><span class="p">,</span>
                <span class="sh">"</span><span class="s">space</span><span class="sh">"</span><span class="p">:</span> <span class="p">{</span>
                    <span class="sh">"</span><span class="s">key</span><span class="sh">"</span><span class="p">:</span> <span class="sh">"</span><span class="s">mySpaceNameGoesHere</span><span class="sh">"</span>
                <span class="p">},</span>
                <span class="sh">"</span><span class="s">body</span><span class="sh">"</span><span class="p">:</span> <span class="p">{</span>
                    <span class="sh">"</span><span class="s">storage</span><span class="sh">"</span><span class="p">:</span> <span class="p">{</span>
                        <span class="sh">"</span><span class="s">representation</span><span class="sh">"</span><span class="p">:</span> <span class="sh">"</span><span class="s">storage</span><span class="sh">"</span><span class="p">,</span>
                        <span class="sh">"</span><span class="s">value</span><span class="sh">"</span><span class="p">:</span> <span class="sh">"</span><span class="s">Meeting description goes here.</span><span class="sh">"</span>
                    <span class="p">}</span>
                <span class="p">}</span>
            <span class="p">}</span>

    
    <span class="n">response</span> <span class="o">=</span> <span class="n">requests</span><span class="p">.</span><span class="nf">post</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> 
                             <span class="n">data</span><span class="o">=</span><span class="n">json</span><span class="p">.</span><span class="nf">dumps</span><span class="p">(</span><span class="n">payload</span><span class="p">),</span> 
                             <span class="n">headers</span><span class="o">=</span><span class="n">headers</span><span class="p">,</span> 
                             <span class="n">auth</span><span class="o">=</span><span class="p">(</span><span class="sh">"</span><span class="s">myUserName</span><span class="sh">"</span><span class="p">,</span> <span class="sh">"</span><span class="s">mySecretPassword</span><span class="sh">"</span><span class="p">))</span>
    
    <span class="k">print</span> <span class="n">json</span><span class="p">.</span><span class="nf">dumps</span><span class="p">(</span><span class="n">response</span><span class="p">.</span><span class="nf">json</span><span class="p">(),</span> <span class="n">indent</span><span class="o">=</span><span class="mi">4</span><span class="p">,</span> <span class="n">sort_keys</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>

    <span class="k">return</span> <span class="n">response</span><span class="p">.</span><span class="nf">json</span><span class="p">()</span></code></pre></figure>

<p>Now, I needed <a href="http://docs.aws.amazon.com/lambda/latest/dg/lambda-python-how-to-create-deployment-package.html" target="_blank">to package</a> the code to make it ready to deploy:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="c"># 1. create folder</span>
<span class="nb">mkdir </span>blogposter
<span class="nb">cd </span>blogposter

<span class="c"># 2. create and copy the code above into poster.py</span>
<span class="nb">touch </span>poster.py

<span class="c"># 3. install requests package locally</span>
pip <span class="nb">install </span>requests <span class="nt">-t</span> <span class="nb">.</span>

<span class="c"># 4. zip contents of the folder and create a zip file in a parent directory</span>
zip <span class="nt">-r9</span> ../pyposter.zip <span class="k">*</span></code></pre></figure>

<p>And we are ready to deploy to AWS! Start with creating a new Lambda Function and selecting a blank function for this job.</p>

<p><img src="/assets/images/posts-images/2017-01-29-confluence-and-aws_screen1.png" alt="Start with selecting a blueprint" /></p>

<p>I didn&#8217;t choose any triggers for now and continued to the configuration page. When presented with function configuration you need to give it a name, description, runtime, and a .zip file with the code. At the end, you will need to define a handler (which will typically be <code class="language-plaintext highlighter-rouge">filename.function_name</code>), and a role.</p>

<p><img src="/assets/images/posts-images/2017-01-29-confluence-and-aws_screen2.png" alt="Fill out the rest of info" /></p>

<p>At the end of the wizard, you can run it manually by pressing the Test button. If you did all the steps above, this should now create a new post on your Confluence. Congratulations, you have now set up a stand-alone function in the Cloud!</p>

<hr />

<h2 id="schedule-it">Schedule it!</h2>

<p>Now that I have automated the task and deployed it to the Cloud, I needed something to trigger that function. In this case, I wanted to schedule it to run weekly, so function was set to be triggered by the <a href="http://docs.aws.amazon.com/lambda/latest/dg/with-scheduled-events.html" target="_blank">CloudWatch</a> events. It offers a good support for <a href="http://docs.aws.amazon.com/AmazonCloudWatch/latest/events/RunLambdaSchedule.html" target="_blank">scheduling Lambda expressions</a>.</p>

<p>I defined event source as a cron expression, and a target as a Lambda function I created in the previous step.</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="c"># 9:05, every Sunday</span>
5 9 ? <span class="k">*</span> 1 <span class="k">*</span></code></pre></figure>

<p><img src="/assets/images/posts-images/2017-01-29-confluence-and-aws_screen3.png" alt="Adding a scheduled event" /></p>

<p>Now you (and I) have a function that is scheduled to run weekly and does not require a dedicated machine to run. It also has some good options for logging and sending alarms in case it fails.</p>

<hr />]]></content><author><name>Rustam Mehmandarov</name></author><summary type="html">Automating posting to Confluence with cloud services like Amazon Web Services (AWS).</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://mehmandarov.com/assets/images/posts-images/clouds.jpg"/><category term="blog"/><category term="field notes"/><category term="automation"/><category term="cloud"/><category term="python"/><category term="english"/></entry><entry><title type="html">Five Pillars of a Good Maven Project</title><link href="https://mehmandarov.com/five-pillars-of-a-good-maven-project/" rel="alternate" type="text/html" title="Five Pillars of a Good Maven Project"/><published>2016-07-23T08:26:00+02:00</published><updated>2016-07-23T08:26:00+02:00</updated><id>https://mehmandarov.com/five-pillars-of-a-good-maven-project</id><content type="html" xml:base="https://mehmandarov.com/five-pillars-of-a-good-maven-project/"><![CDATA[<p><em>What makes a Maven project good to work with and easy to maintain? There are five types of Maven plugins that will simplify the development process and increase maintainability of a project.</em></p>

<ul>
  <li><a href="#1-technical-aspects">1. Technical Aspects</a></li>
  <li><a href="#2-legal-aspects">2. Legal Aspects</a></li>
  <li><a href="#3-rapid-development">3. Rapid Development</a></li>
  <li><a href="#4-documentation">4. Documentation</a></li>
  <li><a href="#5-testing-and-qa">5. Testing and QA</a></li>
  <li><a href="#bonus-video">Bonus: Video</a></li>
</ul>

<hr />

<p><a href="https://maven.apache.org/">Apache Maven</a> is a build automation tool used primarily for Java projects. It has been around for a while, and it does not seem to be going anywhere anytime soon (whether some of you like it or not). Recently, it has been confirmed yet again, this time in ZeroTurnaround&#8217;s <a href="http://zeroturnaround.com/rebellabs/java-tools-and-technologies-landscape-2016-trends/">Java Tools and Technologies Landscape Report 2016</a> (see the <em>Build Tools</em> section).</p>

<p>The good thing about Maven is that you can do almost anything with it and its plugins. With such a great ecosystem of plugins, able to do nearly anything, one might wonder where to begin when setting up a new Maven project or improving your old one.</p>

<p>I usually like to think of five main categories &#8211; or pillars &#8211; that we will be looking into in this post. Each category will have a set of example plugins that are meant to serve merely as a starting point.</p>

<p>In this post, I will assume that you have some experience with build tools in general and Maven in particular.</p>

<hr />

<h2 id="1-technical-aspects">1. Technical Aspects</h2>

<p>First of all, you would like to make sure that all the technical stuff is in place. You might want to automate the packaging, the checks if the project is running the latest version of all artifacts, that all the dependencies are met, and that the unused dependencies are removed. You might even want to define your own rules for all the things that cause troubles, or just simply annoy you down the line, making the build fail if they are not met.</p>

<p>With all that automation in place, you will be getting predictable results and nice packaging from the first day of the project.</p>

<p>Some of the plugins that should be mentioned here:</p>

<ul>
  <li><strong><a href="http://www.mojohaus.org/versions-maven-plugin/">Versions</a> plugin</strong> does the versions management of artifacts in a project&#8217;s POM file</li>
  <li><strong><a href="http://maven.apache.org/plugins/maven-dependency-plugin/">Dependency</a> plugin</strong> helps you analyzing dependencies, building dependency trees, showing unused dependencies, etc</li>
  <li><strong><a href="http://maven.apache.org/plugins/maven-assembly-plugin/">Assembly</a> plugin</strong> helps you packaging all the dependencies, modules, site documentation, and other files into a single distributable archive</li>
  <li><strong><a href="http://maven.apache.org/enforcer/maven-enforcer-plugin/">Enforcer</a> plugin</strong> lets you make your own rules! You can set up your build to break if some of your requirements are not met</li>
</ul>

<hr />

<h2 id="2-legal-aspects">2. Legal Aspects</h2>

<p>With all the technical stuff out of the way, we might want to make sure that the legal side is taken care of as well.</p>

<p>Yes, I know, it might be less fun thinking about licenses than writing code, but it is still something that has to be done. You still have to release your code under some kind of license, and you will have to make sure that the third-party licenses do not violate your own licensing. So, why not leave that job to a plugin?</p>

<p>The following plugin will manage the license of a maven project and its dependencies; it will also update file headers, download dependency licenses, check third-party licenses, etc.</p>

<ul>
  <li><strong><a href="http://www.mojohaus.org/license-maven-plugin/">License</a> plugin</strong></li>
</ul>

<hr />

<h2 id="3-rapid-development">3. Rapid Development</h2>

<p>Now, back to coding. Or even better &#8211; to seeing the results of your hard work. The chances are that you will need some kind of web or application server for running your code, and you want to able to deploy to that server in no time. Another kind of plugins that will be helping you from the very first day of the project.</p>

<p>Some of the plugins that can be mentioned here:</p>

<ul>
  <li><strong><a href="http://tomcat.apache.org/maven-plugin.html">Apache Tomcat</a> plugin</strong></li>
  <li><strong><a href="https://mvnrepository.com/artifact/org.eclipse.jetty/jetty-maven-plugin">Jetty</a> plugin</strong></li>
  <li><strong><a href="https://docs.jboss.org/wildfly/plugins/maven/latest/">WildFly</a> plugin</strong></li>
  <li><em>&#8230;or any other deploy plugin, depending on your application</em></li>
</ul>

<hr />

<h2 id="4-documentation">4. Documentation</h2>

<p>Every decent project must also be properly documented. However, this is something that developers might postpone until the end. Well, no more! This kind of plugins will help you to get started early and will help you to produce some beautiful (<em>maybe?</em>) and maintainable docs.</p>

<p>You might even consider coupling these with some rules in the Enforcer plugin, but tread carefully as too many, and too strict rules can, and usually do, backfire.</p>

<ul>
  <li><strong><a href="https://maven.apache.org/plugins/maven-site-plugin/">Site</a> plugin</strong></li>
  <li><strong><a href="http://asciidoctor.org/docs/asciidoctor-maven-plugin/">Asciidoctor</a> plugin</strong></li>
</ul>

<hr />

<h2 id="5-testing-and-qa">5. Testing and QA</h2>

<p>By now, your code should be looking great, with all the right licenses, and up and running in no time. So, how about squashing some [virtual] bugs? The list below might help you setting up a proper QA environment and fixing bugs before the come crawling to your production servers.</p>

<ul>
  <li><strong><a href="http://maven.apache.org/surefire/maven-surefire-plugin/">Surefire</a> plugin</strong></li>
  <li><strong><a href="http://maven.apache.org/surefire/maven-failsafe-plugin/">Failsafe</a> plugin</strong></li>
  <li><strong><a href="http://www.mojohaus.org/sonar-maven-plugin/project-info.html">SonarQube</a> plugin</strong></li>
  <li><strong><a href="http://gleclaire.github.io/findbugs-maven-plugin/">FindBugs</a> plugin</strong></li>
  <li><strong><a href="https://maven.apache.org/plugins/maven-pmd-plugin/">PMD</a> plugin</strong></li>
</ul>

<hr />

<h2 id="bonus-video">Bonus: Video</h2>

<p>A video of a talk I gave about this topic at <a href="http://2015.javazone.no/details.html?talk=86734cc36c24b081d399454534248f3aad7062ce30de5aea27de84f80a476269">JavaZone</a> in Oslo (in Norwegian).</p>

<iframe src="https://player.vimeo.com/video/138955650?byline=0&amp;portrait=0" width="640" height="360" frameborder="0" webkitallowfullscreen="" mozallowfullscreen="" allowfullscreen=""></iframe>

<hr />]]></content><author><name>Rustam Mehmandarov</name></author><summary type="html">The five main types of Maven plugins that will simplify the development process and increase maintainability of a project.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://mehmandarov.com/assets/images/posts-images/desk-pencils_1200x800.jpg"/><category term="blog"/><category term="field notes"/><category term="maven"/><category term="software development"/><category term="build and deploy"/><category term="automation"/><category term="java"/><category term="english"/></entry><entry><title type="html">Posting Jekyll Content on Time</title><link href="https://mehmandarov.com/jekyll-content-on-time/" rel="alternate" type="text/html" title="Posting Jekyll Content on Time"/><published>2016-06-12T11:04:00+02:00</published><updated>2016-06-12T11:04:00+02:00</updated><id>https://mehmandarov.com/jekyll-content-on-time</id><content type="html" xml:base="https://mehmandarov.com/jekyll-content-on-time/"><![CDATA[<p><em>Posting of content in Jekyll relies on the date assigned to the post, and the time is relative to the time zone on the server. While this works fine for local installations of Jekyll, it can sometimes be confusing when running Jekyll on the remote servers without being able to control the time zone on that server, like hosting the content on GitHub Pages.</em></p>

<ul>
  <li><a href="#whats-going-on">What&#8217;s going on?</a></li>
  <li><a href="#setting-the-date-in-the-front-matter">Setting the date in the front matter</a></li>
  <li><a href="#setting-the-time-zone-in-the-jekyll-configuration-file">Setting the time zone in the Jekyll configuration file</a></li>
</ul>

<hr />

<h2 id="whats-going-on">What&#8217;s going on?</h2>

<p>So, you have written a brand new post. You have run tests on a local <a href="https://jekyllrb.com/">Jekyll</a> server, and everything looks great. You finally commit the changes to your GitHub site repository and push the changes to the server. You are excited and full of anticipation to see your new blog post online, you hit refresh in your browser, and&#8230; nothing. Another refresh &#8211; still nothing.</p>

<p>One of the reasons for this is that you have specified a date/time for your post in the <a href="https://jekyllrb.com/docs/frontmatter/">YAML front matter</a> in the header.</p>

<p>By setting a date in the front matter, you can override the date/time assigned to the post in the format <code class="language-plaintext highlighter-rouge">YYYY-MM-DD HH:MM:SS</code>. However, this notation will use the local time zone, set by your operating system. This works fine when running a local installation of Jekyll. However, if your Jekyll installation is running on a remote server (e.g., on the GitHub Pages server) the time on that server is likely not to be the same as the time on your local machine. Jekyll will then wait before processing the contents of the post until the specified time hits the clock on the server.</p>

<p>For your post to be processed according to your time zone, you can either add a UTC offset for your time zone for the post in question or specify a time zone in the Jekyll configuration file.</p>

<h2 id="setting-the-date-in-the-front-matter">Setting the date in the front matter</h2>

<p>To specify the UTC offset for each post use the following format: <code class="language-plaintext highlighter-rouge">YYYY-MM-DD HH:MM:SS +/-TTTT</code>, e.g. <code class="language-plaintext highlighter-rouge">2016-06-12 11:04:00 +0200</code>. This might be useful if you want to specify the offset for some specific posts.</p>

<figure class="highlight"><pre><code class="language-yaml" data-lang="yaml"><span class="nn">---</span>
<span class="na">title</span><span class="pi">:</span> <span class="s2">"</span><span class="s">Your</span><span class="nv"> </span><span class="s">title"</span>
<span class="na">layout</span><span class="pi">:</span> <span class="s">post</span>
<span class="na">date</span><span class="pi">:</span> <span class="s">2016-06-12 11:04 +0200</span>
<span class="nn">---</span>
<span class="s">Your content.</span></code></pre></figure>

<h2 id="setting-the-time-zone-in-the-jekyll-configuration-file">Setting the time zone in the Jekyll configuration file</h2>

<p>If you want an offset to be applied to all of the dates on your site, you should configure Jekyll by setting the time zone for site generation in <code class="language-plaintext highlighter-rouge">_config.yml</code>.</p>

<p>Any entry from the <a href="https://en.wikipedia.org/wiki/Tz_database">IANA Time Zone Database</a> is a valid value, e.g., <code class="language-plaintext highlighter-rouge">Europe/Oslo</code>. Wikipedia also has a list of <a href="https://en.wikipedia.org/wiki/List_of_tz_database_time_zones">all available values</a>.</p>

<figure class="highlight"><pre><code class="language-yaml" data-lang="yaml"><span class="c1"># set timezone</span>
<span class="na">timezone</span><span class="pi">:</span> <span class="s">Europe/Oslo</span></code></pre></figure>

<p>If not specified, Jekyll will use the local time zone, as set by your operating system.</p>

<hr />]]></content><author><name>Rustam Mehmandarov</name></author><summary type="html">Posting of content in Jekyll relies on the date assigned to the post, and the time is relative to the time zone on the server. It can sometimes be confusing when running Jekyll on the remote servers in different time zones, like hosting the content on GitHub Pages.</summary><category term="blog"/><category term="field notes"/><category term="jekyll"/><category term="english"/></entry></feed>
