<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Oscar Medina</title>
    <description>The latest articles on Forem by Oscar Medina (@devopsoscar).</description>
    <link>https://forem.com/devopsoscar</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F182527%2F13ca9a10-734e-47a7-9964-fb50975dfb1f.jpg</url>
      <title>Forem: Oscar Medina</title>
      <link>https://forem.com/devopsoscar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/devopsoscar"/>
    <language>en</language>
    <item>
      <title>Enable Self-service Deployments for Devs in EKS</title>
      <dc:creator>Oscar Medina</dc:creator>
      <pubDate>Mon, 09 May 2022 20:51:16 +0000</pubDate>
      <link>https://forem.com/devopsoscar/enable-self-service-deployments-for-devs-in-eks-dal</link>
      <guid>https://forem.com/devopsoscar/enable-self-service-deployments-for-devs-in-eks-dal</guid>
      <description>&lt;p&gt;If you are interested in establishing a smooth collaboration with your Platform Team and n Dev Teams, and allowing Dev Teams to deploy freely and at will without Platform Team being the bottleneck, please checkout my article on the &lt;a href="https://www.hashicorp.com/blog/enable-self-service-aws-eks-deployments-with-cdk-for-terraform"&gt;HashiCorp Learn Series&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Oscar Medina, senior cloud architect at Amazon Web Services, joined us on a live stream recently to demo a collaborative workflow to enable self-service Amazon EKS deployments for developers, using CDK for Terraform. Check out the recording of the live demo, and read on for a tutorial of the workflow that platform and developer teams can use to collaborate on Kubernetes deployments with HashiCorp Terraform, Sentinel policies, CDK for Terraform, and EKS.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;iframe width="560" height="315" src="https://www.youtube.com/embed/ijgKc6vGVyM" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&amp;gt;&amp;lt;/iframe&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>kubernetes</category>
      <category>eks</category>
      <category>terraform</category>
    </item>
    <item>
      <title>Securing Apps Deployed via Jenkins X Using Ambassador Edge Stack</title>
      <dc:creator>Oscar Medina</dc:creator>
      <pubDate>Wed, 24 Jun 2020 19:55:08 +0000</pubDate>
      <link>https://forem.com/devopsoscar/securing-apps-deployed-via-jenkins-x-using-ambassador-edge-stack-4oa</link>
      <guid>https://forem.com/devopsoscar/securing-apps-deployed-via-jenkins-x-using-ambassador-edge-stack-4oa</guid>
      <description>&lt;h1&gt;
  
  
  Overview
&lt;/h1&gt;

&lt;p&gt;Microservice orchestrated by Kubernetes sometimes need not be public-facing.  &lt;/p&gt;

&lt;p&gt;There are many options to secure an endpoint, however, in this post we walk through configuring &lt;a href="https://getambassador.io"&gt;Datawire's Ambassador Edge Stack&lt;/a&gt; to protect an app which has been put through CI/CD and published via Jenkins X.  We enable SSO to leverage existing identity management using Azure Active Directory all in AWS and EKS.&lt;/p&gt;

&lt;p&gt;I also walk you through installing Jenkins X on AWS EKS first, then installing and configuring Ambassador.  Of course, if you have a &lt;strong&gt;Jenkins X&lt;/strong&gt; cluster already, you can skip to the &lt;strong&gt;Setup Ambassador Edge Stack&lt;/strong&gt; section.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub Repo&lt;/strong&gt;: You can &lt;a href="https://github.com/jenkins-oscar/skiapp/tree/ambassador-annotations"&gt;clone&lt;/a&gt; the repo specific branch.&lt;/p&gt;

&lt;h1&gt;
  
  
  Create EKS Cluster
&lt;/h1&gt;

&lt;p&gt;For this scenario, we will use AWS EKS&lt;/p&gt;

&lt;p&gt;Create an EKS cluster using &lt;code&gt;eksctl&lt;/code&gt; using the following command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;eksctl create cluster  &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--name&lt;/span&gt; drymartini  &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--full-ecr-access&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the cluster is &lt;strong&gt;Active&lt;/strong&gt; you are ready to install Jenkins X.&lt;/p&gt;

&lt;h1&gt;
  
  
  Configure Route 53 DNS
&lt;/h1&gt;

&lt;p&gt;Part of our scenario is to configure Jenkins X with a custom domain.  To do this, we must first configure a Route 53 &lt;strong&gt;Managed Zone&lt;/strong&gt; then delegate your subdomain to Route 53.  In my case, my domain is managed by Google Domains, and so I’ve created an NS record pointing to the NS servers given to me by Route 53 after I created my Hosted Zone.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a Managed Zone for subdomain&lt;/li&gt;
&lt;li&gt;Delegate your subdomain to AWS Route 53 from the vendor hosting your domain.&lt;/li&gt;
&lt;li&gt;Test it using dig &lt;code&gt;jx.eks.sharepointoscar.com&lt;/code&gt; (in my case).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; Testing the Hosted Zone can be done from the AWS Console, and ultimately you want a response with NOERROR&lt;/p&gt;

&lt;h1&gt;
  
  
  Install Jenkins X using Boot
&lt;/h1&gt;

&lt;p&gt;With the cluster created and DNS configured, we are ready to install Jenkins X using &lt;strong&gt;Jenkins X Boot&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We will be using a stable distribution of the open-source Jenkins X project, otherwise known as CJXD &lt;a href="https://www.cloudbees.com/products/cloudbees-jenkins-x-distribution/overview"&gt;CloudBees Jenkins X Distribution&lt;/a&gt;.  The advantage of using this edition vs. the straight OSS is that it has been tested, and certified for EKS, it also allows for a controlled platform upgrade within your enterprise environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install Jenkins X CLI
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# download binary for CJXD (CloudBees Jenkins X Distro) based on your platform.&lt;/span&gt;
&lt;span class="c"&gt;# https://docs.cloudbees.com/docs/cloudbees-jenkins-x-distribution &lt;/span&gt;
curl &lt;span class="nt"&gt;-L&lt;/span&gt; https://storage.googleapis.com/artifacts.jenkinsxio.appspot.com/binaries/cjxd/latest/jx-darwin-amd64.tar.gz | &lt;span class="nb"&gt;tar &lt;/span&gt;xzv

&lt;span class="c"&gt;# move to bin&lt;/span&gt;
&lt;span class="nb"&gt;sudo mv &lt;/span&gt;jx /usr/local/bin

&lt;span class="c"&gt;# test&lt;/span&gt;
➜ jx version
NAME               VERSION
jx                 2.0.1245+cjxd.8
Kubernetes cluster v1.14.10-gke.27
kubectl            v1.15.0
helm client        2.14.3
git                2.21.0
Operating System   Mac OS X 10.14.6 build 18G3020
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Execute JX Boot
&lt;/h2&gt;

&lt;p&gt;Our next step is to install Jenkins X on top of the EKS cluster.  We do this by using a declarative &lt;code&gt;yaml&lt;/code&gt; approach.&lt;/p&gt;

&lt;p&gt;During the &lt;code&gt;curl&lt;/code&gt; of the &lt;code&gt;jx&lt;/code&gt; binary, a couple of &lt;code&gt;yaml&lt;/code&gt; files were downloaded to the same directory where we executed that command.&lt;/p&gt;

&lt;p&gt;We will use the &lt;code&gt;jx-requirements-eks.yml&lt;/code&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1 - Modify the jx-requirements-eks.yml file with basic settings
&lt;/h3&gt;

