<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Marcin Kaszyński</title>
    <description>Coding, analyzing requirements, managing, testing, marketing – been there, done that, failed at least once at every single one.
</description>
    <link>/</link>
    <atom:link href="/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Fri, 02 Apr 2021 13:16:53 +0200</pubDate>
    <lastBuildDate>Fri, 02 Apr 2021 13:16:53 +0200</lastBuildDate>
    <generator>Jekyll v3.2.1</generator>
    
      
      <item>
        <title>Empathy for the Maintainer</title>
        <description>&lt;p&gt;I’ve been thinking a lot about communication and code quality over the past
couple of years.  It’s nothing new of course, I’m not the only one, but I
believe that most of ways we address it start with a wrong perspective, and a
wrong focal point.&lt;/p&gt;

&lt;p&gt;(this is a heavily edited and expanded text version of my lightning talk at
PyCon PL 2019)&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;&lt;strong&gt;Disclaimer&lt;/strong&gt;: I don’t claim to know how to write good code.  I’m drawing from
my ~30 years of experience writing bad one.&lt;/p&gt;

&lt;p&gt;There is plenty of advice on how to write good code.  The &lt;a href=&quot;https://www.python.org/dev/peps/pep-0020/&quot;&gt;Zen of
Python&lt;/a&gt;, the
&lt;a href=&quot;http://wiki.c2.com/?DontRepeatYourself&quot;&gt;DRY&lt;/a&gt;/&lt;a href=&quot;http://wiki.c2.com/?OnceAndOnlyOnce&quot;&gt;Once and Only
Once&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/Software_metric&quot;&gt;a whole bunch of software
metrics&lt;/a&gt;, random advice like
particular naming schemes and attempts at consistency.  Most of those are very
procedural.  Which is understandable, they are mostly created by techies for
techies, procedures is what we do for a living and what we tend to expect.&lt;/p&gt;

&lt;p&gt;But these are bad rules.  Because, really, they are not rules at all.  They are
guidelines.  Tools.&lt;/p&gt;

&lt;p class=&quot;center&quot;&gt;&lt;img src=&quot;/post-images/empathy-for-the-maintainer/guidelines-1.jpg&quot; alt=&quot;They are more like guidelines&quot; style=&quot;width: 25em&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Writing code is a lot like writing prose.  You have one extra restriction (it
has to be executable, and perform some task as it runs), but other than that
you get a similar level of flexibility, complexity, and the same problem: how
to convey your goals, ideas, and reasoning to other people.  Yes, &lt;strong&gt;people&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you focus on tools instead of communication, just like with prose you will
get a result that is correct, to some definition of correct.  So, congrats!
But it might not be the definition you really want.&lt;/p&gt;

&lt;p class=&quot;center&quot;&gt;&lt;img src=&quot;/post-images/empathy-for-the-maintainer/technically-correct-1.jpg&quot; alt=&quot;You are technically correct&quot; style=&quot;width: 25em&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We need to start from a different direction, with a different focus, and that
focus should be &lt;strong&gt;empathy&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;To be more specific: empathy for the maintainer.&lt;/p&gt;

&lt;p&gt;Who, with high probability, might also be you.&lt;/p&gt;

&lt;p&gt;After a long break from the project.&lt;/p&gt;

&lt;p&gt;On a tight deadline.&lt;/p&gt;

&lt;p&gt;Because you have a fire on production and everyone else on the team is also
involved with some aspect of that fire, so you go into the code and what
happens is:&lt;/p&gt;

&lt;p class=&quot;center&quot;&gt;&lt;img src=&quot;/post-images/empathy-for-the-maintainer/no-memory-of-this-place.jpg&quot; alt=&quot;I have no memory of this place&quot; style=&quot;width: 25em&quot; /&gt;&lt;/p&gt;

&lt;p&gt;If you already know this exact scenario: good, it’s a blessing in disguise.
It’s a rare chance to see your own code with completely fresh eyes; it’s some
of the best, most humbling feedback you can get.&lt;/p&gt;

&lt;p&gt;(and if you don’t, don’t worry! it’s all ahead of you)&lt;/p&gt;

&lt;p&gt;Let’s approach the problem from a different direction.  Here is the situation:&lt;/p&gt;

&lt;div style=&quot;white-space: pre;border:  1px solid black;margin: 2em auto;text-align: center; width: 20em; padding: 1em&quot;&gt;you



the maintainer
&lt;/div&gt;

&lt;p&gt;There are you now, and there is the maintainer in the future.  Who, again,
might be an older you, but not necessarily.&lt;/p&gt;

&lt;p&gt;The two you communicate via the source code:&lt;/p&gt;

&lt;div style=&quot;white-space: pre;border:  1px solid black;margin: 2em auto;text-align: center; width: 20em; padding: 1em&quot;&gt;you
↓
[your code]
↓
the maintainer
&lt;/div&gt;

&lt;p&gt;Assume this is the only means of communication.  It’s uni-directional: you will
not get immediate feedback on whether what you sent along the wire is
sufficient to understand you.  So put yourself in the position of the person
who will receive that communication and ask some questions:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;How understandable is it?  Are there any unnecessarily tricky parts?  What
can you simplify?  Again, assume a fresh look by someone who does not know
the full history of the project.&lt;/li&gt;
  &lt;li&gt;How much of other code do they have to read?  If your file or function a
cohesive part of the larger whole, readable on its own?  Is the control flow
visible and readable?  How much of the surrounding package, library, or
project do they have to read to make sense of it?&lt;/li&gt;
  &lt;li&gt;What can you assume they already know?  The language, the framework[s], the
libraries you used, and the project this file is part of, all create their
own conventions and vocabulary; the deeper in this hierarchy, the less you
can rely on it.&lt;/li&gt;
  &lt;li&gt;Most importantly: &lt;strong&gt;how can you help them understand it&lt;/strong&gt;?  If you have any
