Webpack 2 and code splitting

This week I’ve been updating our front end applications to Webpack 2. The upgrade proved to be fairly straightforward and one of the main benefits so far has been the ability to code split, dynamically load JavaScript at runtime and thus build a progressive web app.

I would recommend reading the following article for more information on how to do it:

https://hackernoon.com/straightforward-code-splitting-with-react-and-webpack-4b94c28f6c3f#.ikyl2htnu

The benefits for us are that we will be able to maintain different implementations of sub modules of our front end applications and serve them up based on the tenant who is logged in. These can either be maintained in one code base or pulled in via different npm packages.

This will also enable us to split code out into separate bundles to improve initial load speed.

Gotchas so far

Only one so far, in production if you are serving up your js bundles as gzipped files in your express server like so:


app.get('*.js', function (req, res, next) {
    req.url = req.url + '.gz';
    res.set('Content-Encoding', 'gzip');
    next();
});

Then you will need to exclude doing the above for the js you wish to load dynamically at runtime, since when the front end pulls down the js it won’t be able to handle it in gzip format.

I’ll keep you posted.

Our DevOps Toolbox

DevOps is rapidly being adopted within the IT industry. It’s a set of practices used within the IT industry to help bridge the gap between developers and operations. To help IT professionals achieve this, the industry has introduced various tools to help organisation’s achieve this.

Our toolbox

Here at Wealth Wizards we use a wide range of technologies which help us form a DevOps culture.

As our products matured, we realized how important it was to be able to perform operational task in an agile way as a part of not only keeping ahead of the competition, but also ensuring we release world class software such as Pension Wizards.

This led us down a road where we began to find various tools that we thought needed to be added to our DevOps toolbox.

Some of the tools we found along the way were open source technologies such as Ansible, Kubernetes, Node.js, Elasticsearch, Kibana, Logstash, Filebeat, Packetbeat, Consul and many more.

How our DevOps toolbox benefits Wealth Wizards

It was imperative that the tools added to our DevOps toolbox were open source, especially as we are a start-up.

Investing in open source technologies allows us to successfully carry out daily tasks whilst keeping costs down, as we don’t want to have to spend money unnecessarily by purchasing things like licenses alongside worry about complying to strict license policy.

With automation fueling the IT industry we decided to take full advantage of the DevOps tools available to us. Our DevOps toolbox enabled us to automate a lot of our manual tasks which then freed up engineers’ time allowing them to focus on other tasks that would add value to our products ultimately improving the customers experience.

Ups and Downs

Although using open source technologies has benefited us allowing us to rapidly release software updates, it has also introduced unforeseen problems.

As part of keeping our systems secure we make it a priority to remove any possible vulnerabilities that may pose a risk to our applications. This means we have had to schedule regular updates for any software used in our applications which can at times be time consuming.

As you may already be aware, out of date software can introduce inconsistencies in the way the software functions.

A perfect example of this is Kubernetes. We initially started using Kubernetes 1.3, which was the latest version at the time.

Initially, we were over the moon with the amount of out of the box functionality it had, but that was sadly short lived. We quickly began to run into problems as the open source community began to release rapid updates as part of fixing bugs and adding new additional features.

Now currently running version 1.5 we are happy with the results but are always looking out for new problems so that we can address them as soon as possible.

Although we have encountered problems we have learnt a lot along the way so we are happy to say it was worth it.

Conclusion

Our DevOps toolbox has helped us bridge the gap between developers and operations. It has also helped us simplify build and deployment process which as a result has rewarded our engineers with more time to invest in other areas of the business.

Now ask yourself, are you doing DevOps? What’s in your DevOps toolbox? Can you benefit from what’s in our DevOps toolbox?

Leading a team to deliver an MVP at breakneck speed

tl;dr

We were given the task of delivering an MVP within a short timeframe. We chose a microservice based architecture, allowing concurrent development of functionality. We adopted the popular MERN stack, unifying the language across the system. Working closely with the customer and stakeholders was key to delivering what was really wanted. High engineering standards underpinned the work that we did, providing us with fast feedback when the system broke and high confidence in deployments, and leaving us with a robust and extensible system.

The challenge

Several months ago we were given the task of delivering an MVP within only a handful of months, for a product that at its core is an over the phone variation of one of our existing offerings. It initially appeared that we could try to crowbar it into a cloned version of our existing offering, but we realized during our initial design sessions that this approach would be drastically hindered by the limitations of our existing system (which was not designed with this in mind). It would also not live up to the high engineering standards we have grown used to within our department.

We chose to adopt the strangler pattern, writing parts of our system from scratch and interfacing with our legacy system where appropriate, to make a deliverable feasible in only a handful of months, and to also build out a platform that is extensible.

In a nutshell, the plan was to quickly spin up a plain but functional UI, a new set of RESTful APIs (to overcome some technical debt we have been carrying with our legacy APIs) and a new set of data stores to keep our new products’ data separate from our existing offerings’. All this within a resilient microservice based architecture. We planned to marshall data between this new system and our legacy system where required, being careful to limit the number of microservices that would facilitate this communication with the legacy system to as few as possible. In fact, we managed to limit this to only one!

The MERN stack

The MERN stack consists of the Mongo database, the Express Node.js framework, the React front end library (often coupled with Redux), and the Node.js server environment.

Using this stack has several great advantages, including having only one language across the stack (JavaScript), being lightweight with server configuration within the code (making it ideal for microservices), being fast, and being well backed within the software industry.

Benefits of the approach

For starters, working with a microservice based architecture lends itself well to working on different parts of the system concurrently, due to the system’s decoupled nature. Assuming contracts are agreed up front, stub servers can be spun up easily using technologies such as Dyson, allowing us to isolate development and testing of components within our system without upstream components even existing yet. That’s pretty awesome.

Other great benefits include a highly decoupled back end system with a high level of cohesion, alongside a front end that separates concerns well and avoids the tie in of a large framework such as AngularJS. With React, it’s as much a philosophy as it is a library – declare the view and manage state separately, in our case with the popular Redux library. Redux enforces a unidirectional data flow and encourages a functional style, making code easier to reason about.

Engineering standards

Throughout development, we have prided ourselves on maintaining a high level of engineering standards. This goes much further than simply baking code linting into our pipeline.

For one, it has involved writing meaningful unit tests with a high level of test coverage. This allows us to validate that new functions work as desired and provide fast feedback about any regressions that have been introduced.

It has also involved writing tests at the component or integration level, providing us with confidence that the building blocks of our system fit together as components in the way we expect.

In addition, we have included several system tests, serving as a useful smoke test within our pipeline to verify that the system is up and running and not obviously broken.

Monitoring and logging are another key area for us and should be for anyone adopting a similar approach. We’ve used a “ping” dashboard to show the health of each microservice at any given time, providing us with another useful mechanism to spot failures fast.

It goes without saying that manual exploratory testing has remained a tool within our arsenal.

Working with the customer

It’s not surprising that customers will often ask for a fixed scope with fixed time but you can’t have both. We have tried to manage this by communicating well and prioritizing effectively. It’s been a key challenge for us working with the customer to establish which features are essential to delivering the key business value and which are not.

What next

As the project continues to move forward its key that we continue to gain fast and frequent feedback and involvement from the customer to help guide the future direction of the product. It’s also key that we continue to adhere to and even improve upon our high engineering standards.

In addition to incrementally adding features, I envisage us looking to add contract testing between services within our system. We know that tests at the unit and component/integration level are great to verify that those parts of the system work as expected, but it’s a great improvement to know that these parts of the system satisfy the contracts expected of them by the other services within the system. This will enable us to individually deploy microservices with truly high confidence.

Getting functional in JS with Ramda

Introduction

Lately, I’ve begun programming in JS using an increasingly functional style, with the help of Ramda (a functional programming library). What does this mean? At its core, this means writing predominantly pure functions, handling side effects and making use of techniques such as currying, partial application and functional composition. You can choose to take it further than this, however, that’s a story for another day.

The pillars of functional programming in JS

Pure functions

One key area of functional programming is the concept of pure functions. A pure function is one that takes an input and returns an output. It does not depend on external system state and it does not have any side effects. Pure functions will for a given input always return the same output, making them predictable and easy to test.

Side effects

It’s worth mentioning that side effects are sometimes unavoidable, and there are different techniques you can adopt to deal with these. But the key objective here is minimising side effects and handling these away from your pure functions.

Currying

