Skip to content

Test/add runtime manager tests #2175

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 28 commits into from
Aug 29, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
65f6bd3
add tests for runtime manager
miledxz Jul 7, 2024
b98942e
adding required tests update
miledxz Jul 7, 2024
266fdc0
resolving conflicts
miledxz Jul 7, 2024
676548c
adding resolving conflicts
miledxz Jul 7, 2024
88f656f
adding additional updates with Reload fnction tests
miledxz Feb 26, 2024
93157b9
adding required updates
miledxz Mar 12, 2024
df5ccbe
adding fixes
miledxz May 6, 2024
3dc727a
adding processHandler struct update
miledxz May 20, 2024
a0c0228
adding cleanup fix update
miledxz May 20, 2024
596efd3
adding gofumpt fix update
miledxz May 20, 2024
54e1efe
adding additional fix updates
miledxz May 20, 2024
39cc3d7
adding tests for runtime manager
miledxz Jun 27, 2024
7f6d1bf
resolving partionally comments in pr
miledxz Jun 29, 2024
9777319
Merge branch 'nginxinc:main' into test/add-runtime-manager-tests
miledxz Jul 7, 2024
0ecf5d1
adding first part of resolving final comments
miledxz Jul 7, 2024
ecc39c5
experimental commit for NewProcessHandlerImpl
miledxz Jul 7, 2024
948b9be
Merge branch 'nginxinc:main' into test/add-runtime-manager-tests
miledxz Jul 13, 2024
f146435
updating test desc
miledxz Jul 13, 2024
b7884d0
adding required updates regarding readFile
miledxz Jul 13, 2024
04f6e30
adding additional experimental ReadFile update
miledxz Jul 13, 2024
6963fd4
adding general fix for manager
miledxz Jul 14, 2024
547e903
adding small fix update
miledxz Aug 10, 2024
27fed56
adding manager fix update
miledxz Aug 20, 2024
8b94a05
quick upstream test update
miledxz Aug 20, 2024
eda39b2
Merge branch 'main' into test/add-runtime-manager-tests
kate-osborn Aug 20, 2024
7be17ee
experimental fix
miledxz Aug 21, 2024
1a56441
adding lint fix update
miledxz Aug 29, 2024
8913e20
Merge branch 'main' into test/add-runtime-manager-tests
sjberman Aug 29, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
adding additional updates with Reload fnction tests
  • Loading branch information
