Skip to content

Instantly share code, notes, and snippets.

@sesmith177
Created December 4, 2017 17:16
Show Gist options
  • Save sesmith177/94d47938ecf1ec0fdaf7d5d1fbcedad8 to your computer and use it in GitHub Desktop.
Save sesmith177/94d47938ecf1ec0fdaf7d5d1fbcedad8 to your computer and use it in GitHub Desktop.
package main
import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"log"
"os"
"os/signal"
"path/filepath"
"sync"
"time"
"github.com/Microsoft/hcsshim"
)
func main() {
rootfsPath, present := os.LookupEnv("ROOTFS_PATH")
if !present {
log.Fatal("Must set ROOTFS_PATH env var")
}
networkName, present := os.LookupEnv("NETWORK_NAME")
if !present {
log.Fatal("Must set NETWORK_NAME env var")
}
containerId := fmt.Sprintf("%d", time.Now().UnixNano())
imageStore := `C:\windows\temp\image-store`
driverInfo := hcsshim.DriverInfo{
HomeDir: imageStore,
Flavour: 1,
}
fmt.Printf("Container ID: %s\n", containerId)
parentLayerChain, err := ioutil.ReadFile(filepath.Join(rootfsPath, "layerchain.json"))
if err != nil {
log.Fatal(err)
}
var parentLayers []string
if err := json.Unmarshal(parentLayerChain, &parentLayers); err != nil {
log.Fatal(err)
}
sandboxLayers := append([]string{rootfsPath}, parentLayers...)
if err := hcsshim.CreateSandboxLayer(driverInfo, containerId, rootfsPath, sandboxLayers); err != nil {
log.Fatal(err)
}
if err := hcsshim.ActivateLayer(driverInfo, containerId); err != nil {
log.Fatal(err)
}
if err := hcsshim.PrepareLayer(driverInfo, containerId, sandboxLayers); err != nil {
log.Fatal(err)
}
volumePath, err := hcsshim.GetLayerMountPath(driverInfo, containerId)
if err != nil {
log.Fatal(err)
}
var layerInfos []hcsshim.Layer
for _, layerPath := range sandboxLayers {
layerId := filepath.Base(layerPath)
layerGuid, err := hcsshim.NameToGuid(layerId)
if err != nil {
log.Fatal(err)
}
layerInfos = append(layerInfos, hcsshim.Layer{
ID: layerGuid.ToString(),
Path: layerPath,
})
}
containerConfig := hcsshim.ContainerConfig{
SystemType: "Container",
Name: containerId,
VolumePath: volumePath,
Owner: "owner",
LayerFolderPath: filepath.Join(imageStore, containerId),
Layers: layerInfos,
}
container, err := hcsshim.CreateContainer(containerId, &containerConfig)
if err != nil {
log.Fatal(err)
}
defer container.Close()
if err := container.Start(); err != nil {
log.Fatal(err)
}
network, err := hcsshim.GetHNSNetworkByName(networkName)
if err != nil {
log.Fatal(err)
}
endpoint := &hcsshim.HNSEndpoint{
VirtualNetwork: network.Id,
Name: containerId,
}
createdEndpoint, err := endpoint.Create()
if err != nil {
log.Fatal(err)
}
if err := hcsshim.HotAttachEndpoint(containerId, createdEndpoint.Id); err != nil {
log.Fatal(err)
}
p, err := container.CreateProcess(&hcsshim.ProcessConfig{
CommandLine: "ping www.bing.com",
CreateStdOutPipe: true,
CreateStdErrPipe: true,
})
if err != nil {
log.Fatal(err)
}
_, stdout, stderr, err := p.Stdio()
if err != nil {
log.Fatal(err)
}
var wg sync.WaitGroup
go func() {
wg.Add(1)
_, _ = io.Copy(os.Stdout, stdout)
_ = stdout.Close()
wg.Done()
}()
go func() {
wg.Add(1)
_, _ = io.Copy(os.Stderr, stderr)
_ = stderr.Close()
wg.Done()
}()
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
go func() {
<-c
_ = p.Kill()
}()
if err := p.Wait(); err != nil {
log.Fatal(err)
}
waitWithTimeout(&wg, 1*time.Second)
exitCode, err := p.ExitCode()
if err != nil {
log.Fatal(err)
}
if exitCode != 0 {
log.Fatal(fmt.Errorf("failed to exec in container: exit code %d", exitCode))
}
}
func waitWithTimeout(wg *sync.WaitGroup, timeout time.Duration) {
wgEmpty := make(chan interface{}, 1)
go func() {
wg.Wait()
wgEmpty <- nil
}()
select {
case <-time.After(timeout):
case <-wgEmpty:
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment