From f887eed7360b088a200c34fdb7e8ba6723449c38 Mon Sep 17 00:00:00 2001 From: Andrew Suderman Date: Mon, 6 Mar 2023 11:33:07 -0700 Subject: [PATCH] Enable the ability to run just once (#83) * Enable the ability to run just once * Fix issues when enableMetrics is false. Fix some error handling --- cmd/root.go | 8 +++++++- pkg/app/app.go | 41 +++++++++++++++++++++++++++++++++-------- pkg/app/errors.go | 18 ++++++++++++------ 3 files changed, 52 insertions(+), 15 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index dd95fc0..e6d55a5 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -5,7 +5,7 @@ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -34,6 +34,7 @@ var ( tfCloudToken string vaultTokenFile string enableMetrics bool + runOnce bool ) var rootCmd = &cobra.Command{ @@ -52,6 +53,10 @@ func run(cmd *cobra.Command, args []string) error { } app := app.NewApp(circleToken, vaultTokenFile, tfCloudToken, config, enableMetrics) + if runOnce { + app.EnableMetrics = false + return app.RunOnce() + } return app.Run() } @@ -71,6 +76,7 @@ func init() { rootCmd.Flags().StringVar(&tfCloudToken, "tfcloud-token", "", "A token for TFCloud access.") rootCmd.Flags().StringVar(&vaultTokenFile, "vault-token-file", "", "A file that contains a vault token. Optional - can set VAULT_TOKEN directly if preferred.") rootCmd.Flags().BoolVar(&enableMetrics, "enable-metrics", true, "Enable a prometheus endpoint on port 4329.") + rootCmd.Flags().BoolVar(&runOnce, "run-once", false, "If true, will run the token injection one time. Does not enable health endpoint or metrics.") envMap := map[string]string{ "CIRCLE_CI_TOKEN": "circle-token", diff --git a/pkg/app/app.go b/pkg/app/app.go index 5b73c8a..708f96b 100644 --- a/pkg/app/app.go +++ b/pkg/app/app.go @@ -149,6 +149,27 @@ func (a *App) Run() error { } } +// RunOnce just does a single run for use with a Kubernetes cronjob +func (a *App) RunOnce() error { + + klog.Info("running the token injection once") + + if err := a.refreshVaultToken(); err != nil { + return err + } + var wg sync.WaitGroup + for _, workspace := range a.Config.TFCloud { + wg.Add(1) + go a.updateTFCloudInstance(workspace, &wg) + } + for _, project := range a.Config.CircleCI { + wg.Add(1) + go a.updateCircleCIInstance(project, &wg) + } + wg.Wait() + return nil +} + func (a *App) updateCircleCIInstance(project CircleCIConfig, wg *sync.WaitGroup) { defer wg.Done() projName := project.Name @@ -156,22 +177,24 @@ func (a *App) updateCircleCIInstance(project CircleCIConfig, wg *sync.WaitGroup) token, err := a.VaultClient.CreateToken(project.VaultRole, project.VaultPolicies, a.Config.TokenTTL, a.Config.OrphanTokens) if err != nil { a.incrementVaultError() - klog.Errorf("error making token for CircleCI project %s: %w", projName, err) + klog.Errorf("error making token for CircleCI project %s: %s", projName, err.Error()) return } klog.V(10).Infof("got token %s for CircleCI project %s", token.Auth.ClientToken, projName) klog.Infof("setting env var %s to vault token value in CircleCI project %s", projVariableName, projName) if err := circleci.UpdateEnvVar(projName, projVariableName, token.Auth.ClientToken, a.CircleToken); err != nil { a.incrementCircleCIError() - klog.Errorf("error updating CircleCI project %s with token value: %w", projName, err) + klog.Errorf("error updating CircleCI project %s with token value: %s", projName, err.Error()) return } if err := circleci.UpdateEnvVar(projName, "VAULT_ADDR", a.Config.VaultAddress, a.CircleToken); err != nil { a.incrementCircleCIError() - klog.Errorf("error updating VAULT_ADDR in CircleCI project %s: %w", projName, err) + klog.Errorf("error updating VAULT_ADDR in CircleCI project %s: %s", projName, err.Error()) return } - a.Metrics.circleTokensUpdated.Inc() + if a.EnableMetrics { + a.Metrics.circleTokensUpdated.Inc() + } } func (a *App) updateTFCloudInstance(instance TFCloudConfig, wg *sync.WaitGroup) { @@ -185,7 +208,7 @@ func (a *App) updateTFCloudInstance(instance TFCloudConfig, wg *sync.WaitGroup) token, err := a.VaultClient.CreateToken(instance.VaultRole, instance.VaultPolicies, a.Config.TokenTTL, a.Config.OrphanTokens) if err != nil { a.incrementVaultError() - klog.Errorf("error getting vault token for TFCloud workspace %s: %w", workspaceLogIdentifier, err) + klog.Errorf("error getting vault token for TFCloud workspace %s: %s", workspaceLogIdentifier, err.Error()) return } klog.V(10).Infof("got token %v for tfcloud workspace %s", token.Auth.ClientToken, workspaceLogIdentifier) @@ -199,7 +222,7 @@ func (a *App) updateTFCloudInstance(instance TFCloudConfig, wg *sync.WaitGroup) } if err := tokenVar.Update(); err != nil { a.incrementTfCloudError() - klog.Errorf("error updating token for TFCloud workspace %s: %w", workspaceLogIdentifier, err) + klog.Errorf("error updating token for TFCloud workspace %s: %s", workspaceLogIdentifier, err.Error()) return } addressVar := tfcloud.Variable{ @@ -212,10 +235,12 @@ func (a *App) updateTFCloudInstance(instance TFCloudConfig, wg *sync.WaitGroup) } if err := addressVar.Update(); err != nil { a.incrementTfCloudError() - klog.Errorf("error updating VAULT_ADDR for ws %s: %w", workspaceLogIdentifier, err) + klog.Errorf("error updating VAULT_ADDR for ws %s: %s", workspaceLogIdentifier, err.Error()) return } - a.Metrics.tfcloudTokensUpdated.Inc() + if a.EnableMetrics { + a.Metrics.tfcloudTokensUpdated.Inc() + } } func (a *App) refreshVaultToken() error { diff --git a/pkg/app/errors.go b/pkg/app/errors.go index f327a4d..ae2e62c 100644 --- a/pkg/app/errors.go +++ b/pkg/app/errors.go @@ -44,16 +44,22 @@ func (a *App) registerMetrics() { } func (a App) incrementVaultError() { - a.Metrics.vaultErrorCount.Inc() - a.Metrics.totalErrorCount.Inc() + if a.EnableMetrics { + a.Metrics.vaultErrorCount.Inc() + a.Metrics.totalErrorCount.Inc() + } } func (a App) incrementTfCloudError() { - a.Metrics.tfCloudErrorCount.Inc() - a.Metrics.totalErrorCount.Inc() + if a.EnableMetrics { + a.Metrics.tfCloudErrorCount.Inc() + a.Metrics.totalErrorCount.Inc() + } } func (a App) incrementCircleCIError() { - a.Metrics.circleCIErrorCount.Inc() - a.Metrics.totalErrorCount.Inc() + if a.EnableMetrics { + a.Metrics.circleCIErrorCount.Inc() + a.Metrics.totalErrorCount.Inc() + } }