miledxz committed Jul 7, 2024
commit 88f656f5b7d66a6bce5ad10901c8da403aae2c11
2 changes: 2 additions & 0 deletions internal/mode/static/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,8 @@ func StartManager(cfg config.Config) error {
ngxPlusClient,
ngxruntimeCollector,
cfg.Logger.WithName("nginxRuntimeManager"),
nil,
nil,
),
statusUpdater: groupStatusUpdater,
eventRecorder: recorder,
Expand Down
70 changes: 51 additions & 19 deletions internal/mode/static/nginx/runtime/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,33 @@ import (
//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate

const (
pidFile = "/var/run/nginx/nginx.pid"
PidFile = "/var/run/nginx/nginx.pid"
pidFileTimeout = 10000 * time.Millisecond
nginxReloadTimeout = 60000 * time.Millisecond
)

type (
readFileFunc func(string) ([]byte, error)
checkFileFunc func(string) (fs.FileInfo, error)
ReadFileFunc func(string) ([]byte, error)
CheckFileFunc func(string) (fs.FileInfo, error)
)

var childProcPathFmt = "/proc/%[1]v/task/%[1]v/children"

//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . NginxPlusClient
//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . nginxPlusClient

type NginxPlusClient interface {
type nginxPlusClient interface {
UpdateHTTPServers(upstream string, servers []ngxclient.UpstreamServer) (added []ngxclient.UpstreamServer, deleted []ngxclient.UpstreamServer, updated []ngxclient.UpstreamServer, err error)
GetUpstreams() (*ngxclient.Upstreams, error)
}

//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . processHandler

type processHandler interface {
FindMainProcess(ctx context.Context, checkFile CheckFileFunc, readFile ReadFileFunc, timeout time.Duration) (int, error)
ReadFile(file string) ([]byte, error)
SysCallKill(pid int, signum syscall.Signal) error
}

//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . Manager

// Manager manages the runtime of NGINX.
Expand All @@ -54,6 +62,8 @@ type Manager interface {
GetUpstreams() (ngxclient.Upstreams, error)
}

//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . MetricsCollector

// MetricsCollector is an interface for the metrics of the NGINX runtime manager.
type MetricsCollector interface {
IncReloadCount()
Expand All @@ -63,23 +73,27 @@ type MetricsCollector interface {

// ManagerImpl implements Manager.
type ManagerImpl struct {
verifyClient *verifyClient
verifyClient verifyClient
metricsCollector MetricsCollector
ngxPlusClient NginxPlusClient
ngxPlusClient nginxPlusClient
logger logr.Logger
process processHandler
}

// NewManagerImpl creates a new ManagerImpl.
func NewManagerImpl(
ngxPlusClient NginxPlusClient,
ngxPlusClient nginxPlusClient,
collector MetricsCollector,
logger logr.Logger,
process processHandler,
verifyClient verifyClient,
) *ManagerImpl {
return &ManagerImpl{
verifyClient: newVerifyClient(nginxReloadTimeout),
verifyClient: verifyClient,
metricsCollector: collector,
ngxPlusClient: ngxPlusClient,
logger: logger,
process: process,
}
}

Expand All @@ -91,25 +105,25 @@ func (m *ManagerImpl) IsPlus() bool {
func (m *ManagerImpl) Reload(ctx context.Context, configVersion int) error {
start := time.Now()
// We find the main NGINX PID on every reload because it will change if the NGINX container is restarted.
pid, err := findMainProcess(ctx, os.Stat, os.ReadFile, pidFileTimeout)
pid, err := m.process.FindMainProcess(ctx, os.Stat, os.ReadFile, pidFileTimeout)
if err != nil {
return fmt.Errorf("failed to find NGINX main process: %w", err)
}

childProcFile := fmt.Sprintf(childProcPathFmt, pid)
previousChildProcesses, err := os.ReadFile(childProcFile)
previousChildProcesses, err := m.process.ReadFile(childProcFile)
if err != nil {
return err
}

// send HUP signal to the NGINX main process reload configuration
// See https://nginx.org/en/docs/control.html
if err := syscall.Kill(pid, syscall.SIGHUP); err != nil {
if err := m.process.SysCallKill(pid, syscall.SIGHUP); err != nil {
m.metricsCollector.IncReloadErrors()
return fmt.Errorf("failed to send the HUP signal to NGINX main: %w", err)
}

if err = m.verifyClient.waitForCorrectVersion(
if err = m.verifyClient.WaitForCorrectVersion(
ctx,
configVersion,
childProcFile,
Expand Down Expand Up @@ -162,16 +176,16 @@ func (m *ManagerImpl) GetUpstreams() (ngxclient.Upstreams, error) {

// EnsureNginxRunning ensures NGINX is running by locating the main process.
func EnsureNginxRunning(ctx context.Context) error {
if _, err := findMainProcess(ctx, os.Stat, os.ReadFile, pidFileTimeout); err != nil {
if _, err := FindMainProcess(ctx, os.Stat, os.ReadFile, pidFileTimeout); err != nil {
return fmt.Errorf("failed to find NGINX main process: %w", err)
}
return nil
}

func findMainProcess(
func FindMainProcess(
ctx context.Context,
checkFile checkFileFunc,
readFile readFileFunc,
checkFile CheckFileFunc,
readFile ReadFileFunc,
timeout time.Duration,
) (int, error) {
ctx, cancel := context.WithTimeout(ctx, timeout)
Expand All @@ -182,7 +196,7 @@ func findMainProcess(
500*time.Millisecond,
true, /* poll immediately */
func(_ context.Context) (bool, error) {
_, err := checkFile(pidFile)
_, err := checkFile(PidFile)
if err == nil {
return true, nil
}
Expand All @@ -195,7 +209,7 @@ func findMainProcess(
return 0, err
}

content, err := readFile(pidFile)
content, err := readFile(PidFile)
if err != nil {
return 0, err
}
Expand All @@ -207,3 +221,21 @@ func findMainProcess(

return pid, nil
}

func ReadFile(file string) ([]byte, error) {
content, err := os.ReadFile(file)
if err != nil {
return nil, err
}

return content, nil
}

func SysCallKill(pid int, signum syscall.Signal) error {
err := syscall.Kill(pid, syscall.SIGHUP)
if err != nil {
return err
}

return nil
}
Loading