Merge pull request #158 from Quentin-M/contrib_cleanup_signals

contrib: Catch signals to delete tmp folder in local-analyze-images
This commit is contained in:
Quentin Machu 2016-04-26 17:35:50 -04:00
commit 01efa56929

View File

@ -27,6 +27,7 @@ import (
"net/http" "net/http"
"os" "os"
"os/exec" "os/exec"
"os/signal"
"sort" "sort"
"strconv" "strconv"
"strings" "strings"
@ -85,6 +86,10 @@ func (s *sorter) Less(i, j int) bool {
} }
func main() { func main() {
os.Exit(intMain())
}
func intMain() int {
// Parse command-line arguments. // Parse command-line arguments.
flag.Usage = func() { flag.Usage = func() {
fmt.Fprintf(os.Stderr, "Usage: %s [options] image-id\n\nOptions:\n", os.Args[0]) fmt.Fprintf(os.Stderr, "Usage: %s [options] image-id\n\nOptions:\n", os.Args[0])
@ -94,14 +99,14 @@ func main() {
if len(flag.Args()) != 1 { if len(flag.Args()) != 1 {
flag.Usage() flag.Usage()
os.Exit(1) return 1
} }
imageName := flag.Args()[0] imageName := flag.Args()[0]
minSeverity := types.Priority(*flagMinimumSeverity) minSeverity := types.Priority(*flagMinimumSeverity)
if !minSeverity.IsValid() { if !minSeverity.IsValid() {
flag.Usage() flag.Usage()
os.Exit(1) return 1
} }
if *flagColorMode == "never" { if *flagColorMode == "never" {
@ -110,24 +115,46 @@ func main() {
color.NoColor = false color.NoColor = false
} }
err := AnalyzeLocalImage(imageName, minSeverity, *flagEndpoint, *flagMyAddress) // Create a temporary folder.
tmpPath, err := ioutil.TempDir("", "analyze-local-image-")
if err != nil { if err != nil {
log.Fatal(err) log.Fatalf("Could not create temporary folder: %s", err)
} }
defer os.RemoveAll(tmpPath)
// Intercept SIGINT / SIGKILl signals.
interrupt := make(chan os.Signal)
signal.Notify(interrupt, os.Interrupt, os.Kill)
// Analyze the image.
analyzeCh := make(chan error, 1)
go func() {
analyzeCh <- AnalyzeLocalImage(imageName, minSeverity, *flagEndpoint, *flagMyAddress, tmpPath)
}()
select {
case <-interrupt:
return 130
case err := <-analyzeCh:
if err != nil {
log.Print(err)
return 1
}
}
return 0
} }
func AnalyzeLocalImage(imageName string, minSeverity types.Priority, endpoint, myAddress string) error { func AnalyzeLocalImage(imageName string, minSeverity types.Priority, endpoint, myAddress, tmpPath string) error {
// Save image. // Save image.
log.Printf("Saving %s to local disk (this may take some time)", imageName) log.Printf("Saving %s to local disk (this may take some time)", imageName)
path, err := save(imageName) err := save(imageName, tmpPath)
defer os.RemoveAll(path)
if err != nil { if err != nil {
return fmt.Errorf("Could not save image: %s", err) return fmt.Errorf("Could not save image: %s", err)
} }
// Retrieve history. // Retrieve history.
log.Println("Retrieving image history") log.Println("Retrieving image history")
layerIDs, err := historyFromManifest(path) layerIDs, err := historyFromManifest(tmpPath)
if err != nil { if err != nil {
layerIDs, err = historyFromCommand(imageName) layerIDs, err = historyFromCommand(imageName)
} }
@ -146,7 +173,7 @@ func AnalyzeLocalImage(imageName string, minSeverity types.Priority, endpoint, m
log.Printf("Setting up HTTP server (allowing: %s)\n", allowedHost) log.Printf("Setting up HTTP server (allowing: %s)\n", allowedHost)
ch := make(chan error) ch := make(chan error)
go listenHTTP(path, allowedHost, ch) go listenHTTP(tmpPath, allowedHost, ch)
select { select {
case err := <-ch: case err := <-ch:
return fmt.Errorf("An error occured when starting HTTP server: %s", err) return fmt.Errorf("An error occured when starting HTTP server: %s", err)
@ -154,7 +181,7 @@ func AnalyzeLocalImage(imageName string, minSeverity types.Priority, endpoint, m
break break
} }
path = "http://" + myAddress + ":" + strconv.Itoa(httpPort) tmpPath = "http://" + myAddress + ":" + strconv.Itoa(httpPort)
} }
// Analyze layers. // Analyze layers.
@ -162,11 +189,10 @@ func AnalyzeLocalImage(imageName string, minSeverity types.Priority, endpoint, m
for i := 0; i < len(layerIDs); i++ { for i := 0; i < len(layerIDs); i++ {
log.Printf("Analyzing %s\n", layerIDs[i]) log.Printf("Analyzing %s\n", layerIDs[i])
var err error
if i > 0 { if i > 0 {
err = analyzeLayer(endpoint, path+"/"+layerIDs[i]+"/layer.tar", layerIDs[i], layerIDs[i-1]) err = analyzeLayer(endpoint, tmpPath+"/"+layerIDs[i]+"/layer.tar", layerIDs[i], layerIDs[i-1])
} else { } else {
err = analyzeLayer(endpoint, path+"/"+layerIDs[i]+"/layer.tar", layerIDs[i], "") err = analyzeLayer(endpoint, tmpPath+"/"+layerIDs[i]+"/layer.tar", layerIDs[i], "")
} }
if err != nil { if err != nil {
return fmt.Errorf("Could not analyze layer: %s", err) return fmt.Errorf("Could not analyze layer: %s", err)
@ -249,12 +275,7 @@ func AnalyzeLocalImage(imageName string, minSeverity types.Priority, endpoint, m
return nil return nil
} }
func save(imageName string) (string, error) { func save(imageName, path string) error {
path, err := ioutil.TempDir("", "analyze-local-image-")
if err != nil {
return "", err
}
var stderr bytes.Buffer var stderr bytes.Buffer
save := exec.Command("docker", "save", imageName) save := exec.Command("docker", "save", imageName)
save.Stderr = &stderr save.Stderr = &stderr
@ -262,28 +283,28 @@ func save(imageName string) (string, error) {
extract.Stderr = &stderr extract.Stderr = &stderr
pipe, err := extract.StdinPipe() pipe, err := extract.StdinPipe()
if err != nil { if err != nil {
return "", err return err
} }
save.Stdout = pipe save.Stdout = pipe
err = extract.Start() err = extract.Start()
if err != nil { if err != nil {
return "", errors.New(stderr.String()) return errors.New(stderr.String())
} }
err = save.Run() err = save.Run()
if err != nil { if err != nil {
return "", errors.New(stderr.String()) return errors.New(stderr.String())
} }
err = pipe.Close() err = pipe.Close()
if err != nil { if err != nil {
return "", err return err
} }
err = extract.Wait() err = extract.Wait()
if err != nil { if err != nil {
return "", errors.New(stderr.String()) return errors.New(stderr.String())
} }
return path, nil return nil
} }
func historyFromManifest(path string) ([]string, error) { func historyFromManifest(path string) ([]string, error) {