Skip to content

Commit 4943042

Browse files
author
Dudi Dolev
committed
Fix: Exporter not initiating connection to mongo when Unauthorized
1 parent 111a29d commit 4943042

11 files changed

+188
-9
lines changed

Dockerfile

+82-7
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,84 @@
1-
FROM alpine AS builder
2-
RUN apk add --no-cache ca-certificates
1+
# #FROM alpine AS builder
2+
# FROM docker.io/bitnami/minideb:bookworm
3+
# #RUN apk add --no-cache ca-certificates
4+
# RUN install_packages ca-certificates curl procps
5+
6+
# RUN apt-get autoremove --purge -y curl && \
7+
# apt-get update && apt-get upgrade -y && \
8+
# apt-get clean && rm -rf /var/lib/apt/lists /var/cache/apt/archives
9+
10+
# #FROM scratch AS final
11+
# USER 1001:1001
12+
# #COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
13+
# COPY ./mongodb_exporter /bin/mongodb_exporter
14+
# #RUN chmod g+rwX /bin/mongodb_exporter
15+
# RUN chmod 777 /bin/mongodb_exporter
16+
17+
# EXPOSE 9216
18+
# ENTRYPOINT ["/mongodb_exporter"]
19+
20+
21+
22+
# Copyright Broadcom, Inc. All Rights Reserved.
23+
# SPDX-License-Identifier: APACHE-2.0
24+
25+
FROM docker.io/bitnami/minideb:bookworm
26+
27+
ARG DOWNLOADS_URL="downloads.bitnami.com/files/stacksmith"
28+
ARG TARGETARCH
29+
30+
LABEL com.vmware.cp.artifact.flavor="sha256:c50c90cfd9d12b445b011e6ad529f1ad3daea45c26d20b00732fae3cd71f6a83" \
31+
org.opencontainers.image.base.name="docker.io/bitnami/minideb:bookworm" \
32+
org.opencontainers.image.created="2025-01-17T03:23:22Z" \
33+
org.opencontainers.image.description="Application packaged by Broadcom, Inc." \
34+
org.opencontainers.image.documentation="https://github.com/bitnami/containers/tree/main/bitnami/mongodb-exporter/README.md" \
35+
org.opencontainers.image.licenses="Apache-2.0" \
36+
org.opencontainers.image.ref.name="0.43.1-debian-12-r2" \
37+
org.opencontainers.image.source="https://github.com/bitnami/containers/tree/main/bitnami/mongodb-exporter" \
38+
org.opencontainers.image.title="mongodb-exporter" \
39+
org.opencontainers.image.vendor="Broadcom, Inc." \
40+
org.opencontainers.image.version="0.43.1"
41+
42+
ENV HOME="/" \
43+
OS_ARCH="${TARGETARCH:-amd64}" \
44+
OS_FLAVOUR="debian-12" \
45+
OS_NAME="linux"
46+
47+
# COPY prebuildfs /
48+
# SHELL ["/bin/bash", "-o", "errexit", "-o", "nounset", "-o", "pipefail", "-c"]
49+
# Install required system packages and dependencies
50+
RUN install_packages ca-certificates curl procps
51+
# RUN mkdir -p /tmp/bitnami/pkg/cache/ ; cd /tmp/bitnami/pkg/cache/ ; \
52+
# COMPONENTS=( \
53+
# "mongodb-exporter-0.43.1-1-linux-${OS_ARCH}-debian-12" \
54+
# ) ; \
55+
# for COMPONENT in "${COMPONENTS[@]}"; do \
56+
# if [ ! -f "${COMPONENT}.tar.gz" ]; then \
57+
# curl -SsLf "https://${DOWNLOADS_URL}/${COMPONENT}.tar.gz" -O ; \
58+
# curl -SsLf "https://${DOWNLOADS_URL}/${COMPONENT}.tar.gz.sha256" -O ; \
59+
# fi ; \
60+
# sha256sum -c "${COMPONENT}.tar.gz.sha256" ; \
61+
# tar -zxf "${COMPONENT}.tar.gz" -C /opt/bitnami --strip-components=2 --no-same-owner --wildcards '*/files' ; \
62+
# rm -rf "${COMPONENT}".tar.gz{,.sha256} ; \
63+
# done
64+
65+
RUN mkdir -p /opt/bitnami/mongodb-exporter/bin
66+
67+
COPY ./mongodb_exporter /opt/bitnami/mongodb-exporter/bin/mongodb_exporter
68+
69+
RUN apt-get autoremove --purge -y curl && \
70+
apt-get update && apt-get upgrade -y && \
71+
apt-get clean && rm -rf /var/lib/apt/lists /var/cache/apt/archives
72+
RUN chmod g+rwX /opt/bitnami
73+
RUN find / -perm /6000 -type f -exec chmod a-s {} \; || true
74+
RUN ln -sf /opt/bitnami/mongodb-exporter/bin/mongodb_exporter /bin/mongodb_exporter
75+
76+
ENV APP_VERSION="0.43.1" \
77+
BITNAMI_APP_NAME="mongodb-exporter" \
78+
PATH="/opt/bitnami/mongodb-exporter/bin:$PATH"
379

