Skip to content

Commit 1d6bb88

Browse files
authored
Merge pull request Azure#11144 from anusapan/iot-parent-device
[IoT Hub] Get/Set parent device cmdlet of Iot device.
2 parents df534e6 + 8e97c17 commit 1d6bb88

File tree

11 files changed

+1236
-270
lines changed

11 files changed

+1236
-270
lines changed

src/IotHub/IotHub.Test/ScenarioTests/IotHubDPDeviceTests.ps1

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,20 @@ function Test-AzureRmIotHubDeviceLifecycle
7777
Assert-True { $updatedDevice1.StatusReason -eq 'Reason1' }
7878

7979
# Update iot device to edge device
80-
$updatedDevice2 = Set-AzIoTHubDevice -ResourceGroupName $ResourceGroupName -IotHubName $IotHubName -DeviceId $device3 -EdgeEnabled $true
81-
Assert-True { $updatedDevice2.Capabilities.IotEdge }
80+
$updatedDevice3 = Set-AzIoTHubDevice -ResourceGroupName $ResourceGroupName -IotHubName $IotHubName -DeviceId $device3 -EdgeEnabled $true
81+
Assert-True { $updatedDevice3.Capabilities.IotEdge }
82+
83+
# Set parent device Id
84+
$updatedChildDevice = Set-AzIotHubDeviceParent -ResourceGroupName $ResourceGroupName -IotHubName $IotHubName -DeviceId $device1 -ParentDeviceId $device3
85+
Assert-False { $updatedChildDevice.Capabilities.IotEdge }
86+
Assert-True { $updatedChildDevice.Id -eq $device1 }
87+
Assert-True { $updatedChildDevice.Scope -eq $updatedDevice3.Scope }
88+
89+
# Get parent device Id
90+
$parentDevice = Get-AzIotHubDeviceParent -ResourceGroupName $ResourceGroupName -IotHubName $IotHubName -DeviceId $device1
91+
Assert-True { $parentDevice.Capabilities.IotEdge }
92+
Assert-True { $parentDevice.Id -eq $device3 }
93+
Assert-True { $updatedChildDevice.Scope -eq $updatedDevice3.Scope }
8294

8395
# Get device detail
8496
$iotDevice = Get-AzIotHubDevice -ResourceGroupName $ResourceGroupName -IotHubName $IotHubName -DeviceId $device1

src/IotHub/IotHub.Test/SessionRecords/Microsoft.Azure.Commands.IotHub.Test.ScenarioTests.IotHubDPDeviceTests/TestAzureIotHubDeviceLifecycle.json

Lines changed: 576 additions & 267 deletions
Large diffs are not rendered by default.

src/IotHub/IotHub/Az.IotHub.psd1

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@ CmdletsToExport = 'Add-AzIotHubKey', 'Get-AzIotHubEventHubConsumerGroup',
9898
'Set-AzIotHubDevice', 'Add-AzIotHubModule',
9999
'Get-AzIotHubModule', 'Remove-AzIotHubModule',
100100
'Set-AzIotHubModule', 'Get-AzIotHubDeviceConnectionString',
101-
'Get-AzIotHubModuleConnectionString'
101+
'Get-AzIotHubModuleConnectionString', 'Get-AzIotHubDeviceParent',
102+
'Set-AzIotHubDeviceParent'
102103
# Variables to export from this module
103104
# VariablesToExport = @()
104105

src/IotHub/IotHub/ChangeLog.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@
3030
- Set-AzIotHubModule
3131
* Add cmdlet to get the connection string of a target IoT device in an Iot Hub.
3232
* Add cmdlet to get the connection string of a module on a target IoT device in an Iot Hub.
33+
* Add support to get/set parent device of an IoT device. New Cmdlets are:
34+
- Get-AzIotHubDeviceParent
35+
- Set-AzIotHubDeviceParent
3336

