Skip to content

Instantly share code, notes, and snippets.

@crosbymichael
Created June 17, 2017 00:20
Show Gist options
  • Save crosbymichael/42a6ca6b8f21af1bead05095aa97681c to your computer and use it in GitHub Desktop.
Save crosbymichael/42a6ca6b8f21af1bead05095aa97681c to your computer and use it in GitHub Desktop.
package main
import (
"context"
"fmt"
"time"
"github.com/Sirupsen/logrus"
"github.com/containerd/containerd"
"github.com/containerd/containerd/namespaces"
"github.com/vishvananda/netlink"
)
const (
address = "/run/containerd/containerd.sock"
redis = "docker.io/library/redis:alpine"
)
func main() {
var (
ctx = context.Background()
docker = namespaces.WithNamespace(ctx, "demo")
)
if err := runRedis(docker, "redis"); err != nil {
logrus.Error(err)
}
}
func newPair(bridge string) (p *vethPair, err error) {
tmpName := "veth007"
veth := &netlink.Veth{
LinkAttrs: netlink.LinkAttrs{
Name: "tony0",
},
PeerName: tmpName,
}
if err := netlink.LinkAdd(veth); err != nil {
return nil, err
}
defer func() {
if err != nil {
netlink.LinkDel(veth)
}
}()
brl, err := netlink.LinkByName(bridge)
if err != nil {
return nil, err
}
br, ok := brl.(*netlink.Bridge)
if !ok {
return nil, fmt.Errorf("Wrong device type %T", brl)
}
host, err := netlink.LinkByName(veth.Name)
if err != nil {
return nil, err
}
if err := netlink.LinkSetMaster(host, br); err != nil {
return nil, err
}
if err := netlink.LinkSetMTU(host, 1500); err != nil {
return nil, err
}
if err := netlink.LinkSetUp(host); err != nil {
return nil, err
}
return &vethPair{
peer: tmpName,
}, nil
}
type vethPair struct {
peer string
}
func (v *vethPair) set(task containerd.Task) error {
child, err := netlink.LinkByName(v.peer)
if err != nil {
return err
}
return netlink.LinkSetNsPid(child, int(task.Pid()))
}
func runRedis(ctx context.Context, id string) error {
client, err := containerd.New(address)
if err != nil {
return err
}
defer client.Close()
image, err := client.Pull(ctx, redis, containerd.WithPullUnpack)
if err != nil {
return err
}
spec, err := containerd.GenerateSpec(containerd.WithImageConfig(ctx, image), containerd.WithProcessArgs("ip", "a"))
if err != nil {
return err
}
pair, err := newPair("docker0")
if err != nil {
return err
}
container, err := client.NewContainer(ctx, id,
containerd.WithSpec(spec),
containerd.WithNewRootFS(id, image),
)
if err != nil {
return err
}
defer container.Delete(ctx)
task, err := container.NewTask(ctx, containerd.Stdio)
if err != nil {
return err
}
c := make(chan struct{}, 1)
go func() {
if _, err := task.Wait(ctx); err != nil {
fmt.Println(err)
}
c <- struct{}{}
}()
defer task.Delete(ctx)
// before calling start, add the interface to the task
if err := pair.set(task); err != nil {
return err
}
if err := task.Start(ctx); err != nil {
return err
}
time.Sleep(3 * time.Second)
// wait for exit
<-c
return nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment