Skip to content

Commit

Permalink
Add user-assigned identity sample. (#213)
Browse files Browse the repository at this point in the history
* Add user-assigned identity sample.

Sample includes creating a user-assigned identity, then adding and
removing one from a VM.

* add errors package to toml file
  • Loading branch information
jhendrixMSFT authored Aug 9, 2018
1 parent 3e573f9 commit 11cbf88
Show file tree
Hide file tree
Showing 5 changed files with 253 additions and 2 deletions.
9 changes: 7 additions & 2 deletions Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Gopkg.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,7 @@
[[constraint]]
name = "github.com/satori/go.uuid"
version = "1.2.0"

[[constraint]]
name = "github.com/pkg/errors"
version = "^0.8.0"
91 changes: 91 additions & 0 deletions compute/vm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/Azure-Samples/azure-sdk-for-go-samples/internal/config"
"github.com/Azure-Samples/azure-sdk-for-go-samples/internal/util"
"github.com/Azure-Samples/azure-sdk-for-go-samples/keyvault"
"github.com/Azure-Samples/azure-sdk-for-go-samples/msi"
"github.com/Azure-Samples/azure-sdk-for-go-samples/network"
"github.com/Azure-Samples/azure-sdk-for-go-samples/resources"
"github.com/Azure/go-autorest/autorest/to"
Expand Down Expand Up @@ -398,3 +399,93 @@ func ExampleCreateVMWithDisks() {
// detached data disks
// updated OS disk size
}

func ExampleCreateVMWithUserAssignedIdentity() {
var groupName = config.GenerateGroupName("VMWithUserAssignedID")
// TODO: remove and use local `groupName` only
config.SetGroupName(groupName)

ctx, cancel := context.WithTimeout(context.Background(), 6000*time.Second)
defer cancel()
defer resources.Cleanup(ctx)

_, err := resources.CreateGroup(ctx, groupName)
if err != nil {
util.PrintAndLog(err.Error())
return
}

_, err = network.CreateVirtualNetworkAndSubnets(ctx, virtualNetworkName, subnet1Name, subnet2Name)
if err != nil {
util.PrintAndLog(err.Error())
return
}
util.PrintAndLog("created vnet and 2 subnets")

_, err = network.CreateNetworkSecurityGroup(ctx, nsgName)
if err != nil {
util.PrintAndLog(err.Error())
return
}
util.PrintAndLog("created network security group")

_, err = network.CreatePublicIP(ctx, ipName)
if err != nil {
util.PrintAndLog(err.Error())
return
}
util.PrintAndLog("created public IP")

_, err = network.CreateNIC(ctx, virtualNetworkName, subnet1Name, nsgName, ipName, nicName)
if err != nil {
util.PrintAndLog(err.Error())
return
}
util.PrintAndLog("created nic")

id1, err := msi.CreateUserAssignedIdentity(groupName, "useridentity1")
if err != nil {
util.PrintAndLog(err.Error())
return
}
util.PrintAndLog("created first user-assigned identity")

_, err = CreateVMWithUserAssignedID(ctx, vmName, nicName, username, password, *id1)
if err != nil {
util.PrintAndLog(err.Error())
return
}
util.PrintAndLog("created VM")

id2, err := msi.CreateUserAssignedIdentity(groupName, "useridentity2")
if err != nil {
util.PrintAndLog(err.Error())
return
}
util.PrintAndLog("created second user-assigned identity")

_, err = AddUserAssignedIDToVM(ctx, vmName, *id2)
if err != nil {
util.PrintAndLog(err.Error())
return
}
util.PrintAndLog("added second user-assigned identity to VM")

_, err = RemoveUserAssignedIDFromVM(ctx, vmName, *id1)
if err != nil {
util.PrintAndLog(err.Error())
return
}
util.PrintAndLog("removed first user-assigned identity from VM")

// Output:
// created vnet and 2 subnets
// created network security group
// created public IP
// created nic
// created first user-assigned identity
// created VM
// created second user-assigned identity
// added second user-assigned identity to VM
// removed first user-assigned identity from VM
}
112 changes: 112 additions & 0 deletions compute/vm_with_identity.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
"fmt"

"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2018-06-01/compute"
"github.com/Azure/azure-sdk-for-go/services/preview/msi/mgmt/2015-08-31-preview/msi"
"github.com/pkg/errors"

"github.com/Azure-Samples/azure-sdk-for-go-samples/internal/config"
"github.com/Azure-Samples/azure-sdk-for-go-samples/network"
Expand Down Expand Up @@ -105,3 +107,113 @@ func AddIdentityToVM(ctx context.Context, vmName string) (ext compute.VirtualMac

return future.Result(extensionsClient)
}

// CreateVMWithUserAssignedID creates a virtual machine with a user-assigned identity.
func CreateVMWithUserAssignedID(ctx context.Context, vmName, nicName, username, password string, id msi.Identity) (vm compute.VirtualMachine, err error) {
nic, _ := network.GetNic(ctx, nicName)
vmClient := getVMClient()
future, err := vmClient.CreateOrUpdate(
ctx,
config.GroupName(),
vmName,
compute.VirtualMachine{
Location: to.StringPtr(config.Location()),
Identity: &compute.VirtualMachineIdentity{
Type: compute.ResourceIdentityTypeUserAssigned,
UserAssignedIdentities: map[string]*compute.VirtualMachineIdentityUserAssignedIdentitiesValue{
*id.ID: &compute.VirtualMachineIdentityUserAssignedIdentitiesValue{},
},
},
VirtualMachineProperties: &compute.VirtualMachineProperties{
HardwareProfile: &compute.HardwareProfile{
VMSize: compute.BasicA0,
},
StorageProfile: &compute.StorageProfile{
ImageReference: &compute.ImageReference{
Publisher: to.StringPtr(publisher),
Offer: to.StringPtr(offer),
Sku: to.StringPtr(sku),
Version: to.StringPtr("latest"),
},
},
OsProfile: &compute.OSProfile{
ComputerName: to.StringPtr(vmName),
AdminUsername: to.StringPtr(username),
AdminPassword: to.StringPtr(password),
},
NetworkProfile: &compute.NetworkProfile{
NetworkInterfaces: &[]compute.NetworkInterfaceReference{
{
ID: nic.ID,
NetworkInterfaceReferenceProperties: &compute.NetworkInterfaceReferenceProperties{
Primary: to.BoolPtr(true),
},
},
},
},
},
},
)
if err != nil {
return vm, errors.Wrap(err, "failed to create VM")
}
err = future.WaitForCompletion(ctx, vmClient.Client)
if err != nil {
return vm, errors.Wrap(err, "failed waiting for async operation to complete")
}
return future.Result(vmClient)
}

// AddUserAssignedIDToVM adds the specified user-assigned identity to the specified pre-existing VM.
func AddUserAssignedIDToVM(ctx context.Context, vmName string, id msi.Identity) (*compute.VirtualMachine, error) {
vmClient := getVMClient()
future, err := vmClient.Update(
ctx,
config.GroupName(),
vmName,
compute.VirtualMachineUpdate{
Identity: &compute.VirtualMachineIdentity{
Type: compute.ResourceIdentityTypeUserAssigned,
UserAssignedIdentities: map[string]*compute.VirtualMachineIdentityUserAssignedIdentitiesValue{
*id.ID: &compute.VirtualMachineIdentityUserAssignedIdentitiesValue{},
},
},
},
)
if err != nil {
return nil, errors.Wrap(err, "failed to update VM")
}
err = future.WaitForCompletionRef(ctx, vmClient.Client)
if err != nil {
return nil, errors.Wrap(err, "failed waiting for async operation to complete")
}
vm, err := future.Result(vmClient)
return &vm, err
}

// RemoveUserAssignedIDFromVM removes the specified user-assigned identity from the specified pre-existing VM.
func RemoveUserAssignedIDFromVM(ctx context.Context, vmName string, id msi.Identity) (*compute.VirtualMachine, error) {
vmClient := getVMClient()
future, err := vmClient.Update(
ctx,
config.GroupName(),
vmName,
compute.VirtualMachineUpdate{
Identity: &compute.VirtualMachineIdentity{
Type: compute.ResourceIdentityTypeUserAssigned,
UserAssignedIdentities: map[string]*compute.VirtualMachineIdentityUserAssignedIdentitiesValue{
*id.ID: nil,
},
},
},
)
if err != nil {
return nil, errors.Wrap(err, "failed to update VM")
}
err = future.WaitForCompletionRef(ctx, vmClient.Client)
if err != nil {
return nil, errors.Wrap(err, "failed waiting for async operation to complete")
}
vm, err := future.Result(vmClient)
return &vm, err
}
39 changes: 39 additions & 0 deletions msi/msi.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright (c) Microsoft and contributors. All rights reserved.
//
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree.

package msi

import (
"context"

"github.com/Azure-Samples/azure-sdk-for-go-samples/internal/config"
"github.com/Azure-Samples/azure-sdk-for-go-samples/internal/iam"
"github.com/Azure/azure-sdk-for-go/services/preview/msi/mgmt/2015-08-31-preview/msi"
"github.com/Azure/go-autorest/autorest/to"
"github.com/pkg/errors"
)

func getMSIUserAssignedIDClient() (*msi.UserAssignedIdentitiesClient, error) {
a, err := iam.GetResourceManagementAuthorizer()
if err != nil {
return nil, errors.Wrap(err, "failed to get authorizer")
}
msiClient := msi.NewUserAssignedIdentitiesClient(config.SubscriptionID())
msiClient.Authorizer = a
msiClient.AddToUserAgent(config.UserAgent())
return &msiClient, nil
}

// CreateUserAssignedIdentity creates a user-assigned identity in the specified resource group.
func CreateUserAssignedIdentity(resourceGroup, identity string) (*msi.Identity, error) {
msiClient, err := getMSIUserAssignedIDClient()
if err != nil {
return nil, err
}
id, err := msiClient.CreateOrUpdate(context.Background(), resourceGroup, identity, msi.Identity{
Location: to.StringPtr(config.Location()),
})
return &id, err
}

0 comments on commit 11cbf88

Please sign in to comment.