&lt;p&gt;The basic settings we will modify in order to execute an initial jx boot installation will be as follows (please modify your file accordingly)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cluster:
 clusterName: drymartini
 environmentGitOwner: jenkins-oscar &lt;span class="c"&gt;#github organization&lt;/span&gt;
 environmentGitPublic: &lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="c"&gt;#my org is on free tier, so public repos&lt;/span&gt;
 provider: eks
 region: us-west-2

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next we modify the main &lt;code&gt;ingress&lt;/code&gt; field as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ingress:
 domain: jx.eks.sharepointoscar.com &lt;span class="c"&gt;#Route 53 Managed Zone&lt;/span&gt;
 externalDNS: &lt;span class="nb"&gt;true
 &lt;/span&gt;ignoreLoadBalancer: &lt;span class="nb"&gt;true
 &lt;/span&gt;namespaceSubDomain: &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="c"&gt;# personally a dot makes for cleaner FQDN entries&lt;/span&gt;
 tls:
   email: me@sharepointoscar.com
   enabled: &lt;span class="nb"&gt;true
   &lt;/span&gt;production: &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;HashiCorp Vault Initial Configuration&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In order for the jx boot command to run successfully the first time, we need to specify an IAM username in the specific jx-requirements-eks.yml file section as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vault:
 aws:
   autoCreate: &lt;span class="nb"&gt;true
   &lt;/span&gt;iamUserName: aws_admin@sharepointoscar.com &lt;span class="c"&gt;#IAM Username&lt;/span&gt;
 disableURLDiscovery: &lt;span class="nb"&gt;true&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For details on IAM permissions, please refer to the &lt;a href="https://docs.cloudbees.com/docs/cloudbees-jenkins-x-distribution/latest/eks-install-guide/aws-iam-permissions"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2 - Execute JX Boot CLI Command
&lt;/h3&gt;

&lt;p&gt;Having modified the appropriate fields in the jx-requirements-eks.yml, we are ready to execute the jx boot CLI command as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;jx boot &lt;span class="nt"&gt;-r&lt;/span&gt; jx-requirements.eks.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The CLI will ask a few questions.&lt;/p&gt;

&lt;p&gt;The cluster configuration repository is cloned immediately.  This repository will be added to your GitHub Organization, and any future changes will require a Pull Request, the GitOps way!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;IMPORTANT:&lt;/strong&gt; Any future executions of jx boot, will require you to execute it from the root of the &lt;a href="https://github.com/cloudbees/cloudbees-jenkins-x-boot-config.git"&gt;cluster configuration repository&lt;/a&gt; that was cloned during the first run.  This effectively means the original jx-requirements-eks.yml file is no longer used in subsequent executions.&lt;/p&gt;

&lt;h1&gt;
  
  
  Setup Ambassador Edge Stack
&lt;/h1&gt;

&lt;p&gt;To setup Ambassador, you can follow the simple instructions on their wonderful &lt;a href="https://www.getambassador.io/docs/latest/topics/install/"&gt;Docs site&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Install from MacOS
&lt;/h4&gt;

&lt;p&gt;Download it with a curl command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;curl &lt;span class="nt"&gt;-fL&lt;/span&gt; https://metriton.datawire.io/downloads/darwin/edgectl &lt;span class="nt"&gt;-o&lt;/span&gt; /usr/local/bin/edgectl &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo chmod &lt;/span&gt;a+x /usr/local/bin/edgectl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The installer will provision a load balancer, configure TLS, and provide you with an edgestack.me subdomain. The edgestack.me subdomain allows the Ambassador Edge Stack to automatically provision TLS and HTTPS for a domain name, so you can get started right away.&lt;/p&gt;

&lt;p&gt;Once you have it configured, you are ready to move to next step.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create AD App Registration
&lt;/h3&gt;

&lt;p&gt;Setup Azure App Registration as per the &lt;a href="https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app"&gt;instructions on Docs site&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configure Filter
&lt;/h3&gt;

&lt;p&gt;Create a file &lt;code&gt;oauth_filter.yaml&lt;/code&gt; and paste this content.  Then deploy it via &lt;code&gt;kubectl apply -f oauth_filter.yaml&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;getambassador.io/v2&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Filter&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;azure-skiapp-ad&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;jx-staging&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;OAuth2&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;authorizationURL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://login.microsoftonline.com/&amp;lt;AD_TENANT_ID&amp;gt;/v2.0&lt;/span&gt;  &lt;span class="c1"&gt;## URL where Ambassador Edge Stack can find OAuth2 descriptor&lt;/span&gt;
    &lt;span class="na"&gt;clientID&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;APP_CLIENT_ID&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;## OAuth2 client from your IdP&lt;/span&gt;
    &lt;span class="na"&gt;secret&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;APP_SECRET&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;## Secret used to access OAuth2 client&lt;/span&gt;
    &lt;span class="na"&gt;protectedOrigins&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;origin&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://skiapp.dev.sharepointoscar.com&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Configure Filter Policy
&lt;/h3&gt;

&lt;p&gt;Create a file &lt;code&gt;oauth_filter_policy.yaml&lt;/code&gt; and paste this content.  Then deploy it via &lt;code&gt;kubectl apply -f oauth_filter_policy.yaml&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;getambassador.io/v2&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;FilterPolicy&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;azure-skiapp-policy&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;jx-staging&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# Requires authentication on requests from hostname&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;skiapp.dev.sharepointoscar.com"&lt;/span&gt;
      &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;*"&lt;/span&gt;
      &lt;span class="na"&gt;filters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;azure-skiapp-ad&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Additional Config via Ambassador Portal
&lt;/h3&gt;

&lt;p&gt;To access the portal, execute the CLI as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;edgectl login &lt;span class="nt"&gt;--namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ambassador &amp;lt;yourinstancename&amp;gt;.edgestack.me
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Create new &lt;strong&gt;Host&lt;/strong&gt; entry.  In my case, it is for &lt;code&gt;skiapp.dev.sharepointoscar.com&lt;/code&gt;.  I let Ambassador handle TLS as you can see.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ftM1DHPZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/nrjaftnm1eghsjt5fv5b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ftM1DHPZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/nrjaftnm1eghsjt5fv5b.png" alt="Host Config" width="880" height="356"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a new &lt;strong&gt;Mapping&lt;/strong&gt;, it should look like the following.
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pLC2bFvS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/2ca1kw26gk3d5cygiz6s.png" alt="Alt Text" width="880" height="279"&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Import App Into Jenkins X
&lt;/h1&gt;

&lt;p&gt;Import app from GitHub as follows.  NOTE:  Please make sure to fork the app before importing it.  You are effectively importing it from your own GitHub Organization.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;jx import &lt;span class="nt"&gt;--url&lt;/span&gt; &amp;lt;GITHUB_REPO_URL&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Modify App Ingress Config
&lt;/h2&gt;

&lt;p&gt;When you import an application into Jenkins X, it automatically creates a Helm Chart!  In this step, we need to modify the Helm Chart to tell Jenkins X, it should &lt;strong&gt;not&lt;/strong&gt; use &lt;code&gt;exposecontroller&lt;/code&gt; component to expose the app, which it did automatically.&lt;/p&gt;

&lt;h2&gt;
  
  
  Modify the Helm Chart
&lt;/h2&gt;

