|
| 1 | +#!/usr/bin/env expect |
| 2 | + |
| 3 | +set con_prompt "(ns: getty) linuxkit-*:*# " |
| 4 | +set ssh_prompt "linuxkit-*:*# " |
| 5 | +set timeout 120 |
| 6 | + |
| 7 | +set bootexec [lindex $argv 0] |
| 8 | +set sshexec [lindex $argv 1] |
| 9 | + |
| 10 | +proc kill args { |
| 11 | + foreach what $args { |
| 12 | + global $what |
| 13 | + if [info exists $what] { |
| 14 | + upvar #0 $what sid |
| 15 | + set pid [exp_pid -i $sid] |
| 16 | + puts "killing $what ($sid) = $pid" |
| 17 | + exec kill $pid |
| 18 | + close $sid |
| 19 | + } else { |
| 20 | + puts "not killing $what (not started)" |
| 21 | + } |
| 22 | + } |
| 23 | +} |
| 24 | + |
| 25 | +proc boot_linuxkit {} { |
| 26 | + global lk_sid bootexec |
| 27 | + spawn env {KUBE_RUN_ARGS=-publish 2222:22 -publish 30002:30002} KUBE_MEM=3584 KUBE_VCPUS=2 KUBE_DISK=8G KUBE_CLEAR_STATE=y KUBE_MASTER_UNTAINT=y $bootexec |
| 28 | + set lk_sid $spawn_id |
| 29 | + puts "INFO lk ($lk_sid) is pid [exp_pid -i $lk_sid]" |
| 30 | +} |
| 31 | + |
| 32 | +proc ssh_into_kubelet {} { |
| 33 | + global ssh_sid sshexec |
| 34 | + |
| 35 | + set sshopts {-p 2222 -o ConnectTimeout=5 -o LogLevel=DEBUG} |
| 36 | + if [info exists ::env(SSHOPTS)] { |
| 37 | + set sshopts [concat $::env(SSHOPTS) $sshopts] |
| 38 | + } |
| 39 | + spawn env SSHOPTS=$sshopts $sshexec localhost |
| 40 | + set ssh_sid $spawn_id |
| 41 | + puts "INFO ssh ($ssh_sid) is pid [exp_pid -i $ssh_sid]" |
| 42 | +} |
| 43 | + |
| 44 | +proc await_prompt {sidvar promptvar step} { |
| 45 | + upvar #0 $sidvar sid $promptvar prompt |
| 46 | + expect -i $sid \ |
| 47 | + $prompt { |
| 48 | + puts "SUCCESS $step" |
| 49 | + } timeout { |
| 50 | + puts "FAIL $step (timeout)" |
| 51 | + kill ssh_sid lk_sid |
| 52 | + exit 1 |
| 53 | + } eof { |
| 54 | + puts "FAIL $step (eof)" |
| 55 | + kill ssh_sid lk_sid |
| 56 | + exit 1 |
| 57 | + } |
| 58 | +} |
| 59 | + |
| 60 | +proc send_concmd {s} { |
| 61 | + global lk_sid |
| 62 | + send -i $lk_sid "$s\n" |
| 63 | +} |
| 64 | + |
| 65 | +proc await_con_prompt {step} { |
| 66 | + global lk_sid con_prompt |
| 67 | + await_prompt lk_sid con_prompt $step |
| 68 | +} |
| 69 | + |
| 70 | +proc concmd {step cmd} { |
| 71 | + send_concmd $cmd |
| 72 | + await_con_prompt $step |
| 73 | +} |
| 74 | + |
| 75 | +proc send_sshcmd {s} { |
| 76 | + global ssh_sid |
| 77 | + send -i $ssh_sid "$s\n" |
| 78 | +} |
| 79 | + |
| 80 | +proc await_ssh_prompt {step} { |
| 81 | + global ssh_sid ssh_prompt |
| 82 | + await_prompt ssh_sid ssh_prompt $step |
| 83 | +} |
| 84 | + |
| 85 | +proc sshcmd {step cmd} { |
| 86 | + send_sshcmd $cmd |
| 87 | + await_ssh_prompt $step |
| 88 | +} |
| 89 | + |
| 90 | +# Run $cmd at 1s intervals until we get $want or timeout |
| 91 | +# $sidvar names a variable containing sid to send/receive on |
| 92 | +# $promptvar names a variable containing the expected prompt |
| 93 | +# $step is used for logging |
| 94 | +proc await_cmd_output {sidvar promptvar step cmd want} { |
| 95 | + upvar #0 $sidvar sid $promptvar prompt |
| 96 | + send -i $sid "$cmd\n" |
| 97 | + set retries 0 |
| 98 | + expect -i $sid -timeout 300 \ |
| 99 | + $want { |
| 100 | + puts "SUCCESS $step: $cmd => $want" |
| 101 | + } $prompt { |
| 102 | + set retries [expr $retries + 1] |
| 103 | + sleep 1 |
| 104 | + send -i $sid "$cmd\n" |
| 105 | + exp_continue -continue_timer |
| 106 | + } timeout { |
| 107 | + puts "FAIL $step (timeout)" |
| 108 | + kill ssh_sid lk_sid |
| 109 | + exit 1 |
| 110 | + } |
| 111 | + await_prompt $sidvar $promptvar "$step (after $retries attempts)" |
| 112 | +} |
| 113 | + |
| 114 | +proc await_sshcmd_output {step cmd want} { |
| 115 | + global ssh_sid ssh_prompt |
| 116 | + await_cmd_output ssh_sid ssh_prompt $step $cmd $want |
| 117 | +} |
| 118 | + |
| 119 | +boot_linuxkit |
| 120 | + |
| 121 | +await_con_prompt "boot" |
| 122 | + |
| 123 | +concmd "ifconfig" "ifconfig eth0" |
| 124 | +concmd "list containers" "ctr -n services.linuxkit container ls" |
| 125 | + |
| 126 | +set retries 0 |
| 127 | +ssh_into_kubelet |
| 128 | +# provide ssh_sid as an indirect, allowing ssh to be respawned, which |
| 129 | +# changes the id, we need this in case ssh cannot immediately connect. |
| 130 | +expect -i ssh_sid \ |
| 131 | + $ssh_prompt { |
| 132 | + puts "SUCCESS connected to ssh (after $retries attempts)" |
| 133 | + } "read: Connection reset by peer" { |
| 134 | + # ssh happened too soon, wait a bit. |
| 135 | + set retries [expr $retries + 1] |
| 136 | + #puts "RETRY:$retries ssh (conn reset)" |
| 137 | + wait -i $ssh_sid |
| 138 | + sleep 1 |
| 139 | + ssh_into_kubelet |
| 140 | + exp_continue -continue_timer |
| 141 | + } eof { |
| 142 | + set retries [expr $retries + 1] |
| 143 | + #puts "RETRY:$retries ssh (eof)" |
| 144 | + wait -i $ssh_sid |
| 145 | + sleep 1 |
| 146 | + ssh_into_kubelet |
| 147 | + exp_continue -continue_timer |
| 148 | + } timeout { |
| 149 | + puts "FAIL ssh (timeout)" |
| 150 | + kill ssh_sid lk_sid |
| 151 | + exit 1 |
| 152 | + } |
| 153 | + |
| 154 | +puts "RUN kubeadm-init.sh" |
| 155 | +send_sshcmd "kubeadm-init.sh" |
| 156 | + |
| 157 | +# Written as N*5m with logging to avoid "10 mins with no output" from CI |
| 158 | +set retries 0 |
| 159 | +set maxretries 10 |
| 160 | +expect -i $ssh_sid -timeout 300 \ |
| 161 | + "Your Kubernetes master has initialized successfully!" { |
| 162 | + puts "SUCCESS cluster initialised!" |
| 163 | + } $ssh_prompt { |
| 164 | + puts "FAIL kubeadm-init.sh (returned to prompt)" |
| 165 | + kill ssh_sid lk_sid |
| 166 | + exit 1 |
| 167 | + } timeout { |
| 168 | + set retries [expr $retries + 1] |
| 169 | + if [expr $retries < $maxretries] { |
| 170 | + #puts "RETRY:$retries kubeadm-init.sh (timeout)" |
| 171 | + exp_continue |
| 172 | + } |
| 173 | + puts "FAIL kubeadm-init.sh (timeout)" |
| 174 | + kill ssh_sid lk_sid |
| 175 | + exit 1 |
| 176 | + } eof { |
| 177 | + puts "FAIL kubeadm-init.sh (eof)" |
| 178 | + kill ssh_sid lk_sid |
| 179 | + exit 1 |
| 180 | + } |
| 181 | +await_ssh_prompt "kubeadm-init.sh" |
| 182 | + |
| 183 | +sshcmd "status" "kubectl get -o wide nodes ; echo ; kubectl --namespace=kube-system get -o wide pods" |
| 184 | + |
| 185 | +await_sshcmd_output "await node ready" \ |
| 186 | + {kubectl get nodes -o jsonpath='{range .items[*]}{@.metadata.name}:{range @.status.conditions[*]}{@.type}={@.status};{end}{end}' ; echo} \ |
| 187 | + "Ready=True" |
| 188 | + |
| 189 | +await_sshcmd_output "await kube-dns ready" \ |
| 190 | + {kubectl --namespace=kube-system get --selector='k8s-app'='kube-dns' -o jsonpath='{.items[*].status.phase}' pods ; echo} \ |
| 191 | + "Running" |
| 192 | +await_sshcmd_output "await etcd ready" \ |
| 193 | + {kubectl --namespace=kube-system get --selector='component'='etcd' -o jsonpath='{.items[*].status.phase}' pods ; echo} \ |
| 194 | + "Running" |
| 195 | + |
| 196 | +sshcmd "status" "kubectl get -o wide nodes ; echo ; kubectl --namespace=kube-system get -o wide pods" |
| 197 | + |
| 198 | +sshcmd "apply app.yaml" "kubectl apply -f /root/app.yaml" |
| 199 | + |
| 200 | +await_sshcmd_output "await alpine pod ready" \ |
| 201 | + {kubectl get pods --selector=name=alpine -o jsonpath='{.items[*].status.phase}' ; echo} \ |
| 202 | + "Running" |
| 203 | +await_sshcmd_output "await nginx pod ready" \ |
| 204 | + {kubectl get pods --selector=name=nginx -o jsonpath='{.items[*].status.phase}' ; echo} \ |
| 205 | + "Running" |
| 206 | +puts "SUCCESS application pods ready" |
| 207 | + |
| 208 | +sshcmd "status" "kubectl get -o wide nodes ; echo ; kubectl --namespace=kube-system get -o wide pods ; echo ; kubectl --namespace=default get -o wide pods" |
| 209 | + |
| 210 | +set curl [exec curl -sS http://localhost:30002] |
| 211 | +if [string match "Welcome to nginx!" $curl] { |
| 212 | + puts "FAIL nginx returned:" |
| 213 | + puts $curl |
| 214 | + kill ssh_sid lk_sid |
| 215 | + exit 1 |
| 216 | +} |
| 217 | +puts "SUCCESS nginx responded well" |
| 218 | + |
| 219 | +send_sshcmd {kubectl exec $(kubectl get pods -l name==alpine -o=jsonpath='{.items[*].metadata.name}') -- wget -q -O - http://nginx/} |
| 220 | +expect -i $ssh_sid -timeout 10 \ |
| 221 | + "Welcome to nginx!" { |
| 222 | + puts "SUCCESS intra-pod networking ok" |
| 223 | + } $ssh_prompt { |
| 224 | + puts "FAIL intra-pod networking (returned to prompt)" |
| 225 | + kill ssh_sid lk_sid |
| 226 | + exit 1 |
| 227 | + } timeout { |
| 228 | + puts "FAIL intra-pod networking (timeout)" |
| 229 | + kill ssh_sid lk_sid |
| 230 | + exit 1 |
| 231 | + } eof { |
| 232 | + puts "FAIL intra-pod networking (eof)" |
| 233 | + kill ssh_sid lk_sid |
| 234 | + exit 1 |
| 235 | + } |
| 236 | +await_ssh_prompt "intra-pod networking" |
| 237 | + |
| 238 | +kill ssh_sid |
| 239 | + |
| 240 | +puts "RUN poweroff -f" |
| 241 | +send_concmd "poweroff -f" |
| 242 | + |
| 243 | +expect -i $lk_sid \ |
| 244 | + "Power down" { |
| 245 | + puts "SUCCESS poweroff" |
| 246 | + } eof { |
| 247 | + puts "SUCCESS poweroff" |
| 248 | + } timeout { |
| 249 | + puts "FAILED poweroff (timeout)" |
| 250 | + exit 1 |
| 251 | + } |
0 commit comments