Skip to content

Commit

Permalink
Merge pull request #34 from pathwar/dev/moul/docker-hypervisor
Browse files Browse the repository at this point in the history
feat: initial docker hypervisor
  • Loading branch information
moul committed Feb 11, 2019
2 parents 31116fa + 40d113a commit b1d3a14
Show file tree
Hide file tree
Showing 13 changed files with 388 additions and 165 deletions.
224 changes: 113 additions & 111 deletions entity/entity.pb.go

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,14 @@ module pathwar.pw

require (
github.com/BurntSushi/toml v0.3.1 // indirect
github.com/Microsoft/go-winio v0.4.11 // indirect
github.com/denisenkom/go-mssqldb v0.0.0-20181014144952-4e0d7dc8888f // indirect
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/docker/distribution v2.7.1+incompatible // indirect
github.com/docker/docker v0.7.3-0.20181024220401-bc4c1c238b55
github.com/docker/go-connections v0.4.0
github.com/docker/go-units v0.3.3 // indirect
github.com/dockerparis/docker-pot v1.4.0
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 // indirect
github.com/go-sql-driver/mysql v1.4.1 // indirect
github.com/gofrs/uuid v3.1.0+incompatible // indirect
Expand All @@ -19,6 +25,8 @@ require (
github.com/jinzhu/now v0.0.0-20181116074157-8ec929ed50c3 // indirect
github.com/lib/pq v1.0.0 // indirect
github.com/mattn/go-sqlite3 v1.10.0
github.com/opencontainers/go-digest v1.0.0-rc1 // indirect
github.com/opencontainers/image-spec v1.0.1 // indirect
github.com/pkg/errors v0.8.1
github.com/sirupsen/logrus v1.3.0 // indirect
github.com/spf13/cobra v0.0.3
Expand Down
20 changes: 20 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Microsoft/go-winio v0.4.11 h1:zoIOcVf0xPN1tnMVbTtEdI+P8OofVk3NObnwOQ6nK2Q=
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/berty/berty-poc v0.0.0-20181227220439-4de524a0a444 h1:Z3Ew/TVvotncH5vwCVsqo84nd3QYX3Rkvt8Mi9Hyq+Q=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
Expand All @@ -10,6 +12,20 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/denisenkom/go-mssqldb v0.0.0-20181014144952-4e0d7dc8888f/go.mod h1:xN/JuLBIz4bjkxNmByTiV1IbhfnYb6oo99phBn4Eqhc=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v0.7.3-0.20181024220401-bc4c1c238b55 h1:9aQls8BP+cWrfaq8M0RqR6CT58FcKZeSios1MvsTIkQ=
github.com/docker/docker v0.7.3-0.20181024220401-bc4c1c238b55/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v0.7.3-0.20190207111444-e6fe7f8f2936 h1:pdLlqyUORDKEBcPNN5AqIAJO6pTRCOvs/suECEroFN8=
github.com/docker/docker v0.7.3-0.20190207111444-e6fe7f8f2936/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v1.13.1 h1:5VBhsO6ckUxB0A8CE5LlUJdXzik9cbEbBTQ/ggeml7M=
github.com/docker/docker v1.13.1/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-units v0.3.3 h1:Xk8S3Xj5sLGlG5g67hJmYMmUgXv5N4PhkjJHHqrwnTk=
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/dockerparis/docker-pot v1.4.0 h1:rMLHmAXuFkBOy8E16UKeTELEpuCdvrcHp06Ycbl3kFk=
github.com/dockerparis/docker-pot v1.4.0/go.mod h1:O8AN4Q/Q0dhzvv9HQkSGyCIneicwKxvMyeT8nfyZgOY=
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
Expand Down Expand Up @@ -47,6 +63,10 @@ github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK86
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
Expand Down
43 changes: 43 additions & 0 deletions hypervisor/cmd_hypervisor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package hypervisor

import (
"encoding/json"

"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/spf13/viper"
"go.uber.org/zap"

"pathwar.pw/pkg/cli"
)

type Options struct {
}

func (opts Options) String() string {
out, _ := json.Marshal(opts)
return string(out)
}

func Commands() cli.Commands {
return cli.Commands{
"hypervisor": &hypervisorCommand{},
"hypervisor run": &runCommand{},
}
}

type hypervisorCommand struct{ opts Options }

func (cmd *hypervisorCommand) LoadDefaultOptions() error { return viper.Unmarshal(&cmd.opts) }
func (cmd *hypervisorCommand) ParseFlags(flags *pflag.FlagSet) {
if err := viper.BindPFlags(flags); err != nil {
zap.L().Warn("failed to bind viper flags", zap.Error(err))
}
}
func (cmd *hypervisorCommand) CobraCommand(commands cli.Commands) *cobra.Command {
command := &cobra.Command{
Use: "hypervisor",
}
command.AddCommand(commands["hypervisor run"].CobraCommand(commands))
return command
}
140 changes: 140 additions & 0 deletions hypervisor/cmd_hypervisor_run.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
package hypervisor

import (
"context"
"fmt"
"time"

"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/client"
"github.com/docker/go-connections/nat"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/spf13/viper"
"go.uber.org/zap"

"pathwar.pw/pkg/cli"
)

type runOptions struct {
target string `mapstructure:"target"`
webPort int `mapstructure:"web-port"`
// port, other options
// driver=docker
}

type runCommand struct{ opts runOptions }

func (cmd *runCommand) CobraCommand(commands cli.Commands) *cobra.Command {
cc := &cobra.Command{
Use: "run",
Args: func(_ *cobra.Command, args []string) error {
if cmd.opts.target == "" {
return errors.New("--target is mandatory")
}
return nil
},
RunE: func(_ *cobra.Command, args []string) error {
opts := cmd.opts
return runRun(opts)
},
}
cmd.ParseFlags(cc.Flags())
return cc
}
func (cmd *runCommand) LoadDefaultOptions() error { return viper.Unmarshal(&cmd.opts) }
func (cmd *runCommand) ParseFlags(flags *pflag.FlagSet) {
flags.StringVarP(&cmd.opts.target, "target", "t", "", "target (image, path, etc)")
flags.IntVarP(&cmd.opts.webPort, "web-port", "p", 8080, "web listening port")
if err := viper.BindPFlags(flags); err != nil {
zap.L().Warn("failed to bind viper flags", zap.Error(err))
}
}

func runRun(opts runOptions) error {
ctx := context.Background()
cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
return errors.Wrap(err, "failed to create docker client")
}

// configure new container
imageInspect, _, err := cli.ImageInspectWithRaw(ctx, opts.target)
if err != nil {
return errors.Wrap(err, "failed to inspect image")
}
containerConfig := &container.Config{
Image: opts.target,
Tty: true,
OpenStdin: true,
// StdinOnce: true,
// AttachStdin: true,
AttachStdout: true,
AttachStderr: true,
ExposedPorts: nat.PortSet{
nat.Port("80/tcp"): {},
},
// Hostname: ""
Cmd: imageInspect.Config.Cmd,
}
hostConfig := &container.HostConfig{
// Binds: /etc/timezone
PortBindings: nat.PortMap{
nat.Port("80/tcp"): []nat.PortBinding{{HostIP: "0.0.0.0", HostPort: fmt.Sprintf("%d", opts.webPort)}},
},
AutoRemove: true,
// RestartPolicy: "no"
// Dns
// DnsOptions
// DnsSearch
}
//networkingConfig := &network.NetworkingConfig{SandboxID:"XXX",SandboxKey:"XXX"}

// FIXME: create a limited network config
// FIXME: restrict resources (cgroups, etc.)
// FIXME: handle exposed port
// FIXME: handle entrypoint/cmd
// FIXME: wrap with custom init
// FIXME: copy init binary into image
// FIXME: configure env
// FIXME: copy tokens somewhere safe in the image

cont, err := cli.ContainerCreate(ctx, containerConfig, hostConfig, nil, "")
if err != nil {
return err
}
if cont.Warnings != nil && len(cont.Warnings) > 0 {
for _, warn := range cont.Warnings {
zap.L().Warn(warn)
}
}

if err := cli.ContainerStart(ctx, cont.ID, types.ContainerStartOptions{}); err != nil {
return err
}

// FIXME: wait for error or ctrl+C
ctxCancel, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
_, errC := cli.ContainerWait(ctxCancel, cont.ID, "")
if err := <-errC; err != nil {
return err
}

duration := 2 * time.Second
if err := cli.ContainerStop(ctx, cont.ID, &duration); err != nil {
return errors.Wrap(err, "failed to stop container")
}

if err := cli.ContainerRemove(ctx, cont.ID, types.ContainerRemoveOptions{
RemoveVolumes: true,
RemoveLinks: true,
Force: true,
}); err != nil {
return errors.Wrap(err, "failed to remove container")
}

return nil
}
1 change: 1 addition & 0 deletions hypervisor/hypervisor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package hypervisor
2 changes: 2 additions & 0 deletions level/example/hello-world/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
FROM nginx
COPY static /usr/share/nginx/html
1 change: 1 addition & 0 deletions level/example/hello-world/static/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<h1>Hello World!</h1>
Empty file added level/skeleton/.gitkeep
Empty file.
Empty file added level/stack/.gitkeep
Empty file.
4 changes: 4 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"go.uber.org/zap"
"go.uber.org/zap/zapcore"

"pathwar.pw/hypervisor"
"pathwar.pw/pkg/cli"
"pathwar.pw/server"
"pathwar.pw/sql"
Expand Down Expand Up @@ -44,6 +45,9 @@ func newRootCommand() *cobra.Command {
for name, command := range server.Commands() {
commands[name] = command
}
for name, command := range hypervisor.Commands() {
commands[name] = command
}

cmd.PersistentPreRunE = func(cmd *cobra.Command, args []string) error {
// setup logging
Expand Down
Loading

0 comments on commit b1d3a14

Please sign in to comment.