experience working as a developer, you already know how it feels to stare at
someone else’s code, trying to make sense of it.  What do you remember from
situations like that?  What would have helped you?  (you might want to
answer “documentation” or “comments”; neither is a good main resource for
understanding code, so focus on the code itself)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And &lt;strong&gt;then&lt;/strong&gt;, with those questions in mind, take a look at the tools at your
disposal:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;conventions: not all conventions are of equal value; look for the ones that
are widely shared, for example: if your code does something similar to
things that are in standard library, use a similar interface, so that people
can recognise it,&lt;/li&gt;
  &lt;li&gt;vocabulary: variables are nouns, functions and methods are verbs, use them
to explain what’s going on,&lt;/li&gt;
  &lt;li&gt;control flow: if the reader can analyse code from top to bottom, following
the control flow and choosing parts to read more closely, it will be easier
for them than if they have to jump between multiple unrelated files to piece
together the top-level behavior,&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;and all the other tools mentioned at the beginning of this text.  Use them as a
catalogue of ideas to address the questions.  Things to try out and use where
you notice they help.&lt;/p&gt;

&lt;p&gt;Don’t stop when your code starts doing what you want it to do.  Make it work
first, but then keep editing it to make it readable.  Take a break, return to
the code after a while and see if you can edit it some more.&lt;/p&gt;

&lt;p&gt;You may think you have no time for it, and are in the hurry to deliver
functionality; in most cases that is not true.  If you work on a real-life
project, in a team larger than a single person, you have no time not to do it.
Whatever you save here you and your team will repay in the future, with
interest, when trying to maintain the code.&lt;/p&gt;

&lt;p&gt;Empathise with the maintainer.  It will make you a better programmer.&lt;/p&gt;

&lt;p&gt;See also: &lt;a href=&quot;/2017/04/21/code-quality.html&quot;&gt;My main code quality guideline&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Sun, 15 Sep 2019 00:00:00 +0200</pubDate>
        <link>/2019/09/15/empathy-for-the-maintainer.html</link>
        <guid isPermaLink="true">/2019/09/15/empathy-for-the-maintainer.html</guid>
        
        <category>tech,programming,empathy</category>
        
        
      </item>
      
    
      
      <item>
        <title>How auth works in EKS with IAM Users</title>
        <description>&lt;p&gt;This was not trivial to find: how exactly does authentication and
authorization work in &lt;a href=&quot;https://aws.amazon.com/eks/&quot;&gt;EKS&lt;/a&gt; if you want
to use IAM Users or Roles to authenticate?&lt;/p&gt;

&lt;p&gt;As an example, what happens when you run &lt;code class=&quot;highlighter-rouge&quot;&gt;kubectl auth can-i get pods&lt;/code&gt;?&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;prerequisites&quot;&gt;Prerequisites&lt;/h2&gt;

&lt;p&gt;You will need to install &lt;code class=&quot;highlighter-rouge&quot;&gt;aws&lt;/code&gt; command line tools, &lt;code class=&quot;highlighter-rouge&quot;&gt;kubectl&lt;/code&gt;, and
&lt;code class=&quot;highlighter-rouge&quot;&gt;heptio-authenticator-aws&lt;/code&gt;; make sure they are on &lt;code class=&quot;highlighter-rouge&quot;&gt;PATH&lt;/code&gt;.  I also use
&lt;code class=&quot;highlighter-rouge&quot;&gt;jq&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;shyaml&lt;/code&gt;, and &lt;code class=&quot;highlighter-rouge&quot;&gt;httpie&lt;/code&gt; in examples.&lt;/p&gt;

&lt;h2 id=&quot;client-side-configuration-aws&quot;&gt;Client-side configuration: AWS&lt;/h2&gt;

&lt;p&gt;In case of EKS there are two parts to configure: AWS command line
tools (AWS CLI) and kubectl.  I need to access multiple clusters using multiple
credentials, so I’ll cover that more generic case here.&lt;/p&gt;

&lt;p&gt;The usual way to configure AWS is to run &lt;code class=&quot;highlighter-rouge&quot;&gt;aws configure --profile &amp;lt;profile-name&amp;gt;&lt;/code&gt;, but you can just as well just edit &lt;code class=&quot;highlighter-rouge&quot;&gt;~/.aws/config&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;~/.aws/credentials&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[@trurl ~] cat .aws/config
 [default]
 region = us-west-2
 [profile some-other-profile]
 region = us-west-2
 [profile profile-that-uses-iam-role]
 region = us-west-2

[@trurl ~] cat .aws/credentials
 [default]
 aws_access_key_id = [REDACTED]
 aws_secret_access_key = [REDACTED]
 [some-other-profile]
 aws_access_key_id = [REDACTED]
 aws_secret_access_key = [REDACTED]
 [profile-that-uses-iam-role]
 role_arn = &amp;lt;ARN of the role to assume&amp;gt;
 source_profile = &amp;lt;name of profile used for auth before assuming this role&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;IAM has two kinds of identity entities: users and roles.  An IAM User
is what you’d expect: it has an username and credentials, belongs to
some groups, has permissions attached to it.  An IAM Role is similar,
but it’s an identity that a user or a process may assume temporarily
for the purpose of performing some actions.  IAM Users are usually
used for human interaction with AWS; IAM Roles are usually used for
automated access, for example: when EKS server wants to tell AWS it
needs to start a new node, it can manage that part of your AWS account
only because it authenticates into a role that has sufficient
permissions in the account.&lt;/p&gt;

&lt;p&gt;AWS CLI always starts with credentials of an IAM user (or the account
owner, although you should use that identity only to create an IAM
user to interact with your account); you can also assume a role, like
in the last profile, but I won’t use that here.&lt;/p&gt;

