This simplifies the stand-up of a sandbox:

Only 2 main Vagrant calls are now needed (`vagrant up` and `vagrant up machine1`).
This PR only updates the Vagrant Virtualbox setup. The Vagrant Libvirt and Terraform
still need to be updated.

This uses docker-compose as the entry point for standing up the stack and makes the stand-up
of the sandbox more portal. Vagrant and Terraform are only responsible for standing up infrastructure
and then running docker-compose, not for running any glue scripts.

The docker-compose calls out to single-shot services to do all the glue required to get the fully
functional Tinkerbell stack up and running. All the single-shot services are idempotent.
This increases portability and the development iteration loop. This also simplifies the required
steps needed to get a fully functioning sandbox up and running.

This is intended to help people looking to get started by getting them to a provisioned
machine quicker and more easily.

Signed-off-by: Jacob Weinstock <jakobweinstock@gmail.com>
This commit is contained in:
Jacob Weinstock
2021-08-09 08:04:06 -06:00
parent 1ebcf482de
commit 6b841fee7c
58 changed files with 1862 additions and 1020 deletions

View File

@ -0,0 +1,85 @@
#!/usr/bin/env sh
# shellcheck disable=SC2039,SC2155,SC2086
set -xo pipefail
# update_hw_ip_addr the hardware json with a specified IP address
update_hw_ip_addr() {
local ip_address="$1"
local hw_file="$2"
sed -i "s/\"address\":.*,/\"address\": \"${ip_address}\",/" "${hw_file}"
}
# update_hw_mac_addr the hardware json with a specified MAC address
update_hw_mac_addr() {
local mac_address="$1"
local hw_file="$2"
sed -i "s/\"mac\":.*,/\"mac\": \"${mac_address}\",/" "${hw_file}"
}
# hardware creates a hardware record in tink from the file_loc provided
hardware() {
local file_loc="$1"
tink hardware push --file "${file_loc}"
}
# update_template_img_ip the template yaml with a specified IP address
update_template_img_ip() {
local ip_address="$1"
local template_file="$2"
sed -i "s,IMG_URL: \"http://.*,IMG_URL: \"http://${ip_address}:8080/focal-server-cloudimg-amd64.raw.gz\"," "${template_file}"
}
# template create a template record in tink from the file_loc provided
template() {
local file_loc="$1"
tink template create --file "${file_loc}"
}
# workflow creates a workflow record in tink from the hardware and template records
workflow() {
local workflow_dir="$1"
local mac_address="$2"
local mac=$(echo "${mac_address}" | tr '[:upper:]' '[:lower:]')
local template_id=$(tink template get --no-headers 2>/dev/null | grep -v "+" | cut -d" " -f2 | xargs)
tink workflow create --template "${template_id}" --hardware "{\"device_1\":\"${mac}\"}" | tee "${workflow_dir}"/workflow_id.txt
# write just the workflow id to a file. `|| true` is a failsafe in case the workflow creation fails
sed -i 's/Created Workflow: //g' ${workflow_dir}/workflow_id.txt || true
}
# workflow_exists checks if a workflow record exists in tink before creating a new one
workflow_exists() {
local workflow_dir="$1"
local mac_address="$2"
if [ ! -f "${workflow_dir}"/workflow_id.txt ]; then
workflow "${workflow_dir}" "${mac_address}"
return 0
fi
local workflow_id=$(cat "${workflow_dir}"/workflow_id.txt)
tink workflow get | grep -q "${workflow_id}"
local result=$?
if [ "${result}" -ne 0 ]; then
workflow "${workflow_dir}" "${mac_address}"
else
echo "Workflow [$(cat "${workflow_dir}"/workflow_id.txt)] already exists"
fi
}
# main runs the creation functions in order
main() {
local hw_file="$1"
local template_file="$2"
local workflow_dir="$3"
local ip_address="$4"
local client_ip_address="$5"
local client_mac_address="$6"
update_hw_ip_addr "${client_ip_address}" "${hw_file}"
update_hw_mac_addr "${client_mac_address}" "${hw_file}"
hardware "${hw_file}"
update_template_img_ip "${ip_address}" "${template_file}"
template "${template_file}"
workflow_exists "${workflow_dir}" "${client_mac_address}"
}
main "$1" "$2" "$3" "$4" "$5" "$6"

View File

@ -0,0 +1,31 @@
{
"id": "0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94",
"metadata": {
"facility": {
"facility_code": "onprem",
"plan_slug": "c2.medium.x86",
"plan_version_slug": ""
},
"instance": {},
"state": "provisioning"
},
"network": {
"interfaces": [
{
"dhcp": {
"arch": "x86_64",
"ip": {
"address": "192.168.50.43",
"netmask": "255.255.255.0"
},
"mac": "08:00:27:9E:F5:3A",
"uefi": false
},
"netboot": {
"allow_pxe": true,
"allow_workflow": true
}
}
]
}
}

View File