4-
FROM scratch AS final
5-
USER 65535:65535
6-
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
7-
COPY ./mongodb_exporter /
880
EXPOSE 9216
9-
ENTRYPOINT ["/mongodb_exporter"]
81+
82+
WORKDIR /opt/bitnami/mongodb-exporter
83+
USER 1001
84+
ENTRYPOINT [ "mongodb_exporter" ]

Makefile

+5-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ GO_TEST_PATH ?= ./...
55
GO_TEST_EXTRA ?=
66
GO_TEST_COVER_PROFILE ?= cover.out
77
GO_TEST_CODECOV ?=
8+
GOARCH = amd64
9+
CGO_ENABLED = 0
10+
GOOS = linux
811

912
BUILD ?= $(shell date +%FT%T%z)
1013
GOVERSION ?= $(shell go version | cut -d " " -f3)
@@ -68,10 +71,10 @@ env:
6871
@echo $(TEST_ENV) | tr ' ' '\n' >.env
6972

7073
init: ## Install linters.
71-
cd tools && go generate -x -tags=tools
74+
cd tools && GOARCH=amd64 CGO_ENABLED=0 GOOS=linux go generate -x -tags=tools
7275

7376
build: ## Compile using plain go build
74-
go build -ldflags="$(GO_BUILD_LDFLAGS)" -o $(PMM_RELEASE_PATH)/mongodb_exporter
77+
GOARCH=amd64 CGO_ENABLED=0 GOOS=linux go build -ldflags="$(GO_BUILD_LDFLAGS)" -o $(PMM_RELEASE_PATH)/mongodb_exporter
7578

7679
release: ## Build the binaries using goreleaser
7780
docker run --rm --privileged \

exporter/currentop_collector.go

+8
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package exporter
1717