&lt;p&gt;If your configuration is correct, you can do this:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# You may omit the AWS_PROFILE=..., aws will use the default
[@trurl ~] export AWS_PROFILE=&amp;lt;profile-name&amp;gt;
[@trurl ~] aws sts get-caller-identity
 {
     &quot;Account&quot;: &quot;[REDACTED]&quot;,
     &quot;UserId&quot;: &quot;[REDACTED]&quot;,
     &quot;Arn&quot;: &quot;arn:aws:iam::[REDACTED]:user/&amp;lt;username&amp;gt;&quot;
 }
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;If you created a cluster, you can now ask AWS for information
necessary to access it:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[@trurl ~] aws eks list-clusters
 {
     &quot;clusters&quot;: [
         &quot;my-cluster&quot;,
         [...]
     ]
 }
[@trurl ~] aws eks describe-cluster --name=my-cluster
 {
     &quot;cluster&quot;: {
         &quot;status&quot;: &quot;ACTIVE&quot;,
         &quot;endpoint&quot;: &quot;https://[REDACTED].[REDACTED].us-west-2.eks.amazonaws.com&quot;,
         &quot;name&quot;: &quot;my-cluster&quot;,
         &quot;certificateAuthority&quot;: {
             &quot;data&quot;: &quot;[REDACTED]&quot;
         },
         [...]
     }
 }
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;client-side-configuration-kubectl&quot;&gt;Client-side configuration: kubectl&lt;/h2&gt;

&lt;p&gt;Now that you have AWS CLI running, create configuration file for
&lt;code class=&quot;highlighter-rouge&quot;&gt;kubectl&lt;/code&gt;.  You can have a single file for multiple clusters,
but it’s cleaner to have a separate file for every cluster.  The
location does not matter, I use &lt;code class=&quot;highlighter-rouge&quot;&gt;~/.kube/config.d/&amp;lt;cluster-name&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Example file:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[@trurl ~] cat ~/.kube/config.d/my-cluster
 apiVersion: v1
 clusters:
 - cluster:
     certificate-authority-data: &amp;lt;certificateAuthority.data from describe-cluster&amp;gt;
     server: &amp;lt;endpoint from describe-cluster&amp;gt;
   name: &amp;lt;cluster-name&amp;gt;
 contexts:
 - context:
     cluster: &amp;lt;cluster-name&amp;gt;
     user: aws
   name: aws
 current-context: aws
 kind: Config
 preferences: {}
 users:
 - name: aws
   user:
     exec:
       apiVersion: client.authentication.k8s.io/v1alpha1
       args:
       - token
       - -i
       - &amp;lt;cluster-name&amp;gt;
       command: heptio-authenticator-aws
       env:
       - name: AWS_PROFILE
         value: &amp;lt;profile-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This file tells kubectl:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;the base URL for the cluster’s API server (&lt;code class=&quot;highlighter-rouge&quot;&gt;cluster.server&lt;/code&gt;),&lt;/li&gt;
  &lt;li&gt;the certificate authority data to use for TLS verification
(&lt;code class=&quot;highlighter-rouge&quot;&gt;certificate-authority-data&lt;/code&gt;),&lt;/li&gt;
  &lt;li&gt;that for authentication it should use bearer tokens generated by
&lt;code class=&quot;highlighter-rouge&quot;&gt;heptio-authenticator-aws&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;heptio-authenticator-aws&lt;/code&gt; does not execute any remote calls; it just
creates a signed token based on cluster name and credentials from your
&lt;code class=&quot;highlighter-rouge&quot;&gt;AWS_PROFILE&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[@trurl ~] heptio-authenticator-aws token -i my-cluster
 {
   &quot;kind&quot;: &quot;ExecCredential&quot;,
   &quot;apiVersion&quot;: &quot;client.authentication.k8s.io/v1alpha1&quot;,
   &quot;spec&quot;: {},
   &quot;status&quot;: {
     &quot;token&quot;: &quot;[REDACTED]&quot;
   }
 }
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;If your configuration is correct AND you have permissions set right,
this should work:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[@trurl ~] export KUBECONFIG=~/.kube/config.d/my-cluster
[@trurl ~] kubectl auth can-i get pods
yes
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;You might also see one of these:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[@trurl ~] kubectl auth can-i get pods
 error: You must be logged in to the server (Unauthorized)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;meaning there’s something wrong with authentication, or:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[@trurl ~] kubectl auth can-i get pods
 no
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;meaning that authentication went well, but authorization did not.
I’ll address both below.&lt;/p&gt;

&lt;h2 id=&quot;authentication&quot;&gt;Authentication&lt;/h2&gt;

&lt;p&gt;Kubernetes has two kinds of users:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Service accounts&lt;/strong&gt;: they are just what you would expect from user
accounts; they are first class entities in Kubernetes, available
through its API. you can use them with EKS, but there is nothing
EKS-specific here as they sidestep all the IAM machinery; and there
already exist better guides about this branch, so I’ll skip them here.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Normal users&lt;/strong&gt;: managed completely outside Kubernetes; the API
server trusts some external software to provide it with the username
and groups for every request it receives.  This is what EKS uses when
you authenticate using IAM identities, and this is what I’ll cover
here.&lt;/p&gt;

&lt;p&gt;When you execute a &lt;code class=&quot;highlighter-rouge&quot;&gt;kubectl&lt;/code&gt; command it does a REST call to
Kubernetes’s API server and sends the token generated by
&lt;code class=&quot;highlighter-rouge&quot;&gt;heptio-authenticator-aws&lt;/code&gt; in the &lt;code class=&quot;highlighter-rouge&quot;&gt;Authentication&lt;/code&gt; header.  When you
&lt;code class=&quot;highlighter-rouge&quot;&gt;kubectl auth can-i get pods&lt;/code&gt;, the client does more or less this:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# Store the CA data in a file for TLS verification; you can skip it if
# you're fine with the insecure `--verify=no` in http call below.
[@trurl ~] cat ~/.kube/config.d/my-cluster \
    | shyaml get-value 'clusters.0.cluster.certificate-authority-data' \
    | base64 -D &amp;gt; ~/.kube/config.d/my-cluster-ca-data

# Generate the authentication token
[@trurl ~] TOKEN=`heptio-authenticator-aws token -i my-cluster | jq -r .status.token`

