server: fsnotify on hooks
Signed-off-by: Antonio Murdaca <runcom@redhat.com>
This commit is contained in:
parent
d6c32fa88e
commit
ca94095739
4 changed files with 91 additions and 5 deletions
|
@ -485,6 +485,9 @@ func main() {
|
|||
go func() {
|
||||
service.StartExitMonitor()
|
||||
}()
|
||||
go func() {
|
||||
service.StartHooksMonitor()
|
||||
}()
|
||||
|
||||
m := cmux.New(lis)
|
||||
grpcL := m.Match(cmux.HTTP2HeaderField("content-type", "application/grpc"))
|
||||
|
@ -527,7 +530,7 @@ func main() {
|
|||
<-streamServerCloseCh
|
||||
logrus.Debug("closed stream server")
|
||||
<-serverMonitorsCh
|
||||
logrus.Debug("closed exit monitor")
|
||||
logrus.Debug("closed monitors")
|
||||
<-serverCloseCh
|
||||
logrus.Debug("closed main server")
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ type ContainerServer struct {
|
|||
podNameIndex *registrar.Registrar
|
||||
podIDIndex *truncindex.TruncIndex
|
||||
hooks map[string]HookParams
|
||||
hooksLock sync.Mutex
|
||||
|
||||
imageContext *types.SystemContext
|
||||
stateLock sync.Locker
|
||||
|
@ -53,7 +54,41 @@ func (c *ContainerServer) Runtime() *oci.Runtime {
|
|||
|
||||
// Hooks returns the oci hooks for the ContainerServer
|
||||
func (c *ContainerServer) Hooks() map[string]HookParams {
|
||||
return c.hooks
|
||||
hooks := map[string]HookParams{}
|
||||
c.hooksLock.Lock()
|
||||
defer c.hooksLock.Unlock()
|
||||
for key, h := range c.hooks {
|
||||
hooks[key] = h
|
||||
}
|
||||
return hooks
|
||||
}
|
||||
|
||||
// RemoveHook removes an hook by name
|
||||
func (c *ContainerServer) RemoveHook(hook string) {
|
||||
c.hooksLock.Lock()
|
||||
defer c.hooksLock.Unlock()
|
||||
if _, ok := c.hooks[hook]; ok {
|
||||
delete(c.hooks, hook)
|
||||
}
|
||||
}
|
||||
|
||||
// AddHook adds an hook by hook's path
|
||||
func (c *ContainerServer) AddHook(hookPath string) {
|
||||
c.hooksLock.Lock()
|
||||
defer c.hooksLock.Unlock()
|
||||
hook, err := readHook(hookPath)
|
||||
if err != nil {
|
||||
logrus.Debugf("error while reading hook %s", hookPath)
|
||||
return
|
||||
}
|
||||
for key, h := range c.hooks {
|
||||
// hook.Hook can only be defined in one hook file, unless it has the
|
||||
// same name in the override path.
|
||||
if hook.Hook == h.Hook && key != filepath.Base(hookPath) {
|
||||
logrus.Debugf("duplicate path, hook %q from %q already defined in %q", hook.Hook, c.config.HooksDirPath, key)
|
||||
}
|
||||
}
|
||||
c.hooks[filepath.Base(hookPath)] = hook
|
||||
}
|
||||
|
||||
// Store returns the Store for the ContainerServer
|
||||
|
@ -153,6 +188,7 @@ func New(config *Config) (*ContainerServer, error) {
|
|||
}
|
||||
}
|
||||
}
|
||||
logrus.Debugf("hooks %+v", hooks)
|
||||
|
||||
return &ContainerServer{
|
||||
runtime: runtime,
|
||||
|
|
13
lib/hooks.go
13
lib/hooks.go
|
@ -30,9 +30,16 @@ type HookParams struct {
|
|||
Arguments []string `json:"arguments"`
|
||||
}
|
||||
|
||||
var (
|
||||
errNotJSON = errors.New("hook file isn't a JSON")
|
||||
)
|
||||
|
||||
// readHook reads hooks json files, verifies it and returns the json config
|
||||
func readHook(hookPath string) (HookParams, error) {
|
||||
var hook HookParams
|
||||
if !strings.HasSuffix(hookPath, ".json") {
|
||||
return hook, errNotJSON
|
||||
}
|
||||
raw, err := ioutil.ReadFile(hookPath)
|
||||
if err != nil {
|
||||
return hook, errors.Wrapf(err, "error Reading hook %q", hookPath)
|
||||
|
@ -83,11 +90,11 @@ func readHooks(hooksPath string, hooks map[string]HookParams) error {
|
|||
}
|
||||
|
||||
for _, file := range files {
|
||||
if !strings.HasSuffix(file.Name(), ".json") {
|
||||
continue
|
||||
}
|
||||
hook, err := readHook(filepath.Join(hooksPath, file.Name()))
|
||||
if err != nil {
|
||||
if err == errNotJSON {
|
||||
continue
|
||||
}
|
||||
return err
|
||||
}
|
||||
for key, h := range hooks {
|
||||
|
|
|
@ -365,6 +365,46 @@ func (s *Server) MonitorsCloseChan() chan struct{} {
|
|||
return s.monitorsChan
|
||||
}
|
||||
|
||||
// StartHooksMonitor starts a goroutine to dynamically add hooks at runtime
|
||||
func (s *Server) StartHooksMonitor() {
|
||||
watcher, err := fsnotify.NewWatcher()
|
||||
if err != nil {
|
||||
logrus.Fatalf("Failed to create new watch: %v", err)
|
||||
}
|
||||
defer watcher.Close()
|
||||
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case event := <-watcher.Events:
|
||||
logrus.Debugf("event: %v", event)
|
||||
if event.Op&fsnotify.Remove == fsnotify.Remove {
|
||||
logrus.Debugf("removing hook %s", event.Name)
|
||||
s.ContainerServer.RemoveHook(filepath.Base(event.Name))
|
||||
}
|
||||
if event.Op&fsnotify.Create == fsnotify.Create || event.Op&fsnotify.Write == fsnotify.Write {
|
||||
logrus.Debugf("adding hook %s", event.Name)
|
||||
s.ContainerServer.AddHook(event.Name)
|
||||
}
|
||||
case err := <-watcher.Errors:
|
||||
logrus.Debugf("watch error: %v", err)
|
||||
close(done)
|
||||
return
|
||||
case <-s.monitorsChan:
|
||||
logrus.Debug("closing hooks monitor...")
|
||||
close(done)
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
if err := watcher.Add(s.config.HooksDirPath); err != nil {
|
||||
logrus.Errorf("watcher.Add(%q) failed: %s", s.config.HooksDirPath, err)
|
||||
close(done)
|
||||
}
|
||||
<-done
|
||||
}
|
||||
|
||||
// StartExitMonitor start a routine that monitors container exits
|
||||
// and updates the container status
|
||||
func (s *Server) StartExitMonitor() {
|
||||
|
|
Loading…
Reference in a new issue