Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ConfigurationContentProvider #11

Merged
merged 4 commits into from
Jun 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 50 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,17 @@ IoT library, which contains common services for Azure IotHub, DeviceProvisioning
- [Method](#method-1)
- [Module Retrieval](#module-retrieval)
- [Usage Example](#usage-example-3)
- [CLI](#cli)
- [Installation](#installation)
- [IConfigurationContentProvider](#iconfigurationcontentprovider)
- [Features](#features-4)
- [Methods](#methods-2)
- [Configuration Content Retrieval from File](#configuration-content-retrieval-from-file)
- [Configuration Content Retrieval from Stream](#configuration-content-retrieval-from-stream)
- [Usage Example](#usage-example-4)
- [Update](#update)
- [Usage](#usage)
- [Option --help](#option---help)
- [Atc.Azure.IoTEdge](#atcazureiotedge)
- [Features](#features-4)
- [Features](#features-5)
- [Extensions](#extensions)
- [Factories](#factories)
- [Wrappers](#wrappers)
Expand Down Expand Up @@ -83,6 +87,7 @@ The `IIoTHubService` is designed to facilitate communication with Azure IoT Hub,
### Methods

#### Device Management

- `CreateDevice(string deviceId, bool edgeEnabled, CancellationToken cancellationToken)`: Create a new device with the option to enable as an edge device.
- `DeleteDevice(string deviceId, CancellationToken cancellationToken)`: Delete a device from the IoT Hub.
- `GetDevice(string deviceId, CancellationToken cancellationToken)`: Retrieve a specific device using its device ID.
Expand All @@ -95,6 +100,7 @@ The `IIoTHubService` is designed to facilitate communication with Azure IoT Hub,
- `GetDeviceTwins(bool onlyIncludeEdgeDevices)`: Retrieve all device twins, with an option to filter for only edge devices.

#### Module Management

- `GetModuleTwin(string deviceId, string moduleId, CancellationToken cancellationToken)`: Retrieve a specific module twin.
- `UpdateDesiredProperties(string deviceId, string moduleId, TwinCollection twinCollection, CancellationToken cancellationToken)`: Update desired properties on a module twin.
- `RemoveModuleFromDevice(string deviceId, string moduleId, CancellationToken cancellationToken)`: Remove a module from an IoT device.
Expand Down Expand Up @@ -145,6 +151,7 @@ The `IIoTHubModuleService` is tailored for direct interactions with IoT devices
### Method

#### Direct Method Invocation

- `CallMethod(string deviceId, string moduleId, MethodParameterModel parameters, CancellationToken cancellationToken)`: This method sends a direct command to a specified module on a device. The `MethodParameterModel` allows for detailed specification of the command, and the operation returns a `MethodResultModel` that includes the status of the call and any resultant data in JSON format.

### Usage Example
Expand Down Expand Up @@ -183,6 +190,7 @@ The `IDeviceProvisioningService` is designed to manage device enrollments within
### Methods

#### Individual Enrollment Management

- `GetIndividualEnrollment(string registrationId, CancellationToken cancellationToken)`: Retrieves a specific enrollment using the registration ID.
- `GetIndividualEnrollments(CancellationToken cancellationToken)`: Fetches all registered individual enrollments.
- `CreateIndividualTpmEnrollment(string endorsementKey, string registrationId, string deviceId, Dictionary<string, string>? tags, Dictionary<string, string>? desiredProperties, CancellationToken cancellationToken)`: Creates or updates a TPM enrollment with specified parameters.
Expand Down Expand Up @@ -253,6 +261,7 @@ The `IDeviceTwinModuleExtractor` is designed to aid in extracting module informa
### Method

#### Module Retrieval

- `GetModuleFromEdgeAgentTwin(Twin twin, string moduleId)`: Extracts a module from the Edge Agent twin using the module identifier. This method is essential for operations needing detailed information about individual modules managed by the Edge Agent.

### Usage Example
Expand All @@ -276,6 +285,44 @@ else
}
```

## IConfigurationContentProvider

The `IConfigurationContentProvider` is designed to assist in retrieving configuration content from deployment manifests in Azure IoT solutions. This interface provides methods for obtaining configuration content from both file and stream sources, ensuring flexibility and reliability in handling deployment manifests.

### Features

- **Configuration Content Retrieval**: Extract configuration content from deployment manifests, facilitating efficient deployment and management of IoT modules.

### Methods

#### Configuration Content Retrieval from File

- `GetConfigurationContent(FileInfo deploymentManifestFileInfo, CancellationToken cancellationToken)`: Retrieves configuration content from a deployment manifest file.

#### Configuration Content Retrieval from Stream

- `GetConfigurationContent(Stream deploymentManifestFileStream, CancellationToken cancellationToken)`: Retrieves configuration content from a deployment manifest stream.

### Usage Example

Below is an example demonstrating how to use the `ConfigurationContentProvider` to retrieve configuration content from a deployment manifest file:

```csharp
var configurationContentProvider = serviceProvider.GetRequiredService<IConfigurationContentProvider>();
var deploymentManifestFile = new FileInfo("path/to/deploymentManifest.json");
var cancellationToken = new CancellationToken();

var (configurationContent, errorMessage) = await configurationContentProvider.GetConfigurationContent(deploymentManifestFile, cancellationToken);

if (configurationContent != null)
{
Console.WriteLine("Configuration content retrieved successfully.");
}
else
{
Console.WriteLine($"Failed to retrieve configuration content: {errorMessage}");
}

# CLI

[![NuGet Version](https://img.shields.io/nuget/v/atc-azure-iot.svg?logo=nuget&style=for-the-badge)](https://www.nuget.org/packages/atc-azure-iot)
Expand Down
2 changes: 2 additions & 0 deletions src/Atc.Azure.IoT/Extensions/ServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ public static IServiceCollection ConfigureDeviceProvisioningServices(
throw new InvalidOperationException($"Required service '{nameof(DeviceProvisioningServiceOptions)}' is not registered");
}

services.TryAddSingleton<IConfigurationContentProvider, ConfigurationContentProvider>();

services.AddSingleton<IDeviceProvisioningService, DeviceProvisioningService>(s => new DeviceProvisioningService(
s.GetRequiredService<ILoggerFactory>(),
deviceProvisioningServiceOptions));
Expand Down
1 change: 1 addition & 0 deletions src/Atc.Azure.IoT/GlobalUsings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
global using Atc.Azure.IoT.Extractors;
global using Atc.Azure.IoT.Models;
global using Atc.Azure.IoT.Options;
global using Atc.Azure.IoT.Providers;
global using Atc.Azure.IoT.Serialization.JsonConverters;
global using Atc.Azure.IoT.Services.DeviceProvisioning;
global using Atc.Azure.IoT.Services.IoTHub;
Expand Down
71 changes: 71 additions & 0 deletions src/Atc.Azure.IoT/Providers/ConfigurationContentProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
namespace Atc.Azure.IoT.Providers;

public sealed class ConfigurationContentProvider : IConfigurationContentProvider
{
public async Task<(ConfigurationContent? ConfigurationContent, string? ErrorMessage)> GetConfigurationContent(
FileInfo deploymentManifestFileInfo,
CancellationToken cancellationToken)
{
if (!deploymentManifestFileInfo.Exists)
{
return (null, "Deployment Manifest file does not exist.");
}

try
{
await using var fileStream = deploymentManifestFileInfo.OpenRead();
return await GetConfigurationContent(fileStream, cancellationToken);
}
catch (Exception ex)
{
return (null, $"Error reading Deployment Manifest file: {ex.Message}");
}
}

public async Task<(ConfigurationContent? ConfigurationContent, string? ErrorMessage)> GetConfigurationContent(
Stream deploymentManifestFileStream,
CancellationToken cancellationToken)
{
var templateContent = await GetTemplateContent(deploymentManifestFileStream, cancellationToken);
if (templateContent is null)
{
return (null, "Deployment Manifest was not in proper format.");
}

var configurationContent = GetConfigurationContentFromManifest(templateContent!);
if (configurationContent is null)
{
return (null, "Could not get ConfigurationContent from Deployment Manifest.");
}

return (configurationContent, null);
}

private static async Task<string?> GetTemplateContent(
Stream deploymentManifestFileStream,
CancellationToken cancellationToken)
{
using var reader = new StreamReader(deploymentManifestFileStream);
var content = await reader.ReadToEndAsync(cancellationToken);

return content.IsFormatJson()
? content
: null;
}

/// <summary>
/// Gets the ConfigurationContent from the deployment manifest
/// </summary>
/// <param name="deploymentManifest">The deployment manifest</param>
/// <returns>The deployment manifest as a <see cref="ConfigurationContent"/></returns>
/// <remarks>
/// We utilize Newtonsoft.Json here, because System.Text.Json does not work!
/// When de-serializing the edgeAgent - properties.desired, instead of "object-array", the serializer returns:
/// ValueKind = Object : " instead of {
/// and " instead of } (for the end).
/// </remarks>
private static ConfigurationContent? GetConfigurationContentFromManifest(
string deploymentManifest)
=> Newtonsoft.Json.JsonConvert.DeserializeObject<ConfigurationContent>(
deploymentManifest);
}
12 changes: 12 additions & 0 deletions src/Atc.Azure.IoT/Providers/IConfigurationContentProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace Atc.Azure.IoT.Providers;

public interface IConfigurationContentProvider
{
Task<(ConfigurationContent? ConfigurationContent, string? ErrorMessage)> GetConfigurationContent(
FileInfo deploymentManifestFileInfo,
CancellationToken cancellationToken);

Task<(ConfigurationContent? ConfigurationContent, string? ErrorMessage)> GetConfigurationContent(
Stream deploymentManifestFileStream,
CancellationToken cancellationToken);
}