[@trurl ~] REQUEST='{&quot;kind&quot;: &quot;SelfSubjectAccessReview&quot;, &quot;apiVersion&quot;: &quot;authorization.k8s.io/v1&quot;, &quot;spec&quot;:{&quot;resourceAttributes&quot;:{&quot;name&quot;:&quot;pod&quot;,&quot;verb&quot;:&quot;get&quot;}}}'

[@trurl ~] echo &quot;$REQUEST&quot; \
    | http --verify=~/.kube/config.d/my-cluster-ca-data \
      post https://[REDACTED].[REDACTED].us-west-2.eks.amazonaws.com/apis/authorization.k8s.io/v1/selfsubjectaccessreviews \
      Authorization:&quot;Bearer $TOKEN&quot;
 HTTP/1.1 201 Created
 Content-Length: 196
 Content-Type: application/json
 Date: Wed, 11 Jul 2018 01:21:27 GMT
 
 {
     [...]
     &quot;status&quot;: {
         &quot;allowed&quot;: true
     }
 }
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;On the server side Kubernetes passes the token to a webhook to the
&lt;code class=&quot;highlighter-rouge&quot;&gt;aws-iam-authenticator&lt;/code&gt; process running on EKS host; if all goes well
the authenticator returns a “normal user” identity consisting of
&lt;code class=&quot;highlighter-rouge&quot;&gt;username&lt;/code&gt; (a string) and &lt;code class=&quot;highlighter-rouge&quot;&gt;groups&lt;/code&gt; (a list of strings containing group
names).  If that works, that is when authentication ends.&lt;/p&gt;

&lt;p&gt;If it fails then it means that you attempted to execute the request
using an IAM User or Role that the &lt;code class=&quot;highlighter-rouge&quot;&gt;aws-iam-authenticator&lt;/code&gt; running on
your cluster does not know how to map to a “normal user” in Kubernetes
space.&lt;/p&gt;

&lt;p&gt;There are essentially two cases here:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The IAM User or Role that was used to create the cluster&lt;/strong&gt; is
hardwired in &lt;code class=&quot;highlighter-rouge&quot;&gt;aws-iam-authenticator&lt;/code&gt; configuration to map to a
“normal user” who belongs to the &lt;code class=&quot;highlighter-rouge&quot;&gt;system:masters&lt;/code&gt; group.  This part
is not visible anywhere in data you can reach via &lt;code class=&quot;highlighter-rouge&quot;&gt;kubectl&lt;/code&gt; and
&lt;code class=&quot;highlighter-rouge&quot;&gt;aws&lt;/code&gt; commands, but that also means you can’t modify it.&lt;/p&gt;

&lt;p&gt;For &lt;strong&gt;other IAM Users or Roles&lt;/strong&gt; you must configure
&lt;code class=&quot;highlighter-rouge&quot;&gt;aws-iam-authenticator&lt;/code&gt; by setting the &lt;code class=&quot;highlighter-rouge&quot;&gt;aws-auth&lt;/code&gt; configmap.  If you
went far along with the cluster to actually add some nodes it means
you must have created that configmap already, since it’s the same
thing that lets the cluster authenticate its nodes.  If not, you might
want to look into
&lt;a href=&quot;https://docs.aws.amazon.com/eks/latest/userguide/getting-started.html&quot;&gt;Getting Started with Amazon EKS&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To authenticate another IAM User or Role, you have to add user or role
mappings:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[@trurl ~] cat /tmp/aws-auth-cm
 apiVersion: v1
 kind: ConfigMap
 metadata:
   name: aws-auth
   namespace: kube-system
 data:
   mapRoles: |
     - rolearn: &amp;lt;ARN of instance role (not instance profile)&amp;gt;
       username: system:node:{{EC2PrivateDNSName}}
       groups:
         - system:bootstrappers
         - system:nodes
     - rolearn: &amp;lt;ARN of some-other-role&amp;gt;
       username: some-other-role
       groups:
         - system:masters
   mapUsers: |
     - userarn: &amp;lt;ARN of other-user&amp;gt;
       username: other-user
       groups:
         - system:masters
[@trurl ~] KUBECONFIG=~/.kube/config.d/my-cluster kubectl apply -f /tmp/aws-auth-cm
configmap &quot;aws-auth&quot; configured
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;I added &lt;code class=&quot;highlighter-rouge&quot;&gt;some-other-role&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;other-user&lt;/code&gt; to the configuration, and
for simplicity added them both to &lt;code class=&quot;highlighter-rouge&quot;&gt;system:masters&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;authorization&quot;&gt;Authorization&lt;/h2&gt;

&lt;p&gt;There is nothing EKS-specific in authorization process; in particular,
any permissions or policies attached to IAM Users don’t mean anything,
you’re talking directly to Kubernetes API server, and it uses IAM only
for authentication.&lt;/p&gt;

&lt;p&gt;EKS clusters run in &lt;abbr title=&quot;Role-Based Access Control&quot;&gt;RBAC&lt;/abbr&gt; mode, meaning you grant permissions by
binding roles to identities.  In above examples I did not have to do
that because I depended on &lt;code class=&quot;highlighter-rouge&quot;&gt;aws-iam-authenticator&lt;/code&gt; to return the
&lt;code class=&quot;highlighter-rouge&quot;&gt;system:masters&lt;/code&gt; group for all identities I used, and that is a
built-in group that has full permissions to the cluster.  That’s the
simplest thing and most likely what you want to do for manual
interaction with the cluster anyway.  For cases where that’s not
enough and you would prefer to grant less permissions to an account,
there are much better guides, in particular
&lt;a href=&quot;https://kubernetes.io/docs/reference/access-authn-authz/rbac/&quot;&gt;Using &lt;abbr title=&quot;Role-Based Access Control&quot;&gt;RBAC&lt;/abbr&gt; Authorization&lt;/a&gt;
in Kubernetes docs.&lt;/p&gt;

