Background
Prior to taking a software engineering-focussed summer internship in 2019, I was dead-set on becoming a network engineer - I studied for my Cisco Certified Network Associate (CCNA) in my own free time alongside university and continued to delve into the professional-level content afterwards, those who knew me back then will likely recall how much of a Cisco fanatic I was. During this time, I barely did any coding at all. I knew some basic Python, about enough to pass the courses at university, but nothing past this. My GitHub was completely empty, aside from a single markdown repository which contained some networking notes for a class I taught to the 1st year students.
Another moment which heavily reinforced the fact I needed to start coding more often, was from absolutely crashing and burning in an interview. This interview was for a company I was extremely excited to attempt an internship with, the interview was split into two sections: networking and programming. I can feel confident in saying that I crushed the networking section, after all I was obsessed with it, especially for someone who was in their 2nd year of university at the time. Things took a nosedive once I was handed a laminated sheet of Python code and asked to say what it did and whether there was anything wrong - I can’t recall the exact problem, but I do know that it was quite simple, yet I had absolutely no clue whatsoever. In all honesty, I was quite embarrassed and didn’t know what to do, panic set in and I told the interviewer that I wasn’t sure and didn’t press much further than that, this was certainly a mistake. However, a real positive emerged from this in that I started to code everyday, I discovered a passion for software engineering and eventually set eyes on the DevOps takeover and Google’s Site Reliability Engineering-type roles when looking at how to make a start on building my career.
After I had been coding for a year or so, I had a couple of small projects on GitHub and graduated university, received an excellent mark on my final year project, and was working full time as a DevOps Engineer. I continued to notice a common theme among many software engineers in that they would say something along the lines of “contributing to open source is the best way to become a better developer or get hired as one.”, I can absolutely say that the idea of making a meaningful contribution to a project like Kubernetes is still fascinating to me, but doing this as your first contribution is likely out of reach - at least it certainly was for me. A problem that plagued me was checking for issues with a tag of good-first-issue
and noticing they were taken relatively quickly and assigned to others, it seems that you need to be fast to act on this front with large projects. Fast forward to present day and I made it a solid goal to contribute to a project, especially one which was closely related to my day job, no matter how small the contribution, this brings us nicely to the projects I contributed to: go-jsonnet and kaniko.
Contributions
go-jsonnet
Jsonnet is a data templating language used by some of the top companies you might recognise: Google, Bitnami, Grafana Labs, and many other. The original tool is written in C++; however, there is a feature complete implementation in Go.
As my day job involves heavy use of jsonnet
, and subsequently go-jsonnet
, it made the most sense to attempt my first contribution with something I am familiar with. When I say a small contribution, it absolutely was the case, this was a 3 line change which provided a simple conditional check and sensible error message if satisfied, this fixed a panic error. Even here, it drew on reading the C++ implementation and adding similar functionality into the Go code. Nevertheless, when I got an email that this had been merged, I was ecstatic - I had finally made a contribution to open source that wasn’t fixing a typo in a README
file.
From this, I’ve learnt that it does not matter what kind of contribution you make, merely starting something is the key. By making a small contribution, such as adding a single if statement in this case, might provide you enough confidence to push you onto making further contributions to the same or other projects in the future. This is the effect it had on me, seeing that a small change was merged made me want to do another, leading onto my next contribution.
kaniko
Kaniko enables the creation of container images without access a Docker daemon, this means that images can be built where a machine does not have elevated privileges, such as within a best practices Kubernetes cluster.
After my previous contribution, I became hooked on the idea of having it merged, since I knew that it was now possible, it was a great feeling to have made a difference to a project that wasn’t only used or created by me. From here, I wanted to make more than a small change, perhaps even something to do with a feature or minor enhancement. The feature which I picked up was to alter a hard coded directory into being configurable by a user, described here, this sounded relatively simple to me; however, this turned out to be a larger change than anticipated compared to my initial survey of the issue, but I was helped along the way by one of the maintainers, a full record of the conversation and my ongoing thoughts are available on the pull request for those who are interested. The change sprawled multiple files and included adding another integration test, looking back this was quite trivial, but making such sweeping changes on an unfamiliar and large project is rather daunting. In the end, the changes and my test passed the pipeline checks and the contribution was merged. This was a pretty standout moment, as I worked on this issue over approximately 2 weeks, after I initially thought it would take a single evening, and it meant that I made a reasonably significant contribution, by way of implementing a feature to a large project.
With this, I learnt that being stuck on a contribution is absolutely okay. The maintainers of the project care about it and will want to help you out where they can, there were certainly things that I wasn’t certain about and realised that it is better to ask for help than to charge ahead and have to undo a bunch of work. This comes with the caveat that constantly asking for help is likely not welcomed much, but attempting a solution, getting stuck, explaining what you have tried, and then what you believe you have to do is completely acceptable. As the old saying goes “you don’t know what you don’t know”, meaning that on a large project where the intricacies are unfamiliar, there are bound to be things that are unknown and that is absolutely okay.
Update 29/04/2022: After my pull request was merged, there were a few follow up comments which were concerned with a problem in that the KANIKO_DIR
environment variable was unused, this was because of an oversight on my part whereby I was only passing the config.KanikoDir
flag, rather than an option which was populated by either the flag or environment variable. I addressed this in a follow-up pull request to correct the issue.
Whilst addressing this problem, I also ran into an issue where the test I introduced for checking the ability to move away from the hard-coded /kaniko
directory was failing with invalid cross-device link
, this is caused by the inability to use os.Rename
to rename/move directories across partitions - if we dig into this a little more, it makes sense that this is an issue, since when we rename or move a directory/file, it is still on the same drive, but the operating system points to a different location, whereas when the /kaniko
directory moves to a new partition, the contents cannot simply be pointed to from another location. Therefore, it was necessary to directly copy the contents into the new directory, the kaniko
project nicely provides a simple way to do this with util.CopyDir
and then remove the contents of the old directory. I was contemplating whether we introduce a way to know whether the chosen kaniko-dir
is on the same drive or not, but this did not seem necessary as the pull request was merged without further comments. This may be something which is introduced in a later change, for specific performance requirements.
This was a great experience in needing to address a bug in a larger project, especially from causing it myself.