&lt;p&gt;Under the &lt;code&gt;helm/myapp&lt;/code&gt; chart, you will find a file called &lt;code&gt;values.yaml&lt;/code&gt; which we need to modify as follows.&lt;/p&gt;

&lt;p&gt;Original &lt;code&gt;Service&lt;/code&gt; configuration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;skiapp&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ClusterIP&lt;/span&gt;
  &lt;span class="na"&gt;externalPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
  &lt;span class="na"&gt;internalPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
  &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;fabric8.io/expose&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true"&lt;/span&gt;
    &lt;span class="na"&gt;fabric8.io/ingress.annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;kubernetes.io/ingress.class:&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;nginx"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Modified &lt;code&gt;Service&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;skiapp&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ClusterIP&lt;/span&gt;
  &lt;span class="na"&gt;externalPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
  &lt;span class="na"&gt;internalPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
  &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;getambassador.io/config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;---&lt;/span&gt;
        &lt;span class="s"&gt;apiVersion: ambassador/v1&lt;/span&gt;
        &lt;span class="s"&gt;kind: Mapping&lt;/span&gt;
        &lt;span class="s"&gt;name: skiapp-service_mapping&lt;/span&gt;
        &lt;span class="s"&gt;host: skiapp.dev.sharepointoscar.com&lt;/span&gt;
        &lt;span class="s"&gt;prefix: /&lt;/span&gt;
        &lt;span class="s"&gt;service: skiapp:80&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this configuration in place, I can go to &lt;a href="https://skiapp.dev.sharepointoscar.com"&gt;https://skiapp.dev.sharepointoscar.com&lt;/a&gt; and will get redirected to Microsoft login screen. &lt;/p&gt;

&lt;h1&gt;
  
  
  Watch the Webinar
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=PUEno5NTSKA&amp;amp;feature=youtu.be"&gt;https://www.youtube.com/watch?v=PUEno5NTSKA&amp;amp;feature=youtu.be&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Summary
&lt;/h1&gt;

&lt;p&gt;We now have an app which was put through CI/CD using Jenkins X - protected using Ambassador, and using SSO backed by Azure Active Directory.  You can use Okta or any other IdP you environment uses, as long as it is using OAuth2 in this case.&lt;/p&gt;

&lt;p&gt;Cheers,&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/SharePointOscar"&gt;@SharePointOscar&lt;/a&gt;&lt;/p&gt;

</description>
      <category>jenkinsx</category>
      <category>kubernetes</category>
      <category>ambassador</category>
    </item>
    <item>
      <title>Interpolating HashiCorp Vault Secrets into Jenkins X Helm Chart App</title>
      <dc:creator>Oscar Medina</dc:creator>
      <pubDate>Fri, 24 Jan 2020 17:48:37 +0000</pubDate>
      <link>https://forem.com/devopsoscar/interpolating-hashicorp-vault-secrets-into-jenkins-x-helm-chart-app-4cp0</link>
      <guid>https://forem.com/devopsoscar/interpolating-hashicorp-vault-secrets-into-jenkins-x-helm-chart-app-4cp0</guid>
      <description>&lt;h1&gt;
  
  
  Overview
&lt;/h1&gt;

&lt;p&gt;If you have used Jenkins X, you know that &lt;a href="https://www.hashicorp.com/products/vault/"&gt;HashiCorp Vault&lt;/a&gt; is installed by default in the CJXD (CloudBees Jenkins X Distro).  However, there hasn't really been an example in the docs about how to use secrets stored in Vault when deploying an app that has the need for them.&lt;/p&gt;

&lt;p&gt;In this guide, I walk you through deploying the Cars REST API a &lt;a href="https://github.com/jenkins-oscar/cars-rest-api"&gt;full-stack app with a backend in MongoDB&lt;/a&gt;.  The repo branch titled &lt;strong&gt;Vault-Secrets&lt;/strong&gt; is the one you want to look at.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TIP:&lt;/strong&gt;  With the recently announced tighter Vault integration with Kubernetes, there is actually a better way.  We can inject Vault secrets directly into pods and make them available.  My friend &lt;a href="https://twitter.com/sheriffjackson"&gt;Nick Jackson&lt;/a&gt; explains how to do this on his post - &lt;a href="https://www.hashicorp.com/blog/dynamic-database-credentials-with-vault-and-kubernetes/"&gt;Dynamic Database Credentials with Vault and Kubernetes&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nick and I will be showing you how to do this on &lt;em&gt;Jenkins X&lt;/em&gt; very soon, so stay tuned!&lt;/p&gt;

&lt;h1&gt;
  
  
  Prerequisites
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;Either the OSS or CJXD editions of Jenkins X working with Vault installed. &lt;/li&gt;
&lt;li&gt;Clone the &lt;a href="(https://github.com/jenkins-oscar/cars-rest-api/blob/vault-secrets/)"&gt;Cars REST API app&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  1. Creating Vault Secret
&lt;/h1&gt;

&lt;p&gt;The first thing you want to do is create the Vault Secret.  Call it &lt;code&gt;mongodb&lt;/code&gt; and add the following keys:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;mongodb-username&lt;/li&gt;
&lt;li&gt;mongodb-password&lt;/li&gt;
&lt;li&gt;mongodb-root-password&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Accessing HashiCorp Vault UI
&lt;/h3&gt;

