Skip to content

Commit

Permalink
Add FluxProvisioner (#14)
Browse files Browse the repository at this point in the history
* Added FluxProvisioner

* Update README Tree workflow to include Flux GitOps tooling dependency

* Refactor FluxProvisioner import statement

* Fix FluxProvisioner reconciliation

* Fix Flux_InstallsAndReconciles_KustomizationsAsync to use the kube context for all calls
  • Loading branch information
devantler authored Oct 15, 2024
1 parent 5364331 commit ecd912b
Show file tree
Hide file tree
Showing 10 changed files with 214 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AnalysisLevel>preview-all</AnalysisLevel>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<CodeAnalysisTreatWarningsAsErrors>false</CodeAnalysisTreatWarningsAsErrors>
</PropertyGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
namespace Devantler.KubernetesProvisioner.GitOps.Core;

/// <summary>
/// A Kubernetes GitOps provisioner.
/// </summary>
public interface IKubernetesGitOpsProvisioner
{
/// <summary>
/// The Kubernetes context.
/// </summary>
public string? Context { get; set; }
/// <summary>
/// Install the GitOps tooling on the Kubernetes cluster.
/// </summary>
public Task InstallAsync(CancellationToken cancellationToken = default);

/// <summary>
/// Uninstall the GitOps tooling from the Kubernetes cluster.
/// </summary>
public Task UninstallAsync(CancellationToken cancellationToken = default);

/// <summary>
/// Reconcile resources on the Kubernetes cluster.
/// </summary>
public Task ReconcileAsync(CancellationToken cancellationToken = default);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AnalysisLevel>preview-all</AnalysisLevel>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<CodeAnalysisTreatWarningsAsErrors>false</CodeAnalysisTreatWarningsAsErrors>
<UseCurrentRuntimeIdentifier>true</UseCurrentRuntimeIdentifier>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
<PackageReference Include="xunit" Version="2.9.2" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Devantler.KubernetesProvisioner.GitOps.Flux\Devantler.KubernetesProvisioner.GitOps.Flux.csproj" />
<ProjectReference Include="..\Devantler.KubernetesProvisioner.Cluster.Kind\Devantler.KubernetesProvisioner.Cluster.Kind.csproj" />
</ItemGroup>

<ItemGroup>
<Content Include="assets/kind-config.yaml" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>

<ItemGroup>
<Using Include="Xunit" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using Devantler.KindCLI;

namespace Devantler.KubernetesProvisioner.GitOps.Flux.Tests.FluxProvisionerTests;

/// <summary>
/// Tests for all methods in the <see cref="FluxProvisioner"/> class.
/// </summary>
[Collection("Flux")]
public class AllMethodsTests
{
/// <summary>
/// Test to verify that flux installs and reconciles kustomizations.
/// </summary>
/// <returns></returns>
[Fact]
public async Task Flux_InstallsAndReconciles_KustomizationsAsync()
{
// Arrange
string clusterName = "test-flux-cluster";
string context = "kind-" + clusterName;
string configPath = Path.Combine(AppContext.BaseDirectory, "assets/kind-config.yaml");
var fluxProvisioner = new FluxProvisioner(context);
var cancellationToken = new CancellationToken();

// Act
await Kind.DeleteClusterAsync(clusterName, cancellationToken);
await Kind.CreateClusterAsync(clusterName, configPath, cancellationToken);
await fluxProvisioner.InstallAsync(cancellationToken);
await FluxCLI.Flux.CreateOCISourceAsync("podinfo", new Uri("oci://ghcr.io/stefanprodan/manifests/podinfo"), context, cancellationToken: cancellationToken);
await FluxCLI.Flux.CreateKustomizationAsync("podinfo", "OCIRepository/podinfo", "", context, cancellationToken: cancellationToken);
await fluxProvisioner.ReconcileAsync(cancellationToken);
await fluxProvisioner.UninstallAsync(cancellationToken);

// Cleanup
await Kind.DeleteClusterAsync(clusterName, cancellationToken);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AnalysisLevel>preview-all</AnalysisLevel>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<CodeAnalysisTreatWarningsAsErrors>false</CodeAnalysisTreatWarningsAsErrors>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Devantler.FluxCLI" Version="0.0.4" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Devantler.KubernetesProvisioner.GitOps.Core\Devantler.KubernetesProvisioner.GitOps.Core.csproj" />
<ProjectReference Include="..\Devantler.KubernetesProvisioner.Resources.Native\Devantler.KubernetesProvisioner.Resources.Native.csproj" />
</ItemGroup>

</Project>
51 changes: 51 additions & 0 deletions Devantler.KubernetesProvisioner.GitOps.Flux/FluxProvisioner.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
using Devantler.KubernetesProvisioner.GitOps.Core;
using Devantler.KubernetesProvisioner.Resources.Native;
using k8s;
using k8s.Models;

namespace Devantler.KubernetesProvisioner.GitOps.Flux;

/// <summary>
/// A Kubernetes GitOps provisioner using Flux.
/// </summary>
/// <remarks>
/// Initializes a new instance of the <see cref="FluxProvisioner"/> class.
/// </remarks>
/// <param name="context"></param>
public class FluxProvisioner(string? context = default) : IKubernetesGitOpsProvisioner
{

/// <inheritdoc/>
public string? Context { get; set; } = context;

/// <summary>
/// Install Flux on the Kubernetes cluster.
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task InstallAsync(CancellationToken cancellationToken = default) =>
await FluxCLI.Flux.InstallAsync(Context, cancellationToken).ConfigureAwait(false);

/// <summary>
/// Reconcile resources on the Kubernetes cluster.
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task ReconcileAsync(CancellationToken cancellationToken = default)
{
using var kubernetesResourceProvisioner = new KubernetesResourceProvisioner(Context);
var kustomizations = await kubernetesResourceProvisioner.CustomObjects.ListNamespacedCustomObjectAsync<V1CustomResourceDefinitionList>("kustomize.toolkit.fluxcd.io", "v1", "flux-system", "kustomizations", cancellationToken: cancellationToken).ConfigureAwait(false);
foreach (var kustomization in kustomizations.Items)
{
await FluxCLI.Flux.ReconcileKustomizationAsync(kustomization.Metadata.Name, Context, withSource: true, cancellationToken: cancellationToken).ConfigureAwait(false);
}
}

/// <summary>
/// Uninstall Flux from the Kubernetes cluster.
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task UninstallAsync(CancellationToken cancellationToken = default) =>
await FluxCLI.Flux.UninstallAsync(Context, cancellationToken).ConfigureAwait(false);
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ namespace Devantler.KubernetesProvisioner.Resources.Native;
/// Initializes a new instance of the <see cref="KubernetesResourceProvisioner"/> class.
/// </remarks>
/// <param name="context"></param>
public sealed class KubernetesResourceProvisioner(string context) : Kubernetes(BuildConfig(context))
public sealed class KubernetesResourceProvisioner(string? context = default) : Kubernetes(BuildConfig(context))
{
static KubernetesClientConfiguration BuildConfig(string context)
static KubernetesClientConfiguration BuildConfig(string? context)
{
var kubeConfig = KubernetesClientConfiguration.LoadKubeConfig();
var config = KubernetesClientConfiguration.BuildConfigFromConfigObject(kubeConfig, context);
Expand Down
18 changes: 18 additions & 0 deletions Devantler.KubernetesProvisioner.sln
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Devantler.KubernetesProvisi
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Devantler.KubernetesProvisioner.Resources.Native.Tests", "Devantler.KubernetesProvisioner.Resources.Native.Tests\Devantler.KubernetesProvisioner.Resources.Native.Tests.csproj", "{0F5FB874-6689-4466-914B-BBA2E9EB9C26}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Devantler.KubernetesProvisioner.GitOps.Flux", "Devantler.KubernetesProvisioner.GitOps.Flux\Devantler.KubernetesProvisioner.GitOps.Flux.csproj", "{2AC5B5A3-B138-42B9-86A9-ECC9BA3E165A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Devantler.KubernetesProvisioner.GitOps.Core", "Devantler.KubernetesProvisioner.GitOps.Core\Devantler.KubernetesProvisioner.GitOps.Core.csproj", "{271CB43E-D09A-4448-A8DD-79BCE5798555}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Devantler.KubernetesProvisioner.GitOps.Flux.Tests", "Devantler.KubernetesProvisioner.GitOps.Flux.Tests\Devantler.KubernetesProvisioner.GitOps.Flux.Tests.csproj", "{4BF9F996-B03B-434A-B913-8406BEE3A5CE}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -54,5 +60,17 @@ Global
{0F5FB874-6689-4466-914B-BBA2E9EB9C26}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0F5FB874-6689-4466-914B-BBA2E9EB9C26}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0F5FB874-6689-4466-914B-BBA2E9EB9C26}.Release|Any CPU.Build.0 = Release|Any CPU
{2AC5B5A3-B138-42B9-86A9-ECC9BA3E165A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2AC5B5A3-B138-42B9-86A9-ECC9BA3E165A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2AC5B5A3-B138-42B9-86A9-ECC9BA3E165A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2AC5B5A3-B138-42B9-86A9-ECC9BA3E165A}.Release|Any CPU.Build.0 = Release|Any CPU
{271CB43E-D09A-4448-A8DD-79BCE5798555}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{271CB43E-D09A-4448-A8DD-79BCE5798555}.Debug|Any CPU.Build.0 = Debug|Any CPU
{271CB43E-D09A-4448-A8DD-79BCE5798555}.Release|Any CPU.ActiveCfg = Release|Any CPU
{271CB43E-D09A-4448-A8DD-79BCE5798555}.Release|Any CPU.Build.0 = Release|Any CPU
{4BF9F996-B03B-434A-B913-8406BEE3A5CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4BF9F996-B03B-434A-B913-8406BEE3A5CE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4BF9F996-B03B-434A-B913-8406BEE3A5CE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4BF9F996-B03B-434A-B913-8406BEE3A5CE}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Simple provisioners that can provision Kubernetes and Kubernetes resources.
<summary>Show/hide folder structure</summary>

<!-- readme-tree start -->

```
.
├── .github
Expand All @@ -30,6 +31,7 @@ Simple provisioners that can provision Kubernetes and Kubernetes resources.
15 directories
```

<!-- readme-tree end -->

</details>
Expand All @@ -49,6 +51,9 @@ dotnet add package Devantler.KubernetesProvisioner.Cluster.K3d
# For provisioning a Kind cluster
dotnet add package Devantler.KubernetesProvisioner.Cluster.Kind

# For provisioning Flux GitOps tooling
dotnet add package Devantler.KubernetesProvisioner.GitOps.Flux

# For provisioning native Kubernetes resources
dotnet add package Devantler.KubernetesProvisioner.Resources.Native
```
Expand Down

0 comments on commit ecd912b

Please sign in to comment.