Sign in during Public Preview to get the Team plan free, plus an early-adopter discount when we launch. Sign in
The Azure SDK for Go is Microsoft's set of libraries for working with Azure from your Go applications. At this time the SDK needs a couple of lines of code to be able to work against Locally.
This guide covers those changes, using a Resource Group as an example - the same configuration works for the other Azure SDK clients too. You can find more examples using the Azure SDK for Go in the locallybuild/examples repository.
This guide was tested using the following versions of these packages, but newer versions should work too.
github.com/Azure/azure-sdk-for-go/sdk/azcore - v1.23.1github.com/Azure/azure-sdk-for-go/sdk/azidentity - v1.14.1github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources - v1.2.0
We're going to provision a Resource Group using the SDK Client ResourceGroupsClient from the github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources package.
When constructing an Azure SDK client, there's two things we need to do configure it to work against Locally:
Cloud property to target Locally. This ensures that calls made by the Azure SDK will interact with Locally rather than Azure Public (or another Azure Environment).
DisableInstanceDiscovery to true. Instance Discovery is a MSAL service which validates that the Azure Tenant is known by Microsoft, to ensure you don't send your credentials to an unknown third-party. Since Locally is running on your local machine and isn't a Microsoft-hosted service - it's Tenant ID isn't returned by MSAL Instance Discovery, therefore we need to disable it for the Azure SDK to connect.
We're hoping to have the Azure SDK for Go support Automatic Configuration in the future, but for now these handful of changes need to be made to the Azure SDKs to be able to connect to Locally.
We can set these by manually constructing the arm.ClientOptions and DefaultAzureCredential objects:
package main
import (
"context"
"log"
"os"
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/arm"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud"
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources"
)
func main() {
clientOptions := azcore.ClientOptions{
// Connect to Locally rather than Azure Public
Cloud: cloud.Configuration{
Services: map[cloud.ServiceName]cloud.ServiceConfiguration{
cloud.ResourceManager: {
Audience: "https://localhost:5680",
Endpoint: "https://localhost:5680",
},
},
},
}
credential, err := azidentity.NewDefaultAzureCredential(&azidentity.DefaultAzureCredentialOptions{
ClientOptions: clientOptions,
// MSAL Instance Discovery validates that the Tenant is known and hosted by Microsoft, with the
// intention being to prevent credentials accidentally being sent to a non-Microsoft provided service.
//
// Since Locally is running on your local machine (and therefore isn't a Microsoft-hosted service)
// we need to disable Instance Discovery, else we'll fail to connect.
DisableInstanceDiscovery: true,
})
if err != nil {
log.Fatalf("building DefaultAzureCredential: %v", err)
}
armClient := &arm.ClientOptions{
ClientOptions: clientOptions,
}
// ...
}
Locally provides the Subscription ID as an Environment Variable (AZURE_SUBSCRIPTION_ID), which can can be obtained via:
// ...
// Retrieve the default Subscription ID from the Environment Variable provided by Locally
subscriptionID := os.Getenv("AZURE_SUBSCRIPTION_ID")
We can use these 3 values when constructing an Azure SDK client, to connect the client to Locally:
// ...
// Construct an Azure SDK client targeting Locally
client, err := armresources.NewResourceGroupsClient(subscriptionID, credential, armClient)
if err != nil {
log.Fatalf("building the Resource Groups client: %+v", err)
}
At this point the Azure SDK client is a regular Azure SDK client - meaning that any calls should work as normal.
This means that we can create a Resource Group in Locally using the Azure SDK using:
// ...
// Create a Resource Group using the Azure SDK for Go
ctx := context.Background()
resourceGroupName := "rg-from-azure-sdk-for-go"
location := "berlin"
payload := armresources.ResourceGroup{
Location: &location,
}
createResp, err := client.CreateOrUpdate(ctx, resourceGroupName, payload, nil)
if err != nil {
log.Fatalf("creating Resource Group %q: %+v", resourceGroupName, err)
}
log.Printf("Created Resource Group %q..", *createResp.ID)
Assuming this file is named main.go, we can then run this sample against Locally using:
$
locally run go run main.go
Should you encounter any issues, please take a look at the troubleshooting section.
package main
import (
"context"
"log"
"os"
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/arm"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud"
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources"
)
func main() {
clientOptions := azcore.ClientOptions{
// Connect to Locally rather than Azure Public
Cloud: cloud.Configuration{
Services: map[cloud.ServiceName]cloud.ServiceConfiguration{
cloud.ResourceManager: {
Audience: "https://localhost:5680",
Endpoint: "https://localhost:5680",
},
},
},
}
credential, err := azidentity.NewDefaultAzureCredential(&azidentity.DefaultAzureCredentialOptions{
ClientOptions: clientOptions,
// MSAL Instance Discovery validates that the Tenant is known and hosted by Microsoft, with the
// intention being to prevent credentials accidentally being sent to a non-Microsoft provided service.
//
// Since Locally is running on your local machine (and therefore isn't a Microsoft-hosted service)
// we need to disable Instance Discovery, else we'll fail to connect.
DisableInstanceDiscovery: true,
})
if err != nil {
log.Fatalf("building DefaultAzureCredential: %v", err)
}
armClient := &arm.ClientOptions{
ClientOptions: clientOptions,
}
// Retrieve the default Subscription ID from the Environment Variable provided by Locally
subscriptionID := os.Getenv("AZURE_SUBSCRIPTION_ID")
// Construct an Azure SDK client targeting Locally
client, err := armresources.NewResourceGroupsClient(subscriptionID, credential, armClient)
if err != nil {
log.Fatalf("building the Resource Groups client: %+v", err)
}
// Create a Resource Group using the Azure SDK for Go
ctx := context.Background()
resourceGroupName := "rg-from-azure-sdk-for-go"
location := "berlin"
payload := armresources.ResourceGroup{
Location: &location,
}
createResp, err := client.CreateOrUpdate(ctx, resourceGroupName, payload, nil)
if err != nil {
log.Fatalf("creating Resource Group %q: %+v", resourceGroupName, err)
}
log.Printf("Created Resource Group %q..", *createResp.ID)
}
The Examples include more Azure SDK for Go samples, and Using Locally in CI shows how to run Locally in your pipeline. Resources like Storage Accounts also get a Data Plane Emulator, which the Azure Storage SDKs can connect to.
Sign in during Public Preview to get the Team plan free, plus an early-adopter discount when we launch. Sign in
Your Azure infrastructure, running on your machine. Deploy in seconds, break things freely, and ship to Azure when you're ready.