From dff283b018f61b5d66015c5ba13ddab6e79b7e1e Mon Sep 17 00:00:00 2001 From: Eamonn O'Toole Date: Wed, 10 Jul 2024 17:35:07 +0100 Subject: [PATCH] Add support for the hahicorp mux library Hashicorp has a new "framework" for provider development that replaces SDK v2.0. We can combine "framework" provider code which can still be in separate repos with SDK v2.0 provider code using the Hashicorp "mux" library. In this PR we adapt the existing pkg/provider code to allow us to use "mux" with "legacy" provider code that uses the framework that we put together for SDK v2.0. To do this instead of creating one combined provider instance we create separate provider instances one for each service. There are a couple of restrictions on providers that are passed to the mux library: - the ProviderSchema (i.e. the schema that determines the provider stanza) must be same for each sub-provider - you cannot repeat any data-source or resource definitions in any of the sub-providers We've implemented a NewProviderMux function in pkg/provider which creates sub-providers that satisfy the above restrictions. The inputs to this function are the same as those to NewProviderFunc. SDK v2.0 provider repos that use the framework don't need any changes. However we will need to add registration.ServiceRegistration implementations for all new "framework" providers that implement just the ProviderSchemaEntry and pass those down to NewProviderMux. Signed-off-by: Eamonn O'Toole --- pkg/provider/provider_mux.go | 69 ++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 pkg/provider/provider_mux.go diff --git a/pkg/provider/provider_mux.go b/pkg/provider/provider_mux.go new file mode 100644 index 0000000..884bff1 --- /dev/null +++ b/pkg/provider/provider_mux.go @@ -0,0 +1,69 @@ +// (C) Copyright 2021-2024 Hewlett Packard Enterprise Development LP + +package provider + +import ( + "fmt" + "github.com/hashicorp/terraform-plugin-go/tfprotov5" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/hewlettpackard/hpegl-provider-lib/pkg/registration" +) + +// ProviderForMux is a function that returns a list of ProviderServer functions that can be used with the +// Hashicorp mux library. This function will be called from terraform-provider-hpegl which will be adapted +// to support "legacy" provider code that use SDK v2.0 (i.e. metal, vmaas, caas on PCE) as well as newer provider +// code that uses the new Hashicorp provider "framework". +// +// Note that we will need to add the ProviderSchemaEntry() functions for the newer providers. This means that +// registration.ServiceRegistration implementations for the newer providers that only contain ProviderSchemaEntry() +// and no SupportedResource() or SupportedDataSources(). +func ProviderForMux(reg []registration.ServiceRegistration, pf ConfigureFunc) []func() tfprotov5.ProviderServer { + providerSchema := generateProviderSchema(reg) + providerServerList := make([]func() tfprotov5.ProviderServer, 0) + for _, service := range reg { + // Only create a provider if it has resources or data sources + if service.SupportedResources() != nil || service.SupportedDataSources() != nil { + providerServerList = append(providerServerList, generateProvider(service, pf, providerSchema)) + } + } + + return providerServerList +} + +// generateProviderSchema generates the provider schema from the service registrations. Note that this schema +// needs to be added to each of the sub-providers. +func generateProviderSchema(reg []registration.ServiceRegistration) map[string]*schema.Schema { + providerSchema := Schema() + for _, service := range reg { + if service.ProviderSchemaEntry() != nil { + // We panic if the service.Name() key is repeated in providerSchema + if _, ok := providerSchema[service.Name()]; ok { + panic(fmt.Sprintf("service name %s is repeated", service.Name())) + } + providerSchema[service.Name()] = convertToTypeSet(service.ProviderSchemaEntry()) + } + } + + return providerSchema +} + +// generateProvider will generate a sub-provider for each service that can be used with the Hashicorp mux library. +func generateProvider( + service registration.ServiceRegistration, + pf ConfigureFunc, + providerSchema map[string]*schema.Schema, +) func() tfprotov5.ProviderServer { + p := schema.Provider{ + Schema: providerSchema, + ResourcesMap: service.SupportedResources(), + DataSourcesMap: service.SupportedDataSources(), + // Don't use the following field, experimental + ProviderMetaSchema: nil, + TerraformVersion: "", + } + + p.ConfigureContextFunc = pf(&p) // nolint staticcheck + + return p.GRPCProvider +}