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

8
deploy/.env Normal file
View File

@ -0,0 +1,8 @@
OSIE_DOWNLOAD_URL="https://tinkerbell-oss.s3.amazonaws.com/osie-uploads/osie-v0-n=404,c=c35a5f8,b=master.tar.gz"
TINK_CLI_IMAGE="quay.io/tinkerbell/tink-cli:sha-8ea8a0e5"
TINK_SERVER_IMAGE="quay.io/tinkerbell/tink:sha-8ea8a0e5"
BOOTS_SERVER_IMAGE="quay.io/tinkerbell/boots:sha-cb0290f8"
HEGEL_SERVER_IMAGE="quay.io/tinkerbell/hegel:sha-9f5da0a8"
TINKERBELL_HOST_IP=192.168.50.4
TINKERBELL_CLIENT_IP=192.168.50.43
TINKERBELL_CLIENT_MAC=08:00:27:9E:F5:3A

1
deploy/.gitignore vendored
View File

@ -1 +0,0 @@
state

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"

View File

@ -1,7 +1,111 @@
version: "2.1"
services:
# TLS cert for tink-server and docker registry
tls-gen:
image: cfssl/cfssl
entrypoint: /code/tls/generate.sh
command: ["$TINKERBELL_HOST_IP"]
environment:
FACILITY: ${FACILITY:-onprem}
volumes:
- ${REPO_TOP_LEVEL:-.}:/code
- certs:/certs/${FACILITY:-onprem}:rw
# User creds for the registry
registry-auth:
image: httpd:2
entrypoint: htpasswd
working_dir: /auth
command:
[
"-Bbc",
".htpasswd",
"${TINKERBELL_REGISTRY_USERNAME:-admin}",
"${TINKERBELL_REGISTRY_PASSWORD:-Admin1234}",
]
volumes:
- auth:/auth:rw
# OSIE work
osie-work:
image: alpine
entrypoint: /scripts/lastmile.sh
command: ["${OSIE_DOWNLOAD_URL}", "/source", "/source", "/destination"]
volumes:
- ${REPO_TOP_LEVEL:-.}/compose/osie:/scripts
- ${REPO_TOP_LEVEL:-.}/state/webroot/misc/osie/current:/source
- ${REPO_TOP_LEVEL:-.}/state/webroot/workflow:/destination
# Uploads images in /registry/registry_images.txt to the local registry
images-to-local-registry:
image: quay.io/containers/skopeo:latest
entrypoint: /registry/upload.sh
command:
[
"${TINKERBELL_REGISTRY_USERNAME:-admin}",
"${TINKERBELL_REGISTRY_PASSWORD:-Admin1234}",
"${TINKERBELL_HOST_IP}",
"/registry/registry_images.txt",
]
volumes:
- ${REPO_TOP_LEVEL:-.}/compose/registry:/registry
depends_on:
registry:
condition: service_healthy
# registry ca.crt download
registry-ca-crt-download:
image: alpine
entrypoint: wget
working_dir: /code
command: ["http://$TINKERBELL_HOST_IP:42114/cert", "-O", "ca.pem"]
volumes:
- ${REPO_TOP_LEVEL:-.}/state/webroot/workflow:/code
depends_on:
tink-server:
condition: service_healthy
db:
condition: service_healthy
# Create hardware, template, and workflow records in tink-server
create-tink-records:
image: ${TINK_CLI_IMAGE}
entrypoint: /manifests/apply_manifests.sh
command:
[
"/manifests/hardware/hardware.json",
"/manifests/template/ubuntu.yaml",
"/manifests/workflow",
"$TINKERBELL_HOST_IP",
"$TINKERBELL_CLIENT_IP",
"$TINKERBELL_CLIENT_MAC",
]
environment:
TINKERBELL_GRPC_AUTHORITY: tink-server:42113
TINKERBELL_CERT_URL: http://tink-server:42114/cert
volumes:
- ${REPO_TOP_LEVEL:-.}/compose/manifests:/manifests
depends_on:
tink-server:
condition: service_healthy
db:
condition: service_healthy
# Setup ubuntu image
ubuntu-image-setup:
image: ubuntu
entrypoint: /scripts/setup_ubuntu.sh
command:
[
"https://cloud-images.ubuntu.com/daily/server/focal/current/focal-server-cloudimg-amd64.img",
"focal-server-cloudimg-amd64.img",
"/destination/focal-server-cloudimg-amd64.raw",
]
volumes:
- ${REPO_TOP_LEVEL:-.}/compose/ubuntu:/scripts
- ${REPO_TOP_LEVEL:-.}/state/webroot:/destination
tink-server:
image: ${TINKERBELL_TINK_SERVER_IMAGE}
image: ${TINK_SERVER_IMAGE}
restart: unless-stopped
environment:
FACILITY: ${FACILITY:-onprem}
@ -17,26 +121,28 @@ services:
PGUSER: tinkerbell
TINKERBELL_GRPC_AUTHORITY: :42113
TINKERBELL_HTTP_AUTHORITY: :42114
TINK_AUTH_USERNAME: ${TINKERBELL_TINK_USERNAME}
TINK_AUTH_PASSWORD: ${TINKERBELL_TINK_PASSWORD}
TINK_AUTH_USERNAME: ${TINKERBELL_TINK_USERNAME:-admin}
TINK_AUTH_PASSWORD: ${TINKERBELL_TINK_PASSWORD:-admin}
depends_on:
tink-server-migration:
condition: service_started
db:
condition: service_healthy
tls-gen:
condition: service_completed_successfully
healthcheck:
test: ["CMD-SHELL", "wget -qO- 127.0.0.1:42114/cert"] # port needs to match TINKERBELL_HTTP_AUTHORITY
interval: 5s
timeout: 2s
retries: 30
volumes:
- ./state/certs:/certs/${FACILITY:-onprem}
- certs:/certs/${FACILITY:-onprem}:rw
ports:
- 42113:42113/tcp
- 42114:42114/tcp
tink-server-migration:
image: ${TINKERBELL_TINK_SERVER_IMAGE}
image: ${TINK_SERVER_IMAGE}
restart: on-failure
environment:
ONLY_MIGRATION: "true"
@ -49,13 +155,13 @@ services:
PGUSER: tinkerbell
TINKERBELL_GRPC_AUTHORITY: :42113
TINKERBELL_HTTP_AUTHORITY: :42114
TINK_AUTH_USERNAME: ${TINKERBELL_TINK_USERNAME}
TINK_AUTH_PASSWORD: ${TINKERBELL_TINK_PASSWORD}
TINK_AUTH_USERNAME: ${TINKERBELL_TINK_USERNAME:-admin}
TINK_AUTH_PASSWORD: ${TINKERBELL_TINK_PASSWORD:-admin}
depends_on:
db:
condition: service_healthy
volumes:
- ./state/certs:/certs/${FACILITY:-onprem}
- certs:/certs/${FACILITY:-onprem}:rw
db:
image: postgres:10-alpine
@ -75,47 +181,51 @@ services:
retries: 30
tink-cli:
image: ${TINKERBELL_TINK_CLI_IMAGE}
image: ${TINK_CLI_IMAGE}
restart: unless-stopped
environment:
TINKERBELL_GRPC_AUTHORITY: 127.0.0.1:42113
TINKERBELL_CERT_URL: http://127.0.0.1:42114/cert
TINKERBELL_GRPC_AUTHORITY: tink-server:42113
TINKERBELL_CERT_URL: http://tink-server:42114/cert
depends_on:
tink-server:
condition: service_healthy
db:
condition: service_healthy
network_mode: host
registry:
build:
context: registry
args:
REGISTRY_USERNAME: $TINKERBELL_REGISTRY_USERNAME
REGISTRY_PASSWORD: $TINKERBELL_REGISTRY_PASSWORD
image: registry:2.7.1
restart: unless-stopped
network_mode: host
healthcheck:
test: ["CMD-SHELL", "curl --cacert /certs/ca.pem https://127.0.0.1"]
test:
[
"CMD-SHELL",
"wget --no-check-certificate https://$TINKERBELL_HOST_IP -O -",
]
interval: 5s
timeout: 1s
retries: 5
environment:
REGISTRY_HTTP_ADDR: 0.0.0.0:443
REGISTRY_HTTP_TLS_CERTIFICATE: /certs/server.pem
REGISTRY_HTTP_TLS_KEY: /certs/server-key.pem
REGISTRY_AUTH: htpasswd
REGISTRY_AUTH_HTPASSWD_REALM: "Registry Realm"
REGISTRY_AUTH_HTPASSWD_PATH: /auth/htpasswd
REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm
REGISTRY_AUTH_HTPASSWD_PATH: /auth/.htpasswd
REGISTRY_HTTP_TLS_CERTIFICATE: /certs/${FACILITY:-onprem}/bundle.pem
REGISTRY_HTTP_TLS_KEY: /certs/${FACILITY:-onprem}/server-key.pem
REGISTRY_HTTP_ADDR: $TINKERBELL_HOST_IP:443
volumes:
- ./state/certs:/certs
- ./state/registry:/var/lib/registry
network_mode: host
- certs:/certs/${FACILITY:-onprem}:ro
- auth:/auth:rw
depends_on:
tls-gen:
condition: service_completed_successfully
registry-auth:
condition: service_completed_successfully
boots:
image: ${TINKERBELL_TINK_BOOTS_IMAGE}
image: ${BOOTS_SERVER_IMAGE}
restart: unless-stopped
network_mode: host
command: -dhcp-addr 0.0.0.0:67 -tftp-addr $TINKERBELL_HOST_IP:69 -http-addr $TINKERBELL_HOST_IP:80 -log-level DEBUG
network_mode: host
environment:
API_AUTH_TOKEN: ${PACKET_API_AUTH_TOKEN:-ignored}
API_CONSUMER_TOKEN: ${PACKET_CONSUMER_TOKEN:-ignored}
@ -132,33 +242,35 @@ services:
SYSLOG_BIND: $TINKERBELL_HOST_IP:514
TFTP_BIND: $TINKERBELL_HOST_IP:69
DOCKER_REGISTRY: $TINKERBELL_HOST_IP
REGISTRY_USERNAME: $TINKERBELL_REGISTRY_USERNAME
REGISTRY_PASSWORD: $TINKERBELL_REGISTRY_PASSWORD
REGISTRY_USERNAME: ${TINKERBELL_REGISTRY_USERNAME:-admin}
REGISTRY_PASSWORD: ${TINKERBELL_REGISTRY_PASSWORD:-Admin1234}
TINKERBELL_GRPC_AUTHORITY: $TINKERBELL_HOST_IP:42113
TINKERBELL_CERT_URL: http://$TINKERBELL_HOST_IP:42114/cert
ELASTIC_SEARCH_URL: $TINKERBELL_HOST_IP:9200
DATA_MODEL_VERSION: 1
extra_hosts:
- "tink-server:$TINKERBELL_HOST_IP"
depends_on:
db:
tink-server:
condition: service_healthy
ports:
- $TINKERBELL_HOST_IP:80:80/tcp
- 67:67/udp
- 69:69/udp
nginx:
osie-bootloader:
image: nginx:alpine
restart: unless-stopped
tty: true
user: root
ports:
- 8080:80/tcp
volumes:
- ./state/webroot:/usr/share/nginx/html/
- ${REPO_TOP_LEVEL:-.}/state/webroot:/usr/share/nginx/html/
depends_on:
osie-work:
condition: service_completed_successfully
ubuntu-image-setup:
condition: service_completed_successfully
hegel:
image: ${TINKERBELL_TINK_HEGEL_IMAGE}
image: ${HEGEL_SERVER_IMAGE}
restart: unless-stopped
network_mode: host
environment:
ROLLBAR_TOKEN: ${ROLLBAR_TOKEN-ignored}
ROLLBAR_DISABLE: 1
@ -167,13 +279,15 @@ services:
GRPC_PORT: 42115
HEGEL_FACILITY: ${FACILITY:-onprem}
HEGEL_USE_TLS: 0
TINKERBELL_GRPC_AUTHORITY: 127.0.0.1:42113
TINKERBELL_CERT_URL: http://127.0.0.1:42114/cert
TINKERBELL_GRPC_AUTHORITY: tink-server:42113
TINKERBELL_CERT_URL: http://tink-server:42114/cert
DATA_MODEL_VERSION: 1
CUSTOM_ENDPOINTS: '{"/metadata":""}'
depends_on:
db:
tink-server:
condition: service_healthy
volumes:
postgres_data:
certs:
auth:

