Skip to content

Commit

Permalink
Handle cleanup for interrupt (#322)
Browse files Browse the repository at this point in the history
handle cleanup for interrupt

Signed-off-by: Emily McMullan <[email protected]>
  • Loading branch information
eemcmullan authored Aug 22, 2024
1 parent f1ad67c commit 2b4caf5
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 85 deletions.
98 changes: 13 additions & 85 deletions cmd/analyze.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"io/fs"
"os"
"os/exec"
"os/signal"
"path"
"runtime"

Expand Down Expand Up @@ -181,6 +182,9 @@ func NewAnalyzeCmd(log logr.Logger) *cobra.Command {
if val, err := cmd.Flags().GetBool(noCleanupFlag); err == nil {
analyzeCmd.cleanup = !val
}
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
defer stop()

if analyzeCmd.overrideProviderSettings == "" {
if analyzeCmd.listSources || analyzeCmd.listTargets {
err := analyzeCmd.ListLabels(cmd.Context())
Expand Down Expand Up @@ -222,7 +226,7 @@ func NewAnalyzeCmd(log logr.Logger) *cobra.Command {
}
}
if len(foundProviders) == 1 && foundProviders[0] == dotnetFrameworkProvider {
return analyzeCmd.analyzeDotnetFramework(cmd.Context())
return analyzeCmd.analyzeDotnetFramework(ctx)
}

// default rulesets are only java rules
Expand All @@ -231,7 +235,7 @@ func NewAnalyzeCmd(log logr.Logger) *cobra.Command {
return fmt.Errorf("No providers found with default rules. Use --rules option")
}

xmlOutputDir, err := analyzeCmd.ConvertXML(cmd.Context())
xmlOutputDir, err := analyzeCmd.ConvertXML(ctx)
if err != nil {
log.Error(err, "failed to convert xml rules")
return err
Expand All @@ -240,7 +244,7 @@ func NewAnalyzeCmd(log logr.Logger) *cobra.Command {
// in this case we need to run only the analyzer to use builtin provider
if len(foundProviders) == 0 {
analyzeCmd.needsBuiltin = true
return analyzeCmd.RunAnalysis(cmd.Context(), xmlOutputDir, analyzeCmd.input)
return analyzeCmd.RunAnalysis(ctx, xmlOutputDir, analyzeCmd.input)
}

err = analyzeCmd.setProviderInitInfo(foundProviders)
Expand All @@ -251,7 +255,8 @@ func NewAnalyzeCmd(log logr.Logger) *cobra.Command {
// defer cleaning created resources here instead of PostRun
// if Run returns an error, PostRun does not run
defer func() {
if err := analyzeCmd.CleanAnalysisResources(cmd.Context()); err != nil {
// start other context here to cleanup in case of program interrupt
if err := analyzeCmd.CleanAnalysisResources(context.TODO()); err != nil {
log.Error(err, "failed to clean temporary directories")
}
}()
Expand All @@ -267,18 +272,18 @@ func NewAnalyzeCmd(log logr.Logger) *cobra.Command {
return err
}
// allow for 5 retries of running provider in the case of port in use
err = analyzeCmd.RunProviders(cmd.Context(), containerNetworkName, containerVolName, 5)
err = analyzeCmd.RunProviders(ctx, containerNetworkName, containerVolName, 5)
if err != nil {
log.Error(err, "failed to run provider")
return err
}
err = analyzeCmd.RunAnalysis(cmd.Context(), xmlOutputDir, containerVolName)
err = analyzeCmd.RunAnalysis(ctx, xmlOutputDir, containerVolName)
if err != nil {
log.Error(err, "failed to run analysis")
return err
}
} else {
err := analyzeCmd.RunAnalysisOverrideProviderSettings(cmd.Context())
err := analyzeCmd.RunAnalysisOverrideProviderSettings(ctx)
if err != nil {
log.Error(err, "failed to run analysis")
return err
Expand All @@ -290,7 +295,7 @@ func NewAnalyzeCmd(log logr.Logger) *cobra.Command {
return err
}

err = analyzeCmd.GenerateStaticReport(cmd.Context())
err = analyzeCmd.GenerateStaticReport(ctx)
if err != nil {
log.Error(err, "failed to generate static report")
return err
Expand Down Expand Up @@ -1949,83 +1954,6 @@ func (a *analyzeCommand) mergeProviderSpecificConfig(optionsConf, seenConf map[s
return seenConf, nil
}

func (a *analyzeCommand) CleanAnalysisResources(ctx context.Context) error {
if !a.cleanup || a.needsBuiltin {
return nil
}
a.log.V(1).Info("removing temp dirs")
for _, path := range a.tempDirs {
err := os.RemoveAll(path)
if err != nil {
a.log.V(1).Error(err, "failed to delete temporary dir", "dir", path)
continue
}
}
err := a.RmProviderContainers(ctx)
if err != nil {
a.log.Error(err, "failed to remove provider container")
}
err = a.RmNetwork(ctx)
if err != nil {
a.log.Error(err, "failed to remove network", "network", a.networkName)
}
err = a.RmVolumes(ctx)
if err != nil {
a.log.Error(err, "failed to remove volume", "volume", a.volumeName)
}
return nil
}

func (a *analyzeCommand) RmNetwork(ctx context.Context) error {
if a.networkName == "" {
return nil
}
cmd := exec.CommandContext(
ctx,
Settings.ContainerBinary,
"network",
"rm", a.networkName)
a.log.V(1).Info("removing container network",
"network", a.networkName)
return cmd.Run()
}

func (a *analyzeCommand) RmVolumes(ctx context.Context) error {
if a.volumeName == "" {
return nil
}
cmd := exec.CommandContext(
ctx,
Settings.ContainerBinary,
"volume",
"rm", a.volumeName)
a.log.V(1).Info("removing created volume",
"volume", a.volumeName)
return cmd.Run()
}

func (a *analyzeCommand) RmProviderContainers(ctx context.Context) error {
// if multiple provider containers, we need to remove the first created provider container last
for i := len(a.providerContainerNames) - 1; i >= 0; i-- {
con := a.providerContainerNames[i]
// because we are using the --rm option when we start the provider container,
// it will immediately be removed after it stops
cmd := exec.CommandContext(
ctx,
Settings.ContainerBinary,
"stop", con)
a.log.V(1).Info("stopping container", "container", con)
err := cmd.Run()
if err != nil {
a.log.V(1).Error(err, "failed to stop container",
"container", con)
continue
}
}

return nil
}

func (a *analyzeCommand) getProviderLogs(ctx context.Context) error {
if len(a.providerContainerNames) == 0 || a.needsBuiltin {
return nil
Expand Down
85 changes: 85 additions & 0 deletions cmd/cleanup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package cmd

import (
"context"
"os"
"os/exec"
)

func (a *analyzeCommand) CleanAnalysisResources(ctx context.Context) error {
if !a.cleanup || a.needsBuiltin {
return nil
}
a.log.V(1).Info("removing temp dirs")
for _, path := range a.tempDirs {
err := os.RemoveAll(path)
if err != nil {
a.log.V(1).Error(err, "failed to delete temporary dir", "dir", path)
continue
}
}
err := a.RmProviderContainers(ctx)
if err != nil {
a.log.Error(err, "failed to remove provider container")
}
err = a.RmNetwork(ctx)
if err != nil {
a.log.Error(err, "failed to remove network", "network", a.networkName)
}
err = a.RmVolumes(ctx)
if err != nil {
a.log.Error(err, "failed to remove volume", "volume", a.volumeName)
}
return nil
}

func (a *analyzeCommand) RmNetwork(ctx context.Context) error {
if a.networkName == "" {
return nil
}
a.log.V(1).Info("removing container network",
"network", a.networkName)
cmd := exec.CommandContext(
ctx,
Settings.ContainerBinary,
"network",
"rm", a.networkName)
a.log.V(1).Info("removing container network",
"network", a.networkName)
return cmd.Run()
}

func (a *analyzeCommand) RmVolumes(ctx context.Context) error {
if a.volumeName == "" {
return nil
}
cmd := exec.CommandContext(
ctx,
Settings.ContainerBinary,
"volume",
"rm", a.volumeName)
a.log.V(1).Info("removing created volume",
"volume", a.volumeName)
return cmd.Run()
}

func (a *analyzeCommand) RmProviderContainers(ctx context.Context) error {
// if multiple provider containers, we need to remove the first created provider container last
for i := len(a.providerContainerNames) - 1; i >= 0; i-- {
con := a.providerContainerNames[i]
// because we are using the --rm option when we start the provider container,
// it will immediately be removed after it stops
cmd := exec.CommandContext(
ctx,
Settings.ContainerBinary,
"stop", con)
a.log.V(1).Info("stopping provider container", "container", con)
err := cmd.Run()
if err != nil {
a.log.V(1).Error(err, "failed to stop container",
"container", con)
continue
}
}
return nil
}

0 comments on commit 2b4caf5

Please sign in to comment.