316 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Bash
		
	
	
	
			
		
		
	
	
			316 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Bash
		
	
	
	
#!/usr/bin/env bats
 | 
						|
 | 
						|
load helpers
 | 
						|
 | 
						|
# This is a long ugly way to clean up pods and remove the pause image
 | 
						|
function teardown() {
 | 
						|
    run_podman pod rm -f -a
 | 
						|
    run_podman rm -f -a
 | 
						|
    run_podman image list --format '{{.ID}} {{.Repository}}'
 | 
						|
    while read id name; do
 | 
						|
        if [[ "$name" =~ /pause ]]; then
 | 
						|
            run_podman rmi $id
 | 
						|
        fi
 | 
						|
    done <<<"$output"
 | 
						|
 | 
						|
    basic_teardown
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
@test "podman pod - basic tests" {
 | 
						|
    run_podman pod list --noheading
 | 
						|
    is "$output" "" "baseline: empty results from list --noheading"
 | 
						|
 | 
						|
    run_podman pod ls --noheading
 | 
						|
    is "$output" "" "baseline: empty results from ls --noheading"
 | 
						|
 | 
						|
    run_podman pod ps --noheading
 | 
						|
    is "$output" "" "baseline: empty results from ps --noheading"
 | 
						|
}
 | 
						|
 | 
						|
@test "podman pod top - containers in different PID namespaces" {
 | 
						|
    # With infra=false, we don't get a /pause container (we also
 | 
						|
    # don't pull k8s.gcr.io/pause )
 | 
						|
    no_infra='--infra=false'
 | 
						|
    run_podman pod create $no_infra
 | 
						|
    podid="$output"
 | 
						|
 | 
						|
    # Start two containers...
 | 
						|
    run_podman run -d --pod $podid $IMAGE top -d 2
 | 
						|
    cid1="$output"
 | 
						|
    run_podman run -d --pod $podid $IMAGE top -d 2
 | 
						|
    cid2="$output"
 | 
						|
 | 
						|
    # ...and wait for them to actually start.
 | 
						|
    wait_for_output "PID \+PPID \+USER " $cid1
 | 
						|
    wait_for_output "PID \+PPID \+USER " $cid2
 | 
						|
 | 
						|
    # Both containers have emitted at least one top-like line.
 | 
						|
    # Now run 'pod top', and expect two 'top -d 2' processes running.
 | 
						|
    run_podman pod top $podid
 | 
						|
    is "$output" ".*root.*top -d 2.*root.*top -d 2" "two 'top' containers"
 | 
						|
 | 
						|
    # By default (podman pod create w/ default --infra) there should be
 | 
						|
    # a /pause container.
 | 
						|
    if [ -z "$no_infra" ]; then
 | 
						|
        is "$output" ".*0 \+1 \+0 \+[0-9. ?s]\+/pause" "there is a /pause container"
 | 
						|
    fi
 | 
						|
 | 
						|
    # Clean up
 | 
						|
    run_podman pod rm -f $podid
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
@test "podman pod - communicating between pods" {
 | 
						|
    podname=pod$(random_string)
 | 
						|
    run_podman 1 pod exists $podname
 | 
						|
    run_podman pod create --infra=true --name=$podname
 | 
						|
    podid="$output"
 | 
						|
    run_podman pod exists $podname
 | 
						|
    run_podman pod exists $podid
 | 
						|
 | 
						|
    # (Assert that output is formatted, not a one-line blob: #8021)
 | 
						|
    run_podman pod inspect $podname
 | 
						|
    if [[ "${#lines[*]}" -lt 10 ]]; then
 | 
						|
        die "Output from 'pod inspect' is only ${#lines[*]} lines; see #8011"
 | 
						|
    fi
 | 
						|
 | 
						|
    # Randomly-assigned port in the 5xxx range
 | 
						|
    for port in $(shuf -i 5000-5999);do
 | 
						|
        if ! { exec 3<> /dev/tcp/127.0.0.1/$port; } &>/dev/null; then
 | 
						|
            break
 | 
						|
        fi
 | 
						|
    done
 | 
						|
 | 
						|
    # Listener. This will exit as soon as it receives a message.
 | 
						|
    run_podman run -d --pod $podname $IMAGE nc -l -p $port
 | 
						|
    cid1="$output"
 | 
						|
 | 
						|
    # (While we're here, test the 'Pod' field of 'podman ps'. Expect two ctrs)
 | 
						|
    run_podman ps --format '{{.Pod}}'
 | 
						|
    newline="
 | 
						|
"
 | 
						|
    is "$output" "${podid:0:12}${newline}${podid:0:12}" "ps shows 2 pod IDs"
 | 
						|
 | 
						|
    # Talker: send the message via common port on localhost
 | 
						|
    message=$(random_string 15)
 | 
						|
    run_podman run --rm --pod $podname $IMAGE \
 | 
						|
               sh -c "echo $message | nc 127.0.0.1 $port"
 | 
						|
 | 
						|
    # Back to the first (listener) container. Make sure message was received.
 | 
						|
    run_podman logs $cid1
 | 
						|
    is "$output" "$message" "message sent from one container to another"
 | 
						|
 | 
						|
    # Clean up. First the nc -l container...
 | 
						|
    run_podman rm $cid1
 | 
						|
 | 
						|
    # ...then, from pause container, find the image ID of the pause image...
 | 
						|
    run_podman pod inspect --format '{{(index .Containers 0).ID}}' $podname
 | 
						|
    pause_cid="$output"
 | 
						|
    run_podman container inspect --format '{{.Image}}' $pause_cid
 | 
						|
    pause_iid="$output"
 | 
						|
 | 
						|
    # ...then rm the pod, then rmi the pause image so we don't leave strays.
 | 
						|
    run_podman pod rm $podname
 | 
						|
    run_podman rmi $pause_iid
 | 
						|
 | 
						|
    # Pod no longer exists
 | 
						|
    run_podman 1 pod exists $podid
 | 
						|
    run_podman 1 pod exists $podname
 | 
						|
}
 | 
						|
 | 
						|
@test "podman pod - communicating via /dev/shm " {
 | 
						|
    podname=pod$(random_string)
 | 
						|
    run_podman 1 pod exists $podname
 | 
						|
    run_podman pod create --infra=true --name=$podname
 | 
						|
    podid="$output"
 | 
						|
    run_podman pod exists $podname
 | 
						|
    run_podman pod exists $podid
 | 
						|
 | 
						|
    run_podman run --rm --pod $podname $IMAGE touch /dev/shm/test1
 | 
						|
    run_podman run --rm --pod $podname $IMAGE ls /dev/shm/test1
 | 
						|
    is "$output" "/dev/shm/test1"
 | 
						|
 | 
						|
    # ...then rm the pod, then rmi the pause image so we don't leave strays.
 | 
						|
    run_podman pod rm $podname
 | 
						|
 | 
						|
    # Pod no longer exists
 | 
						|
    run_podman 1 pod exists $podid
 | 
						|
    run_podman 1 pod exists $podname
 | 
						|
}
 | 
						|
 | 
						|
# Random byte
 | 
						|
function octet() {
 | 
						|
    echo $(( $RANDOM & 255 ))
 | 
						|
}
 | 
						|
 | 
						|
# random MAC address: convention seems to be that 2nd lsb=1, lsb=0
 | 
						|
# (i.e. 0bxxxxxx10) in the first octet guarantees a private space.
 | 
						|
# FIXME: I can't find a definitive reference for this though
 | 
						|
# Generate the address IN CAPS (A-F), but we will test it in lowercase.
 | 
						|
function random_mac() {
 | 
						|
    local mac=$(printf "%02X" $(( $(octet) & 242 | 2 )) )
 | 
						|
    for i in $(seq 2 6); do
 | 
						|
        mac+=$(printf ":%02X" $(octet))
 | 
						|
    done
 | 
						|
 | 
						|
    echo $mac
 | 
						|
}
 | 
						|
 | 
						|
# Random RFC1918 IP address
 | 
						|
function random_ip() {
 | 
						|
    local ip="172.20"
 | 
						|
    for i in 1 2;do
 | 
						|
        ip+=$(printf ".%d" $(octet))
 | 
						|
    done
 | 
						|
    echo $ip
 | 
						|
}
 | 
						|
 | 
						|
@test "podman pod create - hashtag AllTheOptions" {
 | 
						|
    mac=$(random_mac)
 | 
						|
    add_host_ip=$(random_ip)
 | 
						|
    add_host_n=$(random_string | tr A-Z a-z).$(random_string | tr A-Z a-z).xyz
 | 
						|
 | 
						|
    dns_server=$(random_ip)
 | 
						|
    dns_opt="ndots:$(octet)"
 | 
						|
    dns_search=$(random_string 15 | tr A-Z a-z).abc
 | 
						|
 | 
						|
    hostname=$(random_string | tr A-Z a-z).$(random_string | tr A-Z a-z).net
 | 
						|
 | 
						|
    labelname=$(random_string 11)
 | 
						|
    labelvalue=$(random_string 22)
 | 
						|
 | 
						|
    pod_id_file=${PODMAN_TMPDIR}/pod-id-file
 | 
						|
 | 
						|
    # Randomly-assigned ports in the 5xxx and 6xxx range
 | 
						|
    for port_in in $(shuf -i 5000-5999);do
 | 
						|
        if ! { exec 3<> /dev/tcp/127.0.0.1/$port_in; } &>/dev/null; then
 | 
						|
            break
 | 
						|
        fi
 | 
						|
    done
 | 
						|
    for port_out in $(shuf -i 6000-6999);do
 | 
						|
        if ! { exec 3<> /dev/tcp/127.0.0.1/$port_out; } &>/dev/null; then
 | 
						|
            break
 | 
						|
        fi
 | 
						|
    done
 | 
						|
 | 
						|
    # Create a pod with all the desired options
 | 
						|
    # FIXME: --ip=$ip fails:
 | 
						|
    #      Error adding network: failed to allocate all requested IPs
 | 
						|
    local mac_option="--mac-address=$mac"
 | 
						|
 | 
						|
    # Create a custom image so we can test --infra-image and -command.
 | 
						|
    # It will have a randomly generated infra command, using the
 | 
						|
    # existing 'pause' script in our testimage. We assign a bogus
 | 
						|
    # entrypoint to confirm that --infra-command will override.
 | 
						|
    local infra_image="infra_$(random_string 10 | tr A-Z a-z)"
 | 
						|
    local infra_command="/pause_$(random_string 10)"
 | 
						|
    run_podman build -t $infra_image - << EOF
 | 
						|
FROM $IMAGE
 | 
						|
RUN ln /home/podman/pause $infra_command
 | 
						|
ENTRYPOINT ["/original-entrypoint-should-be-overridden"]
 | 
						|
EOF
 | 
						|
 | 
						|
    if is_rootless; then
 | 
						|
        mac_option=
 | 
						|
    fi
 | 
						|
    run_podman pod create --name=mypod                   \
 | 
						|
               --pod-id-file=$pod_id_file                \
 | 
						|
               $mac_option                               \
 | 
						|
               --hostname=$hostname                      \
 | 
						|
               --add-host   "$add_host_n:$add_host_ip"   \
 | 
						|
               --dns        "$dns_server"                \
 | 
						|
               --dns-search "$dns_search"                \
 | 
						|
               --dns-opt    "$dns_opt"                   \
 | 
						|
               --publish    "$port_out:$port_in"         \
 | 
						|
               --label      "${labelname}=${labelvalue}" \
 | 
						|
               --infra-image   "$infra_image"            \
 | 
						|
               --infra-command "$infra_command"
 | 
						|
    pod_id="$output"
 | 
						|
 | 
						|
    # Check --pod-id-file
 | 
						|
    is "$(<$pod_id_file)" "$pod_id" "contents of pod-id-file"
 | 
						|
 | 
						|
    # Get ID of infra container
 | 
						|
    run_podman pod inspect --format '{{(index .Containers 0).ID}}' mypod
 | 
						|
    local infra_cid="$output"
 | 
						|
    # confirm that entrypoint is what we set
 | 
						|
    run_podman container inspect --format '{{.Config.Entrypoint}}' $infra_cid
 | 
						|
    is "$output" "$infra_command" "infra-command took effect"
 | 
						|
 | 
						|
    # Check each of the options
 | 
						|
    if [ -n "$mac_option" ]; then
 | 
						|
        run_podman run --rm --pod mypod $IMAGE ip link show
 | 
						|
        # 'ip' outputs hex in lower-case, ${expr,,} converts UC to lc
 | 
						|
        is "$output" ".* link/ether ${mac,,} " "requested MAC address was set"
 | 
						|
    fi
 | 
						|
 | 
						|
    run_podman run --rm --pod mypod $IMAGE hostname
 | 
						|
    is "$output" "$hostname" "--hostname set the hostname"
 | 
						|
 | 
						|
    run_podman run --rm --pod $pod_id $IMAGE cat /etc/hosts
 | 
						|
    is "$output" ".*$add_host_ip $add_host_n" "--add-host was added"
 | 
						|
    is "$output" ".*	$hostname"            "--hostname is in /etc/hosts"
 | 
						|
    #               ^^^^ this must be a tab, not a space
 | 
						|
 | 
						|
    run_podman run --rm --pod mypod $IMAGE cat /etc/resolv.conf
 | 
						|
    is "$output" ".*nameserver $dns_server"  "--dns [server] was added"
 | 
						|
    is "$output" ".*search $dns_search"      "--dns-search was added"
 | 
						|
    is "$output" ".*options $dns_opt"        "--dns-opt was added"
 | 
						|
 | 
						|
    # pod inspect
 | 
						|
    run_podman pod inspect --format '{{.Name}}: {{.ID}} : {{.NumContainers}} : {{.Labels}}' mypod
 | 
						|
    is "$output" "mypod: $pod_id : 1 : map\[${labelname}:${labelvalue}]" \
 | 
						|
       "pod inspect --format ..."
 | 
						|
 | 
						|
    # pod ps
 | 
						|
    run_podman pod ps --format '{{.ID}} {{.Name}} {{.Status}} {{.Labels}}'
 | 
						|
    is "$output" "${pod_id:0:12} mypod Running map\[${labelname}:${labelvalue}]"  "pod ps"
 | 
						|
 | 
						|
    run_podman pod ps --no-trunc --filter "label=${labelname}=${labelvalue}" --format '{{.ID}}'
 | 
						|
    is "$output" "$pod_id" "pod ps --filter label=..."
 | 
						|
 | 
						|
    # Test local port forwarding, as well as 'ps' output showing ports
 | 
						|
    # Run 'nc' in a container, waiting for input on the published port.
 | 
						|
    c_name=$(random_string 15)
 | 
						|
    run_podman run -d --pod mypod --name $c_name $IMAGE nc -l -p $port_in
 | 
						|
    cid="$output"
 | 
						|
 | 
						|
    # Try running another container also listening on the same port.
 | 
						|
    run_podman 1 run --pod mypod --name dsfsdfsdf $IMAGE nc -l -p $port_in
 | 
						|
    is "$output" "nc: bind: Address in use" \
 | 
						|
       "two containers cannot bind to same port"
 | 
						|
 | 
						|
    # make sure we can ping; failure here might mean that capabilities are wrong
 | 
						|
    run_podman run --rm --pod mypod $IMAGE ping -c1 127.0.0.1
 | 
						|
    run_podman run --rm --pod mypod $IMAGE ping -c1 $hostname
 | 
						|
 | 
						|
    # While the container is still running, run 'podman ps' (no --format)
 | 
						|
    # and confirm that the output includes the published port
 | 
						|
    run_podman ps --filter id=$cid
 | 
						|
    is "${lines[1]}" "${cid:0:12}  $IMAGE  nc -l -p $port_in .* 0.0.0.0:$port_out->$port_in/tcp  $c_name" \
 | 
						|
       "output of 'podman ps'"
 | 
						|
 | 
						|
    # send a random string to the container. This will cause the container
 | 
						|
    # to output the string to its logs, then exit.
 | 
						|
    teststring=$(random_string 30)
 | 
						|
    echo "$teststring" | nc 127.0.0.1 $port_out
 | 
						|
 | 
						|
    # Confirm that the container log output is the string we sent it.
 | 
						|
    run_podman logs $cid
 | 
						|
    is "$output" "$teststring" "test string received on container"
 | 
						|
 | 
						|
    # Finally, confirm the infra-container and -command. We run this late,
 | 
						|
    # not at pod creation, to give the infra container time to start & log.
 | 
						|
    run_podman logs $infra_cid
 | 
						|
    is "$output" "Confirmed: testimage pause invoked as $infra_command" \
 | 
						|
       "pod ran with our desired infra container + command"
 | 
						|
 | 
						|
    # Clean up
 | 
						|
    run_podman rm $cid
 | 
						|
    run_podman pod rm -f mypod
 | 
						|
    run_podman rmi $infra_image
 | 
						|
}
 | 
						|
 | 
						|
# vim: filetype=sh
 |