Remove tasks and containers on SIGINT/SIGTERM

* Cleans-up and removes faasd containers/tasks when receiving
SIGINT/SIGTERM

Signed-off-by: Alex Ellis (OpenFaaS Ltd) <alexellis2@gmail.com>
This commit is contained in:
Alex Ellis (OpenFaaS Ltd) 2019-12-24 10:09:56 +00:00
parent da16bdeee8
commit 3ee52c6ed7
2 changed files with 76 additions and 35 deletions

View File

@ -1,9 +1,13 @@
package cmd
import (
"fmt"
"log"
"os"
"os/signal"
"path"
"sync"
"syscall"
"time"
"github.com/alexellis/faasd/pkg"
@ -40,8 +44,28 @@ func runUp(_ *cobra.Command, _ []string) error {
log.Printf("Supervisor init done in: %s\n", time.Since(start).String())
time.Sleep(time.Minute * 120)
shutdownTimeout := time.Second * 1
wg := sync.WaitGroup{}
wg.Add(1)
go func() {
sig := make(chan os.Signal, 1)
signal.Notify(sig, syscall.SIGTERM, syscall.SIGINT)
log.Printf("faasd: waiting for SIGTERM or SIGINT\n")
<-sig
log.Printf("Signal received.. shutting down server in %s\n", shutdownTimeout.String())
err := supervisor.Remove(services)
if err != nil {
fmt.Println(err)
}
time.AfterFunc(shutdownTimeout, func() {
wg.Done()
})
}()
wg.Wait()
return nil
}

View File

@ -44,6 +44,18 @@ func (s *Supervisor) Close() {
defer s.client.Close()
}
func (s *Supervisor) Remove(svcs []Service) error {
ctx := namespaces.WithNamespace(context.Background(), "default")
for _, svc := range svcs {
err := removeContainer(ctx, s.client, svc.Name)
if err != nil {
return err
}
}
return nil
}
func (s *Supervisor) Start(svcs []Service) error {
ctx := namespaces.WithNamespace(context.Background(), "default")
@ -61,7 +73,7 @@ func (s *Supervisor) Start(svcs []Service) error {
images := map[string]containerd.Image{}
for _, svc := range svcs {
fmt.Printf("Preparing: %s\n", svc.Name)
fmt.Printf("Preparing: %s with image: %s\n", svc.Name, svc.Image)
img, err := prepareImage(ctx, s.client, svc.Image)
if err != nil {
@ -70,7 +82,6 @@ func (s *Supervisor) Start(svcs []Service) error {
images[svc.Name] = img
size, _ := img.Size(ctx)
fmt.Printf("Prepare done for: %s, %d bytes\n", svc.Image, size)
}
for _, svc := range svcs {
@ -78,37 +89,9 @@ func (s *Supervisor) Start(svcs []Service) error {
image := images[svc.Name]
container, containerErr := s.client.LoadContainer(ctx, svc.Name)
if containerErr == nil {
found := true
t, err := container.Task(ctx, nil)
if err != nil {
if errdefs.IsNotFound(err) {
found = false
} else {
return fmt.Errorf("unable to get task %s: ", err)
}
}
if found {
status, _ := t.Status(ctx)
fmt.Println("Status:", status.Status)
// if status.Status == containerd.Running {
log.Println("need to kill", svc.Name)
err := killTask(ctx, t)
if err != nil {
return fmt.Errorf("error killing task %s, %s, %s", container.ID(), svc.Name, err)
}
// }
}
err = container.Delete(ctx, containerd.WithSnapshotCleanup)
if err != nil {
return fmt.Errorf("error deleting container %s, %s, %s", container.ID(), svc.Name, err)
}
containerErr := removeContainer(ctx, s.client, svc.Name)
if containerErr != nil {
return containerErr
}
mounts := []specs.Mount{}
@ -185,7 +168,7 @@ func (s *Supervisor) Start(svcs []Service) error {
return err
}
ip := getIP(container.ID(), task.Pid())
ip := getIP(newContainer.ID(), task.Pid())
hosts, _ := ioutil.ReadFile("hosts")
@ -324,3 +307,37 @@ func killTask(ctx context.Context, task containerd.Task) error {
return err
}
func removeContainer(ctx context.Context, client *containerd.Client, name string) error {
container, containerErr := client.LoadContainer(ctx, name)
if containerErr == nil {
found := true
t, err := container.Task(ctx, nil)
if err != nil {
if errdefs.IsNotFound(err) {
found = false
} else {
return fmt.Errorf("unable to get task %s: ", err)
}
}
if found {
status, _ := t.Status(ctx)
fmt.Printf("Status of %s is: %s\n", name, status.Status)
log.Printf("Need to kill %s\n", name)
err := killTask(ctx, t)
if err != nil {
return fmt.Errorf("error killing task %s, %s, %s", container.ID(), name, err)
}
}
err = container.Delete(ctx, containerd.WithSnapshotCleanup)
if err != nil {
return fmt.Errorf("error deleting container %s, %s, %s", container.ID(), name, err)
}
}
return nil
}