One of the key building blocks of functional programming is the technique of currying. This is where you take a polyadic function (one with multiple arguments) and translate it into a sequence of monadic functions (functions that take a single argument). This works by each function returning its result as the argument to the next function in the sequence. This allows you to partially apply functions by fixing a number of arguments. Importantly, this also enables you to compose functions together which I’ll get onto later.

Example of partial application:

// Function for multiplying two numbers together
const multiplyTogether = (x, y) => {
return x * y;
}
multiplyTogether(2, 5);
// => 10

// Curried multiplication of two numbers
const multiplyTogetherCurried = x => y => {
return x * y;
}
multiplyTogetherCurried(2)(5);
// => 10

// Partial application used to create double number function
const doubleNumber = multiplyTogetherCurried(2);
doubleNumber(5);
// => 10

Composition

Building on currying and adopting another functional discipline of moving data to be the last argument of your function, you can now begin to make use of functional composition, and this is where things start to get pretty awesome.
With functional composition, you can create a sequence of functions which (after the first in the sequence) must be monadic, where each function feeds its returned value into the next function in the sequence as its argument, returning the result at the end of the sequence. We do this in Ramda using compose . Adopting this style can not only make code easier to reason about but also easier to read and write. In my opinion, where this style really shines is in data transformation, allowing you to break down potentially complex transformations into logical steps. Ramda is a big help here, as although you could simply choose to make use of compose and write your own curried monadic functions, it just so happens that Ramda is a library of super useful, (mostly) curried functions, containing functions for mapping over data, reducing data, omitting data based on keys, flattening and unflattening objects and so much more!

Imperative vs functional

Now that you’ve (hopefully) got a better idea of what functional programming is, the question becomes, is following an imperative style wrong? In my opinion, no. When it comes down to choosing between imperative and functional programming in JS, I believe you have to be pragmatic – whilst functional may be your go to choice, there are times when I believe you have to ask yourself if a simple if else statement will do the job. That said, adopting the discipline of writing pure functions where possible and managing side effects, along with handling data transformations using functional composition, will likely make your life as a developer a lot easier and more enjoyable. It sure has for me!

A worked example using Ramda

I’ve included a worked example of a function which I rewrote from a predominantly imperative style to a functional style, as I felt the function was becoming increasing difficult to reason about and with further anticipated additions, I was concerned it would become increasingly brittle.

Original function:

import R from 'ramda';

const dataMapper = factFindData => {
  const obj = {};

  Object.keys(factFindData).forEach(k => {
    if (k === 'retirement__pensions') {
      obj.retirement__pensions = normalizePensions(factFindData);
      return;
    }

    if (k !== 'db_options' && k !== 'health__applicant__high_blood_pressure_details__readings') {
      obj[k] = factFindData[k];
      return;
    }

    if (k === 'health__applicant__high_blood_pressure_details__readings') {
      if (factFindData.health__applicant__high_blood_pressure !== 'no') {
        obj.health__applicant__high_blood_pressure_details__readings = factFindData[k];
      }
    }
  });

  return {
    ...emptyArrays,
    ...R.omit(['_id', 'notes', 'created_at', 'updated_at'], obj),
  };
};
Refactored function:

import R from 'ramda';

const normalizeForEngine = x => ({ ...emptyArrays, ...x });
const omitNonEngineKeys = R.omit(['_id', 'notes', 'created_at', 'updated_at', 'db_options']);

const normalizeBloodPressure =
  R.when(
    x => x.health__applicant__high_blood_pressure === 'no',
    R.omit(['health__applicant__high_blood_pressure_details__readings'])
  );

const mapNormalizedPensions =
  R.mapObjIndexed((v, k, o) => k === 'retirement__pensions' ? normalizePensions(o) : v);

const dataMapper =
  R.compose(
    normalizeForEngine,
    omitNonEngineKeys,
    normalizeBloodPressure,
    mapNormalizedPensions
  );

As you can see, when trying to figure out what the data mapper function is doing in the original function, I have to loop through an object, update and maintain the state of a temporary variable (in my head), in each loop checking against multiple conditions, before then taking this result and sticking in into an object, remembering to remove certain keys.

With the refactored function, at a glance I can say that I’m normalising pensions, then normalising blood pressure, then omitting non engine keys, before finally normalising the data for the engine. Doesn’t that feel easier to reason about? If a new requirement came in to normalise let’s say, cholesterol readings, I would simply slot another curried function in after normalizeBloodPressure called for arguments sake normalizeCholesterol.

