Skip to content

Commit 2c18bfe

Browse files
authored
Update atomic writes logic to create hidden files in same directory as the files being updated (#1348)
1 parent f2a3998 commit 2c18bfe

File tree

6 files changed

+72
-195
lines changed

6 files changed

+72
-195
lines changed

internal/datasource/config/nginx_config_parser.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,29 @@ const (
4444
locationDirective = "location"
4545
)
4646

47+
var globFunction = func(path string) ([]string, error) {
48+
matches, err := filepath.Glob(path)
49+
if err != nil {
50+
return nil, err
51+
}
52+
53+
// Exclude hidden files unless the glob pattern itself starts with a dot
54+
if !strings.HasPrefix(filepath.Base(path), ".") {
55+
filteredMatches := make([]string, 0)
56+
57+
for _, match := range matches {
58+
base := filepath.Base(match)
59+
if !strings.HasPrefix(base, ".") {
60+
filteredMatches = append(filteredMatches, match)
61+
}
62+
}
63+
64+
return filteredMatches, nil
65+
}
66+
67+
return matches, nil
68+
}
69+
4770
//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6@v6.8.1 -generate
4871
//counterfeiter:generate . ConfigParser
4972

@@ -95,6 +118,7 @@ func (ncp *NginxConfigParser) Parse(ctx context.Context, instance *mpi.Instance)
95118
LexOptions: crossplane.LexOptions{
96119
Lexers: []crossplane.RegisterLexer{lua.RegisterLexer()},
97120
},
121+
Glob: globFunction,
98122
},
99123
)
100124
if err != nil {

internal/file/file_manager_service.go

Lines changed: 37 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import (
1313
"fmt"
1414
"log/slog"
1515
"os"
16-
"path"
1716
"path/filepath"
1817
"strconv"
1918
"sync"
@@ -82,7 +81,6 @@ type (
8281
err error)
8382
Rollback(ctx context.Context, instanceID string) error
8483
ClearCache()
85-
SetConfigPath(configPath string)
8684
ConfigUpload(ctx context.Context, configUploadRequest *mpi.ConfigUploadRequest) error
8785
ConfigUpdate(ctx context.Context, nginxConfigContext *model.NginxConfigContext)
8886
UpdateCurrentFilesOnDisk(ctx context.Context, updateFiles map[string]*mpi.File, referenced bool) error
@@ -108,9 +106,6 @@ type FileManagerService struct {
108106
currentFilesOnDisk map[string]*mpi.File // key is file path
109107
previousManifestFiles map[string]*model.ManifestFile
110108
manifestFilePath string
111-
tempConfigDir string
112-
tempRollbackDir string
113-
tempConfigPath string
114109
rollbackManifest bool
115110
filesMutex sync.RWMutex
116111
}
@@ -131,11 +126,6 @@ func NewFileManagerService(fileServiceClient mpi.FileServiceClient, agentConfig
131126
}
132127
}
133128

134-
func (fms *FileManagerService) SetConfigPath(configPath string) {
135-
fms.tempConfigPath = fmt.Sprintf("%s/.agent-%s", filepath.Dir(configPath), fms.agentConfig.UUID)
136-
fms.ClearCache()
137-
}
138-
139129
func (fms *FileManagerService) ResetClient(ctx context.Context, fileServiceClient mpi.FileServiceClient) {
140130
fms.fileServiceOperator.UpdateClient(ctx, fileServiceClient)
141131
slog.DebugContext(ctx, "File manager service reset client successfully")
@@ -152,9 +142,6 @@ func (fms *FileManagerService) SetIsConnected(isConnected bool) {
152142
func (fms *FileManagerService) ConfigApply(ctx context.Context,
153143
configApplyRequest *mpi.ConfigApplyRequest,
154144
) (status model.WriteStatus, err error) {
155-
var configTempErr error
156-
var rollbackTempErr error
157-
158145
fms.rollbackManifest = true
159146
fileOverview := configApplyRequest.GetOverview()
160147

@@ -189,16 +176,6 @@ func (fms *FileManagerService) ConfigApply(ctx context.Context,
189176

190177
fms.fileActions = diffFiles
191178

192-
fms.tempConfigDir, configTempErr = fms.createTempConfigDirectory("config")
193-
if configTempErr != nil {
194-
return model.Error, configTempErr
195-
}
196-
197-
fms.tempRollbackDir, rollbackTempErr = fms.createTempConfigDirectory("rollback")
198-
if rollbackTempErr != nil {
199-
return model.Error, rollbackTempErr
200-
}
201-
202179
rollbackTempFilesErr := fms.backupFiles(ctx)
203180
if rollbackTempFilesErr != nil {
204181
return model.Error, rollbackTempFilesErr
@@ -220,14 +197,22 @@ func (fms *FileManagerService) ConfigApply(ctx context.Context,
220197
}
221198

222199
func (fms *FileManagerService) ClearCache() {
223-
slog.Debug("Clearing cache and temp files")
224-
clear(fms.fileActions)
225-
clear(fms.previousManifestFiles)
200+
slog.Debug("Clearing cache and backup files")
226201

227-
configErr := os.RemoveAll(fms.tempConfigPath)
228-
if configErr != nil && !os.IsNotExist(configErr) {
229-
slog.Error("Error removing temp directory", "path", fms.tempConfigDir, "err", configErr)
202+
for _, fileAction := range fms.fileActions {
203+
if fileAction.Action == model.Update || fileAction.Action == model.Delete {
204+
tempFilePath := tempBackupFilePath(fileAction.File.GetFileMeta().GetName())
205+
if err := os.Remove(tempFilePath); err != nil && !os.IsNotExist(err) {
206+
slog.Warn("Unable to delete backup file",
207+
"file", fileAction.File.GetFileMeta().GetName(),
208+
"error", err,
209+
)
210+
}
211+
}
230212
}
213+
214+
clear(fms.fileActions)
215+
clear(fms.previousManifestFiles)
231216
}
232217

233218
//nolint:revive,cyclop // cognitive-complexity of 13 max is 12, loop is needed cant be broken up
@@ -502,7 +487,7 @@ func (fms *FileManagerService) backupFiles(ctx context.Context) error {
502487
continue
503488
}
504489

505-
tempFilePath := filepath.Join(fms.tempRollbackDir, filePath)
490+
tempFilePath := tempBackupFilePath(filePath)
506491
slog.DebugContext(ctx, "Attempting to backup file content since file exists", "temp_path", tempFilePath)
507492

508493
moveErr := fms.fileOperator.MoveFile(ctx, filePath, tempFilePath)
@@ -519,7 +504,7 @@ func (fms *FileManagerService) restoreFiles(fileAction *model.FileCache) ([]byte
519504
fileMeta := fileAction.File.GetFileMeta()
520505
fileName := fileMeta.GetName()
521506

522-
tempFilePath := filepath.Join(fms.tempRollbackDir, fileName)
507+
tempFilePath := tempBackupFilePath(fileName)
523508

524509
// Create parent directories for the target file if they don't exist
525510
if err := os.MkdirAll(filepath.Dir(fileName), dirPerm); err != nil {
@@ -570,26 +555,24 @@ func (fms *FileManagerService) manifestFile() (map[string]*model.ManifestFile, m
570555

571556
func (fms *FileManagerService) executeFileActions(ctx context.Context) (actionError error) {
572557
// Download files to temporary location
573-
downloadError := fms.downloadUpdatedFilesToTempLocation(ctx, fms.tempConfigDir)
558+
downloadError := fms.downloadUpdatedFilesToTempLocation(ctx)
574559
if downloadError != nil {
575560
return downloadError
576561
}
577562

578563
// Remove temp files if there is a failure moving or deleting files
579-
actionError = fms.moveOrDeleteFiles(ctx, fms.tempConfigDir, actionError)
564+
actionError = fms.moveOrDeleteFiles(ctx, actionError)
580565
if actionError != nil {
581-
fms.deleteTempFiles(ctx, fms.tempConfigDir)
566+
fms.deleteTempFiles(ctx)
582567
}
583568

584569
return actionError
585570
}
586571

587-
func (fms *FileManagerService) downloadUpdatedFilesToTempLocation(
588-
ctx context.Context, tempDir string,
589-
) (updateError error) {
572+
func (fms *FileManagerService) downloadUpdatedFilesToTempLocation(ctx context.Context) (updateError error) {
590573
for _, fileAction := range fms.fileActions {
591574
if fileAction.Action == model.Add || fileAction.Action == model.Update {
592-
tempFilePath := filepath.Join(tempDir, fileAction.File.GetFileMeta().GetName())
575+
tempFilePath := tempFilePath(fileAction.File.GetFileMeta().GetName())
593576

594577
slog.DebugContext(
595578
ctx,
@@ -608,7 +591,7 @@ func (fms *FileManagerService) downloadUpdatedFilesToTempLocation(
608591
return updateError
609592
}
610593

611-
func (fms *FileManagerService) moveOrDeleteFiles(ctx context.Context, tempDir string, actionError error) error {
594+
func (fms *FileManagerService) moveOrDeleteFiles(ctx context.Context, actionError error) error {
612595
actionsLoop:
613596
for _, fileAction := range fms.fileActions {
614597
switch fileAction.Action {
@@ -624,7 +607,8 @@ actionsLoop:
624607
continue
625608
case model.Add, model.Update:
626609
fileMeta := fileAction.File.GetFileMeta()
627-
err := fms.fileServiceOperator.RenameFile(ctx, fileMeta.GetHash(), fileMeta.GetName(), tempDir)
610+
tempFilePath := tempFilePath(fileAction.File.GetFileMeta().GetName())
611+
err := fms.fileServiceOperator.RenameFile(ctx, fileMeta.GetHash(), tempFilePath, fileMeta.GetName())
628612
if err != nil {
629613
actionError = err
630614

@@ -638,11 +622,11 @@ actionsLoop:
638622
return actionError
639623
}
640624

641-
func (fms *FileManagerService) deleteTempFiles(ctx context.Context, tempDir string) {
625+
func (fms *FileManagerService) deleteTempFiles(ctx context.Context) {
642626
for _, fileAction := range fms.fileActions {
643627
if fileAction.Action == model.Add || fileAction.Action == model.Update {
644-
tempFile := path.Join(tempDir, fileAction.File.GetFileMeta().GetName())
645-
if err := os.Remove(tempFile); err != nil && !os.IsNotExist(err) {
628+
tempFilePath := tempFilePath(fileAction.File.GetFileMeta().GetName())
629+
if err := os.Remove(tempFilePath); err != nil && !os.IsNotExist(err) {
646630
slog.ErrorContext(
647631
ctx, "Error deleting temp file",
648632
"file", fileAction.File.GetFileMeta().GetName(),
@@ -767,21 +751,6 @@ func (fms *FileManagerService) convertToFile(manifestFile *model.ManifestFile) *
767751
}
768752
}
769753

770-
func (fms *FileManagerService) createTempConfigDirectory(pattern string) (string, error) {
771-
if _, err := os.Stat(fms.tempConfigPath); os.IsNotExist(err) {
772-
mkdirErr := os.MkdirAll(fms.tempConfigPath, dirPerm)
773-
if mkdirErr != nil {
774-
return "", mkdirErr
775-
}
776-
}
777-
tempDir, tempDirError := os.MkdirTemp(fms.tempConfigPath, pattern)
778-
if tempDirError != nil {
779-
return "", fmt.Errorf("failed creating temp config directory: %w", tempDirError)
780-
}
781-
782-
return tempDir, nil
783-
}
784-
785754
// ConvertToMapOfFiles converts a list of files to a map of file caches (file and action) with the file name as the key
786755
func ConvertToMapOfFileCache(convertFiles []*mpi.File) map[string]*model.FileCache {
787756
filesMap := make(map[string]*model.FileCache)
@@ -793,3 +762,13 @@ func ConvertToMapOfFileCache(convertFiles []*mpi.File) map[string]*model.FileCac
793762

794763
return filesMap
795764
}
765+
766+
func tempFilePath(fileName string) string {
767+
tempFileName := "." + filepath.Base(fileName) + ".agent.tmp"
768+
return filepath.Join(filepath.Dir(fileName), tempFileName)
769+
}
770+
771+
func tempBackupFilePath(fileName string) string {
772+
tempFileName := "." + filepath.Base(fileName) + ".agent.backup"
773+
return filepath.Join(filepath.Dir(fileName), tempFileName)
774+
}

0 commit comments

Comments
 (0)