github.com/blixtra/rkt@v0.8.1-0.20160204105720-ab0d1add1a43/tests/rkt_socket_activation_test.go (about) 1 // Copyright 2015 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 package main 16 17 import ( 18 "bufio" 19 "fmt" 20 "io/ioutil" 21 "math/rand" 22 "net" 23 "os" 24 "path/filepath" 25 "strconv" 26 "strings" 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/coreos/rkt/tests/testutils" 33 ) 34 35 func randomFreePort(t *testing.T) (int, error) { 36 l, err := net.Listen("tcp", "") 37 if err != nil { 38 return -1, err 39 } 40 defer l.Close() 41 42 addr := l.Addr().String() 43 44 n := strings.LastIndex(addr, ":") 45 port, err := strconv.Atoi(addr[n+1:]) 46 if err != nil { 47 return -1, err 48 } 49 50 return port, nil 51 } 52 53 func TestSocketActivation(t *testing.T) { 54 if !sd_util.IsRunningSystemd() { 55 t.Skip("Systemd is not running on the host.") 56 } 57 58 r := rand.New(rand.NewSource(time.Now().UnixNano())) 59 60 port, err := randomFreePort(t) 61 if err != nil { 62 t.Fatal(err) 63 } 64 65 echoImage := patchTestACI("rkt-inspect-echo.aci", 66 "--exec=/echo-socket-activated", 67 fmt.Sprintf("--ports=%d-tcp,protocol=tcp,port=%d,socketActivated=true", port, port)) 68 defer os.Remove(echoImage) 69 70 ctx := testutils.NewRktRunCtx() 71 defer ctx.Cleanup() 72 73 conn, err := sd_dbus.New() 74 if err != nil { 75 t.Fatal(err) 76 } 77 78 rktTestingEchoService := ` 79 [Unit] 80 Description=Socket-activated echo server 81 82 [Service] 83 ExecStart=%s 84 KillMode=process 85 ` 86 87 rnd := r.Int() 88 89 // Write unit files directly to runtime system units directory 90 // (/run/systemd/system) to avoid calling LinkUnitFiles - it is buggy in 91 // systemd v219 as it does not work with absolute paths. 92 unitsDir := "/run/systemd/system" 93 94 cmd := fmt.Sprintf("%s --insecure-options=image run --mds-register=false %s", ctx.Cmd(), echoImage) 95 serviceContent := fmt.Sprintf(rktTestingEchoService, cmd) 96 serviceTargetBase := fmt.Sprintf("rkt-testing-socket-activation-%d.service", rnd) 97 serviceTarget := filepath.Join(unitsDir, serviceTargetBase) 98 99 if err := ioutil.WriteFile(serviceTarget, []byte(serviceContent), 0666); err != nil { 100 t.Fatal(err) 101 } 102 defer os.Remove(serviceTarget) 103 104 rktTestingEchoSocket := ` 105 [Unit] 106 Description=Socket-activated netcat server socket 107 108 [Socket] 109 ListenStream=%d 110 ` 111 socketContent := fmt.Sprintf(rktTestingEchoSocket, port) 112 socketTargetBase := fmt.Sprintf("rkt-testing-socket-activation-%d.socket", rnd) 113 socketTarget := filepath.Join(unitsDir, socketTargetBase) 114 115 if err := ioutil.WriteFile(socketTarget, []byte(socketContent), 0666); err != nil { 116 t.Fatal(err) 117 } 118 defer os.Remove(socketTarget) 119 120 reschan := make(chan string) 121 doJob := func() { 122 job := <-reschan 123 if job != "done" { 124 t.Fatal("Job is not done:", job) 125 } 126 } 127 128 if _, err := conn.StartUnit(socketTargetBase, "replace", reschan); err != nil { 129 t.Fatal(err) 130 } 131 doJob() 132 133 defer func() { 134 if _, err := conn.StopUnit(socketTargetBase, "replace", reschan); err != nil { 135 t.Fatal(err) 136 } 137 doJob() 138 139 if _, err := conn.StopUnit(serviceTargetBase, "replace", reschan); err != nil { 140 t.Fatal(err) 141 } 142 doJob() 143 }() 144 145 expected := "HELO\n" 146 sockConn, err := net.Dial("tcp", fmt.Sprintf("localhost:%d", port)) 147 if err != nil { 148 t.Fatal(err) 149 } 150 151 if _, err := fmt.Fprintf(sockConn, expected); err != nil { 152 t.Fatal(err) 153 } 154 155 answer, err := bufio.NewReader(sockConn).ReadString('\n') 156 if err != nil { 157 t.Fatal(err) 158 } 159 160 if answer != expected { 161 t.Fatalf("Expected %q, Got %q", expected, answer) 162 } 163 164 return 165 }