Conclusion

Functional programming in JS using Ramda can not only reduce your codebase in size, but it can also increase its readability and testability, and make it easier to reason about.

Running Jenkins on Kubernetes

by Sion Williams

tl;dr

This guide will take you through the steps necessary to continuously deliver your software to end users by leveraging Amazon Web Services and Jenkins to orchestrate the software delivery pipeline. If you are not familiar with basic Kubernetes concepts, have a look at Kubernetes 101.

In order to accomplish this goal you will use the following Jenkins plugins:

  • Jenkins EC2 Plugin – start Jenkins build slaves in AWS when builds are requested, terminate those containers when builds complete, freeing resources up for the rest of the cluster
  • Bitbucket Oauth Plugin – allows you to add your bitbucket oauth credentials to jenkins

In order to deploy the application with Kubernetes you will use the following resources:

  • Deployments – replicates our application across our kubernetes nodes and allows us to do a controlled rolling update of our software across the fleet of application instances
  • Services – load balancing and service discovery for our internal services
  • Volumes – persistent storage for containers

Credit

This article is an AWS variant of the original Google Cloud Platform article found, here.

Prerequisites

  1. An Amazon Web Services Account
  2. A running Kubernetes cluster

Containers in Production

Containers are ideal for stateless applications and are meant to be ephemeral. This means no data or logs should be stored in the container otherwise they’ll be lost when the container terminates.

– Arun Gupta

The data for Jenkins is stored in the container filesystem. If the container terminates then the entire state of the application is lost. To ensure that we don’t lose our configuration each time a container restarts we need to add a Persistent Volume.

Adding a Persistent Volume

From the Jenkins documentation we know that the directory we want to persist is going to be the Jenkins home directory, which in the container is located at /var/jenkins_home (assuming you are using the official Jenkins container). This is the directory where all our plugins are installed, jobs and config information is kept.

At this point we’re faced with a chicken and egg situation; we want to mount a volume where Jenkins Home is located, but if we do that the volume will be empty. To overcome this hurdle we first need to add our volume to a sacrificial instance in AWS, install Jenkins, copy the contents of Jenkins Home to the volume, detach it, then finally add it to the container.

Gotchas

Make sure that the user and group permissions in the Jenkins Home are the same. Failure to do so will cause the container to fail certain Write processes. We will discuss more about the Security Context later in this article.

To recursively change permissions of group to equal owner, use:

$ sudo chmod -R g=u .

Now that we have our volume populated with the Jenkins data we can start writing the Kubernetes manifests.  The main things of note are the name, volumeId and storage.

jenkins-pv.yml

apiVersion: v1
kind: PersistentVolume
metadata:
 name: jenkins-data
spec:
 capacity:
 storage: 30Gi
 accessModes:
 - ReadWriteOnce
 awsElasticBlockStore:
 volumeID: aws://eu-west-1a/vol-XXXXXX
 fsType: ext4

With this manifest we have told Kubernetes where our volume is held. Now we need to tell Kubernetes that we want to make a claim on it. We do that with a Persistent Volume Claim.

jenkins-pvc.yml

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
 name: jenkins-data
spec:
 accessModes:
 - ReadWriteOnce
 resources:
 requests:
 storage: 30Gi

In the file above we are telling Kubernetes that we would like to claim the full 30GB. We will associate this claim with a container in the next section.

Create a Jenkins Deployment and Service

Here you’ll create a deployment running a Jenkins container with a persistent disk attached containing the Jenkins home directory.

jenkins-deployment.yml

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
 annotations:
 labels:
 app: jenkins
 name: jenkins
spec:
 replicas: 1
 selector:
 matchLabels:
 app: jenkins
 template:
 metadata:
 labels:
 app: jenkins
 spec:
 containers:
 - image: jenkins:2.19.2
 imagePullPolicy: IfNotPresent
 name: jenkins
 ports:
 - containerPort: 8080
 protocol: TCP
 name: web
 - containerPort: 50000
 protocol: TCP
 name: slaves
 resources:
 limits:
 cpu: 500m
 memory: 1000Mi
 requests:
 cpu: 500m
 memory: 1000Mi
 volumeMounts:
 - mountPath: /var/jenkins_home
 name: jenkinshome
 securityContext:
 fsGroup: 1000
 volumes:
 - name: jenkinshome
 persistentVolumeClaim:
 claimName: jenkins-data

