Skip to content

Commit 1ef117b

Browse files
authored
Merge branch 'main' into K8SPSMDB-1413
2 parents ef175f9 + ca05f46 commit 1ef117b

File tree

252 files changed

+2575
-280
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

252 files changed

+2575
-280
lines changed

.e2eignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,4 @@ operator.png
99
kubernetes.svg
1010
release_versions
1111
.github/**
12-
.snyk
1312
.e2eignore

.github/workflows/scan.yml

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -30,27 +30,10 @@ jobs:
3030
export DOCKER_DEFAULT_PLATFORM='linux/arm64'
3131
./e2e-tests/build
3232
33-
- name: Run Snyk vulnerability scanner image (linux/arm64)
34-
uses: snyk/actions/docker@master
35-
env:
36-
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
37-
with:
38-
image: '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}-arm64'
39-
args: --platform=linux/arm64 --severity-threshold=high --exclude-base-image-vulns --file=./build/Dockerfile -fail-on=upgradable
40-
4133
- name: Build an image from Dockerfile (linux/amd64)
4234
run: |
4335
export IMAGE=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}-amd64
4436
export DOCKER_PUSH=0
4537
export DOCKER_SQUASH=0
4638
export DOCKER_DEFAULT_PLATFORM='linux/amd64'
4739
./e2e-tests/build
48-
49-
- name: Run Snyk vulnerability scanner image (linux/amd64)
50-
uses: snyk/actions/docker@master
51-
env:
52-
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
53-
with:
54-
image: '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}-amd64'
55-
args: --platform=linux/amd64 --severity-threshold=high --exclude-base-image-vulns --file=./build/Dockerfile -fail-on=upgradable
56-

.snyk

Lines changed: 0 additions & 9 deletions
This file was deleted.

build/logcollector/entrypoint.sh

Lines changed: 90 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,100 @@
1-
#!/bin/sh
1+
#!/bin/bash
22
set -e
3-
set -o xtrace
43

5-
export PATH="$PATH":/opt/fluent-bit/bin
4+
export PATH="$PATH:/opt/fluent-bit/bin"
65

7-
if [ "$1" = 'logrotate' ]; then
6+
LOGROTATE_SCHEDULE="${LOGROTATE_SCHEDULE:-0 0 * * *}"
7+
8+
is_logrotate_config_invalid() {
9+
local config_file="$1"
10+
if [ -z "$config_file" ] || [ ! -f "$config_file" ]; then
11+
return 1
12+
fi
13+
# Specifying -d runs in debug mode, so even in case of errors, it will exit with 0.
14+
# We need to check the output for "error" but skip those lines that are related to the missing logrotate.status file.
15+
# Filter out logrotate.status lines first, then check for remaining errors
16+
(
17+
set +e
18+
logrotate -d "$config_file" 2>&1 | grep -v "logrotate.status" | grep -qi "error"
19+
)
20+
return $?
21+
}
22+
23+
run_logrotate() {
24+
local logrotate_status_file="/data/db/logs/logrotate.status"
25+
local logrotate_conf_file="/opt/percona/logcollector/logrotate/logrotate.conf"
26+
local logrotate_additional_conf_files=()
27+
local conf_d_dir="/opt/percona/logcollector/logrotate/conf.d"
28+
29+
# Check if mongodb.conf exists and validate it
30+
if [ -f "$conf_d_dir/mongodb.conf" ]; then
31+
logrotate_conf_file="$conf_d_dir/mongodb.conf"
32+
if is_logrotate_config_invalid "$logrotate_conf_file"; then
33+
echo "ERROR: Logrotate configuration is invalid, fallback to default configuration"
34+
logrotate_conf_file="/opt/percona/logcollector/logrotate/logrotate.conf"
35+
fi
36+
fi
37+
38+
# Process all .conf files in conf.d directory (excluding mongodb.conf which is already handled)
39+
if [ -d "$conf_d_dir" ]; then
40+
for conf_file in "$conf_d_dir"/*.conf; do
41+
# Check if glob matched any files (if no .conf files exist, the glob returns itself)
42+
[ -f "$conf_file" ] || continue
43+
# Skip mongodb.conf as it's already processed above
44+
[ "$(basename "$conf_file")" = "mongodb.conf" ] && continue
45+
if is_logrotate_config_invalid "$conf_file"; then
46+
echo "ERROR: Logrotate configuration file $conf_file is invalid, it will be ignored"
47+
else
48+
logrotate_additional_conf_files+=("$conf_file")
49+
fi
50+
done
51+
fi
52+
# Ensure logrotate can run with current UID
853
if [[ $EUID != 1001 ]]; then
954
# logrotate requires UID in /etc/passwd
1055
sed -e "s^x:1001:^x:$EUID:^" /etc/passwd >/tmp/passwd
1156
cat /tmp/passwd >/etc/passwd
1257
rm -rf /tmp/passwd
1358
fi
14-
exec go-cron "0 0 * * *" sh -c "logrotate -s /data/db/logs/logrotate.status /opt/percona/logcollector/logrotate/logrotate.conf;"
15-
else
16-
if [ "$1" = 'fluent-bit' ]; then
17-
fluentbit_opt+='-c /opt/percona/logcollector/fluentbit/fluentbit.conf'
18-
fi
1959

20-
exec "$@" $fluentbit_opt
21-
fi
60+
local logrotate_cmd="logrotate -s \"$logrotate_status_file\" \"$logrotate_conf_file\""
61+
for additional_conf in "${logrotate_additional_conf_files[@]}"; do
62+
logrotate_cmd="$logrotate_cmd \"$additional_conf\""
63+
done
64+
65+
set -o xtrace
66+
exec go-cron "$LOGROTATE_SCHEDULE" sh -c "$logrotate_cmd"
67+
}
68+
69+
run_fluentbit() {
70+
local fluentbit_opt=(-c /opt/percona/logcollector/fluentbit/fluentbit.conf)
71+
mkdir -p /tmp/fluentbit/custom
72+
set +e
73+
local fluentbit_conf_dir="/opt/percona/logcollector/fluentbit/custom"
74+
for conf_file in $fluentbit_conf_dir/*.conf; do
75+
[ -f "$conf_file" ] || continue
76+
if ! fluent-bit --dry-run -c "$conf_file" >/dev/null 2>&1; then
77+
echo "ERROR: Fluentbit configuration file $conf_file is invalid, it will be ignored"
78+
else
79+
cp "$conf_file" /tmp/fluentbit/custom/
80+
fi
81+
done
82+
touch /tmp/fluentbit/custom/default.conf || true
83+
84+
set -e
85+
set -o xtrace
86+
exec "$@" "${fluentbit_opt[@]}"
87+
}
88+
89+
case "$1" in
90+
logrotate)
91+
run_logrotate
92+
;;
93+
fluent-bit)
94+
run_fluentbit "$@"
95+
;;
96+
*)
97+
echo "Invalid argument: $1"
98+
exit 1
99+
;;
100+
esac
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
@INCLUDE fluentbit_*.conf
2-
@INCLUDE custom/*.conf
2+
@INCLUDE /tmp/fluentbit/custom/*.conf

cmd/mongodb-healthcheck/db/db.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,25 +29,27 @@ var (
2929
)
3030

3131
func Dial(ctx context.Context, conf *Config) (mongo.Client, error) {
32-
if err := conf.configureTLS(); err != nil {
32+
log := logf.FromContext(ctx).WithName("Dial")
33+
ctx = logf.IntoContext(ctx, log)
34+
35+
if err := conf.configureTLS(ctx); err != nil {
3336
return nil, errors.Wrap(err, "configure TLS")
3437
}
3538

36-
log := logf.FromContext(ctx)
3739
log.V(1).Info("Connecting to mongodb", "hosts", conf.Hosts, "ssl", conf.SSL.Enabled, "ssl_insecure", conf.SSL.Insecure)
3840

3941
if conf.Username != "" && conf.Password != "" {
4042
log.V(1).Info("Enabling authentication for session", "user", conf.Username)
4143
}
4244

43-
cl, err := mongo.Dial(&conf.Config)
45+
cl, err := mongo.Dial(ctx, &conf.Config)
4446
if err != nil {
4547
cfg := conf.Config
4648
cfg.Direct = true
4749
cfg.ReplSetName = ""
48-
cl, err = mongo.Dial(&cfg)
50+
cl, err = mongo.Dial(ctx, &cfg)
4951
if err != nil {
50-
return nil, errors.Wrap(err, "filed to dial mongo")
52+
return nil, errors.Wrap(err, "failed to dial mongo")
5153
}
5254
}
5355

cmd/mongodb-healthcheck/db/ssl.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
package db
1616

1717
import (
18+
"context"
1819
"crypto/tls"
1920
"crypto/x509"
2021
"os"
@@ -40,8 +41,8 @@ func (sc *SSLConfig) loadCaCertificate() (*x509.CertPool, error) {
4041
return certificates, nil
4142
}
4243

43-
func (cnf *Config) configureTLS() error {
44-
log := logf.Log
44+
func (cnf *Config) configureTLS(ctx context.Context) error {
45+
log := logf.FromContext(ctx).WithName("configureTLS")
4546

4647
if !cnf.SSL.Enabled {
4748
return nil
@@ -72,7 +73,7 @@ func (cnf *Config) configureTLS() error {
7273
return errors.Wrapf(err, "check if file with name %s exists", cnf.SSL.CAFile)
7374
}
7475

75-
log.V(1).Info("Loading SSL/TLS Certificate Authority: %s", "ca", cnf.SSL.CAFile)
76+
log.V(1).Info("Loading SSL/TLS Certificate Authority", "ca", cnf.SSL.CAFile)
7677
ca, err := cnf.SSL.loadCaCertificate()
7778
if err != nil {
7879
return errors.Wrapf(err, "load client CAs from %s", cnf.SSL.CAFile)

cmd/mongodb-healthcheck/db/ssl_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ func TestSSLNotEnabled(t *testing.T) {
1616
},
1717
}
1818

19-
if err := cfg.configureTLS(); err != nil {
19+
if err := cfg.configureTLS(t.Context()); err != nil {
2020
t.Fatalf("TLS configuration failed: %s", err)
2121
}
2222

@@ -32,7 +32,7 @@ func TestSSLEnabled(t *testing.T) {
3232
},
3333
}
3434

35-
if err := cfg.configureTLS(); err != nil {
35+
if err := cfg.configureTLS(t.Context()); err != nil {
3636
t.Fatalf("TLS configuration failed: %s", err)
3737
}
3838

@@ -49,7 +49,7 @@ func TestPEMKeyFileDoesNotExists(t *testing.T) {
4949
},
5050
}
5151

52-
err := cfg.configureTLS()
52+
err := cfg.configureTLS(t.Context())
5353
if err == nil {
5454
t.Fatal("Expected TLS config to fail, but it returned no error")
5555
}
@@ -71,7 +71,7 @@ func TestCAFileDoesNotExists(t *testing.T) {
7171
},
7272
}
7373

74-
err := cfg.configureTLS()
74+
err := cfg.configureTLS(t.Context())
7575
if err == nil {
7676
t.Fatal("Expected TLS config to fail, but it returned no error")
7777
}

cmd/mongodb-healthcheck/healthcheck/health.go

Lines changed: 12 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,9 @@ package healthcheck
1616

1717
import (
1818
"context"
19-
"encoding/json"
2019

21-
v "github.com/hashicorp/go-version"
2220
"github.com/pkg/errors"
2321
"go.mongodb.org/mongo-driver/bson"
24-
"go.mongodb.org/mongo-driver/bson/primitive"
2522
logf "sigs.k8s.io/controller-runtime/pkg/log"
2623

2724
"github.com/percona/percona-server-mongodb-operator/cmd/mongodb-healthcheck/db"
@@ -32,6 +29,7 @@ var ErrNoReplsetConfigStr = "(NotYetInitialized) no replset config has been rece
3229

3330
func HealthCheckMongosLiveness(ctx context.Context, cnf *db.Config) (err error) {
3431
log := logf.FromContext(ctx).WithName("HealthCheckMongosLiveness")
32+
ctx = logf.IntoContext(ctx, log)
3533

3634
client, err := db.Dial(ctx, cnf)
3735
if err != nil {
@@ -58,6 +56,7 @@ func HealthCheckMongosLiveness(ctx context.Context, cnf *db.Config) (err error)
5856

5957
func HealthCheckMongodLiveness(ctx context.Context, cnf *db.Config, startupDelaySeconds int64) (_ *mongo.MemberState, err error) {
6058
log := logf.FromContext(ctx).WithName("HealthCheckMongodLiveness")
59+
ctx = logf.IntoContext(ctx, log)
6160

6261
client, err := db.Dial(ctx, cnf)
6362
if err != nil {
@@ -74,50 +73,14 @@ func HealthCheckMongodLiveness(ctx context.Context, cnf *db.Config, startupDelay
7473
return nil, errors.Wrap(err, "get isMaster response")
7574
}
7675

77-
buildInfo, err := client.RSBuildInfo(ctx)
76+
rsStatus, err := client.RSStatus(ctx)
7877
if err != nil {
79-
return nil, errors.Wrap(err, "get buildInfo response")
80-
}
81-
82-
replSetStatusCommand := bson.D{{Key: "replSetGetStatus", Value: 1}}
83-
mongoVersion := v.Must(v.NewVersion(buildInfo.Version))
84-
if mongoVersion.Compare(v.Must(v.NewVersion("4.2.1"))) < 0 {
85-
// https://docs.mongodb.com/manual/reference/command/replSetGetStatus/#syntax
86-
replSetStatusCommand = append(replSetStatusCommand, primitive.E{Key: "initialSync", Value: 1})
87-
}
88-
89-
res := client.Database("admin").RunCommand(ctx, replSetStatusCommand)
90-
if res.Err() != nil {
91-
// if we come this far, it means db connection was successful
92-
// standalone mongod nodes in an unmanaged cluster doesn't need
93-
// to die before they added to a replset
94-
if res.Err().Error() == ErrNoReplsetConfigStr {
78+
if err.Error() == ErrNoReplsetConfigStr {
9579
state := mongo.MemberStateUnknown
96-
log.V(1).Info("replSetGetStatus failed", "err", res.Err().Error(), "state", state)
80+
log.V(1).Info("replSetGetStatus failed", "err", err.Error(), "state", state)
9781
return &state, nil
9882
}
99-
return nil, errors.Wrap(res.Err(), "get replsetGetStatus response")
100-
}
101-
102-
// this is a workaround to fix decoding of empty interfaces
103-
// https://jira.mongodb.org/browse/GODRIVER-988
104-
rsStatus := ReplSetStatus{}
105-
tempResult := bson.M{}
106-
err = res.Decode(&tempResult)
107-
if err != nil {
108-
return nil, errors.Wrap(err, "decode replsetGetStatus response")
109-
}
110-
111-
if err == nil {
112-
result, err := json.Marshal(tempResult)
113-
if err != nil {
114-
return nil, errors.Wrap(err, "marshal temp result")
115-
}
116-
117-
err = json.Unmarshal(result, &rsStatus)
118-
if err != nil {
119-
return nil, errors.Wrap(err, "unmarshal temp result")
120-
}
83+
return nil, errors.Wrap(err, "get replSetGetStatus response")
12184
}
12285

12386
oplogRs := OplogRs{}
@@ -156,15 +119,12 @@ type OplogRs struct {
156119
StorageSize int64 `bson:"storageSize" json:"storageSize"`
157120
}
158121

159-
type ReplSetStatus struct {
160-
InitialSyncStatus InitialSyncStatus `bson:"initialSyncStatus" json:"initialSyncStatus"`
161-
mongo.Status `bson:",inline"`
162-
}
163-
164-
type InitialSyncStatus interface{}
165-
166-
func CheckState(rs ReplSetStatus, startupDelaySeconds int64, oplogSize int64) error {
167-
uptime := rs.GetSelf().Uptime
122+
func CheckState(rs mongo.Status, startupDelaySeconds int64, oplogSize int64) error {
123+
self := rs.GetSelf()
124+
if self == nil {
125+
return errors.New("self member is not found")
126+
}
127+
uptime := self.Uptime
168128

169129
switch rs.MyState {
170130
case mongo.MemberStatePrimary, mongo.MemberStateSecondary, mongo.MemberStateArbiter:

0 commit comments

Comments
 (0)