3437
## Version 2.1.0
3538
* Added support to manage devices in an Iot Hub. New Cmdlets are:
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
// ----------------------------------------------------------------------------------
2+
//
3+
// Copyright Microsoft Corporation
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
// ----------------------------------------------------------------------------------
14+
15+
namespace Microsoft.Azure.Commands.Management.IotHub
16+
{
17+
using System;
18+
using System.Collections.Generic;
19+
using System.Management.Automation;
20+
using Microsoft.Azure.Commands.Management.IotHub.Common;
21+
using Microsoft.Azure.Commands.Management.IotHub.Models;
22+
using Microsoft.Azure.Devices;
23+
using Microsoft.Azure.Management.IotHub;
24+
using Microsoft.Azure.Management.IotHub.Models;
25+
using ResourceManager.Common.ArgumentCompleters;
26+
27+
[Cmdlet("Get", ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "IotHubDeviceParent", DefaultParameterSetName = ResourceParameterSet)]
28+
[OutputType(typeof(PSDevice))]
29+
public class GetAzIotHubDeviceParent : IotHubBaseCmdlet
30+
{
31+
private const string ResourceIdParameterSet = "ResourceIdSet";
32+
private const string ResourceParameterSet = "ResourceSet";
33+
private const string InputObjectParameterSet = "InputObjectSet";
34+
35+
[Parameter(Position = 0, Mandatory = true, ParameterSetName = InputObjectParameterSet, ValueFromPipeline = true, HelpMessage = "IotHub object")]
36+
[ValidateNotNullOrEmpty]
37+
public PSIotHub InputObject { get; set; }
38+
39+
[Parameter(Position = 0, Mandatory = true, ParameterSetName = ResourceParameterSet, HelpMessage = "Name of the Resource Group")]
40+
[ValidateNotNullOrEmpty]
41+
[ResourceGroupCompleter]
42+
public string ResourceGroupName { get; set; }
43+
44+
[Parameter(Position = 0, Mandatory = true, ParameterSetName = ResourceIdParameterSet, ValueFromPipelineByPropertyName = true, HelpMessage = "IotHub Resource Id")]
45+
[ValidateNotNullOrEmpty]
46+
[ResourceIdCompleter("Microsoft.Devices/IotHubs")]
47+
public string ResourceId { get; set; }
48+
49+
[Parameter(Position = 1, Mandatory = true, ParameterSetName = ResourceParameterSet, HelpMessage = "Name of the Iot Hub")]
50+
[ValidateNotNullOrEmpty]
51+
public string IotHubName { get; set; }
52+
53+
[Parameter(Position = 1, Mandatory = true, ParameterSetName = InputObjectParameterSet, HelpMessage = "Id of non-edge device.")]
54+
[Parameter(Position = 1, Mandatory = true, ParameterSetName = ResourceIdParameterSet, HelpMessage = "Id of non-edge device.")]
55+
[Parameter(Position = 2, Mandatory = true, ParameterSetName = ResourceParameterSet, HelpMessage = "Id of non-edge device.")]
56+
[ValidateNotNullOrEmpty]
57+
public string DeviceId { get; set; }
58+
59+
public override void ExecuteCmdlet()
60+
{
61+
IotHubDescription iotHubDescription;
62+
if (ParameterSetName.Equals(InputObjectParameterSet))
63+
{
64+
this.ResourceGroupName = this.InputObject.Resourcegroup;
65+
this.IotHubName = this.InputObject.Name;
66+
iotHubDescription = IotHubUtils.ConvertObject<PSIotHub, IotHubDescription>(this.InputObject);
67+
}
68+
else
69+
{
70+
if (ParameterSetName.Equals(ResourceIdParameterSet))
71+
{
72+
this.ResourceGroupName = IotHubUtils.GetResourceGroupName(this.ResourceId);
73+
this.IotHubName = IotHubUtils.GetIotHubName(this.ResourceId);
74+
}
75+
76+
iotHubDescription = this.IotHubClient.IotHubResource.Get(this.ResourceGroupName, this.IotHubName);
77+
}
78+
79+
IEnumerable<SharedAccessSignatureAuthorizationRule> authPolicies = this.IotHubClient.IotHubResource.ListKeys(this.ResourceGroupName, this.IotHubName);
80+
SharedAccessSignatureAuthorizationRule policy = IotHubUtils.GetPolicy(authPolicies, PSAccessRights.RegistryRead);
81+
PSIotHubConnectionString psIotHubConnectionString = IotHubUtils.ToPSIotHubConnectionString(policy, iotHubDescription.Properties.HostName);
82+
RegistryManager registryManager = RegistryManager.CreateFromConnectionString(psIotHubConnectionString.PrimaryConnectionString);
83+
84+
Device childDevice = registryManager.GetDeviceAsync(this.DeviceId).GetAwaiter().GetResult();
85+
86+
if (childDevice.Capabilities.IotEdge)
87+
{
88+
throw new ArgumentException($"The entered device \"{this.DeviceId}\" should be non-edge device.");
89+
}
90+
91+
if (string.IsNullOrEmpty(childDevice.Scope))
92+
{
93+
throw new ArgumentException($"The entered device \"{this.DeviceId}\" doesn\'t support parent device functionality.");
94+
}
95+
96+
string parentDeviceId = childDevice.Scope.Substring(Properties.Resources.DEVICE_DEVICESCOPE_PREFIX.Length, childDevice.Scope.LastIndexOf("-") - Properties.Resources.DEVICE_DEVICESCOPE_PREFIX.Length);
97+
98+
this.WriteObject(IotHubDataPlaneUtils.ToPSDevice(registryManager.GetDeviceAsync(parentDeviceId).GetAwaiter().GetResult()));
99+
}
100+
}
101+
}
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
// ----------------------------------------------------------------------------------
2+
//
3+
// Copyright Microsoft Corporation
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
// ----------------------------------------------------------------------------------
14+
15+
namespace Microsoft.Azure.Commands.Management.IotHub
16+
{
17+
using System;
18+
using System.Collections.Generic;
19+
using System.Management.Automation;
20+
using Microsoft.Azure.Commands.Management.IotHub.Common;
21+
using Microsoft.Azure.Commands.Management.IotHub.Models;
22+
using Microsoft.Azure.Devices;
23+
using Microsoft.Azure.Management.IotHub;
24+
using Microsoft.Azure.Management.IotHub.Models;
25+
using ResourceManager.Common.ArgumentCompleters;
26+
27+
[Cmdlet("Set", ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "IotHubDeviceParent", DefaultParameterSetName = ResourceParameterSet, SupportsShouldProcess = true)]
28+
[OutputType(typeof(PSDevice))]
29+
public class SetAzIotHubDeviceParent : IotHubBaseCmdlet
30+
{
31+
private const string ResourceIdParameterSet = "ResourceIdSet";
32+
private const string ResourceParameterSet = "ResourceSet";
33+
private const string InputObjectParameterSet = "InputObjectSet";
34+
35+
[Parameter(Position = 0, Mandatory = true, ParameterSetName = InputObjectParameterSet, ValueFromPipeline = true, HelpMessage = "IotHub object")]
36+
[ValidateNotNullOrEmpty]
37+
public PSIotHub InputObject { get; set; }
38+
39+
[Parameter(Position = 0, Mandatory = true, ParameterSetName = ResourceParameterSet, HelpMessage = "Name of the Resource Group")]
40+
[ValidateNotNullOrEmpty]
41+
[ResourceGroupCompleter]
42+
public string ResourceGroupName { get; set; }
43+
44+
[Parameter(Position = 0, Mandatory = true, ParameterSetName = ResourceIdParameterSet, ValueFromPipelineByPropertyName = true, HelpMessage = "IotHub Resource Id")]
45+
[ValidateNotNullOrEmpty]
46+
[ResourceIdCompleter("Microsoft.Devices/IotHubs")]
47+
public string ResourceId { get; set; }
48+
49+
[Parameter(Position = 1, Mandatory = true, ParameterSetName = ResourceParameterSet, HelpMessage = "Name of the Iot Hub")]
50+
[ValidateNotNullOrEmpty]
51+
public string IotHubName { get; set; }
52+
53+
[Parameter(Position = 1, Mandatory = true, ParameterSetName = InputObjectParameterSet, HelpMessage = "Id of non-edge device.")]
54+
[Parameter(Position = 1, Mandatory = true, ParameterSetName = ResourceIdParameterSet, HelpMessage = "Id of non-edge device.")]
55+
[Parameter(Position = 2, Mandatory = true, ParameterSetName = ResourceParameterSet, HelpMessage = "Id of non-edge device.")]
56+
[ValidateNotNullOrEmpty]
57+
public string DeviceId { get; set; }
58+
59+
[Parameter(Position = 2, Mandatory = true, ParameterSetName = InputObjectParameterSet, HelpMessage = "Id of edge device.")]
60+
[Parameter(Position = 2, Mandatory = true, ParameterSetName = ResourceIdParameterSet, HelpMessage = "Id of edge device.")]
61+
[Parameter(Position = 3, Mandatory = true, ParameterSetName = ResourceParameterSet, HelpMessage = "Id of edge device.")]
62+
[ValidateNotNullOrEmpty]
63+
public string ParentDeviceId { get; set; }
64+
65+
[Parameter(Mandatory = false, HelpMessage = "Overwrites the non-edge device\'s parent device.")]
66+
public SwitchParameter Force { get; set; }
67+
68+
public override void ExecuteCmdlet()
69+
{
70+
if (ShouldProcess(this.DeviceId, Properties.Resources.AddIotHubDevice))
71+
{
72+
IotHubDescription iotHubDescription;
73+
if (ParameterSetName.Equals(InputObjectParameterSet))
74+
{
75+
this.ResourceGroupName = this.InputObject.Resourcegroup;
76+
this.IotHubName = this.InputObject.Name;
77+
iotHubDescription = IotHubUtils.ConvertObject<PSIotHub, IotHubDescription>(this.InputObject);
78+
}
79+
else
80+
{
81+
if (ParameterSetName.Equals(ResourceIdParameterSet))
82+
{
83+
this.ResourceGroupName = IotHubUtils.GetResourceGroupName(this.ResourceId);
84+
this.IotHubName = IotHubUtils.GetIotHubName(this.ResourceId);
85+
}
86+
87+
iotHubDescription = this.IotHubClient.IotHubResource.Get(this.ResourceGroupName, this.IotHubName);
88+
}
89+
90+
IEnumerable<SharedAccessSignatureAuthorizationRule> authPolicies = this.IotHubClient.IotHubResource.ListKeys(this.ResourceGroupName, this.IotHubName);
91+
SharedAccessSignatureAuthorizationRule policy = IotHubUtils.GetPolicy(authPolicies, PSAccessRights.RegistryWrite);
92+
PSIotHubConnectionString psIotHubConnectionString = IotHubUtils.ToPSIotHubConnectionString(policy, iotHubDescription.Properties.HostName);
93+
RegistryManager registryManager = RegistryManager.CreateFromConnectionString(psIotHubConnectionString.PrimaryConnectionString);
94+
95+
Device childDevice = registryManager.GetDeviceAsync(this.DeviceId).GetAwaiter().GetResult();
96+
Device parentDevice = registryManager.GetDeviceAsync(this.ParentDeviceId).GetAwaiter().GetResult();
97+
98+
if (childDevice.Capabilities.IotEdge)
99+
{
100+
throw new ArgumentException($"The entered device \"{this.DeviceId}\" should be non-edge device.");
101+
}
102+
103+
if (!parentDevice.Capabilities.IotEdge)
104+
{
105+
throw new ArgumentException($"The entered parent device \"{this.ParentDeviceId}\" should be edge device.");
106+
}
107+
108+
if (!string.IsNullOrEmpty(childDevice.Scope) && !childDevice.Scope.Equals(parentDevice.Scope) && !this.Force.IsPresent)
109+
{
110+
throw new ArgumentException($"The entered device \"{this.DeviceId}\" already has a parent device, please use '-Force' to overwrite.");
111+
}
112+
113+
childDevice.Scope = parentDevice.Scope;
114+
115+
this.WriteObject(IotHubDataPlaneUtils.ToPSDevice(registryManager.UpdateDeviceAsync(childDevice).GetAwaiter().GetResult()));
116+
}
117+
}
118+
}
119+
}

