2020-01-14 18:32:20 +00:00
package env
2019-12-09 17:56:02 +00:00
2019-12-23 22:44:59 +00:00
import (
2019-12-24 19:08:09 +00:00
"fmt"
"io"
2019-12-31 18:03:53 +00:00
"os"
2019-12-28 00:18:10 +00:00
"regexp"
2019-12-31 18:03:53 +00:00
"strings"
2020-03-31 22:07:28 +00:00
"github.com/kelseyhightower/envconfig"
2019-12-23 22:44:59 +00:00
)
2019-12-09 17:56:02 +00:00
2021-05-19 17:16:43 +00:00
const (
2022-08-16 18:43:37 +00:00
defaultHistoryMax = 10
2021-05-19 17:16:43 +00:00
)
2019-12-31 18:03:53 +00:00
var (
justNumbers = regexp . MustCompile ( ` ^\d+$ ` )
deprecatedVars = [ ] string { "PURGE" , "RECREATE_PODS" , "TILLER_NS" , "UPGRADE" , "CANARY_IMAGE" , "CLIENT_ONLY" , "STABLE_REPO_URL" }
)
2019-12-28 00:18:10 +00:00
2019-12-23 22:03:51 +00:00
// The Config struct captures the `settings` and `environment` blocks in the application's drone
2019-12-09 18:52:41 +00:00
// config. Configuration in drone's `settings` block arrives as uppercase env vars matching the
2019-12-24 00:45:09 +00:00
// config key, prefixed with `PLUGIN_`. Config from the `environment` block is uppercased, but does
2019-12-31 17:28:42 +00:00
// not have the `PLUGIN_` prefix.
2019-12-09 17:56:02 +00:00
type Config struct {
// Configuration for drone-helm itself
2020-01-08 18:45:53 +00:00
Command string ` envconfig:"mode" ` // Helm command to run
2020-01-20 18:54:52 +00:00
DroneEvent string ` envconfig:"drone_build_event" ` // Drone event that invoked this plugin.
2020-04-05 12:22:46 +00:00
UpdateDependencies bool ` split_words:"true" ` // [Deprecated] Call `helm dependency update` before the main command (deprecated, use dependencies_action: update instead)
DependenciesAction string ` split_words:"true" ` // Call `helm dependency build` or `helm dependency update` before the main command
2020-01-08 18:45:53 +00:00
AddRepos [ ] string ` split_words:"true" ` // Call `helm repo add` before the main command
2020-01-20 23:40:36 +00:00
RepoCertificate string ` envconfig:"repo_certificate" ` // The Helm chart repository's self-signed certificate (must be base64-encoded)
RepoCACertificate string ` envconfig:"repo_ca_certificate" ` // The Helm chart repository CA's self-signed certificate (must be base64-encoded)
2019-12-23 22:06:05 +00:00
Debug bool ` ` // Generate debug output and pass --debug to all helm commands
Values string ` ` // Argument to pass to --set in applicable helm commands
StringValues string ` split_words:"true" ` // Argument to pass to --set-string in applicable helm commands
ValuesFiles [ ] string ` split_words:"true" ` // Arguments to pass to --values in applicable helm commands
Namespace string ` ` // Kubernetes namespace for all helm commands
2020-08-19 03:11:11 +00:00
CreateNamespace bool ` split_words:"true" ` // Pass --create-namespace to `helm upgrade`
2020-01-08 18:45:53 +00:00
KubeToken string ` split_words:"true" ` // Kubernetes authentication token to put in .kube/config
2020-08-25 02:59:06 +00:00
SkipKubeconfig bool ` envconfig:"skip_kubeconfig" ` // Skip kubeconfig creation
2020-01-20 18:54:52 +00:00
SkipTLSVerify bool ` envconfig:"skip_tls_verify" ` // Put insecure-skip-tls-verify in .kube/config
2020-01-08 18:45:53 +00:00
Certificate string ` envconfig:"kube_certificate" ` // The Kubernetes cluster CA's self-signed certificate (must be base64-encoded)
APIServer string ` envconfig:"kube_api_server" ` // The Kubernetes cluster's API endpoint
ServiceAccount string ` envconfig:"kube_service_account" ` // Account to use for connecting to the Kubernetes cluster
2019-12-23 22:06:05 +00:00
ChartVersion string ` split_words:"true" ` // Specific chart version to use in `helm upgrade`
DryRun bool ` split_words:"true" ` // Pass --dry-run to applicable helm commands
2020-01-08 18:45:53 +00:00
Wait bool ` envconfig:"wait_for_upgrade" ` // Pass --wait to applicable helm commands
2019-12-23 22:06:05 +00:00
ReuseValues bool ` split_words:"true" ` // Pass --reuse-values to `helm upgrade`
2020-01-02 18:58:58 +00:00
KeepHistory bool ` split_words:"true" ` // Pass --keep-history to `helm uninstall`
2021-05-19 17:16:43 +00:00
HistoryMax int ` split_words:"true" ` // Pass --history-max option
2019-12-23 22:06:05 +00:00
Timeout string ` ` // Argument to pass to --timeout in applicable helm commands
Chart string ` ` // Chart argument to use in applicable helm commands
Release string ` ` // Release argument to use in applicable helm commands
2020-01-08 18:45:53 +00:00
Force bool ` envconfig:"force_upgrade" ` // Pass --force to applicable helm commands
2020-01-07 20:21:55 +00:00
AtomicUpgrade bool ` split_words:"true" ` // Pass --atomic to `helm upgrade`
2020-01-20 18:54:52 +00:00
CleanupOnFail bool ` envconfig:"cleanup_failed_upgrade" ` // Pass --cleanup-on-fail to `helm upgrade`
2020-01-02 19:25:13 +00:00
LintStrictly bool ` split_words:"true" ` // Pass --strict to `helm lint`
2021-07-20 18:21:44 +00:00
SkipCrds bool ` split_words:"true" ` // Pass --skip-crds to `helm upgrade`
2019-12-24 19:08:09 +00:00
Stdout io . Writer ` ignored:"true" `
Stderr io . Writer ` ignored:"true" `
2019-12-09 17:56:02 +00:00
}
2019-12-23 22:44:59 +00:00
2019-12-24 17:34:38 +00:00
// NewConfig creates a Config and reads environment variables into it, accounting for several possible formats.
2019-12-24 19:08:09 +00:00
func NewConfig ( stdout , stderr io . Writer ) ( * Config , error ) {
2020-01-08 17:31:22 +00:00
var aliases settingAliases
if err := envconfig . Process ( "plugin" , & aliases ) ; err != nil {
return nil , err
}
if err := envconfig . Process ( "" , & aliases ) ; err != nil {
return nil , err
}
2019-12-24 19:08:09 +00:00
cfg := Config {
2020-01-08 17:31:22 +00:00
Command : aliases . Command ,
AddRepos : aliases . AddRepos ,
APIServer : aliases . APIServer ,
ServiceAccount : aliases . ServiceAccount ,
Wait : aliases . Wait ,
Force : aliases . Force ,
KubeToken : aliases . KubeToken ,
Certificate : aliases . Certificate ,
2021-05-19 17:16:43 +00:00
// set to same default as helm CLI
2022-08-16 18:43:37 +00:00
HistoryMax : defaultHistoryMax ,
2021-05-19 17:16:43 +00:00
2019-12-24 19:08:09 +00:00
Stdout : stdout ,
Stderr : stderr ,
}
2019-12-24 17:34:38 +00:00
if err := envconfig . Process ( "plugin" , & cfg ) ; err != nil {
return nil , err
2019-12-23 23:31:40 +00:00
}
2019-12-24 17:34:38 +00:00
if err := envconfig . Process ( "" , & cfg ) ; err != nil {
return nil , err
2019-12-23 23:31:40 +00:00
}
2020-08-25 02:59:06 +00:00
if cfg . SkipKubeconfig {
if cfg . KubeToken != "" || cfg . Certificate != "" || cfg . APIServer != "" || cfg . ServiceAccount != "" || cfg . SkipTLSVerify {
fmt . Fprintf ( cfg . Stderr , "Warning: skip_kubeconfig is set. The following kubeconfig-related settings will be ignored: kube_config, kube_certificate, kube_api_server, kube_service_account, skip_tls_verify." )
}
}
2019-12-28 00:18:10 +00:00
if justNumbers . MatchString ( cfg . Timeout ) {
cfg . Timeout = fmt . Sprintf ( "%ss" , cfg . Timeout )
}
2020-01-22 00:23:55 +00:00
cfg . loadValuesSecrets ( )
2019-12-24 19:08:09 +00:00
if cfg . Debug && cfg . Stderr != nil {
cfg . logDebug ( )
}
2019-12-31 18:03:53 +00:00
cfg . deprecationWarn ( )
2019-12-24 17:34:38 +00:00
return & cfg , nil
2019-12-23 22:44:59 +00:00
}
2019-12-24 19:08:09 +00:00
2020-01-21 23:37:59 +00:00
func ( cfg * Config ) loadValuesSecrets ( ) {
findVar := regexp . MustCompile ( ` \$\ { ?(\w+)\}? ` )
replacer := func ( varName string ) string {
sigils := regexp . MustCompile ( ` [$ { }] ` )
varName = sigils . ReplaceAllString ( varName , "" )
if value , ok := os . LookupEnv ( varName ) ; ok {
return value
}
2020-01-22 00:04:05 +00:00
if cfg . Debug {
fmt . Fprintf ( cfg . Stderr , "$%s not present in environment, replaced with \"\"\n" , varName )
}
2020-01-21 23:37:59 +00:00
return ""
}
cfg . Values = findVar . ReplaceAllStringFunc ( cfg . Values , replacer )
cfg . StringValues = findVar . ReplaceAllStringFunc ( cfg . StringValues , replacer )
2020-03-31 22:07:28 +00:00
for i := 0 ; i < len ( cfg . AddRepos ) ; i ++ {
cfg . AddRepos [ i ] = findVar . ReplaceAllStringFunc ( cfg . AddRepos [ i ] , replacer )
}
2020-01-21 23:37:59 +00:00
}
2019-12-24 19:08:09 +00:00
func ( cfg Config ) logDebug ( ) {
if cfg . KubeToken != "" {
cfg . KubeToken = "(redacted)"
}
fmt . Fprintf ( cfg . Stderr , "Generated config: %+v\n" , cfg )
}
2019-12-31 18:03:53 +00:00
func ( cfg * Config ) deprecationWarn ( ) {
for _ , varname := range deprecatedVars {
_ , barePresent := os . LookupEnv ( varname )
_ , prefixedPresent := os . LookupEnv ( "PLUGIN_" + varname )
if barePresent || prefixedPresent {
fmt . Fprintf ( cfg . Stderr , "Warning: ignoring deprecated '%s' setting\n" , strings . ToLower ( varname ) )
}
}
}
2020-01-07 23:25:54 +00:00
2020-05-22 22:35:43 +00:00
// settingAliases provides alternate environment variable names for certain settings, either because
// they were renamed during drone-helm3's lifetime or for backward-compatibility with the original
// drone-helm. Most config options don't need to be included here; adding them to the main Config
// struct is sufficient.
2020-01-07 23:25:54 +00:00
type settingAliases struct {
2020-01-08 18:45:53 +00:00
Command string ` envconfig:"helm_command" `
AddRepos [ ] string ` envconfig:"helm_repos" `
APIServer string ` envconfig:"api_server" `
ServiceAccount string ` split_words:"true" `
Wait bool ` `
Force bool ` `
KubeToken string ` envconfig:"kubernetes_token" `
Certificate string ` envconfig:"kubernetes_certificate" `
2020-01-07 23:25:54 +00:00
}