&lt;p&gt;To access the Vault instance in Jenkins X, you will need to first retrieve the configuration by executing the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo eval&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;jx get vault-config&lt;span class="sb"&gt;`&lt;/span&gt;

&lt;span class="c"&gt;# copy the output to set env variables (yours are different of course)&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;VAULT_ADDR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://vault.cjxd.sharepointoscar.com &lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;VAULT_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;r.4bbbbbbbX4jDB4QOKoHDCid4Sxtk5v
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What we are doing is retrieving the configuration.  Then setting up Environment Variables (copy n paste them on your terminal).  If you then execute &lt;code&gt;env | grep VAULT&lt;/code&gt; you will see the variables are set.&lt;/p&gt;

&lt;p&gt;From the UI, follow the instructions to create a secret.  It should look something similar to the following:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--r9u9G6uc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/29bh2rlcv9wxup2dpr3d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--r9u9G6uc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/29bh2rlcv9wxup2dpr3d.png" alt="Vault UI" width="880" height="238"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  2. Modify the Environment Repo (Staging)
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;&lt;br&gt;
Though I am told that you can accomplish secret interpolation by setting this at the app level only, I have not tried it and so I want you to also include this on your target environment where the app is being deployed.  In my case, it is &lt;em&gt;Staging&lt;/em&gt;.  Take a look at the actual &lt;a href="https://github.com/jenkins-oscar/environment-whiskeysour-staging/blob/master/env/values.tmpl.yaml"&gt;file in my repo&lt;/a&gt;.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;You will want to check out the file located at &lt;code&gt;env/values.yaml&lt;/code&gt; (this file can be empty based on my experience, later gets populated again)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You will want to create a new file, name it &lt;code&gt;env/values.tmpl.yaml&lt;/code&gt;.  The file should look like the sample code below.  At the bottom is where I add my app secrets and set them as &lt;em&gt;environment variables&lt;/em&gt; for the &lt;em&gt;Staging&lt;/em&gt; environment.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;
&lt;span class="na"&gt;PipelineSecrets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{}&lt;/span&gt;
&lt;span class="na"&gt;cleanup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;Annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;helm.sh/hook&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pre-delete&lt;/span&gt;
    &lt;span class="na"&gt;helm.sh/hook-delete-policy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hook-succeeded&lt;/span&gt;
  &lt;span class="na"&gt;Args&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--cleanup&lt;/span&gt;
&lt;span class="na"&gt;expose&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;Annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;helm.sh/hook&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;post-install,post-upgrade&lt;/span&gt;
    &lt;span class="na"&gt;helm.sh/hook-delete-policy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hook-succeeded&lt;/span&gt;
  &lt;span class="na"&gt;Args&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--v&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;
  &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;domain&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cjxd.sharepointoscar.com&lt;/span&gt;
    &lt;span class="na"&gt;exposer&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Ingress&lt;/span&gt;
    &lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true"&lt;/span&gt;
    &lt;span class="na"&gt;tlsacme&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;false"&lt;/span&gt;
&lt;span class="na"&gt;jenkins&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;Servers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Global&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{}&lt;/span&gt;
&lt;span class="na"&gt;prow&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{}&lt;/span&gt;

&lt;span class="na"&gt;cars-rest-api&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;MONGODB_USERNAME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vault:mongodb:mongodb-username&lt;/span&gt;
    &lt;span class="na"&gt;MONGODB_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vault:mongodb:mongodb-password&lt;/span&gt;
    &lt;span class="na"&gt;MONGODB_DATABASE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cars-rest-api&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  3. Modify App Helm Charts
&lt;/h1&gt;

&lt;p&gt;There are several files we need to modify for two charts, the main chart is named &lt;em&gt;cars-rest-api&lt;/em&gt; and the &lt;em&gt;Preview&lt;/em&gt; app helm chart. Here is the structure depicting the charts in question.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
➜ tree charts &lt;span class="nt"&gt;-l&lt;/span&gt; 2
charts
├── cars-rest-api
│   ├── Chart.yaml
│   ├── Makefile
│   ├── README.md
│   ├── requirements.lock
│   ├── requirements.yaml
│   ├── templates
│   │   ├── NOTES.txt
│   │   ├── _helpers.tpl
│   │   ├── deployment.yaml
│   │   ├── ksvc.yaml
│   │   └── service.yaml
│   └── values.yaml
└── preview
    ├── Chart.yaml
    ├── Makefile
    ├── requirements.yaml
    └── values..yaml


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The requirements.yaml changes
&lt;/h2&gt;

&lt;p&gt;First, we must add the dependencies to the main chart.  There is nothing new here, we add the MongoDB dependency to our chart using Helm standard approach, which is by modifying the &lt;code&gt;requirements.yaml&lt;/code&gt; as shown below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;dependencies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mongodb&lt;/span&gt;
  &lt;span class="na"&gt;alias&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cars-rest-api-db&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;7.6.5&lt;/span&gt;
  &lt;span class="na"&gt;repository&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://kubernetes-charts.storage.googleapis.com&lt;/span&gt;
  &lt;span class="na"&gt;condition&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cars-rest-api-db.enabled&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we modify &lt;code&gt;values.yaml&lt;/code&gt; and add to the &lt;code&gt;env:&lt;/code&gt; variables as well as the &lt;code&gt;mongoDB&lt;/code&gt; dependency, which I've aliased as &lt;code&gt;cars-rest-api-db&lt;/code&gt; (shown on &lt;code&gt;requirements.yaml&lt;/code&gt; above) &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; It is important to notice that the reference to the Vault keys within the MongoDB chart parameters is within double-quotes.  Took me &lt;strong&gt;4 full days to realize this issue and I grew more gray hair for sure.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The values.yaml changes
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;values.yaml&lt;/code&gt; file should look like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt; &lt;span class="s"&gt;.....&lt;/span&gt;
&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;MONGDB_USERNAME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vault:mongodb:mongodb-username&lt;/span&gt;
  &lt;span class="na"&gt;MONGDB_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vault:mongodb:mongodb-password&lt;/span&gt;
  &lt;span class="na"&gt;MONGDB_ROOT_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vault:mongodb:mongodb-root-password&lt;/span&gt;
&lt;span class="s"&gt;....&lt;/span&gt;

&lt;span class="c1"&gt;# MongoDB Configuration&lt;/span&gt;
&lt;span class="na"&gt;cars-rest-api-db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;## Whether to deploy a mongodb server to satisfy the application database requirements.&lt;/span&gt;
  &lt;span class="c1"&gt;## To use an external database set this to false and configure the externaldb parameters&lt;/span&gt;
  &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;

  &lt;span class="c1"&gt;## Enable authentication&lt;/span&gt;
  &lt;span class="c1"&gt;## ref: https://docs.mongodb.com/manual/tutorial/enable-authentication/&lt;/span&gt;
  &lt;span class="c1"&gt;#&lt;/span&gt;
  &lt;span class="na"&gt;usePassword&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
  &lt;span class="c1"&gt;# existingSecret: jx-auth&lt;/span&gt;

  &lt;span class="c1"&gt;## MongoDB custom user and database&lt;/span&gt;
  &lt;span class="c1"&gt;## ref: https://github.com/bitnami/bitnami-docker-mongodb/blob/master/README.md#creating-a-user-and-database-on-first-run&lt;/span&gt;
  &lt;span class="c1"&gt;##&lt;/span&gt;
  &lt;span class="na"&gt;mongodbUsername&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;vault:mongodb:mongodb-username"&lt;/span&gt;
  &lt;span class="na"&gt;mongodbDatabase&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cars_rest_api"&lt;/span&gt;
  &lt;span class="na"&gt;mongodbPassword&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;vault:mongodb:mongodb-password"&lt;/span&gt;

  &lt;span class="c1"&gt;## MongoDB admin password&lt;/span&gt;
  &lt;span class="c1"&gt;## ref: https://github.com/bitnami/bitnami-docker-mongodb/blob/master/README.md#setting-the-root-password-on-first-run&lt;/span&gt;
  &lt;span class="c1"&gt;##&lt;/span&gt;
  &lt;span class="na"&gt;mongodbRootPassword&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;vault:mongodb:mongodb-root-password"&lt;/span&gt;
  &lt;span class="s"&gt;...&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Preview Chart Changes
&lt;/h2&gt;

&lt;p&gt;For the Preview chart, we modify two files.  The &lt;code&gt;values.yaml&lt;/code&gt; and the &lt;code&gt;requirements.yaml&lt;/code&gt;, very similar changes.  However, we name things differently.&lt;/p&gt;

&lt;p&gt;On the &lt;code&gt;requirements.yaml&lt;/code&gt; we alias the MongoDB as &lt;code&gt;preview-db&lt;/code&gt; and make sure we add it below the existing dependencies, BUT before the &lt;code&gt;preview&lt;/code&gt; chart definition as shown below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt; &lt;span class="na"&gt;dependencies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;alias&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;expose&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;exposecontroller&lt;/span&gt;
  &lt;span class="na"&gt;repository&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://chartmuseum.jenkins-x.io&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2.3.92&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;alias&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cleanup&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;exposecontroller&lt;/span&gt;
  &lt;span class="na"&gt;repository&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://chartmuseum.jenkins-x.io&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2.3.92&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mongodb&lt;/span&gt;
  &lt;span class="na"&gt;alias&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;preview-db&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;5.3.0&lt;/span&gt;
  &lt;span class="na"&gt;repository&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://kubernetes-charts.storage.googleapis.com&lt;/span&gt;

    &lt;span class="s"&gt;# !! "alias&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;preview" must be last entry in dependencies array !!&lt;/span&gt;
  &lt;span class="c1"&gt;# !! Place custom dependencies above !!&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;alias&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;preview&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cars-rest-api&lt;/span&gt;
  &lt;span class="na"&gt;repository&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;file://../cars-rest-api&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;values.yaml&lt;/code&gt; file contains the same environment variables as the main chart.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; It is important to notice that the reference to the Vault keys within the MongoDB chart parameters is within double-quotes.  Took me &lt;strong&gt;4 full days to realize this issue and I grew more gray hair for sure.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt; &lt;span class="s"&gt;.....&lt;/span&gt;
  &lt;span class="s"&gt;env&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;MONGODB_USERNAME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vault:mongodb:mongodb-username&lt;/span&gt;
    &lt;span class="na"&gt;MONGODB_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vault:mongodb:mongodb-password&lt;/span&gt;
    &lt;span class="na"&gt;MONGODB_DATABASE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cars-rest-api&lt;/span&gt;
    &lt;span class="na"&gt;MONGODB_ROOT_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vault:mongodb:mongodb-root-password&lt;/span&gt;
&lt;span class="c1"&gt;## MongoDB chart configuration&lt;/span&gt;
&lt;span class="c1"&gt;## ref: https://github.com/helm/charts/blob/master/stable/mongodb/values.yaml&lt;/span&gt;
&lt;span class="c1"&gt;##&lt;/span&gt;
&lt;span class="na"&gt;preview-db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;## Whether to deploy a mongodb server to satisfy the applications database requirements.&lt;/span&gt;
  &lt;span class="c1"&gt;## To use an external database set this to false and configure the externaldb parameters&lt;/span&gt;
  &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;

  &lt;span class="c1"&gt;## Enable authentication&lt;/span&gt;
  &lt;span class="c1"&gt;## ref: https://docs.mongodb.com/manual/tutorial/enable-authentication/&lt;/span&gt;
  &lt;span class="c1"&gt;# NOTE: make sure this secret is in &lt;/span&gt;
  &lt;span class="na"&gt;usePassword&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
  &lt;span class="c1"&gt;#existingSecret: preview-auth&lt;/span&gt;

  &lt;span class="c1"&gt;## MongoDB custom user and database&lt;/span&gt;
  &lt;span class="c1"&gt;## ref: https://github.com/bitnami/bitnami-docker-mongodb/blob/master/README.md#creating-a-user-and-database-on-first-run&lt;/span&gt;
  &lt;span class="c1"&gt;##&lt;/span&gt;
  &lt;span class="na"&gt;mongodbUsername&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;vault:mongodb:mongodb-username"&lt;/span&gt;
  &lt;span class="na"&gt;mongodbDatabase&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cars_rest_api"&lt;/span&gt;
  &lt;span class="na"&gt;mongodbPassword&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;vault:mongodb:mongodb-password"&lt;/span&gt;

    &lt;span class="c1"&gt;## MongoDB admin password&lt;/span&gt;
  &lt;span class="c1"&gt;## ref: https://github.com/bitnami/bitnami-docker-mongodb/blob/master/README.md#setting-the-root-password-on-first-run&lt;/span&gt;
  &lt;span class="c1"&gt;##&lt;/span&gt;
  &lt;span class="na"&gt;mongodbRootPassword&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;vault:mongodb:mongodb-root-password"&lt;/span&gt;
&lt;span class="s"&gt;.....&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Summary
&lt;/h1&gt;

&lt;p&gt;On this post, we walked through the required steps to ensure you are able to retrieve and interpolate Vault secrets within your custom app being put through CI/CD in Jenkins X.&lt;/p&gt;

&lt;p&gt;Here is the video of the webinar session where I show it in action.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/embed/LRj_yHKxG80"&gt;https://www.youtube.com/embed/LRj_yHKxG80&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cheers,&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/SharePointOscar"&gt;@SharePointOscar&lt;/a&gt;&lt;/p&gt;

</description>
      <category>jenkinsx</category>
      <category>helm</category>
      <category>kubernetes</category>
      <category>devops</category>
    </item>
    <item>
      <title>Using Rollout.io Feature Flags for apps deployed via Jenkins X CI/CD</title>
      <dc:creator>Oscar Medina</dc:creator>
      <pubDate>Fri, 30 Aug 2019 17:27:20 +0000</pubDate>
      <link>https://forem.com/devopsoscar/using-rollout-io-feature-flags-for-apps-deployed-via-jenkins-x-ci-cd-54j1</link>
      <guid>https://forem.com/devopsoscar/using-rollout-io-feature-flags-for-apps-deployed-via-jenkins-x-ci-cd-54j1</guid>
      <description>&lt;h1&gt;
  
  
  Overview
&lt;/h1&gt;

&lt;p&gt;I believe any company that produces software, will always have the need to test if a new feature is working for its target audience.  We know that giants like Facebook do this, and they do it well.&lt;/p&gt;

&lt;p&gt;How can you elevate your feature deployment game?  Use feature flags to target a group of users with a specific feature, get feedback and improve said feature all while leveraging Jenkins X CI/CD and Environments!&lt;/p&gt;

&lt;p&gt;What are feature flags?  Here is directly from rollout.io&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Feature flags are at the core of Rollout.io. Using feature flags, you can easily enable and disable features in your application, giving you full control over how users are able to interact with your application.&lt;br&gt;
                                                                                        - rollout.io&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Prerequisites
&lt;/h1&gt;

&lt;p&gt;To get started, you will need to do the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Sign up for a &lt;a href="http://rollout.io"&gt;rollout.io&lt;/a&gt; account.&lt;/li&gt;
&lt;li&gt;Ensure you have to Rollout Environments (Production, Staging) &lt;/li&gt;
&lt;li&gt;You have &lt;code&gt;jx&lt;/code&gt; &lt;a href="https://jenkins-x.io/getting-started/install/"&gt;installed&lt;/a&gt; and a cluster running in GKE for example.&lt;/li&gt;
&lt;li&gt;This post is based on a &lt;a href="https://jenkins-x.io/developing/create-quickstart/"&gt;Jenkins X QuickStart&lt;/a&gt; I created and is available to you already. It is called &lt;code&gt;rollout-app&lt;/code&gt;.  To follow along, simply create it using &lt;code&gt;jx create quickstart&lt;/code&gt;, then select it.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Scenario
&lt;/h1&gt;

&lt;p&gt;Our scenario is simple.  We have a NodeJS application, and we would like to test if a button placement on the UI makes sense.  So we will use Rollout.io Feature Flags to configure our NodeJS app accordingly. &lt;/p&gt;

&lt;p&gt;The app will be put through CI/CD in Jenkins X.  The &lt;strong&gt;Staging&lt;/strong&gt; environment is the place where our intended audience will view the new feature, in this scenario it is just a button.  No other environment will have that button show up.&lt;/p&gt;

&lt;h1&gt;
  
  
  Rollout Dashboard Configuration
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Create a Custom Property, call it &lt;code&gt;JenkinsX Environment&lt;/code&gt; of type &lt;code&gt;string&lt;/code&gt; by going to left navigation &lt;strong&gt;App Settings&lt;/strong&gt; &amp;gt; &lt;strong&gt;Custom Properties&lt;/strong&gt;, click &lt;em&gt;Add New Custom Property&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a &lt;strong&gt;Flag&lt;/strong&gt; within the Rollout &lt;code&gt;Staging&lt;/code&gt; environment, by clicking on the left nav under Staging &amp;gt; Experiments, then click &lt;strong&gt;New Experiment&lt;/strong&gt; and select &lt;code&gt;Create Flag1&lt;/code&gt;  Confusing right, but that should work.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ggiEwqVH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/9xsde66i7ugqal12jycl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ggiEwqVH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/9xsde66i7ugqal12jycl.png" alt="Create Flag"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Call the flag &lt;code&gt;jenkinsx environment&lt;/code&gt;, this will map to an internal name of &lt;code&gt;ski-rollout.jenkinsx_environment&lt;/code&gt; which we create via code.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a &lt;strong&gt;Target Group&lt;/strong&gt; and configure it as shown below&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UyBM0zXO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/6rj5w9uwn0jpr1zw4whm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UyBM0zXO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/6rj5w9uwn0jpr1zw4whm.png" alt="Target Group"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We are creating a &lt;strong&gt;Target Group&lt;/strong&gt; that is &lt;em&gt;targeting&lt;/em&gt; the Staging Environment in Jenkins X.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; Enter the values as strings (multiple), ensure that you add the exact name of your environment &lt;code&gt;namespace&lt;/code&gt;, which you can obtain by executing &lt;code&gt;jx get env&lt;/code&gt; and view the &lt;strong&gt;NAMESPACE&lt;/strong&gt; column.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create an &lt;strong&gt;Experiment&lt;/strong&gt; and configure it to target the group you created in the previous step.  It should be configured as follows:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aBM5Bjfe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/e0jazmvj4a2qtt5ap0ow.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aBM5Bjfe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/e0jazmvj4a2qtt5ap0ow.png" alt="Experiment"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ensure, that the dropdown, is set to &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  The App Code
&lt;/h1&gt;

&lt;p&gt;Integrating Rollout into our NodeJS application is actually quite simple.  For this example, I've added the necessary code into the &lt;code&gt;server.js&lt;/code&gt; file, ideally you organize your files as needed to avoid having this file cluttered.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;fileSystem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;Rox&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rox-node&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

&lt;span class="c1"&gt;//setup Rollout app settings container and flag&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;appSettingsContainer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;jenkinsx_environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Rox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Flag&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// this property must exist in the Rollout Dashboard.&lt;/span&gt;
&lt;span class="nx"&gt;Rox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setCustomStringProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;JenkinsX Environment&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jenkinsx_environment&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// change the name accordingly&lt;/span&gt;
&lt;span class="nx"&gt;Rox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ski-rollout&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;appSettingsContainer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


&lt;span class="c1"&gt;// Rollout Staging Env&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;setupRox&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;calling Rox.setup for Staging...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// the parameter for setup, is the ID of the Staging Environment in the Rollout Dashboard.&lt;/span&gt;
    &lt;span class="c1"&gt;// you can use other environment IDs but those must be defined in the Rollout Dashboard.&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Rox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;5d016c4223864938a85c1d33&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

      &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;sleep&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;_result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;


 &lt;span class="nx"&gt;setupRox&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;appSettingsContainer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jenkinsx_environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isEnabled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;----- We are in Staging Jenkins X environment! --------&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
     &lt;span class="p"&gt;}&lt;/span&gt;
     &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;------ What Jenkins X environment? : &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jenkinsx_environment&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; ---------&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
     &lt;span class="p"&gt;}&lt;/span&gt;

 &lt;span class="p"&gt;});&lt;/span&gt;


&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getJXEnvironment&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;_env&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;_env&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fileSystem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/var/run/secrets/kubernetes.io/serviceaccount/namespace&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;_env&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Routes - we pass two variables to the HTML to preform approrpiate actions based on conditions.&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;// first ensure we have our file contents, which contains the k8s namespace we are in.&lt;/span&gt;
    &lt;span class="nx"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;jenkinsx_environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;getJXEnvironment&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;----------- app.get() - called getJXEnvironment() and got: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jenkinsx_environment&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; so rendering ---------------------&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pages/index&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,{&lt;/span&gt;&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jenkinsx_environment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="na"&gt;renderButton&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;appSettingsContainer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jenkinsx_environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isEnabled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;------ Ok your app is listening on port 8080! -------- &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here is what the end result looks like.  Notice the URL and the button showing for this environment.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PU5DGFV9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/9exwgs9cxvx4d6pt9uhe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PU5DGFV9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/9exwgs9cxvx4d6pt9uhe.png" alt="Button showing in Staging"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;With this basic configuraton in place.   Our button will only now show when the app is running in the staging environment. This post merely scratches the surface of what is possible with Feature Flags.  I encourage you to explore releasing features in this manner.  &lt;/p&gt;

&lt;p&gt;Some of the nice capabilities I am looking forward to try are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Targeting Rules&lt;/li&gt;
&lt;li&gt;Gradual Rollout &amp;amp; Rollback&lt;/li&gt;
&lt;li&gt;Multivariate Testing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Learn more at &lt;a href="https://rollout.io/product/"&gt;rollout.io&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cheers,&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/SharePointOscar"&gt;@SharePointOscar&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;NOTE: This post originally published at &lt;a href="https://sharepointoscar.com"&gt;sharepointoscar.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>featureflags</category>
      <category>docker</category>
      <category>node</category>
      <category>jenkinsx</category>
    </item>
    <item>
      <title>Increasing CI/CD Pipeline Observability in Jenkins X</title>
      <dc:creator>Oscar Medina</dc:creator>
      <pubDate>Mon, 29 Jul 2019 22:32:59 +0000</pubDate>
      <link>https://forem.com/devopsoscar/increasing-ci-cd-pipeline-observability-in-jenkins-x-5e0i</link>
      <guid>https://forem.com/devopsoscar/increasing-ci-cd-pipeline-observability-in-jenkins-x-5e0i</guid>
      <description>&lt;h1&gt;
  
  
  Overview
&lt;/h1&gt;

&lt;p&gt;You might have heard of Observability given that folks have been talking about this for a while now.  Sure, you might think it is just the latest tech buzzword.  However, the practice has been around for a long time now.  &lt;/p&gt;

&lt;p&gt;Observability is certainly relevant today given the Microservices architectures, distributed systems, and the characteristics of modern applications being deployed at a faster pace by leveraging CI/CD pipelines to Kubernetes, in this case using Jenkins X.  Indeed old practices of setting up monitoring after an app is deployed, are no longer acceptable.&lt;/p&gt;

&lt;p&gt;Let’s face it, modern apps call for modern instrumentation, not only once they are deployed; even at build-time having proper instrumentation can help you gain insights into what is happening at various stages of the build and release process. This may include spotting any latency issues, performance and dependency download times.  In other words, instrumentation and monitoring should be baked into our deployment pipeline in Jenkins X!&lt;/p&gt;

&lt;p&gt;Given that Jenkins X is the native CI/CD platform for Kubernetes, we must start thinking of Observability in the context of the build and release of our containerized applications via this platform, and not after the deployment process itself.&lt;/p&gt;

&lt;h1&gt;
  
  
  What we are doing today
&lt;/h1&gt;

&lt;p&gt;Today, I walk you through the process of increasing observability in your build and release pipeline by implementing tracing for a couple of events such as &lt;code&gt;npm install&lt;/code&gt; and &lt;code&gt;npm test&lt;/code&gt; which are part of a sample NodeJS application.  &lt;/p&gt;

&lt;p&gt;NOTE: Tracing is only a small portion of other things that need to be in place.  Logging and Metrics are also required.  The combination and aggregation of this data allows you to understand how observable your pipeline is.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpeter.bourgon.org%2Fimg%2Finstrumentation%2F01.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpeter.bourgon.org%2Fimg%2Finstrumentation%2F01.png" alt="Components"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Diagram by: Peter Bourgon&lt;/p&gt;

&lt;h2&gt;
  
  
  Leveraging Third-Party Tools
&lt;/h2&gt;

&lt;p&gt;Jenkins X was built with extensibility and flexibility in mind.  Today, you can easily create &lt;strong&gt;QuickStarts&lt;/strong&gt; for a language not implemented.  You can also build &lt;strong&gt;addOns&lt;/strong&gt; to augment the platform functionality.  There are currently &lt;strong&gt;addOns&lt;/strong&gt; for &lt;code&gt;istio&lt;/code&gt;, &lt;code&gt;prometheus&lt;/code&gt; and &lt;code&gt;anchore&lt;/code&gt; to name a few.  Given this extensibility, we encourage our community to build these components and share with everyone.  &lt;/p&gt;

&lt;p&gt;If you look around, you’ll find that &lt;a href="http://Honeycomb.io" rel="noopener noreferrer"&gt;Honeycomb.io&lt;/a&gt; is at the forefront of Observability.  We are collaborating with them to eventually have a &lt;em&gt;Honeycomb addOn&lt;/em&gt; for Jenkins X&lt;/p&gt;

&lt;p&gt;In this post, we use the Honeycomb.io API to trace our pipeline events.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tracing CI/CD Pipeline Events
&lt;/h3&gt;

&lt;p&gt;In this scenario we want to trace start and end times for certain events.  In our example NodeJS app, we have commands such as &lt;code&gt;npm install&lt;/code&gt; and &lt;code&gt;npm test&lt;/code&gt;, which are part of our &lt;strong&gt;build-pack&lt;/strong&gt; pipeline out of the box.  To do start tracing, we modify the Tekton pipeline and inject calls to the Honeycomb.io API before and after these specific &lt;strong&gt;build pack&lt;/strong&gt; named steps.  &lt;/p&gt;

&lt;p&gt;NOTE: Please be sure to sign up for &lt;a href="http://honeycomb.io" rel="noopener noreferrer"&gt;honeycomb.io&lt;/a&gt; to obtain your &lt;strong&gt;API Key&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Create Kubernetes Secret
&lt;/h4&gt;

&lt;p&gt;Once we have our API Key, we want to create a Kubernetes Secret which is required to make API calls within our pipeline.  To do this, we create it in the &lt;code&gt;jx&lt;/code&gt; and &lt;code&gt;jx-staging&lt;/code&gt; namespaces.  For each namespace execute the following command (be sure to modify the namespace value as needed).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl create secret generic honeycomb-creds —from-literal&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;BUILDEVENT_APIKEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;KEY&amp;gt;  &lt;span class="nt"&gt;--namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;NAMESPACE&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Modify Tekton Pipeline
&lt;/h4&gt;

&lt;p&gt;Now that we have our Kubernetes Secret in place, we will modify the &lt;code&gt;jenkins-x.yaml&lt;/code&gt; file, which currently has exactly one line as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;buildpack&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;javascript&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's go over the important components of the YAML file once modified.  The first items I'd like to highlight, are the environment variables needed.  We need to provide honeycomb.io three key pieces of information:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CI Provider&lt;/strong&gt;:  this is the JENKINS-X environment variable.  Honeycomb will add additional metadata fields to our dataset&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;BUILDEVENT_DATASET&lt;/strong&gt;: this indicates which dataset we want to populate (you can have many).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;BUILDEVENT_APIKEY&lt;/strong&gt;: the Kubernetes Secret value, which is the API Key provided via the honeycomb site
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;buildPack&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;javascript&lt;/span&gt;
&lt;span class="na"&gt;pipelineConfig&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;JENKINS-X&lt;/span&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;JENKINS-X&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;BUILDEVENT_DATASET&lt;/span&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;jx&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;BUILDEVENT_APIKEY&lt;/span&gt;
    &lt;span class="na"&gt;valueFrom&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;secretKeyRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;BUILDEVENT_APIKEY&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;honeycomb-creds&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;build-pack&lt;/strong&gt; used for a NodeJS app is &lt;strong&gt;javascript&lt;/strong&gt; as detected by the language.  Hence the single line we had as the contents of the &lt;code&gt;jenkins-x.yaml&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Because we know which build-pack is being used, we can determine which named steps exist.  Typically they include an &lt;code&gt;npm install&lt;/code&gt; and &lt;code&gt;npm test&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Therefore, we want to inject a timestamp &lt;strong&gt;before&lt;/strong&gt; and &lt;strong&gt;after&lt;/strong&gt; each of these named steps are called.  The following shows how I inject this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="na"&gt;pipelines&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;overrides&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm-install&lt;/span&gt;
      &lt;span class="na"&gt;pipeline&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pullRequest&lt;/span&gt;
      &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build&lt;/span&gt;
      &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo ===== pullrequest:build:before  sending honeycomb step trace  ===============&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;honeycomb-npm-install-set-step-start-timestamp&lt;/span&gt;
        &lt;span class="na"&gt;sh&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo $(date +%s) &amp;gt; step_start&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;honeycomb-npm-install-before-timestamp&lt;/span&gt;
        &lt;span class="na"&gt;sh&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo =================================  $(cat step_start)  =================================&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;before&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm-install&lt;/span&gt;
      &lt;span class="na"&gt;pipeline&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pullRequest&lt;/span&gt;
      &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build&lt;/span&gt;
      &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo ===== pullrequest:build:after   sending honeycomb step trace  ===============&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;honeycomb-npm-install-after-timestamp&lt;/span&gt;
        &lt;span class="na"&gt;sh&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo =================================  $(cat step_start)  =================================&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;honeycomb-step-log-after-npm-install&lt;/span&gt;
        &lt;span class="na"&gt;sh&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./buildevents step "${APP_NAME}-${PULL_NUMBER}-${VERSION}-${BUILD_NUMBER}" $(echo npm-install | sum | cut -f 1 -d \ ) $(cat step_start) npm-install&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;after&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm-test&lt;/span&gt;
      &lt;span class="na"&gt;pipeline&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pullRequest&lt;/span&gt;
      &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build&lt;/span&gt;
      &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;honeycomb-npm-test-set-step-start-timestamp&lt;/span&gt;
        &lt;span class="na"&gt;sh&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo $(date +%s) &amp;gt; step_start&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;honeycomb-npm-test-before-timestamp&lt;/span&gt;
        &lt;span class="na"&gt;sh&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo =================================  $(cat step_start)  =================================&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;before&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm-test&lt;/span&gt;
      &lt;span class="na"&gt;pipeline&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pullRequest&lt;/span&gt;
      &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build&lt;/span&gt;
      &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;honeycomb-npm-test-after-timestamp&lt;/span&gt;
        &lt;span class="na"&gt;sh&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo =================================  $(cat step_start)  =================================&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;honeycomb-step-log-after-npm-test&lt;/span&gt;
        &lt;span class="na"&gt;sh&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./buildevents step "${APP_NAME}-${PULL_NUMBER}-${VERSION}-${BUILD_NUMBER}" $(echo npm-test | sum | cut -f 1 -d \ ) $(cat step_start) npm-test&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;after&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that I have  captured timestamps for these two named steps, I want to send an API call to honeycomb as follows.  You will notice how I am using a binary called &lt;strong&gt;buildevents&lt;/strong&gt; this is downloaded during the setup of my pipelines which I discuss shortly.&lt;/p&gt;

&lt;p&gt;By concatenating a few metadata pieces that exist as &lt;strong&gt;environment variables&lt;/strong&gt; in Jenkins X, I build a unique name which is needed by honeycomb to track things correctly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;pipeline&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pullRequest&lt;/span&gt;
      &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build&lt;/span&gt;
      &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;honeycomb-build-name-concat&lt;/span&gt;
        &lt;span class="na"&gt;sh&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo the build is "${APP_NAME}-${PULL_NUMBER}-${VERSION}-${BUILD_NUMBER}" and HONEYCOMB_BUILD_START=$(cat build_start)&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;honeycomb-send-success&lt;/span&gt;
        &lt;span class="na"&gt;sh&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./buildevents build "${APP_NAME}-${PULL_NUMBER}-${VERSION}-${BUILD_NUMBER}" $(cat build_start) success&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;after&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We do the same for the &lt;strong&gt;Release&lt;/strong&gt; pipeline...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# release pipeline releated calls&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm-install&lt;/span&gt;
      &lt;span class="na"&gt;pipeline&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;release&lt;/span&gt;
      &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build&lt;/span&gt;
      &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo ===== release:build:before  sending honeycomb step trace  ===============&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;release-honeycomb-npm-install-step-start-timestamp&lt;/span&gt;
        &lt;span class="na"&gt;sh&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo $(date +%s) &amp;gt; release_step_start&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;release-honeycomb-npm-install-before-timestamp&lt;/span&gt;
        &lt;span class="na"&gt;sh&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo ================================= release  release-npm-install step start  $(cat release_step_start)  =================================&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;before&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm-install&lt;/span&gt;
      &lt;span class="na"&gt;pipeline&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;release&lt;/span&gt;
      &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build&lt;/span&gt;
      &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;release-honeycomb-npm-install-after-timestamp&lt;/span&gt;
        &lt;span class="na"&gt;sh&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo ================================= release npm-install step end  $(cat release_step_start)  =================================&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;release-honeycomb-step-log-after-npm-install&lt;/span&gt;
        &lt;span class="na"&gt;sh&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./buildevents step "${APP_NAME}-${PULL_NUMBER}-${VERSION}-${BUILD_NUMBER}" $(echo release-npm-install | sum | cut -f 1 -d \ ) $(cat release_step_start) release-npm-install&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;after&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;pipeline&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;release&lt;/span&gt;
      &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build&lt;/span&gt;
      &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;release-honeycomb-build-name-concat&lt;/span&gt;
        &lt;span class="na"&gt;sh&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo the build is "${APP_NAME}-${PULL_NUMBER}-${VERSION}-${BUILD_NUMBER}" and HONEYCOMB_BUILD_START=$(cat release_start)&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;release-honeycomb-build-send-success&lt;/span&gt;
        &lt;span class="na"&gt;sh&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./buildevents build "${APP_NAME}-${PULL_NUMBER}-${VERSION}-${BUILD_NUMBER}" $(cat release_start) success&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;after&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is portion of the pipeline executes first hence the &lt;strong&gt;setup&lt;/strong&gt; node.  There are several things we want to accomplish in the setup of our pipelines.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Download the Build Events binary provided by Honeycomb, make it executable&lt;/li&gt;
&lt;li&gt;Create the timestamp we will use to track the &lt;strong&gt;pullRequest&lt;/strong&gt; pipeline execution.  I do this by saving a temporary file with the timestamp.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is done for both pipelines, as we are working with both.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;
    &lt;span class="na"&gt;pullRequest&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo =========================== pullrequest:setup downloading Honeycomb.io buildevents binary ===========================&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pullrequest-download-honeycomb-binary&lt;/span&gt;
            &lt;span class="na"&gt;sh&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;curl -L -o buildevents https://github.com/honeycombio/buildevents/releases/latest/download/buildevents-linux-amd64&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;honeycomb-set-binary-permissions&lt;/span&gt;
            &lt;span class="na"&gt;sh&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;chmod 755 buildevents&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;honeycomb-display-buildevents-version&lt;/span&gt;
            &lt;span class="na"&gt;sh&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./buildevents --version&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;honeycomb-setup-build-timestamp&lt;/span&gt;
            &lt;span class="na"&gt;sh&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo $(date +%s) &amp;gt; build_start&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;honeycomb-output-debug&lt;/span&gt;
            &lt;span class="na"&gt;sh&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo the build is "${APP_NAME}-${PULL_NUMBER}-${VERSION}-${BUILD_NUMBER}" and HONEYCOMB_BUILD_START=$(cat build_start)   =======================================================&lt;/span&gt;
    &lt;span class="na"&gt;release&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo =========================== release:setup downloading Honeycomb.io buildevents binary ===========================&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;release-download-honeycomb-binary&lt;/span&gt;
          &lt;span class="na"&gt;sh&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;curl -L -o buildevents https://github.com/honeycombio/buildevents/releases/latest/download/buildevents-linux-amd64&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;release-honeycomb-set-binary-permissions&lt;/span&gt;
          &lt;span class="na"&gt;sh&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;chmod 755 buildevents&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;release-honeycomb-setup-build-timestamp&lt;/span&gt;
          &lt;span class="na"&gt;sh&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo $(date +%s) &amp;gt; release_start&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;release-honeycomb-output-debug&lt;/span&gt;
          &lt;span class="na"&gt;sh&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo the build is "${APP_NAME}-${PULL_NUMBER}-${VERSION}-${BUILD_NUMBER}" and HONEYCOMB_BUILD_START=$(cat release_start)   =======================================================&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once this pipeline executes, the dashboard on the honeycomb.io site will show us the execution tracing as follows.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fjenkins-x.io%2Fnews%2Fjenkins-x-observability%2Fhoneycomb_trace_example.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fjenkins-x.io%2Fnews%2Fjenkins-x-observability%2Fhoneycomb_trace_example.png" alt="Honeycomb Dashboard"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, we have a unique name for our build being traced, underneath that we are tracking the two events &lt;code&gt;npm install&lt;/code&gt; and &lt;code&gt;npm test&lt;/code&gt; time spans.  We can easily see how long our dependencies are taking to download, and how long does it take to run the tests for the app.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Hopefully I’ve enticed you to at least look into why you might consider incorporating observability into your build and release process. There is a lot more that can be done.  In a future post, we will cover additional setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Jenkins World | DevOps World 2019
&lt;/h2&gt;

&lt;p&gt;I'll be demoing this solution at various times while at the conference this year.  You can still register and get a big discount by using code: &lt;strong&gt;PREVIEW&lt;/strong&gt;. Instead of your cost being $1499, with discount is only $799&lt;/p&gt;

&lt;p&gt;You can find my full schedule on the &lt;a href="https://www.cloudbees.com/devops-world/san-francisco/agenda" rel="noopener noreferrer"&gt;official website&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cheers,&lt;br&gt;&lt;br&gt;
&lt;a href="https://twitter.com/SharePointOscar" rel="noopener noreferrer"&gt;@SharePointOscar&lt;/a&gt;&lt;/p&gt;

</description>
      <category>observability</category>
      <category>jenkinsx</category>
      <category>kubernetes</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
