diff --git a/tinkerbell/provider.go b/tinkerbell/provider.go index ecef088..9ed91f8 100644 --- a/tinkerbell/provider.go +++ b/tinkerbell/provider.go @@ -3,6 +3,7 @@ package tinkerbell import ( "fmt" "os" + "sync" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -12,12 +13,6 @@ import ( "github.com/tinkerbell/tink/protos/workflow" ) -type tinkClient struct { - TemplateClient template.TemplateClient - WorkflowClient workflow.WorkflowSvcClient - HardwareClient hardware.HardwareServiceClient -} - // Provider returns the Tinkerbell terraform provider. func Provider() *schema.Provider { return &schema.Provider{ @@ -42,15 +37,34 @@ func Provider() *schema.Provider { } } -func providerConfigure(d *schema.ResourceData) (interface{}, error) { - if v := d.Get("grpc_authority").(string); v != "" { - if err := os.Setenv("TINKERBELL_GRPC_AUTHORITY", v); err != nil { +type tinkClientConfig struct { + providerConfig *schema.ResourceData + client *tinkClient + clientMutex sync.Mutex +} + +type tinkClient struct { + templateClient template.TemplateClient + workflowClient workflow.WorkflowSvcClient + hardwareClient hardware.HardwareServiceClient +} + +func (tc *tinkClientConfig) New() (*tinkClient, error) { + tc.clientMutex.Lock() + defer tc.clientMutex.Unlock() + + if tc.client != nil { + return tc.client, nil + } + + if grpcAuthority := tc.providerConfig.Get("grpc_authority").(string); grpcAuthority != "" { + if err := os.Setenv("TINKERBELL_GRPC_AUTHORITY", grpcAuthority); err != nil { return nil, fmt.Errorf("setting TINKERBELL_GRPC_AUTHORITY environment variable: %w", err) } } - if v := d.Get("cert_url").(string); v != "" { - if err := os.Setenv("TINKERBELL_CERT_URL", v); err != nil { + if certURL := tc.providerConfig.Get("cert_url").(string); certURL != "" { + if err := os.Setenv("TINKERBELL_CERT_URL", certURL); err != nil { return nil, fmt.Errorf("setting TINKERBELL_CERT_URL environment variable: %w", err) } } @@ -60,9 +74,17 @@ func providerConfigure(d *schema.ResourceData) (interface{}, error) { return nil, fmt.Errorf("creating tink client: %w", err) } - return &tinkClient{ - TemplateClient: template.NewTemplateClient(conn), - WorkflowClient: workflow.NewWorkflowSvcClient(conn), - HardwareClient: hardware.NewHardwareServiceClient(conn), + tc.client = &tinkClient{ + templateClient: template.NewTemplateClient(conn), + workflowClient: workflow.NewWorkflowSvcClient(conn), + hardwareClient: hardware.NewHardwareServiceClient(conn), + } + + return tc.client, nil +} + +func providerConfigure(d *schema.ResourceData) (interface{}, error) { + return &tinkClientConfig{ + providerConfig: d, }, nil } diff --git a/tinkerbell/resource_hardware.go b/tinkerbell/resource_hardware.go index 041d28e..48d753d 100644 --- a/tinkerbell/resource_hardware.go +++ b/tinkerbell/resource_hardware.go @@ -80,7 +80,12 @@ func validateHardwareData(m interface{}, p cty.Path) diag.Diagnostics { } func resourceHardwareCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - c := m.(*tinkClient).HardwareClient + tc, err := m.(*tinkClientConfig).New() + if err != nil { + return diagsFromErr(fmt.Errorf("creating Tink client: %w", err)) + } + + c := tc.hardwareClient hw := pkg.HardwareWrapper{} @@ -106,7 +111,12 @@ func resourceHardwareCreate(ctx context.Context, d *schema.ResourceData, m inter } func resourceHardwareUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - c := m.(*tinkClient).HardwareClient + tc, err := m.(*tinkClientConfig).New() + if err != nil { + return diagsFromErr(fmt.Errorf("creating Tink client: %w", err)) + } + + c := tc.hardwareClient hw := pkg.HardwareWrapper{} @@ -126,6 +136,8 @@ func resourceHardwareUpdate(ctx context.Context, d *schema.ResourceData, m inter return diagsFromErr(fmt.Errorf("pushing hardware data: %w", err)) } + d.SetId(hw.Hardware.Id) + return nil } @@ -158,7 +170,12 @@ func getHardware(ctx context.Context, c hardware.HardwareServiceClient, uuid str } func resourceHardwareRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - c := m.(*tinkClient).HardwareClient + tc, err := m.(*tinkClientConfig).New() + if err != nil { + return diagsFromErr(fmt.Errorf("creating Tink client: %w", err)) + } + + c := tc.hardwareClient h, err := getHardware(ctx, c, d.Id()) if err != nil { @@ -184,7 +201,12 @@ func resourceHardwareRead(ctx context.Context, d *schema.ResourceData, m interfa } func resourceHardwareDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - c := m.(*tinkClient).HardwareClient + tc, err := m.(*tinkClientConfig).New() + if err != nil { + return diagsFromErr(fmt.Errorf("creating Tink client: %w", err)) + } + + c := tc.hardwareClient req := hardware.DeleteRequest{ Id: d.Id(), diff --git a/tinkerbell/resource_template.go b/tinkerbell/resource_template.go index e7c319a..e92d506 100644 --- a/tinkerbell/resource_template.go +++ b/tinkerbell/resource_template.go @@ -88,7 +88,12 @@ func getTemplate(ctx context.Context, c template.TemplateClient, id string) (*te } func resourceTemplateCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - c := m.(*tinkClient).TemplateClient + tc, err := m.(*tinkClientConfig).New() + if err != nil { + return diagsFromErr(fmt.Errorf("creating Tink client: %w", err)) + } + + c := tc.templateClient req := template.WorkflowTemplate{ Name: d.Get("name").(string), @@ -106,7 +111,12 @@ func resourceTemplateCreate(ctx context.Context, d *schema.ResourceData, m inter } func resourceTemplateRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - c := m.(*tinkClient).TemplateClient + tc, err := m.(*tinkClientConfig).New() + if err != nil { + return diagsFromErr(fmt.Errorf("creating Tink client: %w", err)) + } + + c := tc.templateClient t, err := getTemplate(ctx, c, d.Id()) if err != nil { @@ -136,7 +146,12 @@ func resourceTemplateRead(ctx context.Context, d *schema.ResourceData, m interfa } func resourceTemplateDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - c := m.(*tinkClient).TemplateClient + tc, err := m.(*tinkClientConfig).New() + if err != nil { + return diagsFromErr(fmt.Errorf("creating Tink client: %w", err)) + } + + c := tc.templateClient t, err := getTemplate(ctx, c, d.Id()) if err != nil { @@ -161,7 +176,12 @@ func resourceTemplateDelete(ctx context.Context, d *schema.ResourceData, m inter } func resourceTemplateUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - c := m.(*tinkClient).TemplateClient + tc, err := m.(*tinkClientConfig).New() + if err != nil { + return diagsFromErr(fmt.Errorf("creating Tink client: %w", err)) + } + + c := tc.templateClient t, err := getTemplate(ctx, c, d.Id()) if err != nil { diff --git a/tinkerbell/resource_workflow.go b/tinkerbell/resource_workflow.go index f939a33..39e2396 100644 --- a/tinkerbell/resource_workflow.go +++ b/tinkerbell/resource_workflow.go @@ -36,7 +36,12 @@ func resourceWorkflow() *schema.Resource { } func resourceWorkflowCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - c := m.(*tinkClient).WorkflowClient + tc, err := m.(*tinkClientConfig).New() + if err != nil { + return diagsFromErr(fmt.Errorf("creating Tink client: %w", err)) + } + + c := tc.workflowClient req := workflow.CreateRequest{ Template: d.Get("template").(string), @@ -82,7 +87,12 @@ func getWorkflow(ctx context.Context, c workflow.WorkflowSvcClient, uuid string) } func resourceWorkflowRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - c := m.(*tinkClient).WorkflowClient + tc, err := m.(*tinkClientConfig).New() + if err != nil { + return diagsFromErr(fmt.Errorf("creating Tink client: %w", err)) + } + + c := tc.workflowClient wf, err := getWorkflow(ctx, c, d.Id()) if err != nil { @@ -99,7 +109,12 @@ func resourceWorkflowRead(ctx context.Context, d *schema.ResourceData, m interfa } func resourceWorkflowDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - c := m.(*tinkClient).WorkflowClient + tc, err := m.(*tinkClientConfig).New() + if err != nil { + return diagsFromErr(fmt.Errorf("creating Tink client: %w", err)) + } + + c := tc.workflowClient wf, err := getWorkflow(ctx, c, d.Id()) if err != nil {