pkg/linuxutils/linuxutils.go (82 lines of code) (raw):
// TODO: Consider modifying https://github.com/Azure/azure-extension-platform/blob/main/pkg/utils/utils_linux.go to
// add the logic to allow other extensions to delete all files and settings as desired.
package linuxutils
import (
"fmt"
"os"
"path/filepath"
"regexp"
"github.com/go-kit/kit/log"
"github.com/pkg/errors"
)
func TryClearExtensionScriptsDirectoriesAndSettingsFiles(ctx *log.Context, scriptsDirectory string, runtimeSettingsDirectory string, extensionName string, runtimeSettingsRegexFormatWithAnyExtName string) error {
// It is important to call both methods first and then handle the errors or unexpected files could remain in the VM.
// E.g., If nothing was dowloaded to the VM, the directory won't exist and thus the `TryDeleteDirectories` will return an error.
dirErr := TryDeleteDirectories(ctx, filepath.Join(scriptsDirectory, extensionName))
filesErr := tryClearRegexMatchingFiles(ctx, runtimeSettingsDirectory, runtimeSettingsRegexFormatWithAnyExtName, true)
if dirErr != nil && filesErr != nil {
return fmt.Errorf("failed to delete dirs: %w; failed to delete settings: %w", dirErr, filesErr)
} else if dirErr != nil {
return errors.Wrap(dirErr, "could not delete extension scripts directories")
} else if filesErr != nil {
return errors.Wrap(filesErr, "could not delete runtime settings files")
}
return nil
}
func TryDeleteDirectories(ctx *log.Context, parentDirectory string) error {
// Check if the directory exists
directoryFDRef, err := os.Open(parentDirectory)
if err != nil {
return errors.Wrap(err, "could not open parent directory")
}
dirEntries, err := directoryFDRef.ReadDir(0)
if err != nil {
return errors.Wrap(err, "could not read contents from directory")
}
if dirEntries != nil {
for _, dirEntry := range dirEntries {
if dirEntry.IsDir() {
fullDirectoryPath := filepath.Join(parentDirectory, dirEntry.Name())
ctx.Log("message", "trying to remove directory: "+fullDirectoryPath)
err = os.RemoveAll(fullDirectoryPath)
if err != nil {
ctx.Log("warning", "could not delete directory", "error", err)
}
}
}
return nil
}
return err
}
func tryClearRegexMatchingFiles(ctx *log.Context, directory string, regexFileNamePattern string, deleteFiles bool) error {
if regexFileNamePattern == "" {
return errors.New("empty regexFileNamePattern argument")
}
// Check if the directory exists
directoryFDRef, err := os.Open(directory)
if err != nil {
return errors.Wrap(err, "could not open directory")
}
regex, err := regexp.Compile(regexFileNamePattern)
if err != nil {
return errors.Wrap(err, "could not parse given regular expression")
}
dirEntries, err := directoryFDRef.ReadDir(0)
if err != nil {
return errors.Wrap(err, "could not read contents from directory")
}
for _, dirEntry := range dirEntries {
fileName := dirEntry.Name()
if regex.MatchString(fileName) {
fullFilePath := filepath.Join(directory, fileName)
if deleteFiles {
ctx.Log("message", "deleting file "+fullFilePath)
err = os.Remove(fullFilePath)
if err != nil {
ctx.Log("warning", "could not delete file", "error", err)
}
} else {
ctx.Log("message", "cleaning file "+fullFilePath)
err = os.Truncate(fullFilePath, 0) // Calling create on existing file truncates file
if err != nil {
ctx.Log("warning", "could not truncate file", "error", err)
}
}
}
}
return nil
}