Skip to content

Commit f035a05

Browse files
committed
fix test and race
1 parent 04c5512 commit f035a05

File tree

9 files changed

+49
-27
lines changed

9 files changed

+49
-27
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ official-image-integration-test: $(SELECTED_PACKAGE) build-mock-management-plane
167167
TEST_ENV="Container" CONTAINER_OS_TYPE=$(CONTAINER_OS_TYPE) CONTAINER_NGINX_IMAGE_REGISTRY=${CONTAINER_NGINX_IMAGE_REGISTRY} BUILD_TARGET="install" \
168168
PACKAGES_REPO=$(OSS_PACKAGES_REPO) TAG=${TAG} PACKAGE_NAME=$(PACKAGE_NAME) BASE_IMAGE=$(BASE_IMAGE) DOCKERFILE_PATH=$(OFFICIAL_IMAGE_DOCKERFILE_PATH) \
169169
OS_VERSION=$(OS_VERSION) OS_RELEASE=$(OS_RELEASE) IMAGE_PATH=$(IMAGE_PATH) \
170-
go test -v ./test/integration/managementplane ./test/integration/managementplane
170+
go test -v ./test/integration/managementplane ./test/integration/auxiliarycommandserver
171171

172172
performance-test:
173173
@mkdir -p $(TEST_BUILD_DIR)

internal/file/file_manager_service.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,18 +100,20 @@ type FileManagerService struct {
100100
previousManifestFiles map[string]*model.ManifestFile
101101
manifestFilePath string
102102
filesMutex sync.RWMutex
103+
manifestLock *sync.RWMutex
103104
}
104105

