-
-
Notifications
You must be signed in to change notification settings - Fork 57
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: initial version of the dotnet operator sdk (DOS)
- Loading branch information
0 parents
commit c34676c
Showing
56 changed files
with
3,082 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# User-specific files | ||
*.suo | ||
*.user | ||
*.userosscache | ||
*.sln.docstates | ||
|
||
# Ci things | ||
node_modules/ | ||
tools/ | ||
nuget/ | ||
artifacts/ | ||
coverage/ | ||
.tmp/ | ||
|
||
# Build results | ||
[Dd]ebug/ | ||
[Dd]ebugPublic/ | ||
[Rr]elease/ | ||
[Rr]eleases/ | ||
x64/ | ||
x86/ | ||
bld/ | ||
[Bb]in/ | ||
[Oo]bj/ | ||
[Oo]ut/ | ||
|
||
# Testing results | ||
coverage.json | ||
coverage.info |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
|
||
Microsoft Visual Studio Solution File, Format Version 12.00 | ||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{95F3A6DD-B421-441D-B263-1B34A1465FF5}" | ||
EndProject | ||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dos", "src\Dos\Dos.csproj", "{D7AB6CB9-94B6-4FEB-B7D8-D8AA793BD2A4}" | ||
EndProject | ||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{50E9B964-68F7-4B9F-BEA8-165CE45BC5C6}" | ||
EndProject | ||
Global | ||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||
Debug|Any CPU = Debug|Any CPU | ||
Release|Any CPU = Release|Any CPU | ||
EndGlobalSection | ||
GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||
{D7AB6CB9-94B6-4FEB-B7D8-D8AA793BD2A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{D7AB6CB9-94B6-4FEB-B7D8-D8AA793BD2A4}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{D7AB6CB9-94B6-4FEB-B7D8-D8AA793BD2A4}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{D7AB6CB9-94B6-4FEB-B7D8-D8AA793BD2A4}.Release|Any CPU.Build.0 = Release|Any CPU | ||
EndGlobalSection | ||
GlobalSection(NestedProjects) = preSolution | ||
{D7AB6CB9-94B6-4FEB-B7D8-D8AA793BD2A4} = {95F3A6DD-B421-441D-B263-1B34A1465FF5} | ||
EndGlobalSection | ||
EndGlobal |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
<Project> | ||
<PropertyGroup> | ||
<!-- Configuration for Docker related commands--> | ||
<DosDockerfilePath Condition="'$(DosDockerfilePath)' == '' And '$(SolutionDir)' != '' ">$(SolutionDir)Dockerfile</DosDockerfilePath> | ||
<DosDockerfilePath Condition="'$(DosDockerfilePath)' == '' And '$(SolutionDir)' == '' ">$(MSBuildProjectDirectory)\Dockerfile</DosDockerfilePath> | ||
<DosDockerTag Condition="'$(DosDockerTag)' == ''">latest</DosDockerTag> | ||
</PropertyGroup> | ||
|
||
<PropertyGroup> | ||
<!-- Configuration for the pathes where to store the generated yamls and elements --> | ||
<DosConfigRoot Condition="'$(DosConfigRoot)' == '' And '$(SolutionDir)' != '' ">$(SolutionDir)config</DosConfigRoot> | ||
<DosConfigRoot Condition="'$(DosConfigRoot)' == '' And '$(SolutionDir)' == '' ">$(MSBuildProjectDirectory)\config</DosConfigRoot> | ||
</PropertyGroup> | ||
|
||
<PropertyGroup> | ||
<!-- Configuration for the crd generation --> | ||
<DosCrdDir Condition="'$(DosCrdDir)' == ''">$(DosConfigRoot)\crds</DosCrdDir> | ||
<DosCrdFormat Condition="'$(DosCrdFormat)' == ''">Yaml</DosCrdFormat> | ||
<DosCrdUseOldCrds Condition="'$(DosCrdUseOldCrds)' == ''">false</DosCrdUseOldCrds> | ||
</PropertyGroup> | ||
|
||
<PropertyGroup> | ||
<!-- Configuration for the rbac generation --> | ||
<DosRbacDir Condition="'$(DosRbacDir)' == ''">$(DosConfigRoot)\rbac</DosRbacDir> | ||
<DosRbacFormat Condition="'$(DosRbacFormat)' == ''">Yaml</DosRbacFormat> | ||
</PropertyGroup> | ||
|
||
<PropertyGroup> | ||
<!-- Configuration for the operator manifest generation --> | ||
<DosOperatorDir Condition="'$(DosOperatorDir)' == ''">$(DosConfigRoot)\operator</DosOperatorDir> | ||
<DosOperatorFormat Condition="'$(DosOperatorFormat)' == ''">Yaml</DosOperatorFormat> | ||
</PropertyGroup> | ||
|
||
<PropertyGroup> | ||
<!-- Configuration for the installer manifest generation --> | ||
<DosInstallerDir Condition="'$(DosInstallerDir)' == ''">$(DosConfigRoot)\install</DosInstallerDir> | ||
<DosInstallerFormat Condition="'$(DosInstallerFormat)' == ''">Yaml</DosInstallerFormat> | ||
</PropertyGroup> | ||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
<Project DefaultTargets="GenerateAfterBuild"> | ||
<Target Name="GenerateDockerfile"> | ||
<Message Text="Generating Dockerfile" Importance="high"/> | ||
<Message Text="Dockerfile path: $(DosDockerfilePath)" Importance="normal"/> | ||
|
||
<Message Condition="Exists('$(DosDockerfilePath)')" Text="Dockerfile already exists. Don't overwrite." Importance="high"/> | ||
<Exec Condition="!Exists('$(DosDockerfilePath)')" | ||
Command="dotnet $(OutputPath)$(TargetFileName) generator docker --out $(DosDockerfilePath) --dotnet-tag $(DosDockerTag) --solution-dir $(SolutionDir) --target-file $(TargetFileName) --project-path $(ProjectPath)"/> | ||
</Target> | ||
|
||
<Target Name="GenerateCrds"> | ||
<Message Text="Generating CRDs" Importance="high"/> | ||
<Message Text="Configuration path: $(DosCrdDir)" Importance="normal"/> | ||
|
||
<Exec Condition="'$(DosCrdUseOldCrds)' == 'false'" Command="dotnet $(OutputPath)$(TargetFileName) generator crds --out $(DosCrdDir) --format $(DosCrdFormat)"/> | ||
<Exec Condition="'$(DosCrdUseOldCrds)' == 'true'" Command="dotnet $(OutputPath)$(TargetFileName) generator crds --out $(DosCrdDir) --format $(DosCrdFormat) --use-old-crds"/> | ||
</Target> | ||
|
||
<Target Name="GenerateRbac"> | ||
<Message Text="Generating Rbac roles" Importance="high"/> | ||
<Message Text="Configuration path: $(DosRbacDir)" Importance="normal"/> | ||
|
||
<Exec Command="dotnet $(OutputPath)$(TargetFileName) generator rbac --out $(DosRbacDir) --format $(DosRbacFormat)"/> | ||
</Target> | ||
|
||
<Target Name="GenerateOperator"> | ||
<Message Text="Generating Operator yamls" Importance="high"/> | ||
<Message Text="Configuration path: $(DosOperatorDir)" Importance="normal"/> | ||
|
||
<Exec Command="dotnet $(OutputPath)$(TargetFileName) generator operator --out $(DosOperatorDir) --format $(DosOperatorFormat)"/> | ||
</Target> | ||
|
||
<Target Name="GenerateInstaller"> | ||
<Message Text="Generating Installer yamls" Importance="high"/> | ||
<Message Text="Configuration path: $(DosInstallerDir)" Importance="normal"/> | ||
|
||
<Message Condition="Exists('$(DosInstallerDir)')" Text="Installer dir exists, don't overwrite contents." Importance="high"/> | ||
<Exec Condition="!Exists('$(DosInstallerDir)')" | ||
Command="dotnet $(OutputPath)$(TargetFileName) generator installer --out $(DosInstallerDir) --format $(DosInstallerFormat) --crds-dir $(DosCrdDir) --rbac-dir $(DosRbacDir) --operator-dir $(DosOperatorDir)"/> | ||
</Target> | ||
|
||
<Target Name="GenerateAfterBuild" AfterTargets="Build"> | ||
<CallTarget Condition="'$(DosSkipDockerfile)' == ''" Targets="GenerateDockerfile"/> | ||
<CallTarget Condition="'$(DosSkipCrds)' == ''" Targets="GenerateCrds"/> | ||
<CallTarget Condition="'$(DosSkipRbac)' == ''" Targets="GenerateRbac"/> | ||
<CallTarget Condition="'$(DosSkipOperator)' == ''" Targets="GenerateOperator"/> | ||
<CallTarget Condition="'$(DosSkipInstaller)' == ''" Targets="GenerateInstaller"/> | ||
</Target> | ||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
using System.Threading.Tasks; | ||
using Dos.Operator; | ||
|
||
namespace Dos.Build | ||
{ | ||
internal static class Program | ||
{ | ||
public static Task Main(string[] args) => new KubernetesOperator().Run(args); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
<Project Sdk="Microsoft.NET.Sdk.Web"> | ||
|
||
<PropertyGroup> | ||
<OutputType>exe</OutputType> | ||
<TargetFramework>netcoreapp3.1</TargetFramework> | ||
<Nullable>enable</Nullable> | ||
<LangVersion>8</LangVersion> | ||
</PropertyGroup> | ||
|
||
<PropertyGroup> | ||
<IsPackable>true</IsPackable> | ||
<PackageId>DotnetOperatorSdk</PackageId> | ||
<PackageTags>Kubernetes Operator SDK CustomResourceDefinition</PackageTags> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="CompareNETObjects" Version="4.66.0" /> | ||
<PackageReference Include="KubernetesClient" Version="2.0.18" /> | ||
<PackageReference Include="McMaster.Extensions.CommandLineUtils" Version="3.0.0" /> | ||
<PackageReference Include="McMaster.Extensions.Hosting.CommandLine" Version="3.0.0" /> | ||
<PackageReference Include="YamlDotNet" Version="8.1.1" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<Content Include="Build\DotnetOperatorSdk.props"> | ||
<PackagePath>build\</PackagePath> | ||
</Content> | ||
<Content Include="Build\DotnetOperatorSdk.targets"> | ||
<PackagePath>build\</PackagePath> | ||
</Content> | ||
</ItemGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
namespace Dos.Operator.Caching | ||
{ | ||
internal enum CacheComparisonResult | ||
{ | ||
New, | ||
Modified, | ||
StatusModified, | ||
FinalizersModified, | ||
NotModified, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using Dos.Operator.Entities; | ||
using k8s; | ||
using k8s.Models; | ||
using KellermanSoftware.CompareNetObjects; | ||
|
||
namespace Dos.Operator.Caching | ||
{ | ||
internal class EntityCache<TEntity> | ||
where TEntity : IKubernetesObject<V1ObjectMeta> | ||
{ | ||
private const string ResourceVersion = "ResourceVersion"; | ||
private const string Finalizers = "Metadata.Finalizers"; | ||
private const string Status = "Status"; | ||
|
||
private readonly CompareLogic _compare = new CompareLogic( | ||
new ComparisonConfig | ||
{ | ||
Caching = true, | ||
AutoClearCache = false, | ||
MembersToIgnore = new List<string> { ResourceVersion }, | ||
}); | ||
|
||
private readonly IDictionary<string, TEntity> _cache = new Dictionary<string, TEntity>(); | ||
|
||
public TEntity Get(string id) => _cache[id]; | ||
|
||
public TEntity Upsert(TEntity resource, out CacheComparisonResult result) | ||
{ | ||
result = CompareCache(resource); | ||
|
||
if (result == CacheComparisonResult.New) | ||
{ | ||
_cache.Add(resource.Metadata.Uid, resource.DeepClone()); | ||
} | ||
else | ||
{ | ||
_cache[resource.Metadata.Uid] = resource.DeepClone(); | ||
} | ||
|
||
return resource; | ||
} | ||
|
||
private CacheComparisonResult CompareCache(TEntity resource) | ||
{ | ||
if (!Exists(resource)) | ||
{ | ||
return CacheComparisonResult.New; | ||
} | ||
|
||
var cacheObject = _cache[resource.Metadata.Uid]; | ||
var comparison = _compare.Compare(resource, cacheObject); | ||
if (comparison.AreEqual) | ||
{ | ||
return CacheComparisonResult.NotModified; | ||
} | ||
|
||
if (comparison.Differences.All(d => d.ParentPropertyName == Status)) | ||
{ | ||
return CacheComparisonResult.StatusModified; | ||
} | ||
|
||
if (comparison.Differences.All(d => d.PropertyName == Finalizers)) | ||
{ | ||
return CacheComparisonResult.FinalizersModified; | ||
} | ||
|
||
return CacheComparisonResult.Modified; | ||
} | ||
|
||
public void Remove(TEntity resource) => Remove(resource.Metadata.Uid); | ||
|
||
public void Clear() => _cache.Clear(); | ||
|
||
private bool Exists(TEntity resource) => _cache.ContainsKey(resource.Metadata.Uid); | ||
|
||
private bool Exists(string id) => _cache.ContainsKey(id); | ||
|
||
private void Remove(string resourceUid) => _cache.Remove(resourceUid); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
using System; | ||
using System.Linq; | ||
using System.Net.Http; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
namespace Dos.Operator.Client | ||
{ | ||
internal class ClientUrlFixer : DelegatingHandler | ||
{ | ||
protected override async Task<HttpResponseMessage> SendAsync( | ||
HttpRequestMessage request, | ||
CancellationToken cancellationToken) | ||
{ | ||
if (request.RequestUri.Segments.Count(s => s == "/") > 1) | ||
{ | ||
// This request uri contains "empty" segments. (i.e. https://.../apis//v1/...) | ||
// This means, this is a default api group (/api/v1) | ||
var builder = new UriBuilder(request.RequestUri); | ||
builder.Path = builder.Path.Replace("//", "/").Replace("apis", "api"); | ||
request.RequestUri = builder.Uri; | ||
} | ||
|
||
return await base.SendAsync(request, cancellationToken); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Dos.Operator.Client.LabelSelectors; | ||
using k8s; | ||
using k8s.Models; | ||
|
||
namespace Dos.Operator.Client | ||
{ | ||
public interface IKubernetesClient | ||
{ | ||
IKubernetes ApiClient { get; } | ||
|
||
Task<TResource?> Get<TResource>(string name, string? @namespace = null) | ||
where TResource : class, IKubernetesObject<V1ObjectMeta>; | ||
|
||
// Task<TResource?> Get<TResource>(string name, string? @namespace = null, TResource? requireClass = null) | ||
// where TResource : class, IKubernetesObject<V1ObjectMeta>; | ||
|
||
// Task<TResource> Get<TResource>(string name, string? @namespace = null, TResource? requireStruct = null) | ||
// where TResource : struct, IKubernetesObject<V1ObjectMeta>; | ||
|
||
Task<IList<TResource>> List<TResource>( | ||
string? @namespace = null, | ||
string? labelSelector = null) | ||
where TResource : IKubernetesObject<V1ObjectMeta>; | ||
|
||
Task<IList<TResource>> List<TResource>( | ||
string? @namespace = null, | ||
params ILabelSelector[] labelSelectors) | ||
where TResource : IKubernetesObject<V1ObjectMeta>; | ||
|
||
Task<TResource> Save<TResource>(TResource resource) | ||
where TResource : class, IKubernetesObject<V1ObjectMeta>; | ||
|
||
Task<TResource> Create<TResource>(TResource resource) | ||
where TResource : IKubernetesObject<V1ObjectMeta>; | ||
|
||
Task<TResource> Update<TResource>(TResource resource) | ||
where TResource : IKubernetesObject<V1ObjectMeta>; | ||
|
||
public Task UpdateStatus<TStatus>(IStatus<TStatus> resource); | ||
|
||
Task Delete<TResource>(TResource resource) | ||
where TResource : IKubernetesObject<V1ObjectMeta>; | ||
|
||
Task Delete<TResource>(IEnumerable<TResource> resources) | ||
where TResource : IKubernetesObject<V1ObjectMeta>; | ||
|
||
Task Delete<TResource>(params TResource[] resources) | ||
where TResource : IKubernetesObject<V1ObjectMeta>; | ||
|
||
Task Delete<TResource>(string name, string? @namespace = null) | ||
where TResource : IKubernetesObject<V1ObjectMeta>; | ||
|
||
Task<Watcher<TResource>> Watch<TResource>( | ||
TimeSpan timeout, | ||
Action<WatchEventType, TResource> onEvent, | ||
Action<Exception>? onError = null, | ||
Action? onClose = null, | ||
string? @namespace = null, | ||
CancellationToken cancellationToken = default) | ||
where TResource : IKubernetesObject<V1ObjectMeta>; | ||
} | ||
} |
Oops, something went wrong.