Migrated T.I.L. posts to blog

Signed-off-by: Marcus Noble <github@marcusnoble.co.uk>
This commit is contained in:
Marcus Noble 2022-06-22 20:04:49 +01:00
parent 080912401b
commit 652cee0e2e
Signed by: AverageMarcus
GPG Key ID: B8F2DB8A7AEBAF78
11 changed files with 388 additions and 0 deletions

View File

@ -0,0 +1,57 @@
---
layout: post.html
title: "T.I.L. Tekton Multi-Arch Image Builds"
summary: "Today I Learnt: Tekton Multi-Arch Image Builds"
date: 2020-09-13T01:49:37+01:00
tags: til tekton docker
---
Using Buildkit to build multi-arch compatible images without Docker daemon:
```yaml
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: docker-build-and-publish
namespace: tekton-pipelines
spec:
- name: IMAGE
type: string
resources:
inputs:
- name: src
type: git
steps:
- name: build-and-push
workingDir: /workspace/src
image: moby/buildkit:latest
env:
- name: DOCKER_CONFIG
value: /root/.docker
command:
- sh
- -c
- |
buildctl-daemonless.sh --debug \
build \
--progress=plain \
--frontend=dockerfile.v0 \
--opt filename=Dockerfile \
--opt platform=linux/amd64,linux/arm/7,linux/arm64 \
--local context=. \
--local dockerfile=. \
--output type=image,name=$(params.IMAGE),push=true \
--export-cache type=inline \
--import-cache type=registry,ref=$(params.IMAGE)
securityContext:
privileged: true
volumeMounts:
- name: docker-config
mountPath: /root/.docker/config.json
subPath: config.json
volumes:
- name: docker-config
secret:
secretName: docker-config
```

View File

