|
1 | 1 | #!/usr/bin/env bash
|
2 | 2 |
|
3 |
| -set -xo pipefail |
4 |
| - |
5 | 3 | install_docker() {
|
6 | 4 | curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
|
7 |
| - add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" |
| 5 | + add-apt-repository "deb https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" |
8 | 6 | update_apt
|
9 |
| - DEBIAN_FRONTEND=noninteractive apt install -y apt-transport-https ca-certificates curl gnupg-agent gnupg2 software-properties-common docker-ce docker-ce-cli containerd.io |
| 7 | + apt-get install --no-install-recommends containerd.io docker-ce docker-ce-cli |
10 | 8 | }
|
11 | 9 |
|
12 | 10 | install_docker_compose() {
|
13 |
| - curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose |
14 |
| - chmod +x /usr/local/bin/docker-compose |
| 11 | + apt-get install --no-install-recommends python3-pip |
| 12 | + pip install docker-compose |
15 | 13 | }
|
16 | 14 |
|
17 |
| -update_apt() ( |
18 |
| - $APT update |
19 |
| - DEBIAN_FRONTEND=noninteractive $APT --yes --force-yes -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" upgrade |
20 |
| -) |
| 15 | +install_iptables_persistent() { |
| 16 | + apt-get install --no-install-recommends iptables-persistent |
| 17 | +} |
21 | 18 |
|
22 |
| -restart_docker_service() ( |
23 |
| - service docker restart |
24 |
| -) |
| 19 | +apt-get() { |
| 20 | + DEBIAN_FRONTEND=noninteractive command apt-get \ |
| 21 | + --allow-change-held-packages \ |
| 22 | + --allow-downgrades \ |
| 23 | + --allow-remove-essential \ |
| 24 | + --allow-unauthenticated \ |
| 25 | + --option Dpkg::Options::=--force-confdef \ |
| 26 | + --option Dpkg::Options::=--force-confold \ |
| 27 | + --yes \ |
| 28 | + "$@" |
| 29 | +} |
| 30 | + |
| 31 | +update_apt() { |
| 32 | + apt-get update |
| 33 | + apt-get upgrade |
| 34 | +} |
25 | 35 |
|
26 | 36 | # get_second_interface_from_bond0 returns the second interface of the bond0 interface
|
27 | 37 | get_second_interface_from_bond0() {
|
28 |
| - local return_value |
29 |
| - return_value=$(cut -d' ' -f2 /sys/class/net/bond0/bonding/slaves | xargs) |
30 |
| - echo "${return_value}" |
| 38 | + local addr=$1 |
| 39 | + |
| 40 | + # if the ip is in a file in interfaces.d then lets assume this is a re-run and we can just |
| 41 | + # return the basename of the file (which should be named same as the interface) |
| 42 | + f=$(grep -lr "${addr}" /etc/network/interfaces.d) |
| 43 | + [[ -n ${f:-} ]] && basename "$f" && return |
| 44 | + |
| 45 | + # sometimes the interfaces aren't sorted as expected in the /slaves file |
| 46 | + # |
| 47 | + # seeing as how this function is named *second* I figured its best to be |
| 48 | + # precise (via head -n2) when choosing the iface instead of choosing the last |
| 49 | + # iface and hoping there are only 2 |
| 50 | + tr ' ' '\n' </sys/class/net/bond0/bonding/slaves | sort | head -n2 | tail -n1 |
31 | 51 | }
|
32 | 52 |
|
33 | 53 | # setup_layer2_network removes the second interface from bond0 and uses it for the layer2 network
|
34 | 54 | # https://metal.equinix.com/developers/docs/layer2-networking/hybrid-unbonded-mode/
|
35 | 55 | setup_layer2_network() {
|
36 |
| - local layer2_interface="$1" |
37 |
| - #local ip_addr="$2" |
38 |
| - ifenslave -d bond0 "${layer2_interface}" |
39 |
| - #ip addr add ${ip_addr}/24 dev "${layer2_interface}" |
40 |
| - ip addr add 192.168.56.4/24 dev "${layer2_interface}" |
41 |
| - ip link set dev "${layer2_interface}" up |
| 56 | + local interface=$1 |
| 57 | + local addr=$2 |
| 58 | + |
| 59 | + # I tried getting rid of the following "manual" commands in favor of |
| 60 | + # persisting the network config and then restarting the network but that |
| 61 | + # didn't always work and was hard to recover from without a reboot so we're |
| 62 | + # stuck doing it once imperatively and also persisting the config |
| 63 | + ifenslave -d bond0 "${interface}" |
| 64 | + ip addr add "${addr}/24" dev "${interface}" |
| 65 | + ip link set dev "${interface}" up |
| 66 | + |
| 67 | + # persist the new network settings |
| 68 | + # gets rid of the auto ${interface} block |
| 69 | + # "/^auto ${interface}/,/^\s*$/ d" |
| 70 | + # gets rid of ${interface} in bond config |
| 71 | + # "s|${interface}||" \ |
| 72 | + # gets rid empty lines |
| 73 | + # 's|\s*$||' \ |
| 74 | + # gets rid of source lines from previous runs, having this here helps in debugging/developing |
| 75 | + # '/^source / d' \ |
| 76 | + # appends a source line to the end of the file that will pick up iface-conf file we generate |
| 77 | + # '$ s|$|\n\nsource /etc/network/interfaces.d/*|' \ |
| 78 | + sed -i \ |
| 79 | + -e "/^auto ${interface}/,/^\s*$/ d" \ |
| 80 | + -e "s|${interface}||" \ |
| 81 | + -e 's|\s*$||' \ |
| 82 | + -e '/^source / d' \ |
| 83 | + -e '$ s|$|\n\nsource /etc/network/interfaces.d/*|' \ |
| 84 | + /etc/network/interfaces |
| 85 | + |
| 86 | + cat >"/etc/network/interfaces.d/${interface}" <<-EOF |
| 87 | + auto ${interface} |
| 88 | + iface ${interface} inet static |
| 89 | + address ${addr} |
| 90 | + EOF |
42 | 91 | }
|
43 | 92 |
|
44 | 93 | # make_host_gw_server makes the host a gateway server
|
45 | 94 | make_host_gw_server() {
|
46 |
| - local incoming_interface="$1" |
47 |
| - local outgoing_interface="$2" |
| 95 | + local incoming_interface=$1 |
| 96 | + local outgoing_interface=$2 |
| 97 | + |
| 98 | + # drop all rules, especially interested in droppin docker's we don't want to persist docker's rules |
| 99 | + # docker will re-create them when starting back up |
| 100 | + systemctl stop docker |
| 101 | + netfilter-persistent flush |
| 102 | + |
48 | 103 | iptables -t nat -A POSTROUTING -o "${outgoing_interface}" -j MASQUERADE
|
49 | 104 | iptables -A FORWARD -i "${outgoing_interface}" -o "${incoming_interface}" -m state --state RELATED,ESTABLISHED -j ACCEPT
|
50 | 105 | iptables -A FORWARD -i "${incoming_interface}" -o "${outgoing_interface}" -j ACCEPT
|
| 106 | + |
| 107 | + netfilter-persistent save |
| 108 | + systemctl start docker |
| 109 | +} |
| 110 | + |
| 111 | +extract_compose_files() { |
| 112 | + mkdir -p /sandbox |
| 113 | + unzip /root/compose.zip -d /sandbox/compose |
| 114 | +} |
| 115 | + |
| 116 | +setup_compose_env_overrides() { |
| 117 | + local worker_mac=$1 |
| 118 | + readarray -t lines <<-EOF |
| 119 | + TINKERBELL_CLIENT_MAC=$worker_mac |
| 120 | + TINKERBELL_TEMPLATE_MANIFEST=/manifests/template/ubuntu-equinix-metal.yaml |
| 121 | + TINKERBELL_HARDWARE_MANIFEST=/manifests/hardware/hardware-equinix-metal.json |
| 122 | + EOF |
| 123 | + for line in "${lines[@]}"; do |
| 124 | + grep -q "$line" /sandbox/compose/.env && continue |
| 125 | + echo "$line" >>/sandbox/compose/.env |
| 126 | + done |
| 127 | +} |
| 128 | + |
| 129 | +create_tink_helper_script() { |
| 130 | + cat >/usr/local/bin/tink <<-'EOF' |
| 131 | + #!/usr/bin/env bash |
| 132 | +
|
| 133 | + exec docker-compose -f /sandbox/compose/docker-compose.yml exec tink-cli tink "$@" |
| 134 | + EOF |
| 135 | + chmod +x /usr/local/bin/tink |
| 136 | +} |
| 137 | + |
| 138 | +tweak_bash_interactive_settings() { |
| 139 | + grep -q 'cd /sandbox/compose' ~root/.bashrc || echo 'cd /sandbox/compose' >>~root/.bashrc |
| 140 | + readarray -t aliases <<-EOF |
| 141 | + dc=docker-compose |
| 142 | + EOF |
| 143 | + for alias in "${aliases[@]}"; do |
| 144 | + grep -q "$alias" ~root/.bash_aliases || echo "alias $alias" >>~root/.bash_aliases |
| 145 | + done |
51 | 146 | }
|
52 | 147 |
|
53 |
| -main() ( |
54 |
| - #local provisioner_ip="$1" |
| 148 | +main() { |
| 149 | + worker_mac=$1 |
| 150 | + layer2_ip=192.168.56.4 |
55 | 151 |
|
| 152 | + update_apt |
56 | 153 | install_docker
|
57 | 154 | install_docker_compose
|
58 |
| - restart_docker_service |
59 |
| - mkdir -p /root/sandbox/compose |
| 155 | + install_iptables_persistent |
| 156 | + |
60 | 157 | local layer2_interface
|
61 |
| - layer2_interface="$(get_second_interface_from_bond0)" |
62 |
| - setup_layer2_network "${layer2_interface}" #"${provisioner_ip}" |
63 |
| - make_host_gw_server "${layer2_interface}" "bond0" |
64 |
| -) |
| 158 | + layer2_interface=$(get_second_interface_from_bond0 ${layer2_ip}) |
| 159 | + setup_layer2_network "${layer2_interface}" ${layer2_ip} |
| 160 | + make_host_gw_server "${layer2_interface}" bond0 |
| 161 | + |
| 162 | + extract_compose_files |
| 163 | + setup_compose_env_overrides "$worker_mac" |
| 164 | + docker-compose -f /sandbox/compose/docker-compose.yml up -d |
| 165 | + |
| 166 | + create_tink_helper_script |
| 167 | + tweak_bash_interactive_settings |
| 168 | +} |
| 169 | + |
| 170 | +if [[ ${BASH_SOURCE[0]} == "$0" ]]; then |
| 171 | + set -euxo pipefail |
65 | 172 |
|
66 |
| -main #"$1" |
| 173 | + main "$@" |
| 174 | +fi |
0 commit comments