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

Add configuration validation #972

Merged
merged 1 commit into from
Nov 26, 2023
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
1 change: 1 addition & 0 deletions src/LondonTravel.Skill/AlexaFunction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ protected virtual void ConfigureServices(IServiceCollection services)
services.AddSingleton<AlexaSkill>();
services.AddSingleton<FunctionHandler>();
services.AddSingleton<IntentFactory>();
services.AddSingleton<IValidateOptions<SkillConfiguration>, ValidateSkillConfiguration>();
services.AddSingleton((_) => TelemetryConfiguration.CreateDefault());
services.AddSingleton(CreateTelemetryClient);
services.AddSingleton((p) => p.GetRequiredService<IOptions<SkillConfiguration>>().Value);
Expand Down
38 changes: 0 additions & 38 deletions src/LondonTravel.Skill/AlexaFunctionHandler.cs

This file was deleted.

8 changes: 5 additions & 3 deletions src/LondonTravel.Skill/FunctionEntrypoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,19 @@ public static class FunctionEntrypoint
/// <summary>
/// Runs the function using a custom runtime as an asynchronous operation.
/// </summary>
/// <typeparam name="T">The type of the function to execute.</typeparam>
/// <param name="httpClient">The optional HTTP client to use.</param>
/// <param name="cancellationToken">The optional cancellation token to use.</param>
/// <returns>
/// A <see cref="Task"/> representing the asynchronous operation to run the function.
/// </returns>
public static async Task RunAsync(
public static async Task RunAsync<T>(
HttpClient httpClient = null,
CancellationToken cancellationToken = default)
where T : AlexaFunction, new()
{
var serializer = new JsonSerializer();
await using var function = new AlexaFunction();
await using var function = new T();

using var bootstrap = LambdaBootstrapBuilder
.Create<SkillRequest, SkillResponse>(function.HandlerAsync, serializer)
Expand All @@ -47,5 +49,5 @@ public static async Task RunAsync(
/// A <see cref="Task"/> representing the asynchronous operation to run the custom runtime.
/// </returns>
[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
private static async Task Main() => await RunAsync();
private static async Task Main() => await RunAsync<AlexaFunction>();
}
5 changes: 5 additions & 0 deletions src/LondonTravel.Skill/SkillConfiguration.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright (c) Martin Costello, 2017. All rights reserved.
// Licensed under the Apache 2.0 license. See the LICENSE file in the project root for full license information.

using System.ComponentModel.DataAnnotations;

namespace MartinCostello.LondonTravel.Skill;

/// <summary>
Expand All @@ -16,6 +18,7 @@ public sealed class SkillConfiguration
/// <summary>
/// Gets or sets the URL for the skill API.
/// </summary>
[Required]
public string SkillApiUrl { get; set; } = string.Empty;

/// <summary>
Expand All @@ -26,11 +29,13 @@ public sealed class SkillConfiguration
/// <summary>
/// Gets or sets the TfL API application Id.
/// </summary>
[Required]
public string TflApplicationId { get; set; } = string.Empty;

/// <summary>
/// Gets or sets the TfL API application key.
/// </summary>
[Required]
public string TflApplicationKey { get; set; } = string.Empty;

/// <summary>
Expand Down
14 changes: 14 additions & 0 deletions src/LondonTravel.Skill/ValidateSkillConfiguration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright (c) Martin Costello, 2017. All rights reserved.
// Licensed under the Apache 2.0 license. See the LICENSE file in the project root for full license information.

using Microsoft.Extensions.Options;

namespace MartinCostello.LondonTravel.Skill;

/// <summary>
/// A class that validates instances of the <see cref="SkillConfiguration"/> class. This class cannot be inherited.
/// </summary>
[OptionsValidator]
internal sealed partial class ValidateSkillConfiguration : IValidateOptions<SkillConfiguration>
{
}
2 changes: 1 addition & 1 deletion src/LondonTravel.Skill/aws-lambda-tools-defaults.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"configuration": "Release",
"framework": "net8.0",
"function-architecture": "arm64",
"function-handler": "LondonTravel.Skill::MartinCostello.LondonTravel.Skill.AlexaFunctionHandler::HandleAsync",
"function-handler": "LondonTravel.Skill",
"function-memory-size": 192,
"function-runtime": "provided.al2023",
"function-timeout": 10
Expand Down
35 changes: 0 additions & 35 deletions test/LondonTravel.Skill.Tests/AlexaFunctionHandlerTests.cs

This file was deleted.

2 changes: 1 addition & 1 deletion test/LondonTravel.Skill.Tests/EndToEndTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ void Configure(IServiceCollection services)
using var httpClient = server.CreateClient();

// Act
await FunctionEntrypoint.RunAsync(httpClient, cancellationTokenSource.Token);
await FunctionEntrypoint.RunAsync<TestSettingsAlexaFunction>(httpClient, cancellationTokenSource.Token);

// Assert
context.Response.TryRead(out LambdaTestResponse result).ShouldBeTrue();
Expand Down
13 changes: 8 additions & 5 deletions test/LondonTravel.Skill.Tests/FunctionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,17 +119,20 @@ protected virtual SkillRequest CreateRequest<T>(T request = null)
return result;
}

private sealed class TestAlexaFunction(
HttpClientInterceptorOptions options,
ITestOutputHelper outputHelper) : AlexaFunction, ITestOutputHelperAccessor
protected class TestSettingsAlexaFunction() : AlexaFunction
{
public ITestOutputHelper OutputHelper { get; set; } = outputHelper;

protected override void Configure(ConfigurationBuilder builder)
{
base.Configure(builder);
builder.AddJsonFile("testsettings.json");
}
}

private sealed class TestAlexaFunction(
HttpClientInterceptorOptions options,
ITestOutputHelper outputHelper) : TestSettingsAlexaFunction, ITestOutputHelperAccessor
{
public ITestOutputHelper OutputHelper { get; set; } = outputHelper;

protected override void ConfigureServices(IServiceCollection services)
{
Expand Down
3 changes: 1 addition & 2 deletions test/LondonTravel.Skill.Tests/UnknownIntentTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ public class UnknownIntentTests(ITestOutputHelper outputHelper) : FunctionTests(
public async Task Can_Invoke_Function()
{
// Arrange
await using var function = new AlexaFunction();
await function.InitializeAsync();
AlexaFunction function = await CreateFunctionAsync();

SkillRequest request = CreateIntentRequest("FooIntent");

Expand Down