src/IotHub/IotHub/Properties/Resources.Designer.cs

Lines changed: 18 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/IotHub/IotHub/Properties/Resources.resx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,4 +207,10 @@
207207
<data name="UpdateIotHubModule" xml:space="preserve">
208208
<value>Update Module</value>
209209
</data>
210+
<data name="DEVICE_DEVICESCOPE_PREFIX" xml:space="preserve">
211+
<value>ms-azure-iot-edge://</value>
212+
</data>
213+
<data name="SetParentDevice" xml:space="preserve">
214+
<value>Set Parent Device</value>
215+
</data>
210216
</root>

src/IotHub/IotHub/help/Az.IotHub.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ Lists all devices or a particular device contained within an Azure IoT Hub.
5353
### [Get-AzIotHubDeviceConnectionString](Get-AzIotHubDeviceConnectionString.md)
5454
Get the connection string of a target IoT device in an Iot Hub.
5555

56+
### [Get-AzIotHubDeviceParent](Get-AzIotHubDeviceParent.md)
57+
Get the parent device of the specified device.
58+
5659
### [Get-AzIotHubEventHubConsumerGroup](Get-AzIotHubEventHubConsumerGroup.md)
5760
Gets all the eventhub consumergroups.
5861

@@ -134,6 +137,9 @@ Updates the properties of an IotHub.
134137
### [Set-AzIotHubDevice](Set-AzIotHubDevice.md)
135138
Update an IoT Hub device.
136139

140+
### [Set-AzIotHubDeviceParent](Set-AzIotHubDeviceParent.md)
141+
Set the parent device of the specified device.
142+
137143
### [Set-AzIotHubMessageEnrichment](Set-AzIotHubMessageEnrichment.md)
138144
Update a message enrichment in your IoT hub.
139145

0 commit comments

Comments
 (0)