</description>
        <pubDate>Thu, 12 Jul 2018 00:00:00 +0200</pubDate>
        <link>/2018/07/12/eks-auth.html</link>
        <guid isPermaLink="true">/2018/07/12/eks-auth.html</guid>
        
        <category>tech,kubernetes,eks</category>
        
        
      </item>
      
    
      
      <item>
        <title>My main code quality guideline</title>
        <description>&lt;p&gt;…is not succintness, removing duplication, reducing the number of
nested loops, any particular naming scheme or a style guide.  It is,
instead, asking myself the question &lt;b&gt;how tricky will the code be to
understand if I have to fix it after switching to something else for
half a year?&lt;/b&gt;&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;Or to put it another way: assuming I forget this code completely and
have to return to fix a bug in some function, how much of the
surrounding module|library|app do I have to get in my head to see what
is going on?&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;[W]e want to establish the idea that a computer language is not just
a way of getting a computer to perform operations but rather that it
is a novel formal medium for expressing ideas about
methodology. Thus, programs must be written for people to read, and
only incidentally for machines to execute.&lt;/p&gt;

  &lt;p&gt;&lt;span class=&quot;source&quot;&gt;Abelson &amp;amp; Sussman, Structure and Interpretation of Computer Programs&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I know for a fact that most of the code I write will at some point be
modified, fixed, and extended by someone who does not know it.  In
many cases that someone will be me after switching to something else
for long enough to forget the code completely.  It makes perfect sense
to optimise for that by attempting to minimise the cost of
understanding it.&lt;/p&gt;

&lt;p&gt;It sounds blurry, but that’s only because it is.  From this angle and
with a bit of a squint coding starts to look like creating prose with
the additional requirement of the result being executable, and
suddenly we get all the blurriness and difficulty of writing
English&lt;sup id=&quot;fnref:language&quot;&gt;&lt;a href=&quot;#fn:language&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.  There are no strict rules that guarantee
readability, just general guidelines, rules of thumb, and the hope
that I can tap into some context I share with future maintainers.&lt;/p&gt;

&lt;h2 id=&quot;assumptions&quot;&gt;Assumptions&lt;/h2&gt;

&lt;p&gt;In the case of prose you can assume the reader understands the
language and has certain level of common knowledge.  In the case of
code, I assume that they know the language fairly well; not just the
syntax, but also conventions used by its standard library.&lt;/p&gt;

&lt;p&gt;These assumptions are not always met, but that’s okay; in that case if
I manage to make my code conform to conventions it will help the
reader build the right intuition for the community; otherwise I would
be one of people responsible for the deterioration of quality within
it, and would actively get in someone’s way to improve their skills.&lt;/p&gt;

&lt;h2 id=&quot;conventions&quot;&gt;Conventions&lt;/h2&gt;

&lt;p&gt;Conventions are good.  Conventions are decisions for free.
Conventions are lower cognitive load when reading code &lt;em&gt;and&lt;/em&gt; when
writing it.  Conventions are patterns and people are great at
recognising those.  Use them.  Don’t clash with them.&lt;/p&gt;

&lt;p&gt;If something looks similar to what people already know and understand,
they will naturally assume it behaves similar.  Use that whenever
possible, treat it as a way to avoid having to explain things.&lt;/p&gt;

&lt;p&gt;You have multiple levels of conventions at your disposal: language
(idioms and patterns established by the standard library), framework
(Django introduced some good conventions early on), project, module.
The higher level you manage to use, the easier it will be for random
programmer to understand the reference.&lt;/p&gt;

&lt;h2 id=&quot;vocabulary&quot;&gt;Vocabulary&lt;/h2&gt;

&lt;p&gt;You create it whether you want it or not, you might as well use that
to your advantage.  Function and variable names are roughly verbs and
nouns, when someone tries to understand your code that’s how they are
going to read it.&lt;/p&gt;

&lt;p&gt;Good names make it easier to reason about the code.  Bad names require
the reader to go read some other piece of code to understand what’s
going on.  Very bad names are actively misleading.&lt;/p&gt;

&lt;h2 id=&quot;inheritance&quot;&gt;Inheritance&lt;/h2&gt;

&lt;p&gt;It’s a big one.  Many class hierarchies obscure the flow of code and
make discovery more difficult.&lt;/p&gt;

&lt;p&gt;And sure, it’s just as easy to come up with examples of bad function
composition, but the common approach of “here’s a class that
implements the top-level code flow, override pieces in subclasses to
tweak or configure it” requires the reader to have a fairly good
understanding of the superclass, and makes it trickier to follow the
code.&lt;/p&gt;

&lt;p&gt;It’s sometimes worth it (the entire &lt;code class=&quot;highlighter-rouge&quot;&gt;unittest&lt;/code&gt; family is a
particularly good example: test cases allow customization by
overriding a very limited set of methods, and those are mostly
consistent across a large number of languages), more often it is not
(most modules are not &lt;code class=&quot;highlighter-rouge&quot;&gt;unittest&lt;/code&gt;), and the key point is to recognize
that the reversal of flow comes with high cognitive cost you need to
consider when using it.&lt;/p&gt;

&lt;h2 id=&quot;example-wrapping-a-well-known-function&quot;&gt;Example: wrapping a well-known function&lt;/h2&gt;

&lt;p&gt;Let’s say you find yourself writing the same piece of code around some
standard library function often and want to refactor that out.  For
example, my app does a lot of work on a set of data files in a
particular location and encoding, some reads and some writes,
something that might start as multiple calls to &lt;code class=&quot;highlighter-rouge&quot;&gt;open&lt;/code&gt; like this one:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;    &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DATA_DIR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'w'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'utf-8'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;do_something&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The first thing to go would probably be that repeated call to
&lt;code class=&quot;highlighter-rouge&quot;&gt;os.path.join&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;    &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path_to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'w'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'utf-8'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;do_something&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And if it wasn’t for that &lt;code class=&quot;highlighter-rouge&quot;&gt;encoding&lt;/code&gt; parameter I would leave it as is,
without wrapping that &lt;code class=&quot;highlighter-rouge&quot;&gt;open(path_to(filename), &amp;lt;mode&amp;gt;)&lt;/code&gt; in another
function, because it’s idiomatic and most Python programmers will
immediately understand what’s going on.  That’s much more value than
removing this particular piece of duplication.&lt;/p&gt;

