forked from openshift/installer
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
terraform/exec/plugins: add embedded 'azureprivatedns' provider to ha…
…ndle private_dns zone Using the upstream azurerm provider is not possible for now because of following reasons: 1) There is not srv record resource for private dns zone 2) The version of provider that has the private dns zone resources `1.34.0` has a lot of bugs like * hashicorp/terraform-provider-azurerm#4452 * hashicorp/terraform-provider-azurerm#4453 * hashicorp/terraform-provider-azurerm#4501 Some of these bugs are fixed, and some are in flight. Another reason moving to `1.36.0` which might have all the fixes we need is the provider has moved to using `standalone terraform plugin SDK v1.1.1` [1]. Because we vendor both terraform and providers, this causes errors like `panic: gob: registering duplicate types for "github.com/zclconf/go-cty/cty.primitiveType": cty.primitiveType != cty.primitiveType` Therefore, we would have to move towards a single vendor for terraform and plugins for correct inter-operation, which is tricker due to conflicts elsewhere A simple 4 resource plugin that re-uses the already vendored azurerm provider as library and carries over the required resources seems like an easy fix for now. [1]: hashicorp/terraform-provider-azurerm#4474
- Loading branch information
1 parent
ba00702
commit af00810
Showing
15 changed files
with
4,327 additions
and
1 deletion.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package plugins | ||
|
||
import ( | ||
"github.com/hashicorp/terraform/plugin" | ||
"github.com/openshift/installer/pkg/terraform/exec/plugins/azureprivatedns" | ||
) | ||
|
||
func init() { | ||
azurePrivateDNSProvider := func() { | ||
plugin.Serve(&plugin.ServeOpts{ | ||
ProviderFunc: azureprivatedns.Provider, | ||
}) | ||
} | ||
KnownPlugins["terraform-provider-azureprivatedns"] = azurePrivateDNSProvider | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
package azureprivatedns | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"log" | ||
"os" | ||
"strings" | ||
"time" | ||
|
||
"github.com/Azure/azure-sdk-for-go/services/privatedns/mgmt/2018-09-01/privatedns" | ||
"github.com/Azure/go-autorest/autorest" | ||
"github.com/Azure/go-autorest/autorest/adal" | ||
az "github.com/Azure/go-autorest/autorest/azure" | ||
"github.com/hashicorp/go-azure-helpers/authentication" | ||
"github.com/hashicorp/terraform/httpclient" | ||
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" | ||
"github.com/terraform-providers/terraform-provider-azurerm/version" | ||
) | ||
|
||
// ArmClient contains the handles to all the specific Azure Resource Manager | ||
// resource classes' respective clients. | ||
type ArmClient struct { | ||
clientID string | ||
tenantID string | ||
subscriptionID string | ||
usingServicePrincipal bool | ||
environment az.Environment | ||
|
||
StopContext context.Context | ||
|
||
recordSetsClient *privatedns.RecordSetsClient | ||
privateZonesClient *privatedns.PrivateZonesClient | ||
virtualNetworkLinksClient *privatedns.VirtualNetworkLinksClient | ||
} | ||
|
||
func (c *ArmClient) configureClient(client *autorest.Client, auth autorest.Authorizer) { | ||
setUserAgent(client) | ||
client.Authorizer = auth | ||
client.Sender = azure.BuildSender() | ||
client.SkipResourceProviderRegistration = true | ||
client.PollingDuration = 60 * time.Minute | ||
} | ||
|
||
func setUserAgent(client *autorest.Client) { | ||
// TODO: This is the SDK version not the CLI version, once we are on 0.12, should revisit | ||
tfUserAgent := httpclient.UserAgentString() | ||
|
||
pv := version.ProviderVersion | ||
providerUserAgent := fmt.Sprintf("%s terraform-provider-azurerm/%s", tfUserAgent, pv) | ||
client.UserAgent = strings.TrimSpace(fmt.Sprintf("%s %s", client.UserAgent, providerUserAgent)) | ||
|
||
// append the CloudShell version to the user agent if it exists | ||
if azureAgent := os.Getenv("AZURE_HTTP_USER_AGENT"); azureAgent != "" { | ||
client.UserAgent = fmt.Sprintf("%s %s", client.UserAgent, azureAgent) | ||
} | ||
|
||
log.Printf("[DEBUG] AzureRM Client User Agent: %s\n", client.UserAgent) | ||
} | ||
|
||
// getArmClient is a helper method which returns a fully instantiated | ||
// *ArmClient based on the Config's current settings. | ||
func getArmClient(c *authentication.Config) (*ArmClient, error) { | ||
env, err := authentication.DetermineEnvironment(c.Environment) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// client declarations: | ||
client := ArmClient{ | ||
clientID: c.ClientID, | ||
tenantID: c.TenantID, | ||
subscriptionID: c.SubscriptionID, | ||
environment: *env, | ||
usingServicePrincipal: c.AuthenticatedAsAServicePrincipal, | ||
} | ||
|
||
oauthConfig, err := adal.NewOAuthConfig(env.ActiveDirectoryEndpoint, c.TenantID) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// OAuthConfigForTenant returns a pointer, which can be nil. | ||
if oauthConfig == nil { | ||
return nil, fmt.Errorf("unable to configure OAuthConfig for tenant %s", c.TenantID) | ||
} | ||
|
||
sender := azure.BuildSender() | ||
|
||
// Resource Manager endpoints | ||
endpoint := env.ResourceManagerEndpoint | ||
auth, err := c.GetAuthorizationToken(sender, oauthConfig, env.TokenAudience) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
client.registerPrivateDNSClients(endpoint, c.SubscriptionID, auth) | ||
|
||
return &client, nil | ||
} | ||
|
||
func (c *ArmClient) registerPrivateDNSClients(endpoint, subscriptionID string, auth autorest.Authorizer) { | ||
rs := privatedns.NewRecordSetsClientWithBaseURI(endpoint, subscriptionID) | ||
c.configureClient(&rs.Client, auth) | ||
c.recordSetsClient = &rs | ||
|
||
zo := privatedns.NewPrivateZonesClientWithBaseURI(endpoint, subscriptionID) | ||
c.configureClient(&zo.Client, auth) | ||
c.privateZonesClient = &zo | ||
|
||
vnl := privatedns.NewVirtualNetworkLinksClientWithBaseURI(endpoint, subscriptionID) | ||
c.configureClient(&vnl.Client, auth) | ||
c.virtualNetworkLinksClient = &vnl | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
package azureprivatedns | ||
|
||
import ( | ||
"crypto/sha1" | ||
"encoding/base64" | ||
"encoding/hex" | ||
"fmt" | ||
"strings" | ||
|
||
"github.com/hashicorp/go-azure-helpers/authentication" | ||
"github.com/hashicorp/terraform/helper/mutexkv" | ||
"github.com/hashicorp/terraform/helper/schema" | ||
"github.com/hashicorp/terraform/terraform" | ||
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/suppress" | ||
) | ||
|
||
// Provider returns a terraform.ResourceProvider. | ||
func Provider() terraform.ResourceProvider { | ||
p := &schema.Provider{ | ||
Schema: map[string]*schema.Schema{ | ||
"subscription_id": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
DefaultFunc: schema.EnvDefaultFunc("ARM_SUBSCRIPTION_ID", ""), | ||
}, | ||
|
||
"client_id": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
DefaultFunc: schema.EnvDefaultFunc("ARM_CLIENT_ID", ""), | ||
}, | ||
|
||
"tenant_id": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
DefaultFunc: schema.EnvDefaultFunc("ARM_TENANT_ID", ""), | ||
}, | ||
|
||
"environment": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
DefaultFunc: schema.EnvDefaultFunc("ARM_ENVIRONMENT", "public"), | ||
}, | ||
|
||
// Client Secret specific fields | ||
"client_secret": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
DefaultFunc: schema.EnvDefaultFunc("ARM_CLIENT_SECRET", ""), | ||
}, | ||
}, | ||
|
||
DataSourcesMap: map[string]*schema.Resource{}, | ||
|
||
ResourcesMap: map[string]*schema.Resource{ | ||
"azureprivatedns_zone": resourceArmPrivateDNSZone(), | ||
"azureprivatedns_a_record": resourceArmPrivateDNSARecord(), | ||
"azureprivatedns_srv_record": resourceArmPrivateDNSSrvRecord(), | ||
"azureprivatedns_zone_virtual_network_link": resourceArmPrivateDNSZoneVirtualNetworkLink(), | ||
}, | ||
} | ||
|
||
p.ConfigureFunc = providerConfigure(p) | ||
|
||
return p | ||
} | ||
|
||
func providerConfigure(p *schema.Provider) schema.ConfigureFunc { | ||
return func(d *schema.ResourceData) (interface{}, error) { | ||
builder := &authentication.Builder{ | ||
SubscriptionID: d.Get("subscription_id").(string), | ||
ClientID: d.Get("client_id").(string), | ||
ClientSecret: d.Get("client_secret").(string), | ||
TenantID: d.Get("tenant_id").(string), | ||
Environment: d.Get("environment").(string), | ||
|
||
// Feature Toggles | ||
SupportsClientSecretAuth: true, | ||
} | ||
|
||
config, err := builder.Build() | ||
if err != nil { | ||
return nil, fmt.Errorf("error building AzureRM Client: %s", err) | ||
} | ||
|
||
client, err := getArmClient(config) | ||
|
||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
client.StopContext = p.StopContext() | ||
|
||
// replaces the context between tests | ||
p.MetaReset = func() error { | ||
client.StopContext = p.StopContext() | ||
return nil | ||
} | ||
|
||
return client, nil | ||
} | ||
} | ||
|
||
// armMutexKV is the instance of MutexKV for ARM resources | ||
var armMutexKV = mutexkv.NewMutexKV() | ||
|
||
// Deprecated: use `suppress.CaseDifference` instead | ||
func ignoreCaseDiffSuppressFunc(k, old, new string, d *schema.ResourceData) bool { | ||
return suppress.CaseDifference(k, old, new, d) | ||
} | ||
|
||
// ignoreCaseStateFunc is a StateFunc from helper/schema that converts the | ||
// supplied value to lower before saving to state for consistency. | ||
func ignoreCaseStateFunc(val interface{}) string { | ||
return strings.ToLower(val.(string)) | ||
} | ||
|
||
func userDataDiffSuppressFunc(_, old, new string, _ *schema.ResourceData) bool { | ||
return userDataStateFunc(old) == new | ||
} | ||
|
||
func userDataStateFunc(v interface{}) string { | ||
switch s := v.(type) { | ||
case string: | ||
s = base64Encode(s) | ||
hash := sha1.Sum([]byte(s)) | ||
return hex.EncodeToString(hash[:]) | ||
default: | ||
return "" | ||
} | ||
} | ||
|
||
func base64EncodedStateFunc(v interface{}) string { | ||
switch s := v.(type) { | ||
case string: | ||
return base64Encode(s) | ||
default: | ||
return "" | ||
} | ||
} | ||
|
||
// base64Encode encodes data if the input isn't already encoded using | ||
// base64.StdEncoding.EncodeToString. If the input is already base64 encoded, | ||
// return the original input unchanged. | ||
func base64Encode(data string) string { | ||
// Check whether the data is already Base64 encoded; don't double-encode | ||
if isBase64Encoded(data) { | ||
return data | ||
} | ||
// data has not been encoded encode and return | ||
return base64.StdEncoding.EncodeToString([]byte(data)) | ||
} | ||
|
||
func isBase64Encoded(data string) bool { | ||
_, err := base64.StdEncoding.DecodeString(data) | ||
return err == nil | ||
} |
Oops, something went wrong.