Jekyll2019-04-22T20:46:17+00:00https://tomasbasham.dev/feed.xmlTomas Basham’s BlogTomas Basham's Personal Technology Jekyll Blog and Development PortfoliotomasbashamDiagnosing Pods with Kubernetes2018-01-22T00:00:00+00:002018-01-22T00:00:00+00:00https://tomasbasham.dev/development/2018/01/22/diagnosing-pods-with-kubernetes<p>Labels are the mechanism in Kubernetes through which system objects may be
given an organisation structure. A label is a key-value pair with well defined
<a href="https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#syntax-and-character-set">restrictions</a>
concerning length and value used as an identifier and mapped onto system
objects making them more meaningful within the system as a whole.</p>
<p>Whilst labels (and selectors) underpin how Pods are managed within a Deployment
they can be used in other ways more conducive to the diagnosis of the
containers that make up Pods.</p>
<p>When there is a problematic Pod running within a cluster it may not be
desirable to destroy it without first understanding what went wrong. Instead
the Pod should be removed from the load balancer and inspected whilst no longer
serving traffic.</p>
<p>This can be accomplished through the use of labels and selectors within a
Kubernetes manifest files describing a Deployment. In particular a label such
as <code class="highlighter-rouge">serving: true</code> may indicate to Kubernetes that a Pod should be placed
within the load balancer and should be serving traffic.</p>
<p><strong>Note</strong>: The <code class="highlighter-rouge">-L</code> option in the following command specifies the <code class="highlighter-rouge">serving</code>
label should be included in the table output by <code class="highlighter-rouge">kubectl</code>.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>kubectl <span class="nt">-n</span> myapp get pods <span class="nt">-L</span> serving
NAME READY STATUS RESTARTS AGE SERVING
api-441436789-7qzv0 2/2 Running 0 3d <span class="nb">true
</span>api-441436789-dwg2q 2/2 Running 0 3d <span class="nb">true
</span>client-760894609-ggw1b 1/1 Running 0 3d <span class="nb">true
</span>client-760894609-s8blr 1/1 Running 0 3d <span class="nb">true</span>
<span class="nv">$ </span>kubectl <span class="nt">-n</span> myapp describe service/api
Name: api
Namespace: myapp
Labels: <none>
Annotations: cloud.google.com/load-balancer-type<span class="o">=</span>internal
kubectl.kubernetes.io/last-applied-configuration<span class="o">={</span><span class="s2">"apiVersion"</span>:<span class="s2">"v1"</span>,<span class="s2">"kind"</span>:<span class="s2">"Service"</span>,<span class="s2">"metadata"</span>:<span class="o">{</span><span class="s2">"annotations"</span>:<span class="o">{</span><span class="s2">"cloud.google.com/load-balancer-type"</span>:<span class="s2">"internal"</span><span class="o">}</span>,<span class="s2">"name"</span>:<span class="s2">"api"</span>,<span class="s2">"namespace"</span>:<span class="s2">"myapp"</span><span class="o">}</span>,<span class="s2">"spec..."</span>
Selector: <span class="nv">app</span><span class="o">=</span>myapp,serving<span class="o">=</span><span class="nb">true</span>,tier<span class="o">=</span>api
Type: LoadBalancer
IP: 10.7.241.228
LoadBalancer Ingress: 10.132.0.6
Port: http2 80/TCP
TargetPort: %!d<span class="o">(</span><span class="nv">string</span><span class="o">=</span>esp-port<span class="o">)</span>/TCP
NodePort: http2 31364/TCP
Endpoints: 10.4.2.19:9000,10.4.2.21:9000
Session Affinity: None
External Traffic Policy: Cluster
Events: <none></code></pre></figure>
<p>For instance lets say the Pod named <code class="highlighter-rouge">api-441436789-7qzv0</code> is returning an
increased number of <code class="highlighter-rouge">404</code> responses which has been identified as abnormal
behaviour. This Pod is a prime candidate for inspection, but doing so whilst it
is still serving traffic (and thus many <code class="highlighter-rouge">404</code> errors) is undesirable. Replacing
the Pod with a fresh one may solve the problem temporarily, but finding the
root cause of the issue should be the goal. Therefore to remove this Pod from
the load balancer it’s labels must be edited in place.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>kubectl <span class="nt">-n</span> myapp label pods/api-441436789-7qzv0 <span class="nt">--overwrite</span> <span class="nv">serving</span><span class="o">=</span><span class="nb">false</span></code></pre></figure>
<p>The Replication Controller backing the Deployment will spin up a new Pod to
replace the one taken from the load balancer whilst the problematic Pod will
remain active for inspection but will not be available to serve traffic.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>kubectl <span class="nt">-n</span> myapp get pods <span class="nt">-L</span> serving
NAME READY STATUS RESTARTS AGE SERVING
api-441436789-7qzv0 2/2 Running 0 3d <span class="nb">false
</span>api-441436789-dwg2q 2/2 Running 0 3d <span class="nb">true
</span>api-441436789-lh8ht 2/2 Running 0 8s <span class="nb">true
</span>client-760894609-ggw1b 1/1 Running 0 3d <span class="nb">true
</span>client-760894609-s8blr 1/1 Running 0 3d <span class="nb">true</span>
<span class="nv">$ </span>kubectl <span class="nt">-n</span> myapp describe service/api
Name: api
Namespace: myapp
Labels: <none>
Annotations: cloud.google.com/load-balancer-type<span class="o">=</span>internal
kubectl.kubernetes.io/last-applied-configuration<span class="o">={</span><span class="s2">"apiVersion"</span>:<span class="s2">"v3"</span>,<span class="s2">"kind"</span>:<span class="s2">"Service"</span>,<span class="s2">"metadata"</span>:<span class="o">{</span><span class="s2">"annotations"</span>:<span class="o">{</span><span class="s2">"cloud.google.com/load-balancer-type"</span>:<span class="s2">"internal"</span><span class="o">}</span>,<span class="s2">"name"</span>:<span class="s2">"api"</span>,<span class="s2">"namespace"</span>:<span class="s2">"myapp"</span><span class="o">}</span>,<span class="s2">"spec..."</span>
Selector: <span class="nv">app</span><span class="o">=</span>myapp,serving<span class="o">=</span><span class="nb">true</span>,tier<span class="o">=</span>api
Type: LoadBalancer
IP: 10.7.241.228
LoadBalancer Ingress: 10.132.0.6
Port: http2 80/TCP
TargetPort: %!d<span class="o">(</span><span class="nv">string</span><span class="o">=</span>esp-port<span class="o">)</span>/TCP
NodePort: http2 31364/TCP
Endpoints: 10.4.2.21:9000,10.4.2.24:9000
Session Affinity: None
External Traffic Policy: Cluster
Events: <none></code></pre></figure>
<p><strong>Note</strong>: In the above snippet the endpoints that back the service have changed
to reflect the replacement of the problematic Pod.</p>
<p>Now an interactive terminal session can be made with a container running in the
Pod without affecting traffic.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash">kubectl <span class="nt">-n</span> myapp <span class="nb">exec</span> <span class="nt">-it</span> api-441436789-7qzv0 <span class="nt">-c</span> api /bin/bash
root@api-441436789-7qzv0:/usr/src/app#</code></pre></figure>
<p>When the problem has been diagnosed and possibly fixed the Pod can be returned
to the load balancer or more likely just destroyed.</p>Tomas BashamLabels are the mechanism in Kubernetes through which system objects may be given an organisation structure. A label is a key-value pair with well defined restrictions concerning length and value used as an identifier and mapped onto system objects making them more meaningful within the system as a whole.Protocol Buffers and Optional Fields2017-09-13T00:00:00+00:002017-09-13T00:00:00+00:00https://tomasbasham.dev/development/2017/09/13/protocol-buffers-and-optional-values<p>Protocol Buffers are a serialisation solution developed by Google providing a
platform and language neutral mechanism to send and receive structured data
across the wire. Protocol Buffers encode data into dense binary objects that
reduce packet sizes, enabling faster data exchange but with the disadvantage
that the binary objects are not easily human readable.</p>
<p>Protocol Buffers allow developers to define how they want their application
data to be structured and the Remote Procedural Calls (RPC) to be made
available for a particular service. An example of a Protocol Buffer
(specifically <code class="highlighter-rouge">proto3</code>) definition follows with a “Greeter” service that takes
a user’s name and returns a customised greeting.</p>
<figure class="highlight"><pre><code class="language-protobuf" data-lang="protobuf"><span class="na">syntax</span> <span class="o">=</span> <span class="s">"proto3"</span><span class="p">;</span>
<span class="kn">package</span> <span class="nn">greeter</span><span class="p">;</span>
<span class="kd">service</span> <span class="n">Greeter</span> <span class="p">{</span>
<span class="k">rpc</span> <span class="n">Greet</span><span class="p">(</span><span class="n">GreetRequest</span><span class="p">)</span> <span class="k">returns</span> <span class="p">(</span><span class="n">GreetResponse</span><span class="p">);</span>
<span class="p">}</span>
<span class="kd">message</span> <span class="nc">GreetRequest</span> <span class="p">{</span>
<span class="kt">string</span> <span class="na">name</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">message</span> <span class="nc">GreetResponse</span> <span class="p">{</span>
<span class="kt">string</span> <span class="kd">message</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>
<p>Very often we rely on inconsistent code at the boundaries of our applications
where rarely we enforce strict typing and structure of the data we exchange.
Being able to encapsulate the business semantics of an application within a
simple definition strengthens those boundaries providing a means to enforce
business logic. This functions well when all data is required to be present in
each message, however in less trivial applications business logic demands for
the ability to define values that may be nullable; something not possible with
<code class="highlighter-rouge">proto3</code> using primitive data types. In contrast previous versions of Protocol
Buffers, namely <code class="highlighter-rouge">proto2</code>, allowed for optional fields providing nullable
support for any field type.</p>
<p>To understand why, it may help to think about for what reasons <code class="highlighter-rouge">proto2</code> and
<code class="highlighter-rouge">proto3</code> both omit fields from the encoded data. In <code class="highlighter-rouge">proto3</code> fields always have
a value and as such are never left unset. Because of this <code class="highlighter-rouge">proto3</code> can achieve
a smaller payload by not transferring fields set to their default values. This
incurs a form of compression, saving a few bytes on message exchange.</p>
<p>The <code class="highlighter-rouge">proto2</code> specification, in addition to the above, keeps track of whether
the current value was explicitly set on a field. It is this feature of <code class="highlighter-rouge">proto2</code>
that allows for the optional field types. If the current value was not
explicitly set then the value is not transferred. This of course carries a
small penalty of needing extra storage space to transfer flags indicating
fields that have been explicitly set.</p>
<p>In light of this <code class="highlighter-rouge">proto3</code> has been designed to distinguish between the absence
of a primitive typed field and its default value through the use of the
<a href="https://github.com/google/protobuf/blob/master/src/google/protobuf/wrappers.proto">official value wrapper
types</a>
that form part of the <code class="highlighter-rouge">proto3</code> “standard library”.</p>
<figure class="highlight"><pre><code class="language-protobuf" data-lang="protobuf"><span class="na">syntax</span> <span class="o">=</span> <span class="s">"proto3"</span><span class="p">;</span>
<span class="kn">package</span> <span class="nn">greeter</span><span class="p">;</span>
<span class="k">import</span> <span class="s">"google/protobuf/wrappers.proto"</span><span class="p">;</span>
<span class="kd">service</span> <span class="n">Greeter</span> <span class="p">{</span>
<span class="k">rpc</span> <span class="n">Greet</span><span class="p">(</span><span class="n">GreetRequest</span><span class="p">)</span> <span class="k">returns</span> <span class="p">(</span><span class="n">GreetResponse</span><span class="p">);</span>
<span class="p">}</span>
<span class="kd">message</span> <span class="nc">GreetRequest</span> <span class="p">{</span>
<span class="n">google.protobuf.StringValue</span> <span class="na">name</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">message</span> <span class="nc">GreetResponse</span> <span class="p">{</span>
<span class="kt">string</span> <span class="kd">message</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>
<p>The main difference here is the addition of the <code class="highlighter-rouge">StringValue</code> submessage that
is a simple wrapper around a <code class="highlighter-rouge">string</code> field.</p>
<figure class="highlight"><pre><code class="language-protobuf" data-lang="protobuf"><span class="kd">message</span> <span class="nc">StringValue</span> <span class="p">{</span>
<span class="kt">string</span> <span class="na">value</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>
<p>In <code class="highlighter-rouge">proto3</code>, submessages can be set to <code class="highlighter-rouge">nil</code> allowing developers to use
wrappers for fields where the value may be optional. This adds a small amount
of overhead since wrapper values end up consuming an extra byte per field
because of the additional message layer. In addition the presence of the field
must be checked before it is used.</p>
<p>Despite this, one still cannot guarantee that the value in the wrapper was
explicitly set or defaulted to its zero value. However this moves the problem
of supporting optional values further away from the <code class="highlighter-rouge">proto3</code> specification and
more toward developer conventions. Typically if a submessage is <code class="highlighter-rouge">nil</code> then an
application consuming the message can assume the field was deliberately (or
perhaps accidentally) omitted. If however the submessage has a non-nil value
then it must be assumed that whatever value is held by the wrapper was intended
to be consumed.</p>Tomas BashamProtocol Buffers are a serialisation solution developed by Google providing a platform and language neutral mechanism to send and receive structured data across the wire. Protocol Buffers encode data into dense binary objects that reduce packet sizes, enabling faster data exchange but with the disadvantage that the binary objects are not easily human readable.Kubernetes Networking2017-06-30T00:00:00+00:002017-06-30T00:00:00+00:00https://tomasbasham.dev/development/2017/06/30/kubernetes-networking<p>In the software development scene today, containerisation - and Docker in
particular - is hard to ignore. However when an application needs to scale
horizontally it falls upon container orchestration systems to handle the
complex interconnections between distributed nodes and the containers that they
manage.</p>
<p>It is without doubt that Kubernetes has prevailed as the dominant container
orchestration system, but the networking model that it implements is often
difficult to understand. Before discussing how Kubernetes approaches networking
it is worth understanding how the Docker networking model is implemented to
acknowledge some of the issues.</p>
<h3 id="the-docker-model">The Docker Model</h3>
<p>The Docker networking model is somewhat flexible, offering support for multiple
solutions through the use of network drivers. However in the default case
Docker imposes a bridge networking model using a host-private networking
scheme. Docker creates a virtual bridge, called <code class="highlighter-rouge">docker0</code>, in the root network
namespace and allocates a subnet from one of the private address blocks defined
in <a href="https://tools.ietf.org/html/rfc1918">RFC1918</a> (typically <code class="highlighter-rouge">172.16.0.0/12</code>)
to that bridge. For each container managed by Docker a virtual network
namespace is created to isolate the container from the host networking device.
Each namespace is attached to the bridge through a virtual Ethernet device
(<code class="highlighter-rouge">veth</code>) and mapped to appear as <code class="highlighter-rouge">eth0</code> from within the container. The virtual
Ethernet device is then allocated an IP address from the address range assigned
to the bridge.</p>
<p>The result of this setup is that each container Docker manages can communicate
with all other containers providing they are connected to the same virtual
bridge. By extension since the bridge is configured behind the node’s own Ethernet
device the containers must also be on the same machine. In addition because
Docker is configured to use the same IP address range on every node it follows
that containers across nodes may be assigned the same IP address. This makes
containers unable to communicate with each other across nodes out-of-the-box.</p>
<p>One way for containers across nodes to communicate it to carefully coordinate
the allocation of ports on the node’s own IP address and then forward packets
to the respective container. This can be rather errors prone and often lead to
high contention.</p>
<p>Below is a diagram depicting how Docker manages virtual network namespaces for
each container. From this it can be seen how packets would have to traverse
through the virtual bridge to provide connectivity between containers on the
same node.</p>
<p><img src="https://cdn.tomasbasham.dev/posts/kubernetes-networking/docker.png" alt="Docker Model" /></p>
<h3 id="the-kubernetes-ip-per-pod-model">The Kubernetes (IP per Pod) Model</h3>
<p>The Kubernetes networking model does not differ much from the Docker model seen
above. However Kubernetes demands a flattening of the IP address space,
dictating that all containers (and their respective nodes) should be able to
communicate with each other without the use of Network Address Translation
(NAT). How this is achieved is of no concern to Kubernetes and may likely be
implemented differently across infrastructure providers. For instance simple L2
ARP lookups across a switching fabric could achieve this, or alternatively L3
IP routing, or an overlay. Providing this demand is respected Kubernetes should
be able to run across a network.</p>
<p>Unlike the Docker model, Kubernetes assigns IP addresses at the Pod level,
where by default a Pod is allocated a private IP address within the network
namespace address range.</p>
<p>Pods themselves provide an isolated, shared network namespace for their content
(containers) meaning containers within a Pod can communicate by making a
request to <code class="highlighter-rouge">localhost</code>. This consequently means that each container within a
Pod must coordinate port usage. However it is typically considered best
practice to isolate a single container within a single Pod so this issue tends
to be moot. On the occasion there exists one or more containers with a hard
dependency on each other they can be placed within a single Pod but should not
likely need to contest for unallocated ports.</p>
<p>To demonstrate this I have created a single Pod running 2 containers. The
<code class="highlighter-rouge">kubectl</code> command prints out the Pods details.</p>
<p><strong>Note</strong> The <code class="highlighter-rouge">-l</code> options in the following command specifies that only Pods
with a <code class="highlighter-rouge">tier</code> label set to <code class="highlighter-rouge">api</code> should be selected for the output.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>kubectl <span class="nt">-n</span> myapp get pods <span class="nt">-l</span> <span class="nv">tier</span><span class="o">=</span>api
NAME READY STATUS RESTARTS AGE
api-4146221093-7pv1p 2/2 Running 0 1d
<span class="nv">$ </span>kubectl <span class="nt">-n</span> myapp describe pod/api-4146221093-7pv1p
Name: api-1
Namespace: myapp
Node: gke-development-cluster-default-pool-9bf27fcd-vqvz/10.132.0.2
Start Time: Thu, 28 Jun 2017 08:59:10 +0100
Labels: <span class="nv">app</span><span class="o">=</span>myapp
pod-template-hash<span class="o">=</span>4146221093
<span class="nv">serving</span><span class="o">=</span><span class="nb">true
</span><span class="nv">tier</span><span class="o">=</span>api
Annotations: kubernetes.io/created-by<span class="o">={</span><span class="s2">"kind"</span>:<span class="s2">"SerializedReference"</span>,<span class="s2">"apiVersion"</span>:<span class="s2">"v1"</span>,<span class="s2">"reference"</span>:<span class="o">{</span><span class="s2">"kind"</span>:<span class="s2">"ReplicaSet"</span>,<span class="s2">"namespace"</span>:<span class="s2">"myapp"</span>,<span class="s2">"name"</span>:<span class="s2">"api-4146221093"</span>,<span class="s2">"uid"</span>:<span class="s2">"f305e98b-f19f-11e7-a706-42010a840036"</span>,<span class="s2">"apiV..."</span>
Status: Running
IP: 10.4.2.19
Created By: ReplicaSet/api-4146221093
Controlled By: ReplicaSet/api-4146221093
Containers:
...</code></pre></figure>
<p>The above Pod can be accessed by making a request to its IP address
(<code class="highlighter-rouge">10.4.2.19</code>). Since the cluster is running on Google Kubernetes Engine (and by
extension Google Compute Engine) where by default a Pod is given an internal IP
address it can only be accessed from a machine within the same Google Cloud
Platform project.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span><span class="nb">echo</span> <span class="nt">-e</span> <span class="s2">"GET / HTTP/1.1</span><span class="se">\n</span><span class="s2">"</span> | nc 10.4.2.19 9292
HTTP/1.1 200 OK
Content-Type: text/html<span class="p">;</span><span class="nv">charset</span><span class="o">=</span>utf-8
Content-Length: 0
X-Xss-Protection: 1<span class="p">;</span> <span class="nv">mode</span><span class="o">=</span>block
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Date: Mon, 28 Jun 2017 18:23:32 GMT
Connection: Keep-Alive</code></pre></figure>
<p>However having applications make requests to this IP address would be futile in
the long run. Since Pods are by nature ephemeral the IP address assigned to
this Pod may not be the same IP address assigned to a Pod in the future.
Instead there needs to be a layer in front of the Pods to maintain a stable
endpoint.</p>
<h3 id="the-service-abstraction">The Service Abstraction</h3>
<p>Services are an abstraction of stability for Pods providing a persistent
endpoint representing a set of containers behind it. This is achieved with a
Virtual Internet Protocol (VIP) address and enables Kubernetes to deal with
changes to the cluster topology dynamically without effecting user perceived
uptime. Clients now only need know the VIP in order to talk to the Pods behind
the Service. This allows for rolling updates where Pods may be completely
replaced, likely allocated different IP addresses, without the client realising
what actions Kubernetes has taken.</p>
<p>The default implementation of the Service abstraction is the <code class="highlighter-rouge">kube-proxy</code> that
runs on each node in a cluster. Its main responsibility is to query the
Kubernetes API server and configure <code class="highlighter-rouge">iptables</code> to forward packets to the
correct destination Pods (backends). It is able to configure <code class="highlighter-rouge">iptables</code> to
perform simple TCP and UDP stream forwarding or round robin TCP and UDP
forwarding across a set of backends. Despite its name <code class="highlighter-rouge">kube-proxy</code> is <strong>not</strong> a
proxy - once upon a time it was a proxy, now it is a controller. In fact it
does not touch the packets traversing the Kubernetes managed network.</p>
<p><img src="https://cdn.tomasbasham.dev/posts/kubernetes-networking/kubernetes.png" alt="Kubernetes Model" /></p>
<p>To demonstrate this I have created a Service that creates a persistent endpoint
for a single Pod. The <code class="highlighter-rouge">kubectl</code> command prints out the Services details.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>kubectl <span class="nt">-n</span> myapp get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT<span class="o">(</span>S<span class="o">)</span> AGE
api ClusterIP 10.7.241.228 <none> 80/TCP 1d
<span class="nv">$ </span>kubectl <span class="nt">-n</span> myapp describe service/api
Name: api
Namespace: myapp
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration<span class="o">={</span><span class="s2">"apiVersion"</span>:<span class="s2">"v1"</span>,<span class="s2">"kind"</span>:<span class="s2">"Service"</span>,<span class="s2">"metadata"</span>:<span class="o">{</span><span class="s2">"annotations"</span>:<span class="o">{}</span>,<span class="s2">"name"</span>:<span class="s2">"api"</span>,<span class="s2">"namespace"</span>:<span class="s2">"myapp"</span><span class="o">}</span>,<span class="s2">"spec"</span>:<span class="o">{</span><span class="s2">"ports"</span>:[<span class="o">{</span><span class="s2">"name"</span>:<span class="s2">"http2"</span>,<span class="s2">"port"</span>:80,<span class="s2">"protocol..."</span>
Selector: <span class="nv">app</span><span class="o">=</span>myapp,serving<span class="o">=</span><span class="nb">true</span>,tier<span class="o">=</span>api
Type: ClusterIP
IP: 10.7.241.228
Port: http2 80/TCP
TargetPort: %!d<span class="o">(</span><span class="nv">string</span><span class="o">=</span>esp-port<span class="o">)</span>/TCP
Endpoints: 10.4.2.19:9000
Session Affinity: None
Events: <none></code></pre></figure>
<p>Now the same Pod can be reached by making a request to the VIP (<code class="highlighter-rouge">10.7.241.228</code>)
assigned to the Service.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span><span class="nb">echo</span> <span class="nt">-e</span> <span class="s2">"GET / HTTP/1.1</span><span class="se">\n</span><span class="s2">"</span> | nc 10.7.241.228 80
HTTP/1.1 200 OK
Content-Type: text/html<span class="p">;</span><span class="nv">charset</span><span class="o">=</span>utf-8
Content-Length: 0
X-Xss-Protection: 1<span class="p">;</span> <span class="nv">mode</span><span class="o">=</span>block
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Date: Mon, 28 Jun 2017 18:23:32 GMT
Connection: Keep-Alive</code></pre></figure>
<p>By logging onto the node managing the Pod (although any of the nodes would
produce the same output) we are able to see the list of <code class="highlighter-rouge">iptables</code> rules that
have been created by <code class="highlighter-rouge">kube-proxy</code>.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span><span class="nb">sudo </span>iptables-save | <span class="nb">grep </span>api
<span class="nt">-A</span> KUBE-SEP-JREY6CMQUZ2KMT2G <span class="nt">-s</span> 10.4.2.19/32 <span class="nt">-m</span> comment <span class="nt">--comment</span> <span class="s2">"myapp/api:http2"</span> <span class="nt">-j</span> KUBE-MARK-MASQ
<span class="nt">-A</span> KUBE-SEP-JREY6CMQUZ2KMT2G <span class="nt">-p</span> tcp <span class="nt">-m</span> comment <span class="nt">--comment</span> <span class="s2">"myapp/api:http2"</span> <span class="nt">-m</span> tcp <span class="nt">-j</span> DNAT <span class="nt">--to-destination</span> 10.4.2.19:9000
<span class="nt">-A</span> KUBE-SERVICES <span class="o">!</span> <span class="nt">-s</span> 10.4.0.0/14 <span class="nt">-d</span> 10.7.241.228/32 <span class="nt">-p</span> tcp <span class="nt">-m</span> comment <span class="nt">--comment</span> <span class="s2">"myapp/api:http2 cluster IP"</span> <span class="nt">-m</span> tcp <span class="nt">--dport</span> 80 <span class="nt">-j</span> KUBE-MARK-MASQ
<span class="nt">-A</span> KUBE-SERVICES <span class="nt">-d</span> 10.7.241.228/32 <span class="nt">-p</span> tcp <span class="nt">-m</span> comment <span class="nt">--comment</span> <span class="s2">"myapp/api:http2 cluster IP"</span> <span class="nt">-m</span> tcp <span class="nt">--dport</span> 80 <span class="nt">-j</span> KUBE-SVC-CMKF3ZHDEOE3K64F
<span class="nt">-A</span> KUBE-SVC-CMKF3ZHDEOE3K64F <span class="nt">-m</span> comment <span class="nt">--comment</span> <span class="s2">"myapp/api:http2"</span> <span class="nt">-j</span> KUBE-SEP-JREY6CMQUZ2KMT2G</code></pre></figure>
<p>When a Pod wants to request this Service any packets are forwarded from the
network bridge, through <code class="highlighter-rouge">iptables</code> and onto the destination Pod. Specifically
<code class="highlighter-rouge">kube-proxy</code> has created rules that perform a Destination Network Address
Translation (DNAT) on all packets destined for <code class="highlighter-rouge">10.7.241.228/32</code> over TCP on
port 80 and rewrites the destination address to the Pod running the container.
In this case <code class="highlighter-rouge">iptables</code> rewrites the destination address to <code class="highlighter-rouge">10.4.2.19</code> on port
9000.</p>
<p>It is important to note that <code class="highlighter-rouge">iptables</code>, in addition to performing a DNAT, also
creates a record in the connection tracking table. This allows <code class="highlighter-rouge">iptables</code> to
track address translations based on a 5-tuple schema later used to reverse the
translation when a response is received.</p>
<h3 id="scaling-up">Scaling Up</h3>
<p>So far we have only seen what happens with a single Pod. However most
distributed applications require redundancy, adding further complexity. To
demonstrate this I have increased the number of replicas for the Pod from above
to 2. The <code class="highlighter-rouge">kubectl</code> command prints out the Services details.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>kubectl <span class="nt">-n</span> myapp describe service/api
Name: api
Namespace: myapp
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration<span class="o">={</span><span class="s2">"apiVersion"</span>:<span class="s2">"v1"</span>,<span class="s2">"kind"</span>:<span class="s2">"Service"</span>,<span class="s2">"metadata"</span>:<span class="o">{</span><span class="s2">"annotations"</span>:<span class="o">{}</span>,<span class="s2">"name"</span>:<span class="s2">"api"</span>,<span class="s2">"namespace"</span>:<span class="s2">"myapp"</span><span class="o">}</span>,<span class="s2">"spec"</span>:<span class="o">{</span><span class="s2">"ports"</span>:[<span class="o">{</span><span class="s2">"name"</span>:<span class="s2">"http2"</span>,<span class="s2">"port"</span>:80,<span class="s2">"protocol..."</span>
Selector: <span class="nv">app</span><span class="o">=</span>myapp,serving<span class="o">=</span><span class="nb">true</span>,tier<span class="o">=</span>api
Type: ClusterIP
IP: 10.7.241.228
Port: http2 80/TCP
TargetPort: %!d<span class="o">(</span><span class="nv">string</span><span class="o">=</span>esp-port<span class="o">)</span>/TCP
Endpoints: 10.4.1.14:9000,10.4.2.19:9000
Session Affinity: None
Events: <none></code></pre></figure>
<p>Once the new Pod has been created the Service has 2 backends where each Pod
may very well be on different nodes. However because of the rules Kubernetes
demands these Pods can both talk to one another. When this new Pod was created
<code class="highlighter-rouge">kube-proxy</code> created new rules in the <code class="highlighter-rouge">iptables</code> across all the nodes in the
cluster. These rules forward packets to the new Pod when the Service is
requested.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span><span class="nb">sudo </span>iptables-save | <span class="nb">grep </span>api
<span class="nt">-A</span> KUBE-SEP-A2E6GM52XHOS2X76 <span class="nt">-s</span> 10.4.1.14/32 <span class="nt">-m</span> comment <span class="nt">--comment</span> <span class="s2">"myapp/api:http2"</span> <span class="nt">-j</span> KUBE-MARK-MASQ
<span class="nt">-A</span> KUBE-SEP-A2E6GM52XHOS2X76 <span class="nt">-p</span> tcp <span class="nt">-m</span> comment <span class="nt">--comment</span> <span class="s2">"myapp/api:http2"</span> <span class="nt">-m</span> tcp <span class="nt">-j</span> DNAT <span class="nt">--to-destination</span> 10.4.1.14:9000
<span class="nt">-A</span> KUBE-SEP-JREY6CMQUZ2KMT2G <span class="nt">-s</span> 10.4.2.19/32 <span class="nt">-m</span> comment <span class="nt">--comment</span> <span class="s2">"myapp/api:http2"</span> <span class="nt">-j</span> KUBE-MARK-MASQ
<span class="nt">-A</span> KUBE-SEP-JREY6CMQUZ2KMT2G <span class="nt">-p</span> tcp <span class="nt">-m</span> comment <span class="nt">--comment</span> <span class="s2">"myapp/api:http2"</span> <span class="nt">-m</span> tcp <span class="nt">-j</span> DNAT <span class="nt">--to-destination</span> 10.4.2.19:9000
<span class="nt">-A</span> KUBE-SERVICES <span class="o">!</span> <span class="nt">-s</span> 10.4.0.0/14 <span class="nt">-d</span> 10.7.241.228/32 <span class="nt">-p</span> tcp <span class="nt">-m</span> comment <span class="nt">--comment</span> <span class="s2">"myapp/api:http2 cluster IP"</span> <span class="nt">-m</span> tcp <span class="nt">--dport</span> 80 <span class="nt">-j</span> KUBE-MARK-MASQ
<span class="nt">-A</span> KUBE-SERVICES <span class="nt">-d</span> 10.7.241.228/32 <span class="nt">-p</span> tcp <span class="nt">-m</span> comment <span class="nt">--comment</span> <span class="s2">"myapp/api:http2 cluster IP"</span> <span class="nt">-m</span> tcp <span class="nt">--dport</span> 80 <span class="nt">-j</span> KUBE-SVC-CMKF3ZHDEOE3K64F
<span class="nt">-A</span> KUBE-SVC-CMKF3ZHDEOE3K64F <span class="nt">-m</span> comment <span class="nt">--comment</span> <span class="s2">"myapp/api:http2"</span> <span class="nt">-m</span> statistic <span class="nt">--mode</span> random <span class="nt">--probability</span> 0.50000000000 <span class="nt">-j</span> KUBE-SEP-A2E6GM52XHOS2X76
<span class="nt">-A</span> KUBE-SVC-CMKF3ZHDEOE3K64F <span class="nt">-m</span> comment <span class="nt">--comment</span> <span class="s2">"myapp/api:http2"</span> <span class="nt">-j</span> KUBE-SEP-JREY6CMQUZ2KMT2G</code></pre></figure>
<p>Now Kubernetes must make a choice as to which backend to forward packets.
<code class="highlighter-rouge">iptables</code> will pick one of the backends at random, based on some statistic
condition. In this case each Pod has a 50% chance of being selected. From here
the process is as before; <code class="highlighter-rouge">iptables</code> will perform a DNAT, add a record to the
connection tracking table, and forward packets to the destination Pod.</p>
<p>The root network namespace now acts as a distributed load balancer. This is
true because the same set of rules are configured on each of the nodes in a
cluster, so a Service can be “discovered” in the same way from every Pod,
regardless of the node that it runs on.</p>
<h3 id="external-resources">External Resources</h3>
<ul>
<li><a href="https://kubernetes.io/">Kubernetes</a></li>
<li><a href="https://en.wikipedia.org/wiki/Linux_namespaces">Linux Namespace</a></li>
<li><a href="https://en.wikipedia.org/wiki/Network_address_translation">Network Address
Translation</a></li>
<li><a href="https://en.wikipedia.org/wiki/Address_Resolution_Protocol">Address Resolution
Protocol</a></li>
<li><a href="https://en.wikipedia.org/wiki/Iptables">iptables</a></li>
</ul>Tomas BashamIn the software development scene today, containerisation - and Docker in particular - is hard to ignore. However when an application needs to scale horizontally it falls upon container orchestration systems to handle the complex interconnections between distributed nodes and the containers that they manage.The New Full Stack Developer2017-04-18T00:00:00+00:002017-04-18T00:00:00+00:00https://tomasbasham.dev/development/2017/04/18/the-new-full-stack-developer<p>I have recently been on the look out for new employment opportunities, where I
have noticed most applications (as opposed to job descriptions a few years ago)
require you to be what they regard as a “full-stack” developer. It is assumed
that “full-stack” carries a well known definition, accepted by all employers,
where one can easily identify whether they fulfil this criteria. However
looking closer at current trends in the development and operations space (not
DevOps) it follows that perhaps the definition should be expanded.</p>
<p>I’m sometimes baffled by friends and colleges that claim to be “full-stack”
developers having as little as a few months real programming experience, or
where the foundation of their ability is sourced from online programming
courses. It begs the question as to whether they believe software development
is 100% programming and that knowing Ruby on Rails and React makes them a
“full-stack” developer.</p>
<p>Looking more broadly at the software development scene, containerisation – and
Docker in particular – is hard to ignore these days. Coupled with container
scheduling solutions such as Kubernetes there is a huge push to hire for
positions where the successful applicant can demonstrate skills in these
technologies in additional to more traditional software development skills.</p>
<p>I propose a change to the definition of a “full-stack” developer to include the
ability to handle operations too. This could mean Puppet, Chef, Capistrano,
Kubernetes, networking or all of the above but some experience with servers and
deployment should, in my honest opinion, be essential to the definition of
“full stack”. Especially now where the line between developer and operations
has become a little blurred (infrastructure as code) and where it should be the
responsibility of the developer to deploy and maintain their code from
conception to production.</p>
<p>I would be interested to read what others think of this and whether my opinion
is well grounded.</p>Tomas BashamI have recently been on the look out for new employment opportunities, where I have noticed most applications (as opposed to job descriptions a few years ago) require you to be what they regard as a “full-stack” developer. It is assumed that “full-stack” carries a well known definition, accepted by all employers, where one can easily identify whether they fulfil this criteria. However looking closer at current trends in the development and operations space (not DevOps) it follows that perhaps the definition should be expanded.5 Things I Hate About Ruby2017-03-06T00:00:00+00:002017-03-06T00:00:00+00:00https://tomasbasham.dev/development/2017/03/06/5-things-i-hate-about-ruby<p>I find myself more and more lately banging on about how much better Ruby is
when compared to the other languages used by my colleagues (i.e. PHP). I know,
I know I am truly a Ruby fanboy. I much favour being able to write my
applications in a more “plain English” syntax which offers self documenting and
cleaner code.</p>
<p>However I don’t really believe you can trust an advocate who doesn’t know
enough to find something wrong with what they are advocating. Given that I use,
love and shout Ruby’s praises on almost a daily basis, listing out some of it’s
bug bares seems like a good exercise in humility.</p>
<h3 id="5-private-is-not-private">5. Private is not private</h3>
<p>In Ruby there is no such thing as private or protected scope, at least
semantically speaking. The <code class="highlighter-rouge">private</code> and <code class="highlighter-rouge">protected</code> keywords only act as hints
to the interpreter not to allow access to methods outside their intended scope.
This leads to a language feature that is not entirely transparent, but equally
as trivial.</p>
<p>It would appear that the language instead guides developers down the “right”
path by making private method invocations more annoying, throwing exceptions,
but does not stop you from doing so. I believe having this relaxed attitude to
method visibility opens the doors to poor code design. Personally I would
prefer to be forced to code in a certain way than have a mechanism to guide my
coding best practices.</p>
<p>To invoke a private method on an object you may simply use the <code class="highlighter-rouge">Object.send</code>
method.</p>
<h3 id="4-confusing-operators">4. Confusing operators?</h3>
<p>Ruby has two different, but confusing, set of operators. Those being the widely
used <code class="highlighter-rouge">&&</code> and <code class="highlighter-rouge">||</code> which are present in almost every modern computer language,
and the more English style <code class="highlighter-rouge">and</code> and <code class="highlighter-rouge">or</code>. To be honest
<a href="http://www.virtuouscode.com/2014/08/26/how-to-use-rubys-english-andor-operators-without-going-nuts/">this</a>
video by Avdi Grimm does a far better job of explaining the differences than I
can, but it suffices to say that this syntax is copied from Perl whereby the
English style operators have a lesser precedence over the more traditional
style operators.</p>
<p>To be fair both set of operators have different use cases so it is hard to hate
on this feature of Ruby, however it is a very confusing syntax so anybody would
be excused if thinking that they in fact were synonymous.</p>
<h3 id="3-optional-perentheses">3. Optional perentheses</h3>
<p>Ruby does not require that you place parentheses around method arguments.
Although this saves on keystrokes it can be detrimental to readability and in
some cases cause your application to not behave as expected. Take the
following:</p>
<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="n">x</span> <span class="o">=</span> <span class="mi">5</span>
<span class="nb">puts</span> <span class="p">(</span><span class="mi">0</span><span class="o">..</span><span class="mi">10</span><span class="p">).</span><span class="nf">include?</span> <span class="n">x</span> <span class="p">?</span> <span class="s1">'yes'</span> <span class="p">:</span> <span class="s1">'no'</span>
<span class="c1"># is equivalent to</span>
<span class="nb">puts</span> <span class="p">(</span><span class="mi">0</span><span class="o">..</span><span class="mi">10</span><span class="p">).</span><span class="nf">include?</span><span class="p">(</span><span class="n">x</span> <span class="p">?</span> <span class="s1">'yes'</span> <span class="p">:</span> <span class="s1">'no'</span><span class="p">)</span>
<span class="c1"># is equivalent to</span>
<span class="nb">puts</span> <span class="p">(</span><span class="mi">0</span><span class="o">..</span><span class="mi">10</span><span class="p">).</span><span class="nf">include?</span><span class="p">(</span><span class="s1">'yes'</span><span class="p">)</span>
<span class="c1"># is equivalent to</span>
<span class="nb">puts</span> <span class="kp">false</span> <span class="c1">#=> false</span></code></pre></figure>
<p>Clearly this was not the intended result. The Ruby interpreter has taken <code class="highlighter-rouge">x ?
'yes' : 'no'</code> as a single argument to the <code class="highlighter-rouge">include?</code> method whereas the
intention was only to take <code class="highlighter-rouge">x</code>. The correct way to have written this was with
parentheses:</p>
<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="n">x</span> <span class="o">=</span> <span class="mi">5</span>
<span class="nb">puts</span> <span class="p">(</span><span class="mi">0</span><span class="o">..</span><span class="mi">10</span><span class="p">).</span><span class="nf">include?</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="p">?</span> <span class="s1">'yes'</span><span class="p">,</span> <span class="s1">'no'</span>
<span class="c1"># is equivalent to</span>
<span class="nb">puts</span> <span class="kp">true</span> <span class="c1">#=> true</span></code></pre></figure>
<p>The generally accepted rule is to omit parentheses around parameters for
methods that are part of an internal DSL (e.g. Rake, Rails, RSpec); methods
that are with ‘keyword’ status in Ruby (e.g. <code class="highlighter-rouge">attr_reader</code>, <code class="highlighter-rouge">puts</code>) and those
which take no arguments. Use parentheses for all other method invocations.</p>
<h3 id="2-conventions">2. Conventions</h3>
<p>There are certain conventions to the Ruby language, but this point concerns
itself around method naming. For example any method ending with a bang (<code class="highlighter-rouge">!</code>)
indicates that the method will modify the object it’s called on. Similarly any
method ending with a question mark indicates that the method will return a
boolean - <code class="highlighter-rouge">true</code> or <code class="highlighter-rouge">false</code>. Although this is widely accurate, there are some
instances where this does not hold true. Take for example the
<a href="https://ruby-doc.org/core-2.2.0/Float.html#method-i-infinite-3F"><code class="highlighter-rouge">Float.infinite?</code></a>
method. Instead of returning <code class="highlighter-rouge">true</code> or <code class="highlighter-rouge">false</code> it instead returns a trinary
result of either <code class="highlighter-rouge">nil</code>, <code class="highlighter-rouge">1</code> or <code class="highlighter-rouge">-1</code>.</p>
<p>What is the point of having conventions when they can be ignored at any given
time. This now requires developers to remember a series of methods that do not
follow conventions, which defeats the point of having the convention in the
first place.</p>
<h3 id="1-defining-private-class-methods">1. Defining private class methods</h3>
<p>This touches on the first point in this post where private methods are not
actually private. However this point has driven me crazy in the past so was
worth writing about. There are 2 main ways to define class methods. The first
is using <code class="highlighter-rouge">self.method_name</code> and the second is as a singleton using <code class="highlighter-rouge">class <<
self</code>. Both achieve the same result, defining a method on, what is known in the
Ruby community, as the “Eigenclass”. This is effectively an anonymous class
that Ruby creates and inserts into the inheritance hierarchy to hold the class
methods.</p>
<p>The problem here is when defining private class methods. You would expect to
write something along the lines of this:</p>
<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">class</span> <span class="nc">SomeClassWithPrivateMethods</span>
<span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">method_one</span>
<span class="nb">puts</span> <span class="s1">'method one is public'</span>
<span class="k">end</span>
<span class="kp">private</span>
<span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">method_two</span>
<span class="nb">puts</span> <span class="s1">'method two is public'</span>
<span class="k">end</span>
<span class="k">end</span></code></pre></figure>
<p>This however does not make <code class="highlighter-rouge">method_two</code> private. The <code class="highlighter-rouge">private</code> keyword only
affects methods on the class instance, so when we define a class method under
the <code class="highlighter-rouge">private</code> keyword it does nothing.</p>
<p>Using the singleton approach (<code class="highlighter-rouge">class << self</code>) we are defining instance methods
on the “Eigenclass”, which are just class methods of the containing class.
Confusing, right?</p>
<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">class</span> <span class="nc">SomeClassWithPrivateMethods</span>
<span class="k">class</span> <span class="o"><<</span> <span class="nb">self</span>
<span class="k">def</span> <span class="nf">method_one</span>
<span class="nb">puts</span> <span class="s1">'method one is public'</span>
<span class="k">end</span>
<span class="kp">private</span>
<span class="k">def</span> <span class="nf">method_two</span>
<span class="nb">puts</span> <span class="s1">'method two is private'</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span></code></pre></figure>
<p>This now works as expected, but adds that extra level of complexity to the Ruby
language that does not really offer any benefits as a developer. I would much
prefer using <code class="highlighter-rouge">self.method_name</code> if only it was affected by the <code class="highlighter-rouge">private</code>
keyword.</p>Tomas BashamI find myself more and more lately banging on about how much better Ruby is when compared to the other languages used by my colleagues (i.e. PHP). I know, I know I am truly a Ruby fanboy. I much favour being able to write my applications in a more “plain English” syntax which offers self documenting and cleaner code.Git Renegade - Delete Remote Tags2017-01-10T00:00:00+00:002017-01-10T00:00:00+00:00https://tomasbasham.dev/development/2017/01/10/git-renegade-delete-remote-tags<p>This is not something considered best practice but if the need arises that a
tag must be removed from a remote repository server then here is how to delete
it.</p>
<p>If you have a remote tag named <code class="highlighter-rouge">branch-name</code> it can be deleted with:</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>git tag <span class="nt">-d</span> branch-name
<span class="nv">$ </span>git push origin :refs/tags/branch-name</code></pre></figure>
<p>This will delete the tag both locally and remotely.</p>Tomas BashamThis is not something considered best practice but if the need arises that a tag must be removed from a remote repository server then here is how to delete it.Swift 3 - Pattern Matching2016-12-04T00:00:00+00:002016-12-04T00:00:00+00:00https://tomasbasham.dev/development/2016/12/04/swift-3-pattern-matching<p>Whilst working on an iOS app, I was able to really jump into some Swift 3
features that were very new to me. Swift 3 has so many advantages over
Objective-C but the one I am most impressed with is pattern matching.</p>
<p>Having dabbled a bit with Erlang and other functional programming languages in
the past I can immediately see the benefits of this functional paradigm within
Swift. It is rather advantageous because Swift now allows us to solve problems
perhaps beter suited to functional programming languages (at least where
pattern matching is concerned), and we may take examples from these other
language to adapt them to work with Swift. So without further ado, lets talk
about pattern matching.</p>
<h3 id="the-model">The Model</h3>
<p>Say you are modelling your favourite burger. Here’s
<a href="http://glutenfreeregina.com/wp-content/uploads/2016/08/Five-Guys.jpg">mine</a>.
Each topping could be represented as a separate case within an <code class="highlighter-rouge">enum</code>.</p>
<figure class="highlight"><pre><code class="language-swift" data-lang="swift"> <span class="kd">enum</span> <span class="kt">BurgerTopping</span> <span class="p">{</span>
<span class="k">case</span> <span class="kt">Bun</span><span class="p">(</span><span class="nv">type</span><span class="p">:</span> <span class="kt">String</span><span class="p">,</span> <span class="nv">seeds</span><span class="p">:</span> <span class="kt">Bool</span><span class="p">)</span>
<span class="k">case</span> <span class="kt">Patty</span><span class="p">(</span><span class="nv">type</span><span class="p">:</span> <span class="kt">String</span><span class="p">)</span>
<span class="k">case</span> <span class="kt">Cheese</span><span class="p">(</span><span class="nv">type</span><span class="p">:</span> <span class="kt">String</span><span class="p">)</span>
<span class="k">case</span> <span class="kt">Pickle</span>
<span class="k">case</span> <span class="kt">Tomato</span>
<span class="p">}</span></code></pre></figure>
<p>You get the idea. Add whatever toppings take your fancy.</p>
<h3 id="the-humble-switch">The Humble Switch</h3>
<p>In essence we have been using very basic pattern matching for a long time in
languages such as Objective-C, C, Java, and many others through the form of
switch statements. Here we tend to match strings with other strings or integers
with other integers. But now we can take the humble switch statement and put it
on steroids.</p>
<p>Using pattern matching switch statements can be used to match more complex
structures containing placeholder variables, and bind these variables to real
values if they match:</p>
<figure class="highlight"><pre><code class="language-swift" data-lang="swift"> <span class="kd">func</span> <span class="nf">add</span><span class="p">(</span><span class="n">_</span> <span class="nv">topping</span><span class="p">:</span> <span class="kt">BurgerTopping</span><span class="p">)</span> <span class="p">{</span>
<span class="k">switch</span> <span class="n">topping</span> <span class="p">{</span>
<span class="k">case</span> <span class="kd">let</span> <span class="o">.</span><span class="kt">Bun</span><span class="p">(</span><span class="n">type</span><span class="p">,</span> <span class="n">_</span><span class="p">):</span>
<span class="nf">print</span><span class="p">(</span><span class="s">"</span><span class="se">\(</span><span class="n">type</span><span class="se">)</span><span class="s"> bun with or without seeds. The mystery is killing me"</span><span class="p">)</span>
<span class="k">case</span> <span class="kd">let</span> <span class="o">.</span><span class="kt">Patty</span><span class="p">(</span><span class="n">type</span><span class="p">):</span>
<span class="nf">print</span><span class="p">(</span><span class="s">"Juicy. Delicious. Succulant </span><span class="se">\(</span><span class="n">type</span><span class="se">)</span><span class="s"> patty"</span><span class="p">)</span>
<span class="k">case</span> <span class="kd">let</span> <span class="o">.</span><span class="kt">Cheese</span><span class="p">(</span><span class="n">type</span><span class="p">):</span>
<span class="nf">print</span><span class="p">(</span><span class="s">"You genius! </span><span class="se">\(</span><span class="n">type</span><span class="se">)</span><span class="s"> Cheese. Sounds great!"</span><span class="p">)</span>
<span class="k">case</span> <span class="o">.</span><span class="kt">Pickle</span><span class="p">:</span>
<span class="nf">print</span><span class="p">(</span><span class="s">"Pickles? Ok, if you're sure"</span><span class="p">)</span>
<span class="k">case</span> <span class="o">.</span><span class="kt">Tomato</span><span class="p">:</span>
<span class="nf">print</span><span class="p">(</span><span class="s">"Gotta love those tomatoes"</span><span class="p">)</span>
<span class="k">default</span><span class="p">:</span> <span class="k">break</span>
<span class="p">}</span>
<span class="p">}</span></code></pre></figure>
<p>When the <code class="highlighter-rouge">BurgerTopping</code> instance matches one of the cases, lets take the
second case as an example, then a new variable <code class="highlighter-rouge">type</code> is created and the
associated value is bound to this variable.</p>
<p>Notice also the use of the wildcard pattern <code class="highlighter-rouge">_</code> in the first case, which
indicates the presence of a variable but we don’t really care what it is. In
the above code I have used it in place of the seeds value. This is because I
don’t intend on using it in the proceeding statement.</p>
<p>Also note the fourth and fifth cases where no variables have been bound.
<code class="highlighter-rouge">Pickle</code> and <code class="highlighter-rouge">Tomato</code> have no associated values so we don’t need to add the
<code class="highlighter-rouge">let</code> keyword. Furthermore if we were to write <code class="highlighter-rouge">case let .Bun(_, _)</code> this would
be equivalent to <code class="highlighter-rouge">case .Bun</code> as we dont need to bind any values.</p>
<h3 id="where-and-fixed-values">Where and Fixed Values</h3>
<p>As you can see there are a few way in which pattern matching can be made useful
for this use case. The <code class="highlighter-rouge">BurgerTopping</code>s could be made a lot more complex or you
could be modelling something entirely different (i.e. a signup form where each
cell in a tableview could be represented).</p>
<p>But we can go further. Where I had included a wildcard in place of the <code class="highlighter-rouge">seeds</code>
value I now want to have a separate case for when seeds is either <code class="highlighter-rouge">true</code> or
<code class="highlighter-rouge">false</code>. We can do this with the <code class="highlighter-rouge">where</code> clause. This is added to the end of a
case as shown below:</p>
<figure class="highlight"><pre><code class="language-swift" data-lang="swift"> <span class="kd">func</span> <span class="nf">add</span><span class="p">(</span><span class="n">_</span> <span class="nv">topping</span><span class="p">:</span> <span class="kt">BurgerTopping</span><span class="p">)</span> <span class="p">{</span>
<span class="k">switch</span> <span class="n">topping</span> <span class="p">{</span>
<span class="k">case</span> <span class="kd">let</span> <span class="o">.</span><span class="kt">Bun</span><span class="p">(</span><span class="n">type</span><span class="p">,</span> <span class="n">seeds</span><span class="p">)</span> <span class="k">where</span> <span class="n">seeds</span> <span class="o">==</span> <span class="nv">true</span><span class="p">:</span>
<span class="nf">print</span><span class="p">(</span><span class="s">"</span><span class="se">\(</span><span class="n">type</span><span class="se">)</span><span class="s"> bun with seeds. Yeeha!"</span><span class="p">)</span>
<span class="k">case</span> <span class="kd">let</span> <span class="o">.</span><span class="kt">Bun</span><span class="p">(</span><span class="n">type</span><span class="p">,</span> <span class="n">seeds</span><span class="p">)</span> <span class="k">where</span> <span class="n">seeds</span> <span class="o">==</span> <span class="nv">false</span><span class="p">:</span>
<span class="nf">print</span><span class="p">(</span><span class="s">"Ooooo. A lovely </span><span class="se">\(</span><span class="n">type</span><span class="se">)</span><span class="s"> bun. Good choice!"</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">}</span></code></pre></figure>
<p>Here the first case will match with a <code class="highlighter-rouge">Bun</code> where its seeds value is equal to
<code class="highlighter-rouge">true</code>, whereas the seconds case will match with a <code class="highlighter-rouge">Bun</code> where its seeds value
is equal to <code class="highlighter-rouge">false</code>. Of course this is a very trivial equality whereby the
value can only ever be <code class="highlighter-rouge">true</code> or <code class="highlighter-rouge">false</code> and can alternatively be written with
Fixed Values:</p>
<figure class="highlight"><pre><code class="language-swift" data-lang="swift"> <span class="kd">func</span> <span class="nf">add</span><span class="p">(</span><span class="n">_</span> <span class="nv">topping</span><span class="p">:</span> <span class="kt">BurgerTopping</span><span class="p">)</span> <span class="p">{</span>
<span class="k">switch</span> <span class="n">topping</span> <span class="p">{</span>
<span class="k">case</span> <span class="kd">let</span> <span class="o">.</span><span class="kt">Bun</span><span class="p">(</span><span class="n">type</span><span class="p">,</span> <span class="kc">true</span><span class="p">):</span>
<span class="nf">print</span><span class="p">(</span><span class="s">"</span><span class="se">\(</span><span class="n">type</span><span class="se">)</span><span class="s"> bun with seeds. Yeeha!"</span><span class="p">)</span>
<span class="k">case</span> <span class="kd">let</span> <span class="o">.</span><span class="kt">Bun</span><span class="p">(</span><span class="n">type</span><span class="p">,</span> <span class="kc">false</span><span class="p">):</span>
<span class="nf">print</span><span class="p">(</span><span class="s">"Ooooo. A lovely </span><span class="se">\(</span><span class="n">type</span><span class="se">)</span><span class="s"> bun. Good choice!"</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">}</span></code></pre></figure>
<p>This does the exact same thing as the first case except instead of using
<code class="highlighter-rouge">where</code> I have explicitly attempted to match a constant value.</p>
<h3 id="if-and-guard-case">If and Guard Case</h3>
<p>The switch statement is not the only to benefit from pattern matching. It may
also be used with <code class="highlighter-rouge">if case</code> and <code class="highlighter-rouge">guard case</code>. Below is a reimplementation of
the switch statement we have been using:</p>
<figure class="highlight"><pre><code class="language-swift" data-lang="swift"> <span class="kd">func</span> <span class="nf">add</span><span class="p">(</span><span class="n">_</span> <span class="nv">topping</span><span class="p">:</span> <span class="kt">BurgerTopping</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="k">case</span> <span class="kd">let</span> <span class="o">.</span><span class="kt">Bun</span><span class="p">(</span><span class="n">type</span><span class="p">,</span> <span class="n">seeds</span><span class="p">),</span> <span class="n">seeds</span> <span class="o">==</span> <span class="kc">true</span> <span class="p">{</span>
<span class="nf">print</span><span class="p">(</span><span class="s">"</span><span class="se">\(</span><span class="n">type</span><span class="se">)</span><span class="s"> bun with seeds. Yeeha!"</span><span class="p">)</span>
<span class="p">}</span>
<span class="k">if</span> <span class="k">case</span> <span class="kd">let</span> <span class="o">.</span><span class="kt">Bun</span><span class="p">(</span><span class="n">type</span><span class="p">,</span> <span class="n">seeds</span><span class="p">),</span> <span class="n">seeds</span> <span class="o">==</span> <span class="kc">false</span> <span class="p">{</span>
<span class="nf">print</span><span class="p">(</span><span class="s">"Ooooo. A lovely </span><span class="se">\(</span><span class="n">type</span><span class="se">)</span><span class="s"> bun. Good choice!"</span><span class="p">)</span>
<span class="p">}</span>
<span class="k">if</span> <span class="k">case</span> <span class="kd">let</span> <span class="o">.</span><span class="kt">Patty</span><span class="p">(</span><span class="n">type</span><span class="p">)</span> <span class="o">=</span> <span class="n">topping</span> <span class="p">{</span>
<span class="nf">print</span><span class="p">(</span><span class="s">"Juicy. Delicious. Succulant </span><span class="se">\(</span><span class="n">type</span><span class="se">)</span><span class="s"> patty"</span><span class="p">)</span>
<span class="p">}</span>
<span class="k">if</span> <span class="k">case</span> <span class="kd">let</span> <span class="o">.</span><span class="kt">Cheese</span><span class="p">(</span><span class="n">type</span><span class="p">)</span> <span class="o">=</span> <span class="n">topping</span> <span class="p">{</span>
<span class="nf">print</span><span class="p">(</span><span class="s">"You genius! </span><span class="se">\(</span><span class="n">type</span><span class="se">)</span><span class="s"> Cheese. Sounds great!"</span><span class="p">)</span>
<span class="p">}</span>
<span class="k">if</span> <span class="k">case</span> <span class="kd">let</span> <span class="o">.</span><span class="kt">Pickle</span> <span class="o">=</span> <span class="n">topping</span> <span class="p">{</span>
<span class="nf">print</span><span class="p">(</span><span class="s">"Pickles? Ok, if you're sure"</span><span class="p">)</span>
<span class="p">}</span>
<span class="k">if</span> <span class="k">case</span> <span class="o">.</span><span class="kt">Tomato</span> <span class="o">=</span> <span class="n">topping</span> <span class="p">{</span>
<span class="nf">print</span><span class="p">(</span><span class="s">"Gotta love those tomatoes"</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">}</span></code></pre></figure>
<p>You may notice this is more verbose than the switch case scenario, due mostly
to curly braces and newlines, but yields the exact same results. Writing <code class="highlighter-rouge">if
case let x = y { ... }</code> is strictly equivalent to writing <code class="highlighter-rouge">switch y { case let
x: ... }:</code>; it’s just a more compact syntax useful when you only want to match
against one case as opposed to a switch which is more appropriate to multiple
case matching.</p>
<p>Take note that the <code class="highlighter-rouge">where</code> clause here is represented by a single comma,
creating a multi-clause conditional statement.</p>
<h3 id="what-else">What Else?</h3>
<p>Beyond the control flow constructs mentioned above, pattern matching can also
be used with <code class="highlighter-rouge">for case</code> and types. I have not yet needed to use these features
and may write about them in a future post. Until then I am going to continue to
altering my development habits to accommodate this functional pattern.</p>
<h3 id="external-resources">External Resources</h3>
<ul>
<li>Patterns. See
<a href="https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Patterns.html">developer.apple.com</a>.</li>
<li>Match Me if you can: Swift Pattern Matching in Detail. See
<a href="https://appventure.me/2015/08/20/swift-pattern-matching-in-detail/">appventure.me</a>.</li>
</ul>Tomas BashamWhilst working on an iOS app, I was able to really jump into some Swift 3 features that were very new to me. Swift 3 has so many advantages over Objective-C but the one I am most impressed with is pattern matching.Swift 3 - Enums2016-11-12T00:00:00+00:002016-11-12T00:00:00+00:00https://tomasbasham.dev/development/2016/11/12/swift-3-enums<p>I am always looking out for better solutions to implement software features
where the language lends itself well to the problem. This way I get the most
out of the language and offload some responsibility to the specific nuances the
language offers. In this article I talk about Swift enums and how I have used
them.</p>
<h3 id="what-is-an-enum">What is an Enum?</h3>
<p>An enum encapsulates a group of related values within a particular domain.
Unlike enums in C which map values to a set of integers, Swift does not enforce
this mapping. If however a value is associated with the related values it is
not limited to integers, but can be represented by any type conforming to
<code class="highlighter-rouge">RawRepresentable</code> protocol. This means that an associated value can a string,
a character, or a value of any integer or floating-point type.</p>
<p>Swift extends enums further to adopt features traditionally supported only by
classes. This includes the adoption of instance methods, computed properties,
initialisers and the ability to conform to protocols. These features are
particularly useful when needing to implement enums where associated values do
no conform to <code class="highlighter-rouge">RawRepresentable</code>.</p>
<h3 id="using-enum-to-implement-a-type">Using Enum To Implement a Type</h3>
<p>Part of an app I am writing required a way to encapsulate the colour scheme I
intend to use. Since there would be a discrete number of colours an enum
seemed like the best solution. It was also important that I be able to select a
random colour from the enum.</p>
<p>Using an enum the solution was simple as shown in this snippet:</p>
<figure class="highlight"><pre><code class="language-swift" data-lang="swift"> <span class="kd">enum</span> <span class="kt">ColorPalette</span><span class="p">:</span> <span class="kt">UInt32</span> <span class="p">{</span>
<span class="k">case</span> <span class="n">blue</span>
<span class="k">case</span> <span class="n">green</span>
<span class="k">case</span> <span class="n">orange</span>
<span class="k">case</span> <span class="n">pink</span>
<span class="k">case</span> <span class="n">purple</span>
<span class="k">case</span> <span class="n">red</span>
<span class="k">case</span> <span class="n">turquoise</span>
<span class="k">var</span> <span class="nv">color</span><span class="p">:</span> <span class="kt">UIColor</span> <span class="p">{</span>
<span class="k">switch</span> <span class="k">self</span> <span class="p">{</span>
<span class="k">case</span> <span class="o">.</span><span class="nv">blue</span><span class="p">:</span> <span class="k">return</span> <span class="kt">UIColor</span><span class="p">(</span><span class="nv">red</span><span class="p">:</span> <span class="mf">0.39</span><span class="p">,</span> <span class="nv">green</span><span class="p">:</span> <span class="mf">0.62</span><span class="p">,</span> <span class="nv">blue</span><span class="p">:</span> <span class="mf">0.71</span><span class="p">,</span> <span class="nv">alpha</span><span class="p">:</span> <span class="mi">1</span><span class="p">)</span>
<span class="k">case</span> <span class="o">.</span><span class="nv">green</span><span class="p">:</span> <span class="k">return</span> <span class="kt">UIColor</span><span class="p">(</span><span class="nv">red</span><span class="p">:</span> <span class="mf">0.77</span><span class="p">,</span> <span class="nv">green</span><span class="p">:</span> <span class="mf">0.87</span><span class="p">,</span> <span class="nv">blue</span><span class="p">:</span> <span class="mf">0.59</span><span class="p">,</span> <span class="nv">alpha</span><span class="p">:</span> <span class="mi">1</span><span class="p">)</span>
<span class="k">case</span> <span class="o">.</span><span class="nv">orange</span><span class="p">:</span> <span class="k">return</span> <span class="kt">UIColor</span><span class="p">(</span><span class="nv">red</span><span class="p">:</span> <span class="mf">0.96</span><span class="p">,</span> <span class="nv">green</span><span class="p">:</span> <span class="mf">0.76</span><span class="p">,</span> <span class="nv">blue</span><span class="p">:</span> <span class="mf">0.33</span><span class="p">,</span> <span class="nv">alpha</span><span class="p">:</span> <span class="mi">1</span><span class="p">)</span>
<span class="k">case</span> <span class="o">.</span><span class="nv">pink</span><span class="p">:</span> <span class="k">return</span> <span class="kt">UIColor</span><span class="p">(</span><span class="nv">red</span><span class="p">:</span> <span class="mf">0.98</span><span class="p">,</span> <span class="nv">green</span><span class="p">:</span> <span class="mf">0.82</span><span class="p">,</span> <span class="nv">blue</span><span class="p">:</span> <span class="mf">0.85</span><span class="p">,</span> <span class="nv">alpha</span><span class="p">:</span> <span class="mi">1</span><span class="p">)</span>
<span class="k">case</span> <span class="o">.</span><span class="nv">purple</span><span class="p">:</span> <span class="k">return</span> <span class="kt">UIColor</span><span class="p">(</span><span class="nv">red</span><span class="p">:</span> <span class="mf">0.56</span><span class="p">,</span> <span class="nv">green</span><span class="p">:</span> <span class="mf">0.47</span><span class="p">,</span> <span class="nv">blue</span><span class="p">:</span> <span class="mf">0.76</span><span class="p">,</span> <span class="nv">alpha</span><span class="p">:</span> <span class="mi">1</span><span class="p">)</span>
<span class="k">case</span> <span class="o">.</span><span class="nv">red</span><span class="p">:</span> <span class="k">return</span> <span class="kt">UIColor</span><span class="p">(</span><span class="nv">red</span><span class="p">:</span> <span class="mf">0.69</span><span class="p">,</span> <span class="nv">green</span><span class="p">:</span> <span class="mf">0.36</span><span class="p">,</span> <span class="nv">blue</span><span class="p">:</span> <span class="mf">0.46</span><span class="p">,</span> <span class="nv">alpha</span><span class="p">:</span> <span class="mi">1</span><span class="p">)</span>
<span class="k">case</span> <span class="o">.</span><span class="nv">turquoise</span><span class="p">:</span> <span class="k">return</span> <span class="kt">UIColor</span><span class="p">(</span><span class="nv">red</span><span class="p">:</span> <span class="mf">0.35</span><span class="p">,</span> <span class="nv">green</span><span class="p">:</span> <span class="mf">0.78</span><span class="p">,</span> <span class="nv">blue</span><span class="p">:</span> <span class="mf">0.72</span><span class="p">,</span> <span class="nv">alpha</span><span class="p">:</span> <span class="mi">1</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kd">static</span> <span class="kd">func</span> <span class="nf">random</span><span class="p">()</span> <span class="o">-></span> <span class="kt">ColorPalette</span> <span class="p">{</span>
<span class="k">let</span> <span class="nv">randomValue</span> <span class="o">=</span> <span class="nf">arc4random_uniform</span><span class="p">(</span><span class="mi">7</span><span class="p">)</span>
<span class="k">return</span> <span class="kt">ColorPalate</span><span class="p">(</span><span class="nv">rawValue</span><span class="p">:</span> <span class="n">randomValue</span><span class="p">)</span><span class="o">!</span>
<span class="p">}</span>
<span class="p">}</span></code></pre></figure>
<p>Take note of the implementation of <code class="highlighter-rouge">random()</code>. It instantiates and returns a
<code class="highlighter-rouge">ColourPalette</code> using a raw value to identify one of it’s cases. Each case has
been automatically assigned a numerical default value because the enum has been
declared to store associated values of the <code class="highlighter-rouge">UInt32</code> type.</p>
<p><strong>Note</strong>: As stated in the Apple documentation <code class="highlighter-rouge">arc4random_uniform()</code> is
recommended over constructions like <code class="highlighter-rouge">arc4random() % upper_bound</code> as it avoids
modulo bias when the upper bound is not a power of two.</p>Tomas BashamI am always looking out for better solutions to implement software features where the language lends itself well to the problem. This way I get the most out of the language and offload some responsibility to the specific nuances the language offers. In this article I talk about Swift enums and how I have used them.Starting out in CryEngine V2016-10-26T00:00:00+00:002016-10-26T00:00:00+00:00https://tomasbasham.dev/gaming/2016/10/26/starting-out-in-cryengine-v<p>It is an irrefutable fact that CryEngine is a fantastic game engine. This is
made evident be the AAA titles that are being released. As a developer I have
been keen to get in on this action and create my own stunning landscapes with a
captivating storyline. However upon being faced with a blank canvas I really do
feel like the David to this game engine Goliath.</p>
<p>This article clearly is not going to be an in depth discussion about how
professionals use this engine and how to implement the next Crysis, however in
this article you will learn the answers I had to some very basic question when
starting out.</p>
<h3 id="what-is-cryengine-v">What is CryEngine V?</h3>
<p>CryEngine V is the fifth major iteration of the CryEngine game engine developed
by the German company <a href="http://www.crytek.com/">Crytek</a>. Since the release of
the original engine in 2002 it has been used for all their titles and has been
continually updated to support newer technologies, hardware and platforms. This
brings us all the way to CryEngine V, released on 22 March 2016, to support a
new licensing model allowing the engine to be used for free.</p>
<p>The implementation of a launcher, which is used to download the engine, is a
much needed improvement. In the past when stating a game project a new copy of
the engine would need to be downloaded and the game built around the engine
source code. From talking to other game developers who used CryEngine back in
these archaic days they said that they preferred that way of working. Although
Crytek are not the first to do this I personally disagree with the other
developers and am glad Crytek have taken this approach.</p>
<h3 id="how-does-it-differ-from-ue4-or-other-engines">How does it differ from UE4 or other engines?</h3>
<p>Before settling with CryEngine V I also ventured into UnrealEngine 4 (UE4) and
Unity. Although all of these game engines offer similar features there were
some key points that made CryEngine V stand out to me:</p>
<ul>
<li>100% Royalty free. Unlike UE4 and Unity which require you to pay royalties
when you hit the big time, CryEngine is completely royalty free,</li>
<li>Real time sandbox editing. Both UE4 and Unity have this functionality, but it
felt more solid in CryEngine,</li>
<li>Single key press to jump straight into the game. This is facilitated without
loading the game engine as it is already running within the editor,</li>
<li>A lot of boilerplate is already done for you. A new project will start with
an ocean, a small platform, a skybox and Time of Day (TOD) feature with
daylight/nighttime transition. This was not something I found in UE4,</li>
<li>An impressive sample level which I feel is more accessible than those on UE4
or Unity. For instance it runs on my mid spec Windows Desktop whereas the UE4
Infiltrator demo has no hope in hell of running on my machine.</li>
</ul>
<h3 id="what-cryengine-is-not">What CryEngine is not</h3>
<p>So far I have been singing CryEngine praises, but like most things it is not
perfect. In particular:</p>
<ul>
<li>It is not as user friendly as other engines, although it is vastly more so
than in previous versions,</li>
<li>It currently has little support and scattered documentation,</li>
<li>I found there to be a partially elitist community (at least those I spoke to
on Slack), whilst the forums are most helpful,</li>
<li>It’s asset store is lacking in… well, assets. I assume this will improve
over time. CryEngine (with launcher and store) is very new so the community
has yet to release many assets.</li>
</ul>
<h3 id="the-missing-answers">The Missing Answers</h3>
<p>Now with an introduction to the game engine I present the questions that I had
when starting to use CryEngine V.</p>
<h3 id="1-how-to-launch-the-code-editor-and-the-game">1. How to Launch the Code, Editor and the Game?</h3>
<p>I believe it is important to note that Visual Studio (or MonoDevelop for C#)
should be launched using the <code class="highlighter-rouge">Code_CPP.bat</code> file (Code_CS.bat for C#) created
after bootstrapping a new game project. This script creates a series of
environment variables that presumably enable Visual Studio to successfully
build the game.</p>
<p>Similarly launching the sandbox editor should be done via the <code class="highlighter-rouge">Editor.bat</code> file
or from the CryEngine Launcher.</p>
<p><strong>Update</strong>: Now CryEngine 5.2 has been released the above has been updated.
Instead a working installation of CMake (3.6+) is required to generate a Visual
Studio (or MonoDevelop for C#) project file that can be opened through
explorer, whilst the editor and game are launched through the <code class="highlighter-rouge">.cryproject</code>
file.</p>
<h3 id="2-how-are-the-config-files-loaded">2. How are the Config Files Loaded?</h3>
<p>There are a couple of configuration files scattered around the engine and
individual projects. These are loaded in a particular order as discussed below:</p>
<p><code class="highlighter-rouge">system.cfg</code> is the first config file loaded by the engine and found in the
engine root. I tend not to touch this file and pretend it does not exist.
Unless I know I want a certain configuration for every game I plan to create it
will suffice to put my game configs elsewhere. The exception to this is the
audio middleware. It was recommended that I switch middleware in here.</p>
<p><code class="highlighter-rouge">editor.cfg</code> is loaded next and also found in the engine root. Presumably this
config applies only to the editor. As with <code class="highlighter-rouge">system.cfg</code>, unless I know I want a
certain configuration for every game I wont edit this file.</p>
<p><code class="highlighter-rouge">game.cfg</code> is loaded next. This is the configuration file for the specific
project.</p>
<p><strong>Update</strong>: Prior to version 5.2 <code class="highlighter-rouge">project.cfg</code> is the loaded last. This file
seemed superflous to me as <code class="highlighter-rouge">game.cfg</code> would do the job. It would appear it has
been removed.</p>
<p><strong>Upadte</strong>: Having updated to version 5.3 it appears that <code class="highlighter-rouge">system.cfg</code> has been
removed so I was unable to continue using this file to host my audio middleware
configurations. Instead I have moved it over to <code class="highlighter-rouge">game.cfg</code>. This has made a
little more sense to me considering how the new plugin system is supposed to
help separate engine logic from specific game code. Putting my configurations
variables here keeps all my game specific values in one place.</p>
<p>The various configuration variables and console commands are documented on the
CryEngine website and prefixed with the initials of it parent subcomponent of
the engine. For example the <code class="highlighter-rouge">s_</code> prefix is for the sound engine subcomponent. A
full list of the available configuration variables can be found
<a href="http://docs.cryengine.com/display/CRYAUTOGEN/Home">here</a>.</p>
<h3 id="3-what-is-the-resource-compiler">3. What is the Resource Compiler?</h3>
<p>The <code class="highlighter-rouge">MakeAssets.bat</code> invokes the the resource compiler (rc.exe) that optimises
assets for the specific platform. Some useful resources referencing the
resource compiler can be found on the CryEngine website. Ones of note are:
<a href="http://docs.cryengine.com/display/SDKDOC2/Using+the+Resource+Compiler">using the resource
compiler</a>
and <a href="http://docs.cryengine.com/display/CEPROG/Compiling+Assets+for+Multiple+Platforms">compiling assets for multiple
platforms</a>.</p>
<p>Furthermore <code class="highlighter-rouge">MakeAssets.bat</code> contains syntax such as <code class="highlighter-rouge">%~dp0</code>. This is a Windows
shell command that expands the full path to the file (including the drive
letter drive). More on this can be found in
<a href="http://stackoverflow.com/a/5034119">this</a> StackOverflow answer.</p>
<p><strong>Update</strong>: In version 5.2 of the engine this feature seems to be broken since
the project.cfg file was removed. I questioned this on the forums to only have
it confirmed. Hopefully this will be fixed ASAP.</p>
<p><strong>Update</strong>: In version 5.3 <code class="highlighter-rouge">MakeAssets.bat</code> has been removed from the game
templates. I can only assume it is now handled entirely within the <a href="http://docs.cryengine.com/display/CEPROG/CMake">CMake
system</a>.</p>
<h3 id="4-how-to-implement-wwise-sound-engine">4. How to implement Wwise sound engine?</h3>
<p>When I start a project I like to setup and integrate all the other 3rd party
software I intend to use first. So to begin I wanted to switch the audio
middleware that the engine uses. By default this is SDL Mixer. In order for the
engine to interact with different audio middleware it implements an Audio
Translation Layer (ATL) which is an abstraction interface between CryEngine and
other audio middlewares i.e. Wwise.</p>
<p>I wont be going through the setup of Wwise in this article as it is covered
well
<a href="http://docs.cryengine.com/display/CEMANUAL/Setting+up+Wwise+for+CRYENGINE">here</a>
but the two important console commands I used are:</p>
<figure class="highlight"><pre><code class="language-conf" data-lang="conf"><span class="n">s_DrawAudioDebug</span> <span class="m">1</span> <-- <span class="n">Display</span> <span class="n">debug</span> <span class="n">information</span> <span class="n">about</span> <span class="n">ATL</span> <span class="n">middleware</span>.
<span class="n">s_AudioImplName</span> <span class="n">CryAudioImplWwise</span> <-- <span class="n">Switch</span> <span class="n">to</span> <span class="n">the</span> <span class="n">Wwise</span> <span class="n">audio</span> <span class="n">middleware</span>. <span class="n">Other</span> <span class="n">options</span> <span class="n">include</span> <span class="n">CryAudioImplFmod</span> (<span class="n">for</span> <span class="n">fmod</span> <span class="n">studio</span>) <span class="n">and</span> <span class="n">CryAudioImplSDLMixer</span> (<span class="n">for</span> <span class="n">sdl</span> <span class="n">mixer</span>).</code></pre></figure>
<p>I also set these in my <code class="highlighter-rouge">system.cfg</code> file as mentioned earlier. Now every time I
create a new project, or launch a current project the correct audio middleware
is selected.</p>
<p><strong>Update</strong>: As of version 5.3 I have transitioned this configuration to
<code class="highlighter-rouge">game.cfg</code> as <code class="highlighter-rouge">system.cfg</code> has been removed (at least according to my editor
log file which is unable to find it).</p>
<h3 id="5-how-is-the-c-sample-project-structured">5. How is the C++ Sample Project Structured?</h3>
<p>I lean toward using C++ when I can. It seems to have been the industry standard
for many years so there must be something about it that lends itself well to
games. Alternatively it was just the only decent language available at the time
and has just stuck. Regardless, the C++ project the launcher generates includes
a little boilerplate that is not well documented and I simply am unsure what it
all does, whether it is necessary and whether I can remove it without breaking
everything.</p>
<p>I’m cautious that this is an example of <a href="https://en.wikipedia.org/wiki/Functional_fixedness">functional
fixedness</a>, a bias
limiting me to using the engine only in the way it has traditionally been
used. So I intend to figure out what were the intentions of having included
these particular boilerplate features, yet not implement others? Beyond this I
intend to find what each bit does.</p>
<h3 id="6-what-is-included-in-the-assets-folder">6. What is Included in the Assets Folder?</h3>
<p>The Assets folder contains <code class="highlighter-rouge">Textures.pak</code>. What is the difference between this
and the <code class="highlighter-rouge">terraintexture.pak</code> within <code class="highlighter-rouge">Assets/levels/example</code>? I assume
<code class="highlighter-rouge">Textures.pak</code> are global textures whereas <code class="highlighter-rouge">terraintexture.pak</code> contains
textures pertaining to a particular levels landscape including height maps,
normal maps etc…</p>
<h3 id="moving-forward">Moving Forward</h3>
<p>I am clearly still no expert here, with some questions still unanswered. I
fully intend to keep this article up to date whilst I discover more answers to
my questions, perhaps adding further questions as they develop.</p>
<p>Please leave comments correcting any of my assumptions as I have likely made
many mistakes in my findings. I would like this to turn into a great starting
out guide to those jumping in at the deep end like myself.</p>Tomas BashamIt is an irrefutable fact that CryEngine is a fantastic game engine. This is made evident be the AAA titles that are being released. As a developer I have been keen to get in on this action and create my own stunning landscapes with a captivating storyline. However upon being faced with a blank canvas I really do feel like the David to this game engine Goliath.Building a Bar Top Multicade2016-08-29T00:00:00+00:002016-08-29T00:00:00+00:00https://tomasbasham.dev/product%20design/2016/08/29/building-a-bartop-multicade<p>For sometime I have wanted an arcade machine for retro gaming, but they can be
extremely expensive and take up a lot of space. This is no more true then a
full sized cabinet. Furthermore they often come preloaded with only a handful
of games that become tiresome pretty quickly. So I set out to solve these
problems, saving space and achieving an affordable cabinet capable of playing
hundreds of old, classic games.</p>
<p>Of course I am not the first, and I most certainly wont be the last to make my
own arcade cabinet, but it must be said the high level of customisation is
satisfying and rewarding in the end.</p>
<p>Overall building my own cabinet has taken just over a year, mostly due to
finding and waiting on joinery companies to cut out my custom wooden panels as
I possess neither the steady hand, patience or machinery to do it myself. If
Dr. Leonard McCoy worked in IT I’m sure he’d say something along the lines of
“Im a software engineer, not a machinist”.</p>
<p>My arcade is a DIY retro bartop arcade cabinet built for two players whom can
use either the built in joysticks and buttons or plug in SNES controllers for
that added retro console feel. It is powered by a Raspberry Pi Model B capable
of playing multiple types of retro games - primarily NES, SNES, Megadrive and
arcade (MAME) games.</p>
<h3 id="materials-list">Materials List</h3>
<p>I believe in total the arcade has cost me around £250, but considering that is
a fraction of the cost of some machines it is a real steal. The bill of
materials I used to construct the arcade follows:</p>
<table>
<thead>
<tr>
<th>Item</th>
<th>Qty.</th>
<th>Merchant</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="https://shop.pimoroni.com/products/raspberry-pi-3">Raspberry Pi Model B</a> (or better)</td>
<td>1</td>
<td>Pimoroni</td>
</tr>
<tr>
<td><a href="https://www.amazon.co.uk/gp/product/B00DM2L7Z0/ref=oh_aui_detailpage_o09_s00?ie=UTF8&psc=1">Heatsink for Raspberry Pi</a></td>
<td>1</td>
<td>Amazon</td>
</tr>
<tr>
<td><a href="https://www.amazon.co.uk/gp/product/B00J29BR3Y/ref=oh_aui_detailpage_o08_s00?ie=UTF8&psc=1">32 GB SD Card</a></td>
<td>1</td>
<td>Amazon</td>
</tr>
<tr>
<td><a href="https://www.amazon.co.uk/gp/product/B00F4MGRRE/ref=oh_aui_detailpage_o07_s00?ie=UTF8&psc=1">3 Pin Inlet</a></td>
<td>1</td>
<td>Amazon</td>
</tr>
<tr>
<td><a href="https://www.amazon.co.uk/gp/product/B003U798T4/ref=oh_aui_detailpage_o00_s00?ie=UTF8&psc=1">Kettle Lead</a></td>
<td>1</td>
<td>Amazon</td>
</tr>
<tr>
<td><a href="https://www.amazon.co.uk/Skytroni-Extension-Lead-Surge-Protection-White/dp/B000L9CU6C">4-Way Extension</a></td>
<td>1</td>
<td>Amazon</td>
</tr>
<tr>
<td><a href="https://www.amazon.co.uk/gp/product/B005WMIR4C/ref=oh_aui_detailpage_o01_s00?ie=UTF8&psc=1">SNES Controller Extension</a></td>
<td>1</td>
<td>Amazon</td>
</tr>
<tr>
<td>SNES Controller</td>
<td>2</td>
<td>eBay</td>
</tr>
<tr>
<td>19” 5:4 TFT Monitor</td>
<td>1</td>
<td>eBay</td>
</tr>
<tr>
<td><a href="https://www.arcadeworlduk.com/products/Arcade-Joysticks-Buttons-And-Arcade-Controller-Kit.html">Joysticks, Buttons and Controller</a></td>
<td>1</td>
<td>Arcade World UK</td>
</tr>
<tr>
<td><a href="https://www.arcadeworlduk.com/products/hi-fi-stereo-sound-amplifier-kit-for-arcade-machine-projects.html">Speakers and Amplifier</a></td>
<td>1</td>
<td>Arcade World UK</td>
</tr>
<tr>
<td><a href="https://www.arcadeworlduk.com/products/Yellow-3-Quarter-Inch-T-Molding.html">T Moulding (1m)</a></td>
<td>5</td>
<td>Arcade World UK</td>
</tr>
<tr>
<td>19mm MDF Panels</td>
<td> </td>
<td>B&Q</td>
</tr>
</tbody>
</table>
<p><strong>Note</strong>: Heatsink is not necessary on newer Raspberry Pi models.</p>Tomas BashamFor sometime I have wanted an arcade machine for retro gaming, but they can be extremely expensive and take up a lot of space. This is no more true then a full sized cabinet. Furthermore they often come preloaded with only a handful of games that become tiresome pretty quickly. So I set out to solve these problems, saving space and achieving an affordable cabinet capable of playing hundreds of old, classic games.