View File

@ -1,7 +0,0 @@
FROM registry:2.7.1
RUN apk add --no-cache --update curl apache2-utils
ARG REGISTRY_USERNAME
ARG REGISTRY_PASSWORD
RUN mkdir -p /certs /auth
RUN htpasswd -Bbn ${REGISTRY_USERNAME} ${REGISTRY_PASSWORD} > /auth/htpasswd
EXPOSE 443

View File

View File

@ -1 +0,0 @@
*/

View File

@ -1,7 +0,0 @@
FROM alpine:3.11
ENTRYPOINT [ "/entrypoint.sh" ]
RUN apk add --no-cache --update --upgrade ca-certificates postgresql-client
RUN apk add --no-cache --update --upgrade --repository=http://dl-cdn.alpinelinux.org/alpine/edge/testing cfssl
COPY . .

View File

@ -1,12 +0,0 @@
{
"CN": "Autogenerated CA",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"L": "@FACILITY@"
}
]
}

View File

@ -4,8 +4,10 @@
"tinkerbell.registry",
"tinkerbell.tinkerbell",
"tinkerbell",
"localhost",
"127.0.0.1"
"tink-server",
"192.168.50.4",
"127.0.0.1",
"localhost"
],
"key": {
"algo": "rsa",

View File

@ -1,13 +0,0 @@
#!/usr/bin/env sh
# set -o errexit -o nounset -o pipefail
if [ -z "${TINKERBELL_TLS_CERT:-}" ]; then
(
echo "creating directory"
mkdir -p "certs"
./gencerts.sh
)
fi
"$@"

View File

@ -1,30 +0,0 @@
#!/usr/bin/env sh
set -eux
cd /certs
if [ ! -f ca-key.pem ]; then
cfssl gencert \
-initca ca.json | cfssljson -bare ca
fi
if [ ! -f server.pem ]; then
cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=/ca-config.json \
-profile=server \
server-csr.json |
cfssljson -bare server
fi
cat server.pem ca.pem >bundle.pem.tmp
# only "modify" the file if truly necessary since workflow will serve it with
# modtime info for client caching purposes
if ! cmp -s bundle.pem.tmp bundle.pem; then
mv bundle.pem.tmp bundle.pem
else
rm bundle.pem.tmp
fi

47
deploy/tls/generate.sh Executable file
View File

@ -0,0 +1,47 @@
#!/usr/bin/env bash
set -xo pipefail
# update_csr will add the sans_ip to the csr
update_csr() {
local sans_ip="$1"
local csr_file="$2"
sed -i "/\"hosts\".*/a \ \"${sans_ip}\"," "${csr_file}"
}
# cleanup will remove unneeded files
cleanup() {
rm -rf ca-key.pem ca.csr ca.pem server.csr server.pem
}
# gen will generate the key and bundle
gen() {
local bundle_destination="$1"
local key_destination="$2"
cfssl gencert -initca /code/tls/csr.json | cfssljson -bare ca -
cfssl gencert -config /code/tls/ca-config.json -ca ca.pem -ca-key ca-key.pem -profile server /code/tls/csr.json | cfssljson -bare server
cat server.pem ca.pem >"${bundle_destination}"
mv server-key.pem "${key_destination}"
}
# main orchestrates the process
main() {
local sans_ip="$1"
local csr_file="/code/tls/csr.json"
local bundle_file="/certs/${FACILITY:-onprem}/bundle.pem"
local server_key_file="/certs/${FACILITY:-onprem}/server-key.pem"
if ! grep -q "${sans_ip}" "${csr_file}"; then
update_csr "${sans_ip}" "${csr_file}"
else
echo "IP ${sans_ip} already in ${csr_file}"
fi
if [ ! -f "${bundle_file}" ] && [ ! -f "${server_key_file}" ]; then
gen "${bundle_file}" "${server_key_file}"
else
echo "Files [${bundle_file}, ${server_key_file}] already exist"
fi
cleanup
}
main "$1"

View File

@ -1 +0,0 @@
.vagrant

View File

@ -1 +0,0 @@
https://tinkerbell.org/docs/setup/local-with-vagrant/

View File

@ -1,109 +1,43 @@
ENV['VAGRANT_NO_PARALLEL'] = 'yes'
# -*- mode: ruby -*-
# vi: set ft=ruby :
num_workers = ENV['TINKERBELL_NUM_WORKERS'] || '1'
PROVISIONER_IP = "192.168.50.4"
MACHINE1_IP = "192.168.50.43"
# Returns true if `GUI` environment variable exists, value does not matter.
# Defaults to false
def worker_gui_enabled?
ENV.include?('VAGRANT_WORKER_GUI')
unless Vagrant.has_plugin?("vagrant-docker-compose")
system("vagrant plugin install vagrant-docker-compose")
puts "Dependencies installed, please try the command again."
exit
end
# Returns true if `SCALE` environment variable exists, value does not matter.
# Defaults to false
def worker_display_scale_enabled?
ENV.include?('VAGRANT_WORKER_SCALE')
end
def configure_nat
return ENV.has_key?('TINKERBELL_CONFIGURE_NAT') ? ENV['TINKERBELL_CONFIGURE_NAT'] : 'true'
end
def libvirt_forward_mode
return configure_nat == 'false' ? 'nat' : 'none'
end
Vagrant.configure('2') do |config|
config.vm.define :provisioner do |provisioner|
provisioner.vm.box = "tinkerbelloss/sandbox-ubuntu1804"
provisioner.vm.box_version = "0.2.0"
provisioner.vm.hostname = 'provisioner'
provisioner.vm.synced_folder './../../', '/vagrant'
provisioner.vm.provision :shell,
path: './scripts/tinkerbell.sh',
env: {
'TINKERBELL_CONFIGURE_NAT': configure_nat,
}
provisioner.vm.network :private_network,
virtualbox__intnet: "tink_network",
libvirt__network_name: "tink_network",
libvirt__host_ip: "192.168.1.6",
libvirt__netmask: "255.255.255.248",
libvirt__dhcp_enabled: false,
libvirt__forward_mode: libvirt_forward_mode,
libvirt__adapter: 1,
auto_config: false
provisioner.vm.network "forwarded_port", guest: 42113, host: 42113
provisioner.vm.network "forwarded_port", guest: 42114, host: 42114
provisioner.vm.provider :libvirt do |lv, override|
lv.memory = 2*1024
lv.cpus = 2
lv.cpu_mode = 'host-passthrough'
Vagrant.configure("2") do |config|
config.vm.define "provisioner" do |provisioner|
provisioner.vm.box = "generic/ubuntu2004"
provisioner.vm.synced_folder '../', '/vagrant'
provisioner.vm.provider "virtualbox" do |v|
v.memory = 2048
v.cpus = 2
end
provisioner.vm.network "private_network", ip: PROVISIONER_IP
provisioner.vm.provider :virtualbox do |vb, override|
vb.memory = 2*1024
vb.cpus = 2
end
provisioner.vm.provision :docker
# vagrant plugin install vagrant-docker-compose
provisioner.vm.provision :docker_compose, compose_version: "1.29.1", yml: "/vagrant/docker-compose.yml", run:"always", env: {"TINKERBELL_HOST_IP": PROVISIONER_IP, "TINKERBELL_CLIENT_IP": MACHINE1_IP, "REPO_TOP_LEVEL": "/vagrant"}
end
(1..num_workers.to_i).each do |i|
mac_suffix = "%02x" % i
worker_suffix = i==1 ? "" : "i"
config.vm.define "worker#{worker_suffix}" do |worker|
worker.vm.box = nil
worker.vm.network :private_network,
mac: "0800270000#{mac_suffix}",
virtualbox__intnet: "tink_network",
libvirt__network_name: "tink_network",
libvirt__dhcp_enabled: false,
libvirt__forward_mode: libvirt_forward_mode,
auto_config: false
worker.vm.provider :libvirt do |lv|
lv.memory = 4*1024
lv.cpus = 1
lv.boot 'network'
lv.mgmt_attach = false
lv.storage :file, :size => '40G'
lv.random :model => 'random'
end
worker.vm.provider :virtualbox do |vb, worker|
worker.vm.box = 'generic/alpine38'
vb.memory = 4*1024
vb.cpus = 1
vb.gui = worker_gui_enabled?
vb.customize [
'setextradata', :id,
'GUI/ScaleFactor', '3.0'
] if worker_display_scale_enabled?
vb.customize [
'modifyvm', :id,
'--nic1', 'none',
'--boot1', 'net',
'--boot2', 'none',
'--boot3', 'none',
'--boot4', 'none',
'--macaddress1', "0800270000#{mac_suffix}"
]
end
config.vm.define :machine1, autostart: false do |machine1|
machine1.vm.box = 'jtyr/pxe'
machine1.vm.provider "virtualbox" do |v|
v.memory = 2048
v.cpus = 2
v.gui = true
v.customize ['modifyvm', :id, '--nic1', 'hostonly', '--nic2', 'nat', '--boot1', 'disk', '--boot2', 'net']
v.customize ['setextradata', :id, 'GUI/ScaleFactor', '3.0']
v.check_guest_additions = false
end
machine1.ssh.insert_key = false
machine1.vm.boot_timeout = 10
machine1.vm.synced_folder '.', '/vagrant', disabled: true
machine1.vm.network "private_network", ip: MACHINE1_IP, mac: "0800279EF53A", adapter: 1
end
end

View File

@ -1 +0,0 @@
output*

View File

@ -1,30 +0,0 @@
This directory contains a provisioning mechanism for the Vagrant boxes we ship
as part of Sandbox.
In order to self contain and distribute the required dependencies for Tinkerbell
and Sandbox without having to download all of them at runtime we decided to use
[Packer.io](https://packer.io) to build boxes that you can use when provisioning
Tinkerbell on Vagrant.
Currently the generated boxes are available via [Vagrant
Cloud](https://app.vagrantup.com/tinkerbelloss).
---
## Build
To build the boxes checkout the right directory and run
```terminal
$ packer build --parallel-builds=1 ./template.json
```
`-parallel-builds=1` is required because the template builds images for multiple
providers using the [Vagrant
builder](https://www.packer.io/docs/builders/vagrant) and I didn't manage to get
it to work in parallel yet.
## Deploy to Vagrant Cloud
I didn't find a way to make the Vagrant Cloud post processor to work. But I use
the vagrant cli `vagrant cloud publish` command.

View File

@ -1,57 +0,0 @@
#!/bin/bash
# abort this script on errors
set -euxo pipefail
setup_docker() (
# steps from https://docs.docker.com/engine/install/ubuntu/
sudo apt-get install -y \
apt-transport-https \
ca-certificates \
curl \
gnupg-agent \
software-properties-common \
;
curl -fsSL https://download.docker.com/linux/ubuntu/gpg |
sudo apt-key add -
local repo
repo=$(
printf "deb [arch=amd64] https://download.docker.com/linux/ubuntu %s stable" \
"$(lsb_release -cs)"
)
sudo add-apt-repository "$repo"
sudo apt-get update
sudo apt-get install -y \
containerd.io \
docker-ce \
docker-ce-cli \
;
)
# from https://docs.docker.com/compose/install/
setup_docker_compose() (
local name url
name=docker-compose-$(uname -s)-$(uname -m)
url=https://github.com/docker/compose/releases/download/1.26.0/$name
curl -fsSLO "$url"
curl -fsSLO "$url.sha256"
sha256sum -c <"$name.sha256"
rm -f "$name.sha256"
chmod +x "$name"
sudo mv "$name" /usr/local/bin/docker-compose
)
main() (
export DEBIAN_FRONTEND=noninteractive
sudo apt-get update
setup_docker
setup_docker_compose
sudo apt-get install -y jq
sudo usermod -aG docker vagrant
)
main
sync # do not remove!

View File

@ -1,27 +0,0 @@
{
"builders": [
{
"communicator": "ssh",
"name": "vagrant-virtualbox",
"provider": "virtualbox",
"source_path": "generic/ubuntu1804",
"type": "vagrant"
},
{
"communicator": "ssh",
"name": "vagrant-libvirt",
"provider": "libvirt",
"source_path": "generic/ubuntu1804",
"type": "vagrant"
}
],
"provisioners": [
{
"script": "provision.sh",
"type": "shell"
}
],
"variables": {
"cloud_token": "{{ env `VAGRANT_CLOUD_TOKEN` }}"
}
}

View File

@ -1,59 +0,0 @@
#!/bin/bash
# abort this script on errors
set -euxo pipefail
whoami
cd /vagrant
make_certs_writable() (
local certdir="/etc/docker/certs.d/$TINKERBELL_HOST_IP"
sudo mkdir -p "$certdir"
sudo chown -R "$USER" "$certdir"
)
secure_certs() (
local certdir="/etc/docker/certs.d/$TINKERBELL_HOST_IP"
sudo chown "root" "$certdir"
)
configure_vagrant_user() (
echo -n "$TINKERBELL_REGISTRY_PASSWORD" |
sudo -iu vagrant docker login \
--username="$TINKERBELL_REGISTRY_USERNAME" \
--password-stdin "$TINKERBELL_HOST_IP"
)
setup_nat() (
iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT
iptables -A FORWARD -i eth0 -o eth1 -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
)
main() (
export DEBIAN_FRONTEND=noninteractive
if ! [[ -f ./.env ]]; then
./generate-env.sh eth1 >.env
fi
# shellcheck disable=SC1091
source ./.env
make_certs_writable
./setup.sh
if [[ ${TINKERBELL_CONFIGURE_NAT:=true} != "false" ]]; then
setup_nat
fi
secure_certs
configure_vagrant_user
set +x # don't want the stderr output from xtrace messing with the post-setup-message
[[ -f /tmp/post-setup-message ]] && cat /tmp/post-setup-message
)
main