443 lines
15 KiB
Go
443 lines
15 KiB
Go
package azurerm
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"net/http"
|
|
"net/http/httputil"
|
|
|
|
"github.com/Azure/azure-sdk-for-go/arm/cdn"
|
|
"github.com/Azure/azure-sdk-for-go/arm/compute"
|
|
"github.com/Azure/azure-sdk-for-go/arm/network"
|
|
"github.com/Azure/azure-sdk-for-go/arm/resources/resources"
|
|
"github.com/Azure/azure-sdk-for-go/arm/scheduler"
|
|
"github.com/Azure/azure-sdk-for-go/arm/servicebus"
|
|
"github.com/Azure/azure-sdk-for-go/arm/storage"
|
|
"github.com/Azure/azure-sdk-for-go/arm/trafficmanager"
|
|
mainStorage "github.com/Azure/azure-sdk-for-go/storage"
|
|
"github.com/Azure/go-autorest/autorest"
|
|
"github.com/Azure/go-autorest/autorest/azure"
|
|
"github.com/hashicorp/terraform/terraform"
|
|
riviera "github.com/jen20/riviera/azure"
|
|
)
|
|
|
|
// ArmClient contains the handles to all the specific Azure Resource Manager
|
|
// resource classes' respective clients.
|
|
type ArmClient struct {
|
|
rivieraClient *riviera.Client
|
|
|
|
availSetClient compute.AvailabilitySetsClient
|
|
usageOpsClient compute.UsageOperationsClient
|
|
vmExtensionImageClient compute.VirtualMachineExtensionImagesClient
|
|
vmExtensionClient compute.VirtualMachineExtensionsClient
|
|
vmScaleSetClient compute.VirtualMachineScaleSetsClient
|
|
vmImageClient compute.VirtualMachineImagesClient
|
|
vmClient compute.VirtualMachinesClient
|
|
|
|
appGatewayClient network.ApplicationGatewaysClient
|
|
ifaceClient network.InterfacesClient
|
|
loadBalancerClient network.LoadBalancersClient
|
|
localNetConnClient network.LocalNetworkGatewaysClient
|
|
publicIPClient network.PublicIPAddressesClient
|
|
secGroupClient network.SecurityGroupsClient
|
|
secRuleClient network.SecurityRulesClient
|
|
subnetClient network.SubnetsClient
|
|
netUsageClient network.UsagesClient
|
|
vnetGatewayConnectionsClient network.VirtualNetworkGatewayConnectionsClient
|
|
vnetGatewayClient network.VirtualNetworkGatewaysClient
|
|
vnetClient network.VirtualNetworksClient
|
|
vnetPeeringsClient network.VirtualNetworkPeeringsClient
|
|
routeTablesClient network.RouteTablesClient
|
|
routesClient network.RoutesClient
|
|
|
|
cdnProfilesClient cdn.ProfilesClient
|
|
cdnEndpointsClient cdn.EndpointsClient
|
|
|
|
providers resources.ProvidersClient
|
|
resourceGroupClient resources.GroupsClient
|
|
tagsClient resources.TagsClient
|
|
|
|
jobsClient scheduler.JobsClient
|
|
jobsCollectionsClient scheduler.JobCollectionsClient
|
|
|
|
storageServiceClient storage.AccountsClient
|
|
storageUsageClient storage.UsageOperationsClient
|
|
|
|
deploymentsClient resources.DeploymentsClient
|
|
|
|
trafficManagerProfilesClient trafficmanager.ProfilesClient
|
|
trafficManagerEndpointsClient trafficmanager.EndpointsClient
|
|
|
|
serviceBusNamespacesClient servicebus.NamespacesClient
|
|
serviceBusTopicsClient servicebus.TopicsClient
|
|
serviceBusSubscriptionsClient servicebus.SubscriptionsClient
|
|
}
|
|
|
|
func withRequestLogging() autorest.SendDecorator {
|
|
return func(s autorest.Sender) autorest.Sender {
|
|
return autorest.SenderFunc(func(r *http.Request) (*http.Response, error) {
|
|
// dump request to wire format
|
|
if dump, err := httputil.DumpRequestOut(r, true); err == nil {
|
|
log.Printf("[DEBUG] AzureRM Request: \n%s\n", dump)
|
|
} else {
|
|
// fallback to basic message
|
|
log.Printf("[DEBUG] AzureRM Request: %s to %s\n", r.Method, r.URL)
|
|
}
|
|
|
|
resp, err := s.Do(r)
|
|
if resp != nil {
|
|
// dump response to wire format
|
|
if dump, err := httputil.DumpResponse(resp, true); err == nil {
|
|
log.Printf("[DEBUG] AzureRM Response for %s: \n%s\n", r.URL, dump)
|
|
} else {
|
|
// fallback to basic message
|
|
log.Printf("[DEBUG] AzureRM Response: %s for %s\n", resp.Status, r.URL)
|
|
}
|
|
} else {
|
|
log.Printf("[DEBUG] Request to %s completed with no response", r.URL)
|
|
}
|
|
return resp, err
|
|
})
|
|
}
|
|
}
|
|
|
|
func setUserAgent(client *autorest.Client) {
|
|
version := terraform.VersionString()
|
|
client.UserAgent = fmt.Sprintf("HashiCorp-Terraform-v%s", version)
|
|
}
|
|
|
|
// getArmClient is a helper method which returns a fully instantiated
|
|
// *ArmClient based on the Config's current settings.
|
|
func (c *Config) getArmClient() (*ArmClient, error) {
|
|
// client declarations:
|
|
client := ArmClient{}
|
|
|
|
rivieraClient, err := riviera.NewClient(&riviera.AzureResourceManagerCredentials{
|
|
ClientID: c.ClientID,
|
|
ClientSecret: c.ClientSecret,
|
|
TenantID: c.TenantID,
|
|
SubscriptionID: c.SubscriptionID,
|
|
})
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Error creating Riviera client: %s", err)
|
|
}
|
|
|
|
// validate that the credentials are correct using Riviera. Note that this must be
|
|
// done _before_ using the Microsoft SDK, because Riviera handles errors. Using a
|
|
// namespace registration instead of a simple OAuth token refresh guarantees that
|
|
// service delegation is correct. This has the effect of registering Microsoft.Compute
|
|
// which is neccessary anyway.
|
|
if err := registerProviderWithSubscription("Microsoft.Compute", rivieraClient); err != nil {
|
|
return nil, err
|
|
}
|
|
client.rivieraClient = rivieraClient
|
|
|
|
oauthConfig, err := azure.PublicCloud.OAuthConfigForTenant(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)
|
|
}
|
|
|
|
spt, err := azure.NewServicePrincipalToken(*oauthConfig, c.ClientID, c.ClientSecret,
|
|
azure.PublicCloud.ResourceManagerEndpoint)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// NOTE: these declarations should be left separate for clarity should the
|
|
// clients be wished to be configured with custom Responders/PollingModess etc...
|
|
asc := compute.NewAvailabilitySetsClient(c.SubscriptionID)
|
|
setUserAgent(&asc.Client)
|
|
asc.Authorizer = spt
|
|
asc.Sender = autorest.CreateSender(withRequestLogging())
|
|
client.availSetClient = asc
|
|
|
|
uoc := compute.NewUsageOperationsClient(c.SubscriptionID)
|
|
setUserAgent(&uoc.Client)
|
|
uoc.Authorizer = spt
|
|
uoc.Sender = autorest.CreateSender(withRequestLogging())
|
|
client.usageOpsClient = uoc
|
|
|
|
vmeic := compute.NewVirtualMachineExtensionImagesClient(c.SubscriptionID)
|
|
setUserAgent(&vmeic.Client)
|
|
vmeic.Authorizer = spt
|
|
vmeic.Sender = autorest.CreateSender(withRequestLogging())
|
|
client.vmExtensionImageClient = vmeic
|
|
|
|
vmec := compute.NewVirtualMachineExtensionsClient(c.SubscriptionID)
|
|
setUserAgent(&vmec.Client)
|
|
vmec.Authorizer = spt
|
|
vmec.Sender = autorest.CreateSender(withRequestLogging())
|
|
client.vmExtensionClient = vmec
|
|
|
|
vmic := compute.NewVirtualMachineImagesClient(c.SubscriptionID)
|
|
setUserAgent(&vmic.Client)
|
|
vmic.Authorizer = spt
|
|
vmic.Sender = autorest.CreateSender(withRequestLogging())
|
|
client.vmImageClient = vmic
|
|
|
|
vmssc := compute.NewVirtualMachineScaleSetsClient(c.SubscriptionID)
|
|
setUserAgent(&vmssc.Client)
|
|
vmssc.Authorizer = spt
|
|
vmssc.Sender = autorest.CreateSender(withRequestLogging())
|
|
client.vmScaleSetClient = vmssc
|
|
|
|
vmc := compute.NewVirtualMachinesClient(c.SubscriptionID)
|
|
setUserAgent(&vmc.Client)
|
|
vmc.Authorizer = spt
|
|
vmc.Sender = autorest.CreateSender(withRequestLogging())
|
|
client.vmClient = vmc
|
|
|
|
agc := network.NewApplicationGatewaysClient(c.SubscriptionID)
|
|
setUserAgent(&agc.Client)
|
|
agc.Authorizer = spt
|
|
agc.Sender = autorest.CreateSender(withRequestLogging())
|
|
client.appGatewayClient = agc
|
|
|
|
ifc := network.NewInterfacesClient(c.SubscriptionID)
|
|
setUserAgent(&ifc.Client)
|
|
ifc.Authorizer = spt
|
|
ifc.Sender = autorest.CreateSender(withRequestLogging())
|
|
client.ifaceClient = ifc
|
|
|
|
lbc := network.NewLoadBalancersClient(c.SubscriptionID)
|
|
setUserAgent(&lbc.Client)
|
|
lbc.Authorizer = spt
|
|
lbc.Sender = autorest.CreateSender(withRequestLogging())
|
|
client.loadBalancerClient = lbc
|
|
|
|
lgc := network.NewLocalNetworkGatewaysClient(c.SubscriptionID)
|
|
setUserAgent(&lgc.Client)
|
|
lgc.Authorizer = spt
|
|
lgc.Sender = autorest.CreateSender(withRequestLogging())
|
|
client.localNetConnClient = lgc
|
|
|
|
pipc := network.NewPublicIPAddressesClient(c.SubscriptionID)
|
|
setUserAgent(&pipc.Client)
|
|
pipc.Authorizer = spt
|
|
pipc.Sender = autorest.CreateSender(withRequestLogging())
|
|
client.publicIPClient = pipc
|
|
|
|
sgc := network.NewSecurityGroupsClient(c.SubscriptionID)
|
|
setUserAgent(&sgc.Client)
|
|
sgc.Authorizer = spt
|
|
sgc.Sender = autorest.CreateSender(withRequestLogging())
|
|
client.secGroupClient = sgc
|
|
|
|
src := network.NewSecurityRulesClient(c.SubscriptionID)
|
|
setUserAgent(&src.Client)
|
|
src.Authorizer = spt
|
|
src.Sender = autorest.CreateSender(withRequestLogging())
|
|
client.secRuleClient = src
|
|
|
|
snc := network.NewSubnetsClient(c.SubscriptionID)
|
|
setUserAgent(&snc.Client)
|
|
snc.Authorizer = spt
|
|
snc.Sender = autorest.CreateSender(withRequestLogging())
|
|
client.subnetClient = snc
|
|
|
|
vgcc := network.NewVirtualNetworkGatewayConnectionsClient(c.SubscriptionID)
|
|
setUserAgent(&vgcc.Client)
|
|
vgcc.Authorizer = spt
|
|
vgcc.Sender = autorest.CreateSender(withRequestLogging())
|
|
client.vnetGatewayConnectionsClient = vgcc
|
|
|
|
vgc := network.NewVirtualNetworkGatewaysClient(c.SubscriptionID)
|
|
setUserAgent(&vgc.Client)
|
|
vgc.Authorizer = spt
|
|
vgc.Sender = autorest.CreateSender(withRequestLogging())
|
|
client.vnetGatewayClient = vgc
|
|
|
|
vnc := network.NewVirtualNetworksClient(c.SubscriptionID)
|
|
setUserAgent(&vnc.Client)
|
|
vnc.Authorizer = spt
|
|
vnc.Sender = autorest.CreateSender(withRequestLogging())
|
|
client.vnetClient = vnc
|
|
|
|
vnpc := network.NewVirtualNetworkPeeringsClient(c.SubscriptionID)
|
|
setUserAgent(&vnpc.Client)
|
|
vnpc.Authorizer = spt
|
|
vnpc.Sender = autorest.CreateSender(withRequestLogging())
|
|
client.vnetPeeringsClient = vnpc
|
|
|
|
rtc := network.NewRouteTablesClient(c.SubscriptionID)
|
|
setUserAgent(&rtc.Client)
|
|
rtc.Authorizer = spt
|
|
rtc.Sender = autorest.CreateSender(withRequestLogging())
|
|
client.routeTablesClient = rtc
|
|
|
|
rc := network.NewRoutesClient(c.SubscriptionID)
|
|
setUserAgent(&rc.Client)
|
|
rc.Authorizer = spt
|
|
rc.Sender = autorest.CreateSender(withRequestLogging())
|
|
client.routesClient = rc
|
|
|
|
rgc := resources.NewGroupsClient(c.SubscriptionID)
|
|
setUserAgent(&rgc.Client)
|
|
rgc.Authorizer = spt
|
|
rgc.Sender = autorest.CreateSender(withRequestLogging())
|
|
client.resourceGroupClient = rgc
|
|
|
|
pc := resources.NewProvidersClient(c.SubscriptionID)
|
|
setUserAgent(&pc.Client)
|
|
pc.Authorizer = spt
|
|
pc.Sender = autorest.CreateSender(withRequestLogging())
|
|
client.providers = pc
|
|
|
|
tc := resources.NewTagsClient(c.SubscriptionID)
|
|
setUserAgent(&tc.Client)
|
|
tc.Authorizer = spt
|
|
tc.Sender = autorest.CreateSender(withRequestLogging())
|
|
client.tagsClient = tc
|
|
|
|
jc := scheduler.NewJobsClient(c.SubscriptionID)
|
|
setUserAgent(&jc.Client)
|
|
jc.Authorizer = spt
|
|
jc.Sender = autorest.CreateSender(withRequestLogging())
|
|
client.jobsClient = jc
|
|
|
|
jcc := scheduler.NewJobCollectionsClient(c.SubscriptionID)
|
|
setUserAgent(&jcc.Client)
|
|
jcc.Authorizer = spt
|
|
jcc.Sender = autorest.CreateSender(withRequestLogging())
|
|
client.jobsCollectionsClient = jcc
|
|
|
|
ssc := storage.NewAccountsClient(c.SubscriptionID)
|
|
setUserAgent(&ssc.Client)
|
|
ssc.Authorizer = spt
|
|
ssc.Sender = autorest.CreateSender(withRequestLogging())
|
|
client.storageServiceClient = ssc
|
|
|
|
suc := storage.NewUsageOperationsClient(c.SubscriptionID)
|
|
setUserAgent(&suc.Client)
|
|
suc.Authorizer = spt
|
|
suc.Sender = autorest.CreateSender(withRequestLogging())
|
|
client.storageUsageClient = suc
|
|
|
|
cpc := cdn.NewProfilesClient(c.SubscriptionID)
|
|
setUserAgent(&cpc.Client)
|
|
cpc.Authorizer = spt
|
|
cpc.Sender = autorest.CreateSender(withRequestLogging())
|
|
client.cdnProfilesClient = cpc
|
|
|
|
cec := cdn.NewEndpointsClient(c.SubscriptionID)
|
|
setUserAgent(&cec.Client)
|
|
cec.Authorizer = spt
|
|
cec.Sender = autorest.CreateSender(withRequestLogging())
|
|
client.cdnEndpointsClient = cec
|
|
|
|
dc := resources.NewDeploymentsClient(c.SubscriptionID)
|
|
setUserAgent(&dc.Client)
|
|
dc.Authorizer = spt
|
|
dc.Sender = autorest.CreateSender(withRequestLogging())
|
|
client.deploymentsClient = dc
|
|
|
|
tmpc := trafficmanager.NewProfilesClient(c.SubscriptionID)
|
|
setUserAgent(&tmpc.Client)
|
|
tmpc.Authorizer = spt
|
|
tmpc.Sender = autorest.CreateSender(withRequestLogging())
|
|
client.trafficManagerProfilesClient = tmpc
|
|
|
|
tmec := trafficmanager.NewEndpointsClient(c.SubscriptionID)
|
|
setUserAgent(&tmec.Client)
|
|
tmec.Authorizer = spt
|
|
tmec.Sender = autorest.CreateSender(withRequestLogging())
|
|
client.trafficManagerEndpointsClient = tmec
|
|
|
|
sbnc := servicebus.NewNamespacesClient(c.SubscriptionID)
|
|
setUserAgent(&sbnc.Client)
|
|
sbnc.Authorizer = spt
|
|
sbnc.Sender = autorest.CreateSender(withRequestLogging())
|
|
client.serviceBusNamespacesClient = sbnc
|
|
|
|
sbtc := servicebus.NewTopicsClient(c.SubscriptionID)
|
|
setUserAgent(&sbtc.Client)
|
|
sbtc.Authorizer = spt
|
|
sbtc.Sender = autorest.CreateSender(withRequestLogging())
|
|
client.serviceBusTopicsClient = sbtc
|
|
|
|
sbsc := servicebus.NewSubscriptionsClient(c.SubscriptionID)
|
|
setUserAgent(&sbsc.Client)
|
|
sbsc.Authorizer = spt
|
|
sbsc.Sender = autorest.CreateSender(withRequestLogging())
|
|
client.serviceBusSubscriptionsClient = sbsc
|
|
|
|
return &client, nil
|
|
}
|
|
|
|
func (armClient *ArmClient) getKeyForStorageAccount(resourceGroupName, storageAccountName string) (string, bool, error) {
|
|
accountKeys, err := armClient.storageServiceClient.ListKeys(resourceGroupName, storageAccountName)
|
|
if accountKeys.StatusCode == http.StatusNotFound {
|
|
return "", false, nil
|
|
}
|
|
if err != nil {
|
|
// We assume this is a transient error rather than a 404 (which is caught above), so assume the
|
|
// account still exists.
|
|
return "", true, fmt.Errorf("Error retrieving keys for storage account %q: %s", storageAccountName, err)
|
|
}
|
|
|
|
if accountKeys.Keys == nil {
|
|
return "", false, fmt.Errorf("Nil key returned for storage account %q", storageAccountName)
|
|
}
|
|
|
|
keys := *accountKeys.Keys
|
|
return *keys[0].Value, true, nil
|
|
}
|
|
|
|
func (armClient *ArmClient) getBlobStorageClientForStorageAccount(resourceGroupName, storageAccountName string) (*mainStorage.BlobStorageClient, bool, error) {
|
|
key, accountExists, err := armClient.getKeyForStorageAccount(resourceGroupName, storageAccountName)
|
|
if err != nil {
|
|
return nil, accountExists, err
|
|
}
|
|
if accountExists == false {
|
|
return nil, false, nil
|
|
}
|
|
|
|
storageClient, err := mainStorage.NewBasicClient(storageAccountName, key)
|
|
if err != nil {
|
|
return nil, true, fmt.Errorf("Error creating storage client for storage account %q: %s", storageAccountName, err)
|
|
}
|
|
|
|
blobClient := storageClient.GetBlobService()
|
|
return &blobClient, true, nil
|
|
}
|
|
func (armClient *ArmClient) getTableServiceClientForStorageAccount(resourceGroupName, storageAccountName string) (*mainStorage.TableServiceClient, bool, error) {
|
|
key, accountExists, err := armClient.getKeyForStorageAccount(resourceGroupName, storageAccountName)
|
|
if err != nil {
|
|
return nil, accountExists, err
|
|
}
|
|
if accountExists == false {
|
|
return nil, false, nil
|
|
}
|
|
|
|
storageClient, err := mainStorage.NewBasicClient(storageAccountName, key)
|
|
if err != nil {
|
|
return nil, true, fmt.Errorf("Error creating storage client for storage account %q: %s", storageAccountName, err)
|
|
}
|
|
|
|
tableClient := storageClient.GetTableService()
|
|
return &tableClient, true, nil
|
|
}
|
|
|
|
func (armClient *ArmClient) getQueueServiceClientForStorageAccount(resourceGroupName, storageAccountName string) (*mainStorage.QueueServiceClient, bool, error) {
|
|
key, accountExists, err := armClient.getKeyForStorageAccount(resourceGroupName, storageAccountName)
|
|
if err != nil {
|
|
return nil, accountExists, err
|
|
}
|
|
if accountExists == false {
|
|
return nil, false, nil
|
|
}
|
|
|
|
storageClient, err := mainStorage.NewBasicClient(storageAccountName, key)
|
|
if err != nil {
|
|
return nil, true, fmt.Errorf("Error creating storage client for storage account %q: %s", storageAccountName, err)
|
|
}
|
|
|
|
queueClient := storageClient.GetQueueService()
|
|
return &queueClient, true, nil
|
|
}
|