@ -0,0 +1,76 @@
version: "0.1"
name: debian_Focal
global_timeout: 1800
tasks:
- name: "os-installation"
worker: "{{.device_1}}"
volumes:
- /dev:/dev
- /dev/console:/dev/console
- /lib/firmware:/lib/firmware:ro
actions:
- name: "stream-ubuntu-image"
image: image2disk:v1.0.0
timeout: 600
environment:
DEST_DISK: /dev/sda
IMG_URL: "http://192.168.50.4:8080/focal-server-cloudimg-amd64.raw.gz"
COMPRESSED: true
- name: "install-openssl"
image: cexec:v1.0.0
timeout: 90
environment:
BLOCK_DEVICE: /dev/sda1
FS_TYPE: ext4
CHROOT: y
DEFAULT_INTERPRETER: "/bin/sh -c"
CMD_LINE: "apt -y update && apt -y install openssl"
- name: "create-user"
image: cexec:v1.0.0
timeout: 90
environment:
BLOCK_DEVICE: /dev/sda1
FS_TYPE: ext4
CHROOT: y
DEFAULT_INTERPRETER: "/bin/sh -c"
CMD_LINE: "useradd -p $(openssl passwd -1 tink) -s /bin/bash -d /home/tink/ -m -G sudo tink"
- name: "enable-ssh"
image: cexec:v1.0.0
timeout: 90
environment:
BLOCK_DEVICE: /dev/sda1
FS_TYPE: ext4
CHROOT: y
DEFAULT_INTERPRETER: "/bin/sh -c"
CMD_LINE: "ssh-keygen -A; systemctl enable ssh.service; sed -i 's/^PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config"
- name: "disable-apparmor"
image: cexec:v1.0.0
timeout: 90
environment:
BLOCK_DEVICE: /dev/sda1
FS_TYPE: ext4
CHROOT: y
DEFAULT_INTERPRETER: "/bin/sh -c"
CMD_LINE: "systemctl disable apparmor; systemctl disable snapd"
- name: "write-netplan"
image: writefile:v1.0.0
timeout: 90
environment:
DEST_DISK: /dev/sda1
FS_TYPE: ext4
DEST_PATH: /etc/netplan/config.yaml
CONTENTS: |
network:
version: 2
renderer: networkd
ethernets:
enp0s3:
dhcp4: true
enp0s8:
dhcp4: true
ens33:
dhcp4: true
UID: 0
GID: 0
MODE: 0644
DIRMODE: 0755

View File

49
deploy/compose/osie/lastmile.sh Executable file
View File

@ -0,0 +1,49 @@
#!/usr/bin/env sh
# shellcheck disable=SC2039
set -xo pipefail
# osie_download from url and save it to directory
osie_download() {
local url="$1"
local directory="$2"
wget "${url}" -O "${directory}"/osie.tar.gz
}
# osie_extract from tarball and save it to directory
osie_extract() {
local source_dir="$1"
local dest_dir="$2"
tar -zxvf "${source_dir}"/osie.tar.gz -C "${dest_dir}" --strip-components 1
}
# osie_move_helper_scripts moves workflow helper scripts to the workflow directory
osie_move_helper_scripts() {
local source_dir="$1"
local dest_dir="$2"
cp "${source_dir}"/workflow-helper.sh "${source_dir}"/workflow-helper-rc "${dest_dir}"/
}
# main runs the functions in order to download, extract, and move helper scripts
main() {
local url="$1"
local extract_dir="$2"
local source_dir="$3"
local dest_dir="$4"
if [ ! -f "${extract_dir}"/osie.tar.gz ]; then
echo "downloading osie..."
osie_download "${url}" "${extract_dir}"
else
echo "osie already downloaded"
fi
if [ ! -f "${source_dir}"/workflow-helper.sh ] && [ ! -f "${source_dir}"/workflow-helper-rc ]; then
echo "extracting osie..."
osie_extract "${extract_dir}" "${source_dir}"
else
echo "osie files already exist, not extracting"
fi
osie_move_helper_scripts "${source_dir}" "${dest_dir}"
}
main "$1" "$2" "$3" "$4"

View File

@ -0,0 +1,4 @@
quay.io/tinkerbell/tink-worker:latest
quay.io/tinkerbell-actions/image2disk:v1.0.0
quay.io/tinkerbell-actions/cexec:v1.0.0
quay.io/tinkerbell-actions/writefile:v1.0.0

View File

@ -0,0 +1,19 @@
#!/usr/bin/env bash
# shellcheck disable=SC2001,SC2155,SC2046
set -xo pipefail
main() {
local reg_user="$1"
local reg_pw="$2"
local reg_url="$3"
local images_file="$4"
# this confusing IFS= and the || is to capture the last line of the file if there is no newline at the end
while IFS= read -r img || [ -n "${img}" ]; do
# trim trailing whitespace
local imgr="$(echo "${img}" | sed 's/ *$//g')"
skopeo copy --all --dest-tls-verify=false --dest-creds="${reg_user}":"${reg_pw}" docker://"${imgr}" docker://"${reg_url}"/$(basename "${imgr}")
done <"${images_file}"
}
main "$1" "$2" "$3" "$4"

View File

@ -0,0 +1,45 @@
#!/usr/bin/env bash
set -xo pipefail
install_deps() {
apt -y update
DEBIAN_FRONTEND=noninteractive apt -y install qemu-utils wget gzip
}
download_image() {
local url="$1"
wget "${url}"
}
img_to_raw() {
local img_file="$1"
local raw_file="$2"
qemu-img convert "${img_file}" -O raw "${raw_file}"
}
compress_raw() {
local raw_file="$1"
gzip "${raw_file}"
}
cleanup() {
local img_file="$1"
rm -rf "${img_file}"
}
main() {
local image_url="$1"
local img_file="$2"
local raw_file="$3"
if [ ! -f "${raw_file}.gz" ]; then
install_deps
download_image "${image_url}"
img_to_raw "${img_file}" "${raw_file}"
compress_raw "${raw_file}"
cleanup "${img_file}"
fi
}
main "$1" "$2" "$3"