From 738c064e893492320b829fc35736e7486c1dc92d Mon Sep 17 00:00:00 2001 From: Aphral Griffin Date: Wed, 20 Aug 2025 15:43:30 +0100 Subject: [PATCH 1/2] add config path to overview --- api/grpc/mpi/v1/files.pb.go | 15 +++++++++++++-- api/grpc/mpi/v1/files.pb.validate.go | 2 ++ api/grpc/mpi/v1/files.proto | 2 ++ docs/proto/protos.md | 1 + internal/datasource/config/nginx_config_parser.go | 4 +++- internal/datasource/nginx/process.go | 9 +++++++-- internal/file/file_manager_service.go | 5 +++-- internal/file/file_service_operator.go | 7 +++++-- internal/file/file_service_operator_test.go | 4 ++-- internal/model/config.go | 4 ++++ internal/resource/nginx_instance_operator_test.go | 6 ++++++ 11 files changed, 48 insertions(+), 11 deletions(-) diff --git a/api/grpc/mpi/v1/files.pb.go b/api/grpc/mpi/v1/files.pb.go index c68585426..327799de0 100644 --- a/api/grpc/mpi/v1/files.pb.go +++ b/api/grpc/mpi/v1/files.pb.go @@ -625,6 +625,8 @@ type FileOverview struct { Files []*File `protobuf:"bytes,1,rep,name=files,proto3" json:"files,omitempty"` // The configuration version of the current set of files ConfigVersion *ConfigVersion `protobuf:"bytes,2,opt,name=config_version,json=configVersion,proto3" json:"config_version,omitempty"` + // The config file path of an instance + ConfigPath string `protobuf:"bytes,3,opt,name=config_path,json=configPath,proto3" json:"config_path,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -673,6 +675,13 @@ func (x *FileOverview) GetConfigVersion() *ConfigVersion { return nil } +func (x *FileOverview) GetConfigPath() string { + if x != nil { + return x.ConfigPath + } + return "" +} + // Represents meta data about a file type File struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -1535,10 +1544,12 @@ const file_mpi_v1_files_proto_rawDesc = "" + "\rConfigVersion\x12)\n" + "\vinstance_id\x18\x01 \x01(\tB\b\xbaH\x05r\x03\xb0\x01\x01R\n" + "instanceId\x12\x18\n" + - "\aversion\x18\x02 \x01(\tR\aversion\"p\n" + + "\aversion\x18\x02 \x01(\tR\aversion\"\x91\x01\n" + "\fFileOverview\x12\"\n" + "\x05files\x18\x01 \x03(\v2\f.mpi.v1.FileR\x05files\x12<\n" + - "\x0econfig_version\x18\x02 \x01(\v2\x15.mpi.v1.ConfigVersionR\rconfigVersion\"S\n" + + "\x0econfig_version\x18\x02 \x01(\v2\x15.mpi.v1.ConfigVersionR\rconfigVersion\x12\x1f\n" + + "\vconfig_path\x18\x03 \x01(\tR\n" + + "configPath\"S\n" + "\x04File\x12-\n" + "\tfile_meta\x18\x01 \x01(\v2\x10.mpi.v1.FileMetaR\bfileMeta\x12\x1c\n" + "\tunmanaged\x18\x02 \x01(\bR\tunmanaged\"w\n" + diff --git a/api/grpc/mpi/v1/files.pb.validate.go b/api/grpc/mpi/v1/files.pb.validate.go index dfcafca1a..a54f2b32b 100644 --- a/api/grpc/mpi/v1/files.pb.validate.go +++ b/api/grpc/mpi/v1/files.pb.validate.go @@ -1263,6 +1263,8 @@ func (m *FileOverview) validate(all bool) error { } } + // no validation rules for ConfigPath + if len(errors) > 0 { return FileOverviewMultiError(errors) } diff --git a/api/grpc/mpi/v1/files.proto b/api/grpc/mpi/v1/files.proto index 0be5bcd69..8af9a60bf 100644 --- a/api/grpc/mpi/v1/files.proto +++ b/api/grpc/mpi/v1/files.proto @@ -120,6 +120,8 @@ message FileOverview { repeated File files = 1; // The configuration version of the current set of files ConfigVersion config_version = 2; + // The config file path of an instance + string config_path = 3; } // Represents meta data about a file diff --git a/docs/proto/protos.md b/docs/proto/protos.md index 40bdb1828..874107b5b 100644 --- a/docs/proto/protos.md +++ b/docs/proto/protos.md @@ -416,6 +416,7 @@ Represents a collection of files | ----- | ---- | ----- | ----------- | | files | [File](#mpi-v1-File) | repeated | A list of files | | config_version | [ConfigVersion](#mpi-v1-ConfigVersion) | | The configuration version of the current set of files | +| config_path | [string](#string) | | The config file path of an instance | diff --git a/internal/datasource/config/nginx_config_parser.go b/internal/datasource/config/nginx_config_parser.go index 1cb034f15..15871af10 100644 --- a/internal/datasource/config/nginx_config_parser.go +++ b/internal/datasource/config/nginx_config_parser.go @@ -99,7 +99,7 @@ func (ncp *NginxConfigParser) Parse(ctx context.Context, instance *mpi.Instance) return nil, err } - return ncp.createNginxConfigContext(ctx, instance, payload) + return ncp.createNginxConfigContext(ctx, instance, payload, configPath) } //nolint:gocognit,gocyclo,revive,cyclop // cognitive complexity is 51 @@ -107,12 +107,14 @@ func (ncp *NginxConfigParser) createNginxConfigContext( ctx context.Context, instance *mpi.Instance, payload *crossplane.Payload, + configPath string, ) (*model.NginxConfigContext, error) { napSyslogServersFound := make(map[string]bool) napEnabled := false nginxConfigContext := &model.NginxConfigContext{ InstanceID: instance.GetInstanceMeta().GetInstanceId(), + ConfigPath: configPath, PlusAPI: &model.APIDetails{ URL: "", Listen: "", diff --git a/internal/datasource/nginx/process.go b/internal/datasource/nginx/process.go index 8a9f5b109..fe8913d1d 100644 --- a/internal/datasource/nginx/process.go +++ b/internal/datasource/nginx/process.go @@ -10,6 +10,7 @@ import ( "bytes" "context" "fmt" + "log/slog" "regexp" "strings" @@ -39,14 +40,18 @@ func ProcessInfo(ctx context.Context, proc *nginxprocess.Process, confPath := ConfPathFromCommand(proc.Cmd) - var nginxInfo *model.ProcessInfo + nginxInfo := &model.ProcessInfo{} outputBuffer, err := executer.RunCmd(ctx, exePath, "-V") if err != nil { return nil, err } - nginxInfo = ParseNginxVersionCommandOutput(ctx, outputBuffer) + if outputBuffer == nil { + slog.WarnContext(ctx, "Unable to get NGINX version output") + } else { + nginxInfo = ParseNginxVersionCommandOutput(ctx, outputBuffer) + } nginxInfo.ExePath = exePath nginxInfo.ProcessID = proc.PID diff --git a/internal/file/file_manager_service.go b/internal/file/file_manager_service.go index 0b83fafae..e3d258a9b 100644 --- a/internal/file/file_manager_service.go +++ b/internal/file/file_manager_service.go @@ -58,7 +58,7 @@ type ( fileServiceOperatorInterface interface { File(ctx context.Context, file *mpi.File, fileActions map[string]*model.FileCache) error - UpdateOverview(ctx context.Context, instanceID string, filesToUpdate []*mpi.File, iteration int) error + UpdateOverview(ctx context.Context, instanceID string, filesToUpdate []*mpi.File, configPath string, iteration int) error ChunkedFile(ctx context.Context, file *mpi.File) error IsConnected() bool UpdateFile( @@ -233,7 +233,8 @@ func (fms *FileManagerService) ConfigUpdate(ctx context.Context, } slog.InfoContext(ctx, "Updating overview after nginx config update") - err := fms.fileServiceOperator.UpdateOverview(ctx, nginxConfigContext.InstanceID, nginxConfigContext.Files, 0) + err := fms.fileServiceOperator.UpdateOverview(ctx, nginxConfigContext.InstanceID, + nginxConfigContext.Files, nginxConfigContext.ConfigPath, 0) if err != nil { slog.ErrorContext( ctx, diff --git a/internal/file/file_service_operator.go b/internal/file/file_service_operator.go index a37951b29..92931c430 100644 --- a/internal/file/file_service_operator.go +++ b/internal/file/file_service_operator.go @@ -104,6 +104,7 @@ func (fso *FileServiceOperator) UpdateOverview( ctx context.Context, instanceID string, filesToUpdate []*mpi.File, + configPath string, iteration int, ) error { correlationID := logger.CorrelationID(ctx) @@ -127,6 +128,7 @@ func (fso *FileServiceOperator) UpdateOverview( InstanceId: instanceID, Version: files.GenerateConfigVersion(filesToUpdate), }, + ConfigPath: configPath, }, } @@ -178,7 +180,7 @@ func (fso *FileServiceOperator) UpdateOverview( delta := files.ConvertToMapOfFiles(response.GetOverview().GetFiles()) if len(delta) != 0 { - return fso.updateFiles(ctx, delta, instanceID, iteration) + return fso.updateFiles(ctx, delta, instanceID, configPath, iteration) } return err @@ -254,6 +256,7 @@ func (fso *FileServiceOperator) updateFiles( ctx context.Context, delta map[string]*mpi.File, instanceID string, + configPath string, iteration int, ) error { diffFiles := slices.Collect(maps.Values(delta)) @@ -268,7 +271,7 @@ func (fso *FileServiceOperator) updateFiles( iteration++ slog.InfoContext(ctx, "Updating file overview after file updates", "attempt_number", iteration) - return fso.UpdateOverview(ctx, instanceID, diffFiles, iteration) + return fso.UpdateOverview(ctx, instanceID, diffFiles, configPath, iteration) } func (fso *FileServiceOperator) sendUpdateFileRequest( diff --git a/internal/file/file_service_operator_test.go b/internal/file/file_service_operator_test.go index c2f9bf22a..ba092a9f9 100644 --- a/internal/file/file_service_operator_test.go +++ b/internal/file/file_service_operator_test.go @@ -53,7 +53,7 @@ func TestFileServiceOperator_UpdateOverview(t *testing.T) { { FileMeta: fileMeta, }, - }, 0) + }, filePath, 0) require.NoError(t, err) assert.Equal(t, 2, fakeFileServiceClient.UpdateOverviewCallCount()) @@ -91,7 +91,7 @@ func TestFileServiceOperator_UpdateOverview_MaxIterations(t *testing.T) { { FileMeta: fileMeta, }, - }, 0) + }, filePath, 0) require.Error(t, err) assert.Equal(t, "too many UpdateOverview attempts", err.Error()) diff --git a/internal/model/config.go b/internal/model/config.go index 88b083e65..ba9b3760d 100644 --- a/internal/model/config.go +++ b/internal/model/config.go @@ -20,6 +20,7 @@ type NginxConfigContext struct { ErrorLogs []*ErrorLog NAPSysLogServers []string Includes []string + ConfigPath string } type APIDetails struct { @@ -97,6 +98,9 @@ func (ncc *NginxConfigContext) Equal(otherNginxConfigContext *NginxConfigContext } } + if ncc.ConfigPath != otherNginxConfigContext.ConfigPath { + return false + } if ncc.InstanceID != otherNginxConfigContext.InstanceID { return false } diff --git a/internal/resource/nginx_instance_operator_test.go b/internal/resource/nginx_instance_operator_test.go index 1f5a39f58..a5d1f3c78 100644 --- a/internal/resource/nginx_instance_operator_test.go +++ b/internal/resource/nginx_instance_operator_test.go @@ -160,8 +160,14 @@ func TestInstanceOperator_Reload(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { + versionOut := `nginx version: nginx/1.25.3 + built by clang 14.0.0 (clang-1400.0.29.202) + built with OpenSSL 1.1.1s 1 Nov 2022 (running with OpenSSL 1.1.1t 7 Feb 2023) + TLS SNI support enabled + configure arguments: ` + ossConfigArgs mockExec := &execfakes.FakeExecInterface{} mockExec.KillProcessReturns(test.err) + mockExec.RunCmdReturns(bytes.NewBufferString(versionOut), nil) instance := protos.NginxOssInstance([]string{}) From 9133143add77e54df5ec615fee26a2468475bdee Mon Sep 17 00:00:00 2001 From: Aphral Griffin Date: Wed, 20 Aug 2025 15:57:54 +0100 Subject: [PATCH 2/2] add config path to overview --- internal/file/file_manager_service.go | 3 ++- internal/model/config.go | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/internal/file/file_manager_service.go b/internal/file/file_manager_service.go index e3d258a9b..869284492 100644 --- a/internal/file/file_manager_service.go +++ b/internal/file/file_manager_service.go @@ -58,7 +58,8 @@ type ( fileServiceOperatorInterface interface { File(ctx context.Context, file *mpi.File, fileActions map[string]*model.FileCache) error - UpdateOverview(ctx context.Context, instanceID string, filesToUpdate []*mpi.File, configPath string, iteration int) error + UpdateOverview(ctx context.Context, instanceID string, filesToUpdate []*mpi.File, configPath string, + iteration int) error ChunkedFile(ctx context.Context, file *mpi.File) error IsConnected() bool UpdateFile( diff --git a/internal/model/config.go b/internal/model/config.go index ba9b3760d..0e605a7a0 100644 --- a/internal/model/config.go +++ b/internal/model/config.go @@ -15,12 +15,12 @@ type NginxConfigContext struct { StubStatus *APIDetails PlusAPI *APIDetails InstanceID string + ConfigPath string Files []*v1.File AccessLogs []*AccessLog ErrorLogs []*ErrorLog NAPSysLogServers []string Includes []string - ConfigPath string } type APIDetails struct {