There’s a lot of information in this file. As the post is already getting long, I’m only going to pull out the most important parts.

Volume Mounts

Earlier we created a persistent volume and volume claim. We made a claim on the PersistentVolume using the PersistentVolumeClaim, and now we need to attach the claim to our container. We do this using the claim name, which hopefully you can see ties each of the manifests together. In this case jenkins-data.

Security Context

This is where I had the most problems. I found that when I used the surrogate method of getting the files onto the volume I forgot to set the correct ownership and permissions. By setting the group permissions to the same as the user, when we deploy to Kubernetes we can use the fsGroup feature.  This feature lets the Jenkins user in the container have the correct permissions on the directories via the group level permissions. We set this to 1000 as per the documentation.

If all is well and good you should now be able start each of the resources:

kubectl create -f jenkins-pv.yml -f jenkins-pvc.yml -f jenkins-deployment.yml

As long as you dont have any issues at this stage you can now expose the instance using a load balancer. In this example we are provisioning an aws loadbalancer with our AWS provided cert.

jenkins-svc.yml

apiVersion: v1
kind: Service
metadata:
 labels:
 app: jenkins
 name: jenkins
 annotations:
 service.beta.kubernetes.io/aws-load-balancer-ssl-cert: "arn:aws:acm:eu-west-1:xxxxxxxxxxxx:certificate/bac080bc-8f03-4cc0-a8b5-xxxxxxxxxxxxx"
 service.beta.kubernetes.io/aws-load-balancer-backend-protocol: "http"
 service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "443"
spec:
 ports:
 - name: securejenkinsport
 port: 443
 targetPort: 8080
 - name: slaves
 port: 50000
 protocol: TCP
 targetPort: 50000
 selector:
 app: jenkins
 type: LoadBalancer
 loadBalancerSourceRanges:
 - x.x.x.x/32

In the snippet above we also use the loadBalancerSourceRanges feature to whitelist our office. We aren’t making our CI publicly available, so this is a nice way of making it private.

I’m not going to get into the specifics of DNS etc here, but if that’s all configured you should now be able access your Jenkins. You can get the ingress url using the following:

kubectl get -o jsonpath="{.status.loadBalancer.ingress[0].hostname}" svc/jenkins

EC2 Plugin

I guess you’re wondering; “why after all that effort with Kubernetes are you creating AWS instances as slaves?” Well, our cluster has a finite pool of resource. We want elasticity with the Jenkins slaves, but equally, we don’t want a large pool sat idle waiting for work.

We are using the EC2 Plugin so that our builder nodes will be automatically launched as necessary when the Jenkins master requests them. Upon completion of their work they will automatically be turned down ,and we don’t get charged for anything that isn’t running. This does come with a time penalty for spinning up new VM’s, but we’re OK with that. We mitigate some of that cost by leaving them up for 10 mins after a build, so that any new builds can jump straight on the resource.

There’s a great article on how to configure this plugin, here.

Bitbucket OAuth

Our Active Directory is managed externally, so integrating Jenkins with AD was a little bit of a headache. Instead, we opted to integrate Jenkins with Bitbucket OAuth, which is useful because we know all of our engineers will have accounts. The documentation is very clear and accurate, so I would recommend following that guide.

My Test Rig

When the time of year came around for me to rebuild my test rig, I spent longer than ever gathering components to build something that would last more than 12 months (for my daily usage!).

I decided on an “open-rig” style of build and this had more than one benefit:

  • I was able to chop and change components as I wished, without having to open and close a case.
  • Cooling and airflow issues that I had with a standard box disappeared.
  • I can remove my SSD’s and take them with me.

The specs of the machine are as follows:

  • Intel i7 6 core Skylake processor overclocked to 4.9ghz (runs a little hot!)
  • Closed-circuit processor water-cooling
  • 256gb M2 SSD with main Windows 10 OS installed on it
  • 4TB ( 2x 2TB ) Samsung Evo Pro SSDs
  • 64GB Corsair Quad Channel DDR4 RAM
  • ENVA Nvidia Geforce 980TI (Overclocked)

This setup allows the machine to load test systems and it’s strong enough not to fall over itself. It also runs around 10 separate VMs that have different roles within its usage. I also have rainbow tables on my NAS drive at home, enabling the PC to crunch through them at a remarkable rate for my security testing.