From 1969d0242eb9dbe8f6ee116c0e6153f72ff432cd Mon Sep 17 00:00:00 2001 From: Vladimir Kuznichenkov Date: Fri, 21 Jun 2024 14:08:16 +0300 Subject: [PATCH] Add optional support for passing env variables into provider Needed to support dynamic auth as described in [issue][1], as we are using sops dependency which is using native aws sdk, it will read such configuration from env variables of the process. Additionally, I upgraded deprecated terraform SDK such as replacing `Read` into `ReadContext` and added [1]: https://github.com/carlpett/terraform-provider-sops/issues/112 --- sops/data_sops_external.go | 31 +++++++++++++++++++++++++------ sops/data_sops_file.go | 37 +++++++++++++++++++++++++++---------- sops/provider.go | 15 +++++++++++++++ 3 files changed, 67 insertions(+), 16 deletions(-) diff --git a/sops/data_sops_external.go b/sops/data_sops_external.go index c675bf39..f720ddf6 100644 --- a/sops/data_sops_external.go +++ b/sops/data_sops_external.go @@ -1,7 +1,10 @@ package sops import ( + "context" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "io/ioutil" + "os" "strings" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -9,8 +12,7 @@ import ( func dataSourceExternal() *schema.Resource { return &schema.Resource{ - Read: dataSourceExternalRead, - + ReadContext: dataSourceExternalRead, Schema: map[string]*schema.Schema{ "input_type": { Type: schema.TypeString, @@ -37,16 +39,33 @@ func dataSourceExternal() *schema.Resource { } } -func dataSourceExternalRead(d *schema.ResourceData, meta interface{}) error { +func dataSourceExternalRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + // Get the environment variables from the provider configuration + envVars, ok := meta.(map[string]interface{}) + if !ok { + return diag.Errorf("Unable to get provider configuration") + } + // Set the environment variables + for key, value := range envVars { + if strValue, ok := value.(string); ok { + os.Setenv(key, strValue) + } + } + source := d.Get("source").(string) content, err := ioutil.ReadAll(strings.NewReader(source)) if err != nil { - return err + return diag.FromErr(err) } format := d.Get("input_type").(string) if err := validateInputType(format); err != nil { - return err + return diag.FromErr(err) } - return readData(content, format, d) + + if err := readData(content, format, d); err != nil { + return diag.FromErr(err) + } + + return nil } diff --git a/sops/data_sops_file.go b/sops/data_sops_file.go index 7bcbf84d..76a7f87a 100644 --- a/sops/data_sops_file.go +++ b/sops/data_sops_file.go @@ -1,8 +1,10 @@ package sops import ( - "fmt" + "context" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "io/ioutil" + "os" "path" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -10,8 +12,7 @@ import ( func dataSourceFile() *schema.Resource { return &schema.Resource{ - Read: dataSourceFileRead, - + ReadContext: dataSourceFileRead, Schema: map[string]*schema.Schema{ "input_type": { Type: schema.TypeString, @@ -38,16 +39,28 @@ func dataSourceFile() *schema.Resource { } } -func dataSourceFileRead(d *schema.ResourceData, meta interface{}) error { +func dataSourceFileRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + // Get the environment variables from the provider configuration + envVars, ok := meta.(map[string]interface{}) + if !ok { + return diag.Errorf("Unable to get provider configuration") + } + // Set the environment variables + for key, value := range envVars { + if strValue, ok := value.(string); ok { + os.Setenv(key, strValue) + } + } + sourceFile := d.Get("source_file").(string) content, err := ioutil.ReadFile(sourceFile) if err != nil { - return err + return diag.FromErr(err) } var format string - if input_type := d.Get("input_type").(string); input_type != "" { - format = input_type + if inputType := d.Get("input_type").(string); inputType != "" { + format = inputType } else { switch ext := path.Ext(sourceFile); ext { case ".json": @@ -59,13 +72,17 @@ func dataSourceFileRead(d *schema.ResourceData, meta interface{}) error { case ".ini": format = "ini" default: - return fmt.Errorf("Don't know how to decode file with extension %s, set input_type to json, yaml or raw as appropriate", ext) + return diag.Errorf("don't know how to decode file with extension %s, set input_type to json, yaml or raw as appropriate", ext) } } if err := validateInputType(format); err != nil { - return err + return diag.FromErr(err) + } + + if err := readData(content, format, d); err != nil { + return diag.FromErr(err) } - return readData(content, format, d) + return nil } diff --git a/sops/provider.go b/sops/provider.go index 9b6cc732..316b20a1 100644 --- a/sops/provider.go +++ b/sops/provider.go @@ -1,14 +1,29 @@ package sops import ( + "context" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) func Provider() *schema.Provider { return &schema.Provider{ + Schema: map[string]*schema.Schema{ + "environment": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, DataSourcesMap: map[string]*schema.Resource{ "sops_file": dataSourceFile(), "sops_external": dataSourceExternal(), }, + ConfigureContextFunc: providerConfigure, } } + +func providerConfigure(ctx context.Context, d *schema.ResourceData) (interface{}, diag.Diagnostics) { + env := d.Get("environment").(map[string]interface{}) + return env, nil +}