Skip to content

Commit 11cbf88

Browse files
authored
Add user-assigned identity sample. (#213)
* 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
1 parent 3e573f9 commit 11cbf88

File tree

5 files changed

+253
-2
lines changed

5 files changed

+253
-2
lines changed

Gopkg.lock

+7-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Gopkg.toml

+4
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,7 @@
2828
[[constraint]]
2929
name = "github.com/satori/go.uuid"
3030
version = "1.2.0"
31+
32+
[[constraint]]
33+
name = "github.com/pkg/errors"
34+
version = "^0.8.0"

compute/vm_test.go

+91
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/Azure-Samples/azure-sdk-for-go-samples/internal/config"
1515
"github.com/Azure-Samples/azure-sdk-for-go-samples/internal/util"
1616
"github.com/Azure-Samples/azure-sdk-for-go-samples/keyvault"
17+
"github.com/Azure-Samples/azure-sdk-for-go-samples/msi"
1718
"github.com/Azure-Samples/azure-sdk-for-go-samples/network"
1819
"github.com/Azure-Samples/azure-sdk-for-go-samples/resources"
1920
"github.com/Azure/go-autorest/autorest/to"
@@ -398,3 +399,93 @@ func ExampleCreateVMWithDisks() {
398399
// detached data disks
399400
// updated OS disk size
400401
}
402+
403+
func ExampleCreateVMWithUserAssignedIdentity() {
404+
var groupName = config.GenerateGroupName("VMWithUserAssignedID")
405+
// TODO: remove and use local `groupName` only
406+
config.SetGroupName(groupName)
407+
408+
ctx, cancel := context.WithTimeout(context.Background(), 6000*time.Second)
409+
defer cancel()
410+
defer resources.Cleanup(ctx)
411+
412+
_, err := resources.CreateGroup(ctx, groupName)
413+
if err != nil {
414+
util.PrintAndLog(err.Error())
415+
return
416+
}
417+
418+
_, err = network.CreateVirtualNetworkAndSubnets(ctx, virtualNetworkName, subnet1Name, subnet2Name)
419+
if err != nil {
420+
util.PrintAndLog(err.Error())
421+
return
422+
}
423+
util.PrintAndLog("created vnet and 2 subnets")
424+
425+
_, err = network.CreateNetworkSecurityGroup(ctx, nsgName)
426+
if err != nil {
427+
util.PrintAndLog(err.Error())
428+
return
429+
}
430+
util.PrintAndLog("created network security group")
431+
432+
_, err = network.CreatePublicIP(ctx, ipName)
433+
if err != nil {
434+
util.PrintAndLog(err.Error())
435+
return
436+
}
437+
util.PrintAndLog("created public IP")
438+
439+
_, err = network.CreateNIC(ctx, virtualNetworkName, subnet1Name, nsgName, ipName, nicName)
440+
if err != nil {
441+
util.PrintAndLog(err.Error())
442+
return
443+
}
444+
util.PrintAndLog("created nic")
445+
446+
id1, err := msi.CreateUserAssignedIdentity(groupName, "useridentity1")
447+
if err != nil {
448+
util.PrintAndLog(err.Error())
449+
return
450+
}
451+
util.PrintAndLog("created first user-assigned identity")
452+
453+
_, err = CreateVMWithUserAssignedID(ctx, vmName, nicName, username, password, *id1)
454+
if err != nil {
455+
util.PrintAndLog(err.Error())
456+
return
457+
}
458+
util.PrintAndLog("created VM")
459+
460+
id2, err := msi.CreateUserAssignedIdentity(groupName, "useridentity2")
461+
if err != nil {
462+
util.PrintAndLog(err.Error())
463+
return
464+
}
465+
util.PrintAndLog("created second user-assigned identity")
466+
467+
_, err = AddUserAssignedIDToVM(ctx, vmName, *id2)
468+
if err != nil {
469+
util.PrintAndLog(err.Error())
470+
return
471+
}
472+
util.PrintAndLog("added second user-assigned identity to VM")
473+
474+
_, err = RemoveUserAssignedIDFromVM(ctx, vmName, *id1)
475+
if err != nil {
476+
util.PrintAndLog(err.Error())
477+
return
478+
}
479+
util.PrintAndLog("removed first user-assigned identity from VM")
480+
481+
// Output:
482+
// created vnet and 2 subnets
483+
// created network security group
484+
// created public IP
485+
// created nic
486+
// created first user-assigned identity
487+
// created VM
488+
// created second user-assigned identity
489+
// added second user-assigned identity to VM
490+
// removed first user-assigned identity from VM
491+
}

compute/vm_with_identity.go

+112
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import (
1010
"fmt"
1111

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

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

106108
return future.Result(extensionsClient)
107109
}
110+
111+
// CreateVMWithUserAssignedID creates a virtual machine with a user-assigned identity.
112+
func CreateVMWithUserAssignedID(ctx context.Context, vmName, nicName, username, password string, id msi.Identity) (vm compute.VirtualMachine, err error) {
113+
nic, _ := network.GetNic(ctx, nicName)
114+
vmClient := getVMClient()
115+
future, err := vmClient.CreateOrUpdate(
116+
ctx,
117+
config.GroupName(),
118+
vmName,
119+
compute.VirtualMachine{
120+
Location: to.StringPtr(config.Location()),
121+
Identity: &compute.VirtualMachineIdentity{
122+
Type: compute.ResourceIdentityTypeUserAssigned,
123+
UserAssignedIdentities: map[string]*compute.VirtualMachineIdentityUserAssignedIdentitiesValue{
124+
*id.ID: &compute.VirtualMachineIdentityUserAssignedIdentitiesValue{},
125+
},
126+
},
127+
VirtualMachineProperties: &compute.VirtualMachineProperties{
128+
HardwareProfile: &compute.HardwareProfile{
129+
VMSize: compute.BasicA0,
130+
},
131+
StorageProfile: &compute.StorageProfile{
132+
ImageReference: &compute.ImageReference{
133+
Publisher: to.StringPtr(publisher),
134+
Offer: to.StringPtr(offer),
135+
Sku: to.StringPtr(sku),
136+
Version: to.StringPtr("latest"),
137+
},
138+
},
139+
OsProfile: &compute.OSProfile{
140+
ComputerName: to.StringPtr(vmName),
141+
AdminUsername: to.StringPtr(username),
142+
AdminPassword: to.StringPtr(password),
143+
},
144+
NetworkProfile: &compute.NetworkProfile{
145+
NetworkInterfaces: &[]compute.NetworkInterfaceReference{
146+
{
147+
ID: nic.ID,
148+
NetworkInterfaceReferenceProperties: &compute.NetworkInterfaceReferenceProperties{
149+
Primary: to.BoolPtr(true),
150+
},
151+
},
152+
},
153+
},
154+
},
155+
},
156+
)
157+
if err != nil {
158+
return vm, errors.Wrap(err, "failed to create VM")
159+
}
160+
err = future.WaitForCompletion(ctx, vmClient.Client)
161+
if err != nil {
162+
return vm, errors.Wrap(err, "failed waiting for async operation to complete")
163+
}
164+
return future.Result(vmClient)
165+
}
166+
167+
// AddUserAssignedIDToVM adds the specified user-assigned identity to the specified pre-existing VM.
168+
func AddUserAssignedIDToVM(ctx context.Context, vmName string, id msi.Identity) (*compute.VirtualMachine, error) {
169+
vmClient := getVMClient()
170+
future, err := vmClient.Update(
171+
ctx,
172+
config.GroupName(),
173+
vmName,
174+
compute.VirtualMachineUpdate{
175+
Identity: &compute.VirtualMachineIdentity{
176+
Type: compute.ResourceIdentityTypeUserAssigned,
177+
UserAssignedIdentities: map[string]*compute.VirtualMachineIdentityUserAssignedIdentitiesValue{
178+
*id.ID: &compute.VirtualMachineIdentityUserAssignedIdentitiesValue{},
179+
},
180+
},
181+
},
182+
)
183+
if err != nil {
184+
return nil, errors.Wrap(err, "failed to update VM")
185+
}
186+
err = future.WaitForCompletionRef(ctx, vmClient.Client)
187+
if err != nil {
188+
return nil, errors.Wrap(err, "failed waiting for async operation to complete")
189+
}
190+
vm, err := future.Result(vmClient)
191+
return &vm, err
192+
}
193+
194+
// RemoveUserAssignedIDFromVM removes the specified user-assigned identity from the specified pre-existing VM.
195+
func RemoveUserAssignedIDFromVM(ctx context.Context, vmName string, id msi.Identity) (*compute.VirtualMachine, error) {
196+
vmClient := getVMClient()
197+
future, err := vmClient.Update(
198+
ctx,
199+
config.GroupName(),
200+
vmName,
201+
compute.VirtualMachineUpdate{
202+
Identity: &compute.VirtualMachineIdentity{
203+
Type: compute.ResourceIdentityTypeUserAssigned,
204+
UserAssignedIdentities: map[string]*compute.VirtualMachineIdentityUserAssignedIdentitiesValue{
205+
*id.ID: nil,
206+
},
207+
},
208+
},
209+
)
210+
if err != nil {
211+
return nil, errors.Wrap(err, "failed to update VM")
212+
}
213+
err = future.WaitForCompletionRef(ctx, vmClient.Client)
214+
if err != nil {
215+
return nil, errors.Wrap(err, "failed waiting for async operation to complete")
216+
}
217+
vm, err := future.Result(vmClient)
218+
return &vm, err
219+
}

msi/msi.go

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright (c) Microsoft and contributors. All rights reserved.
2+
//
3+
// This source code is licensed under the MIT license found in the
4+
// LICENSE file in the root directory of this source tree.
5+
6+
package msi
7+
8+
import (
9+
"context"
10+
11+
"github.com/Azure-Samples/azure-sdk-for-go-samples/internal/config"
12+
"github.com/Azure-Samples/azure-sdk-for-go-samples/internal/iam"
13+
"github.com/Azure/azure-sdk-for-go/services/preview/msi/mgmt/2015-08-31-preview/msi"
14+
"github.com/Azure/go-autorest/autorest/to"
15+
"github.com/pkg/errors"
16+
)
17+
18+
func getMSIUserAssignedIDClient() (*msi.UserAssignedIdentitiesClient, error) {
19+
a, err := iam.GetResourceManagementAuthorizer()
20+
if err != nil {
21+
return nil, errors.Wrap(err, "failed to get authorizer")
22+
}
23+
msiClient := msi.NewUserAssignedIdentitiesClient(config.SubscriptionID())
24+
msiClient.Authorizer = a
25+
msiClient.AddToUserAgent(config.UserAgent())
26+
return &msiClient, nil
27+
}
28+
29+
// CreateUserAssignedIdentity creates a user-assigned identity in the specified resource group.
30+
func CreateUserAssignedIdentity(resourceGroup, identity string) (*msi.Identity, error) {
31+
msiClient, err := getMSIUserAssignedIDClient()
32+
if err != nil {
33+
return nil, err
34+
}
35+
id, err := msiClient.CreateOrUpdate(context.Background(), resourceGroup, identity, msi.Identity{
36+
Location: to.StringPtr(config.Location()),
37+
})
38+
return &id, err
39+
}

0 commit comments

Comments
 (0)