github.com/rkt/rkt@v1.30.1-0.20200224141603-171c416fac02/tests/rkt_socket_proxyd_test.go (about) 1 // Copyright 2016 The rkt Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // +build host coreos src kvm 16 17 package main 18 19 import ( 20 "bufio" 21 "fmt" 22 "io/ioutil" 23 "math/rand" 24 "net" 25 "os" 26 "path/filepath" 27 "testing" 28 "time" 29 30 sd_dbus "github.com/coreos/go-systemd/dbus" 31 sd_util "github.com/coreos/go-systemd/util" 32 "github.com/rkt/rkt/tests/testutils" 33 "github.com/vishvananda/netlink" 34 ) 35 36 func TestSocketProxyd(t *testing.T) { 37 // Skip the test for now. See 38 // https://github.com/rkt/rkt/issues/2432#issuecomment-238858840 for 39 // details. 40 t.Skip("this test is racy, let's skip it until we fix it") 41 42 if !sd_util.IsRunningSystemd() { 43 t.Skip("Systemd is not running on the host.") 44 } 45 46 socketProxydPath := "/lib/systemd/systemd-socket-proxyd" 47 if _, err := os.Stat(socketProxydPath); os.IsNotExist(err) { 48 t.Skip("systemd-socket-proxyd is not installed.") 49 } 50 51 ctx := testutils.NewRktRunCtx() 52 defer ctx.Cleanup() 53 54 iface, _, err := testutils.GetNonLoIfaceWithAddrs(netlink.FAMILY_V4) 55 if err != nil { 56 t.Fatalf("Error while getting non-lo host interface: %v\n", err) 57 } 58 if iface.Name == "" { 59 t.Skipf("Cannot run test without non-lo host interface") 60 } 61 62 nt := networkTemplateT{ 63 Name: "ptp0", 64 Type: "ptp", 65 IpMasq: true, 66 Master: iface.Name, 67 Ipam: &ipamTemplateT{ 68 Type: "host-local", 69 Subnet: "192.168.0.0/24", 70 Routes: []map[string]string{ 71 {"dst": "0.0.0.0/0"}, 72 }, 73 }, 74 } 75 76 netDir := prepareTestNet(t, ctx, nt) 77 defer os.RemoveAll(netDir) 78 79 port, err := randomFreePort(t) 80 if err != nil { 81 t.Fatal(err) 82 } 83 84 echoImage := patchTestACI("rkt-inspect-echo.aci", 85 "--exec=/echo-socket-activated", 86 "--ports=test-port,protocol=tcp,port=80,socketActivated=true") 87 defer os.Remove(echoImage) 88 89 conn, err := sd_dbus.New() 90 if err != nil { 91 t.Fatal(err) 92 } 93 94 rktTestingEchoService := ` 95 [Unit] 96 Description=Socket-activated echo server 97 98 [Service] 99 ExecStart=%s 100 KillMode=process 101 ` 102 103 r := rand.New(rand.NewSource(time.Now().UnixNano())) 104 rnd := r.Int() 105 106 // Write unit files directly to runtime system units directory 107 // (/run/systemd/system) to avoid calling LinkUnitFiles - it is buggy in 108 // systemd v219 as it does not work with absolute paths. 109 unitsDir := "/run/systemd/system" 110 containerIP := "192.168.0.101" 111 112 cmd := fmt.Sprintf("%s --insecure-options=image --debug run --net=%s:IP=%s --port=test-port:%d --mds-register=false %s", 113 ctx.Cmd(), nt.Name, containerIP, port, echoImage) 114 115 serviceContent := fmt.Sprintf(rktTestingEchoService, cmd) 116 serviceTargetBase := fmt.Sprintf("rkt-testing-socket-activation-%d.service", rnd) 117 serviceTarget := filepath.Join(unitsDir, serviceTargetBase) 118 119 if err := ioutil.WriteFile(serviceTarget, []byte(serviceContent), 0666); err != nil { 120 t.Fatal(err) 121 } 122 defer os.Remove(serviceTarget) 123 124 rktTestingEchoSocket := ` 125 [Unit] 126 Description=Socket-activated netcat server socket 127 128 [Socket] 129 ListenStream=%d 130 131 [Install] 132 WantedBy=sockets.target 133 ` 134 135 socketContent := fmt.Sprintf(rktTestingEchoSocket, port) 136 socketTargetBase := fmt.Sprintf("proxy-to-rkt-testing-socket-activation-%d.socket", rnd) 137 socketTarget := filepath.Join(unitsDir, socketTargetBase) 138 139 if err := ioutil.WriteFile(socketTarget, []byte(socketContent), 0666); err != nil { 140 t.Fatal(err) 141 } 142 defer os.Remove(socketTarget) 143 144 proxyToRktTestingEchoService := ` 145 [Unit] 146 Requires=%s 147 After=%s 148 149 [Service] 150 ExecStart=%s %s:%d 151 ` 152 153 proxyContent := fmt.Sprintf(proxyToRktTestingEchoService, serviceTargetBase, serviceTargetBase, 154 socketProxydPath, containerIP, port) 155 proxyContentBase := fmt.Sprintf("proxy-to-rkt-testing-socket-activation-%d.service", rnd) 156 proxyTarget := filepath.Join(unitsDir, proxyContentBase) 157 158 if err := ioutil.WriteFile(proxyTarget, []byte(proxyContent), 0666); err != nil { 159 t.Fatal(err) 160 } 161 defer os.Remove(proxyTarget) 162 163 reschan := make(chan string) 164 doJob := func() { 165 job := <-reschan 166 if job != "done" { 167 t.Fatal("Job is not done:", job) 168 } 169 } 170 171 if _, err := conn.StartUnit(socketTargetBase, "replace", reschan); err != nil { 172 t.Fatal(err) 173 } 174 doJob() 175 176 defer func() { 177 if _, err := conn.StopUnit(socketTargetBase, "replace", reschan); err != nil { 178 t.Fatal(err) 179 } 180 doJob() 181 182 if _, err := conn.StopUnit(serviceTargetBase, "replace", reschan); err != nil { 183 t.Fatal(err) 184 } 185 doJob() 186 187 if _, err := conn.StopUnit(proxyContentBase, "replace", reschan); err != nil { 188 t.Fatal(err) 189 } 190 doJob() 191 }() 192 193 expected := "HELO\n" 194 sockConn, err := net.Dial("tcp", fmt.Sprintf("localhost:%d", port)) 195 if err != nil { 196 t.Fatal(err) 197 } 198 199 if _, err := fmt.Fprintf(sockConn, expected); err != nil { 200 t.Fatal(err) 201 } 202 203 answer, err := bufio.NewReader(sockConn).ReadString('\n') 204 if err != nil { 205 t.Fatal(err) 206 } 207 208 if answer != expected { 209 t.Fatalf("Expected %q, Got %q", expected, answer) 210 } 211 212 return 213 }