@ -0,0 +1,26 @@
---
layout: post.html
title: "T.I.L. YAML multiline values"
summary: "Today I Learnt: YAML multiline values"
date: 2020-09-17
tags: til yaml
---
After using YAML for a long time, for many, many Kubernetes manifest files, I have today learnt that it contains two multiline value types (called scalars):
```yaml
scalarsExample:
literalScalar: |
Literal scalars use the pipe (`|`) to denote the start of the value with the scope indicated by indentation.
All content here is used literally, with newlines preserved.
<-- This is the start of the line, the spaces before this aren't included in the literal.
This should be used when storing things like file contents (e.g. in a ConfigMap)
foldedScalar: >
Folded scalars use the greater-than symbol (`>`) to denote the start of the value with the scope indicated by indentation.
Unlike literal scalars newlines aren't preserved and instead converted into spaces.
<-- This is the start of the line, the spaces before this aren't included in the value.
This should be used when you'd normally use a string but the contents are long and wrapping makes it easier to read.
```
> More info: [https://yaml.org/spec/1.2/spec.html#id2760844](https://yaml.org/spec/1.2/spec.html#id2760844)

View File

@ -0,0 +1,27 @@
---
layout: post.html
title: "T.I.L. Split on spaces in Go"
summary: "Today I Learnt: Split on spaces in Go"
date: 2020-09-18
tags: til go golang
---
While looking to split a multiline and space separated string and not having any luck with `strings.Split()` I came across this somewhat oddly names function:
```go
import (
"fmt"
"strings"
)
func main() {
input := `This is
a multiline, space
separated string`
output := strings.Fields(input)
fmt.Println(output) // ["This", "is", "a", "multiline,", "space", "separated", "string"]
}
```

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,12 @@
---
layout: post.html
title: "T.I.L. Don't Reuse API Keys"
summary: "Today I Learnt: Don't Reuse API Keys"
date: 2020-10-03T12:49:37+01:00
tags: til cli credentials
---
Not a technical post today, more of a reminder to myself not to reuse API keys for different purposes. In this instance I reset the credentials I had labelled "Terraform" which I just so happened to also be using In [Harbor](https://goharbor.io/) to connect to my S3 bucket.
Que 2 hours of me trying to figure out why I couldn't pull or push any images.

View File

@ -0,0 +1,35 @@
---
layout: post.html
title: "T.I.L. Named returns in Go functions"
summary: "Today I Learnt: Named returns in Go functions"
date: 2020-10-05T15:50:00
tags: til golang
---
While debugging some issues I was having with the AWS Golang SDK I discovered it was possible to name your function return values (pointers) and then set them within your function body without needing to explicitly return them at the end.
E.g.
```go
package main
import "fmt"
var greeting = "Hello, world"
func main() {
fmt.Println(*test())
}
func test() (returnVal *string) {
returnVal = &greeting
return
}
```
Note the single `return` at the end of the function.
I'm not really sure if this is a useful feature, feels more like it'd make code harder to read and could lead to some pretty nasty unintended mistakes when someone unfamilure with the code comes to make changes. Interesting either way.
I'd be interested if anyone has any examples of where this kind of thing is beneficial.

View File

@ -0,0 +1,60 @@
---
layout: post.html
title: "T.I.L. Golang's append mutates the provided array"
summary: "Today I Learnt: Golang's append mutates the provided array"
date: 2020-10-30T12:49:37+01:00
tags: til golang
---
A word of warning when using `append()` in Golang...
When using a slice of an array as the first parameter when calling `append` if the length of the resulting array is less than that of the initial array then the values in the initial array will be overridden by the new values being appended.
For example, if we use `append` to take the first two values from the array called `first` and all the values from the array called `second` we can see that `first` is being mutated unexpectedly.
```go
package main
import "fmt"
func main() {
first := []int{0, 1, 2, 3, 4, 5, 6}
second := []int{4, 5, 6}
fmt.Println(first)
// -> [0 1 2 3 4 5 6]
fmt.Println(append(first[:2], second...))
// -> [0 1 4 5 6]
fmt.Println(first)
// -> [0 1 4 5 6 4 5 6]
}
```
This is _only_ an issue when the resulting array is shorter than the array passed in as the first parameter.
**Update:**
It turns out this is expected behavior (see [github.com/golang/go/issues/28780#issuecomment-438428780](https://github.com/golang/go/issues/28780#issuecomment-438428780)) and a side-effect of how slices work in Go.
A slice (what we're producing when using the `[:2]`) can be thought of as a view onto an array. So when making changes to a slice you're really just making changes to that part of the array it is pointed to. By default slices are dynamic in size so if you go past the end of the slice you still continue along the array if it has more entries.
To avoid this happening you can specify a third value in the slice that sets the fixed length of the slice. E.g.
```go
package main
import "fmt"
func main() {
first := []int{0, 1, 2, 3, 4, 5, 6}
second := []int{4, 5, 6}
fmt.Println(first)
// -> [0 1 2 3 4 5 6]
fmt.Println(append(first[:2:2], second...))
// -> [0 1 4 5 6]
fmt.Println(first)
// -> [0 1 2 3 4 5 6]
fmt.Println("Much better :)")
}
```

View File

@ -0,0 +1,22 @@
---
layout: post.html
title: "T.I.L. How to get the favicon of any site"
summary: "Today I Learnt: How to get the favicon of any site"
date: 2020-11-10T09:49:37+01:00
tags: til
---
If you ever find yourself needing to display a small icon for a 3rd party URL but don't want to have to crawl the site to pull out the favicon URL then you can make use of a Google CDN:
```
https://s2.googleusercontent.com/s2/favicons?domain_url=https://marcusnoble.co.uk/
```
Example: ![](https://s2.googleusercontent.com/s2/favicons?domain_url=https://marcusnoble.co.uk/)
You can even provide any page, not just the root URL.
e.g. `https://s2.googleusercontent.com/s2/favicons?domain_url=https://marcusnoble.co.uk/2020-11-10-t-i-l-how-to-get-the-favicon-of-any-site/`
![](https://s2.googleusercontent.com/s2/favicons?domain_url=https://marcusnoble.co.uk/2020-11-10-t-i-l-how-to-get-the-favicon-of-any-site/)

View File

@ -0,0 +1,14 @@
---
layout: post.html
title: "T.I.L. Kubernetes label length"
summary: "Today I Learnt: Kubernetes label length"
date: 2021-04-20T15:10:37+01:00
tags: til kubernetes
---
It turns out that label _values_ in Kubernetes have a limit of 63 characters!
I discovered this today when none of my nodes seemed to be connecting to the control plane. Eventually discovered the hostname of the node was longer than 63 characters (mainly due to multiple subdomain levels) and so the `kubernetes.io/hostname` label being automtically added to the node was causing Kubernetes to reject it.
If you hit this like me, the hostname used for the label can be [overridden using the `--hostname-override` flag on kubelet](https://kubernetes.io/docs/reference/labels-annotations-taints/#kubernetesiohostname) or by setting the value of the label yourself with the `--node-labels` flag.

View File

@ -0,0 +1,78 @@
---
layout: post.html
title: "T.I.L. YAML keys allow for spaces in them"
summary: "Today I Learnt: YAML keys allow for spaces in them"
date: 2021-05-11
tags: til yaml
---
While browsing through some of [Frenck's](https://github.com/frenck) [Home Assistant Config](https://github.com/frenck/home-assistant-config) for ideas I came across [this interesting line of YAML](https://github.com/frenck/home-assistant-config/blob/a963e1cb3e2acf7beda2b466b334218ac27ee42f/config/integrations/automation.yaml#L7):
```yaml
---
# This handles the loading of my automations
#
# https://www.home-assistant.io/docs/automation/
#
automation: !include ../automations.yaml
automation split: !include_dir_list ../automations # <--
```
I found myself staring at this for a while, followed by searching the [Home Assistant](https://www.home-assistant.io/) documentation website to see if `split` was a special keyword I wasn't aware of.
And then it dawned on me! As all JSON is valid YAML, and JSON keys can be pretty much any string it makes sense that YAML supports it.
The above example converted to JSON using [json2yaml](https://www.json2yaml.com/convert-yaml-to-json) looks like this:
```json
{
"automation": "../automations.yaml",
"automation split": "../automations"
}
```
Knowing this, I decided to try out a few more variations to see what works...
YAML:
```yaml
---
123: Valid
---: also valid
5.5: yup! this too
#how about this?: nope, this is treated as a comment
//: yeah, totally valid
✨: yep!
[1]: Works
[1, 2]: Still works, treated as string
{another}: This one is interesting
```
JSON:
```json
{
"123": "Valid",
"---": "also valid",
"5.5": "yup! this too",
"//": "yeah, totally valid",
"✨": "yep!",
"[1]": "Works",
"[1, 2]": "Still works, treated as string",
"{\"another\"=>nil}": "This one is interesting"
}
```
Depending on the library used, varying results can be generated. For example, [yamlonline](https://yamlonline.com/) returns the following for the same input:
```json
{
"1": "Works",
"123": "Valid",
"---": "also valid",
"5.5": "yup! this too",
"//": "yeah, totally valid",
"✨": "yep!",
"1,2": "Still works, treated as string",
"[object Object]": "This one is interesting"
}
```

View File

@ -0,0 +1,41 @@
---
layout: post.html
title: "T.I.L. CLI flag handling in Bash using getopts"
summary: "Today I Learnt: CLI flag handling in Bash using getopts"
date: 2021-08-04T20:49:37+01:00
tags: til bash
---
I'm not sure how I've never come across this before but while looking through the [Scaleway Kosmos](https://www.scaleway.com/en/betas/#kuberneteskosmos) multi-cloud init script I dicovered the [`getopts`](https://www.man7.org/linux/man-pages/man1/getopts.1p.html) utility.
`getopts` makes it easier to parse arguments passed to a shell script by defining which letters your script supports. It supports both boolean and string style arguments but only supports single letter flags. (e.g. `-h` and not `--help`)
Example usage:
```sh
#!/bin/bash
NAME="World"
FORCE=false
showHelp() {
echo "Usage: example.sh [args]"
exit 0
}
while getopts 'hfn:' FLAG
do
case $FLAG in
h) showHelp ;;
f) FORCE=true ;;
n) NAME=$OPTARG ;;
*) echo "Unsupported argument flag passed" ;;
esac
done
echo "Hello, $NAME"
```
Notice the `:` following the `n`? That indicates that a value should follow the argument flag (`n` in this example) and will be made available as the `OPTARG` variable.