Git Merge Conflict Resolution Cheat Sheet

Some of git’s nomenclature can be confusing, especially since it is context dependent. Following are some TLDR;s for dealing with resolving merge conflicts in different scenarios.

–ours vs –theirs

The meaning of --ours vs --theirs can depend on whether you are doing a rebase or a merge.

Assuming that the feature branch is checked out

git merge developgit rebase develop
To keep changes from develop--theirs--ours
To keep changes from feature--ours--theirs

If, during a rebase there is a conflict and you know you want to take ALL of the changes from the branch you are rebasing onto, or ALL of the changes from the feature branch you can do the following (note that --ours vs --theirs follows the same semantics as described in the table above):

# Take all changes from the branch on which you are rebasing
git checkout --ours <path-to-file>

# Or, if you want to take all of the changes from the feature branch
git checkout --theirs <path-to-file>

# Then you can
git add <path-to-file>
git rebase --continue

Current Change vs. Incoming Change When Rebasing

Sometimes you may also see “Incoming” vs. “Current” changes when rebasing a feature branch. Assuming that the feature branch is checked out

git rebase develop
To keep changes from developAccept Current Change
To keep changes from featureAccept Incoming Change

If,

kubectl/k8s Cheat Sheet

  • Namespaces
    • List all namespaces: kubectl get namespace
    • Set a namespace: kubens <namespace-name>
    • See currently set namespace: kubens -c
  • Pods
    • List all pods: kubectl get pods
    • List all pods in specific namespace: kubectl get pods -n <namespace>
    • Kill a pod: kubectl delete pod <pod-name>
    • Describe/get details of pod: kubectl describe pods <pod-name>
    • InitContainers
      • Get logs: First describe the pod and look for the name of the init container. Then run kubectl logs <pod-name> -c <init-container-name>
  • Deployments
    • Get the deployment name from a pod: kubectl get pod -n -o jsonpath='{.metadata.ownerReferences[0].name}'
    • Get the manifest for a deployment: kubectl get deploy <deployment-name> -o yaml
    • Scaling a deployment: kubectl scale --replicas=<n> deployment/<deployment-name>
    • Gen env vars defined on a pod: kubectl exec <pod> -- env
    • Restart a deployment: kubectl -n <namespace> rollout restart deploy/<deployment-name>
  • ConfigMaps
    • View data in a ConfigMap: kubectl describe configmaps <name>
  • Port-Forwarding
    • kubectl port-forward <resource-type>/<name> <local-port>:<pod-port>
  • Secrets
    • Getting an unsealed secret: kubectl -n <namespace> get secret <secret-name> -o json | jq -r '.data | map_values(@base64d)'
  • List all resouces: kubectl api-resources

kubectl JSONPath — the must-know minimal set

Enough to read any jsonpath you’ll encounter and write the few that kubectl requires. For everything else, use -o json | jq.

ConstructMeansExample
{ }Expression delimiter; text outside braces is literal{.metadata.name}
.foo.barWalk into fields.status.phase
[*]All elements of an array.items[*]
[0]Index.items[0].metadata.name
{range …}{end}Loop over an array{range .items[*]}{.metadata.name}{"\n"}{end}
?(@.x=="y")Filter — pick array elements where a condition holds; @ = current element.status.conditions[?(@.type=="Ready")].status

The four common variants

# 1. pull one field
kubectl get pod mypod -o jsonpath='{.status.podIP}'

# 2. loop with literal text + newlines
kubectl get pods -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.phase}{"\n"}{end}'

# 3. the FILTER idiom — read a specific condition/container by name
kubectl get kustomization ionic-query-engine \
  -o jsonpath='{.status.conditions[?(@.type=="Ready")].status}'

# 4. kubectl wait (jsonpath is mandatory here)
kubectl wait pod/mypod --for=jsonpath='{.status.phase}'=Running --timeout=60s

What to memorize

The single most important construct is the filter [?(@.type=="...")] — it’s the non-obvious one, and it shows up constantly for reading conditions, containers, ports, etc. The rest you can infer on sight.

Bonus cousin (not jsonpath, but same niche and often cleaner for tables):

kubectl get pods -o custom-columns=NAME:.metadata.name,READY:.status.conditions[?(@.type=="Ready")].status

helm Cheat Sheet

Development Tips and Tricks

Test Template Rendering

Run the following. Instead of it installing the chart it will render the template and display the output

helm install --debug --dry-run <release-name> <path-to-chart-dir>

To test with an overriding value

helm install <release-name> <path-to-chart-dir> --dry-run --debug --set k=v

Deployments

  • List releases: helm list
  • Get the manifest for a release: helm get manifest <release-name> [flags]

Implementing a Stack in Go

One of the key features in go is simplicity. As a result there are a number of utilities and data structures that are common in other high-level languages that do not come with the go stdlib.

One of them is a stack. Following is a very simple implementation of a stack that uses a slice to store the data.

The following is an implementation of a simple stack that takes any kind of pointer.

import "fmt"

type Stack[T any] struct {
	stack []*T
}

func (s *Stack[T]) IsEmpty() bool {
	return len(s.stack) == 0
}

func (s *Stack[T]) Push(q *T) {
	// Add the new value to the end of the slice, which acts as the "top" of the Stack
	s.stack = append(s.stack, q)
}

