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:
85
deploy/compose/manifests/apply_manifests.sh
Executable file
85
deploy/compose/manifests/apply_manifests.sh
Executable 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"
|
31
deploy/compose/manifests/hardware/hardware.json
Normal file
31
deploy/compose/manifests/hardware/hardware.json
Normal 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
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
76
deploy/compose/manifests/template/ubuntu.yaml
Normal file
76
deploy/compose/manifests/template/ubuntu.yaml
Normal 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
|
0
deploy/compose/manifests/workflow/.keep
Normal file
0
deploy/compose/manifests/workflow/.keep
Normal file
49
deploy/compose/osie/lastmile.sh
Executable file
49
deploy/compose/osie/lastmile.sh
Executable 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"
|
4
deploy/compose/registry/registry_images.txt
Normal file
4
deploy/compose/registry/registry_images.txt
Normal 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
|
19
deploy/compose/registry/upload.sh
Executable file
19
deploy/compose/registry/upload.sh
Executable 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"
|
45
deploy/compose/ubuntu/setup_ubuntu.sh
Executable file
45
deploy/compose/ubuntu/setup_ubuntu.sh
Executable 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"
|
Reference in New Issue
Block a user