forked from slimtoolkit/slim
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[feat] Standalone control commands (slimtoolkit#596)
To control sensor execution when running in the standalone mode. This PR ships the machinery and the very first command: ``` /opt/_slim/sensor control stop-target-app ``` The command writes to the commands FIFO file and then waits for the StopMonitorDone event to show up in the events file. Signed-off-by: Ivan Velichko <iximiuz@gmail.com>
- Loading branch information
Showing
9 changed files
with
300 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package control | ||
|
||
type Command string | ||
|
||
const ( | ||
StopTargetAppCommand Command = "stop-target-app" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
package control | ||
|
||
import ( | ||
"bufio" | ||
"context" | ||
"io" | ||
"os" | ||
"syscall" | ||
"time" | ||
|
||
log "github.com/sirupsen/logrus" | ||
|
||
"github.com/docker-slim/docker-slim/pkg/ipc/command" | ||
) | ||
|
||
func HandleControlCommandQueue(ctx context.Context, commandsFile string, commandCh chan command.Message) { | ||
fifoPath := getFIFOPath(commandsFile) | ||
if !createFIFOIfNeeded(fifoPath) { | ||
return | ||
} | ||
go func() { | ||
<-ctx.Done() | ||
os.Remove(fifoPath) | ||
}() | ||
|
||
processCommandsFromFIFO(ctx, fifoPath, commandCh) | ||
} | ||
|
||
func getFIFOPath(commandsFile string) string { | ||
return commandsFile + ".fifo" | ||
} | ||
|
||
func createFIFOIfNeeded(fifoPath string) bool { | ||
if _, err := os.Stat(fifoPath); os.IsNotExist(err) { | ||
if err = syscall.Mkfifo(fifoPath, 0600); err != nil { | ||
log.Warnf("sensor: control commands not activated - cannot create %s FIFO file: %s", fifoPath, err) | ||
return false | ||
} | ||
log.Info("sensor: control commands activated") | ||
} | ||
return true | ||
} | ||
|
||
func processCommandsFromFIFO(ctx context.Context, fifoPath string, commandCh chan command.Message) { | ||
for ctx.Err() == nil { | ||
fifo, err := os.Open(fifoPath) | ||
if err != nil { | ||
log.Debugf("sensor: control commands - cannot open %s FIFO file: %s", fifoPath, err) | ||
time.Sleep(1 * time.Second) | ||
continue | ||
} | ||
|
||
readAndHandleCommands(fifo, commandCh) | ||
fifo.Close() | ||
} | ||
} | ||
|
||
func readAndHandleCommands(fifo *os.File, commandCh chan command.Message) { | ||
reader := bufio.NewReader(fifo) | ||
for { | ||
line, err := reader.ReadBytes('\n') | ||
if len(line) > 0 { | ||
handleCommand(line, commandCh) | ||
} | ||
|
||
if err == io.EOF { | ||
return | ||
} | ||
if err != nil { | ||
log.Warnf("sensor: error reading control command: %s", err) | ||
time.Sleep(1 * time.Second) | ||
} | ||
} | ||
} | ||
|
||
func handleCommand(line []byte, commandCh chan command.Message) { | ||
msg, err := command.Decode(line) | ||
if err == nil { | ||
commandCh <- msg | ||
} else { | ||
log.Warnf("sensor: cannot decode control command %#q: %s", line, err) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
package control | ||
|
||
import ( | ||
"bufio" | ||
"context" | ||
"fmt" | ||
"os" | ||
"strings" | ||
"time" | ||
|
||
"github.com/docker-slim/docker-slim/pkg/ipc/command" | ||
"github.com/docker-slim/docker-slim/pkg/ipc/event" | ||
"github.com/docker-slim/docker-slim/pkg/util/fsutil" | ||
) | ||
|
||
func ExecuteStopTargetAppCommand( | ||
ctx context.Context, | ||
commandsFile string, | ||
eventsFile string, | ||
) error { | ||
msg, err := command.Encode(&command.StopMonitor{}) | ||
if err != nil { | ||
return fmt.Errorf("cannot encode stop command: %w", err) | ||
} | ||
|
||
if err := fsutil.AppendToFile(getFIFOPath(commandsFile), msg, false); err != nil { | ||
return fmt.Errorf("cannot append stop command to FIFO file: %w", err) | ||
} | ||
|
||
if err := waitForEvent(ctx, eventsFile, event.StopMonitorDone); err != nil { | ||
return fmt.Errorf("waiting for %v event: %w", event.StopMonitorDone, err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func waitForEvent(ctx context.Context, eventsFile string, target event.Type) error { | ||
for ctx.Err() == nil { | ||
found, err := findEvent(eventsFile, target) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if found { | ||
return nil | ||
} | ||
|
||
time.Sleep(1 * time.Second) | ||
} | ||
|
||
return ctx.Err() | ||
} | ||
|
||
func findEvent(eventsFile string, target event.Type) (bool, error) { | ||
file, err := os.Open(eventsFile) | ||
if err != nil { | ||
return false, err | ||
} | ||
defer file.Close() | ||
|
||
scanner := bufio.NewScanner(file) | ||
for scanner.Scan() { | ||
line := scanner.Text() | ||
// A bit hacky - we probably need to parse the event struct properly. | ||
if strings.Contains(line, string(target)) { | ||
return true, nil | ||
} | ||
} | ||
|
||
if scanner.Err() != nil { | ||
return false, scanner.Err() | ||
} | ||
|
||
return false, nil | ||
} |
Oops, something went wrong.