Skip to content

Commit

Permalink
replaced the original timer hacks in slim and launcher with command a…
Browse files Browse the repository at this point in the history
…nd event channels
  • Loading branch information
kcq committed Oct 28, 2015
1 parent f08dd93 commit 721487e
Show file tree
Hide file tree
Showing 8 changed files with 460 additions and 28 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ The demo run on Mac OS X, but you can build a linux version.
3. Run `docker-slim`:

`cd ../../dist`
`cd ../../dist_mac`

`./docker-slim my/sample-node-app`

Expand All @@ -84,7 +84,7 @@ The demo run on Mac OS X, but you can build a linux version.
You can get the port number either from the `docker ps` or `docker port <CONTAINER_ID>` commands. The current version of DockerSlim doesn't allow you to map exposed network ports (it works like `docker run … -P`).

5. Wait a couple of minutes until `docker-slim` says it's done
5. Press any key and wait until `docker-slim` says it's done

6. Once DockerSlim is done check that the new minified image is there

Expand All @@ -98,7 +98,7 @@ The demo run on Mac OS X, but you can build a linux version.

Notes:

You can explore the artifacts DockerSlim generates when it's creating a slim image. You'll find those in `dist/container/artifacts`. One of the artifacts is a "reverse engineered" Dockerfile for the original image. It'll be called `Dockerfile.fat`.
You can explore the artifacts DockerSlim generates when it's creating a slim image. You'll find those in `dist_mac/container/artifacts`. One of the artifacts is a "reverse engineered" Dockerfile for the original image. It'll be called `Dockerfile.fat`.

If you'd like to see the artifacts without running `docker-slim` you can take a look at the `sample_artifacts` directory in the repo. It doesn't include any image files, but you'll find:

Expand All @@ -108,7 +108,7 @@ If you'd like to see the artifacts without running `docker-slim` you can take a

If you don't want to create a minified image and only want to "reverse engineer" the Dockerfile you can use the `image-info-only` option.

