Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
14 changes: 7 additions & 7 deletions cmd/x509-certificate-exporter/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (
"go.uber.org/automaxprocs/maxprocs"
"k8s.io/client-go/util/flowcontrol"

"github.com/enix/x509-certificate-exporter/v3/internal"
"github.com/enix/x509-certificate-exporter/v3/pkg/exporter"
getopt "github.com/pborman/getopt/v2"
)

Expand Down Expand Up @@ -89,7 +89,7 @@ func main() {
}

if *version {
fmt.Fprintf(os.Stderr, "version %s\n", internal.Version)
fmt.Fprintf(os.Stderr, "version %s\n", exporter.Version)
return
}

Expand All @@ -99,7 +99,7 @@ func main() {
}
slog.SetDefault(logger)

slog.Info("Starting exporter", "version", internal.Version, "revision", internal.Revision, "build_time", internal.BuildDateTime)
slog.Info("Starting exporter", "version", exporter.Version, "revision", exporter.Revision, "build_time", exporter.BuildDateTime)

if *profile {
go func() {
Expand All @@ -124,23 +124,23 @@ func main() {
slog.Error("Cannot set GOMEMLIMIT with automemlimit", "reason", err.Error())
}

kubeSecretTypes := make([]internal.KubeSecretType, 0)
kubeSecretTypes := make([]exporter.KubeSecretType, 0)
for _, pattern := range kubeSecretTypePatterns {
kst, err := internal.ParseSecretType(pattern)
kst, err := exporter.ParseSecretType(pattern)
if err != nil {
log.Fatal("failed to parse --secret-type argument: ", err)
}
kubeSecretTypes = append(kubeSecretTypes, kst)
}

exporter := internal.Exporter{
exporter := exporter.Exporter{
ListenAddress: *listenAddress,
SystemdSocket: *systemdSocket,
ConfigFile: *configFile,
Files: files,
Directories: directories,
YAMLs: yamls,
YAMLPaths: internal.DefaultYamlPaths,
YAMLPaths: exporter.DefaultYamlPaths,
TrimPathComponents: *trimPathComponents,
MaxCacheDuration: time.Duration(maxCacheDuration),
ExposeRelativeMetrics: *exposeRelativeMetrics,
Expand Down
2 changes: 1 addition & 1 deletion internal/certificate.go → pkg/exporter/certificate.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package internal
package exporter

import (
"crypto/x509"
Expand Down
48 changes: 24 additions & 24 deletions internal/collector.go → pkg/exporter/collector.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package internal
package exporter

import (
"log/slog"
"runtime"
"time"
"log/slog"

"github.com/prometheus/client_golang/prometheus"
)

type collector struct {
exporter *Exporter
type Collector struct {
Exporter *Exporter
}

var (
Expand Down Expand Up @@ -51,28 +51,28 @@ var (
"goos": runtime.GOOS,
"goarch": runtime.GOARCH,
}
infoDesc = prometheus.NewDesc(infoMetric, infoHelp, nil, infoConstLabels)
//infoDesc = prometheus.NewDesc(infoMetric, infoHelp, nil, infoConstLabels)
)

func (collector *collector) Describe(ch chan<- *prometheus.Desc) {
func (collector Collector) Describe(ch chan<- *prometheus.Desc) {
ch <- certExpiredDesc
ch <- certNotBeforeDesc
ch <- certNotAfterDesc
ch <- certErrorsDesc
ch <- infoDesc
//ch <- infoDesc

if collector.exporter.ExposeRelativeMetrics {
if collector.Exporter.ExposeRelativeMetrics {
ch <- certExpiresInDesc
ch <- certValidSinceDesc
}

if collector.exporter.ExposeErrorMetrics {
if collector.Exporter.ExposeErrorMetrics {
ch <- certErrorDesc
}
}

func (collector *collector) Collect(ch chan<- prometheus.Metric) {
certRefs, certErrors := collector.exporter.parseAllCertificates()
func (collector Collector) Collect(ch chan<- prometheus.Metric) {
certRefs, certErrors := collector.Exporter.parseAllCertificates()

for _, certRef := range certRefs {
for _, cert := range certRef.certificates {
Expand All @@ -82,8 +82,8 @@ func (collector *collector) Collect(ch chan<- prometheus.Metric) {
}
}

if collector.exporter.ExposeErrorMetrics && len(certRef.certificates) > 0 {
labelKeys, labelValues := collector.exporter.unzipLabels(collector.exporter.getBaseLabels(certRef))
if collector.Exporter.ExposeErrorMetrics && len(certRef.certificates) > 0 {
labelKeys, labelValues := collector.Exporter.unzipLabels(collector.Exporter.getBaseLabels(certRef))

ch <- prometheus.MustNewConstMetric(
prometheus.NewDesc(certErrorMetric, certErrorHelp, labelKeys, nil),
Expand All @@ -99,8 +99,8 @@ func (collector *collector) Collect(ch chan<- prometheus.Metric) {
slog.Debug("Collect read error", "reason", err, "index", index)
}

if collector.exporter.ExposeErrorMetrics && err.ref != nil {
labelKeys, labelValues := collector.exporter.unzipLabels(collector.exporter.getBaseLabels(err.ref))
if collector.Exporter.ExposeErrorMetrics && err.ref != nil {
labelKeys, labelValues := collector.Exporter.unzipLabels(collector.Exporter.getBaseLabels(err.ref))

ch <- prometheus.MustNewConstMetric(
prometheus.NewDesc(certErrorMetric, certErrorHelp, labelKeys, nil),
Expand All @@ -117,22 +117,22 @@ func (collector *collector) Collect(ch chan<- prometheus.Metric) {
float64(len(certErrors)),
)

ch <- prometheus.MustNewConstMetric(
infoDesc,
prometheus.GaugeValue,
float64(1),
)
// ch <- prometheus.MustNewConstMetric(
// infoDesc,
// prometheus.GaugeValue,
// float64(1),
// )
}

func (collector *collector) getMetricsForCertificate(certData *parsedCertificate, ref *certificateRef) []prometheus.Metric {
labels := collector.exporter.getLabels(certData, ref)
func (collector Collector) getMetricsForCertificate(certData *parsedCertificate, ref *certificateRef) []prometheus.Metric {
labels := collector.Exporter.getLabels(certData, ref)

expired := 0.
if time.Now().After(certData.cert.NotAfter) {
expired = 1.
}

labelKeys, labelValues := collector.exporter.unzipLabels(labels)
labelKeys, labelValues := collector.Exporter.unzipLabels(labels)
metrics := []prometheus.Metric{
prometheus.MustNewConstMetric(
prometheus.NewDesc(certExpiredMetric, certExpiredHelp, labelKeys, nil),
Expand All @@ -154,7 +154,7 @@ func (collector *collector) getMetricsForCertificate(certData *parsedCertificate
),
}

if collector.exporter.ExposeRelativeMetrics {
if collector.Exporter.ExposeRelativeMetrics {
metrics = append(metrics, prometheus.MustNewConstMetric(
prometheus.NewDesc(certExpiresInMetric, certExpiresInHelp, labelKeys, nil),
prometheus.GaugeValue,
Expand Down
73 changes: 70 additions & 3 deletions internal/exporter.go → pkg/exporter/exporter.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package internal
package exporter

import (
"context"
Expand All @@ -24,6 +24,7 @@ import (
"github.com/dimiro1/health"
"github.com/prometheus/exporter-toolkit/web"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/util/flowcontrol"
)

// Exporter : Configuration (from command-line)
Expand Down Expand Up @@ -57,6 +58,30 @@ type Exporter struct {
configMapsCache *cache.Cache
}

type Options struct {
Directories []string
Files []string
YAMLs []string
YAMLPaths []YAMLCertRef
TrimPathComponents int
MaxCacheDuration time.Duration
ExposeRelativeMetrics bool
ExposeErrorMetrics bool
ExposeLabels []string
ConfigMapKeys []string
KubeEnabled bool
KubeConfigPath string
KubeSecretTypes []KubeSecretType
KubeIncludeNamespaces []string
KubeExcludeNamespaces []string
KubeIncludeNamespaceLabels []string
KubeExcludeNamespaceLabels []string
KubeIncludeLabels []string
KubeExcludeLabels []string
RateLimitQPS int
RateLimitBurst int
}

type KubeSecretType struct {
Type string
Regexp *regexp.Regexp
Expand Down Expand Up @@ -95,13 +120,55 @@ func (exporter *Exporter) ListenAndServe() error {
return exporter.Serve()
}

func New(options Options) (Exporter, error) {

exporter := Exporter{
Directories: options.Directories,
Files: options.Files,
YAMLs: options.YAMLs,
YAMLPaths: options.YAMLPaths,
TrimPathComponents: options.TrimPathComponents,
MaxCacheDuration: options.MaxCacheDuration,
ExposeRelativeMetrics: options.ExposeRelativeMetrics,
ExposeErrorMetrics: options.ExposeErrorMetrics,
ExposeLabels: options.ExposeLabels,
ConfigMapKeys: options.ConfigMapKeys,
KubeSecretTypes: options.KubeSecretTypes,
KubeIncludeNamespaces: options.KubeIncludeNamespaces,
KubeExcludeNamespaces: options.KubeExcludeNamespaces,
KubeIncludeNamespaceLabels: options.KubeIncludeNamespaceLabels,
KubeExcludeNamespaceLabels: options.KubeExcludeNamespaceLabels,
KubeIncludeLabels: options.KubeIncludeLabels,
KubeExcludeLabels: options.KubeExcludeLabels,
}

exporter.DiscoverCertificates()

if options.KubeEnabled {
// Set rate limiter only if both QPS and burst are set
var rateLimiter flowcontrol.RateLimiter
if options.RateLimitQPS > 0 && options.RateLimitBurst > 0 {
slog.Info("Setting Kubernetes API rate limiter", "qps", options.RateLimitQPS, "burst", options.RateLimitBurst)
rateLimiter = flowcontrol.NewTokenBucketRateLimiter(float32(options.RateLimitQPS), options.RateLimitBurst)
}

err := exporter.ConnectToKubernetesCluster(options.KubeConfigPath, rateLimiter)
if err != nil {
slog.Error("Failed to connect to Kubernetes API", "reason", err)
return exporter, err
}
}

return exporter, nil
}

// Listen : Listen for requests
func (exporter *Exporter) Listen() error {
err := prometheus.Register(&collector{exporter: exporter})
err := prometheus.Register(&Collector{Exporter: exporter})
if err != nil {
if registered, ok := err.(prometheus.AlreadyRegisteredError); ok {
prometheus.Unregister(registered.ExistingCollector)
prometheus.MustRegister(&collector{exporter: exporter})
prometheus.MustRegister(&Collector{Exporter: exporter})
} else {
return err
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package internal
package exporter

import (
"bytes"
Expand Down
2 changes: 1 addition & 1 deletion internal/kubernetes.go → pkg/exporter/kubernetes.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package internal
package exporter

import (
"context"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package internal
package exporter

import (
"context"
Expand Down
2 changes: 1 addition & 1 deletion internal/utility.go → pkg/exporter/utility.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package internal
package exporter

func unique(data []*certificateRef) []*certificateRef {
output := []*certificateRef{}
Expand Down
2 changes: 1 addition & 1 deletion internal/version.go → pkg/exporter/version.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package internal
package exporter

// Version and build informations set at link time
var Version = "0.0.0"
Expand Down