105-
func NewFileManagerService(fileServiceClient mpi.FileServiceClient, agentConfig *config.Config) *FileManagerService {
106+
func NewFileManagerService(fileServiceClient mpi.FileServiceClient, agentConfig *config.Config, manifestLock *sync.RWMutex) *FileManagerService {
106107
return &FileManagerService{
107108
agentConfig: agentConfig,
108-
fileOperator: NewFileOperator(),
109-
fileServiceOperator: NewFileServiceOperator(agentConfig, fileServiceClient),
109+
fileOperator: NewFileOperator(manifestLock),
110+
fileServiceOperator: NewFileServiceOperator(agentConfig, fileServiceClient, manifestLock),
110111
fileActions: make(map[string]*model.FileCache),
111112
rollbackFileContents: make(map[string][]byte),
112113
currentFilesOnDisk: make(map[string]*mpi.File),
113114
previousManifestFiles: make(map[string]*model.ManifestFile),
114115
manifestFilePath: agentConfig.ManifestDir + "/manifest.json",
116+
manifestLock: manifestLock,
115117
}
116118
}
117119

@@ -423,9 +425,12 @@ func (fms *FileManagerService) UpdateCurrentFilesOnDisk(
423425
// seems to be a control flag, avoid control coupling
424426
// nolint: revive
425427
func (fms *FileManagerService) UpdateManifestFile(currentFiles map[string]*mpi.File, referenced bool) (err error) {
428+
slog.Debug("Updating manifest file", "current_files", currentFiles, "referenced", referenced)
426429
currentManifestFiles, _, readError := fms.manifestFile()
427430
fms.previousManifestFiles = currentManifestFiles
428431
if readError != nil && !errors.Is(readError, os.ErrNotExist) {
432+
slog.Debug("Error reading manifest file", "current_manifest_files",
433+
currentManifestFiles, "updated_files", currentFiles, "referenced", referenced)
429434
return fmt.Errorf("unable to read manifest file: %w", readError)
430435
}
431436

@@ -457,6 +462,8 @@ func (fms *FileManagerService) manifestFile() (map[string]*model.ManifestFile, m
457462
return nil, nil, err
458463
}
459464

465+
fms.manifestLock.Lock()
466+
defer fms.manifestLock.Unlock()
460467
file, err := os.ReadFile(fms.manifestFilePath)
461468
if err != nil {
462469
return nil, nil, fmt.Errorf("failed to read manifest file: %w", err)
@@ -466,6 +473,9 @@ func (fms *FileManagerService) manifestFile() (map[string]*model.ManifestFile, m
466473

467474
err = json.Unmarshal(file, &manifestFiles)
468475
if err != nil {
476+
if len(file) == 0 {
477+
return nil, nil, fmt.Errorf("manifest file is empty: %w", err)
478+
}
469479
return nil, nil, fmt.Errorf("failed to parse manifest file: %w", err)
470480
}
471481

internal/file/file_operator.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"log/slog"
1515
"os"
1616
"path"
17+
"sync"
1718

1819
"github.com/nginx/agent/v3/internal/model"
1920

@@ -24,14 +25,18 @@ import (
2425
mpi "github.com/nginx/agent/v3/api/grpc/mpi/v1"
2526
)
2627

27-
type FileOperator struct{}
28+
type FileOperator struct {
29+
manifestLock *sync.RWMutex
30+
}
2831

2932
var _ fileOperator = (*FileOperator)(nil)
3033

3134
// FileOperator only purpose is to write files,
3235

33-
func NewFileOperator() *FileOperator {
34-
return &FileOperator{}
36+
func NewFileOperator(manifestLock *sync.RWMutex) *FileOperator {
37+
return &FileOperator{
38+
manifestLock: manifestLock,
39+
}
3540
}
3641

3742
func (fo *FileOperator) Write(ctx context.Context, fileContent []byte, file *mpi.FileMeta) error {
@@ -152,6 +157,8 @@ func (fo *FileOperator) WriteManifestFile(updatedFiles map[string]*model.Manifes
152157
return fmt.Errorf("unable to marshal manifest file json: %w", err)
153158
}
154159

160+
fo.manifestLock.Lock()
161+
defer fo.manifestLock.Unlock()
155162
// 0755 allows read/execute for all, write for owner
156163
if err = os.MkdirAll(manifestDir, dirPerm); err != nil {
157164
return fmt.Errorf("unable to create directory %s: %w", manifestDir, err)

internal/file/file_plugin.go

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ package file
88
import (
99
"context"
1010
"log/slog"
11+
"sync"
1112

1213
"github.com/nginx/agent/v3/pkg/files"
1314
"github.com/nginx/agent/v3/pkg/id"
@@ -32,15 +33,17 @@ type FilePlugin struct {
3233
conn grpc.GrpcConnectionInterface
3334
fileManagerService fileManagerServiceInterface
3435
serverType model.ServerType
36+
manifestLock *sync.RWMutex
3537
}
3638

3739
func NewFilePlugin(agentConfig *config.Config, grpcConnection grpc.GrpcConnectionInterface,
38-
serverType model.ServerType,
40+
serverType model.ServerType, manifestLock *sync.RWMutex,
3941
) *FilePlugin {
4042
return &FilePlugin{
41-
config: agentConfig,
42-
conn: grpcConnection,
43-
serverType: serverType,
43+
config: agentConfig,
44+
conn: grpcConnection,
45+
serverType: serverType,
46+
manifestLock: manifestLock,
4447
}
4548
}
4649

@@ -52,7 +55,7 @@ func (fp *FilePlugin) Init(ctx context.Context, messagePipe bus.MessagePipeInter
5255
slog.DebugContext(ctx, "Starting file plugin")
5356

5457
fp.messagePipe = messagePipe
55-
fp.fileManagerService = NewFileManagerService(fp.conn.FileServiceClient(), fp.config)
58+
fp.fileManagerService = NewFileManagerService(fp.conn.FileServiceClient(), fp.config, fp.manifestLock)
5659

5760
return nil
5861
}
@@ -145,7 +148,7 @@ func (fp *FilePlugin) handleConnectionReset(ctx context.Context, msg *bus.Messag
145148
fp.conn = newConnection
146149

147150
reconnect = fp.fileManagerService.IsConnected()
148-
fp.fileManagerService = NewFileManagerService(fp.conn.FileServiceClient(), fp.config)
151+
fp.fileManagerService = NewFileManagerService(fp.conn.FileServiceClient(), fp.config, fp.manifestLock)
149152
fp.fileManagerService.SetIsConnected(reconnect)
150153

151154
slog.DebugContext(ctx, "File manager service client reset successfully")

internal/file/file_service_operator.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"math"
1616
"os"
1717
"slices"
18+
"sync"
1819
"sync/atomic"
1920

2021
"github.com/cenkalti/backoff/v4"
@@ -41,14 +42,14 @@ type FileServiceOperator struct {
4142

4243
var _ fileServiceOperatorInterface = (*FileServiceOperator)(nil)
4344

44-
func NewFileServiceOperator(agentConfig *config.Config, fileServiceClient mpi.FileServiceClient) *FileServiceOperator {
45+
func NewFileServiceOperator(agentConfig *config.Config, fileServiceClient mpi.FileServiceClient, manifestLock *sync.RWMutex) *FileServiceOperator {
4546
isConnected := &atomic.Bool{}
4647
isConnected.Store(false)
4748

4849
return &FileServiceOperator{
4950
fileServiceClient: fileServiceClient,
5051
agentConfig: agentConfig,
51-
fileOperator: NewFileOperator(),
52+
fileOperator: NewFileOperator(manifestLock),
5253
isConnected: isConnected,
5354
}
5455
}

internal/plugin/plugin_manager.go

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ package plugin
88
import (
99
"context"
1010
"log/slog"
11+
"sync"
1112

1213
"github.com/nginx/agent/v3/internal/model"
1314

@@ -27,9 +28,11 @@ import (
2728
func LoadPlugins(ctx context.Context, agentConfig *config.Config) []bus.Plugin {
2829
plugins := make([]bus.Plugin, 0)
2930

31+
manifestLock := &sync.RWMutex{}
32+
3033
plugins = addResourcePlugin(plugins, agentConfig)
31-
plugins = addCommandAndFilePlugins(ctx, plugins, agentConfig)
32-
plugins = addAuxiliaryCommandAndFilePlugins(ctx, plugins, agentConfig)
34+
plugins = addCommandAndFilePlugins(ctx, plugins, agentConfig, manifestLock)
35+
plugins = addAuxiliaryCommandAndFilePlugins(ctx, plugins, agentConfig, manifestLock)
3336
plugins = addCollectorPlugin(ctx, agentConfig, plugins)
3437
plugins = addWatcherPlugin(plugins, agentConfig)
3538

@@ -43,15 +46,15 @@ func addResourcePlugin(plugins []bus.Plugin, agentConfig *config.Config) []bus.P
4346
return plugins
4447
}
4548

46-
func addCommandAndFilePlugins(ctx context.Context, plugins []bus.Plugin, agentConfig *config.Config) []bus.Plugin {
49+
func addCommandAndFilePlugins(ctx context.Context, plugins []bus.Plugin, agentConfig *config.Config, manifestLock *sync.RWMutex) []bus.Plugin {
4750
if agentConfig.IsCommandGrpcClientConfigured() {
4851
grpcConnection, err := grpc.NewGrpcConnection(ctx, agentConfig, agentConfig.Command)
4952
if err != nil {
5053
slog.WarnContext(ctx, "Failed to create gRPC connection for command server", "error", err)
5154
} else {
5255
commandPlugin := command.NewCommandPlugin(agentConfig, grpcConnection, model.Command)
5356
plugins = append(plugins, commandPlugin)
54-
filePlugin := file.NewFilePlugin(agentConfig, grpcConnection, model.Command)
57+
filePlugin := file.NewFilePlugin(agentConfig, grpcConnection, model.Command, manifestLock)
5558
plugins = append(plugins, filePlugin)
5659
}
5760
} else {
@@ -63,7 +66,7 @@ func addCommandAndFilePlugins(ctx context.Context, plugins []bus.Plugin, agentCo
6366
}
6467

6568
func addAuxiliaryCommandAndFilePlugins(ctx context.Context, plugins []bus.Plugin,
66-
agentConfig *config.Config,
69+
agentConfig *config.Config, manifestLock *sync.RWMutex,
6770
) []bus.Plugin {
6871
if agentConfig.IsAuxiliaryCommandGrpcClientConfigured() {
6972
auxGRPCConnection, err := grpc.NewGrpcConnection(ctx, agentConfig, agentConfig.AuxiliaryCommand)
@@ -72,7 +75,7 @@ func addAuxiliaryCommandAndFilePlugins(ctx context.Context, plugins []bus.Plugin
7275
} else {
7376
auxCommandPlugin := command.NewCommandPlugin(agentConfig, auxGRPCConnection, model.Auxiliary)
7477
plugins = append(plugins, auxCommandPlugin)
75-
readFilePlugin := file.NewFilePlugin(agentConfig, auxGRPCConnection, model.Auxiliary)
78+
readFilePlugin := file.NewFilePlugin(agentConfig, auxGRPCConnection, model.Auxiliary, manifestLock)
7679
plugins = append(plugins, readFilePlugin)
7780
}
7881
} else {

internal/watcher/file/file_watcher_service.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ func (fws *FileWatcherService) checkForUpdates(ctx context.Context, ch chan<- Fi
195195
// Check if directories no longer need to be watched
196196
fws.removeWatchers(ctx)
197197

198-
if fws.filesChanged.Load() {
198+
if fws.filesChanged.Load() && fws.enabled.Load() {
199199
newCtx := context.WithValue(
200200
ctx,
201201
logger.CorrelationIDContextKey,

test/helpers/test_containers_utils.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,8 @@ func LogAndTerminateContainers(
319319
require.NoError(tb, err)
320320
logs := string(buf)
321321

322+
assert.NotContains(tb, logs, "manifest file is empty",
323+
"Error reading manifest file found in agent log")
322324
tb.Log(logs)
323325
if expectNoErrorsInLogs {
324326
assert.NotContains(tb, logs, "level=ERROR", "agent log file contains logs at error level")

test/integration/auxiliarycommandserver/connection_test.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ package auxiliarycommandserver
88
import (
99
"context"
1010
"fmt"
11+
"github.com/go-resty/resty/v2"
1112
"net"
1213
"net/http"
1314
"os"
1415
"sort"
1516
"testing"
1617
"time"
1718

18-
"github.com/go-resty/resty/v2"
1919
mpi "github.com/nginx/agent/v3/api/grpc/mpi/v1"
2020
"github.com/nginx/agent/v3/test/integration/utils"
2121
"github.com/stretchr/testify/suite"
@@ -187,10 +187,6 @@ func (s *AuxiliaryTestSuite) TestAuxiliary_Test5_ConfigApply() {
187187
}
188188

189189
func (s *AuxiliaryTestSuite) TestAuxiliary_Test6_ConfigApplyInvalid() {
190-
// Perform config apply with aux
191-
// Check new config is broken
192-
// Check using hash with new API endpoint which was added to get the file overview
193-
194190
utils.ClearManagementPlaneResponses(s.T(), utils.MockManagementPlaneAPIAddress)
195191
utils.ClearManagementPlaneResponses(s.T(), utils.AuxiliaryMockManagementPlaneAPIAddress)
196192

0 commit comments

Comments
 (0)