Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set CLI options from VSO_ environment variables #551

Merged
merged 3 commits into from
Jan 19, 2024
Merged
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
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ require (
github.com/hashicorp/hcp-sdk-go v0.65.0
github.com/hashicorp/vault/api v1.10.0
github.com/hashicorp/vault/sdk v0.10.2
github.com/kelseyhightower/envconfig v1.4.0
github.com/onsi/ginkgo v1.16.5
github.com/onsi/gomega v1.30.0
github.com/prometheus/client_golang v1.18.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,8 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8=
github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
Expand Down
31 changes: 31 additions & 0 deletions internal/options/env.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1

package options

import (
"github.com/kelseyhightower/envconfig"
)

// VSOEnvOptions are the supported environment variable options, prefixed with VSO.
// The names of the variables in the struct are split using camel case:
// Specification.ClientCacheSize = VSO_CLIENT_CACHE_SIZE
type VSOEnvOptions struct {
// OutputFormat is the VSO_OUTPUT_FORMAT environment variable option
OutputFormat string `split_words:"true"`

// ClientCacheSize is the VSO_CLIENT_CACHE_SIZE environment variable option
ClientCacheSize *int `split_words:"true"`

// ClientCachePersistenceModel is the VSO_CLIENT_CACHE_PERSISTENCE_MODEL
// environment variable option
ClientCachePersistenceModel string `split_words:"true"`

// MaxConcurrentReconciles is the VSO_MAX_CONCURRENT_RECONCILES environment variable option
MaxConcurrentReconciles *int `split_words:"true"`
}

// Parse environment variable options, prefixed with "VSO_"
func (c *VSOEnvOptions) Parse() error {
return envconfig.Process("vso", c)
}
59 changes: 59 additions & 0 deletions internal/options/env_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1

package options

import (
"os"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestParse(t *testing.T) {
tests := map[string]struct {
envs map[string]string
wantOptions VSOEnvOptions
}{
"empty": {
envs: map[string]string{},
wantOptions: VSOEnvOptions{},
},
"set all": {
envs: map[string]string{
"VSO_OUTPUT_FORMAT": "json",
"VSO_CLIENT_CACHE_SIZE": "100",
"VSO_CLIENT_CACHE_PERSISTENCE_MODEL": "memory",
"VSO_MAX_CONCURRENT_RECONCILES": "10",
},
wantOptions: VSOEnvOptions{
OutputFormat: "json",
ClientCacheSize: makeInt(t, 100),
ClientCachePersistenceModel: "memory",
MaxConcurrentReconciles: makeInt(t, 10),
},
},
}
for name, tt := range tests {
t.Run(name, func(t *testing.T) {
defer func() {
for env := range tt.envs {
require.NoError(t, os.Unsetenv(env))
}
}()
for env, val := range tt.envs {
require.NoError(t, os.Setenv(env, val))
}

gotOptions := VSOEnvOptions{}
require.NoError(t, gotOptions.Parse())
assert.Equal(t, tt.wantOptions, gotOptions)
})
}
}

func makeInt(t *testing.T, i int) *int {
t.Helper()
return &i
}
39 changes: 33 additions & 6 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
"github.com/hashicorp/vault-secrets-operator/controllers"
"github.com/hashicorp/vault-secrets-operator/internal/helpers"
"github.com/hashicorp/vault-secrets-operator/internal/metrics"
"github.com/hashicorp/vault-secrets-operator/internal/options"
vclient "github.com/hashicorp/vault-secrets-operator/internal/vault"
"github.com/hashicorp/vault-secrets-operator/internal/version"
//+kubebuilder:scaffold:imports
Expand Down Expand Up @@ -67,6 +68,7 @@ func main() {
cfc := vclient.DefaultCachingClientFactoryConfig()
startTime := time.Now()

var vsoEnvOptions options.VSOEnvOptions
var metricsAddr string
var enableLeaderElection bool
var probeAddr string
Expand All @@ -79,22 +81,27 @@ func main() {

// command-line args and flags
flag.BoolVar(&printVersion, "version", false, "Print the operator version information")
flag.StringVar(&outputFormat, "output", "", "Output format for the operator version information (yaml or json)")
flag.StringVar(&outputFormat, "output", "",
"Output format for the operator version information (yaml or json). "+
"Also set from environment variable VSO_OUTPUT_FORMAT.")
flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.")
flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")
flag.BoolVar(&enableLeaderElection, "leader-elect", true,
"Enable leader election for controller manager. "+
"Enabling this will ensure there is only one active controller manager.")
flag.IntVar(&cfc.ClientCacheSize, "client-cache-size", cfc.ClientCacheSize,
"Size of the in-memory LRU client cache.")
"Size of the in-memory LRU client cache. "+
"Also set from environment variable VSO_CLIENT_CACHE_SIZE.")
flag.StringVar(&clientCachePersistenceModel, "client-cache-persistence-model", defaultPersistenceModel,
fmt.Sprintf(
"The type of client cache persistence model that should be employed."+
"The type of client cache persistence model that should be employed. "+
"Also set from environment variable VSO_CLIENT_CACHE_PERSISTENCE_MODEL. "+
"choices=%v", []string{persistenceModelDirectUnencrypted, persistenceModelDirectEncrypted, persistenceModelNone}))
flag.IntVar(&vdsOptions.MaxConcurrentReconciles, "max-concurrent-reconciles-vds", defaultVaultDynamicSecretsConcurrency,
"Maximum number of concurrent reconciles for the VaultDynamicSecrets controller.")
"Maximum number of concurrent reconciles for the VaultDynamicSecrets controller. Deprecated in favor of -max-concurrent-reconciles.")
flag.IntVar(&controllerOptions.MaxConcurrentReconciles, "max-concurrent-reconciles", defaultSyncableSecretsConcurrency,
"Maximum number of concurrent reconciles for each controller.")
"Maximum number of concurrent reconciles for each controller. "+
"Also set from environment variable VSO_MAX_CONCURRENT_RECONCILES.")
flag.BoolVar(&uninstall, "uninstall", false, "Run in uninstall mode")
flag.IntVar(&preDeleteHookTimeoutSeconds, "pre-delete-hook-timeout-seconds", 60,
"Pre-delete hook timeout in seconds")
Expand All @@ -106,6 +113,26 @@ func main() {
opts.BindFlags(flag.CommandLine)
flag.Parse()

// Parse environment variable options, prefixed with "VSO_"
if err := vsoEnvOptions.Parse(); err != nil {
os.Stderr.WriteString(fmt.Sprintf("Failed to process environment variable options: %q\n", err))
os.Exit(1)
}

// Set options from env if any are set
if vsoEnvOptions.OutputFormat != "" {
tvoran marked this conversation as resolved.
Show resolved Hide resolved
outputFormat = vsoEnvOptions.OutputFormat
}
if vsoEnvOptions.ClientCacheSize != nil {
cfc.ClientCacheSize = *vsoEnvOptions.ClientCacheSize
}
if vsoEnvOptions.ClientCachePersistenceModel != "" {
clientCachePersistenceModel = vsoEnvOptions.ClientCachePersistenceModel
}
if vsoEnvOptions.MaxConcurrentReconciles != nil {
controllerOptions.MaxConcurrentReconciles = *vsoEnvOptions.MaxConcurrentReconciles
}

// versionInfo is used when setting up the buildInfo metric below
versionInfo := version.Version()
if printVersion {
Expand Down Expand Up @@ -214,7 +241,7 @@ func main() {
cfc.Persist = false
default:
setupLog.Error(errors.New("invalid option"),
fmt.Sprintf("Invalid cache pesistence model %q", clientCachePersistenceModel))
fmt.Sprintf("Invalid cache persistence model %q", clientCachePersistenceModel))
os.Exit(1)
}

Expand Down