mirror of
https://gitlab.alpinelinux.org/alpine/cloud/tiny-cloud.git
synced 2026-06-21 00:07:16 +03:00
Compare commits
13 Commits
6d9ff5e264
...
c5988e0141
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c5988e0141 | ||
|
|
6290b1e1bd | ||
|
|
da1e86f4bd | ||
|
|
656aad0896 | ||
|
|
86b4ec351a | ||
|
|
699240945a | ||
|
|
2f0efe508f | ||
|
|
e7175bd9c1 | ||
|
|
584551e331 | ||
|
|
727963829e | ||
|
|
dfe114dbed | ||
|
|
90e028231e | ||
|
|
13a2cc6968 |
@ -1,5 +1,14 @@
|
||||
# CHANGELOG
|
||||
|
||||
## 2026-06-XX - Tiny Cloud v3.3.3
|
||||
|
||||
* Support IPv6 and multiple endpoints
|
||||
[#68](https://gitlab.alpinelinux.org/alpine/cloud/tiny-cloud/-/work_items/68)
|
||||
|
||||
* Check for IP routes to IMDS endpoints before trying them; retry if none are
|
||||
routable. Fixes race condition between `dhcpcd` starting and attempting to
|
||||
reach IMDS before routes are resolved.
|
||||
|
||||
## 2026-06-08 - Tiny Cloud v3.3.2
|
||||
|
||||
* Fixes an autodetect regression introduced in v3.3.1
|
||||
|
||||
1
Makefile
1
Makefile
@ -23,6 +23,7 @@ core: $(MAN1PAGES) $(MAN5PAGES) $(MAN8PAGES)
|
||||
install -Dm644 -t "$(PREFIX)"/usr/lib/tiny-cloud \
|
||||
lib/tiny-cloud/common \
|
||||
lib/tiny-cloud/init \
|
||||
lib/tiny-cloud/network-config \
|
||||
lib/tiny-cloud/tiny-cloud.conf
|
||||
install -Dm644 -t "$(PREFIX)"/usr/lib/tiny-cloud/user-data \
|
||||
lib/tiny-cloud/user-data/*
|
||||
|
||||
20
README.md
20
README.md
@ -41,6 +41,13 @@ instance:
|
||||
|
||||
Other cloud specific and user-data handler specific actions may also occur.
|
||||
|
||||
For the NoCloud provider, Tiny Cloud also supports a subset of
|
||||
`network-config` version 2. The currently supported keys are:
|
||||
`version: 2`, `ethernets`, `dhcp4`, `dhcp6`, `accept-ra`,
|
||||
`match.macaddress`, `set-name`, `addresses`, `gateway4`, `gateway6`,
|
||||
`nameservers.addresses`, `dhcp4-overrides.route-metric`, and
|
||||
`dhcp6-overrides.route-metric`.
|
||||
|
||||
Also included is a handy `imds` client script for easy access to an instance's
|
||||
IMDS data.
|
||||
|
||||
@ -131,6 +138,19 @@ The default endpoint is `169.254.169.254` for most cloud providers. This
|
||||
setting allows you to specify a custom IP address and optional port for the
|
||||
metadata service.
|
||||
|
||||
Multiple endpoints can be configured with `IMDS_ENDPOINTS`. The list is tried
|
||||
in order, and the most recently working endpoint is tried first on later
|
||||
queries. `IMDS_ENDPOINTS` defaults to `IMDS_ENDPOINT` when unset. IPv6 endpoints
|
||||
must use URL-style brackets:
|
||||
|
||||
```sh
|
||||
IMDS_ENDPOINTS="169.254.169.254 [fd00:ec2::254]"
|
||||
```
|
||||
|
||||
Tiny Cloud checks for routes to configured IMDS endpoints before trying metadata
|
||||
requests. `IMDS_ENDPOINT_WAIT_ATTEMPTS` controls how many route checks are made
|
||||
before metadata requests are tried anyway.
|
||||
|
||||
### Metadata API Version
|
||||
|
||||
Each provider's API has a built-in default version. You can override the
|
||||
|
||||
2
TODO.md
2
TODO.md
@ -18,7 +18,7 @@
|
||||
|
||||
* Support for multipart `user-data` payload?
|
||||
|
||||
* Support for `#network-config`?
|
||||
* Support for `#network-config` v1?
|
||||
|
||||
* Support non-`ext[234]` filesystems?
|
||||
|
||||
|
||||
87
bin/imds
87
bin/imds
@ -53,6 +53,9 @@ unset -f \
|
||||
# Common to many clouds
|
||||
# Can be overridden in /etc/tiny-cloud.conf
|
||||
: "${IMDS_ENDPOINT:=169.254.169.254}"
|
||||
: "${IMDS_ENDPOINTS:=$IMDS_ENDPOINT}"
|
||||
: "${IMDS_ENDPOINT_CACHE:=$TINY_CLOUD_VAR/.imds-endpoint}"
|
||||
: "${IMDS_ENDPOINT_WAIT_ATTEMPTS:=10}"
|
||||
|
||||
# Common to AWS and NoCloud(ish)
|
||||
IMDS_HOSTNAME="meta-data/hostname"
|
||||
@ -68,10 +71,88 @@ IMDS_IPV6_NET="subnet-ipv6-cidr-blocks"
|
||||
IMDS_IPV4_PREFIX="ipv4-prefix"
|
||||
IMDS_IPV6_PREFIX="ipv6-prefix"
|
||||
|
||||
_imds_endpoints() {
|
||||
local cached e
|
||||
cached="$(cat "$IMDS_ENDPOINT_CACHE" 2>/dev/null)" || :
|
||||
for e in $IMDS_ENDPOINTS; do
|
||||
[ "$e" = "$cached" ] && echo "$e"
|
||||
done
|
||||
for e in $IMDS_ENDPOINTS; do
|
||||
[ "$e" != "$cached" ] && echo "$e"
|
||||
done
|
||||
}
|
||||
|
||||
_imds_host_port() {
|
||||
local host port
|
||||
case "$1" in
|
||||
\[*\]:*)
|
||||
host="${1#\[}"
|
||||
host="${host%%\]*}"
|
||||
port="${1##*\]:}"
|
||||
;;
|
||||
\[*\])
|
||||
host="${1#\[}"
|
||||
host="${host%\]}"
|
||||
port=80
|
||||
;;
|
||||
*:*)
|
||||
host="${1%:*}"
|
||||
port="${1##*:}"
|
||||
;;
|
||||
*)
|
||||
host="$1"
|
||||
port=80
|
||||
;;
|
||||
esac
|
||||
echo "$host"
|
||||
echo "$port"
|
||||
}
|
||||
|
||||
_imds_has_route() {
|
||||
local host
|
||||
set -- $(_imds_host_port "$1")
|
||||
host="$1"
|
||||
case "$host" in
|
||||
*:*) ip -6 route get "$host" >/dev/null 2>&1 ;;
|
||||
[0-9]*.[0-9]*.[0-9]*.[0-9]*) ip route get "$host" >/dev/null 2>&1 ;;
|
||||
*) return 0 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
_imds() {
|
||||
wget --quiet --timeout 1 --output-document - \
|
||||
--header "$(_imds_header)" \
|
||||
"http://$IMDS_ENDPOINT/$IMDS_URI/$1$IMDS_QUERY"
|
||||
local endpoint endpoints routed attempts=1
|
||||
if [ "$IMDS_ENDPOINT_WAIT_ATTEMPTS" -le 0 ]; then
|
||||
endpoints="$(_imds_endpoints)"
|
||||
fi
|
||||
while :; do
|
||||
[ -n "$endpoints" ] && break
|
||||
endpoints=
|
||||
routed=
|
||||
for endpoint in $(_imds_endpoints); do
|
||||
if _imds_has_route "$endpoint"; then
|
||||
endpoints="$endpoints $endpoint"
|
||||
routed=1
|
||||
fi
|
||||
done
|
||||
[ -n "$routed" ] && break
|
||||
[ "$attempts" -ge "$IMDS_ENDPOINT_WAIT_ATTEMPTS" ] && {
|
||||
endpoints="$(_imds_endpoints)"
|
||||
break
|
||||
}
|
||||
sleep 1
|
||||
attempts=$((attempts + 1))
|
||||
done
|
||||
for endpoint in $endpoints; do
|
||||
IMDS_ENDPOINT="$endpoint"
|
||||
IMDS_CURRENT_ENDPOINT="$endpoint"
|
||||
wget --quiet --timeout 1 --output-document - \
|
||||
--header "$(_imds_header)" \
|
||||
"http://$endpoint/$IMDS_URI/$1$IMDS_QUERY" && {
|
||||
echo "$endpoint" > "$IMDS_ENDPOINT_CACHE"
|
||||
return 0
|
||||
}
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
_imds_userdata() { _imds "$IMDS_USERDATA"; }
|
||||
|
||||
@ -98,6 +98,18 @@ inside *@nic:* queries.
|
||||
*CLOUD*
|
||||
Cloud provider name. When set to *auto*, the autodetected provider is used.
|
||||
|
||||
*IMDS_ENDPOINT*
|
||||
Single provider metadata endpoint. Used as the default value for
|
||||
*IMDS_ENDPOINTS*.
|
||||
|
||||
*IMDS_ENDPOINTS*
|
||||
Whitespace-separated provider metadata endpoint list. IPv6 endpoints must use
|
||||
brackets, for example *[fd00:ec2::254]*.
|
||||
|
||||
*IMDS_ENDPOINT_WAIT_ATTEMPTS*
|
||||
Number of times to check for routes to any IMDS endpoint before trying
|
||||
metadata requests anyway. The default is *10*.
|
||||
|
||||
# EXIT STATUS
|
||||
|
||||
*0*
|
||||
|
||||
@ -79,6 +79,35 @@ Otherwise, the selected phase action list is loaded from the tiny-cloud init
|
||||
library. Each action is run in order. If an action fails, *tiny-cloud* exits
|
||||
with a non-zero status.
|
||||
|
||||
# NOCLOUD NETWORKING
|
||||
|
||||
For the *nocloud* provider, *tiny-cloud* supports the legacy
|
||||
*meta-data* *network-interfaces* and a subset of NoCloud
|
||||
*network-config* version 2.
|
||||
|
||||
Supported *network-config* keys are:
|
||||
|
||||
- *version: 2*
|
||||
- *ethernets*
|
||||
- *dhcp4*
|
||||
- *dhcp6*
|
||||
- *accept-ra*
|
||||
- *match.macaddress*
|
||||
- *set-name*
|
||||
- *addresses*
|
||||
- *gateway4*
|
||||
- *gateway6*
|
||||
- *nameservers.addresses*
|
||||
- *dhcp4-overrides.route-metric*
|
||||
- *dhcp6-overrides.route-metric*
|
||||
|
||||
When `match.macaddress` and `set-name` are used, *tiny-cloud* writes
|
||||
_/etc/iftab_, configures _/etc/conf.d/macifrename_ to use it, and enables
|
||||
and starts the `macifrename` OpenRC service if available.
|
||||
|
||||
Unsupported `network-config` versions or unsupported v2 layouts are ignored
|
||||
with a warning, and normal network fallback behavior applies.
|
||||
|
||||
# FILES
|
||||
|
||||
_/etc/tiny-cloud.conf_
|
||||
@ -87,6 +116,16 @@ _/etc/tiny-cloud.conf_
|
||||
_/etc/tiny-cloud.disabled_
|
||||
When present, suppresses phase execution.
|
||||
|
||||
_/etc/network/interfaces_
|
||||
Generated network interface configuration.
|
||||
|
||||
_/etc/iftab_
|
||||
MAC-based interface rename rules generated from NoCloud *network-config*
|
||||
version 2.
|
||||
|
||||
_/etc/conf.d/macifrename_
|
||||
OpenRC service configuration used when _/etc/iftab_ is generated.
|
||||
|
||||
_/var/lib/cloud/.bootstrap-complete_
|
||||
Bootstrap completion marker.
|
||||
|
||||
|
||||
@ -37,10 +37,20 @@ Blank lines and shell comments are ignored.
|
||||
Provider's API version to use. Providers that have versioned APIs have
|
||||
built-in default values.
|
||||
|
||||
*IMDS_ENDPOINT*=<ip_address>
|
||||
*IMDS_ENDPOINT*=<ip_address[:port]>
|
||||
Provider endpoint IP address to use. Defaults to 169.254.169.254 for many
|
||||
providers.
|
||||
|
||||
*IMDS_ENDPOINTS*=<endpoint> ...
|
||||
Whitespace-separated provider endpoint list. Defaults to *IMDS_ENDPOINT*.
|
||||
Endpoints are tried in order, with the most recently working endpoint tried
|
||||
first on later queries. IPv6 endpoints must use brackets, for example
|
||||
*[fd00:ec2::254]* or *[fd00:ec2::254]:80*.
|
||||
|
||||
*IMDS_ENDPOINT_WAIT_ATTEMPTS*=<number>
|
||||
Number of times to check for routes to any IMDS endpoint before trying
|
||||
metadata requests anyway. The default is *10*.
|
||||
|
||||
*IMDS_TOKEN_TTL*=<seconds>
|
||||
Metadata token lifetime in seconds for AWS metadata access. This is only used
|
||||
by the AWS provider. The default is *5*.
|
||||
|
||||
@ -9,14 +9,18 @@ IMDS_TOKEN_TTL_HEADER="X-aws-ec2-metadata-token-ttl-seconds"
|
||||
IMDS_URI="$IMDS_API_VERSION"
|
||||
|
||||
_imds_token() {
|
||||
local host port
|
||||
# Only try to get token if using IMDSv2
|
||||
# IMDSv1: API versions 2009-04-04 and earlier (no token support)
|
||||
# IMDSv2: API versions 2009-04-05 and later, or 'latest' (requires token)
|
||||
expr "$IMDS_API_VERSION" "<=" "2009-04-04" > /dev/null && return
|
||||
set -- $(_imds_host_port "${IMDS_CURRENT_ENDPOINT:-$IMDS_ENDPOINT}")
|
||||
host="$1"
|
||||
port="$2"
|
||||
# IMDSv2 - request token
|
||||
printf "PUT /latest/api/token HTTP/1.0\r\n%s: %s\r\n\r\n" \
|
||||
"$IMDS_TOKEN_TTL_HEADER" "$IMDS_TOKEN_TTL" \
|
||||
| nc -w 1 "$IMDS_ENDPOINT" 80 | tail -n 1
|
||||
| nc -w 1 "$host" "$port" | tail -n 1
|
||||
}
|
||||
|
||||
_imds_header() {
|
||||
|
||||
@ -45,12 +45,16 @@ want_ephemeral_network() {
|
||||
|
||||
init__set_network_interfaces() {
|
||||
local interfaces="$(imds meta-data/network-interfaces)"
|
||||
local network_config="$TINY_CLOUD_VAR/network-config"
|
||||
mkdir -p "$ETC"/network
|
||||
if [ -n "$interfaces" ]; then
|
||||
printf "%s\n" "$interfaces" > "$ETC"/network/interfaces
|
||||
elif network_config_set "$network_config" "NoCloud"; then
|
||||
:
|
||||
elif ! [ -f "$ETC"/network/interfaces ]; then
|
||||
init__set_default_interfaces
|
||||
fi
|
||||
network_config_setup_macifrename
|
||||
if ! grep -q dhcp "$ETC"/network/interfaces; then
|
||||
set_resolv_conf
|
||||
fi
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
: "${PREFIX:=/usr}"
|
||||
: "${LIBDIR:=$PREFIX/lib}"
|
||||
. "$LIBDIR/tiny-cloud/common"
|
||||
. "$LIBDIR/tiny-cloud/network-config"
|
||||
|
||||
: "${SKIP_INIT_ACTIONS:=}"
|
||||
|
||||
|
||||
165
lib/tiny-cloud/network-config
Normal file
165
lib/tiny-cloud/network-config
Normal file
@ -0,0 +1,165 @@
|
||||
# Tiny Cloud - Network Config Functions
|
||||
# vim:set filetype=sh:
|
||||
# shellcheck shell=sh
|
||||
|
||||
network_config_get() {
|
||||
local file="$1" path="$2"
|
||||
IFS="/"
|
||||
yx -f "$file" $path 2>/dev/null
|
||||
unset IFS
|
||||
}
|
||||
|
||||
network_config_set_v2() {
|
||||
local file="$1" source_name="${2:-network-config}"
|
||||
|
||||
[ -s "$file" ] || return 1
|
||||
|
||||
local ethernets="$(network_config_get "$file" ethernets)"
|
||||
if [ -z "$ethernets" ]; then
|
||||
log -i -t "$phase" warning "$ACTION: $source_name network-config v2 has no supported ethernets entries"
|
||||
return 1
|
||||
fi
|
||||
|
||||
printf "%s\n%s\n\n" \
|
||||
"auto lo" \
|
||||
"iface lo inet loopback" \
|
||||
> "$ETC/network/interfaces"
|
||||
rm -f "$ETC/iftab"
|
||||
|
||||
local iface configured= target_name macaddress
|
||||
for iface in $ethernets; do
|
||||
local stanza= dhcp4= dhcp6= accept_ra= dhcp_program= dhcp_opts=
|
||||
local address= gateway= nameservers= server=
|
||||
local route_metric=
|
||||
|
||||
target_name="$(network_config_get "$file" ethernets/$iface/set-name)"
|
||||
macaddress="$(network_config_get "$file" ethernets/$iface/match/macaddress)"
|
||||
[ -n "$target_name" ] || target_name="$iface"
|
||||
|
||||
if [ -n "$target_name" ] && [ -n "$macaddress" ]; then
|
||||
printf "%s %s\n" "$target_name" "$macaddress" >> "$ETC/iftab"
|
||||
fi
|
||||
|
||||
dhcp4="$(network_config_get "$file" ethernets/$iface/dhcp4)"
|
||||
dhcp6="$(network_config_get "$file" ethernets/$iface/dhcp6)"
|
||||
accept_ra="$(network_config_get "$file" ethernets/$iface/accept-ra)"
|
||||
|
||||
case "$dhcp4" in
|
||||
true|yes)
|
||||
stanza="$stanza\tuse dhcp\n"
|
||||
route_metric="$(network_config_get "$file" ethernets/$iface/dhcp4-overrides/route-metric)"
|
||||
if [ -n "$route_metric" ]; then
|
||||
dhcp_program="dhcpcd"
|
||||
dhcp_opts="$dhcp_opts -m $route_metric"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$dhcp6" in
|
||||
true|yes)
|
||||
case "$dhcp4" in
|
||||
true|yes)
|
||||
route_metric="$(network_config_get "$file" ethernets/$iface/dhcp6-overrides/route-metric)"
|
||||
if [ -n "$route_metric" ]; then
|
||||
dhcp_program="dhcpcd"
|
||||
dhcp_opts="$dhcp_opts -m $route_metric"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
stanza="$stanza\tuse dhcp\n"
|
||||
dhcp_program="dhcpcd"
|
||||
dhcp_opts="$dhcp_opts -6"
|
||||
route_metric="$(network_config_get "$file" ethernets/$iface/dhcp6-overrides/route-metric)"
|
||||
if [ -n "$route_metric" ]; then
|
||||
dhcp_opts="$dhcp_opts -m $route_metric"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$accept_ra" in
|
||||
true|yes)
|
||||
stanza="$stanza\tuse ipv6-ra\n"
|
||||
;;
|
||||
esac
|
||||
|
||||
address="$(network_config_get "$file" ethernets/$iface/addresses/1)"
|
||||
if [ -n "$address" ]; then
|
||||
stanza="$stanza\taddress $address\n"
|
||||
gateway="$(network_config_get "$file" ethernets/$iface/gateway4)"
|
||||
[ -n "$gateway" ] || gateway="$(network_config_get "$file" ethernets/$iface/gateway6)"
|
||||
if [ -n "$gateway" ]; then
|
||||
stanza="$stanza\tgateway $gateway\n"
|
||||
fi
|
||||
nameservers="$(network_config_get "$file" ethernets/$iface/nameservers/addresses)"
|
||||
for server in $nameservers; do
|
||||
add_once "$ETC/resolv.conf" \
|
||||
"nameserver $(network_config_get "$file" ethernets/$iface/nameservers/addresses/$server)"
|
||||
done
|
||||
fi
|
||||
|
||||
if [ -n "$dhcp_program" ]; then
|
||||
stanza="$stanza\tdhcp-program $dhcp_program\n"
|
||||
fi
|
||||
if [ -n "$dhcp_opts" ]; then
|
||||
stanza="$stanza\tdhcp-opts${dhcp_opts}\n"
|
||||
fi
|
||||
|
||||
[ -n "$stanza" ] || continue
|
||||
|
||||
printf "%s\n%s\n%b\n" \
|
||||
"auto $target_name" \
|
||||
"iface $target_name" \
|
||||
"$stanza" >> "$ETC/network/interfaces"
|
||||
configured=1
|
||||
done
|
||||
|
||||
if [ -z "$configured" ]; then
|
||||
log -i -t "$phase" warning "$ACTION: $source_name network-config v2 has no supported ethernets entries"
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
network_config_set() {
|
||||
local file="$1" source_name="${2:-network-config}"
|
||||
|
||||
[ -s "$file" ] || return 1
|
||||
|
||||
local version="$(network_config_get "$file" version)"
|
||||
case "$version" in
|
||||
2)
|
||||
network_config_set_v2 "$file" "$source_name"
|
||||
;;
|
||||
*)
|
||||
log -i -t "$phase" warning "$ACTION: unsupported $source_name network-config version: ${version:-unknown}"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
network_config_setup_macifrename() {
|
||||
[ -s "$ETC/iftab" ] || return 0
|
||||
|
||||
if ! [ -e "$ETC/init.d/macifrename" ]; then
|
||||
log -i -t "$phase" warning "$ACTION: macifrename service not installed; interface renames will not be applied"
|
||||
return 0
|
||||
fi
|
||||
|
||||
mkdir -p "$ETC/conf.d"
|
||||
if [ -f "$ETC/conf.d/macifrename" ]; then
|
||||
if grep -q '^MACIFRENAME_OPTS=' "$ETC/conf.d/macifrename"; then
|
||||
sed -i -e 's|^MACIFRENAME_OPTS=.*|MACIFRENAME_OPTS="/etc/iftab"|' \
|
||||
"$ETC/conf.d/macifrename"
|
||||
else
|
||||
printf '%s\n' 'MACIFRENAME_OPTS="/etc/iftab"' >> "$ETC/conf.d/macifrename"
|
||||
fi
|
||||
else
|
||||
printf '%s\n' 'MACIFRENAME_OPTS="/etc/iftab"' > "$ETC/conf.d/macifrename"
|
||||
fi
|
||||
|
||||
$MOCK rc-update add macifrename boot
|
||||
$MOCK rc-service macifrename start
|
||||
}
|
||||
@ -13,6 +13,14 @@
|
||||
# Useful for custom metadata services
|
||||
#IMDS_ENDPOINT=169.254.169.254
|
||||
|
||||
# Ordered IMDS endpoint list. Defaults to IMDS_ENDPOINT.
|
||||
# IPv6 endpoints must use brackets: [fd00:ec2::254] or [fd00:ec2::254]:80
|
||||
#IMDS_ENDPOINTS="169.254.169.254 [fd00:ec2::254]"
|
||||
|
||||
# Number of times to check for routes to any IMDS endpoint before trying
|
||||
# metadata requests anyway.
|
||||
#IMDS_ENDPOINT_WAIT_ATTEMPTS=10
|
||||
|
||||
# IMDS API version
|
||||
# Most providers have a default version, overrideable here if necessary
|
||||
#IMDS_API_VERSION=""
|
||||
|
||||
@ -78,11 +78,19 @@ for url; do
|
||||
esac
|
||||
done
|
||||
|
||||
host="${url#http*://}"
|
||||
host="${host%%/*}"
|
||||
path="${url#http*://$host}"
|
||||
url_no_scheme="${url#*://}"
|
||||
case "$url_no_scheme" in
|
||||
*/*) host="${url_no_scheme%%/*}"; path="/${url_no_scheme#*/}";;
|
||||
*) host="$url_no_scheme"; path=/;;
|
||||
esac
|
||||
path="${path#${WGET_STRIP_PREFIX:-/}}"
|
||||
path="${path%\?*}"
|
||||
[ -n "$WGET_HOST_LOG" ] && echo "$host" >> "$WGET_HOST_LOG"
|
||||
case "$host" in
|
||||
\[*\]:*) yaml_host="${host#\[}"; yaml_host="${yaml_host%%\]*}";;
|
||||
\[*\]) yaml_host="${host#\[}"; yaml_host="${yaml_host%\]}";;
|
||||
*) yaml_host="$host";;
|
||||
esac
|
||||
|
||||
|
||||
if [ -z "$WGETCONTENT" ]; then
|
||||
@ -93,7 +101,7 @@ if [ -z "$WGETCONTENT" ]; then
|
||||
(
|
||||
IFS=/
|
||||
set -- ${path#/}
|
||||
yx -f "${WGET_YAML:-$host.yaml}" "$@" 2>/dev/null
|
||||
yx -f "${WGET_YAML:-$yaml_host.yaml}" "$@" 2>/dev/null
|
||||
)
|
||||
fi
|
||||
fi
|
||||
@ -107,4 +115,3 @@ case "$outfile" in
|
||||
echo "$WGETCONTENT" > "$outfile"
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
103
tests/imds.test
103
tests/imds.test
@ -10,6 +10,11 @@ PROVIDERS="aws azure digitalocean gcp hetzner incus oci nocloud scaleway"
|
||||
init_tests \
|
||||
imds_help \
|
||||
imds_space \
|
||||
imds_endpoint_fallback \
|
||||
imds_endpoint_cache \
|
||||
imds_endpoint_ipv6 \
|
||||
imds_endpoint_route_skip \
|
||||
imds_endpoint_route_wait \
|
||||
\
|
||||
imds_hostname_aws \
|
||||
imds_hostname_azure \
|
||||
@ -44,6 +49,7 @@ init_tests \
|
||||
imds_aws_api_version_imdsv1 \
|
||||
imds_aws_api_version_imdsv2_explicit \
|
||||
imds_aws_api_version_imdsv2_latest \
|
||||
imds_aws_token_endpoint_port \
|
||||
\
|
||||
imds_nocloud_cmdline_local_hostname \
|
||||
imds_nocloud_smbios_local_hostname \
|
||||
@ -63,6 +69,81 @@ imds_space_body() {
|
||||
done
|
||||
}
|
||||
|
||||
imds_endpoint_fallback_body() {
|
||||
IMDS_API_VERSION=2009-04-04 CLOUD=aws fake_metadata aws <<-EOF
|
||||
hostname: myhostname
|
||||
EOF
|
||||
IMDS_API_VERSION=2009-04-04 IMDS_ENDPOINT_WAIT_ATTEMPTS=0 \
|
||||
IMDS_ENDPOINTS="fail 169.254.169.254" CLOUD=aws atf_check \
|
||||
-o match:"myhostname" \
|
||||
imds @hostname
|
||||
atf_check -o match:"^169.254.169.254$" cat var/lib/cloud/.imds-endpoint
|
||||
}
|
||||
|
||||
imds_endpoint_cache_body() {
|
||||
mkdir -p var/lib/cloud
|
||||
echo "cached.example" > var/lib/cloud/.imds-endpoint
|
||||
cat > cached.example.yaml <<-EOF
|
||||
hostname: cached-hostname
|
||||
EOF
|
||||
cat > first.example.yaml <<-EOF
|
||||
hostname: first-hostname
|
||||
EOF
|
||||
IMDS_API_VERSION=2009-04-04 IMDS_ENDPOINT_WAIT_ATTEMPTS=0 \
|
||||
WGET_STRIP_PREFIX="/2009-04-04/meta-data" \
|
||||
WGET_HOST_LOG="$PWD/hosts.log" \
|
||||
IMDS_ENDPOINTS="first.example cached.example" CLOUD=aws atf_check \
|
||||
-o match:"cached-hostname" \
|
||||
imds @hostname
|
||||
atf_check -o match:"^cached.example$" head -n 1 hosts.log
|
||||
}
|
||||
|
||||
imds_endpoint_ipv6_body() {
|
||||
cat > "fd00:ec2::254.yaml" <<-EOF
|
||||
hostname: ipv6-hostname
|
||||
EOF
|
||||
IMDS_API_VERSION=2009-04-04 IMDS_ENDPOINT_WAIT_ATTEMPTS=0 \
|
||||
WGET_STRIP_PREFIX="/2009-04-04/meta-data" \
|
||||
WGET_HOST_LOG="$PWD/hosts.log" \
|
||||
IMDS_ENDPOINTS="[fd00:ec2::254]" CLOUD=aws atf_check \
|
||||
-o match:"ipv6-hostname" \
|
||||
imds @hostname
|
||||
atf_check -o match:"^\\[fd00:ec2::254\\]$" cat hosts.log
|
||||
}
|
||||
|
||||
imds_endpoint_route_skip_body() {
|
||||
IMDS_API_VERSION=2009-04-04 CLOUD=aws fake_metadata aws <<-EOF
|
||||
hostname: myhostname
|
||||
EOF
|
||||
fake_bin ip <<-'EOF'
|
||||
#!/bin/sh
|
||||
[ "$3" = 169.254.169.254 ]
|
||||
EOF
|
||||
IMDS_API_VERSION=2009-04-04 IMDS_ENDPOINT_WAIT_ATTEMPTS=1 \
|
||||
IMDS_ENDPOINTS="192.0.2.1 169.254.169.254" CLOUD=aws atf_check \
|
||||
-o match:"myhostname" \
|
||||
imds @hostname
|
||||
atf_check -o match:"^169.254.169.254$" cat var/lib/cloud/.imds-endpoint
|
||||
}
|
||||
|
||||
imds_endpoint_route_wait_body() {
|
||||
IMDS_API_VERSION=2009-04-04 CLOUD=aws fake_metadata aws <<-EOF
|
||||
hostname: myhostname
|
||||
EOF
|
||||
fake_bin ip <<-'EOF'
|
||||
#!/bin/sh
|
||||
mkdir -p tmp
|
||||
count=$(cat tmp/route-count 2>/dev/null || echo 0)
|
||||
count=$((count + 1))
|
||||
echo "$count" > tmp/route-count
|
||||
[ "$count" -gt 1 ]
|
||||
EOF
|
||||
IMDS_API_VERSION=2009-04-04 IMDS_ENDPOINT_WAIT_ATTEMPTS=5 CLOUD=aws atf_check \
|
||||
-o match:"myhostname" \
|
||||
imds @hostname
|
||||
atf_check -o match:"^2$" cat tmp/route-count
|
||||
}
|
||||
|
||||
check_hostname() {
|
||||
fake_metadata "$1" <<-EOF
|
||||
# aws, digitalocean, hetzner, nocloud
|
||||
@ -251,6 +332,28 @@ imds_aws_api_version_imdsv2_latest_body() {
|
||||
imds @hostname
|
||||
}
|
||||
|
||||
imds_aws_token_endpoint_port_body() {
|
||||
cat > "fd00:ec2::254.yaml" <<-EOF
|
||||
hostname: test-imdsv2-port
|
||||
EOF
|
||||
fake_bin nc <<-'NCEOF'
|
||||
#!/bin/sh
|
||||
while [ -n "$1" ]; do
|
||||
case "$1" in
|
||||
-w) shift 2;;
|
||||
*) echo "$1" >> nc.args; shift;;
|
||||
esac
|
||||
done
|
||||
cat > /dev/null
|
||||
printf "HTTP/1.0 200 OK\r\n\r\nmock-token"
|
||||
NCEOF
|
||||
IMDS_API_VERSION=latest WGET_STRIP_PREFIX="/latest/meta-data" \
|
||||
IMDS_ENDPOINTS="[fd00:ec2::254]:8080" CLOUD=aws atf_check \
|
||||
-o match:"test-imdsv2-port" \
|
||||
imds @hostname
|
||||
atf_check -o match:"^fd00:ec2::254 8080 $" sh -c "tr '\n' ' ' < nc.args"
|
||||
}
|
||||
|
||||
imds_nocloud_cmdline_local_hostname_body() {
|
||||
atf_require_prog yx
|
||||
mkdir proc
|
||||
|
||||
@ -6,6 +6,7 @@ PATH="$atf_srcdir/bin:$srcdir/bin:$srcdir/sbin:$PATH"
|
||||
|
||||
export TINY_CLOUD_BASEDIR="$srcdir"
|
||||
export ROOT="$PWD"
|
||||
export IMDS_ENDPOINT_WAIT_ATTEMPTS=0
|
||||
|
||||
|
||||
init_tests() {
|
||||
@ -36,7 +37,7 @@ fake_umount() {
|
||||
while ! [ -d "\$1" ]; do
|
||||
shift
|
||||
done
|
||||
rm -f "\$1"/meta-data "\$1"/user-data
|
||||
rm -f "\$1"/meta-data "\$1"/user-data "\$1"/network-config
|
||||
EOF
|
||||
}
|
||||
|
||||
@ -64,6 +65,10 @@ fake_userdata_nocloud() {
|
||||
fake_data_nocloud user-data
|
||||
}
|
||||
|
||||
fake_network_config_nocloud() {
|
||||
fake_data_nocloud network-config
|
||||
}
|
||||
|
||||
fake_metadata_aws() {
|
||||
cat > "169.254.169.254.yaml"
|
||||
export WGET_STRIP_PREFIX="/${IMDS_API_VERSION:-latest}/meta-data"
|
||||
|
||||
@ -11,6 +11,15 @@ export CLOUD=nocloud
|
||||
init_tests \
|
||||
set_ephemeral_network_cmdline \
|
||||
set_network_config_network_interfaces \
|
||||
set_network_config_v2_dhcp4 \
|
||||
set_network_config_v2_match_macaddress_set_name_dhcp4 \
|
||||
set_network_config_v2_configures_macifrename_service \
|
||||
set_network_config_v2_static_ipv4 \
|
||||
set_network_config_v2_static_ipv6 \
|
||||
set_network_config_v2_dhcp6 \
|
||||
set_network_config_v2_accept_ra \
|
||||
set_network_config_v2_dhcp4_route_metric \
|
||||
set_network_config_v2_dhcp6_route_metric \
|
||||
set_network_config_auto \
|
||||
userdata_user_name \
|
||||
userdata_user_homedir \
|
||||
@ -100,6 +109,254 @@ set_network_config_network_interfaces_body() {
|
||||
cat etc/resolv.conf
|
||||
}
|
||||
|
||||
set_network_config_v2_dhcp4_body() {
|
||||
fake_network_config_nocloud <<-EOF
|
||||
version: 2
|
||||
ethernets:
|
||||
eth1:
|
||||
dhcp4: true
|
||||
EOF
|
||||
|
||||
atf_check \
|
||||
-o match:"rc-update" \
|
||||
-e match:"set_network_interfaces: done" \
|
||||
tiny-cloud boot
|
||||
|
||||
atf_check \
|
||||
-o match:"auto eth1" \
|
||||
-o match:"iface eth1" \
|
||||
-o match:"use dhcp" \
|
||||
cat etc/network/interfaces
|
||||
}
|
||||
|
||||
set_network_config_v2_match_macaddress_set_name_dhcp4_body() {
|
||||
fake_network_config_nocloud <<-EOF
|
||||
version: 2
|
||||
ethernets:
|
||||
net0:
|
||||
match:
|
||||
macaddress: 52:55:55:1d:2a:0b
|
||||
set-name: lima0
|
||||
dhcp4: true
|
||||
EOF
|
||||
|
||||
atf_check \
|
||||
-o match:"rc-update" \
|
||||
-e match:"set_network_interfaces: done" \
|
||||
tiny-cloud boot
|
||||
|
||||
atf_check \
|
||||
-o match:"auto lima0" \
|
||||
-o match:"iface lima0" \
|
||||
-o match:"use dhcp" \
|
||||
cat etc/network/interfaces
|
||||
|
||||
atf_check \
|
||||
-o match:"^lima0 52:55:55:1d:2a:0b$" \
|
||||
cat etc/iftab
|
||||
}
|
||||
|
||||
set_network_config_v2_configures_macifrename_service_body() {
|
||||
mkdir -p etc/conf.d etc/init.d
|
||||
cat > etc/conf.d/macifrename <<-EOF
|
||||
MACIFRENAME_OPTS="/etc/foo"
|
||||
EOF
|
||||
touch etc/init.d/macifrename
|
||||
|
||||
fake_network_config_nocloud <<-EOF
|
||||
version: 2
|
||||
ethernets:
|
||||
net0:
|
||||
match:
|
||||
macaddress: 52:55:55:1d:2a:0b
|
||||
set-name: lima0
|
||||
dhcp4: true
|
||||
EOF
|
||||
|
||||
atf_check \
|
||||
-o match:"rc-update add macifrename boot" \
|
||||
-o match:"rc-service macifrename start" \
|
||||
-o match:"rc-update add sshd default" \
|
||||
-e match:"set_network_interfaces: done" \
|
||||
tiny-cloud boot
|
||||
|
||||
atf_check \
|
||||
-o match:'^MACIFRENAME_OPTS="/etc/iftab"$' \
|
||||
cat etc/conf.d/macifrename
|
||||
}
|
||||
|
||||
set_network_config_v2_static_ipv4_body() {
|
||||
fake_network_config_nocloud <<-EOF
|
||||
version: 2
|
||||
ethernets:
|
||||
net0:
|
||||
match:
|
||||
macaddress: 52:55:55:1d:2a:0b
|
||||
set-name: lima0
|
||||
addresses:
|
||||
- 192.168.100.10/24
|
||||
gateway4: 192.168.100.1
|
||||
nameservers:
|
||||
addresses:
|
||||
- 8.8.8.8
|
||||
- 8.8.4.4
|
||||
EOF
|
||||
|
||||
atf_check \
|
||||
-o ignore \
|
||||
-e match:"set_network_interfaces: done" \
|
||||
tiny-cloud boot
|
||||
|
||||
atf_check \
|
||||
-o match:"auto lima0" \
|
||||
-o match:"iface lima0" \
|
||||
-o match:"address 192.168.100.10/24" \
|
||||
-o match:"gateway 192.168.100.1" \
|
||||
cat etc/network/interfaces
|
||||
|
||||
atf_check \
|
||||
-o match:"^nameserver 8.8.8.8$" \
|
||||
-o match:"^nameserver 8.8.4.4$" \
|
||||
cat etc/resolv.conf
|
||||
}
|
||||
|
||||
set_network_config_v2_static_ipv6_body() {
|
||||
fake_network_config_nocloud <<-EOF
|
||||
version: 2
|
||||
ethernets:
|
||||
net0:
|
||||
match:
|
||||
macaddress: 52:55:55:1d:2a:0b
|
||||
set-name: lima0
|
||||
addresses:
|
||||
- 2001:db8::10/64
|
||||
gateway6: 2001:db8::1
|
||||
nameservers:
|
||||
addresses:
|
||||
- 2001:4860:4860::8888
|
||||
- 2001:4860:4860::8844
|
||||
EOF
|
||||
|
||||
atf_check \
|
||||
-o ignore \
|
||||
-e match:"set_network_interfaces: done" \
|
||||
tiny-cloud boot
|
||||
|
||||
atf_check \
|
||||
-o match:"auto lima0" \
|
||||
-o match:"iface lima0" \
|
||||
-o match:"address 2001:db8::10/64" \
|
||||
-o match:"gateway 2001:db8::1" \
|
||||
cat etc/network/interfaces
|
||||
|
||||
atf_check \
|
||||
-o match:"^nameserver 2001:4860:4860::8888$" \
|
||||
-o match:"^nameserver 2001:4860:4860::8844$" \
|
||||
cat etc/resolv.conf
|
||||
}
|
||||
|
||||
set_network_config_v2_dhcp6_body() {
|
||||
fake_network_config_nocloud <<-EOF
|
||||
version: 2
|
||||
ethernets:
|
||||
net0:
|
||||
match:
|
||||
macaddress: 52:55:55:1d:2a:0b
|
||||
set-name: lima0
|
||||
dhcp6: true
|
||||
EOF
|
||||
|
||||
atf_check \
|
||||
-o ignore \
|
||||
-e match:"set_network_interfaces: done" \
|
||||
tiny-cloud boot
|
||||
|
||||
atf_check \
|
||||
-o match:"auto lima0" \
|
||||
-o match:"iface lima0" \
|
||||
-o match:"use dhcp" \
|
||||
-o match:"dhcp-program dhcpcd" \
|
||||
-o match:"dhcp-opts -6" \
|
||||
cat etc/network/interfaces
|
||||
}
|
||||
|
||||
set_network_config_v2_accept_ra_body() {
|
||||
fake_network_config_nocloud <<-EOF
|
||||
version: 2
|
||||
ethernets:
|
||||
net0:
|
||||
match:
|
||||
macaddress: 52:55:55:1d:2a:0b
|
||||
set-name: lima0
|
||||
accept-ra: true
|
||||
EOF
|
||||
|
||||
atf_check \
|
||||
-o ignore \
|
||||
-e match:"set_network_interfaces: done" \
|
||||
tiny-cloud boot
|
||||
|
||||
atf_check \
|
||||
-o match:"auto lima0" \
|
||||
-o match:"iface lima0" \
|
||||
-o match:"use ipv6-ra" \
|
||||
cat etc/network/interfaces
|
||||
}
|
||||
|
||||
set_network_config_v2_dhcp4_route_metric_body() {
|
||||
fake_network_config_nocloud <<-EOF
|
||||
version: 2
|
||||
ethernets:
|
||||
net0:
|
||||
match:
|
||||
macaddress: 52:55:55:1d:2a:0b
|
||||
set-name: lima0
|
||||
dhcp4: true
|
||||
dhcp4-overrides:
|
||||
route-metric: 200
|
||||
EOF
|
||||
|
||||
atf_check \
|
||||
-o ignore \
|
||||
-e match:"set_network_interfaces: done" \
|
||||
tiny-cloud boot
|
||||
|
||||
atf_check \
|
||||
-o match:"auto lima0" \
|
||||
-o match:"iface lima0" \
|
||||
-o match:"use dhcp" \
|
||||
-o match:"dhcp-program dhcpcd" \
|
||||
-o match:"dhcp-opts -m 200" \
|
||||
cat etc/network/interfaces
|
||||
}
|
||||
|
||||
set_network_config_v2_dhcp6_route_metric_body() {
|
||||
fake_network_config_nocloud <<-EOF
|
||||
version: 2
|
||||
ethernets:
|
||||
net0:
|
||||
match:
|
||||
macaddress: 52:55:55:1d:2a:0b
|
||||
set-name: lima0
|
||||
dhcp6: true
|
||||
dhcp6-overrides:
|
||||
route-metric: 100
|
||||
EOF
|
||||
|
||||
atf_check \
|
||||
-o ignore \
|
||||
-e match:"set_network_interfaces: done" \
|
||||
tiny-cloud boot
|
||||
|
||||
atf_check \
|
||||
-o match:"auto lima0" \
|
||||
-o match:"iface lima0" \
|
||||
-o match:"use dhcp" \
|
||||
-o match:"dhcp-program dhcpcd" \
|
||||
-o match:"dhcp-opts -6 -m 100" \
|
||||
cat etc/network/interfaces
|
||||
}
|
||||
|
||||
set_network_config_auto_body() {
|
||||
fake_metadata_nocloud <<-EOF
|
||||
resolv_conf:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user