1818
import (
1919
"context"
20+
"os"
2021
"strconv"
2122
"time"
2223

@@ -90,6 +91,13 @@ func (d *currentopCollector) collect(ch chan<- prometheus.Metric) {
9091

9192
var r primitive.M
9293
if err := res.Decode(&r); err != nil {
94+
if e, ok := err.(mongo.CommandError); ok {
95+
if e.Code == Unauthorized {
96+
logger.Errorf("unauthorized to run currtop: %s", err)
97+
os.Exit(1)
98+
}
99+
}
100+
93101
logger.Errorf("Failed to decode currentOp response: %s", err)
94102
ch <- prometheus.NewInvalidMetric(prometheus.NewInvalidDesc(err), err)
95103
return

exporter/dbstats_collector.go

+7
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package exporter
1717

1818
import (
1919
"context"
20+
"os"
2021

2122
"github.com/prometheus/client_golang/prometheus"
2223
"github.com/sirupsen/logrus"
@@ -84,6 +85,12 @@ func (d *dbstatsCollector) collect(ch chan<- prometheus.Metric) {
8485
r := client.Database(db).RunCommand(d.ctx, cmd)
8586
err := r.Decode(&dbStats)
8687
if err != nil {
88+
if e, ok := err.(mongo.CommandError); ok {
89+
if e.Code == Unauthorized {
90+
logger.Errorf("unauthorized to run replSetGetStatus: %s", err)
91+
os.Exit(1)
92+
}
93+
}
8794
logger.Errorf("Failed to get $dbstats for database %s: %s", db, err)
8895

8996
continue

exporter/diagnostic_data_collector.go

+13
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package exporter
1717

1818
import (
1919
"context"
20+
"os"
2021

2122
"github.com/pkg/errors"
2223
"github.com/prometheus/client_golang/prometheus"
@@ -94,6 +95,12 @@ func (d *diagnosticDataCollector) collect(ch chan<- prometheus.Metric) {
9495
}
9596
} else {
9697
if err := res.Decode(&m); err != nil {
98+
if e, ok := err.(mongo.CommandError); ok {
99+
if e.Code == Unauthorized {
100+
logger.Errorf("unauthorized to run getDiagnosticData: %s", err)
101+
os.Exit(1)
102+
}
103+
}
97104
logger.Errorf("cannot run getDiagnosticData: %s", err)
98105
return
99106
}
@@ -163,6 +170,12 @@ func (d *diagnosticDataCollector) getSecurityMetricFromLineOptions(client *mongo
163170
return nil, errors.Wrap(resCmdLineOptions.Err(), "cannot execute getCmdLineOpts command")
164171
}
165172
if err := resCmdLineOptions.Decode(&cmdLineOpionsBson); err != nil {
173+
if e, ok := err.(mongo.CommandError); ok {
174+
if e.Code == Unauthorized {
175+
errors.New("unauthorized to run getCmdLineOpts")
176+
os.Exit(1)
177+
}
178+
}
166179
return nil, errors.Wrap(err, "cannot parse response of the getCmdLineOpts command")
167180
}
168181

exporter/feature_compatibility_version_collector.go

+7
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package exporter
1818
import (
1919
"context"
2020
"fmt"
21+
"os"
2122
"strconv"
2223

2324
"github.com/prometheus/client_golang/prometheus"
@@ -61,6 +62,12 @@ func (d *featureCompatibilityCollector) collect(ch chan<- prometheus.Metric) {
6162
if err := res.Decode(&m); err != nil {
6263
d.base.logger.Errorf("Failed to decode featureCompatibilityVersion: %v", err)
6364
ch <- prometheus.NewInvalidMetric(prometheus.NewInvalidDesc(err), err)
65+
if e, ok := err.(mongo.CommandError); ok {
66+
if e.Code == Unauthorized {
67+
d.base.logger.Errorf("Failed to decode featureCompatibilityVersion: %v", err)
68+
os.Exit(1)
69+
}
70+
}
6471
return
6572
}
6673

exporter/replset_status_collector.go

+6
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package exporter
1717

1818
import (
1919
"context"
20+
"os"
2021

2122
"github.com/prometheus/client_golang/prometheus"
2223
"github.com/sirupsen/logrus"
@@ -27,6 +28,7 @@ import (
2728
const (
2829
replicationNotEnabled = 76
2930
replicationNotYetInitialized = 94
31+
Unauthorized = 13
3032
)
3133

3234
type replSetGetStatusCollector struct {
@@ -72,6 +74,10 @@ func (d *replSetGetStatusCollector) collect(ch chan<- prometheus.Metric) {
7274
if e.Code == replicationNotYetInitialized || e.Code == replicationNotEnabled {
7375
return
7476
}
77+
if e.Code == Unauthorized {
78+
logger.Errorf("unauthorized to run replSetGetStatus: %s", err)
79+
os.Exit(1)
80+
}
7581
}
7682
logger.Errorf("cannot get replSetGetStatus: %s", err)
7783

exporter/top_collector.go

+7
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package exporter
1818
import (
1919
"context"
2020
"fmt"
21+
"os"
2122

2223
"github.com/prometheus/client_golang/prometheus"
2324
"github.com/sirupsen/logrus"
@@ -66,6 +67,12 @@ func (d *topCollector) collect(ch chan<- prometheus.Metric) {
6667

6768
var m primitive.M
6869
if err := res.Decode(&m); err != nil {
70+
if e, ok := err.(mongo.CommandError); ok {
71+
if e.Code == Unauthorized {
72+
logger.Errorf("unauthorized to run top command")
73+
os.Exit(1)
74+
}
75+
}
6976
ch <- prometheus.NewInvalidMetric(prometheus.NewInvalidDesc(err), err)
7077
return
7178
}

exporter/topology_info.go

+13
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package exporter
1818
import (
1919
"context"
2020
"fmt"
21+
"os"
2122
"sync"
2223

2324
"github.com/pkg/errors"
@@ -143,6 +144,12 @@ func getNodeType(ctx context.Context, client *mongo.Client) (mongoDBNodeType, er
143144
}
144145
md := proto.MasterDoc{}
145146
if err := client.Database("admin").RunCommand(ctx, primitive.M{"isMaster": 1}).Decode(&md); err != nil {
147+
if e, ok := err.(mongo.CommandError); ok {
148+
if e.Code == Unauthorized {
149+
errors.New("unauthorized to getisMaster")
150+
os.Exit(1)
151+
}
152+
}
146153
return "", err
147154
}
148155

@@ -171,6 +178,12 @@ func getClusterRole(ctx context.Context, client *mongo.Client) (string, error) {
171178
}
172179

173180
if err := res.Decode(&cmdOpts); err != nil {
181+
if e, ok := err.(mongo.CommandError); ok {
182+
if e.Code == Unauthorized {
183+
errors.New("unauthorized to getCmdLineOpts")
184+
os.Exit(1)
185+
}
186+
}
174187
return "", errors.Wrap(err, "cannot decode getCmdLineOpts response")
175188
}
176189

exporter/v1_compatibility.go

+19
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"context"
2020
"fmt"
2121
"math"
22+
"os"
2223
"strings"
2324
"time"
2425

@@ -835,6 +836,12 @@ func retrieveMongoDBBuildInfo(ctx context.Context, client *mongo.Client, l *logr
835836
var buildInfoDoc bson.M
836837
err := res.Decode(&buildInfoDoc)
837838
if err != nil {
839+
if e, ok := err.(mongo.CommandError); ok {
840+
if e.Code == Unauthorized {
841+
errors.Wrap(err, "unauthorized to run command buildInfo")
842+
os.Exit(1)
843+
}
844+
}
838845
return buildInfo{}, errors.Wrap(err, "Failed to run buildInfo command")
839846
}
840847

@@ -1176,6 +1183,12 @@ func chunksBalancerRunning(ctx context.Context, client *mongo.Client) (prometheu
11761183
res := client.Database("admin").RunCommand(ctx, cmd)
11771184

11781185
if err := res.Decode(&m); err != nil {
1186+
if e, ok := err.(mongo.CommandError); ok {
1187+
if e.Code == Unauthorized {
1188+
errors.Wrap(err, "unauthorized to run command balancerStatus")
1189+
os.Exit(1)
1190+
}
1191+
}
11791192
return nil, err
11801193
}
11811194

@@ -1201,6 +1214,12 @@ func balancerEnabled(ctx context.Context, client *mongo.Client) (prometheus.Metr
12011214
cmd := bson.D{{Key: "balancerStatus", Value: "1"}}
12021215
err := client.Database("admin").RunCommand(ctx, cmd).Decode(&bs)
12031216
if err != nil {
1217+
if e, ok := err.(mongo.CommandError); ok {
1218+
if e.Code == Unauthorized {
1219+
errors.Wrap(err, "unauthorized to run command balancerStatus")
1220+
os.Exit(1)
1221+
}
1222+
}
12041223
return nil, err
12051224
}
12061225
if bs.Mode == "full" {

internal/util/util.go

+21
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ package util
1717

1818
import (
1919
"context"
20+
"fmt"
21+
"os"
2022

2123
"go.mongodb.org/mongo-driver/bson"
2224
"go.mongodb.org/mongo-driver/mongo"
@@ -29,6 +31,7 @@ const (
2931
ErrNotYetInitialized = int32(94)
3032
ErrNoReplicationEnabled = int32(76)
3133
ErrNotPrimaryOrSecondary = int32(13436)
34+
ErrNotUnauthorized = int32(13)
3235
)
3336

3437
// MyState returns the replica set and the instance's state if available.
@@ -37,6 +40,12 @@ func MyState(ctx context.Context, client *mongo.Client) (string, int, error) {
3740

3841
err := client.Database("admin").RunCommand(ctx, bson.M{"replSetGetStatus": 1}).Decode(&status)
3942
if err != nil {
43+
if e, ok := err.(mongo.CommandError); ok {
44+
if e.Code == ErrNotUnauthorized {
45+
fmt.Fprintf(os.Stderr, "unauthorized to run command replSetGetStatus: %v\n", err)
46+
os.Exit(1)
47+
}
48+
}
4049
return "", 0, err
4150
}
4251

@@ -48,6 +57,12 @@ func MyRole(ctx context.Context, client *mongo.Client) (*proto.HelloResponse, er
4857
var role proto.HelloResponse
4958
err := client.Database("admin").RunCommand(ctx, bson.M{"isMaster": 1}).Decode(&role)
5059
if err != nil {
60+
if e, ok := err.(mongo.CommandError); ok {
61+
if e.Code == ErrNotUnauthorized {
62+
fmt.Fprintf(os.Stderr, "unauthorized to run command isMaster: %v\n", err)
63+
os.Exit(1)
64+
}
65+
}
5166
return nil, err
5267
}
5368

@@ -57,6 +72,12 @@ func MyRole(ctx context.Context, client *mongo.Client) (*proto.HelloResponse, er
5772
func ReplicasetConfig(ctx context.Context, client *mongo.Client) (*proto.ReplicasetConfig, error) {
5873
var rs proto.ReplicasetConfig
5974
if err := client.Database("admin").RunCommand(ctx, bson.M{"replSetGetConfig": 1}).Decode(&rs); err != nil {
75+
if e, ok := err.(mongo.CommandError); ok {
76+
if e.Code == ErrNotUnauthorized {
77+
fmt.Fprintf(os.Stderr, "unauthorized to run command replSetGetConfig: %v\n", err)
78+
os.Exit(1)
79+
}
80+
}
6081
return nil, err
6182
}
6283

0 commit comments

Comments
 (0)