func (s *Stack[T]) Pop() *T {
	if s.IsEmpty() {
		return nil
	} else {
		// Get the index of the "top" of the Stack
		idx := len(s.stack) - 1
		// Retrieve the element from the stack that we are going to "pop" and return
		retval := s.stack[idx]
		// Remove it from the underlying slice by re-slicing the slice.
		s.stack = s.stack[:idx]
		return retval
	}
}

func main() {
	i := 1
	j := 2
	s1 := &Stack[int]{}
	s1.Push(&i)
	s1.Push(&j)

	fmt.Printf("Pop! = %d\n", *s1.Pop())
	fmt.Printf("Pop! = %d\n", *s1.Pop())
}

Diffing the output of two commands

The GNU diff command on most Linux and UNIX systems will diff the contents of two files. With Bash, you can, using process substitution, take the output of any arbitrary command and process its input, or output, as a file descriptor. In this way, you can then use diff against the output of two commands as follows

diff <(cmd1) <(cmd2)

Both cmd1 and cmd2 will appear as a file name/file descriptor. The < character indicates that the file descriptor should be read to obtain the output.

Creating Custom Vagrant Boxes for Integration Testing

For some things, a docker container will not work. For example, I am working on a Python project to automate the deployment and configuration of VMs and bare-metal boxes. It involves installing packages and configuring the OS and to properly test it requires a full fledged VM and not just a container.

Use packer to define the box you want to build

Install packer. The description straight from apt show packer is “HashiCorp Packer – A tool for creating identical machine images for multiple platforms from a single source configuration” Then create your pkr.hcl file (I am using the newer HCL DSL). The following is for a box that extends Debian 11.

variable "version" {
  type    = string
  default = ""
}

locals { timestamp = regex_replace(timestamp(), "[- TZ:]", "") }

source "vagrant" "xfce4_debian_11" {
  add_force    = true
  communicator = "ssh"
  provider     = "virtualbox"
  source_path  = "debian/bullseye64"
}

build {
  sources = ["source.vagrant.xfce4_debian_11"]

  provisioner "shell" {
    execute_command = "echo 'vagrant' | {{.Vars}} sudo -S -E bash '{{.Path}}'"
    script          = "provision.sh"
  }
}

Build the box

packer build xfce4_debian_11.hcl

This will create an output-xfce4_debian_11 directory and build the box writing it into that directory. The contents of which, when finished will be

output-xfce4_debian_11/
|-- package.box
`-- Vagrantfile

Create a Vagrant file that uses the pre-built box

For your integration testing you will be spinning up an “instance” of the box you just built.

  1. Create a directory for your instance and cd into it: mkdir test-instance && cd test-instance
  2. Initialize the vagrant instance and then add the box that you built; vagrant init test-instance && vagrant box add test-instance <path-to-dir>/output-xfce4_debian_11/package.box
  3. Update the Vagrant file with any additional configs that you require and then run vagrant up to start it.

Using Environment Variables in a Vagrant File

An easy way to parameterize a Vagrant file is to use environment variables. You simply need to export a variable and then refer to it in the Vagrant file with the following syntax.

Export the variable:

export SSH_PORT=22222

Sample Vagrant file that reads the exported variable

# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|
  config.vm.box = "debian/bullseye64"
  config.vm.box_version = "11.20221219.1"

  config.vm.network "forwarded_port", guest: 22, host: ENV['SSH_PORT']
end

Declaring, Exporting, and Reading Dynamic Variables in Bash

If you want to dynamically define and export variable names in Bash here is the TLDR;

# Define the name of the variable
key="my-dynamic-var-name"

# Declare it and export it
declare -gx "$key"="some-value"

To then access that value via a dynamically generated variable name

# Create a variable that contains the variable name
var_to_access="my-dynamic-var-name"

# Read the value
my_var_value=${!var_to_access}

Read the man page for declare for more details and read this article for a really good explanation and further examples.

To read the declare man page

help declare

[SOLVED] ‘Virtualized Intel VT-x/EPT is not supported on this platform. Continue without virtualized Intel VT-x/EPT’ on Windows 11 host

I was trying to run a Debian, Linux, guest on a Windows 11 Enterprise host with virtualization enabled for the VMWare Linux guest so that I could install minikube. Minikube requires running a VM on the host on which minikube is running, so essentially, a VM within a VM.

After enabling the “Virtualize Intel VT-x/EPT or AMD-V/RVI” setting and attempting to boot the VM it indicated that this configuration was not supported on this platform.

After quite a bit of digging I figured out the settings required for the Windows 11 host.

  1. Disable Hyper-V
    1. Open the Control Panel and search for “program”
    2. Click on Turn Windows features on or off which will open another modal
    3. Ensure that Hyper-V and all of its child check-boxes are de-selected
    4. Ensure that Virtual Machine Platform is deselected
  2. Disable Core Isolation/Memory integrity
    • Open Settings and click on **Privacy & Security** in the left-hand nav
    • Click on Windows Security
    • Click on Device Security
    • Click on Core isolation details under the Core isolation heading
    • Toggle the Memory integrity setting to Off and restart your machine

How to check if a file is sourced in Bash

Sometimes you will want to ensure that a file is sourced instead of executed. This ensures, among other things, that any environment variables that the script defines remain in your current shell after the script completes.

To do so, use the following to check whether the file was sourced or run in a sub-shell

(return 0 2>/dev/null) && sourced=1 || sourced=0
echo "sourced=$sourced"

Bash allows return statements only from functions and in a scripts top level scope IF it is sourced. If you try to use a return statement outside of a function in a non-sourced context it returns an error.