Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
e29e544
add LogRotate spec to PSMDB CR
mayankshah1607 Dec 17, 2025
cfd50e0
implement logrotate config override
mayankshah1607 Dec 17, 2025
8f2e658
fix field name
mayankshah1607 Dec 17, 2025
135050b
update comment
mayankshah1607 Dec 17, 2025
2e8b590
allow configuring schedule
mayankshah1607 Dec 18, 2025
8f54b3f
fix naming
mayankshah1607 Dec 18, 2025
5e69d7c
revert logrotate.conf
mayankshah1607 Dec 18, 2025
da7af91
fixes
mayankshah1607 Dec 20, 2025
31d2284
use volume projections
mayankshah1607 Dec 22, 2025
7c32278
refactoring
mayankshah1607 Dec 22, 2025
ee251c6
update comment
mayankshah1607 Dec 22, 2025
ea21154
Merge branch 'main' into K8SPSMDB-1518
mayankshah1607 Dec 22, 2025
979fa25
add unit test
mayankshah1607 Dec 22, 2025
a5ad117
Update pkg/psmdb/logcollector/logrotate/container.go
mayankshah1607 Dec 23, 2025
6b1ab34
some improvements
mayankshah1607 Dec 23, 2025
49dd962
use bash shell
mayankshah1607 Dec 23, 2025
f11ccc3
fix shellcheck
mayankshah1607 Dec 23, 2025
39a6382
add comment
mayankshah1607 Dec 23, 2025
e38f489
fix test
mayankshah1607 Dec 23, 2025
7c0b50a
Update pkg/psmdb/logcollector/logrotate/container.go
mayankshah1607 Dec 23, 2025
55667d0
Update pkg/psmdb/logcollector/logrotate/container.go
mayankshah1607 Dec 23, 2025
e0b3f58
use array
mayankshah1607 Dec 23, 2025
37812f2
Merge branch 'main' into K8SPSMDB-1518
mayankshah1607 Dec 24, 2025
a906613
Merge branch 'main' into K8SPSMDB-1518
mayankshah1607 Dec 29, 2025
afa8920
update cr.yaml
mayankshah1607 Dec 30, 2025
99b7367
fix test fixtures
mayankshah1607 Dec 30, 2025
35a08ff
Merge branch 'main' into K8SPSMDB-1518
mayankshah1607 Dec 30, 2025
7eab046
validate configuration
mayankshah1607 Dec 31, 2025
c499c0f
add validation to script
mayankshah1607 Dec 31, 2025
b618502
Merge branch 'main' into K8SPSMDB-1518
mayankshah1607 Jan 2, 2026
8743537
Update build/logcollector/entrypoint.sh
mayankshah1607 Jan 2, 2026
778d792
Update build/logcollector/entrypoint.sh
mayankshah1607 Jan 2, 2026
d055c34
Update build/logcollector/entrypoint.sh
mayankshah1607 Jan 2, 2026
cb75d75
Update deploy/cr.yaml
mayankshah1607 Jan 2, 2026
e87af6e
improve script to not hardcode custom.conf
mayankshah1607 Jan 2, 2026
08df282
Update build/logcollector/entrypoint.sh
mayankshah1607 Jan 2, 2026
87c835c
dry-run fluentbit configurations
mayankshah1607 Jan 2, 2026
3073a01
Update build/logcollector/entrypoint.sh
mayankshah1607 Jan 2, 2026
580f1c9
Update build/logcollector/entrypoint.sh
mayankshah1607 Jan 2, 2026
c6e3a52
Update build/logcollector/entrypoint.sh
mayankshah1607 Jan 2, 2026
950ecfd
use ERROR message prefix
mayankshah1607 Jan 5, 2026
692f432
add unit test
mayankshah1607 Jan 5, 2026
c78dbf0
add logrotate container test
mayankshah1607 Jan 5, 2026
70255f4
use k8s.io/utils/ptr
mayankshah1607 Jan 5, 2026
f269653
Update pkg/controller/perconaservermongodb/psmdb_controller.go
mayankshah1607 Jan 5, 2026
6775fcd
remove extra whitespace
mayankshah1607 Jan 5, 2026
dfe4966
add unit test
mayankshah1607 Jan 5, 2026
e985718
fix error handling
mayankshah1607 Jan 5, 2026
f9b073b
Merge branch 'main' into K8SPSMDB-1518
mayankshah1607 Jan 5, 2026
b93307a
Merge branch 'main' into K8SPSMDB-1518
hors Jan 7, 2026
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
101 changes: 90 additions & 11 deletions build/logcollector/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -1,21 +1,100 @@
#!/bin/sh
#!/bin/bash
set -e
set -o xtrace