You can get the current binaries for Macs [here](https://github.com/cloudimmunity/docker-slim/releases/download/v1.4/mac_dist.zip)
You can get the current binaries for Macs [here](https://github.com/cloudimmunity/docker-slim/releases/download/v1.5/dist_mac.zip)


## BUILD PROCESS
Expand Down
Binary file removed dist/container/bin/alauncher
Binary file not shown.
Binary file added dist_linux/container/bin/alauncher
Binary file not shown.
Binary file added dist_linux/docker-slim
Binary file not shown.
Binary file added dist_mac/container/bin/alauncher
Binary file not shown.
Binary file renamed dist/docker-slim → dist_mac/docker-slim
Binary file not shown.
230 changes: 229 additions & 1 deletion src/launcher/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import (
"log"
"os"
"os/exec"
//"syscall"
"syscall"
"os/signal"
"bufio"
"bytes"
"crypto/sha1"
Expand All @@ -20,6 +21,11 @@ import (
"strings"
"time"

"github.com/gdamore/mangos"
"github.com/gdamore/mangos/protocol/rep"
"github.com/gdamore/mangos/protocol/pub"
//"github.com/gdamore/mangos/transport/ipc"
"github.com/gdamore/mangos/transport/tcp"
"bitbucket.org/madmo/fanotify"
"github.com/cloudimmunity/pdiscover"
)
Expand Down Expand Up @@ -48,6 +54,178 @@ func fileDir(fileName string) string {
return dirName
}

///////////////////////////////////////////////////////////////////////////////

var doneChan chan struct{}

var cmdChannelAddr = "tcp://0.0.0.0:65501"
//var cmdChannelAddr = "ipc:///tmp/docker-slim-launcher.cmds.ipc"
//var cmdChannelAddr = "ipc:///opt/dockerslim/ipc/docker-slim-launcher.cmds.ipc"
var cmdChannel mangos.Socket

func newCmdServer(addr string) (mangos.Socket,error) {
log.Println("alauncher: creating cmd server...")
socket, err := rep.NewSocket()
if err != nil {
return nil,err
}

if err := socket.SetOption(mangos.OptionRecvDeadline,time.Second * 3); err != nil {
socket.Close()
return nil,err
}

//socket.AddTransport(ipc.NewTransport())
socket.AddTransport(tcp.NewTransport())
if err := socket.Listen(addr); err != nil {
socket.Close()
return nil,err
}

return socket,nil
}

func runCmdServer(channel mangos.Socket,done <-chan struct{}) (<-chan string,error) {
cmdChan := make(chan string)
go func() {
for {
// Could also use sock.RecvMsg to get header
log.Println("alauncher: cmd server - waiting for a command...")
select {
case <- done:
log.Println("alauncher: cmd server - done...")
return
default:
if rawCmd, err := channel.Recv(); err != nil {
switch err {
case mangos.ErrRecvTimeout:
log.Println("alauncher: cmd server - timeout... ok")
default:
log.Println("alauncher: cmd server - error =>",err)
}
} else {
cmd := string(rawCmd)
log.Println("alauncher: cmd server - got a command =>",cmd)
cmdChan <- cmd
//for now just ack the command and process the command asynchronously
//NOTE:
//must reply before receiving the next message
//otherwise nanomsg/mangos will be confused :-)
monitorFinishReply := "ok"
err = channel.Send([]byte(monitorFinishReply))
if err != nil {
log.Println("alauncher: cmd server - fail to send monitor.finish reply =>",err)
}
}
}
}
}()

return cmdChan,nil
}

func shutdownCmdChannel() {
if cmdChannel != nil {
cmdChannel.Close()
cmdChannel = nil
}
}

var evtChannelAddr = "tcp://0.0.0.0:65502"
//var evtChannelAddr = "ipc:///tmp/docker-slim-launcher.events.ipc"
//var evtChannelAddr = "ipc:///opt/dockerslim/ipc/docker-slim-launcher.events.ipc"
var evtChannel mangos.Socket

func newEvtPublisher(addr string) (mangos.Socket,error) {
log.Println("alauncher: creating event publisher...")
socket, err := pub.NewSocket()
if err != nil {
return nil,err
}

if err := socket.SetOption(mangos.OptionSendDeadline,time.Second * 3); err != nil {
socket.Close()
return nil,err
}

//socket.AddTransport(ipc.NewTransport())
socket.AddTransport(tcp.NewTransport())
if err = socket.Listen(addr); err != nil {
socket.Close()
return nil,err
}

return socket,nil
}

func publishEvt(channel mangos.Socket,evt string) error {
if err := channel.Send([]byte(evt)); err != nil {
log.Printf("fail to publish '%v' event:%v\n",evt,err)
return err
}

return nil
}

func shutdownEvtChannel() {
if evtChannel != nil {
evtChannel.Close()
evtChannel = nil
}
}

//////////////

func cleanupOnStartup() {
if _, err := os.Stat("/tmp/docker-slim-launcher.cmds.ipc"); err == nil {
if err := os.Remove("/tmp/docker-slim-launcher.cmds.ipc"); err != nil {
fmt.Printf("Error removing unix socket %s: %s", "/tmp/docker-slim-launcher.cmds.ipc", err.Error())
}
}

if _, err := os.Stat("/tmp/docker-slim-launcher.events.ipc"); err == nil {
if err := os.Remove("/tmp/docker-slim-launcher.events.ipc"); err != nil {
fmt.Printf("Error removing unix socket %s: %s", "/tmp/docker-slim-launcher.events.ipc", err.Error())
}
}
}

func cleanupOnShutdown() {
fmt.Println("cleanupOnShutdown()...")

if doneChan != nil {
close(doneChan)
doneChan = nil
}

shutdownCmdChannel()
shutdownEvtChannel()
}

//////////////

var signals = []os.Signal{
os.Interrupt,
syscall.SIGTERM,
syscall.SIGQUIT,
syscall.SIGHUP,
syscall.SIGSTOP,
syscall.SIGCONT,
}

func initSignalHandlers() {
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan,signals...)
go func(){
sig := <-sigChan
fmt.Printf("cleanup on signal (%v)...\n",sig)
cleanupOnShutdown()
os.Exit(0)
}()
}

///////////////////////////////////////////////////////////////////////////////

func sendPids(pidList []int) {
pidsData, err := json.Marshal(pidList)
failOnError(err)
Expand Down Expand Up @@ -832,6 +1010,12 @@ func main() {
appArgs = os.Args[2:]
}

initSignalHandlers()
defer func() {
fmt.Println("defered cleanup on shutdown...")
cleanupOnShutdown()
}()

/*
monitorPath := fmt.Sprintf("%s/amonitor",myFileDir())
log.Printf("launcher: start monitor (%v)\n",monitorPath)
Expand Down Expand Up @@ -871,6 +1055,7 @@ func main() {
pidsChan <- []int{app.Process.Pid}

log.Println("alauncher: waiting for monitor:")
/*
//TODO: fix the hard coded timeout
endTime := time.After(130 * time.Second)
work := 0
Expand All @@ -886,6 +1071,33 @@ doneRunning:
log.Printf(".")
}
}
*/

doneChan = make(chan struct{})
evtChannel,err = newEvtPublisher(evtChannelAddr)
failOnError(err)
cmdChannel,err = newCmdServer(cmdChannelAddr)
failOnError(err)

cmdChan,err := runCmdServer(cmdChannel,doneChan)
failOnError(err)
doneRunning:
for {
select {
case cmd := <-cmdChan:
log.Println("\nalauncher: command =>",cmd)
switch(cmd) {
case "monitor.finish":
log.Println("alauncher: stopping monitor...")
break doneRunning
default:
log.Println("alauncher: ignoring command =>",cmd)
}

case <-time.After(time.Second * 5):
log.Printf(".")
}
}

log.Println("launcher: stopping monitor...")
//monitor.Process.Signal(syscall.SIGTERM)
Expand All @@ -894,5 +1106,21 @@ doneRunning:
<-monDoneAckChan
//time.Sleep(3 * time.Second)

for ptry := 0; ptry < 3; ptry++ {
log.Println("launcher: trying to publish 'monitor.finish.completed' event (attempt %v)\n",ptry + 1)
err = publishEvt(evtChannel,"monitor.finish.completed")
if err != nil {
log.Println("launcher: published 'monitor.finish.completed'")
break
}

switch err {
case mangos.ErrRecvTimeout:
log.Println("launcher: publish event timeout... ok")
default:
log.Println("launcher: publish event error =>",err)
}
}

log.Println("launcher: done!")
}
Loading

0 comments on commit 721487e

Please sign in to comment.