&lt;p&gt;Having to specify encoding changes things because unlike with file
name and mode, omitting it by mistake leads to a bug that might go
unnoticed for a while.  So let’s create a wrapper here.&lt;/p&gt;

&lt;p&gt;The combination of function name and interface is going to be
important.  The name in particular might take a while, but it’s worth
it to get it right because this is how you lead the reader to
understanding what is going on.&lt;/p&gt;

&lt;p&gt;I want something based on &lt;code class=&quot;highlighter-rouge&quot;&gt;open&lt;/code&gt; to use associations with the
built-in.  &lt;code class=&quot;highlighter-rouge&quot;&gt;open_data_file&lt;/code&gt; might work, but the word &lt;code class=&quot;highlighter-rouge&quot;&gt;data&lt;/code&gt; is very
ambiguous and in most situations you’re better off with something more
specific.  Are our files part of configuration?  Cache?  Static files
for a website?  Let’s assume configuration files.&lt;/p&gt;

&lt;p&gt;Next thing to do is get the interface right.  Write how you would like
to use the function before implementing it.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;    &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;open_config_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'w'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;do_something&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Does it read right?  If I see it in code I open for the first time in
my life, will it make it easier for me to understand it?  Hopefully.
I pushed &lt;code class=&quot;highlighter-rouge&quot;&gt;encoding&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;path_to&lt;/code&gt; into &lt;code class=&quot;highlighter-rouge&quot;&gt;open_config_file&lt;/code&gt;, tried to
choose a name that might convey some idea about what’s going on, but
otherwise I kept the interface as close to &lt;code class=&quot;highlighter-rouge&quot;&gt;open&lt;/code&gt; as possible to make
it easier to understand by anyone who already knows that one.&lt;/p&gt;

&lt;p&gt;So now I can implement it.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;open_config_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'r'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'utf-8'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kwargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path_to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kwargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;It ended up being a one-liner that builds the right file name and
overrides the default value of one of &lt;code class=&quot;highlighter-rouge&quot;&gt;open&lt;/code&gt; arguments.&lt;/p&gt;

&lt;h2 id=&quot;example-unit-tests&quot;&gt;Example: unit tests&lt;/h2&gt;

&lt;p&gt;This is fairly common in projects I’ve seen:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ViewTest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ModuleSpecificTestCase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setUp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MyModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;objects&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;intialization&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c&quot;&gt;# some more tests here&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_the_view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;instance&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;do_something&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;assertEqual&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;instance&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'expected value'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;There’s a piece of initialisation that is [probably] used by multiple
test cases.  Some of them might depend on it by using &lt;code class=&quot;highlighter-rouge&quot;&gt;self.instance&lt;/code&gt;,
others might depend on it indirectly by assuming it’s in the DB and
taking it into account when counting objects or checking results of
non-ORM queries.  Those test cases are now coupled and it makes
changes more difficult.&lt;/p&gt;

&lt;p&gt;Sometimes that assignment will migrate to a middle class in the
hierarchy, in which case it’s even less convenient to get all the code
necessary to understand a test case on the screen at the same time.
And then since the assignment is in one of superclasses, you might
want to introduce a way to customize it, and sometimes this happens:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ModuleSpecificTestCase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unittest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TestCase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;instance_options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setUp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MyModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;objects&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;intialization&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                               &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;instance_options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ViewTest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ModuleSpecificTestCase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;instance_options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'attribute'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'override'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_the_view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;instance&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;do_something&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;assertEqual&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;instance&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'expected value'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Or, alternatively:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ModuleSpecificTestCase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unittest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TestCase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setUp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create_instance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;create_instance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;# override to create custom models&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MyModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;objects&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;intialization&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ViewTest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ModuleSpecificTestCase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;create_instance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MyModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;objects&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ViewTest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;specific&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;initialization&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_the_view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;instance&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;do_something&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;assertEqual&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;instance&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'expected value'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;At this point those attempts to reduce code duplication end up creating
more complexity than they prevent.  What I try to do instead is avoid
passing data between &lt;code class=&quot;highlighter-rouge&quot;&gt;setUp&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;test_*&lt;/code&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ViewTest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ModuleSpecificTestCase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;create_instance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;objects&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;intialization&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_the_view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create_instance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;instance&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;do_something&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;assertEqual&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;instance&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'expected value'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;At first glance this might look like going the wrong way: my test is
now longer, and having to do additional work per test is definitely
some cost.  On the other hand, I gain:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Readability: I have the whole data flow in one place, and with the
right naming for helper methods like &lt;code class=&quot;highlighter-rouge&quot;&gt;create_instance&lt;/code&gt; (this one is
generic, but for non-generic initialization data I would choose a
name that gives a hint what is special about the instance) I have
more information in the test.&lt;/li&gt;
  &lt;li&gt;Decoupling: in the first version, &lt;code class=&quot;highlighter-rouge&quot;&gt;setUp&lt;/code&gt; controlled the data that
went into &lt;code class=&quot;highlighter-rouge&quot;&gt;instance&lt;/code&gt;.  In the second, individual tests do that; if
some of them need slightly different data I can easily add that by
having &lt;code class=&quot;highlighter-rouge&quot;&gt;create_instance&lt;/code&gt; allow overriding defaults, eg
&lt;code class=&quot;highlighter-rouge&quot;&gt;create_instance(some_field='override')&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Clarity: now I know for certain which tests really use this
instance.  It’s opt-in.&lt;/li&gt;
  &lt;li&gt;Flexibility: now I can have a test that creates multiple instances.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To me it’s a win.&lt;/p&gt;

&lt;h2 id=&quot;least-maintainer-astonishment&quot;&gt;Least maintainer astonishment&lt;/h2&gt;

