Skip to content

Commit 307cc55

Browse files
committed
refactor(finalizer): Use scoped finalizer.
BREAKING CHANGE: Refactoring of the finalizer logic. Same as with the controller, the finalizer are now instantiated via dependency injection in a scope. As soon as a finalization request happens, the finalizer manager will search for the adequate finalizer and call it. The new way of registering finalizer is via the `IFinalizerManager` to attach a finalizer to an entity.
1 parent 17d636f commit 307cc55

19 files changed

+462
-457
lines changed

build/Build.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,7 @@ class Build : NukeBuild
8181
.SetVersion(Version)
8282
.SetPackageReleaseNotes(PackageReleaseNotes)
8383
.SetOutputDirectory(ArtifactsDirectory)
84-
.CombineWith(Projects, (ss, proj) => ss
85-
.SetProject(proj))));
84+
.SetProject(Solution)));
8685

8786
Target Publish => _ => _
8887
.Requires(

build/_build.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
<NukeRootDirectory>..</NukeRootDirectory>
99
<NukeScriptDirectory>..</NukeScriptDirectory>
1010
<LangVersion>9</LangVersion>
11+
<IsPackable>false</IsPackable>
1112
</PropertyGroup>
1213

1314
<ItemGroup>

src/KubeOps.Testing/KubernetesOperatorFactory.cs

Lines changed: 79 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
using DotnetKubernetesClient;
33
using k8s;
44
using k8s.Models;
5-
using KubeOps.Operator.Queue;
65
using Microsoft.AspNetCore.Hosting;
76
using Microsoft.AspNetCore.Mvc.Testing;
87
using Microsoft.AspNetCore.TestHost;
@@ -17,83 +16,83 @@ namespace KubeOps.Testing
1716
/// Operator factory for testing an operator created with the asp web server.
1817
/// </summary>
1918
/// <typeparam name="TTestStartup">Type of the Startup type (see asp.net).</typeparam>
20-
public class KubernetesOperatorFactory<TTestStartup> : WebApplicationFactory<TTestStartup>
21-
where TTestStartup : class
22-
{
23-
private string? _solutionRelativeContentRoot;
24-
25-
/// <summary>
26-
/// Return a mocked kubernetes client. This client defines
27-
/// no-op for all related methods.
28-
/// </summary>
29-
public MockKubernetesClient MockedKubernetesClient =>
30-
Services.GetRequiredService<IKubernetesClient>() as MockKubernetesClient ??
31-
throw new ArgumentException("Wrong kubernetes client registered.");
32-
33-
/// <summary>
34-
/// Set a specific content root path to the given factory.
35-
/// </summary>
36-
/// <param name="root"></param>
37-
/// <returns></returns>
38-
public KubernetesOperatorFactory<TTestStartup> WithSolutionRelativeContentRoot(string root)
39-
{
40-
_solutionRelativeContentRoot = root;
41-
return this;
42-
}
43-
44-
/// <summary>
45-
/// Start the server.
46-
/// </summary>
47-
public void Run()
48-
{
49-
// This triggers "EnsureServer()" in the base class.
50-
var server = Server;
51-
}
52-
53-
/// <summary>
54-
/// Return a mocked event queue for the given entity.
55-
/// </summary>
56-
/// <typeparam name="TEntity">The type of the entity.</typeparam>
57-
/// <returns>A mocked event queue for the given type.</returns>
58-
public MockResourceEventQueue<TEntity> GetMockedEventQueue<TEntity>()
59-
where TEntity : IKubernetesObject<V1ObjectMeta>
60-
=> Services.GetRequiredService<MockResourceQueueCollection>().Get<TEntity>();
61-
62-
/// <summary>
63-
/// Create the host builder. Needed for the factory.
64-
/// </summary>
65-
/// <returns></returns>
66-
protected override IHostBuilder CreateHostBuilder() =>
67-
Host.CreateDefaultBuilder()
68-
.ConfigureWebHostDefaults(
69-
webBuilder => webBuilder
70-
.UseStartup<TTestStartup>());
71-
72-
/// <summary>
73-
/// Configure the web-host.
74-
/// This registers the mocked client as well as mocked
75-
/// event queues.
76-
/// </summary>
77-
/// <param name="builder">The web host builder.</param>
78-
protected override void ConfigureWebHost(IWebHostBuilder builder)
79-
{
80-
base.ConfigureWebHost(builder);
81-
if (_solutionRelativeContentRoot != null)
82-
{
83-
builder.UseSolutionRelativeContentRoot(_solutionRelativeContentRoot);
84-
}
85-
86-
builder.ConfigureTestServices(
87-
services =>
88-
{
89-
services.RemoveAll(typeof(IResourceEventQueue<>));
90-
services.AddTransient(typeof(IResourceEventQueue<>), typeof(MockResourceEventQueue<>));
91-
services.AddSingleton<MockResourceQueueCollection>();
92-
93-
services.RemoveAll(typeof(IKubernetesClient));
94-
services.AddSingleton<IKubernetesClient, MockKubernetesClient>();
95-
});
96-
builder.ConfigureLogging(logging => logging.ClearProviders());
97-
}
98-
}
19+
// public class KubernetesOperatorFactory<TTestStartup> : WebApplicationFactory<TTestStartup>
20+
// where TTestStartup : class
21+
// {
22+
// private string? _solutionRelativeContentRoot;
23+
//
24+
// /// <summary>
25+
// /// Return a mocked kubernetes client. This client defines
26+
// /// no-op for all related methods.
27+
// /// </summary>
28+
// public MockKubernetesClient MockedKubernetesClient =>
29+
// Services.GetRequiredService<IKubernetesClient>() as MockKubernetesClient ??
30+
// throw new ArgumentException("Wrong kubernetes client registered.");
31+
//
32+
// /// <summary>
33+
// /// Set a specific content root path to the given factory.
34+
// /// </summary>
35+
// /// <param name="root"></param>
36+
// /// <returns></returns>
37+
// public KubernetesOperatorFactory<TTestStartup> WithSolutionRelativeContentRoot(string root)
38+
// {
39+
// _solutionRelativeContentRoot = root;
40+
// return this;
41+
// }
42+
//
43+
// /// <summary>
44+
// /// Start the server.
45+
// /// </summary>
46+
// public void Run()
47+
// {
48+
// // This triggers "EnsureServer()" in the base class.
49+
// var server = Server;
50+
// }
51+
//
52+
// /// <summary>
53+
// /// Return a mocked event queue for the given entity.
54+
// /// </summary>
55+
// /// <typeparam name="TEntity">The type of the entity.</typeparam>
56+
// /// <returns>A mocked event queue for the given type.</returns>
57+
// public MockResourceEventQueue<TEntity> GetMockedEventQueue<TEntity>()
58+
// where TEntity : IKubernetesObject<V1ObjectMeta>
59+
// => Services.GetRequiredService<MockResourceQueueCollection>().Get<TEntity>();
60+
//
61+
// /// <summary>
62+
// /// Create the host builder. Needed for the factory.
63+
// /// </summary>
64+
// /// <returns></returns>
65+
// protected override IHostBuilder CreateHostBuilder() =>
66+
// Host.CreateDefaultBuilder()
67+
// .ConfigureWebHostDefaults(
68+
// webBuilder => webBuilder
69+
// .UseStartup<TTestStartup>());
70+
//
71+
// /// <summary>
72+
// /// Configure the web-host.
73+
// /// This registers the mocked client as well as mocked
74+
// /// event queues.
75+
// /// </summary>
76+
// /// <param name="builder">The web host builder.</param>
77+
// protected override void ConfigureWebHost(IWebHostBuilder builder)
78+
// {
79+
// base.ConfigureWebHost(builder);
80+
// if (_solutionRelativeContentRoot != null)
81+
// {
82+
// builder.UseSolutionRelativeContentRoot(_solutionRelativeContentRoot);
83+
// }
84+
//
85+
// builder.ConfigureTestServices(
86+
// services =>
87+
// {
88+
// // services.RemoveAll(typeof(IResourceEventQueue<>));
89+
// // services.AddTransient(typeof(IResourceEventQueue<>), typeof(MockResourceEventQueue<>));
90+
// // services.AddSingleton<MockResourceQueueCollection>();
91+
//
92+
// services.RemoveAll(typeof(IKubernetesClient));
93+
// services.AddSingleton<IKubernetesClient, MockKubernetesClient>();
94+
// });
95+
// builder.ConfigureLogging(logging => logging.ClearProviders());
96+
// }
97+
// }
9998
}
Lines changed: 96 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,4 @@
1-
using System;
2-
using System.Collections.Generic;
3-
using System.Threading.Tasks;
4-
using k8s;
5-
using k8s.Models;
6-
using KubeOps.Operator.Queue;
7-
8-
namespace KubeOps.Testing
1+
namespace KubeOps.Testing
92
{
103
/// <summary>
114
/// Mocked resource event queue.
@@ -18,99 +11,99 @@ namespace KubeOps.Testing
1811
/// queue.Created(new V1TestEntity());
1912
/// </example>
2013
/// <typeparam name="TEntity"></typeparam>
21-
public class MockResourceEventQueue<TEntity> : IResourceEventQueue<TEntity>
22-
where TEntity : IKubernetesObject<V1ObjectMeta>
23-
{
24-
private readonly MockResourceQueueCollection _collection;
25-
26-
public MockResourceEventQueue(MockResourceQueueCollection collection)
27-
{
28-
_collection = collection;
29-
}
30-
31-
/// <inheritdoc />
32-
public event EventHandler<(ResourceEventType Type, TEntity Resource)>? ResourceEvent;
33-
34-
/// <summary>
35-
/// List of enqueued entities.
36-
/// </summary>
37-
public IList<TEntity> Enqueued { get; } = new List<TEntity>();
38-
39-
/// <summary>
40-
/// List of enqueued errors.
41-
/// </summary>
42-
public IList<(ResourceEventType Type, TEntity Resource)> ErrorEnqueued { get; } =
43-
new List<(ResourceEventType, TEntity)>();
44-
45-
public void Dispose()
46-
{
47-
}
48-
49-
/// <inheritdoc />
50-
public Task Start()
51-
{
52-
_collection.Register(this);
53-
return Task.CompletedTask;
54-
}
55-
56-
/// <inheritdoc />
57-
public Task Stop()
58-
{
59-
_collection.Unregister(this);
60-
return Task.CompletedTask;
61-
}
62-
63-
/// <summary>
64-
/// Fire a (mocked) <see cref="ResourceEventType.Created"/> event.
65-
/// </summary>
66-
/// <param name="entity">The entity that fires the event.</param>
67-
public void Created(TEntity entity) => Fire(ResourceEventType.Created, entity);
68-
69-
/// <summary>
70-
/// Fire a (mocked) <see cref="ResourceEventType.Updated"/> event.
71-
/// </summary>
72-
/// <param name="entity">The entity that fires the event.</param>
73-
public void Updated(TEntity entity) => Fire(ResourceEventType.Updated, entity);
74-
75-
/// <summary>
76-
/// Fire a (mocked) <see cref="ResourceEventType.Deleted"/> event.
77-
/// </summary>
78-
/// <param name="entity">The entity that fires the event.</param>
79-
public void Deleted(TEntity entity) => Fire(ResourceEventType.Deleted, entity);
80-
81-
/// <summary>
82-
/// Fire a (mocked) <see cref="ResourceEventType.NotModified"/> event.
83-
/// </summary>
84-
/// <param name="entity">The entity that fires the event.</param>
85-
public void NotModified(TEntity entity) => Fire(ResourceEventType.NotModified, entity);
86-
87-
/// <summary>
88-
/// Fire a (mocked) <see cref="ResourceEventType.StatusUpdated"/> event.
89-
/// </summary>
90-
/// <param name="entity">The entity that fires the event.</param>
91-
public void StatusUpdated(TEntity entity) => Fire(ResourceEventType.StatusUpdated, entity);
92-
93-
/// <summary>
94-
/// Fire a (mocked) <see cref="ResourceEventType.Finalizing"/> event.
95-
/// </summary>
96-
/// <param name="entity">The entity that fires the event.</param>
97-
public void Finalizing(TEntity entity) => Fire(ResourceEventType.Finalizing, entity);
98-
99-
/// <inheritdoc />
100-
public Task Enqueue(TEntity resource, TimeSpan? enqueueDelay = null)
101-
{
102-
Enqueued.Add(resource);
103-
return Task.CompletedTask;
104-
}
105-
106-
/// <inheritdoc />
107-
public void EnqueueErrored(ResourceEventType type, TEntity resource) => ErrorEnqueued.Add((type, resource));
108-
109-
/// <inheritdoc />
110-
public void ClearError(TEntity resource)
111-
{
112-
}
113-
114-
private void Fire(ResourceEventType type, TEntity entity) => ResourceEvent?.Invoke(this, (type, entity));
115-
}
14+
// public class MockResourceEventQueue<TEntity> : IResourceEventQueue<TEntity>
15+
// where TEntity : IKubernetesObject<V1ObjectMeta>
16+
// {
17+
// private readonly MockResourceQueueCollection _collection;
18+
//
19+
// public MockResourceEventQueue(MockResourceQueueCollection collection)
20+
// {
21+
// _collection = collection;
22+
// }
23+
//
24+
// /// <inheritdoc />
25+
// public event EventHandler<(ResourceEventType Type, TEntity Resource)>? ResourceEvent;
26+
//
27+
// /// <summary>
28+
// /// List of enqueued entities.
29+
// /// </summary>
30+
// public IList<TEntity> Enqueued { get; } = new List<TEntity>();
31+
//
32+
// /// <summary>
33+
// /// List of enqueued errors.
34+
// /// </summary>
35+
// public IList<(ResourceEventType Type, TEntity Resource)> ErrorEnqueued { get; } =
36+
// new List<(ResourceEventType, TEntity)>();
37+
//
38+
// public void Dispose()
39+
// {
40+
// }
41+
//
42+
// /// <inheritdoc />
43+
// public Task Start()
44+
// {
45+
// _collection.Register(this);
46+
// return Task.CompletedTask;
47+
// }
48+
//
49+
// /// <inheritdoc />
50+
// public Task Stop()
51+
// {
52+
// _collection.Unregister(this);
53+
// return Task.CompletedTask;
54+
// }
55+
//
56+
// /// <summary>
57+
// /// Fire a (mocked) <see cref="ResourceEventType.Created"/> event.
58+
// /// </summary>
59+
// /// <param name="entity">The entity that fires the event.</param>
60+
// public void Created(TEntity entity) => Fire(ResourceEventType.Created, entity);
61+
//
62+
// /// <summary>
63+
// /// Fire a (mocked) <see cref="ResourceEventType.Updated"/> event.
64+
// /// </summary>
65+
// /// <param name="entity">The entity that fires the event.</param>
66+
// public void Updated(TEntity entity) => Fire(ResourceEventType.Updated, entity);
67+
//
68+
// /// <summary>
69+
// /// Fire a (mocked) <see cref="ResourceEventType.Deleted"/> event.
70+
// /// </summary>
71+
// /// <param name="entity">The entity that fires the event.</param>
72+
// public void Deleted(TEntity entity) => Fire(ResourceEventType.Deleted, entity);
73+
//
74+
// /// <summary>
75+
// /// Fire a (mocked) <see cref="ResourceEventType.NotModified"/> event.
76+
// /// </summary>
77+
// /// <param name="entity">The entity that fires the event.</param>
78+
// public void NotModified(TEntity entity) => Fire(ResourceEventType.NotModified, entity);
79+
//
80+
// /// <summary>
81+
// /// Fire a (mocked) <see cref="ResourceEventType.StatusUpdated"/> event.
82+
// /// </summary>
83+
// /// <param name="entity">The entity that fires the event.</param>
84+
// public void StatusUpdated(TEntity entity) => Fire(ResourceEventType.StatusUpdated, entity);
85+
//
86+
// /// <summary>
87+
// /// Fire a (mocked) <see cref="ResourceEventType.Finalizing"/> event.
88+
// /// </summary>
89+
// /// <param name="entity">The entity that fires the event.</param>
90+
// public void Finalizing(TEntity entity) => Fire(ResourceEventType.Finalizing, entity);
91+
//
92+
// /// <inheritdoc />
93+
// public Task Enqueue(TEntity resource, TimeSpan? enqueueDelay = null)
94+
// {
95+
// Enqueued.Add(resource);
96+
// return Task.CompletedTask;
97+
// }
98+
//
99+
// /// <inheritdoc />
100+
// public void EnqueueErrored(ResourceEventType type, TEntity resource) => ErrorEnqueued.Add((type, resource));
101+
//
102+
// /// <inheritdoc />
103+
// public void ClearError(TEntity resource)
104+
// {
105+
// }
106+
//
107+
// private void Fire(ResourceEventType type, TEntity entity) => ResourceEvent?.Invoke(this, (type, entity));
108+
// }
116109
}

0 commit comments

Comments
 (0)