export PATH="$PATH":/opt/fluent-bit/bin
export PATH="$PATH:/opt/fluent-bit/bin"

if [ "$1" = 'logrotate' ]; then
LOGROTATE_SCHEDULE="${LOGROTATE_SCHEDULE:-0 0 * * *}"

is_logrotate_config_invalid() {
local config_file="$1"
if [ -z "$config_file" ] || [ ! -f "$config_file" ]; then
return 1
fi
# Specifying -d runs in debug mode, so even in case of errors, it will exit with 0.
# We need to check the output for "error" but skip those lines that are related to the missing logrotate.status file.
# Filter out logrotate.status lines first, then check for remaining errors
(
set +e
logrotate -d "$config_file" 2>&1 | grep -v "logrotate.status" | grep -qi "error"
)
return $?
}
Comment on lines +8 to +21
Copy link

Copilot AI Jan 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The is_logrotate_config_invalid function returns 1 (true/failure) when the config file doesn't exist or is empty, but then checks for the word "error" in the output. The logic is confusing because:

  1. If the file doesn't exist, it returns 1 (invalid)
  2. If the file exists, it runs logrotate -d and checks for "error" in output
  3. The grep command returns 0 if "error" is found, which means the config IS invalid

However, the return value logic is correct. Consider adding a comment to clarify that this function returns 0 (success in shell) when config is valid, and 1 (failure) when invalid, which might be counterintuitive given the function name starts with "is_".

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot open a new pull request to apply changes based on this feedback