&lt;p&gt;UX world has the &lt;i&gt;Principle of Least Astonishment&lt;/i&gt;.  It’s
about understanding that users build some expectations based on what
the system is supposed to do, and how it looks and behaves, and trying
to match those.&lt;/p&gt;

&lt;p&gt;I like that rule a lot, and try to apply it to programming: people
reading my code will use patterns and conventions matching what I
wrote to reason about it.  I can try to work with that to make things
easier to understand.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:language&quot;&gt;

      &lt;p&gt;In one of previous lives I had to [briefly] deal with code created
by merger of three teams who used English, German, and French
respectively for their code and comments.  I don’t remember trying
to make sense of that mess fondly.  Stick to English, please. &lt;a href=&quot;#fnref:language&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Fri, 21 Apr 2017 00:00:00 +0200</pubDate>
        <link>/2017/04/21/code-quality.html</link>
        <guid isPermaLink="true">/2017/04/21/code-quality.html</guid>
        
        <category>tech,programming</category>
        
        
      </item>
      
    
      
      <item>
        <title>Remote work</title>
        <description>&lt;p&gt;File under “blog posts I had on my TODO list for a long time, but now
that I found it written by someone else I can just link to it”
category.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://medium.com/@yanismydj/why-i-only-work-remotely-2e5eb07ae28f&quot;&gt;“Why I only work remotely”&lt;/a&gt; - Yah Lhert&lt;/p&gt;

&lt;p&gt;This is precisely why I have been strictly filtering out all job
offers that require majority of work to happen on site, at a physical
office.&lt;/p&gt;
</description>
        <pubDate>Thu, 19 Jan 2017 00:00:00 +0100</pubDate>
        <link>/2017/01/19/remote-work.html</link>
        <guid isPermaLink="true">/2017/01/19/remote-work.html</guid>
        
        <category>tech,organizations</category>
        
        
      </item>
      
    
      
      <item>
        <title>V-REP kinect + ROS + rgbdslam</title>
        <description>&lt;p&gt;&lt;img src=&quot;/post-images/vrep-kinect.png&quot; alt=&quot;vrep-kinect&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In which I share negligible amounts of code resulting from surprisingly
time consuming research to get it right, along with some gotchas
encountered on the way.  In the hope it will save someone else the
time: here’s an example of how you hook up a kinect simulated by V-REP
to rgbdslam.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;Spoiler: you’ll need to modify the ros_plugin bundled with v-rep and
use a short Lua script to set up publishers.&lt;/p&gt;

&lt;h2 id=&quot;the-issue&quot;&gt;The issue&lt;/h2&gt;

&lt;p&gt;Publish the minimal set of &lt;a href=&quot;http://ros.org/&quot;&gt;ROS&lt;/a&gt; topics required to run &lt;a href=&quot;http://wiki.ros.org/rgbdslam&quot;&gt;rgbdslam&lt;/a&gt; off
of Kinect simulated in &lt;a href=&quot;http://www.coppeliarobotics.com&quot;&gt;V-REP&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As a minimum, rgbdslam requires:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://docs.ros.org/api/sensor_msgs/html/msg/Image.html&quot;&gt;sensor_msgs/Image&lt;/a&gt; topic with RGB image&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://docs.ros.org/api/sensor_msgs/html/msg/CameraInfo.html&quot;&gt;sensor_msgs/CameraInfo&lt;/a&gt; topic with camera geometry data&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://docs.ros.org/api/sensor_msgs/html/msg/Image.html&quot;&gt;sensor_msgs/Image&lt;/a&gt; topic with depth image&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In practice you’ll probably want to also send at least&lt;/p&gt;

&lt;h2 id=&quot;the-plugins&quot;&gt;The plugins&lt;/h2&gt;

&lt;p&gt;V-REP comes with two different ROS plugins: &lt;a href=&quot;http://www.coppeliarobotics.com/helpFiles/en/rosInterfaceOverview.htm&quot;&gt;RosPlugin&lt;/a&gt; and &lt;a href=&quot;http://www.coppeliarobotics.com/helpFiles/en/rosInterf.htm&quot;&gt;RosInterface&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;RosInterface is built to resemble the ROS API to a large degree: your
Lua scripts work with subscribers and publishers directly, sending and
receiving messages very much like you would in your C++ or Python ROS
code.&lt;/p&gt;

&lt;p&gt;RosPlugin, on the other hand, is not as generic, but – in the part
that is relevant here – lets you set up fire-and-forget publishers
that will stream data without any further work on Lua side.  Which is
awesome because it means no need to marshal the data to and from Lua,
everything happens on C++ side.&lt;/p&gt;

&lt;p&gt;V-REP documentation says to “make sure not to mix up” the two, which
sounds like a warning about plugin clash but turns out to mean just
that they are two separate things.  It is perfectly okay to use them
both at the same time, and it makes a lot of sense: use RosPlugin to
stream high-bandwidth image data, and RosInterface to send or receive
lower-bandwidth control messages that are easier to handle in Lua.&lt;/p&gt;

&lt;p&gt;In this case you’ll only need RosPlugin.&lt;/p&gt;

&lt;h2 id=&quot;the-plugin-tweak&quot;&gt;The plugin tweak&lt;/h2&gt;

&lt;p&gt;RosPlugin provides &lt;strong&gt;almost&lt;/strong&gt; everything necessary to pull it off: out
of the box it can publish the RGB and camera geometry data, but falls
short when it comes to depth information: it can stream it as
&lt;a href=&quot;https://github.com/marcinkaszynski/vrep-ros-plugins/blob/master/ros_packages/vrep_common/msg/VisionSensorDepthBuff.msg&quot;&gt;vrep_common/VisionSensorDepthBuff&lt;/a&gt;, or &lt;a href=&quot;http://docs.ros.org/api/sensor_msgs/html/msg/PointCloud2.html&quot;&gt;sensor_msgs/PointCloud2&lt;/a&gt;, but
rgbdslam really needs it as &lt;a href=&quot;http://docs.ros.org/api/sensor_msgs/html/msg/Image.html&quot;&gt;sensor_msgs/Image&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Apply
&lt;a href=&quot;https://github.com/marcinkaszynski/vrep-ros-plugins/commit/3e3c1c22703a14e55cf32aff4603c23f82b2a5ab&quot;&gt;this changeset&lt;/a&gt;
to RosPlugin to add a depth Image publisher.&lt;/p&gt;

