github.com/hanks177/podman/v4@v4.1.3-0.20220613032544-16d90015bc83/pkg/machine/e2e/config.go (about) 1 package e2e 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "math/rand" 7 "os" 8 "os/exec" 9 "path/filepath" 10 "strings" 11 "time" 12 13 "github.com/hanks177/podman/v4/pkg/machine" 14 "github.com/hanks177/podman/v4/pkg/machine/qemu" 15 "github.com/hanks177/podman/v4/pkg/util" 16 . "github.com/onsi/ginkgo" //nolint:golint,stylecheck 17 . "github.com/onsi/gomega" 18 "github.com/onsi/gomega/gexec" 19 . "github.com/onsi/gomega/gexec" //nolint:golint,stylecheck 20 ) 21 22 var originalHomeDir = os.Getenv("HOME") 23 24 const ( 25 defaultTimeout time.Duration = 90 * time.Second 26 ) 27 28 type machineCommand interface { 29 buildCmd(m *machineTestBuilder) []string 30 } 31 32 type MachineTestBuilder interface { 33 setName(string) *MachineTestBuilder 34 setCmd(mc machineCommand) *MachineTestBuilder 35 setTimeout(duration time.Duration) *MachineTestBuilder 36 run() (*machineSession, error) 37 } 38 type machineSession struct { 39 *gexec.Session 40 } 41 42 type machineTestBuilder struct { 43 cmd []string 44 imagePath string 45 name string 46 names []string 47 podmanBinary string 48 timeout time.Duration 49 } 50 type qemuMachineInspectInfo struct { 51 State machine.Status 52 VM qemu.MachineVM 53 } 54 55 // waitWithTimeout waits for a command to complete for a given 56 // number of seconds 57 func (ms *machineSession) waitWithTimeout(timeout time.Duration) { 58 Eventually(ms, timeout).Should(Exit()) 59 os.Stdout.Sync() 60 os.Stderr.Sync() 61 } 62 63 func (ms *machineSession) Bytes() []byte { 64 return []byte(ms.outputToString()) 65 } 66 67 func (ms *machineSession) outputToStringSlice() []string { 68 var results []string 69 output := string(ms.Out.Contents()) 70 for _, line := range strings.Split(output, "\n") { 71 if line != "" { 72 results = append(results, line) 73 } 74 } 75 return results 76 } 77 78 // outputToString returns the output from a session in string form 79 func (ms *machineSession) outputToString() string { 80 if ms == nil || ms.Out == nil || ms.Out.Contents() == nil { 81 return "" 82 } 83 84 fields := strings.Fields(string(ms.Out.Contents())) 85 return strings.Join(fields, " ") 86 } 87 88 // errorToString returns the error output from a session in string form 89 func (ms *machineSession) errorToString() string { 90 if ms == nil || ms.Err == nil || ms.Err.Contents() == nil { 91 return "" 92 } 93 return string(ms.Err.Contents()) 94 } 95 96 // newMB constructor for machine test builders 97 func newMB() (*machineTestBuilder, error) { 98 mb := machineTestBuilder{ 99 timeout: defaultTimeout, 100 } 101 cwd, err := os.Getwd() 102 if err != nil { 103 return nil, err 104 } 105 mb.podmanBinary = filepath.Join(cwd, "../../../bin/podman-remote") 106 if os.Getenv("PODMAN_BINARY") != "" { 107 mb.podmanBinary = os.Getenv("PODMAN_BINARY") 108 } 109 return &mb, nil 110 } 111 112 // setName sets the name of the virtuaql machine for the command 113 func (m *machineTestBuilder) setName(name string) *machineTestBuilder { 114 m.name = name 115 return m 116 } 117 118 // setCmd takes a machineCommand struct and assembles a cmd line 119 // representation of the podman machine command 120 func (m *machineTestBuilder) setCmd(mc machineCommand) *machineTestBuilder { 121 // If no name for the machine exists, we set a random name. 122 if !util.StringInSlice(m.name, m.names) { 123 if len(m.name) < 1 { 124 m.name = randomString(12) 125 } 126 m.names = append(m.names, m.name) 127 } 128 m.cmd = mc.buildCmd(m) 129 return m 130 } 131 132 func (m *machineTestBuilder) setTimeout(timeout time.Duration) *machineTestBuilder { 133 m.timeout = timeout 134 return m 135 } 136 137 // toQemuInspectInfo is only for inspecting qemu machines. Other providers will need 138 // to make their own. 139 func (mb *machineTestBuilder) toQemuInspectInfo() ([]qemuMachineInspectInfo, int, error) { 140 args := []string{"machine", "inspect"} 141 args = append(args, mb.names...) 142 session, err := runWrapper(mb.podmanBinary, args, defaultTimeout, true) 143 if err != nil { 144 return nil, -1, err 145 } 146 mii := []qemuMachineInspectInfo{} 147 err = json.Unmarshal(session.Bytes(), &mii) 148 return mii, session.ExitCode(), err 149 } 150 151 func (m *machineTestBuilder) runWithoutWait() (*machineSession, error) { 152 return runWrapper(m.podmanBinary, m.cmd, m.timeout, false) 153 } 154 155 func (m *machineTestBuilder) run() (*machineSession, error) { 156 return runWrapper(m.podmanBinary, m.cmd, m.timeout, true) 157 } 158 159 func runWrapper(podmanBinary string, cmdArgs []string, timeout time.Duration, wait bool) (*machineSession, error) { 160 if len(os.Getenv("DEBUG")) > 0 { 161 cmdArgs = append([]string{"--log-level=debug"}, cmdArgs...) 162 } 163 fmt.Println(podmanBinary + " " + strings.Join(cmdArgs, " ")) 164 c := exec.Command(podmanBinary, cmdArgs...) 165 session, err := Start(c, GinkgoWriter, GinkgoWriter) 166 if err != nil { 167 Fail(fmt.Sprintf("Unable to start session: %q", err)) 168 return nil, err 169 } 170 ms := machineSession{session} 171 if wait { 172 ms.waitWithTimeout(timeout) 173 fmt.Println("output:", ms.outputToString()) 174 } 175 return &ms, nil 176 } 177 178 func (m *machineTestBuilder) init() {} 179 180 // randomString returns a string of given length composed of random characters 181 func randomString(n int) string { 182 var randomLetters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") 183 b := make([]rune, n) 184 for i := range b { 185 b[i] = randomLetters[rand.Intn(len(randomLetters))] 186 } 187 return string(b) 188 }