(dc dnode)
| 289 | } |
| 290 | |
| 291 | func (c *LocalCluster) createContainer(dc dnode) (string, error) { |
| 292 | cmd := dc.cmd(c) |
| 293 | image := c.dgraphImage() |
| 294 | mts, err := dc.mounts(c) |
| 295 | if err != nil { |
| 296 | return "", err |
| 297 | } |
| 298 | |
| 299 | // Verify the network still exists before creating container |
| 300 | ctx, cancel := context.WithTimeout(context.Background(), requestTimeout) |
| 301 | defer cancel() |
| 302 | if c.net.id != "" { |
| 303 | _, err := c.dcli.NetworkInspect(ctx, c.net.id, network.InspectOptions{}) |
| 304 | if err != nil { |
| 305 | // Use mutex to prevent multiple goroutines from recreating network simultaneously |
| 306 | c.netMutex.Lock() |
| 307 | // Double-check after acquiring lock - another goroutine may have recreated it |
| 308 | _, recheckErr := c.dcli.NetworkInspect(ctx, c.net.id, network.InspectOptions{}) |
| 309 | if recheckErr != nil { |
| 310 | log.Printf("[WARNING] network %s (ID: %s) not found, recreating", c.net.name, c.net.id) |
| 311 | if err := c.createNetwork(); err != nil { |
| 312 | c.netMutex.Unlock() |
| 313 | return "", errors.Wrap(err, "error recreating network") |
| 314 | } |
| 315 | } |
| 316 | c.netMutex.Unlock() |
| 317 | } |
| 318 | } |
| 319 | |
| 320 | cconf := &container.Config{Cmd: cmd, Image: image, WorkingDir: dc.workingDir(), ExposedPorts: dc.ports()} |
| 321 | // ApplyContainerUser is a public hook in dgraphtest/hooks.go; the |
| 322 | // default is no-op. Downstream consumers that run dgraph as a |
| 323 | // non-root user inside the test container override it to set |
| 324 | // cconf.User to the host's uid:gid, so files the container writes |
| 325 | // are readable on the host and bind-mounted host paths are readable |
| 326 | // inside the container. |
| 327 | ApplyContainerUser(cconf) |
| 328 | hconf := &container.HostConfig{Mounts: mts, PublishAllPorts: true, PortBindings: dc.bindings(c.conf.portOffset)} |
| 329 | networkConfig := &network.NetworkingConfig{ |
| 330 | EndpointsConfig: map[string]*network.EndpointSettings{ |
| 331 | c.net.name: { |
| 332 | Aliases: []string{dc.cname(), dc.aname()}, |
| 333 | NetworkID: c.net.id, |
| 334 | }, |
| 335 | }, |
| 336 | } |
| 337 | |
| 338 | resp, err := c.dcli.ContainerCreate(ctx, cconf, hconf, networkConfig, nil, dc.cname()) |
| 339 | if err != nil { |
| 340 | return "", errors.Wrapf(err, "error creating container %v", dc.cname()) |
| 341 | } |
| 342 | |
| 343 | return resp.ID, nil |
| 344 | } |
| 345 | |
| 346 | func (c *LocalCluster) destroyContainers() error { |
| 347 | ctx, cancel := context.WithTimeout(context.Background(), requestTimeout) |
no test coverage detected