Skip to content

Commit

Permalink
Add --opts-config-file flag
Browse files Browse the repository at this point in the history
Add `--opts-config-file` flag to support suppling options from a config
file.

Signed-off-by: Pranshu Srivastava <rexagod@gmail.com>
  • Loading branch information
rexagod committed Sep 4, 2022
1 parent 7343894 commit fed11c5
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 11 deletions.
61 changes: 54 additions & 7 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ package main
import (
"context"
"fmt"
"os"
"strings"

"github.com/prometheus/common/version"
"gopkg.in/yaml.v3"
"k8s.io/klog/v2"
"os"
"strings"
"time"

"k8s.io/kube-state-metrics/v2/pkg/customresource"
"k8s.io/kube-state-metrics/v2/pkg/customresourcestate"
Expand Down Expand Up @@ -62,10 +62,57 @@ func main() {
factories = append(factories, crf...)
}

ctx := context.Background()
if err := app.RunKubeStateMetrics(ctx, opts, factories...); err != nil {
klog.ErrorS(err, "Failed to run kube-state-metrics")
klog.FlushAndExit(klog.ExitFlushTimeout, 1)
KSMRunOrDie := func(ctx context.Context) {
klog.Infoln("Starting kube-state-metrics")
if err := app.RunKubeStateMetricsWrapper(ctx, opts, factories...); err != nil {
klog.Errorln(err)
klog.FlushAndExit(klog.ExitFlushTimeout, 1)
}
}
changed := make(chan bool, 1)
go KSMWrapper(changed, KSMRunOrDie)
got := options.GetOptsConfigFile(*opts)
if got != "" {
initialStat, err := os.Stat(got)
if err != nil {
klog.Fatalf("Failed to get file stat: %v", err)
}
initialModTime := initialStat.ModTime()
go monitorChange(changed, got, initialModTime)
}
select {}
}

func KSMWrapper(changed chan bool, fn func(context.Context)) {
// start kube-state-metrics
ctx, cancel := context.WithCancel(context.Background())
go fn(ctx)
for {
// wait for any changes
<-changed

// stop kube-state-metrics
cancel()
klog.Infoln(ctx.Err())

// restart kube-state-metrics
ctx, cancel = context.WithCancel(context.Background())
go fn(ctx)
}
}

func monitorChange(changed chan bool, optsConfigFile string, initialModTime time.Time) {
for {
stat, err := os.Stat(optsConfigFile)
if err != nil {
klog.Fatalln(err)
}
newModTime := stat.ModTime()
if newModTime != initialModTime {
changed <- true
initialModTime = newModTime
}
<-time.After(3 * time.Second)
}
}

Expand Down
32 changes: 30 additions & 2 deletions pkg/app/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ package app
import (
"context"
"fmt"
"gopkg.in/yaml.v3"
"io/ioutil"
"net"
"net/http"
"net/http/pprof"
Expand Down Expand Up @@ -66,10 +68,24 @@ func (pl promLogger) Log(v ...interface{}) error {
return nil
}

// RunKubeStateMetrics will build and run the kube-state-metrics.
func RunKubeStateMetricsWrapper(ctx context.Context, opts *options.Options, factories ...customresource.RegistryFactory) error {
err := runKubeStateMetrics(ctx, opts, factories...)
for {
select {
case <-ctx.Done():
if ctx.Err() == context.Canceled {
return nil
}
return err
default:
}
}
}

// runKubeStateMetrics will build and run the kube-state-metrics.
// Any out-of-tree custom resource metrics could be registered by newing a registry factory
// which implements customresource.RegistryFactory and pass all factories into this function.
func RunKubeStateMetrics(ctx context.Context, opts *options.Options, factories ...customresource.RegistryFactory) error {
func runKubeStateMetrics(ctx context.Context, opts *options.Options, factories ...customresource.RegistryFactory) error {
promLogger := promLogger{}

storeBuilder := store.NewBuilder()
Expand All @@ -87,6 +103,18 @@ func RunKubeStateMetrics(ctx context.Context, opts *options.Options, factories .
)
storeBuilder.WithMetrics(ksmMetricsRegistry)

// TODO: Should the options config file override flags?
got := options.GetOptsConfigFile(*opts)
if got != "" {
optsConfigFile, err := ioutil.ReadFile(got)
if err != nil {
return fmt.Errorf("failed to read opts config file: %v", err)
}
err = yaml.Unmarshal(optsConfigFile, opts)
if err != nil {
return fmt.Errorf("failed to unmarshal opts config file: %v", err)
}
}
var resources []string
if len(opts.Resources) == 0 {
klog.InfoS("Used default resources")
Expand Down
11 changes: 9 additions & 2 deletions pkg/options/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ type Options struct {
TotalShards int
Pod string
Namespace string
MetricDenylist MetricSet
MetricAllowlist MetricSet
MetricDenylist MetricSet `yaml:"metric_denylist"`
MetricAllowlist MetricSet `yaml:"metric_allowlist"`
MetricOptInList MetricSet
Version bool
AnnotationsAllowList LabelsAllowList
Expand All @@ -57,9 +57,15 @@ type Options struct {
CustomResourceConfig string
CustomResourceConfigFile string

optsConfigFile string

flags *pflag.FlagSet
}

func GetOptsConfigFile(opt Options) string {
return opt.optsConfigFile
}

// NewOptions returns a new instance of `Options`.
func NewOptions() *Options {
return &Options{
Expand Down Expand Up @@ -117,6 +123,7 @@ func (o *Options) AddFlags() {

o.flags.StringVar(&o.CustomResourceConfig, "custom-resource-state-config", "", "Inline Custom Resource State Metrics config YAML (experimental)")
o.flags.StringVar(&o.CustomResourceConfigFile, "custom-resource-state-config-file", "", "Path to a Custom Resource State Metrics config file (experimental)")
o.flags.StringVar(&o.optsConfigFile, "opts-config-file", "", "Path to the custom options config file (experimental)")
}

// Parse parses the flag definitions from the argument list.
Expand Down

0 comments on commit fed11c5

Please sign in to comment.