&lt;p&gt;Build it, put the resulting dylib/so in the same directory with the
main &lt;code class=&quot;highlighter-rouge&quot;&gt;vrep&lt;/code&gt; library, and remember to tell it how to find &lt;code class=&quot;highlighter-rouge&quot;&gt;roscore&lt;/code&gt;.
You should see line like &lt;code class=&quot;highlighter-rouge&quot;&gt;Plugin 'Ros': load succeeded.&lt;/code&gt; in output:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;@trurl ~] &lt;span class=&quot;nv&quot;&gt;ROS_MASTER_URI&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;http://roshost:11311/ /Applications/vrep/vrep.app/Contents/MacOS/vrep
Using the default Lua library.
Loaded the video compression library.
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;...]
Plugin &lt;span class=&quot;s1&quot;&gt;'Ros'&lt;/span&gt;: loading...
Plugin &lt;span class=&quot;s1&quot;&gt;'Ros'&lt;/span&gt;: load succeeded.
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;...]
Initialization successful.&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;div style=&quot;clear: both&quot; /&gt;

&lt;h2 id=&quot;the-simulation&quot;&gt;The simulation&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/post-images/vrep-kinect-over-dr12.jpg&quot; alt=&quot;vrep-kinect-over-dr12&quot; width=&quot;40%&quot; style=&quot;float: right; margin-left: 1em&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Being lazy, I just bolted Kinect on top of a DR12 robot from one of
examples bundled with V-REP.  Where by “bolted on top” I mean “have it
hover 1m above the robot to get a better view.”&lt;/p&gt;

&lt;p&gt;Throw in some objects around the robot so that SLAM has some details
to pick up and that’s it.&lt;/p&gt;

&lt;div style=&quot;clear: both&quot; /&gt;

&lt;p&gt;And then, to configure publishers:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-lua&quot; data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setup_kinect_sensor_topics&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prefix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;colorCam&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;depthCam&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;simExtROS_enablePublisher&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prefix&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;rgb/image_rect_color&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                             &lt;span class=&quot;n&quot;&gt;simros_strmcmd_get_vision_sensor_image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                             &lt;span class=&quot;n&quot;&gt;colorCam&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;simExtROS_enablePublisher&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prefix&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;rgb/camera_info&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                             &lt;span class=&quot;n&quot;&gt;simros_strmcmd_get_vision_sensor_info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                             &lt;span class=&quot;n&quot;&gt;colorCam&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

   &lt;span class=&quot;n&quot;&gt;simExtROS_enablePublisher&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prefix&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;depth/image_rect&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                             &lt;span class=&quot;n&quot;&gt;simros_strmcmd_get_vision_sensor_depth_image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                             &lt;span class=&quot;n&quot;&gt;depthCam&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sim_call_type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sim_childscriptcall_initialization&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;setup_kinect_sensor_topics&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/sim/kinect1/&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                              &lt;span class=&quot;n&quot;&gt;simGetObjectHandle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;kinect_rgb&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
                              &lt;span class=&quot;n&quot;&gt;simGetObjectHandle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;kinect_depth&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Where &lt;code class=&quot;highlighter-rouge&quot;&gt;kinect_rgb&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;kinect_depth&lt;/code&gt; are the names of simulated
sensors.&lt;/p&gt;

&lt;h2 id=&quot;rgbdslam-configuration&quot;&gt;Rgbdslam configuration&lt;/h2&gt;

&lt;p&gt;Use the &lt;code class=&quot;highlighter-rouge&quot;&gt;rgbdslam.launch&lt;/code&gt; bundled with &lt;code class=&quot;highlighter-rouge&quot;&gt;rgbdslam&lt;/code&gt;, changing the
parameters that specify input topics:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;param&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;config/camera_info_topic&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/sim/kinect1/rgb/camera_info&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;param&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;config/topic_image_mono&quot;&lt;/span&gt;  &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/sim/kinect1/rgb/image_rect_color&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;param&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;config/topic_image_depth&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/sim/kinect1/depth/image_rect&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;the-result&quot;&gt;The result&lt;/h2&gt;

&lt;p&gt;The room in V-REP:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/post-images/vrep-kinect-entire-scene.jpg&quot; alt=&quot;vrep-kinect-entire-scene&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The same scene, as seen by rgbdslam after some rotation:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/post-images/vrep-kinect-to-rgbdslam.jpg&quot; alt=&quot;vrep-kinect-to-rgbdslam&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I have no idea why the point cloud reconstructed by rgbdslam swaps red
and blue channels, since – as visible in the bottom row – input
images have them the right way, but it’s not important as all I need
from SLAM as output is odometry.&lt;/p&gt;

</description>
        <pubDate>Sat, 10 Sep 2016 00:00:00 +0200</pubDate>
        <link>/2016/09/10/vrep-ros-rgbdslam-simulated-kinect.html</link>
        <guid isPermaLink="true">/2016/09/10/vrep-ros-rgbdslam-simulated-kinect.html</guid>
        
        <category>tech,robots,vrep</category>
        
        
      </item>
      
    
      
      <item>
        <title>Reset</title>
        <description>&lt;p&gt;Being fed up with WordPress I’m switching my home page over to static
files generated by Jekyll.  Which means that old blog posts go into
the “let’s see when I feel nostalgic enough to put in the work to
convert them” limbo for the time being.&lt;/p&gt;
</description>
        <pubDate>Fri, 09 Sep 2016 00:00:00 +0200</pubDate>
        <link>/2016/09/09/reset.html</link>
        <guid isPermaLink="true">/2016/09/09/reset.html</guid>
        
        <category>administrivia</category>
        
        
      </item>
      
    
  </channel>
</rss>
