github.com/emc-advanced-dev/unik@v0.0.0-20190717152701-a58d3e8e33b7/test/helpers/test_helpers.go (about) 1 package helpers 2 3 import ( 4 "fmt" 5 "github.com/sirupsen/logrus" 6 "github.com/emc-advanced-dev/pkg/errors" 7 "github.com/solo-io/unik/pkg/client" 8 "github.com/solo-io/unik/pkg/config" 9 unikos "github.com/solo-io/unik/pkg/os" 10 "github.com/solo-io/unik/pkg/types" 11 "github.com/solo-io/unik/pkg/util" 12 "io/ioutil" 13 "os" 14 "os/exec" 15 "path/filepath" 16 "runtime" 17 "time" 18 ) 19 20 type TempUnikHome struct { 21 Dir string 22 } 23 24 func (t *TempUnikHome) SetupUnik() { 25 if runtime.GOOS == "darwin" { 26 tmpDir := filepath.Join(os.Getenv("HOME"), ".unik", "tmp") 27 os.Setenv("TMPDIR", tmpDir) 28 os.MkdirAll(tmpDir, 0755) 29 } 30 31 n, err := ioutil.TempDir("", "unikhome.") 32 if err != nil { 33 panic(err) 34 } 35 config.Internal.UnikHome = n 36 37 t.Dir = n 38 } 39 40 func (t *TempUnikHome) TearDownUnik() { 41 os.RemoveAll(t.Dir) 42 } 43 44 func requireEnvVar(key string) (string, error) { 45 val := os.Getenv(key) 46 if val == "" { 47 return "", errors.New(fmt.Sprintf("%s must be set", key), nil) 48 } 49 return val, nil 50 } 51 52 func NewAwsConfig() (_ config.Aws, err error) { 53 region, err := requireEnvVar("AWS_REGION") 54 if err != nil { 55 return 56 } 57 zone, err := requireEnvVar("AWS_AVAILABILITY_ZONE") 58 if err != nil { 59 return 60 } 61 return config.Aws{ 62 Name: "TEST-AWS-CONFIG", 63 Region: region, 64 Zone: zone, 65 }, nil 66 } 67 68 func NewVirtualboxConfig() (_ config.Virtualbox, err error) { 69 adapterName, err := requireEnvVar("VBOX_ADAPTER_NAME") 70 if err != nil { 71 return 72 } 73 adapterType, err := requireEnvVar("VBOX_ADAPTER_TYPE") 74 if err != nil { 75 return 76 } 77 78 return config.Virtualbox{ 79 Name: "TEST-VBOX-CONFIG", 80 AdapterName: adapterName, 81 VirtualboxAdapterType: config.VirtualboxAdapterType(adapterType), 82 }, nil 83 } 84 85 func NewVsphereConfig() (_ config.Vsphere, err error) { 86 vsphereUser, err := requireEnvVar("VSPHERE_USERNAME") 87 if err != nil { 88 return 89 } 90 vspherePassword, err := requireEnvVar("VSPHERE_PASSWORD") 91 if err != nil { 92 return 93 } 94 vsphereUrl, err := requireEnvVar("VSPHERE_URL") 95 if err != nil { 96 return 97 } 98 vsphereDatastore, err := requireEnvVar("VSPHERE_DATASTORE") 99 if err != nil { 100 return 101 } 102 vsphereDatacenter, err := requireEnvVar("VSPHERE_DATACENTER") 103 if err != nil { 104 return 105 } 106 vsphereNetworkLabel, err := requireEnvVar("VSPHERE_NETWORK_LABEL") 107 if err != nil { 108 return 109 } 110 111 return config.Vsphere{ 112 Name: "TEST-VSPHERE-CONFIG", 113 VsphereUser: vsphereUser, 114 VspherePassword: vspherePassword, 115 VsphereURL: vsphereUrl, 116 Datastore: vsphereDatastore, 117 Datacenter: vsphereDatacenter, 118 NetworkLabel: vsphereNetworkLabel, 119 }, nil 120 } 121 122 func NewQemuConfig() (_ config.Qemu, err error) { 123 return config.Qemu{ 124 Name: "TEST-QEMU-CONFIG", 125 NoGraphic: true, 126 DebuggerPort: 3001, 127 }, nil 128 } 129 130 func NewXenConfig() (_ config.Xen, err error) { 131 pvGrubKernel, err := requireEnvVar("PV_KERNEL") 132 if err != nil { 133 return 134 } 135 return config.Xen{ 136 Name: "TEST-XEN-CONFIG", 137 XenBridge: "xenbr0", 138 KernelPath: pvGrubKernel, 139 }, nil 140 } 141 142 func NewTestConfig() (cfg config.DaemonConfig) { 143 noConfig := true 144 if os.Getenv("TEST_AWS") != "" && os.Getenv("TEST_AWS") != "0" { 145 awsConfig, err := NewAwsConfig() 146 if err != nil { 147 logrus.Panic(err) 148 } 149 cfg.Providers.Aws = append(cfg.Providers.Aws, awsConfig) 150 noConfig = false 151 } 152 if os.Getenv("TEST_VIRTUALBOX") != "" && os.Getenv("TEST_VIRTUALBOX") != "0" { 153 vboxConfig, err := NewVirtualboxConfig() 154 if err != nil { 155 logrus.Panic(err) 156 } 157 cfg.Providers.Virtualbox = append(cfg.Providers.Virtualbox, vboxConfig) 158 noConfig = false 159 } 160 if os.Getenv("TEST_VSPHERE") != "" && os.Getenv("TEST_VSPHERE") != "0" { 161 vsphereConfig, err := NewVsphereConfig() 162 if err != nil { 163 logrus.Panic(err) 164 } 165 cfg.Providers.Vsphere = append(cfg.Providers.Vsphere, vsphereConfig) 166 noConfig = false 167 } 168 if os.Getenv("TEST_QEMU") != "" && os.Getenv("TEST_QEMU") != "0" { 169 qemuConfig, err := NewQemuConfig() 170 if err != nil { 171 logrus.Panic(err) 172 } 173 cfg.Providers.Qemu = append(cfg.Providers.Qemu, qemuConfig) 174 noConfig = false 175 } 176 if os.Getenv("TEST_XEN") != "" && os.Getenv("TEST_XEN") != "0" { 177 xenConfig, err := NewXenConfig() 178 if err != nil { 179 logrus.Panic(err) 180 } 181 cfg.Providers.Xen = append(cfg.Providers.Xen, xenConfig) 182 noConfig = false 183 } 184 if noConfig { 185 logrus.WithField("cfg", cfg).Panic("at least one config must be specified with TEST_<Provider>") 186 } 187 return 188 } 189 190 func MakeContainers(projectRoot string) error { 191 cmd := exec.Command("make", "-C", projectRoot, "containers") 192 util.LogCommand(cmd, true) 193 return cmd.Run() 194 } 195 196 func RemoveContainers(projectRoot string) error { 197 cmd := exec.Command("make", "-C", projectRoot, "remove-containers") 198 util.LogCommand(cmd, false) 199 return cmd.Run() 200 } 201 202 func TarExampleApp(appDir string) (*os.File, error) { 203 projectRoot := GetProjectRoot() 204 absRoot, err := filepath.Abs(projectRoot) 205 if err != nil { 206 return nil, errors.New("getting abs of "+projectRoot, err) 207 } 208 path := filepath.Join(absRoot, "docs", "examples", appDir) 209 logrus.Debugf("tarring sources at %s", path) 210 sourceTar, err := ioutil.TempFile("", "example.app.tar.gz.") 211 if err != nil { 212 return nil, errors.New("failed to create tmp tar file", err) 213 } 214 if err := unikos.Compress(path, sourceTar.Name()); err != nil { 215 os.RemoveAll(path) 216 return nil, errors.New("failed to tar sources", err) 217 } 218 return sourceTar, nil 219 } 220 221 func TarTestApp(appDir string) (*os.File, error) { 222 projectRoot := GetProjectRoot() 223 absRoot, err := filepath.Abs(projectRoot) 224 if err != nil { 225 return nil, errors.New("getting abs of "+projectRoot, err) 226 } 227 path := filepath.Join(absRoot, "test", "test_apps", appDir) 228 logrus.Debugf("tarring sources at %s", path) 229 sourceTar, err := ioutil.TempFile("", "test.app.tar.gz.") 230 if err != nil { 231 return nil, errors.New("failed to create tmp tar file", err) 232 } 233 if err := unikos.Compress(path, sourceTar.Name()); err != nil { 234 return nil, errors.New("failed to tar sources", err) 235 } 236 return sourceTar, nil 237 } 238 239 func TarTestVolume() (*os.File, error) { 240 projectRoot := GetProjectRoot() 241 absRoot, err := filepath.Abs(projectRoot) 242 if err != nil { 243 return nil, errors.New("getting abs of "+projectRoot, err) 244 } 245 path := filepath.Join(absRoot, "test", "test_apps", "test_volume") 246 logrus.Debugf("tarring data at %s", path) 247 dataTar, err := ioutil.TempFile("", "test.data.tar.gz.") 248 if err != nil { 249 return nil, errors.New("failed to create tmp tar file", err) 250 } 251 if err := unikos.Compress(path, dataTar.Name()); err != nil { 252 return nil, errors.New("failed to tar data", err) 253 } 254 return dataTar, nil 255 } 256 257 func BuildExampleImage(daemonUrl, exampleName, compiler, provider string, mounts []string) (*types.Image, error) { 258 force := true 259 noCleanup := false 260 testSourceTar, err := TarExampleApp(exampleName) 261 if err != nil { 262 return nil, errors.New("tarring example app", err) 263 } 264 defer os.RemoveAll(testSourceTar.Name()) 265 return client.UnikClient(daemonUrl).Images().Build(exampleName, testSourceTar.Name(), compiler, provider, "", mounts, force, noCleanup) 266 } 267 268 func BuildTestImage(daemonUrl, appDir, compiler, provider string, mounts []string) (*types.Image, error) { 269 force := true 270 noCleanup := false 271 testSourceTar, err := TarTestApp(appDir) 272 if err != nil { 273 return nil, errors.New("tarring test app", err) 274 } 275 defer os.RemoveAll(testSourceTar.Name()) 276 return client.UnikClient(daemonUrl).Images().Build(appDir, testSourceTar.Name(), compiler, provider, "", mounts, force, noCleanup) 277 } 278 279 func RunExampleInstance(daemonUrl, instanceName, imageName string, mountPointsToVols map[string]string) (*types.Instance, error) { 280 noCleanup := false 281 env := map[string]string{"FOO": "BAR"} 282 memoryMb := 128 283 return client.UnikClient(daemonUrl).Instances().Run(instanceName, imageName, mountPointsToVols, env, memoryMb, noCleanup, false) 284 } 285 286 func CreateExampleVolume(daemonUrl, volumeName, provider string, size int) (*types.Volume, error) { 287 return client.UnikClient(daemonUrl).Volumes().Create(volumeName, "", provider, size, false) 288 } 289 290 func CreateTestDataVolume(daemonUrl, volumeName, provider string) (*types.Volume, error) { 291 dataTar, err := TarTestVolume() 292 if err != nil { 293 return nil, errors.New("tarring test data volume", err) 294 } 295 defer os.RemoveAll(dataTar.Name()) 296 return client.UnikClient(daemonUrl).Volumes().Create(volumeName, dataTar.Name(), provider, 0, false) 297 } 298 299 func GetProjectRoot() string { 300 projectRoot := os.Getenv("PROJECT_ROOT") 301 if projectRoot == "" { 302 _, filename, _, ok := runtime.Caller(1) 303 if !ok { 304 logrus.Panic("could not get current file") 305 } 306 projectRoot = filepath.Join(filepath.Dir(filename), "..", "..") 307 } 308 logrus.Infof("using %s as project root", projectRoot) 309 return projectRoot 310 } 311 312 func WaitForIp(daemonUrl, instanceId string, timeout time.Duration) (string, error) { 313 errc := make(chan error) 314 go func() { 315 <-time.After(timeout) 316 errc <- errors.New("getting instance ip timed out after "+timeout.String(), nil) 317 }() 318 319 resultc := make(chan string) 320 go func() { 321 logrus.Infof("retrieving ip for instance %s", instanceId) 322 started := time.Now() 323 end := started.Add(timeout) 324 for { 325 instance, err := client.UnikClient(daemonUrl).Instances().Get(instanceId) 326 if err != nil { 327 errc <- errors.New("getting instance from UniK daemon", err) 328 return 329 } 330 if instance.IpAddress != "" { 331 resultc <- instance.IpAddress 332 return 333 } 334 logrus.Debugf("sleeping %v left...", end.Sub(time.Now())) 335 time.Sleep(time.Second) 336 } 337 }() 338 select { 339 case result := <-resultc: 340 return result, nil 341 case err := <-errc: 342 return "", err 343 } 344 }