run_logrotate() {
local logrotate_status_file="/data/db/logs/logrotate.status"
local logrotate_conf_file="/opt/percona/logcollector/logrotate/logrotate.conf"
local logrotate_additional_conf_files=()
local conf_d_dir="/opt/percona/logcollector/logrotate/conf.d"

# Check if mongodb.conf exists and validate it
if [ -f "$conf_d_dir/mongodb.conf" ]; then
logrotate_conf_file="$conf_d_dir/mongodb.conf"
if is_logrotate_config_invalid "$logrotate_conf_file"; then
echo "ERROR: Logrotate configuration is invalid, fallback to default configuration"
logrotate_conf_file="/opt/percona/logcollector/logrotate/logrotate.conf"
fi
fi

# Process all .conf files in conf.d directory (excluding mongodb.conf which is already handled)
if [ -d "$conf_d_dir" ]; then
for conf_file in "$conf_d_dir"/*.conf; do
# Check if glob matched any files (if no .conf files exist, the glob returns itself)
[ -f "$conf_file" ] || continue
# Skip mongodb.conf as it's already processed above
[ "$(basename "$conf_file")" = "mongodb.conf" ] && continue
if is_logrotate_config_invalid "$conf_file"; then
echo "ERROR: Logrotate configuration file $conf_file is invalid, it will be ignored"
else
logrotate_additional_conf_files+=("$conf_file")
fi
done
fi
# Ensure logrotate can run with current UID
if [[ $EUID != 1001 ]]; then
# logrotate requires UID in /etc/passwd
sed -e "s^x:1001:^x:$EUID:^" /etc/passwd >/tmp/passwd
cat /tmp/passwd >/etc/passwd
rm -rf /tmp/passwd
fi
exec go-cron "0 0 * * *" sh -c "logrotate -s /data/db/logs/logrotate.status /opt/percona/logcollector/logrotate/logrotate.conf;"
else
if [ "$1" = 'fluent-bit' ]; then
fluentbit_opt+='-c /opt/percona/logcollector/fluentbit/fluentbit.conf'
fi

exec "$@" $fluentbit_opt
fi
local logrotate_cmd="logrotate -s \"$logrotate_status_file\" \"$logrotate_conf_file\""
for additional_conf in "${logrotate_additional_conf_files[@]}"; do
logrotate_cmd="$logrotate_cmd \"$additional_conf\""
done

set -o xtrace
exec go-cron "$LOGROTATE_SCHEDULE" sh -c "$logrotate_cmd"
}

run_fluentbit() {
local fluentbit_opt=(-c /opt/percona/logcollector/fluentbit/fluentbit.conf)
mkdir -p /tmp/fluentbit/custom
set +e
local fluentbit_conf_dir="/opt/percona/logcollector/fluentbit/custom"
for conf_file in $fluentbit_conf_dir/*.conf; do

Check notice on line 74 in build/logcollector/entrypoint.sh

View workflow job for this annotation

GitHub Actions / shellcheck

[shellcheck] build/logcollector/entrypoint.sh#L74 <ShellCheck.SC2231>

Quote expansions in this for loop glob to prevent wordsplitting, e.g. "$dir"/*.txt .
Raw output
./build/logcollector/entrypoint.sh:74:19: info: Quote expansions in this for loop glob to prevent wordsplitting, e.g. "$dir"/*.txt . (ShellCheck.SC2231)
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The loop variable conf_file is not quoted. If the glob pattern doesn't match any files or if filenames contain spaces, this could cause issues. The variable should be quoted: for conf_file in "$fluentbit_conf_dir"/*.conf; do

Suggested change
for conf_file in $fluentbit_conf_dir/*.conf; do
for conf_file in "$fluentbit_conf_dir"/*.conf; do

Copilot uses AI. Check for mistakes.
[ -f "$conf_file" ] || continue
if ! fluent-bit --dry-run -c "$conf_file" >/dev/null 2>&1; then
echo "ERROR: Fluentbit configuration file $conf_file is invalid, it will be ignored"
else
cp "$conf_file" /tmp/fluentbit/custom/
fi
done
touch /tmp/fluentbit/custom/default.conf || true

set -e
set -o xtrace
exec "$@" "${fluentbit_opt[@]}"
}

case "$1" in
logrotate)
run_logrotate
;;
fluent-bit)
run_fluentbit "$@"
;;
*)
echo "Invalid argument: $1"
exit 1
;;
esac
2 changes: 1 addition & 1 deletion build/logcollector/fluentbit/fluentbit.conf
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
@INCLUDE fluentbit_*.conf
Copy link

Copilot AI Jan 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change from "custom/.conf" to "/tmp/fluentbit/custom/.conf" is a breaking change to the fluentbit configuration path. The entrypoint.sh script now copies valid configuration files from "/opt/percona/logcollector/fluentbit/custom" to "/tmp/fluentbit/custom/" for validation purposes. This change should be clearly documented as it affects how custom fluentbit configurations work. Users who mount configurations at the old path may need to adjust their setup, although this appears to be handled by the validation logic in the entrypoint script.

Suggested change
@INCLUDE fluentbit_*.conf
@INCLUDE fluentbit_*.conf
# Custom configuration includes
# NOTE:
# - `/tmp/fluentbit/custom/*.conf` is populated by entrypoint.sh, which validates
# configs from `/opt/percona/logcollector/fluentbit/custom` before copying them.
# - `custom/*.conf` is kept for backward compatibility with older setups that
# mounted configs directly into the image path.
# Prefer mounting into `/opt/percona/logcollector/fluentbit/custom` so that
# validation and copying to `/tmp/fluentbit/custom/` work as intended.
@INCLUDE custom/*.conf

Copilot uses AI. Check for mistakes.
@INCLUDE custom/*.conf
@INCLUDE /tmp/fluentbit/custom/*.conf
15 changes: 15 additions & 0 deletions config/crd/bases/psmdb.percona.com_perconaservermongodbs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -806,6 +806,21 @@ spec:
type: string
imagePullPolicy:
type: string
logrotate:
properties:
configuration:
type: string
extraConfig:
properties:
name:
default: ""
type: string
type: object
x-kubernetes-map-type: atomic
schedule:
default: 0 0 * * *
type: string
type: object
resources:
properties:
claims:
Expand Down
15 changes: 15 additions & 0 deletions deploy/bundle.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1665,6 +1665,21 @@ spec:
type: string
imagePullPolicy:
type: string
logrotate:
properties:
configuration:
type: string
extraConfig:
properties:
name:
default: ""
type: string
type: object
x-kubernetes-map-type: atomic
schedule:
default: 0 0 * * *
type: string
type: object
resources:
properties:
claims:
Expand Down
5 changes: 5 additions & 0 deletions deploy/cr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -884,3 +884,8 @@ spec:
requests:
memory: 100M
cpu: 200m
# logrotate:
# configuration: ""
# extraConfig:
# name: logrotate-config
# schedule: "0 0 * * *"
15 changes: 15 additions & 0 deletions deploy/crd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1665,6 +1665,21 @@ spec:
type: string
imagePullPolicy:
type: string
logrotate:
properties:
configuration:
type: string
extraConfig:
properties:
name:
default: ""
type: string
type: object
x-kubernetes-map-type: atomic
schedule:
default: 0 0 * * *
type: string
type: object
resources:
properties:
claims:
Expand Down
15 changes: 15 additions & 0 deletions deploy/cw-bundle.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1665,6 +1665,21 @@ spec:
type: string
imagePullPolicy:
type: string
logrotate:
properties:
configuration:
type: string
extraConfig:
properties:
name:
default: ""
type: string
type: object
x-kubernetes-map-type: atomic
schedule:
default: 0 0 * * *
type: string
type: object
resources:
properties:
claims:
Expand Down
15 changes: 15 additions & 0 deletions e2e-tests/version-service/conf/crd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1665,6 +1665,21 @@ spec:
type: string
imagePullPolicy:
type: string
logrotate:
properties:
configuration:
type: string
extraConfig:
properties:
name:
default: ""
type: string
type: object
x-kubernetes-map-type: atomic
schedule:
default: 0 0 * * *
type: string
type: object
resources:
properties:
claims:
Expand Down
17 changes: 17 additions & 0 deletions pkg/apis/psmdb/v1/psmdb_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -1579,6 +1579,23 @@ type LogCollectorSpec struct {
ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"`
Env []corev1.EnvVar `json:"env,omitempty"`
EnvFrom []corev1.EnvFromSource `json:"envFrom,omitempty"`
LogRotate *LogRotateSpec `json:"logrotate,omitempty"`
}

// LogRotateSpec defines the configuration for the logrotate container.
type LogRotateSpec struct {
// Configuration allows overriding the default logrotate configuration.
Configuration string `json:"configuration,omitempty"`
// ExtraConfig allows specifying logrotate configuration file in addition to the main configuration file.
// This should be a reference to a ConfigMap or a Secret in the same namespace.
// Key must contain the .conf extension to be processed correctly.
//
// NOTE: mongodb.conf is reserved for the default configuration specified by .configuration field.
ExtraConfig corev1.LocalObjectReference `json:"extraConfig,omitempty"`
// Schedule allows specifying the schedule for logrotate.
// This should be a valid cron expression.
//+kubebuilder:default:="0 0 * * *"
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Schedule field lacks validation for cron expression format. Invalid cron expressions will be passed directly to go-cron, which may cause runtime errors. Consider adding validation (e.g., using a kubebuilder validation marker like +kubebuilder:validation:Pattern) or documenting that invalid schedules will result in container failures.

Suggested change
//+kubebuilder:default:="0 0 * * *"
//+kubebuilder:default:="0 0 * * *"
//+kubebuilder:validation:Pattern=`^(\S+\s+){4}\S+$`

Copilot uses AI. Check for mistakes.
Schedule string `json:"schedule,omitempty"`
}

func (cr *PerconaServerMongoDB) IsLogCollectorEnabled() bool {
Expand Down
21 changes: 21 additions & 0 deletions pkg/apis/psmdb/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

41 changes: 41 additions & 0 deletions pkg/controller/perconaservermongodb/psmdb_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import (
"github.com/percona/percona-server-mongodb-operator/pkg/psmdb/backup"
psmdbconfig "github.com/percona/percona-server-mongodb-operator/pkg/psmdb/config"
"github.com/percona/percona-server-mongodb-operator/pkg/psmdb/logcollector"
"github.com/percona/percona-server-mongodb-operator/pkg/psmdb/logcollector/logrotate"
"github.com/percona/percona-server-mongodb-operator/pkg/psmdb/pmm"
"github.com/percona/percona-server-mongodb-operator/pkg/psmdb/secret"
"github.com/percona/percona-server-mongodb-operator/pkg/psmdb/tls"
Expand Down Expand Up @@ -364,6 +365,12 @@ func (r *ReconcilePerconaServerMongoDB) Reconcile(ctx context.Context, request r
}
}

if cr.CompareVersion("1.22.0") >= 0 {
if err := r.reconcileLogRotateConfigMaps(ctx, cr); err != nil {
return reconcile.Result{}, errors.Wrap(err, "reconcile log rotate config map")
}
}

err = r.reconcileUsers(ctx, cr, repls)
if err != nil {
return reconcile.Result{}, errors.Wrap(err, "failed to reconcile users")
Expand Down Expand Up @@ -1263,6 +1270,40 @@ func (r *ReconcilePerconaServerMongoDB) reconcileLogCollectorConfigMaps(ctx cont
return nil
}

func (r *ReconcilePerconaServerMongoDB) reconcileLogRotateConfigMaps(ctx context.Context, cr *api.PerconaServerMongoDB) error {
if !cr.IsLogCollectorEnabled() {
if err := deleteConfigMapIfExists(ctx, r.client, cr, logrotate.ConfigMapName(cr.Name)); err != nil {
return errors.Wrap(err, "failed to delete log rotate config map when log collector is disabled")
}
return nil
}

if cr.Spec.LogCollector.LogRotate == nil || cr.Spec.LogCollector.LogRotate.Configuration == "" {
if err := deleteConfigMapIfExists(ctx, r.client, cr, logrotate.ConfigMapName(cr.Name)); err != nil {
return errors.Wrap(err, "failed to delete log rotate config map when the configuration is empty")
}
return nil
}

cm := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: logrotate.ConfigMapName(cr.Name),
Namespace: cr.GetNamespace(),
Labels: naming.ClusterLabels(cr),
},
Data: map[string]string{
logrotate.MongodbConfig: cr.Spec.LogCollector.LogRotate.Configuration,
},
}

err := r.createOrUpdateConfigMap(ctx, cr, cm)
if err != nil {
return errors.Wrap(err, "create or update config map")
}

return nil
}

func deleteConfigMapIfExists(ctx context.Context, cl client.Client, cr *api.PerconaServerMongoDB, cmName string) error {
configMap := &corev1.ConfigMap{}

Expand Down
Loading
Loading