diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json new file mode 100644 index 00000000..268c37c3 --- /dev/null +++ b/.config/dotnet-tools.json @@ -0,0 +1,12 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "docfx": { + "version": "2.70.4", + "commands": [ + "docfx" + ] + } + } +} \ No newline at end of file diff --git a/.editorconfig b/.editorconfig index 8f7ba624..8a49fdf5 100644 --- a/.editorconfig +++ b/.editorconfig @@ -3,6 +3,7 @@ root = true # All files [*] indent_style = space +max_line_length = 120 # Xml files [*.xml] @@ -19,7 +20,7 @@ tab_width = 4 # New line preferences end_of_line = crlf -insert_final_newline = false +insert_final_newline = true #### Custom Analyzer Rules #### @@ -45,6 +46,16 @@ dotnet_diagnostic.SA1649.severity = none dotnet_diagnostic.RCS1029.severity = none dotnet_diagnostic.RCS1090.severity = none +#### Custom Coding Conventions #### +resharper_csharp_space_in_singleline_accessorholder = true +resharper_csharp_space_between_accessors_in_singleline_property = true +resharper_csharp_space_in_singleline_method = true +resharper_csharp_space_in_singleline_anonymous_method = true +resharper_csharp_space_within_single_line_array_initializer_braces = true +resharper_csharp_trailing_comma_in_multiline_lists = true +resharper_csharp_place_type_attribute_on_same_line = false +resharper_csharp_place_attribute_on_same_line = false + #### .NET Coding Conventions #### [*.{cs,vb}] diff --git a/.github/workflows/dotnet-release.yml b/.github/workflows/dotnet-release.yml index b9d73afb..2c40d5b9 100644 --- a/.github/workflows/dotnet-release.yml +++ b/.github/workflows/dotnet-release.yml @@ -3,8 +3,8 @@ name: .NET Release on: push: branches: - - master - - next + - main + - release jobs: semantic-release: diff --git a/.github/workflows/dotnet-test.yml b/.github/workflows/dotnet-test.yml index 23d1ccfa..0f3f4b62 100644 --- a/.github/workflows/dotnet-test.yml +++ b/.github/workflows/dotnet-test.yml @@ -5,22 +5,14 @@ on: branches: - "**" +concurrency: + group: testing + cancel-in-progress: true + jobs: test: - name: Execute Test ${{ matrix.project }} + name: Testing runs-on: ubuntu-latest - strategy: - fail-fast: true - matrix: - include: - - project: KubeOps.KubernetesClient.Test - kubernetes: true - - project: KubeOps.Test - kubernetes: false - - project: KubeOps.Templates.Test - kubernetes: false - - project: KubeOps.TestOperator.Test - kubernetes: false steps: - uses: actions/checkout@v3 @@ -31,21 +23,6 @@ jobs: - name: Create Kubernetes Cluster uses: helm/kind-action@v1.8.0 - if: ${{ matrix.kubernetes == true }} - name: Execute Tests - run: dotnet test --configuration Release tests/${{ matrix.project }} - - result: - if: ${{ always() }} - runs-on: ubuntu-latest - name: Final Results - needs: [test] - steps: - - run: | - result="${{ needs.test.result }}" - if [[ $result == "success" || $result == "skipped" ]]; then - exit 0 - else - exit 1 - fi + run: dotnet test --configuration Release diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml index 0d2581cf..3917bc1b 100644 --- a/.github/workflows/gh-pages.yml +++ b/.github/workflows/gh-pages.yml @@ -3,7 +3,7 @@ name: Deploy GitHub Pages on: push: branches: - - master + - main workflow_dispatch: @@ -21,55 +21,18 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - with: - fetch-depth: 1 - - - run: mkdir public - - - name: Build Index - uses: jaywcjlove/markdown-to-html-cli@main - with: - source: res/docs_index.md - output: public/index.html - github-corners: https://github.com/buehler/dotnet-operator-sdk - - - name: Build Contribution - uses: jaywcjlove/markdown-to-html-cli@main - with: - source: CONTRIBUTING.md - output: public/contribution.html - github-corners: https://github.com/buehler/dotnet-operator-sdk - - name: Build KubeOps - uses: jaywcjlove/markdown-to-html-cli@main + - name: Setup .NET + uses: actions/setup-dotnet@v3 with: - source: src/KubeOps/README.md - output: public/kubeops.html - github-corners: https://github.com/buehler/dotnet-operator-sdk/tree/master/src/KubeOps + dotnet-version: 7.x - - name: Build KubeOps.KubernetesClient - uses: jaywcjlove/markdown-to-html-cli@main - with: - source: src/KubeOps.KubernetesClient/README.md - output: public/kubeops-kubernetesclient.html - github-corners: https://github.com/buehler/dotnet-operator-sdk/tree/master/src/KubeOps.KubernetesClient + - run: dotnet tool restore - - name: Build KubeOps.Templates - uses: jaywcjlove/markdown-to-html-cli@main - with: - source: src/KubeOps.Templates/README.md - output: public/kubeops-templates.html - github-corners: https://github.com/buehler/dotnet-operator-sdk/tree/master/src/KubeOps.Templates - - - name: Build KubeOps.Testing - uses: jaywcjlove/markdown-to-html-cli@main - with: - source: src/KubeOps.Testing/README.md - output: public/kubeops-testing.html - github-corners: https://github.com/buehler/dotnet-operator-sdk/tree/master/src/KubeOps.Testing + - run: dotnet docfx - uses: actions/upload-pages-artifact@v1 with: - path: public + path: _site - uses: actions/deploy-pages@v1 diff --git a/.github/workflows/security-analysis.yml b/.github/workflows/security-analysis.yml index c52e73bb..a78c7717 100644 --- a/.github/workflows/security-analysis.yml +++ b/.github/workflows/security-analysis.yml @@ -3,10 +3,14 @@ name: Code Security Testing on: pull_request: branches: - - master + - main schedule: - cron: "0 20 * * 5" +concurrency: + group: security + cancel-in-progress: true + jobs: codeQL: name: Analyze diff --git a/.gitignore b/.gitignore index 5622d0aa..179ec038 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,6 @@ bld/ coverage.json coverage.info .vs + +# Docs +_site diff --git a/.releaserc.json b/.releaserc.json index 3a361b18..f24df3dc 100644 --- a/.releaserc.json +++ b/.releaserc.json @@ -1,11 +1,15 @@ { "debug": true, "branches": [ - "master", { - "name": "next", - "prerelease": "prerelease" - } + "name": "maintenance/7.x", + "range": "7.x" + }, + { + "name": "main", + "prerelease": "pre" + }, + "release" ], "plugins": [ "@semantic-release/commit-analyzer", diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 00000000..f453475c --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,58 @@ + + + enable + enable + 11 + Christoph Bühler + cbuehler + true + + + + https://github.com/buehler/dotnet-operator-sdk.git + https://github.com/buehler/dotnet-operator-sdk.git + git + Apache-2.0 + icon.png + README.md + LICENSE + + + + true + + + + + + + true + \ + false + + + + + + + + + + + + <_Parameter1>$(MSBuildProjectName).Test + + + + <_Parameter1>DynamicProxyGenAssembly2 + + + diff --git a/DotnetOperatorSdk.sln b/DotnetOperatorSdk.sln deleted file mode 100644 index 01fdb179..00000000 --- a/DotnetOperatorSdk.sln +++ /dev/null @@ -1,104 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.30406.217 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{95F3A6DD-B421-441D-B263-1B34A1465FF5}" -ProjectSection(SolutionItems) = preProject - README.md = README.md - LICENSE = LICENSE -EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KubeOps", "src\KubeOps\KubeOps.csproj", "{D7AB6CB9-94B6-4FEB-B7D8-D8AA793BD2A4}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{50E9B964-68F7-4B9F-BEA8-165CE45BC5C6}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KubeOps.Test", "tests\KubeOps.Test\KubeOps.Test.csproj", "{A33D30D0-AC1B-48F8-8A5A-36E569981793}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KubeOps.TestOperator", "tests\KubeOps.TestOperator\KubeOps.TestOperator.csproj", "{751BDC14-D75F-4DDE-9C45-2432041FBCAC}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KubeOps.TestOperator.Test", "tests\KubeOps.TestOperator.Test\KubeOps.TestOperator.Test.csproj", "{B374D7E4-E9BA-47F8-B1A4-440DECD376E4}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "config", "config", "{EF94C48A-1D2A-459B-B397-A130463FF52D}" -ProjectSection(SolutionItems) = preProject - config\CodeAnalysis.targets = config\CodeAnalysis.targets - config\Common.targets = config\Common.targets - config\stylecop.json = config\stylecop.json - .gitignore = .gitignore - .releaserc.json = .releaserc.json - renovate.json = renovate.json - config\CommonTests.targets = config\CommonTests.targets - .editorconfig = .editorconfig -EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KubeOps.Testing", "src\KubeOps.Testing\KubeOps.Testing.csproj", "{4A6D1BEB-CB4C-495A-A20D-D8728F6BBC93}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KubeOps.Templates", "src\KubeOps.Templates\KubeOps.Templates.csproj", "{210EF3DD-151D-4547-9A35-39C97B887CD0}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KubeOps.Templates.Test", "tests\KubeOps.Templates.Test\KubeOps.Templates.Test.csproj", "{B88CFB69-709B-4B7D-A1F6-BD8200609770}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KubeOps.KubernetesClient", "src\KubeOps.KubernetesClient\KubeOps.KubernetesClient.csproj", "{8211BC96-6BA7-480E-8B30-4DA107FF404A}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KubeOps.KubernetesClient.Test", "tests\KubeOps.KubernetesClient.Test\KubeOps.KubernetesClient.Test.csproj", "{B9E58CCE-51CC-43A1-B490-01F750B5475E}" -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 - {A33D30D0-AC1B-48F8-8A5A-36E569981793}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A33D30D0-AC1B-48F8-8A5A-36E569981793}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A33D30D0-AC1B-48F8-8A5A-36E569981793}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A33D30D0-AC1B-48F8-8A5A-36E569981793}.Release|Any CPU.Build.0 = Release|Any CPU - {751BDC14-D75F-4DDE-9C45-2432041FBCAC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {751BDC14-D75F-4DDE-9C45-2432041FBCAC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {751BDC14-D75F-4DDE-9C45-2432041FBCAC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {751BDC14-D75F-4DDE-9C45-2432041FBCAC}.Release|Any CPU.Build.0 = Release|Any CPU - {B374D7E4-E9BA-47F8-B1A4-440DECD376E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B374D7E4-E9BA-47F8-B1A4-440DECD376E4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B374D7E4-E9BA-47F8-B1A4-440DECD376E4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B374D7E4-E9BA-47F8-B1A4-440DECD376E4}.Release|Any CPU.Build.0 = Release|Any CPU - {4A6D1BEB-CB4C-495A-A20D-D8728F6BBC93}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4A6D1BEB-CB4C-495A-A20D-D8728F6BBC93}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4A6D1BEB-CB4C-495A-A20D-D8728F6BBC93}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4A6D1BEB-CB4C-495A-A20D-D8728F6BBC93}.Release|Any CPU.Build.0 = Release|Any CPU - {210EF3DD-151D-4547-9A35-39C97B887CD0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {210EF3DD-151D-4547-9A35-39C97B887CD0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {210EF3DD-151D-4547-9A35-39C97B887CD0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {210EF3DD-151D-4547-9A35-39C97B887CD0}.Release|Any CPU.Build.0 = Release|Any CPU - {B88CFB69-709B-4B7D-A1F6-BD8200609770}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B88CFB69-709B-4B7D-A1F6-BD8200609770}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B88CFB69-709B-4B7D-A1F6-BD8200609770}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B88CFB69-709B-4B7D-A1F6-BD8200609770}.Release|Any CPU.Build.0 = Release|Any CPU - {8211BC96-6BA7-480E-8B30-4DA107FF404A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8211BC96-6BA7-480E-8B30-4DA107FF404A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8211BC96-6BA7-480E-8B30-4DA107FF404A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8211BC96-6BA7-480E-8B30-4DA107FF404A}.Release|Any CPU.Build.0 = Release|Any CPU - {B9E58CCE-51CC-43A1-B490-01F750B5475E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B9E58CCE-51CC-43A1-B490-01F750B5475E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B9E58CCE-51CC-43A1-B490-01F750B5475E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B9E58CCE-51CC-43A1-B490-01F750B5475E}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {D7AB6CB9-94B6-4FEB-B7D8-D8AA793BD2A4} = {95F3A6DD-B421-441D-B263-1B34A1465FF5} - {A33D30D0-AC1B-48F8-8A5A-36E569981793} = {50E9B964-68F7-4B9F-BEA8-165CE45BC5C6} - {751BDC14-D75F-4DDE-9C45-2432041FBCAC} = {50E9B964-68F7-4B9F-BEA8-165CE45BC5C6} - {B374D7E4-E9BA-47F8-B1A4-440DECD376E4} = {50E9B964-68F7-4B9F-BEA8-165CE45BC5C6} - {4A6D1BEB-CB4C-495A-A20D-D8728F6BBC93} = {95F3A6DD-B421-441D-B263-1B34A1465FF5} - {210EF3DD-151D-4547-9A35-39C97B887CD0} = {95F3A6DD-B421-441D-B263-1B34A1465FF5} - {B88CFB69-709B-4B7D-A1F6-BD8200609770} = {50E9B964-68F7-4B9F-BEA8-165CE45BC5C6} - {8211BC96-6BA7-480E-8B30-4DA107FF404A} = {95F3A6DD-B421-441D-B263-1B34A1465FF5} - {B9E58CCE-51CC-43A1-B490-01F750B5475E} = {50E9B964-68F7-4B9F-BEA8-165CE45BC5C6} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {ADAA5DFB-A7E5-490C-88EF-48D67C715F24} - EndGlobalSection -EndGlobal diff --git a/DotnetOperatorSdk.sln.DotSettings b/DotnetOperatorSdk.sln.DotSettings deleted file mode 100644 index 9345308d..00000000 --- a/DotnetOperatorSdk.sln.DotSettings +++ /dev/null @@ -1,25 +0,0 @@ - - - True - True - NEVER - False - NEVER - False - True - True - False - True - True - CHOP_IF_LONG - CHOP_IF_LONG - CHOP_IF_LONG - CHOP_IF_LONG - CHOP_IF_LONG - CHOP_ALWAYS - CHOP_IF_LONG - True - True - True - True - diff --git a/KubeOps.sln b/KubeOps.sln new file mode 100644 index 00000000..5a8ae4be --- /dev/null +++ b/KubeOps.sln @@ -0,0 +1,110 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{C587731F-8191-4A19-8662-B89A60FE79A1}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{4DB01062-6DC5-4028-BB72-C0619C2F5F2E}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{DC760E69-D0EA-417F-AE38-B12D0B04DE39}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Operator", "examples\Operator\Operator.csproj", "{E9A0B04E-D90E-4B94-90E0-DD3666B098FF}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "config", "config", "{DCC36310-C31F-4BCE-B252-2827A060ED7B}" + ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig + .gitignore = .gitignore + .releaserc.json = .releaserc.json + Directory.Build.props = Directory.Build.props + renovate.json = renovate.json + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KubeOps.Cli", "src\KubeOps.Cli\KubeOps.Cli.csproj", "{E1521548-7CAD-464D-BFD2-ECFBA3FFC7EF}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KubeOps.Abstractions", "src\KubeOps.Abstractions\KubeOps.Abstractions.csproj", "{D29A46CF-E494-4365-9BFF-0FF19AD7AA8F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KubeOps.Operator", "src\KubeOps.Operator\KubeOps.Operator.csproj", "{94B40118-80EF-4226-912B-CC9AC0B69E59}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KubeOps.Generator", "src\KubeOps.Generator\KubeOps.Generator.csproj", "{759AE147-D4A4-44E3-914B-6CBB427D6223}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KubeOps.Cli.Test", "test\KubeOps.Cli.Test\KubeOps.Cli.Test.csproj", "{3725E9BD-5530-4606-9C05-B825F80897E3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KubeOps.Operator.Test", "test\KubeOps.Operator.Test\KubeOps.Operator.Test.csproj", "{E2FC83BD-0ABD-4EA3-95B7-B208649B8E31}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KubeOps.Generator.Test", "test\KubeOps.Generator.Test\KubeOps.Generator.Test.csproj", "{162EE2A9-F8BA-4D52-9D65-67CCDB76EAC9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KubeOps.Operator.Web", "src\KubeOps.Operator.Web\KubeOps.Operator.Web.csproj", "{E5012C55-B34E-4672-AF4C-C233B45E8EA2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KubeOps.Operator.Web.Test", "test\KubeOps.Operator.Web.Test\KubeOps.Operator.Web.Test.csproj", "{BC6E6D3C-6404-4B01-9D72-AA16FEEBFF5C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KubeOps.Transpiler", "src\KubeOps.Transpiler\KubeOps.Transpiler.csproj", "{9C155732-5CE8-4F1D-8D5F-AB60DB1A1B5C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {E9A0B04E-D90E-4B94-90E0-DD3666B098FF} = {DC760E69-D0EA-417F-AE38-B12D0B04DE39} + {E1521548-7CAD-464D-BFD2-ECFBA3FFC7EF} = {4DB01062-6DC5-4028-BB72-C0619C2F5F2E} + {D29A46CF-E494-4365-9BFF-0FF19AD7AA8F} = {4DB01062-6DC5-4028-BB72-C0619C2F5F2E} + {94B40118-80EF-4226-912B-CC9AC0B69E59} = {4DB01062-6DC5-4028-BB72-C0619C2F5F2E} + {759AE147-D4A4-44E3-914B-6CBB427D6223} = {4DB01062-6DC5-4028-BB72-C0619C2F5F2E} + {3725E9BD-5530-4606-9C05-B825F80897E3} = {C587731F-8191-4A19-8662-B89A60FE79A1} + {E2FC83BD-0ABD-4EA3-95B7-B208649B8E31} = {C587731F-8191-4A19-8662-B89A60FE79A1} + {162EE2A9-F8BA-4D52-9D65-67CCDB76EAC9} = {C587731F-8191-4A19-8662-B89A60FE79A1} + {E5012C55-B34E-4672-AF4C-C233B45E8EA2} = {4DB01062-6DC5-4028-BB72-C0619C2F5F2E} + {BC6E6D3C-6404-4B01-9D72-AA16FEEBFF5C} = {C587731F-8191-4A19-8662-B89A60FE79A1} + {9C155732-5CE8-4F1D-8D5F-AB60DB1A1B5C} = {4DB01062-6DC5-4028-BB72-C0619C2F5F2E} + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E9A0B04E-D90E-4B94-90E0-DD3666B098FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E9A0B04E-D90E-4B94-90E0-DD3666B098FF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E9A0B04E-D90E-4B94-90E0-DD3666B098FF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E9A0B04E-D90E-4B94-90E0-DD3666B098FF}.Release|Any CPU.Build.0 = Release|Any CPU + {E1521548-7CAD-464D-BFD2-ECFBA3FFC7EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E1521548-7CAD-464D-BFD2-ECFBA3FFC7EF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E1521548-7CAD-464D-BFD2-ECFBA3FFC7EF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E1521548-7CAD-464D-BFD2-ECFBA3FFC7EF}.Release|Any CPU.Build.0 = Release|Any CPU + {D29A46CF-E494-4365-9BFF-0FF19AD7AA8F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D29A46CF-E494-4365-9BFF-0FF19AD7AA8F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D29A46CF-E494-4365-9BFF-0FF19AD7AA8F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D29A46CF-E494-4365-9BFF-0FF19AD7AA8F}.Release|Any CPU.Build.0 = Release|Any CPU + {94B40118-80EF-4226-912B-CC9AC0B69E59}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {94B40118-80EF-4226-912B-CC9AC0B69E59}.Debug|Any CPU.Build.0 = Debug|Any CPU + {94B40118-80EF-4226-912B-CC9AC0B69E59}.Release|Any CPU.ActiveCfg = Release|Any CPU + {94B40118-80EF-4226-912B-CC9AC0B69E59}.Release|Any CPU.Build.0 = Release|Any CPU + {759AE147-D4A4-44E3-914B-6CBB427D6223}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {759AE147-D4A4-44E3-914B-6CBB427D6223}.Debug|Any CPU.Build.0 = Debug|Any CPU + {759AE147-D4A4-44E3-914B-6CBB427D6223}.Release|Any CPU.ActiveCfg = Release|Any CPU + {759AE147-D4A4-44E3-914B-6CBB427D6223}.Release|Any CPU.Build.0 = Release|Any CPU + {3725E9BD-5530-4606-9C05-B825F80897E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3725E9BD-5530-4606-9C05-B825F80897E3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3725E9BD-5530-4606-9C05-B825F80897E3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3725E9BD-5530-4606-9C05-B825F80897E3}.Release|Any CPU.Build.0 = Release|Any CPU + {E2FC83BD-0ABD-4EA3-95B7-B208649B8E31}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E2FC83BD-0ABD-4EA3-95B7-B208649B8E31}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E2FC83BD-0ABD-4EA3-95B7-B208649B8E31}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E2FC83BD-0ABD-4EA3-95B7-B208649B8E31}.Release|Any CPU.Build.0 = Release|Any CPU + {162EE2A9-F8BA-4D52-9D65-67CCDB76EAC9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {162EE2A9-F8BA-4D52-9D65-67CCDB76EAC9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {162EE2A9-F8BA-4D52-9D65-67CCDB76EAC9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {162EE2A9-F8BA-4D52-9D65-67CCDB76EAC9}.Release|Any CPU.Build.0 = Release|Any CPU + {E5012C55-B34E-4672-AF4C-C233B45E8EA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E5012C55-B34E-4672-AF4C-C233B45E8EA2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E5012C55-B34E-4672-AF4C-C233B45E8EA2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E5012C55-B34E-4672-AF4C-C233B45E8EA2}.Release|Any CPU.Build.0 = Release|Any CPU + {BC6E6D3C-6404-4B01-9D72-AA16FEEBFF5C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BC6E6D3C-6404-4B01-9D72-AA16FEEBFF5C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BC6E6D3C-6404-4B01-9D72-AA16FEEBFF5C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BC6E6D3C-6404-4B01-9D72-AA16FEEBFF5C}.Release|Any CPU.Build.0 = Release|Any CPU + {9C155732-5CE8-4F1D-8D5F-AB60DB1A1B5C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9C155732-5CE8-4F1D-8D5F-AB60DB1A1B5C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9C155732-5CE8-4F1D-8D5F-AB60DB1A1B5C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9C155732-5CE8-4F1D-8D5F-AB60DB1A1B5C}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/README.md b/README.md index 1d095234..5c1684ec 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# KubeOps +# KubeOps ![Code Security Testing](https://github.com/buehler/dotnet-operator-sdk/workflows/Code%20Security%20Testing/badge.svg) ![.NET Release](https://github.com/buehler/dotnet-operator-sdk/workflows/.NET%20Release/badge.svg) @@ -13,10 +13,7 @@ and each package contains a README.md with further information/documentation. ## Packages -- [KubeOps](./src/KubeOps/README.md) - The core package of the SDK. -- [KubeOps.Testing](./src/KubeOps.Testing/README.md) - Extensions that support integration testing. -- [KubeOps.Templates](./src/KubeOps.Templates/README.md) - `dotnet new` templates for creating operators. -- [KubeOps.KubernetesClient](./src/KubeOps.KubernetesClient/README.md) - An improved Kubernetes client to interact with Kubernetes APIs. +TODO. ## Contribution @@ -24,7 +21,7 @@ If you want to contribute, feel free to open a pull request or write issues :-) Read more about contribution (especially for setting up your local environment) in the [CONTRIBUTING file](./CONTRIBUTING.md). -Short wrapup: +In short: - Check out the code - Develop on KubeOps - Use some Kubernetes to run the test operator against diff --git a/config/CodeAnalysis.targets b/_old/config/CodeAnalysis.targets similarity index 100% rename from config/CodeAnalysis.targets rename to _old/config/CodeAnalysis.targets diff --git a/config/Common.targets b/_old/config/Common.targets similarity index 100% rename from config/Common.targets rename to _old/config/Common.targets index a1555188..811223d1 100644 --- a/config/Common.targets +++ b/_old/config/Common.targets @@ -32,10 +32,10 @@ - <_Parameter1>$(MSBuildProjectName).Test + <_Parameter1>$(MSBuildProjectName).TestOperator.Test - <_Parameter1>$(MSBuildProjectName).TestOperator.Test + <_Parameter1>$(MSBuildProjectName).Test diff --git a/config/CommonTests.targets b/_old/config/CommonTests.targets similarity index 100% rename from config/CommonTests.targets rename to _old/config/CommonTests.targets diff --git a/config/stylecop.json b/_old/config/stylecop.json similarity index 100% rename from config/stylecop.json rename to _old/config/stylecop.json diff --git a/src/KubeOps.KubernetesClient/Entities/EntityDefinition.cs b/_old/src/KubeOps.KubernetesClient/Entities/EntityDefinition.cs similarity index 100% rename from src/KubeOps.KubernetesClient/Entities/EntityDefinition.cs rename to _old/src/KubeOps.KubernetesClient/Entities/EntityDefinition.cs diff --git a/src/KubeOps.KubernetesClient/Entities/EntityList{TEntity}.cs b/_old/src/KubeOps.KubernetesClient/Entities/EntityList{TEntity}.cs similarity index 100% rename from src/KubeOps.KubernetesClient/Entities/EntityList{TEntity}.cs rename to _old/src/KubeOps.KubernetesClient/Entities/EntityList{TEntity}.cs diff --git a/src/KubeOps.KubernetesClient/Entities/EntityScope.cs b/_old/src/KubeOps.KubernetesClient/Entities/EntityScope.cs similarity index 100% rename from src/KubeOps.KubernetesClient/Entities/EntityScope.cs rename to _old/src/KubeOps.KubernetesClient/Entities/EntityScope.cs diff --git a/src/KubeOps.KubernetesClient/Entities/EntityScopeAttribute.cs b/_old/src/KubeOps.KubernetesClient/Entities/EntityScopeAttribute.cs similarity index 100% rename from src/KubeOps.KubernetesClient/Entities/EntityScopeAttribute.cs rename to _old/src/KubeOps.KubernetesClient/Entities/EntityScopeAttribute.cs diff --git a/src/KubeOps.KubernetesClient/Entities/Extensions.cs b/_old/src/KubeOps.KubernetesClient/Entities/Extensions.cs similarity index 100% rename from src/KubeOps.KubernetesClient/Entities/Extensions.cs rename to _old/src/KubeOps.KubernetesClient/Entities/Extensions.cs diff --git a/src/KubeOps.KubernetesClient/IKubernetesClient.cs b/_old/src/KubeOps.KubernetesClient/IKubernetesClient.cs similarity index 100% rename from src/KubeOps.KubernetesClient/IKubernetesClient.cs rename to _old/src/KubeOps.KubernetesClient/IKubernetesClient.cs diff --git a/src/KubeOps.KubernetesClient/KubeOps.KubernetesClient.csproj b/_old/src/KubeOps.KubernetesClient/KubeOps.KubernetesClient.csproj similarity index 100% rename from src/KubeOps.KubernetesClient/KubeOps.KubernetesClient.csproj rename to _old/src/KubeOps.KubernetesClient/KubeOps.KubernetesClient.csproj diff --git a/src/KubeOps.KubernetesClient/KubernetesClient.cs b/_old/src/KubeOps.KubernetesClient/KubernetesClient.cs similarity index 100% rename from src/KubeOps.KubernetesClient/KubernetesClient.cs rename to _old/src/KubeOps.KubernetesClient/KubernetesClient.cs diff --git a/src/KubeOps.KubernetesClient/LabelSelectors/EqualsSelector.cs b/_old/src/KubeOps.KubernetesClient/LabelSelectors/EqualsSelector.cs similarity index 100% rename from src/KubeOps.KubernetesClient/LabelSelectors/EqualsSelector.cs rename to _old/src/KubeOps.KubernetesClient/LabelSelectors/EqualsSelector.cs diff --git a/src/KubeOps.KubernetesClient/LabelSelectors/ExistsSelector.cs b/_old/src/KubeOps.KubernetesClient/LabelSelectors/ExistsSelector.cs similarity index 100% rename from src/KubeOps.KubernetesClient/LabelSelectors/ExistsSelector.cs rename to _old/src/KubeOps.KubernetesClient/LabelSelectors/ExistsSelector.cs diff --git a/src/KubeOps.KubernetesClient/LabelSelectors/Extensions.cs b/_old/src/KubeOps.KubernetesClient/LabelSelectors/Extensions.cs similarity index 100% rename from src/KubeOps.KubernetesClient/LabelSelectors/Extensions.cs rename to _old/src/KubeOps.KubernetesClient/LabelSelectors/Extensions.cs diff --git a/src/KubeOps.KubernetesClient/LabelSelectors/ILabelSelector.cs b/_old/src/KubeOps.KubernetesClient/LabelSelectors/ILabelSelector.cs similarity index 100% rename from src/KubeOps.KubernetesClient/LabelSelectors/ILabelSelector.cs rename to _old/src/KubeOps.KubernetesClient/LabelSelectors/ILabelSelector.cs diff --git a/src/KubeOps.KubernetesClient/LabelSelectors/NotEqualsSelector.cs b/_old/src/KubeOps.KubernetesClient/LabelSelectors/NotEqualsSelector.cs similarity index 100% rename from src/KubeOps.KubernetesClient/LabelSelectors/NotEqualsSelector.cs rename to _old/src/KubeOps.KubernetesClient/LabelSelectors/NotEqualsSelector.cs diff --git a/src/KubeOps.KubernetesClient/LabelSelectors/NotExistsSelector.cs b/_old/src/KubeOps.KubernetesClient/LabelSelectors/NotExistsSelector.cs similarity index 100% rename from src/KubeOps.KubernetesClient/LabelSelectors/NotExistsSelector.cs rename to _old/src/KubeOps.KubernetesClient/LabelSelectors/NotExistsSelector.cs diff --git a/src/KubeOps.KubernetesClient/README.md b/_old/src/KubeOps.KubernetesClient/README.md similarity index 100% rename from src/KubeOps.KubernetesClient/README.md rename to _old/src/KubeOps.KubernetesClient/README.md diff --git a/src/KubeOps.Templates/KubeOps.Templates.csproj b/_old/src/KubeOps.Templates/KubeOps.Templates.csproj similarity index 100% rename from src/KubeOps.Templates/KubeOps.Templates.csproj rename to _old/src/KubeOps.Templates/KubeOps.Templates.csproj diff --git a/src/KubeOps.Templates/README.md b/_old/src/KubeOps.Templates/README.md similarity index 100% rename from src/KubeOps.Templates/README.md rename to _old/src/KubeOps.Templates/README.md diff --git a/src/KubeOps.Templates/Templates/EmptyOperator.CSharp/.template.config/template.json b/_old/src/KubeOps.Templates/Templates/EmptyOperator.CSharp/.template.config/template.json similarity index 100% rename from src/KubeOps.Templates/Templates/EmptyOperator.CSharp/.template.config/template.json rename to _old/src/KubeOps.Templates/Templates/EmptyOperator.CSharp/.template.config/template.json diff --git a/src/KubeOps.Templates/Templates/EmptyOperator.CSharp/GeneratedOperatorProject.csproj b/_old/src/KubeOps.Templates/Templates/EmptyOperator.CSharp/GeneratedOperatorProject.csproj similarity index 100% rename from src/KubeOps.Templates/Templates/EmptyOperator.CSharp/GeneratedOperatorProject.csproj rename to _old/src/KubeOps.Templates/Templates/EmptyOperator.CSharp/GeneratedOperatorProject.csproj diff --git a/src/KubeOps.Templates/Templates/EmptyOperator.CSharp/Program.cs b/_old/src/KubeOps.Templates/Templates/EmptyOperator.CSharp/Program.cs similarity index 100% rename from src/KubeOps.Templates/Templates/EmptyOperator.CSharp/Program.cs rename to _old/src/KubeOps.Templates/Templates/EmptyOperator.CSharp/Program.cs diff --git a/src/KubeOps.Templates/Templates/EmptyOperator.CSharp/appsettings.Development.json b/_old/src/KubeOps.Templates/Templates/EmptyOperator.CSharp/appsettings.Development.json similarity index 100% rename from src/KubeOps.Templates/Templates/EmptyOperator.CSharp/appsettings.Development.json rename to _old/src/KubeOps.Templates/Templates/EmptyOperator.CSharp/appsettings.Development.json diff --git a/src/KubeOps.Templates/Templates/EmptyOperator.CSharp/appsettings.json b/_old/src/KubeOps.Templates/Templates/EmptyOperator.CSharp/appsettings.json similarity index 100% rename from src/KubeOps.Templates/Templates/EmptyOperator.CSharp/appsettings.json rename to _old/src/KubeOps.Templates/Templates/EmptyOperator.CSharp/appsettings.json diff --git a/src/KubeOps.Templates/Templates/EmptyOperator.FSharp/.template.config/template.json b/_old/src/KubeOps.Templates/Templates/EmptyOperator.FSharp/.template.config/template.json similarity index 100% rename from src/KubeOps.Templates/Templates/EmptyOperator.FSharp/.template.config/template.json rename to _old/src/KubeOps.Templates/Templates/EmptyOperator.FSharp/.template.config/template.json diff --git a/src/KubeOps.Templates/Templates/EmptyOperator.FSharp/GeneratedOperatorProject.fsproj b/_old/src/KubeOps.Templates/Templates/EmptyOperator.FSharp/GeneratedOperatorProject.fsproj similarity index 100% rename from src/KubeOps.Templates/Templates/EmptyOperator.FSharp/GeneratedOperatorProject.fsproj rename to _old/src/KubeOps.Templates/Templates/EmptyOperator.FSharp/GeneratedOperatorProject.fsproj diff --git a/src/KubeOps.Templates/Templates/EmptyOperator.FSharp/Program.fs b/_old/src/KubeOps.Templates/Templates/EmptyOperator.FSharp/Program.fs similarity index 100% rename from src/KubeOps.Templates/Templates/EmptyOperator.FSharp/Program.fs rename to _old/src/KubeOps.Templates/Templates/EmptyOperator.FSharp/Program.fs diff --git a/src/KubeOps.Templates/Templates/EmptyOperator.FSharp/Startup.fs b/_old/src/KubeOps.Templates/Templates/EmptyOperator.FSharp/Startup.fs similarity index 100% rename from src/KubeOps.Templates/Templates/EmptyOperator.FSharp/Startup.fs rename to _old/src/KubeOps.Templates/Templates/EmptyOperator.FSharp/Startup.fs diff --git a/src/KubeOps.Templates/Templates/EmptyOperator.FSharp/appsettings.Development.json b/_old/src/KubeOps.Templates/Templates/EmptyOperator.FSharp/appsettings.Development.json similarity index 100% rename from src/KubeOps.Templates/Templates/EmptyOperator.FSharp/appsettings.Development.json rename to _old/src/KubeOps.Templates/Templates/EmptyOperator.FSharp/appsettings.Development.json diff --git a/src/KubeOps.Templates/Templates/EmptyOperator.FSharp/appsettings.json b/_old/src/KubeOps.Templates/Templates/EmptyOperator.FSharp/appsettings.json similarity index 100% rename from src/KubeOps.Templates/Templates/EmptyOperator.FSharp/appsettings.json rename to _old/src/KubeOps.Templates/Templates/EmptyOperator.FSharp/appsettings.json diff --git a/src/KubeOps.Templates/Templates/Operator.CSharp/.template.config/template.json b/_old/src/KubeOps.Templates/Templates/Operator.CSharp/.template.config/template.json similarity index 100% rename from src/KubeOps.Templates/Templates/Operator.CSharp/.template.config/template.json rename to _old/src/KubeOps.Templates/Templates/Operator.CSharp/.template.config/template.json diff --git a/src/KubeOps.Templates/Templates/Operator.CSharp/Controller/DemoController.cs b/_old/src/KubeOps.Templates/Templates/Operator.CSharp/Controller/DemoController.cs similarity index 100% rename from src/KubeOps.Templates/Templates/Operator.CSharp/Controller/DemoController.cs rename to _old/src/KubeOps.Templates/Templates/Operator.CSharp/Controller/DemoController.cs diff --git a/src/KubeOps.Templates/Templates/Operator.CSharp/Entities/V1DemoEntity.cs b/_old/src/KubeOps.Templates/Templates/Operator.CSharp/Entities/V1DemoEntity.cs similarity index 100% rename from src/KubeOps.Templates/Templates/Operator.CSharp/Entities/V1DemoEntity.cs rename to _old/src/KubeOps.Templates/Templates/Operator.CSharp/Entities/V1DemoEntity.cs diff --git a/src/KubeOps.Templates/Templates/Operator.CSharp/Finalizer/DemoFinalizer.cs b/_old/src/KubeOps.Templates/Templates/Operator.CSharp/Finalizer/DemoFinalizer.cs similarity index 100% rename from src/KubeOps.Templates/Templates/Operator.CSharp/Finalizer/DemoFinalizer.cs rename to _old/src/KubeOps.Templates/Templates/Operator.CSharp/Finalizer/DemoFinalizer.cs diff --git a/src/KubeOps.Templates/Templates/Operator.CSharp/GeneratedOperatorProject.csproj b/_old/src/KubeOps.Templates/Templates/Operator.CSharp/GeneratedOperatorProject.csproj similarity index 100% rename from src/KubeOps.Templates/Templates/Operator.CSharp/GeneratedOperatorProject.csproj rename to _old/src/KubeOps.Templates/Templates/Operator.CSharp/GeneratedOperatorProject.csproj diff --git a/src/KubeOps.Templates/Templates/Operator.CSharp/Program.cs b/_old/src/KubeOps.Templates/Templates/Operator.CSharp/Program.cs similarity index 100% rename from src/KubeOps.Templates/Templates/Operator.CSharp/Program.cs rename to _old/src/KubeOps.Templates/Templates/Operator.CSharp/Program.cs diff --git a/src/KubeOps.Templates/Templates/Operator.CSharp/Webhooks/DemoMutator.cs b/_old/src/KubeOps.Templates/Templates/Operator.CSharp/Webhooks/DemoMutator.cs similarity index 100% rename from src/KubeOps.Templates/Templates/Operator.CSharp/Webhooks/DemoMutator.cs rename to _old/src/KubeOps.Templates/Templates/Operator.CSharp/Webhooks/DemoMutator.cs diff --git a/src/KubeOps.Templates/Templates/Operator.CSharp/Webhooks/DemoValidator.cs b/_old/src/KubeOps.Templates/Templates/Operator.CSharp/Webhooks/DemoValidator.cs similarity index 100% rename from src/KubeOps.Templates/Templates/Operator.CSharp/Webhooks/DemoValidator.cs rename to _old/src/KubeOps.Templates/Templates/Operator.CSharp/Webhooks/DemoValidator.cs diff --git a/src/KubeOps.Templates/Templates/Operator.CSharp/appsettings.Development.json b/_old/src/KubeOps.Templates/Templates/Operator.CSharp/appsettings.Development.json similarity index 100% rename from src/KubeOps.Templates/Templates/Operator.CSharp/appsettings.Development.json rename to _old/src/KubeOps.Templates/Templates/Operator.CSharp/appsettings.Development.json diff --git a/src/KubeOps.Templates/Templates/Operator.CSharp/appsettings.json b/_old/src/KubeOps.Templates/Templates/Operator.CSharp/appsettings.json similarity index 100% rename from src/KubeOps.Templates/Templates/Operator.CSharp/appsettings.json rename to _old/src/KubeOps.Templates/Templates/Operator.CSharp/appsettings.json diff --git a/src/KubeOps.Templates/Templates/Operator.FSharp/.template.config/template.json b/_old/src/KubeOps.Templates/Templates/Operator.FSharp/.template.config/template.json similarity index 100% rename from src/KubeOps.Templates/Templates/Operator.FSharp/.template.config/template.json rename to _old/src/KubeOps.Templates/Templates/Operator.FSharp/.template.config/template.json diff --git a/src/KubeOps.Templates/Templates/Operator.FSharp/Controller/DemoController.fs b/_old/src/KubeOps.Templates/Templates/Operator.FSharp/Controller/DemoController.fs similarity index 100% rename from src/KubeOps.Templates/Templates/Operator.FSharp/Controller/DemoController.fs rename to _old/src/KubeOps.Templates/Templates/Operator.FSharp/Controller/DemoController.fs diff --git a/src/KubeOps.Templates/Templates/Operator.FSharp/Entities/V1DemoEntity.fs b/_old/src/KubeOps.Templates/Templates/Operator.FSharp/Entities/V1DemoEntity.fs similarity index 100% rename from src/KubeOps.Templates/Templates/Operator.FSharp/Entities/V1DemoEntity.fs rename to _old/src/KubeOps.Templates/Templates/Operator.FSharp/Entities/V1DemoEntity.fs diff --git a/src/KubeOps.Templates/Templates/Operator.FSharp/Finalizer/DemoFinalizer.fs b/_old/src/KubeOps.Templates/Templates/Operator.FSharp/Finalizer/DemoFinalizer.fs similarity index 100% rename from src/KubeOps.Templates/Templates/Operator.FSharp/Finalizer/DemoFinalizer.fs rename to _old/src/KubeOps.Templates/Templates/Operator.FSharp/Finalizer/DemoFinalizer.fs diff --git a/src/KubeOps.Templates/Templates/Operator.FSharp/GeneratedOperatorProject.fsproj b/_old/src/KubeOps.Templates/Templates/Operator.FSharp/GeneratedOperatorProject.fsproj similarity index 100% rename from src/KubeOps.Templates/Templates/Operator.FSharp/GeneratedOperatorProject.fsproj rename to _old/src/KubeOps.Templates/Templates/Operator.FSharp/GeneratedOperatorProject.fsproj diff --git a/src/KubeOps.Templates/Templates/Operator.FSharp/Program.fs b/_old/src/KubeOps.Templates/Templates/Operator.FSharp/Program.fs similarity index 100% rename from src/KubeOps.Templates/Templates/Operator.FSharp/Program.fs rename to _old/src/KubeOps.Templates/Templates/Operator.FSharp/Program.fs diff --git a/src/KubeOps.Templates/Templates/Operator.FSharp/Startup.fs b/_old/src/KubeOps.Templates/Templates/Operator.FSharp/Startup.fs similarity index 100% rename from src/KubeOps.Templates/Templates/Operator.FSharp/Startup.fs rename to _old/src/KubeOps.Templates/Templates/Operator.FSharp/Startup.fs diff --git a/src/KubeOps.Templates/Templates/Operator.FSharp/Webhooks/DemoMutator.fs b/_old/src/KubeOps.Templates/Templates/Operator.FSharp/Webhooks/DemoMutator.fs similarity index 100% rename from src/KubeOps.Templates/Templates/Operator.FSharp/Webhooks/DemoMutator.fs rename to _old/src/KubeOps.Templates/Templates/Operator.FSharp/Webhooks/DemoMutator.fs diff --git a/src/KubeOps.Templates/Templates/Operator.FSharp/Webhooks/DemoValidator.fs b/_old/src/KubeOps.Templates/Templates/Operator.FSharp/Webhooks/DemoValidator.fs similarity index 100% rename from src/KubeOps.Templates/Templates/Operator.FSharp/Webhooks/DemoValidator.fs rename to _old/src/KubeOps.Templates/Templates/Operator.FSharp/Webhooks/DemoValidator.fs diff --git a/src/KubeOps.Templates/Templates/Operator.FSharp/appsettings.Development.json b/_old/src/KubeOps.Templates/Templates/Operator.FSharp/appsettings.Development.json similarity index 100% rename from src/KubeOps.Templates/Templates/Operator.FSharp/appsettings.Development.json rename to _old/src/KubeOps.Templates/Templates/Operator.FSharp/appsettings.Development.json diff --git a/src/KubeOps.Templates/Templates/Operator.FSharp/appsettings.json b/_old/src/KubeOps.Templates/Templates/Operator.FSharp/appsettings.json similarity index 100% rename from src/KubeOps.Templates/Templates/Operator.FSharp/appsettings.json rename to _old/src/KubeOps.Templates/Templates/Operator.FSharp/appsettings.json diff --git a/src/KubeOps.Testing/KubeOps.Testing.csproj b/_old/src/KubeOps.Testing/KubeOps.Testing.csproj similarity index 100% rename from src/KubeOps.Testing/KubeOps.Testing.csproj rename to _old/src/KubeOps.Testing/KubeOps.Testing.csproj diff --git a/src/KubeOps.Testing/KubernetesOperatorFactory.cs b/_old/src/KubeOps.Testing/KubernetesOperatorFactory.cs similarity index 100% rename from src/KubeOps.Testing/KubernetesOperatorFactory.cs rename to _old/src/KubeOps.Testing/KubernetesOperatorFactory.cs diff --git a/src/KubeOps.Testing/MockEventQueue.cs b/_old/src/KubeOps.Testing/MockEventQueue.cs similarity index 100% rename from src/KubeOps.Testing/MockEventQueue.cs rename to _old/src/KubeOps.Testing/MockEventQueue.cs diff --git a/src/KubeOps.Testing/MockKubernetesClient.cs b/_old/src/KubeOps.Testing/MockKubernetesClient.cs similarity index 100% rename from src/KubeOps.Testing/MockKubernetesClient.cs rename to _old/src/KubeOps.Testing/MockKubernetesClient.cs diff --git a/src/KubeOps.Testing/MockedLeaderElection.cs b/_old/src/KubeOps.Testing/MockedLeaderElection.cs similarity index 100% rename from src/KubeOps.Testing/MockedLeaderElection.cs rename to _old/src/KubeOps.Testing/MockedLeaderElection.cs diff --git a/src/KubeOps.Testing/README.md b/_old/src/KubeOps.Testing/README.md similarity index 100% rename from src/KubeOps.Testing/README.md rename to _old/src/KubeOps.Testing/README.md diff --git a/src/KubeOps/Build/KubeOps.targets b/_old/src/KubeOps/Build/KubeOps.targets similarity index 100% rename from src/KubeOps/Build/KubeOps.targets rename to _old/src/KubeOps/Build/KubeOps.targets diff --git a/src/KubeOps/Build/Program.cs b/_old/src/KubeOps/Build/Program.cs similarity index 100% rename from src/KubeOps/Build/Program.cs rename to _old/src/KubeOps/Build/Program.cs diff --git a/src/KubeOps/KubeOps.csproj b/_old/src/KubeOps/KubeOps.csproj similarity index 100% rename from src/KubeOps/KubeOps.csproj rename to _old/src/KubeOps/KubeOps.csproj diff --git a/src/KubeOps/Operator/ApplicationBuilderExtensions.cs b/_old/src/KubeOps/Operator/ApplicationBuilderExtensions.cs similarity index 100% rename from src/KubeOps/Operator/ApplicationBuilderExtensions.cs rename to _old/src/KubeOps/Operator/ApplicationBuilderExtensions.cs diff --git a/src/KubeOps/Operator/Builder/AssemblyScanner.cs b/_old/src/KubeOps/Operator/Builder/AssemblyScanner.cs similarity index 100% rename from src/KubeOps/Operator/Builder/AssemblyScanner.cs rename to _old/src/KubeOps/Operator/Builder/AssemblyScanner.cs diff --git a/src/KubeOps/Operator/Builder/ComponentRegistrar.cs b/_old/src/KubeOps/Operator/Builder/ComponentRegistrar.cs similarity index 100% rename from src/KubeOps/Operator/Builder/ComponentRegistrar.cs rename to _old/src/KubeOps/Operator/Builder/ComponentRegistrar.cs diff --git a/src/KubeOps/Operator/Builder/DisabledAssemblyScanner.cs b/_old/src/KubeOps/Operator/Builder/DisabledAssemblyScanner.cs similarity index 100% rename from src/KubeOps/Operator/Builder/DisabledAssemblyScanner.cs rename to _old/src/KubeOps/Operator/Builder/DisabledAssemblyScanner.cs diff --git a/src/KubeOps/Operator/Builder/IAssemblyScanner.cs b/_old/src/KubeOps/Operator/Builder/IAssemblyScanner.cs similarity index 100% rename from src/KubeOps/Operator/Builder/IAssemblyScanner.cs rename to _old/src/KubeOps/Operator/Builder/IAssemblyScanner.cs diff --git a/src/KubeOps/Operator/Builder/IComponentRegistrar.cs b/_old/src/KubeOps/Operator/Builder/IComponentRegistrar.cs similarity index 100% rename from src/KubeOps/Operator/Builder/IComponentRegistrar.cs rename to _old/src/KubeOps/Operator/Builder/IComponentRegistrar.cs diff --git a/src/KubeOps/Operator/Builder/IOperatorBuilder.cs b/_old/src/KubeOps/Operator/Builder/IOperatorBuilder.cs similarity index 100% rename from src/KubeOps/Operator/Builder/IOperatorBuilder.cs rename to _old/src/KubeOps/Operator/Builder/IOperatorBuilder.cs diff --git a/src/KubeOps/Operator/Builder/OperatorBuilder.cs b/_old/src/KubeOps/Operator/Builder/OperatorBuilder.cs similarity index 100% rename from src/KubeOps/Operator/Builder/OperatorBuilder.cs rename to _old/src/KubeOps/Operator/Builder/OperatorBuilder.cs diff --git a/src/KubeOps/Operator/Caching/CacheComparisonResult.cs b/_old/src/KubeOps/Operator/Caching/CacheComparisonResult.cs similarity index 100% rename from src/KubeOps/Operator/Caching/CacheComparisonResult.cs rename to _old/src/KubeOps/Operator/Caching/CacheComparisonResult.cs diff --git a/src/KubeOps/Operator/Caching/IResourceCache.cs b/_old/src/KubeOps/Operator/Caching/IResourceCache.cs similarity index 100% rename from src/KubeOps/Operator/Caching/IResourceCache.cs rename to _old/src/KubeOps/Operator/Caching/IResourceCache.cs diff --git a/src/KubeOps/Operator/Caching/ResourceCache{TEntity}.cs b/_old/src/KubeOps/Operator/Caching/ResourceCache{TEntity}.cs similarity index 100% rename from src/KubeOps/Operator/Caching/ResourceCache{TEntity}.cs rename to _old/src/KubeOps/Operator/Caching/ResourceCache{TEntity}.cs diff --git a/src/KubeOps/Operator/Commands/CommandHelpers/CertificateGenerator.cs b/_old/src/KubeOps/Operator/Commands/CommandHelpers/CertificateGenerator.cs similarity index 100% rename from src/KubeOps/Operator/Commands/CommandHelpers/CertificateGenerator.cs rename to _old/src/KubeOps/Operator/Commands/CommandHelpers/CertificateGenerator.cs diff --git a/src/KubeOps/Operator/Commands/CommandHelpers/FileWriter.cs b/_old/src/KubeOps/Operator/Commands/CommandHelpers/FileWriter.cs similarity index 100% rename from src/KubeOps/Operator/Commands/CommandHelpers/FileWriter.cs rename to _old/src/KubeOps/Operator/Commands/CommandHelpers/FileWriter.cs diff --git a/src/KubeOps/Operator/Commands/ExitCodes.cs b/_old/src/KubeOps/Operator/Commands/ExitCodes.cs similarity index 100% rename from src/KubeOps/Operator/Commands/ExitCodes.cs rename to _old/src/KubeOps/Operator/Commands/ExitCodes.cs diff --git a/src/KubeOps/Operator/Commands/Generators/CrdGenerator.cs b/_old/src/KubeOps/Operator/Commands/Generators/CrdGenerator.cs similarity index 100% rename from src/KubeOps/Operator/Commands/Generators/CrdGenerator.cs rename to _old/src/KubeOps/Operator/Commands/Generators/CrdGenerator.cs diff --git a/src/KubeOps/Operator/Commands/Generators/DockerGenerator.cs b/_old/src/KubeOps/Operator/Commands/Generators/DockerGenerator.cs similarity index 100% rename from src/KubeOps/Operator/Commands/Generators/DockerGenerator.cs rename to _old/src/KubeOps/Operator/Commands/Generators/DockerGenerator.cs diff --git a/src/KubeOps/Operator/Commands/Generators/Generator.cs b/_old/src/KubeOps/Operator/Commands/Generators/Generator.cs similarity index 100% rename from src/KubeOps/Operator/Commands/Generators/Generator.cs rename to _old/src/KubeOps/Operator/Commands/Generators/Generator.cs diff --git a/src/KubeOps/Operator/Commands/Generators/InstallerGenerator.cs b/_old/src/KubeOps/Operator/Commands/Generators/InstallerGenerator.cs similarity index 100% rename from src/KubeOps/Operator/Commands/Generators/InstallerGenerator.cs rename to _old/src/KubeOps/Operator/Commands/Generators/InstallerGenerator.cs diff --git a/src/KubeOps/Operator/Commands/Generators/OperatorGenerator.cs b/_old/src/KubeOps/Operator/Commands/Generators/OperatorGenerator.cs similarity index 100% rename from src/KubeOps/Operator/Commands/Generators/OperatorGenerator.cs rename to _old/src/KubeOps/Operator/Commands/Generators/OperatorGenerator.cs diff --git a/src/KubeOps/Operator/Commands/Generators/OutputBase.cs b/_old/src/KubeOps/Operator/Commands/Generators/OutputBase.cs similarity index 100% rename from src/KubeOps/Operator/Commands/Generators/OutputBase.cs rename to _old/src/KubeOps/Operator/Commands/Generators/OutputBase.cs diff --git a/src/KubeOps/Operator/Commands/Generators/RbacGenerator.cs b/_old/src/KubeOps/Operator/Commands/Generators/RbacGenerator.cs similarity index 100% rename from src/KubeOps/Operator/Commands/Generators/RbacGenerator.cs rename to _old/src/KubeOps/Operator/Commands/Generators/RbacGenerator.cs diff --git a/src/KubeOps/Operator/Commands/Management/Install.cs b/_old/src/KubeOps/Operator/Commands/Management/Install.cs similarity index 100% rename from src/KubeOps/Operator/Commands/Management/Install.cs rename to _old/src/KubeOps/Operator/Commands/Management/Install.cs diff --git a/src/KubeOps/Operator/Commands/Management/Uninstall.cs b/_old/src/KubeOps/Operator/Commands/Management/Uninstall.cs similarity index 100% rename from src/KubeOps/Operator/Commands/Management/Uninstall.cs rename to _old/src/KubeOps/Operator/Commands/Management/Uninstall.cs diff --git a/src/KubeOps/Operator/Commands/Management/Webhooks/Install.cs b/_old/src/KubeOps/Operator/Commands/Management/Webhooks/Install.cs similarity index 100% rename from src/KubeOps/Operator/Commands/Management/Webhooks/Install.cs rename to _old/src/KubeOps/Operator/Commands/Management/Webhooks/Install.cs diff --git a/src/KubeOps/Operator/Commands/Management/Webhooks/Register.cs b/_old/src/KubeOps/Operator/Commands/Management/Webhooks/Register.cs similarity index 100% rename from src/KubeOps/Operator/Commands/Management/Webhooks/Register.cs rename to _old/src/KubeOps/Operator/Commands/Management/Webhooks/Register.cs diff --git a/src/KubeOps/Operator/Commands/Management/Webhooks/Webhooks.cs b/_old/src/KubeOps/Operator/Commands/Management/Webhooks/Webhooks.cs similarity index 100% rename from src/KubeOps/Operator/Commands/Management/Webhooks/Webhooks.cs rename to _old/src/KubeOps/Operator/Commands/Management/Webhooks/Webhooks.cs diff --git a/src/KubeOps/Operator/Commands/RunOperator.cs b/_old/src/KubeOps/Operator/Commands/RunOperator.cs similarity index 100% rename from src/KubeOps/Operator/Commands/RunOperator.cs rename to _old/src/KubeOps/Operator/Commands/RunOperator.cs diff --git a/src/KubeOps/Operator/Commands/Utilities/Version.cs b/_old/src/KubeOps/Operator/Commands/Utilities/Version.cs similarity index 100% rename from src/KubeOps/Operator/Commands/Utilities/Version.cs rename to _old/src/KubeOps/Operator/Commands/Utilities/Version.cs diff --git a/src/KubeOps/Operator/Comparing/ArrayExtensions.cs b/_old/src/KubeOps/Operator/Comparing/ArrayExtensions.cs similarity index 100% rename from src/KubeOps/Operator/Comparing/ArrayExtensions.cs rename to _old/src/KubeOps/Operator/Comparing/ArrayExtensions.cs diff --git a/src/KubeOps/Operator/Comparing/ArrayTraverse.cs b/_old/src/KubeOps/Operator/Comparing/ArrayTraverse.cs similarity index 100% rename from src/KubeOps/Operator/Comparing/ArrayTraverse.cs rename to _old/src/KubeOps/Operator/Comparing/ArrayTraverse.cs diff --git a/src/KubeOps/Operator/Comparing/ReferenceEqualityComparer.cs b/_old/src/KubeOps/Operator/Comparing/ReferenceEqualityComparer.cs similarity index 100% rename from src/KubeOps/Operator/Comparing/ReferenceEqualityComparer.cs rename to _old/src/KubeOps/Operator/Comparing/ReferenceEqualityComparer.cs diff --git a/src/KubeOps/Operator/Controller/ControllerInstanceBuilder.cs b/_old/src/KubeOps/Operator/Controller/ControllerInstanceBuilder.cs similarity index 100% rename from src/KubeOps/Operator/Controller/ControllerInstanceBuilder.cs rename to _old/src/KubeOps/Operator/Controller/ControllerInstanceBuilder.cs diff --git a/src/KubeOps/Operator/Controller/EventQueue.cs b/_old/src/KubeOps/Operator/Controller/EventQueue.cs similarity index 100% rename from src/KubeOps/Operator/Controller/EventQueue.cs rename to _old/src/KubeOps/Operator/Controller/EventQueue.cs diff --git a/src/KubeOps/Operator/Controller/IControllerInstanceBuilder.cs b/_old/src/KubeOps/Operator/Controller/IControllerInstanceBuilder.cs similarity index 100% rename from src/KubeOps/Operator/Controller/IControllerInstanceBuilder.cs rename to _old/src/KubeOps/Operator/Controller/IControllerInstanceBuilder.cs diff --git a/src/KubeOps/Operator/Controller/IEventQueue.cs b/_old/src/KubeOps/Operator/Controller/IEventQueue.cs similarity index 100% rename from src/KubeOps/Operator/Controller/IEventQueue.cs rename to _old/src/KubeOps/Operator/Controller/IEventQueue.cs diff --git a/src/KubeOps/Operator/Controller/IManagedResourceController.cs b/_old/src/KubeOps/Operator/Controller/IManagedResourceController.cs similarity index 100% rename from src/KubeOps/Operator/Controller/IManagedResourceController.cs rename to _old/src/KubeOps/Operator/Controller/IManagedResourceController.cs diff --git a/src/KubeOps/Operator/Controller/IResourceController{TEntity}.cs b/_old/src/KubeOps/Operator/Controller/IResourceController{TEntity}.cs similarity index 100% rename from src/KubeOps/Operator/Controller/IResourceController{TEntity}.cs rename to _old/src/KubeOps/Operator/Controller/IResourceController{TEntity}.cs diff --git a/src/KubeOps/Operator/Controller/ManagedResourceController{TEntity}.cs b/_old/src/KubeOps/Operator/Controller/ManagedResourceController{TEntity}.cs similarity index 100% rename from src/KubeOps/Operator/Controller/ManagedResourceController{TEntity}.cs rename to _old/src/KubeOps/Operator/Controller/ManagedResourceController{TEntity}.cs diff --git a/src/KubeOps/Operator/Controller/ResourceControllerManager.cs b/_old/src/KubeOps/Operator/Controller/ResourceControllerManager.cs similarity index 100% rename from src/KubeOps/Operator/Controller/ResourceControllerManager.cs rename to _old/src/KubeOps/Operator/Controller/ResourceControllerManager.cs diff --git a/src/KubeOps/Operator/Controller/ResourceEvent.cs b/_old/src/KubeOps/Operator/Controller/ResourceEvent.cs similarity index 100% rename from src/KubeOps/Operator/Controller/ResourceEvent.cs rename to _old/src/KubeOps/Operator/Controller/ResourceEvent.cs diff --git a/src/KubeOps/Operator/Controller/Results/RequeueEventResult.cs b/_old/src/KubeOps/Operator/Controller/Results/RequeueEventResult.cs similarity index 100% rename from src/KubeOps/Operator/Controller/Results/RequeueEventResult.cs rename to _old/src/KubeOps/Operator/Controller/Results/RequeueEventResult.cs diff --git a/src/KubeOps/Operator/Controller/Results/ResourceControllerResult.cs b/_old/src/KubeOps/Operator/Controller/Results/ResourceControllerResult.cs similarity index 100% rename from src/KubeOps/Operator/Controller/Results/ResourceControllerResult.cs rename to _old/src/KubeOps/Operator/Controller/Results/ResourceControllerResult.cs diff --git a/src/KubeOps/Operator/Controller/ScopedResourceController.cs b/_old/src/KubeOps/Operator/Controller/ScopedResourceController.cs similarity index 100% rename from src/KubeOps/Operator/Controller/ScopedResourceController.cs rename to _old/src/KubeOps/Operator/Controller/ScopedResourceController.cs diff --git a/src/KubeOps/Operator/DevOps/IResourceWatcherMetrics{TEntity}.cs b/_old/src/KubeOps/Operator/DevOps/IResourceWatcherMetrics{TEntity}.cs similarity index 100% rename from src/KubeOps/Operator/DevOps/IResourceWatcherMetrics{TEntity}.cs rename to _old/src/KubeOps/Operator/DevOps/IResourceWatcherMetrics{TEntity}.cs diff --git a/src/KubeOps/Operator/DevOps/ResourceCacheMetrics{TEntity}.cs b/_old/src/KubeOps/Operator/DevOps/ResourceCacheMetrics{TEntity}.cs similarity index 100% rename from src/KubeOps/Operator/DevOps/ResourceCacheMetrics{TEntity}.cs rename to _old/src/KubeOps/Operator/DevOps/ResourceCacheMetrics{TEntity}.cs diff --git a/src/KubeOps/Operator/DevOps/ResourceControllerMetrics{TEntity}.cs b/_old/src/KubeOps/Operator/DevOps/ResourceControllerMetrics{TEntity}.cs similarity index 100% rename from src/KubeOps/Operator/DevOps/ResourceControllerMetrics{TEntity}.cs rename to _old/src/KubeOps/Operator/DevOps/ResourceControllerMetrics{TEntity}.cs diff --git a/src/KubeOps/Operator/DevOps/ResourceWatcherMetrics{TEntity}.cs b/_old/src/KubeOps/Operator/DevOps/ResourceWatcherMetrics{TEntity}.cs similarity index 100% rename from src/KubeOps/Operator/DevOps/ResourceWatcherMetrics{TEntity}.cs rename to _old/src/KubeOps/Operator/DevOps/ResourceWatcherMetrics{TEntity}.cs diff --git a/src/KubeOps/Operator/Entities/Annotations/AdditionalPrinterColumnAttribute.cs b/_old/src/KubeOps/Operator/Entities/Annotations/AdditionalPrinterColumnAttribute.cs similarity index 100% rename from src/KubeOps/Operator/Entities/Annotations/AdditionalPrinterColumnAttribute.cs rename to _old/src/KubeOps/Operator/Entities/Annotations/AdditionalPrinterColumnAttribute.cs diff --git a/src/KubeOps/Operator/Entities/Annotations/DescriptionAttribute.cs b/_old/src/KubeOps/Operator/Entities/Annotations/DescriptionAttribute.cs similarity index 100% rename from src/KubeOps/Operator/Entities/Annotations/DescriptionAttribute.cs rename to _old/src/KubeOps/Operator/Entities/Annotations/DescriptionAttribute.cs diff --git a/src/KubeOps/Operator/Entities/Annotations/EmbeddedResourceAttribute.cs b/_old/src/KubeOps/Operator/Entities/Annotations/EmbeddedResourceAttribute.cs similarity index 100% rename from src/KubeOps/Operator/Entities/Annotations/EmbeddedResourceAttribute.cs rename to _old/src/KubeOps/Operator/Entities/Annotations/EmbeddedResourceAttribute.cs diff --git a/src/KubeOps/Operator/Entities/Annotations/ExternalDocsAttribute.cs b/_old/src/KubeOps/Operator/Entities/Annotations/ExternalDocsAttribute.cs similarity index 100% rename from src/KubeOps/Operator/Entities/Annotations/ExternalDocsAttribute.cs rename to _old/src/KubeOps/Operator/Entities/Annotations/ExternalDocsAttribute.cs diff --git a/src/KubeOps/Operator/Entities/Annotations/GenericAdditionalPrinterColumnAttribute.cs b/_old/src/KubeOps/Operator/Entities/Annotations/GenericAdditionalPrinterColumnAttribute.cs similarity index 100% rename from src/KubeOps/Operator/Entities/Annotations/GenericAdditionalPrinterColumnAttribute.cs rename to _old/src/KubeOps/Operator/Entities/Annotations/GenericAdditionalPrinterColumnAttribute.cs diff --git a/src/KubeOps/Operator/Entities/Annotations/IgnoreEntityAttribute.cs b/_old/src/KubeOps/Operator/Entities/Annotations/IgnoreEntityAttribute.cs similarity index 100% rename from src/KubeOps/Operator/Entities/Annotations/IgnoreEntityAttribute.cs rename to _old/src/KubeOps/Operator/Entities/Annotations/IgnoreEntityAttribute.cs diff --git a/src/KubeOps/Operator/Entities/Annotations/IgnorePropertyAttribute.cs b/_old/src/KubeOps/Operator/Entities/Annotations/IgnorePropertyAttribute.cs similarity index 100% rename from src/KubeOps/Operator/Entities/Annotations/IgnorePropertyAttribute.cs rename to _old/src/KubeOps/Operator/Entities/Annotations/IgnorePropertyAttribute.cs diff --git a/src/KubeOps/Operator/Entities/Annotations/ItemsAttribute.cs b/_old/src/KubeOps/Operator/Entities/Annotations/ItemsAttribute.cs similarity index 100% rename from src/KubeOps/Operator/Entities/Annotations/ItemsAttribute.cs rename to _old/src/KubeOps/Operator/Entities/Annotations/ItemsAttribute.cs diff --git a/src/KubeOps/Operator/Entities/Annotations/KubernetesEntityShortNamesAttribute.cs b/_old/src/KubeOps/Operator/Entities/Annotations/KubernetesEntityShortNamesAttribute.cs similarity index 100% rename from src/KubeOps/Operator/Entities/Annotations/KubernetesEntityShortNamesAttribute.cs rename to _old/src/KubeOps/Operator/Entities/Annotations/KubernetesEntityShortNamesAttribute.cs diff --git a/src/KubeOps/Operator/Entities/Annotations/LengthAttribute.cs b/_old/src/KubeOps/Operator/Entities/Annotations/LengthAttribute.cs similarity index 100% rename from src/KubeOps/Operator/Entities/Annotations/LengthAttribute.cs rename to _old/src/KubeOps/Operator/Entities/Annotations/LengthAttribute.cs diff --git a/src/KubeOps/Operator/Entities/Annotations/MultipleOfAttribute.cs b/_old/src/KubeOps/Operator/Entities/Annotations/MultipleOfAttribute.cs similarity index 100% rename from src/KubeOps/Operator/Entities/Annotations/MultipleOfAttribute.cs rename to _old/src/KubeOps/Operator/Entities/Annotations/MultipleOfAttribute.cs diff --git a/src/KubeOps/Operator/Entities/Annotations/PatternAttribute.cs b/_old/src/KubeOps/Operator/Entities/Annotations/PatternAttribute.cs similarity index 100% rename from src/KubeOps/Operator/Entities/Annotations/PatternAttribute.cs rename to _old/src/KubeOps/Operator/Entities/Annotations/PatternAttribute.cs diff --git a/src/KubeOps/Operator/Entities/Annotations/PreserveUnknownFieldsAttribute.cs b/_old/src/KubeOps/Operator/Entities/Annotations/PreserveUnknownFieldsAttribute.cs similarity index 100% rename from src/KubeOps/Operator/Entities/Annotations/PreserveUnknownFieldsAttribute.cs rename to _old/src/KubeOps/Operator/Entities/Annotations/PreserveUnknownFieldsAttribute.cs diff --git a/src/KubeOps/Operator/Entities/Annotations/RangeMaximum.cs b/_old/src/KubeOps/Operator/Entities/Annotations/RangeMaximum.cs similarity index 100% rename from src/KubeOps/Operator/Entities/Annotations/RangeMaximum.cs rename to _old/src/KubeOps/Operator/Entities/Annotations/RangeMaximum.cs diff --git a/src/KubeOps/Operator/Entities/Annotations/RangeMinimum.cs b/_old/src/KubeOps/Operator/Entities/Annotations/RangeMinimum.cs similarity index 100% rename from src/KubeOps/Operator/Entities/Annotations/RangeMinimum.cs rename to _old/src/KubeOps/Operator/Entities/Annotations/RangeMinimum.cs diff --git a/src/KubeOps/Operator/Entities/Annotations/RequiredAttribute.cs b/_old/src/KubeOps/Operator/Entities/Annotations/RequiredAttribute.cs similarity index 100% rename from src/KubeOps/Operator/Entities/Annotations/RequiredAttribute.cs rename to _old/src/KubeOps/Operator/Entities/Annotations/RequiredAttribute.cs diff --git a/src/KubeOps/Operator/Entities/Annotations/StorageVersionAttribute.cs b/_old/src/KubeOps/Operator/Entities/Annotations/StorageVersionAttribute.cs similarity index 100% rename from src/KubeOps/Operator/Entities/Annotations/StorageVersionAttribute.cs rename to _old/src/KubeOps/Operator/Entities/Annotations/StorageVersionAttribute.cs diff --git a/src/KubeOps/Operator/Entities/CrdBuilder.cs b/_old/src/KubeOps/Operator/Entities/CrdBuilder.cs similarity index 100% rename from src/KubeOps/Operator/Entities/CrdBuilder.cs rename to _old/src/KubeOps/Operator/Entities/CrdBuilder.cs diff --git a/src/KubeOps/Operator/Entities/CrdBuilderResourceQuantityOverride.cs b/_old/src/KubeOps/Operator/Entities/CrdBuilderResourceQuantityOverride.cs similarity index 100% rename from src/KubeOps/Operator/Entities/CrdBuilderResourceQuantityOverride.cs rename to _old/src/KubeOps/Operator/Entities/CrdBuilderResourceQuantityOverride.cs diff --git a/src/KubeOps/Operator/Entities/CustomKubernetesEntity.cs b/_old/src/KubeOps/Operator/Entities/CustomKubernetesEntity.cs similarity index 100% rename from src/KubeOps/Operator/Entities/CustomKubernetesEntity.cs rename to _old/src/KubeOps/Operator/Entities/CustomKubernetesEntity.cs diff --git a/src/KubeOps/Operator/Entities/CustomKubernetesEntity{TSpec,TStatus}.cs b/_old/src/KubeOps/Operator/Entities/CustomKubernetesEntity{TSpec,TStatus}.cs similarity index 100% rename from src/KubeOps/Operator/Entities/CustomKubernetesEntity{TSpec,TStatus}.cs rename to _old/src/KubeOps/Operator/Entities/CustomKubernetesEntity{TSpec,TStatus}.cs diff --git a/src/KubeOps/Operator/Entities/CustomKubernetesEntity{TSpec}.cs b/_old/src/KubeOps/Operator/Entities/CustomKubernetesEntity{TSpec}.cs similarity index 100% rename from src/KubeOps/Operator/Entities/CustomKubernetesEntity{TSpec}.cs rename to _old/src/KubeOps/Operator/Entities/CustomKubernetesEntity{TSpec}.cs diff --git a/src/KubeOps/Operator/Entities/EntityList.cs b/_old/src/KubeOps/Operator/Entities/EntityList.cs similarity index 100% rename from src/KubeOps/Operator/Entities/EntityList.cs rename to _old/src/KubeOps/Operator/Entities/EntityList.cs diff --git a/src/KubeOps/Operator/Entities/Extensions/DeepCloneExtensions.cs b/_old/src/KubeOps/Operator/Entities/Extensions/DeepCloneExtensions.cs similarity index 100% rename from src/KubeOps/Operator/Entities/Extensions/DeepCloneExtensions.cs rename to _old/src/KubeOps/Operator/Entities/Extensions/DeepCloneExtensions.cs diff --git a/src/KubeOps/Operator/Entities/Extensions/EntityToCrdExtensions.cs b/_old/src/KubeOps/Operator/Entities/Extensions/EntityToCrdExtensions.cs similarity index 100% rename from src/KubeOps/Operator/Entities/Extensions/EntityToCrdExtensions.cs rename to _old/src/KubeOps/Operator/Entities/Extensions/EntityToCrdExtensions.cs diff --git a/src/KubeOps/Operator/Entities/Extensions/KubernetesObjectExtensions.cs b/_old/src/KubeOps/Operator/Entities/Extensions/KubernetesObjectExtensions.cs similarity index 100% rename from src/KubeOps/Operator/Entities/Extensions/KubernetesObjectExtensions.cs rename to _old/src/KubeOps/Operator/Entities/Extensions/KubernetesObjectExtensions.cs diff --git a/src/KubeOps/Operator/Entities/Extensions/V1SecretExtensions.cs b/_old/src/KubeOps/Operator/Entities/Extensions/V1SecretExtensions.cs similarity index 100% rename from src/KubeOps/Operator/Entities/Extensions/V1SecretExtensions.cs rename to _old/src/KubeOps/Operator/Entities/Extensions/V1SecretExtensions.cs diff --git a/src/KubeOps/Operator/Entities/ICrdBuilder.cs b/_old/src/KubeOps/Operator/Entities/ICrdBuilder.cs similarity index 100% rename from src/KubeOps/Operator/Entities/ICrdBuilder.cs rename to _old/src/KubeOps/Operator/Entities/ICrdBuilder.cs diff --git a/src/KubeOps/Operator/Entities/ICrdBuilderTypeOverride.cs b/_old/src/KubeOps/Operator/Entities/ICrdBuilderTypeOverride.cs similarity index 100% rename from src/KubeOps/Operator/Entities/ICrdBuilderTypeOverride.cs rename to _old/src/KubeOps/Operator/Entities/ICrdBuilderTypeOverride.cs diff --git a/src/KubeOps/Operator/Entities/Kustomize/KustomizationConfig.cs b/_old/src/KubeOps/Operator/Entities/Kustomize/KustomizationConfig.cs similarity index 100% rename from src/KubeOps/Operator/Entities/Kustomize/KustomizationConfig.cs rename to _old/src/KubeOps/Operator/Entities/Kustomize/KustomizationConfig.cs diff --git a/src/KubeOps/Operator/Entities/Kustomize/KustomizationConfigMapGenerator.cs b/_old/src/KubeOps/Operator/Entities/Kustomize/KustomizationConfigMapGenerator.cs similarity index 100% rename from src/KubeOps/Operator/Entities/Kustomize/KustomizationConfigMapGenerator.cs rename to _old/src/KubeOps/Operator/Entities/Kustomize/KustomizationConfigMapGenerator.cs diff --git a/src/KubeOps/Operator/Entities/Kustomize/KustomizationImage.cs b/_old/src/KubeOps/Operator/Entities/Kustomize/KustomizationImage.cs similarity index 100% rename from src/KubeOps/Operator/Entities/Kustomize/KustomizationImage.cs rename to _old/src/KubeOps/Operator/Entities/Kustomize/KustomizationImage.cs diff --git a/src/KubeOps/Operator/Errors/BackoffStrategies.cs b/_old/src/KubeOps/Operator/Errors/BackoffStrategies.cs similarity index 100% rename from src/KubeOps/Operator/Errors/BackoffStrategies.cs rename to _old/src/KubeOps/Operator/Errors/BackoffStrategies.cs diff --git a/src/KubeOps/Operator/Errors/CrdConversionException.cs b/_old/src/KubeOps/Operator/Errors/CrdConversionException.cs similarity index 100% rename from src/KubeOps/Operator/Errors/CrdConversionException.cs rename to _old/src/KubeOps/Operator/Errors/CrdConversionException.cs diff --git a/src/KubeOps/Operator/Errors/CrdPropertyTypeException.cs b/_old/src/KubeOps/Operator/Errors/CrdPropertyTypeException.cs similarity index 100% rename from src/KubeOps/Operator/Errors/CrdPropertyTypeException.cs rename to _old/src/KubeOps/Operator/Errors/CrdPropertyTypeException.cs diff --git a/src/KubeOps/Operator/Events/EventManager.cs b/_old/src/KubeOps/Operator/Events/EventManager.cs similarity index 100% rename from src/KubeOps/Operator/Events/EventManager.cs rename to _old/src/KubeOps/Operator/Events/EventManager.cs diff --git a/src/KubeOps/Operator/Events/EventType.cs b/_old/src/KubeOps/Operator/Events/EventType.cs similarity index 100% rename from src/KubeOps/Operator/Events/EventType.cs rename to _old/src/KubeOps/Operator/Events/EventType.cs diff --git a/src/KubeOps/Operator/Events/IEventManager.cs b/_old/src/KubeOps/Operator/Events/IEventManager.cs similarity index 100% rename from src/KubeOps/Operator/Events/IEventManager.cs rename to _old/src/KubeOps/Operator/Events/IEventManager.cs diff --git a/src/KubeOps/Operator/Finalizer/FinalizerInstanceBuilder.cs b/_old/src/KubeOps/Operator/Finalizer/FinalizerInstanceBuilder.cs similarity index 100% rename from src/KubeOps/Operator/Finalizer/FinalizerInstanceBuilder.cs rename to _old/src/KubeOps/Operator/Finalizer/FinalizerInstanceBuilder.cs diff --git a/src/KubeOps/Operator/Finalizer/FinalizerManager{TEntity}.cs b/_old/src/KubeOps/Operator/Finalizer/FinalizerManager{TEntity}.cs similarity index 100% rename from src/KubeOps/Operator/Finalizer/FinalizerManager{TEntity}.cs rename to _old/src/KubeOps/Operator/Finalizer/FinalizerManager{TEntity}.cs diff --git a/src/KubeOps/Operator/Finalizer/IFinalizerInstanceBuilder.cs b/_old/src/KubeOps/Operator/Finalizer/IFinalizerInstanceBuilder.cs similarity index 100% rename from src/KubeOps/Operator/Finalizer/IFinalizerInstanceBuilder.cs rename to _old/src/KubeOps/Operator/Finalizer/IFinalizerInstanceBuilder.cs diff --git a/src/KubeOps/Operator/Finalizer/IFinalizerManager{TEntity}.cs b/_old/src/KubeOps/Operator/Finalizer/IFinalizerManager{TEntity}.cs similarity index 100% rename from src/KubeOps/Operator/Finalizer/IFinalizerManager{TEntity}.cs rename to _old/src/KubeOps/Operator/Finalizer/IFinalizerManager{TEntity}.cs diff --git a/src/KubeOps/Operator/Finalizer/IResourceFinalizer.cs b/_old/src/KubeOps/Operator/Finalizer/IResourceFinalizer.cs similarity index 100% rename from src/KubeOps/Operator/Finalizer/IResourceFinalizer.cs rename to _old/src/KubeOps/Operator/Finalizer/IResourceFinalizer.cs diff --git a/src/KubeOps/Operator/HashSetExtensions.cs b/_old/src/KubeOps/Operator/HashSetExtensions.cs similarity index 100% rename from src/KubeOps/Operator/HashSetExtensions.cs rename to _old/src/KubeOps/Operator/HashSetExtensions.cs diff --git a/src/KubeOps/Operator/HostExtensions.cs b/_old/src/KubeOps/Operator/HostExtensions.cs similarity index 100% rename from src/KubeOps/Operator/HostExtensions.cs rename to _old/src/KubeOps/Operator/HostExtensions.cs diff --git a/src/KubeOps/Operator/Kubernetes/IResourceWatcher.cs b/_old/src/KubeOps/Operator/Kubernetes/IResourceWatcher.cs similarity index 100% rename from src/KubeOps/Operator/Kubernetes/IResourceWatcher.cs rename to _old/src/KubeOps/Operator/Kubernetes/IResourceWatcher.cs diff --git a/src/KubeOps/Operator/Kubernetes/ResourceEventType.cs b/_old/src/KubeOps/Operator/Kubernetes/ResourceEventType.cs similarity index 100% rename from src/KubeOps/Operator/Kubernetes/ResourceEventType.cs rename to _old/src/KubeOps/Operator/Kubernetes/ResourceEventType.cs diff --git a/src/KubeOps/Operator/Kubernetes/ResourceWatcher{TEntity}.cs b/_old/src/KubeOps/Operator/Kubernetes/ResourceWatcher{TEntity}.cs similarity index 100% rename from src/KubeOps/Operator/Kubernetes/ResourceWatcher{TEntity}.cs rename to _old/src/KubeOps/Operator/Kubernetes/ResourceWatcher{TEntity}.cs diff --git a/src/KubeOps/Operator/Leadership/DisabledLeaderElection.cs b/_old/src/KubeOps/Operator/Leadership/DisabledLeaderElection.cs similarity index 100% rename from src/KubeOps/Operator/Leadership/DisabledLeaderElection.cs rename to _old/src/KubeOps/Operator/Leadership/DisabledLeaderElection.cs diff --git a/src/KubeOps/Operator/Leadership/ILeaderElection.cs b/_old/src/KubeOps/Operator/Leadership/ILeaderElection.cs similarity index 100% rename from src/KubeOps/Operator/Leadership/ILeaderElection.cs rename to _old/src/KubeOps/Operator/Leadership/ILeaderElection.cs diff --git a/src/KubeOps/Operator/Leadership/LeaderElection.cs b/_old/src/KubeOps/Operator/Leadership/LeaderElection.cs similarity index 100% rename from src/KubeOps/Operator/Leadership/LeaderElection.cs rename to _old/src/KubeOps/Operator/Leadership/LeaderElection.cs diff --git a/src/KubeOps/Operator/Leadership/LeaderElector.cs b/_old/src/KubeOps/Operator/Leadership/LeaderElector.cs similarity index 100% rename from src/KubeOps/Operator/Leadership/LeaderElector.cs rename to _old/src/KubeOps/Operator/Leadership/LeaderElector.cs diff --git a/src/KubeOps/Operator/Leadership/LeaderState.cs b/_old/src/KubeOps/Operator/Leadership/LeaderState.cs similarity index 100% rename from src/KubeOps/Operator/Leadership/LeaderState.cs rename to _old/src/KubeOps/Operator/Leadership/LeaderState.cs diff --git a/src/KubeOps/Operator/OperatorBuilderExtensions.cs b/_old/src/KubeOps/Operator/OperatorBuilderExtensions.cs similarity index 100% rename from src/KubeOps/Operator/OperatorBuilderExtensions.cs rename to _old/src/KubeOps/Operator/OperatorBuilderExtensions.cs diff --git a/src/KubeOps/Operator/OperatorSettings.cs b/_old/src/KubeOps/Operator/OperatorSettings.cs similarity index 100% rename from src/KubeOps/Operator/OperatorSettings.cs rename to _old/src/KubeOps/Operator/OperatorSettings.cs diff --git a/src/KubeOps/Operator/Rbac/EntityRbacAttribute.cs b/_old/src/KubeOps/Operator/Rbac/EntityRbacAttribute.cs similarity index 100% rename from src/KubeOps/Operator/Rbac/EntityRbacAttribute.cs rename to _old/src/KubeOps/Operator/Rbac/EntityRbacAttribute.cs diff --git a/src/KubeOps/Operator/Rbac/GenericRbacAttribute.cs b/_old/src/KubeOps/Operator/Rbac/GenericRbacAttribute.cs similarity index 100% rename from src/KubeOps/Operator/Rbac/GenericRbacAttribute.cs rename to _old/src/KubeOps/Operator/Rbac/GenericRbacAttribute.cs diff --git a/src/KubeOps/Operator/Rbac/IRbacBuilder.cs b/_old/src/KubeOps/Operator/Rbac/IRbacBuilder.cs similarity index 100% rename from src/KubeOps/Operator/Rbac/IRbacBuilder.cs rename to _old/src/KubeOps/Operator/Rbac/IRbacBuilder.cs diff --git a/src/KubeOps/Operator/Rbac/RbacAttributeExtensions.cs b/_old/src/KubeOps/Operator/Rbac/RbacAttributeExtensions.cs similarity index 100% rename from src/KubeOps/Operator/Rbac/RbacAttributeExtensions.cs rename to _old/src/KubeOps/Operator/Rbac/RbacAttributeExtensions.cs diff --git a/src/KubeOps/Operator/Rbac/RbacBuilder.cs b/_old/src/KubeOps/Operator/Rbac/RbacBuilder.cs similarity index 100% rename from src/KubeOps/Operator/Rbac/RbacBuilder.cs rename to _old/src/KubeOps/Operator/Rbac/RbacBuilder.cs diff --git a/src/KubeOps/Operator/Rbac/RbacVerbs.cs b/_old/src/KubeOps/Operator/Rbac/RbacVerbs.cs similarity index 100% rename from src/KubeOps/Operator/Rbac/RbacVerbs.cs rename to _old/src/KubeOps/Operator/Rbac/RbacVerbs.cs diff --git a/src/KubeOps/Operator/Serialization/EntitySerializer.cs b/_old/src/KubeOps/Operator/Serialization/EntitySerializer.cs similarity index 100% rename from src/KubeOps/Operator/Serialization/EntitySerializer.cs rename to _old/src/KubeOps/Operator/Serialization/EntitySerializer.cs diff --git a/src/KubeOps/Operator/Serialization/SerializerOutputFormat.cs b/_old/src/KubeOps/Operator/Serialization/SerializerOutputFormat.cs similarity index 100% rename from src/KubeOps/Operator/Serialization/SerializerOutputFormat.cs rename to _old/src/KubeOps/Operator/Serialization/SerializerOutputFormat.cs diff --git a/src/KubeOps/Operator/ServiceCollectionExtensions.cs b/_old/src/KubeOps/Operator/ServiceCollectionExtensions.cs similarity index 100% rename from src/KubeOps/Operator/ServiceCollectionExtensions.cs rename to _old/src/KubeOps/Operator/ServiceCollectionExtensions.cs diff --git a/src/KubeOps/Operator/Util/StringExtensions.cs b/_old/src/KubeOps/Operator/Util/StringExtensions.cs similarity index 100% rename from src/KubeOps/Operator/Util/StringExtensions.cs rename to _old/src/KubeOps/Operator/Util/StringExtensions.cs diff --git a/src/KubeOps/Operator/Webhooks/AdmissionOperations.cs b/_old/src/KubeOps/Operator/Webhooks/AdmissionOperations.cs similarity index 100% rename from src/KubeOps/Operator/Webhooks/AdmissionOperations.cs rename to _old/src/KubeOps/Operator/Webhooks/AdmissionOperations.cs diff --git a/src/KubeOps/Operator/Webhooks/AdmissionRequest.cs b/_old/src/KubeOps/Operator/Webhooks/AdmissionRequest.cs similarity index 100% rename from src/KubeOps/Operator/Webhooks/AdmissionRequest.cs rename to _old/src/KubeOps/Operator/Webhooks/AdmissionRequest.cs diff --git a/src/KubeOps/Operator/Webhooks/AdmissionResponse.cs b/_old/src/KubeOps/Operator/Webhooks/AdmissionResponse.cs similarity index 100% rename from src/KubeOps/Operator/Webhooks/AdmissionResponse.cs rename to _old/src/KubeOps/Operator/Webhooks/AdmissionResponse.cs diff --git a/src/KubeOps/Operator/Webhooks/AdmissionResult.cs b/_old/src/KubeOps/Operator/Webhooks/AdmissionResult.cs similarity index 100% rename from src/KubeOps/Operator/Webhooks/AdmissionResult.cs rename to _old/src/KubeOps/Operator/Webhooks/AdmissionResult.cs diff --git a/src/KubeOps/Operator/Webhooks/AdmissionReview{TEntity}.cs b/_old/src/KubeOps/Operator/Webhooks/AdmissionReview{TEntity}.cs similarity index 100% rename from src/KubeOps/Operator/Webhooks/AdmissionReview{TEntity}.cs rename to _old/src/KubeOps/Operator/Webhooks/AdmissionReview{TEntity}.cs diff --git a/src/KubeOps/Operator/Webhooks/IAdmissionWebhook{TEntity, TResult}.cs b/_old/src/KubeOps/Operator/Webhooks/IAdmissionWebhook{TEntity, TResult}.cs similarity index 100% rename from src/KubeOps/Operator/Webhooks/IAdmissionWebhook{TEntity, TResult}.cs rename to _old/src/KubeOps/Operator/Webhooks/IAdmissionWebhook{TEntity, TResult}.cs diff --git a/src/KubeOps/Operator/Webhooks/IConfigurableMutationWebhook.cs b/_old/src/KubeOps/Operator/Webhooks/IConfigurableMutationWebhook.cs similarity index 100% rename from src/KubeOps/Operator/Webhooks/IConfigurableMutationWebhook.cs rename to _old/src/KubeOps/Operator/Webhooks/IConfigurableMutationWebhook.cs diff --git a/src/KubeOps/Operator/Webhooks/IConfigurableValidationWebhook.cs b/_old/src/KubeOps/Operator/Webhooks/IConfigurableValidationWebhook.cs similarity index 100% rename from src/KubeOps/Operator/Webhooks/IConfigurableValidationWebhook.cs rename to _old/src/KubeOps/Operator/Webhooks/IConfigurableValidationWebhook.cs diff --git a/src/KubeOps/Operator/Webhooks/IMutationWebhook{TEntity}.cs b/_old/src/KubeOps/Operator/Webhooks/IMutationWebhook{TEntity}.cs similarity index 100% rename from src/KubeOps/Operator/Webhooks/IMutationWebhook{TEntity}.cs rename to _old/src/KubeOps/Operator/Webhooks/IMutationWebhook{TEntity}.cs diff --git a/src/KubeOps/Operator/Webhooks/IValidationWebhook{TEntity}.cs b/_old/src/KubeOps/Operator/Webhooks/IValidationWebhook{TEntity}.cs similarity index 100% rename from src/KubeOps/Operator/Webhooks/IValidationWebhook{TEntity}.cs rename to _old/src/KubeOps/Operator/Webhooks/IValidationWebhook{TEntity}.cs diff --git a/src/KubeOps/Operator/Webhooks/IWebhookMetadataBuilder.cs b/_old/src/KubeOps/Operator/Webhooks/IWebhookMetadataBuilder.cs similarity index 100% rename from src/KubeOps/Operator/Webhooks/IWebhookMetadataBuilder.cs rename to _old/src/KubeOps/Operator/Webhooks/IWebhookMetadataBuilder.cs diff --git a/src/KubeOps/Operator/Webhooks/KubernetesJsonDiffer.cs b/_old/src/KubeOps/Operator/Webhooks/KubernetesJsonDiffer.cs similarity index 100% rename from src/KubeOps/Operator/Webhooks/KubernetesJsonDiffer.cs rename to _old/src/KubeOps/Operator/Webhooks/KubernetesJsonDiffer.cs diff --git a/src/KubeOps/Operator/Webhooks/MutatingWebhookBuilder.cs b/_old/src/KubeOps/Operator/Webhooks/MutatingWebhookBuilder.cs similarity index 100% rename from src/KubeOps/Operator/Webhooks/MutatingWebhookBuilder.cs rename to _old/src/KubeOps/Operator/Webhooks/MutatingWebhookBuilder.cs diff --git a/src/KubeOps/Operator/Webhooks/MutatingWebhookConfigurationBuilder.cs b/_old/src/KubeOps/Operator/Webhooks/MutatingWebhookConfigurationBuilder.cs similarity index 100% rename from src/KubeOps/Operator/Webhooks/MutatingWebhookConfigurationBuilder.cs rename to _old/src/KubeOps/Operator/Webhooks/MutatingWebhookConfigurationBuilder.cs diff --git a/src/KubeOps/Operator/Webhooks/MutationResult.cs b/_old/src/KubeOps/Operator/Webhooks/MutationResult.cs similarity index 100% rename from src/KubeOps/Operator/Webhooks/MutationResult.cs rename to _old/src/KubeOps/Operator/Webhooks/MutationResult.cs diff --git a/src/KubeOps/Operator/Webhooks/ValidatingWebhookBuilder.cs b/_old/src/KubeOps/Operator/Webhooks/ValidatingWebhookBuilder.cs similarity index 100% rename from src/KubeOps/Operator/Webhooks/ValidatingWebhookBuilder.cs rename to _old/src/KubeOps/Operator/Webhooks/ValidatingWebhookBuilder.cs diff --git a/src/KubeOps/Operator/Webhooks/ValidatingWebhookConfigurationBuilder.cs b/_old/src/KubeOps/Operator/Webhooks/ValidatingWebhookConfigurationBuilder.cs similarity index 100% rename from src/KubeOps/Operator/Webhooks/ValidatingWebhookConfigurationBuilder.cs rename to _old/src/KubeOps/Operator/Webhooks/ValidatingWebhookConfigurationBuilder.cs diff --git a/src/KubeOps/Operator/Webhooks/ValidationResult.cs b/_old/src/KubeOps/Operator/Webhooks/ValidationResult.cs similarity index 100% rename from src/KubeOps/Operator/Webhooks/ValidationResult.cs rename to _old/src/KubeOps/Operator/Webhooks/ValidationResult.cs diff --git a/src/KubeOps/Operator/Webhooks/WebhookConfig.cs b/_old/src/KubeOps/Operator/Webhooks/WebhookConfig.cs similarity index 100% rename from src/KubeOps/Operator/Webhooks/WebhookConfig.cs rename to _old/src/KubeOps/Operator/Webhooks/WebhookConfig.cs diff --git a/src/KubeOps/Operator/Webhooks/WebhookEndpointFactory.cs b/_old/src/KubeOps/Operator/Webhooks/WebhookEndpointFactory.cs similarity index 100% rename from src/KubeOps/Operator/Webhooks/WebhookEndpointFactory.cs rename to _old/src/KubeOps/Operator/Webhooks/WebhookEndpointFactory.cs diff --git a/src/KubeOps/Operator/Webhooks/WebhookLocalTunnel.cs b/_old/src/KubeOps/Operator/Webhooks/WebhookLocalTunnel.cs similarity index 100% rename from src/KubeOps/Operator/Webhooks/WebhookLocalTunnel.cs rename to _old/src/KubeOps/Operator/Webhooks/WebhookLocalTunnel.cs diff --git a/src/KubeOps/Operator/Webhooks/WebhookMetadataBuilder.cs b/_old/src/KubeOps/Operator/Webhooks/WebhookMetadataBuilder.cs similarity index 100% rename from src/KubeOps/Operator/Webhooks/WebhookMetadataBuilder.cs rename to _old/src/KubeOps/Operator/Webhooks/WebhookMetadataBuilder.cs diff --git a/src/KubeOps/README.md b/_old/src/KubeOps/README.md similarity index 100% rename from src/KubeOps/README.md rename to _old/src/KubeOps/README.md diff --git a/tests/KubeOps.KubernetesClient.Test/KubeOps.KubernetesClient.Test.csproj b/_old/tests/KubeOps.KubernetesClient.Test/KubeOps.KubernetesClient.Test.csproj similarity index 100% rename from tests/KubeOps.KubernetesClient.Test/KubeOps.KubernetesClient.Test.csproj rename to _old/tests/KubeOps.KubernetesClient.Test/KubeOps.KubernetesClient.Test.csproj diff --git a/tests/KubeOps.KubernetesClient.Test/KubernetesClientTest.cs b/_old/tests/KubeOps.KubernetesClient.Test/KubernetesClientTest.cs similarity index 100% rename from tests/KubeOps.KubernetesClient.Test/KubernetesClientTest.cs rename to _old/tests/KubeOps.KubernetesClient.Test/KubernetesClientTest.cs diff --git a/tests/KubeOps.Templates.Test/DotnetExecutor.cs b/_old/tests/KubeOps.Templates.Test/DotnetExecutor.cs similarity index 100% rename from tests/KubeOps.Templates.Test/DotnetExecutor.cs rename to _old/tests/KubeOps.Templates.Test/DotnetExecutor.cs diff --git a/tests/KubeOps.Templates.Test/KubeOps.Templates.Test.csproj b/_old/tests/KubeOps.Templates.Test/KubeOps.Templates.Test.csproj similarity index 100% rename from tests/KubeOps.Templates.Test/KubeOps.Templates.Test.csproj rename to _old/tests/KubeOps.Templates.Test/KubeOps.Templates.Test.csproj diff --git a/tests/KubeOps.Templates.Test/TemplateExecutor.cs b/_old/tests/KubeOps.Templates.Test/TemplateExecutor.cs similarity index 100% rename from tests/KubeOps.Templates.Test/TemplateExecutor.cs rename to _old/tests/KubeOps.Templates.Test/TemplateExecutor.cs diff --git a/tests/KubeOps.Templates.Test/TemplateInstaller.cs b/_old/tests/KubeOps.Templates.Test/TemplateInstaller.cs similarity index 100% rename from tests/KubeOps.Templates.Test/TemplateInstaller.cs rename to _old/tests/KubeOps.Templates.Test/TemplateInstaller.cs diff --git a/tests/KubeOps.Templates.Test/Templates/Empty.CSharp.Test.cs b/_old/tests/KubeOps.Templates.Test/Templates/Empty.CSharp.Test.cs similarity index 100% rename from tests/KubeOps.Templates.Test/Templates/Empty.CSharp.Test.cs rename to _old/tests/KubeOps.Templates.Test/Templates/Empty.CSharp.Test.cs diff --git a/tests/KubeOps.Templates.Test/Templates/Empty.FSharp.Test.cs b/_old/tests/KubeOps.Templates.Test/Templates/Empty.FSharp.Test.cs similarity index 100% rename from tests/KubeOps.Templates.Test/Templates/Empty.FSharp.Test.cs rename to _old/tests/KubeOps.Templates.Test/Templates/Empty.FSharp.Test.cs diff --git a/tests/KubeOps.Templates.Test/Templates/Operator.CSharp.Test.cs b/_old/tests/KubeOps.Templates.Test/Templates/Operator.CSharp.Test.cs similarity index 100% rename from tests/KubeOps.Templates.Test/Templates/Operator.CSharp.Test.cs rename to _old/tests/KubeOps.Templates.Test/Templates/Operator.CSharp.Test.cs diff --git a/tests/KubeOps.Templates.Test/Templates/Operator.FSharp.Test.cs b/_old/tests/KubeOps.Templates.Test/Templates/Operator.FSharp.Test.cs similarity index 100% rename from tests/KubeOps.Templates.Test/Templates/Operator.FSharp.Test.cs rename to _old/tests/KubeOps.Templates.Test/Templates/Operator.FSharp.Test.cs diff --git a/tests/KubeOps.Templates.Test/Templates/TemplateTestCollection.cs b/_old/tests/KubeOps.Templates.Test/Templates/TemplateTestCollection.cs similarity index 100% rename from tests/KubeOps.Templates.Test/Templates/TemplateTestCollection.cs rename to _old/tests/KubeOps.Templates.Test/Templates/TemplateTestCollection.cs diff --git a/tests/KubeOps.Test/KubeOps.Test.csproj b/_old/tests/KubeOps.Test/KubeOps.Test.csproj similarity index 100% rename from tests/KubeOps.Test/KubeOps.Test.csproj rename to _old/tests/KubeOps.Test/KubeOps.Test.csproj diff --git a/tests/KubeOps.Test/Operator/Caching/ResourceCache.Test.cs b/_old/tests/KubeOps.Test/Operator/Caching/ResourceCache.Test.cs similarity index 100% rename from tests/KubeOps.Test/Operator/Caching/ResourceCache.Test.cs rename to _old/tests/KubeOps.Test/Operator/Caching/ResourceCache.Test.cs diff --git a/tests/KubeOps.Test/Operator/Controller/EventQueue.Test.cs b/_old/tests/KubeOps.Test/Operator/Controller/EventQueue.Test.cs similarity index 100% rename from tests/KubeOps.Test/Operator/Controller/EventQueue.Test.cs rename to _old/tests/KubeOps.Test/Operator/Controller/EventQueue.Test.cs diff --git a/tests/KubeOps.Test/Operator/Entities/CrdGeneration.Test.cs b/_old/tests/KubeOps.Test/Operator/Entities/CrdGeneration.Test.cs similarity index 100% rename from tests/KubeOps.Test/Operator/Entities/CrdGeneration.Test.cs rename to _old/tests/KubeOps.Test/Operator/Entities/CrdGeneration.Test.cs diff --git a/tests/KubeOps.Test/Operator/Events/EventManager.Test.cs b/_old/tests/KubeOps.Test/Operator/Events/EventManager.Test.cs similarity index 100% rename from tests/KubeOps.Test/Operator/Events/EventManager.Test.cs rename to _old/tests/KubeOps.Test/Operator/Events/EventManager.Test.cs diff --git a/tests/KubeOps.Test/Operator/Finalizer/ResourceFinalizer.Test.cs b/_old/tests/KubeOps.Test/Operator/Finalizer/ResourceFinalizer.Test.cs similarity index 100% rename from tests/KubeOps.Test/Operator/Finalizer/ResourceFinalizer.Test.cs rename to _old/tests/KubeOps.Test/Operator/Finalizer/ResourceFinalizer.Test.cs diff --git a/tests/KubeOps.Test/Operator/Generators/CrdGenerator.Test.cs b/_old/tests/KubeOps.Test/Operator/Generators/CrdGenerator.Test.cs similarity index 100% rename from tests/KubeOps.Test/Operator/Generators/CrdGenerator.Test.cs rename to _old/tests/KubeOps.Test/Operator/Generators/CrdGenerator.Test.cs diff --git a/tests/KubeOps.Test/Operator/Generators/RbacGenerator.Test.cs b/_old/tests/KubeOps.Test/Operator/Generators/RbacGenerator.Test.cs similarity index 100% rename from tests/KubeOps.Test/Operator/Generators/RbacGenerator.Test.cs rename to _old/tests/KubeOps.Test/Operator/Generators/RbacGenerator.Test.cs diff --git a/tests/KubeOps.Test/Operator/Kubernetes/ResourceWatcher{TEntity}.Test.cs b/_old/tests/KubeOps.Test/Operator/Kubernetes/ResourceWatcher{TEntity}.Test.cs similarity index 100% rename from tests/KubeOps.Test/Operator/Kubernetes/ResourceWatcher{TEntity}.Test.cs rename to _old/tests/KubeOps.Test/Operator/Kubernetes/ResourceWatcher{TEntity}.Test.cs diff --git a/tests/KubeOps.Test/Operator/Leadership/LeaderElector.Test.cs b/_old/tests/KubeOps.Test/Operator/Leadership/LeaderElector.Test.cs similarity index 100% rename from tests/KubeOps.Test/Operator/Leadership/LeaderElector.Test.cs rename to _old/tests/KubeOps.Test/Operator/Leadership/LeaderElector.Test.cs diff --git a/tests/KubeOps.Test/Operator/Webhook/KubernetesJsonDiffer.Test.cs b/_old/tests/KubeOps.Test/Operator/Webhook/KubernetesJsonDiffer.Test.cs similarity index 100% rename from tests/KubeOps.Test/Operator/Webhook/KubernetesJsonDiffer.Test.cs rename to _old/tests/KubeOps.Test/Operator/Webhook/KubernetesJsonDiffer.Test.cs diff --git a/tests/KubeOps.Test/Operator/Webhook/WebhookEndpointFactory.Test.cs b/_old/tests/KubeOps.Test/Operator/Webhook/WebhookEndpointFactory.Test.cs similarity index 100% rename from tests/KubeOps.Test/Operator/Webhook/WebhookEndpointFactory.Test.cs rename to _old/tests/KubeOps.Test/Operator/Webhook/WebhookEndpointFactory.Test.cs diff --git a/tests/KubeOps.Test/TestEntities/TestCustomCrdTypeOverrides.cs b/_old/tests/KubeOps.Test/TestEntities/TestCustomCrdTypeOverrides.cs similarity index 100% rename from tests/KubeOps.Test/TestEntities/TestCustomCrdTypeOverrides.cs rename to _old/tests/KubeOps.Test/TestEntities/TestCustomCrdTypeOverrides.cs diff --git a/tests/KubeOps.Test/TestEntities/TestIgnoredEntity.cs b/_old/tests/KubeOps.Test/TestEntities/TestIgnoredEntity.cs similarity index 100% rename from tests/KubeOps.Test/TestEntities/TestIgnoredEntity.cs rename to _old/tests/KubeOps.Test/TestEntities/TestIgnoredEntity.cs diff --git a/tests/KubeOps.Test/TestEntities/TestInvalidEntity.cs b/_old/tests/KubeOps.Test/TestEntities/TestInvalidEntity.cs similarity index 100% rename from tests/KubeOps.Test/TestEntities/TestInvalidEntity.cs rename to _old/tests/KubeOps.Test/TestEntities/TestInvalidEntity.cs diff --git a/tests/KubeOps.Test/TestEntities/TestSpecEntity.cs b/_old/tests/KubeOps.Test/TestEntities/TestSpecEntity.cs similarity index 100% rename from tests/KubeOps.Test/TestEntities/TestSpecEntity.cs rename to _old/tests/KubeOps.Test/TestEntities/TestSpecEntity.cs diff --git a/tests/KubeOps.Test/TestEntities/TestStatusEntity.cs b/_old/tests/KubeOps.Test/TestEntities/TestStatusEntity.cs similarity index 100% rename from tests/KubeOps.Test/TestEntities/TestStatusEntity.cs rename to _old/tests/KubeOps.Test/TestEntities/TestStatusEntity.cs diff --git a/tests/KubeOps.Test/TestEntities/V1Alpha1VersionedEntity.cs b/_old/tests/KubeOps.Test/TestEntities/V1Alpha1VersionedEntity.cs similarity index 100% rename from tests/KubeOps.Test/TestEntities/V1Alpha1VersionedEntity.cs rename to _old/tests/KubeOps.Test/TestEntities/V1Alpha1VersionedEntity.cs diff --git a/tests/KubeOps.Test/TestEntities/V1AttributeVersionedEntity.cs b/_old/tests/KubeOps.Test/TestEntities/V1AttributeVersionedEntity.cs similarity index 100% rename from tests/KubeOps.Test/TestEntities/V1AttributeVersionedEntity.cs rename to _old/tests/KubeOps.Test/TestEntities/V1AttributeVersionedEntity.cs diff --git a/tests/KubeOps.Test/TestEntities/V1Beta1VersionedEntity.cs b/_old/tests/KubeOps.Test/TestEntities/V1Beta1VersionedEntity.cs similarity index 100% rename from tests/KubeOps.Test/TestEntities/V1Beta1VersionedEntity.cs rename to _old/tests/KubeOps.Test/TestEntities/V1Beta1VersionedEntity.cs diff --git a/tests/KubeOps.Test/TestEntities/V1VersionedEntity.cs b/_old/tests/KubeOps.Test/TestEntities/V1VersionedEntity.cs similarity index 100% rename from tests/KubeOps.Test/TestEntities/V1VersionedEntity.cs rename to _old/tests/KubeOps.Test/TestEntities/V1VersionedEntity.cs diff --git a/tests/KubeOps.Test/TestEntities/V2AttributeVersionedEntity.cs b/_old/tests/KubeOps.Test/TestEntities/V2AttributeVersionedEntity.cs similarity index 100% rename from tests/KubeOps.Test/TestEntities/V2AttributeVersionedEntity.cs rename to _old/tests/KubeOps.Test/TestEntities/V2AttributeVersionedEntity.cs diff --git a/tests/KubeOps.Test/TestEntities/V2Beta2VersionedEntity.cs b/_old/tests/KubeOps.Test/TestEntities/V2Beta2VersionedEntity.cs similarity index 100% rename from tests/KubeOps.Test/TestEntities/V2Beta2VersionedEntity.cs rename to _old/tests/KubeOps.Test/TestEntities/V2Beta2VersionedEntity.cs diff --git a/tests/KubeOps.Test/TestEntities/V2VersionedEntity.cs b/_old/tests/KubeOps.Test/TestEntities/V2VersionedEntity.cs similarity index 100% rename from tests/KubeOps.Test/TestEntities/V2VersionedEntity.cs rename to _old/tests/KubeOps.Test/TestEntities/V2VersionedEntity.cs diff --git a/tests/KubeOps.TestOperator.Test/AssemblyScanner.Test.cs b/_old/tests/KubeOps.TestOperator.Test/AssemblyScanner.Test.cs similarity index 100% rename from tests/KubeOps.TestOperator.Test/AssemblyScanner.Test.cs rename to _old/tests/KubeOps.TestOperator.Test/AssemblyScanner.Test.cs diff --git a/tests/KubeOps.TestOperator.Test/KubeOps.TestOperator.Test.csproj b/_old/tests/KubeOps.TestOperator.Test/KubeOps.TestOperator.Test.csproj similarity index 100% rename from tests/KubeOps.TestOperator.Test/KubeOps.TestOperator.Test.csproj rename to _old/tests/KubeOps.TestOperator.Test/KubeOps.TestOperator.Test.csproj diff --git a/tests/KubeOps.TestOperator.Test/Properties/AssemblyInfo.cs b/_old/tests/KubeOps.TestOperator.Test/Properties/AssemblyInfo.cs similarity index 100% rename from tests/KubeOps.TestOperator.Test/Properties/AssemblyInfo.cs rename to _old/tests/KubeOps.TestOperator.Test/Properties/AssemblyInfo.cs diff --git a/tests/KubeOps.TestOperator.Test/TestAssemblyScannedStartup.cs b/_old/tests/KubeOps.TestOperator.Test/TestAssemblyScannedStartup.cs similarity index 100% rename from tests/KubeOps.TestOperator.Test/TestAssemblyScannedStartup.cs rename to _old/tests/KubeOps.TestOperator.Test/TestAssemblyScannedStartup.cs diff --git a/tests/KubeOps.TestOperator.Test/TestController.Test.cs b/_old/tests/KubeOps.TestOperator.Test/TestController.Test.cs similarity index 100% rename from tests/KubeOps.TestOperator.Test/TestController.Test.cs rename to _old/tests/KubeOps.TestOperator.Test/TestController.Test.cs diff --git a/tests/KubeOps.TestOperator.Test/TestFinalizer.Test.cs b/_old/tests/KubeOps.TestOperator.Test/TestFinalizer.Test.cs similarity index 100% rename from tests/KubeOps.TestOperator.Test/TestFinalizer.Test.cs rename to _old/tests/KubeOps.TestOperator.Test/TestFinalizer.Test.cs diff --git a/tests/KubeOps.TestOperator.Test/TestStartup.cs b/_old/tests/KubeOps.TestOperator.Test/TestStartup.cs similarity index 100% rename from tests/KubeOps.TestOperator.Test/TestStartup.cs rename to _old/tests/KubeOps.TestOperator.Test/TestStartup.cs diff --git a/tests/KubeOps.TestOperator/.gitignore b/_old/tests/KubeOps.TestOperator/.gitignore similarity index 100% rename from tests/KubeOps.TestOperator/.gitignore rename to _old/tests/KubeOps.TestOperator/.gitignore diff --git a/tests/KubeOps.TestOperator/Controller/TestController.cs b/_old/tests/KubeOps.TestOperator/Controller/TestController.cs similarity index 100% rename from tests/KubeOps.TestOperator/Controller/TestController.cs rename to _old/tests/KubeOps.TestOperator/Controller/TestController.cs diff --git a/tests/KubeOps.TestOperator/Entities/V1ClusterTestEntity.cs b/_old/tests/KubeOps.TestOperator/Entities/V1ClusterTestEntity.cs similarity index 100% rename from tests/KubeOps.TestOperator/Entities/V1ClusterTestEntity.cs rename to _old/tests/KubeOps.TestOperator/Entities/V1ClusterTestEntity.cs diff --git a/tests/KubeOps.TestOperator/Entities/V1TestEntity.cs b/_old/tests/KubeOps.TestOperator/Entities/V1TestEntity.cs similarity index 100% rename from tests/KubeOps.TestOperator/Entities/V1TestEntity.cs rename to _old/tests/KubeOps.TestOperator/Entities/V1TestEntity.cs diff --git a/tests/KubeOps.TestOperator/Entities/V2TestEntity.cs b/_old/tests/KubeOps.TestOperator/Entities/V2TestEntity.cs similarity index 100% rename from tests/KubeOps.TestOperator/Entities/V2TestEntity.cs rename to _old/tests/KubeOps.TestOperator/Entities/V2TestEntity.cs diff --git a/tests/KubeOps.TestOperator/Finalizer/TestEntityFinalizer.cs b/_old/tests/KubeOps.TestOperator/Finalizer/TestEntityFinalizer.cs similarity index 100% rename from tests/KubeOps.TestOperator/Finalizer/TestEntityFinalizer.cs rename to _old/tests/KubeOps.TestOperator/Finalizer/TestEntityFinalizer.cs diff --git a/tests/KubeOps.TestOperator/KubeOps.TestOperator.csproj b/_old/tests/KubeOps.TestOperator/KubeOps.TestOperator.csproj similarity index 100% rename from tests/KubeOps.TestOperator/KubeOps.TestOperator.csproj rename to _old/tests/KubeOps.TestOperator/KubeOps.TestOperator.csproj diff --git a/tests/KubeOps.TestOperator/Program.cs b/_old/tests/KubeOps.TestOperator/Program.cs similarity index 100% rename from tests/KubeOps.TestOperator/Program.cs rename to _old/tests/KubeOps.TestOperator/Program.cs diff --git a/tests/KubeOps.TestOperator/TestManager/IManager.cs b/_old/tests/KubeOps.TestOperator/TestManager/IManager.cs similarity index 100% rename from tests/KubeOps.TestOperator/TestManager/IManager.cs rename to _old/tests/KubeOps.TestOperator/TestManager/IManager.cs diff --git a/tests/KubeOps.TestOperator/TestManager/TestManager.cs b/_old/tests/KubeOps.TestOperator/TestManager/TestManager.cs similarity index 100% rename from tests/KubeOps.TestOperator/TestManager/TestManager.cs rename to _old/tests/KubeOps.TestOperator/TestManager/TestManager.cs diff --git a/tests/KubeOps.TestOperator/Webhooks/TestMutator.cs b/_old/tests/KubeOps.TestOperator/Webhooks/TestMutator.cs similarity index 100% rename from tests/KubeOps.TestOperator/Webhooks/TestMutator.cs rename to _old/tests/KubeOps.TestOperator/Webhooks/TestMutator.cs diff --git a/tests/KubeOps.TestOperator/Webhooks/TestValidator.cs b/_old/tests/KubeOps.TestOperator/Webhooks/TestValidator.cs similarity index 100% rename from tests/KubeOps.TestOperator/Webhooks/TestValidator.cs rename to _old/tests/KubeOps.TestOperator/Webhooks/TestValidator.cs diff --git a/tests/KubeOps.TestOperator/appsettings.json b/_old/tests/KubeOps.TestOperator/appsettings.json similarity index 100% rename from tests/KubeOps.TestOperator/appsettings.json rename to _old/tests/KubeOps.TestOperator/appsettings.json diff --git a/tests/KubeOps.TestOperator/test.yaml b/_old/tests/KubeOps.TestOperator/test.yaml similarity index 100% rename from tests/KubeOps.TestOperator/test.yaml rename to _old/tests/KubeOps.TestOperator/test.yaml diff --git a/docfx.json b/docfx.json new file mode 100644 index 00000000..5cd98bc8 --- /dev/null +++ b/docfx.json @@ -0,0 +1,61 @@ +{ + "build": { + "content": [ + { + "files": [ + "docs/api/**.yml" + ] + }, + { + "files": [ + "docs/**.md", + "docs/**/toc.yml", + "toc.yml", + "*.md" + ] + }, + { + "files": [ + "src/**/*.md" + ] + } + ], + "resource": [ + { + "files": [ + "res/**" + ] + } + ], + "output": "_site", + "globalMetadataFiles": [], + "fileMetadataFiles": [], + "template": [ + "default", + "modern" + ], + "postProcessors": [], + "keepFileLink": false, + "disableGitFeatures": false + }, + "metadata": [ + { + "src": [ + { + "files": [ + "src/**/*.csproj" + ] + } + ], + "dest": "docs/api", + "includePrivateMembers": false, + "disableGitFeatures": false, + "disableDefaultFilter": false, + "noRestore": false, + "namespaceLayout": "flattened", + "memberLayout": "samePage", + "EnumSortOrder": "alphabetic", + "allowCompilationErrors": false + } + ] +} diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 00000000..951778e8 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1 @@ +api/ diff --git a/docs/intro.md b/docs/intro.md new file mode 100644 index 00000000..c0478ced --- /dev/null +++ b/docs/intro.md @@ -0,0 +1 @@ +# Add your introductions here! diff --git a/docs/toc.yml b/docs/toc.yml new file mode 100644 index 00000000..ff89ef1f --- /dev/null +++ b/docs/toc.yml @@ -0,0 +1,2 @@ +- name: Introduction + href: intro.md diff --git a/examples/Operator/Controller/V1TestEntityController.cs b/examples/Operator/Controller/V1TestEntityController.cs new file mode 100644 index 00000000..7d79802b --- /dev/null +++ b/examples/Operator/Controller/V1TestEntityController.cs @@ -0,0 +1,29 @@ +using KubeOps.Abstractions.Controller; + +using Microsoft.Extensions.Logging; + +using Operator.Entities; + +namespace Operator.Controller; + +public class V1TestEntityController : IEntityController +{ + private readonly ILogger _logger; + + public V1TestEntityController(ILogger logger) + { + _logger = logger; + } + + public Task ReconcileAsync(V1TestEntity entity) + { + _logger.LogInformation("Reconciling entity {EntityName}.", entity.Metadata.Name); + return Task.CompletedTask; + } + + public Task DeletedAsync(V1TestEntity entity) + { + _logger.LogInformation("Deleting entity {EntityName}.", entity.Metadata.Name); + return Task.CompletedTask; + } +} diff --git a/examples/Operator/Entities/V1TestEntity.cs b/examples/Operator/Entities/V1TestEntity.cs new file mode 100644 index 00000000..54556448 --- /dev/null +++ b/examples/Operator/Entities/V1TestEntity.cs @@ -0,0 +1,18 @@ +using k8s; +using k8s.Models; + +namespace Operator.Entities; + +[KubernetesEntity(Group = "testing.dev", ApiVersion = "v1", Kind = "TestEntity")] +public class V1TestEntity : IKubernetesObject +{ + public string ApiVersion { get; set; } = "testing.dev/v1"; + + public string Kind { get; set; } = "TestEntity"; + + public V1ObjectMeta Metadata { get; set; } = new(); + + public V1TestEntitySpec Spec { get; set; } = new(); + + public V1TestEntityStatus Status { get; set; } = new(); +} diff --git a/examples/Operator/Entities/V1TestEntitySpec.cs b/examples/Operator/Entities/V1TestEntitySpec.cs new file mode 100644 index 00000000..3c1c0f98 --- /dev/null +++ b/examples/Operator/Entities/V1TestEntitySpec.cs @@ -0,0 +1,12 @@ +using k8s.Models; + +namespace Operator.Entities; + +public class V1TestEntitySpec +{ + public string Spec { get; set; } = string.Empty; + + public string Username { get; set; } = string.Empty; + + public IntstrIntOrString StringOrInteger { get; set; } = 42; +} diff --git a/examples/Operator/Entities/V1TestEntityStatus.cs b/examples/Operator/Entities/V1TestEntityStatus.cs new file mode 100644 index 00000000..9fca728a --- /dev/null +++ b/examples/Operator/Entities/V1TestEntityStatus.cs @@ -0,0 +1,6 @@ +namespace Operator.Entities; + +public class V1TestEntityStatus +{ + public string Status { get; set; } = string.Empty; +} diff --git a/examples/Operator/Operator.csproj b/examples/Operator/Operator.csproj new file mode 100644 index 00000000..53fab6e1 --- /dev/null +++ b/examples/Operator/Operator.csproj @@ -0,0 +1,18 @@ + + + + Exe + net7.0 + false + false + + + + + + + + + diff --git a/examples/Operator/Program.cs b/examples/Operator/Program.cs new file mode 100644 index 00000000..c896f175 --- /dev/null +++ b/examples/Operator/Program.cs @@ -0,0 +1,19 @@ +using KubeOps.Operator.Extensions; + +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; + +using Operator.Controller; +using Operator.Entities; + +var builder = Host.CreateApplicationBuilder(args); + +builder.Logging.SetMinimumLevel(LogLevel.Trace); + +builder.Services + .AddKubernetesOperator() + .RegisterEntitiyMetadata() + .AddController(); + +using var host = builder.Build(); +await host.RunAsync(); diff --git a/examples/Operator/test_entity.yaml b/examples/Operator/test_entity.yaml new file mode 100644 index 00000000..d602ec3d --- /dev/null +++ b/examples/Operator/test_entity.yaml @@ -0,0 +1,4 @@ +apiVersion: testing.dev/v1 +kind: TestEntity +metadata: + name: my-test-entity diff --git a/index.md b/index.md new file mode 100644 index 00000000..fd672e54 --- /dev/null +++ b/index.md @@ -0,0 +1,3 @@ +--- +redirect_url: ./readme.html +--- diff --git a/res/docs_index.md b/res/docs_index.md deleted file mode 100644 index 8f2d4142..00000000 --- a/res/docs_index.md +++ /dev/null @@ -1,40 +0,0 @@ -# KubeOps - -![Code Security Testing](https://github.com/buehler/dotnet-operator-sdk/workflows/Code%20Security%20Testing/badge.svg) -![.NET Release](https://github.com/buehler/dotnet-operator-sdk/workflows/.NET%20Release/badge.svg) -![.NET Testing](https://github.com/buehler/dotnet-operator-sdk/workflows/.NET%20Testing/badge.svg) -[![Nuget](https://img.shields.io/nuget/v/KubeOps)](https://www.nuget.org/packages/KubeOps/) -[![Nuget](https://img.shields.io/nuget/vpre/KubeOps?label=nuget%20prerelease)](https://www.nuget.org/packages/KubeOps/absoluteLatest) - -This is the repository of "KubeOps" - The dotnet Kubernetes Operator SDK. - -The documentation moved to respective `README` files in the packages. -Please consult them via nuget explorer, on the GitHub repository, or on the links -below. - -## Packages - -- [KubeOps](./kubeops.html) - The core package of the SDK. -- [KubeOps.KubernetesClient](./kubeops-kubernetesclient.html) - An improved Kubernetes client to interact with Kubernetes APIs. -- [KubeOps.Templates](./kubeops-templates.html) - `dotnet new` templates for creating operators. -- [KubeOps.Testing](./kubeops-testing.html) - Extensions that support integration testing. - -## Contribution - -If you want to contribute, feel free to open a pull request or write issues :-) -Read more about contribution (especially for setting up your local environment) -in the [CONTRIBUTING file](./contribution.html). - -Short wrapup: -- Check out the code -- Develop on KubeOps -- Use some Kubernetes to run the test operator against -- Create tests -- Build the whole solution (lint warnings will result in an error) -- Open PR - -## Motivation - -The motivation was to learn more about the quirks of kubernetes itself and -provide an alternative to kubebuilder and operator sdk which are both -written in GoLang. diff --git a/src/KubeOps.Abstractions/Builder/IOperatorBuilder.cs b/src/KubeOps.Abstractions/Builder/IOperatorBuilder.cs new file mode 100644 index 00000000..649a98a8 --- /dev/null +++ b/src/KubeOps.Abstractions/Builder/IOperatorBuilder.cs @@ -0,0 +1,54 @@ +using k8s; +using k8s.Models; + +using KubeOps.Abstractions.Controller; +using KubeOps.Abstractions.Entities; + +using Microsoft.Extensions.DependencyInjection; + +namespace KubeOps.Abstractions.Builder; + +/// +/// KubeOps operator builder. +/// +public interface IOperatorBuilder +{ + /// + /// The original service collection. + /// + IServiceCollection Services { get; } + + /// + /// Add metadata for an entity to the operator. + /// Metadata must be added for each entity to be used in + /// controllers and other elements. + /// + /// The metadata of the entity. + /// The type of the entity. + /// The builder for chaining. + IOperatorBuilder AddEntityMetadata(EntityMetadata metadata) + where TEntity : IKubernetesObject; + + /// + /// Add a controller implementation for a specific entity to the operator. + /// The metadata for the entity must be added as well. + /// + /// Implementation type of the controller. + /// Entity type. + /// The builder for chaining. + IOperatorBuilder AddController() + where TImplementation : class, IEntityController + where TEntity : IKubernetesObject; + + /// + /// Add a controller implementation for a specific entity with the + /// entity metadata. + /// + /// The metadata of the entity. + /// Implementation type of the controller. + /// Entity type. + /// The builder for chaining. + IOperatorBuilder AddController(EntityMetadata metadata) + where TImplementation : class, IEntityController + where TEntity : IKubernetesObject; +} diff --git a/src/KubeOps.Abstractions/Controller/IEntityController{TEntity}.cs b/src/KubeOps.Abstractions/Controller/IEntityController{TEntity}.cs new file mode 100644 index 00000000..0d5b97ec --- /dev/null +++ b/src/KubeOps.Abstractions/Controller/IEntityController{TEntity}.cs @@ -0,0 +1,38 @@ +using k8s; +using k8s.Models; + +namespace KubeOps.Abstractions.Controller; + +/// +/// Generic entity controller interface. +/// +/// The type of the Kubernetes entity. +public interface IEntityController + where TEntity : IKubernetesObject +{ + /// + /// Called for `added` and `modified` events from the watcher. + /// + /// The entity that fired the reconcile event. + /// A task that completes when the reconciliation is done. +#if NETSTANDARD2_0 + Task ReconcileAsync(TEntity entity); +#else + Task ReconcileAsync(TEntity entity) => + Task.CompletedTask; +#endif + + /// + /// Called for `delete` events for a given entity. + /// + /// The entity that fired the deleted event. + /// + /// A task that completes, when the reconciliation is done. + /// +#if NETSTANDARD2_0 + Task DeletedAsync(TEntity entity); +#else + Task DeletedAsync(TEntity entity) => + Task.CompletedTask; +#endif +} diff --git a/src/KubeOps.Abstractions/Entities/Attributes/AdditionalPrinterColumnAttribute.cs b/src/KubeOps.Abstractions/Entities/Attributes/AdditionalPrinterColumnAttribute.cs new file mode 100644 index 00000000..8803b861 --- /dev/null +++ b/src/KubeOps.Abstractions/Entities/Attributes/AdditionalPrinterColumnAttribute.cs @@ -0,0 +1,35 @@ +namespace KubeOps.Abstractions.Entities.Attributes; + +/// +/// Defines a property as an additional printer column. +/// +[AttributeUsage(AttributeTargets.Property)] +public class AdditionalPrinterColumnAttribute : Attribute +{ + public AdditionalPrinterColumnAttribute(PrinterColumnPriority priority = default, string? name = null) + { + Name = name; + Priority = priority; + } + + /// + /// The name of the column. Defaults to the property-name. + /// + public string? Name { get; } + + /// + /// The priority of the additional printer column. + /// As documented in + /// https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#priority + /// the following rules apply to priority: + /// + /// + /// Columns with priority `0` are shown in standard view + /// + /// + /// Columns with priority greater than `0` are shown only in wide view + /// + /// + /// + public PrinterColumnPriority Priority { get; } +} diff --git a/src/KubeOps.Abstractions/Entities/Attributes/DescriptionAttribute.cs b/src/KubeOps.Abstractions/Entities/Attributes/DescriptionAttribute.cs new file mode 100644 index 00000000..278d9398 --- /dev/null +++ b/src/KubeOps.Abstractions/Entities/Attributes/DescriptionAttribute.cs @@ -0,0 +1,16 @@ +namespace KubeOps.Abstractions.Entities.Attributes; + +/// +/// Defines a description for a property. This precedes the description found in a +/// XML documentation file. +/// +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class)] +public class DescriptionAttribute : Attribute +{ + public DescriptionAttribute(string description) => Description = description; + + /// + /// The given description for the property. + /// + public string Description { get; } +} diff --git a/src/KubeOps.Abstractions/Entities/Attributes/EmbeddedResourceAttribute.cs b/src/KubeOps.Abstractions/Entities/Attributes/EmbeddedResourceAttribute.cs new file mode 100644 index 00000000..1e79134a --- /dev/null +++ b/src/KubeOps.Abstractions/Entities/Attributes/EmbeddedResourceAttribute.cs @@ -0,0 +1,14 @@ +using k8s.Models; + +namespace KubeOps.Abstractions.Entities.Attributes; + +/// +/// Defines a property as an embedded resource. +/// This property can contain another Kubernetes object +/// (e.g. a or a ). +/// This implicitly sets the . +/// +[AttributeUsage(AttributeTargets.Property)] +public class EmbeddedResourceAttribute : Attribute +{ +} diff --git a/src/KubeOps.Abstractions/Entities/Attributes/EntityScopeAttribute.cs b/src/KubeOps.Abstractions/Entities/Attributes/EntityScopeAttribute.cs new file mode 100644 index 00000000..597ae185 --- /dev/null +++ b/src/KubeOps.Abstractions/Entities/Attributes/EntityScopeAttribute.cs @@ -0,0 +1,12 @@ +namespace KubeOps.Abstractions.Entities.Attributes; + +[AttributeUsage(AttributeTargets.Class, Inherited = false)] +public class EntityScopeAttribute : Attribute +{ + public EntityScopeAttribute(EntityScope scope = default) + { + Scope = scope; + } + + public EntityScope Scope { get; } +} diff --git a/src/KubeOps.Abstractions/Entities/Attributes/ExternalDocsAttribute.cs b/src/KubeOps.Abstractions/Entities/Attributes/ExternalDocsAttribute.cs new file mode 100644 index 00000000..32bb8d60 --- /dev/null +++ b/src/KubeOps.Abstractions/Entities/Attributes/ExternalDocsAttribute.cs @@ -0,0 +1,24 @@ +namespace KubeOps.Abstractions.Entities.Attributes; + +/// +/// Defines that the property has an external documentation. +/// +[AttributeUsage(AttributeTargets.Property)] +public class ExternalDocsAttribute : Attribute +{ + public ExternalDocsAttribute(string url, string? description = null) + { + Description = description; + Url = url; + } + + /// + /// Additional description. + /// + public string? Description { get; } + + /// + /// Url where to find the documentation. + /// + public string Url { get; } +} diff --git a/src/KubeOps.Abstractions/Entities/Attributes/GenericAdditionalPrinterColumnAttribute.cs b/src/KubeOps.Abstractions/Entities/Attributes/GenericAdditionalPrinterColumnAttribute.cs new file mode 100644 index 00000000..236c75c5 --- /dev/null +++ b/src/KubeOps.Abstractions/Entities/Attributes/GenericAdditionalPrinterColumnAttribute.cs @@ -0,0 +1,132 @@ +using k8s.Models; + +namespace KubeOps.Abstractions.Entities.Attributes; + +/// +/// Defines a generic additional printer column. +/// With this, other elements (such as Metadata.Name) +/// can be referenced. In contrast to the , +/// all needed information must be provided. +/// +[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] +public class GenericAdditionalPrinterColumnAttribute : Attribute +{ + /// + /// Create a generic additional printer column. + /// + /// JsonPath as in . + /// Name as in . + /// Type as in . + public GenericAdditionalPrinterColumnAttribute(string jsonPath, string name, string type) + { + JsonPath = jsonPath; + Name = name; + Type = type; + } + + /// + /// The json path for the property inside the resource. + /// .spec.replicas + /// .metadata.namespace + /// .metadata.creationTimestamp + /// + public string JsonPath { get; } + + /// + /// The name of the column. + /// + public string Name { get; } + + /// + /// Description for the column. + /// +#if NETSTANDARD + public string? Description { get; set; } +#else + public string? Description { get; init; } +#endif + + /// + /// The type of the column. + /// As documented in + /// https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#type. + /// The type field can be any of the following (from OpenAPI v3 data types): + /// + /// + /// `integer` - non-floating-point number + /// + /// + /// `number` - floating point number + /// + /// + /// `string` - strings + /// + /// + /// `boolean`- `true` or `false` + /// + /// + /// `date` - rendered differentially as time since this timestamp + /// + /// + /// If the value inside a CustomResource does not match the type specified for the column, the value is omitted. + /// + public string Type { get; } + + /// + /// The format of the column. + /// As documented in + /// https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#format. + /// The format field can be any of the following: + /// + /// + /// `int32` + /// + /// + /// `int64` + /// + /// + /// `float` + /// + /// + /// `double` + /// + /// + /// `byte` + /// + /// + /// `date` + /// + /// + /// `date-time` + /// + /// + /// `password` + /// + /// + /// +#if NETSTANDARD + public string? Format { get; set; } +#else + public string? Format { get; init; } +#endif + + /// + /// The priority of the additional printer column. + /// As documented in + /// https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#priority + /// the following rules apply to priority: + /// + /// + /// Columns with priority `0` are shown in standard view + /// + /// + /// Columns with priority greater than `0` are shown only in wide view + /// + /// + /// +#if NETSTANDARD + public PrinterColumnPriority Priority { get; set; } +#else + public PrinterColumnPriority Priority { get; init; } +#endif +} diff --git a/src/KubeOps.Abstractions/Entities/Attributes/IgnoreEntityAttribute.cs b/src/KubeOps.Abstractions/Entities/Attributes/IgnoreEntityAttribute.cs new file mode 100644 index 00000000..87b85c51 --- /dev/null +++ b/src/KubeOps.Abstractions/Entities/Attributes/IgnoreEntityAttribute.cs @@ -0,0 +1,10 @@ +namespace KubeOps.Abstractions.Entities.Attributes; + +/// +/// Attribute that states that the given entity should be +/// ignored during CRD generation. +/// +[AttributeUsage(AttributeTargets.Class)] +public class IgnoreEntityAttribute : Attribute +{ +} diff --git a/src/KubeOps.Abstractions/Entities/Attributes/IgnorePropertyAttribute.cs b/src/KubeOps.Abstractions/Entities/Attributes/IgnorePropertyAttribute.cs new file mode 100644 index 00000000..b7c8b9d4 --- /dev/null +++ b/src/KubeOps.Abstractions/Entities/Attributes/IgnorePropertyAttribute.cs @@ -0,0 +1,10 @@ +namespace KubeOps.Abstractions.Entities.Attributes; + +/// +/// Attribute that states that the given property should be +/// ignored during CRD generation. +/// +[AttributeUsage(AttributeTargets.Property)] +public class IgnorePropertyAttribute : Attribute +{ +} diff --git a/src/KubeOps.Abstractions/Entities/Attributes/ItemsAttribute.cs b/src/KubeOps.Abstractions/Entities/Attributes/ItemsAttribute.cs new file mode 100644 index 00000000..51ee8640 --- /dev/null +++ b/src/KubeOps.Abstractions/Entities/Attributes/ItemsAttribute.cs @@ -0,0 +1,26 @@ +namespace KubeOps.Abstractions.Entities.Attributes; + +/// +/// Define minimum and maximum items count for an array property. +/// +[AttributeUsage(AttributeTargets.Property)] +public class ItemsAttribute : Attribute +{ + /// + /// Defines the minimal item count for the property. + /// +#if NETSTANDARD + public long? MinItems { get; set; } +#else + public long? MinItems { get; init; } +#endif + + /// + /// Defines the maximal item count for the property. + /// +#if NETSTANDARD + public long? MaxItems { get; set; } +#else + public long? MaxItems { get; init; } +#endif +} diff --git a/src/KubeOps.Abstractions/Entities/Attributes/KubernetesEntityShortNamesAttribute.cs b/src/KubeOps.Abstractions/Entities/Attributes/KubernetesEntityShortNamesAttribute.cs new file mode 100644 index 00000000..780216b5 --- /dev/null +++ b/src/KubeOps.Abstractions/Entities/Attributes/KubernetesEntityShortNamesAttribute.cs @@ -0,0 +1,18 @@ +namespace KubeOps.Abstractions.Entities.Attributes; + +/// +/// Define "shortNames" for CRDs. +/// +[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] +public class KubernetesEntityShortNamesAttribute : Attribute +{ + public KubernetesEntityShortNamesAttribute(params string[] shortNames) + { + ShortNames = shortNames; + } + + /// + /// Array of shortnames that should be attached to CRDs. + /// + public string[] ShortNames { get; } +} diff --git a/src/KubeOps.Abstractions/Entities/Attributes/LengthAttribute.cs b/src/KubeOps.Abstractions/Entities/Attributes/LengthAttribute.cs new file mode 100644 index 00000000..0876557c --- /dev/null +++ b/src/KubeOps.Abstractions/Entities/Attributes/LengthAttribute.cs @@ -0,0 +1,26 @@ +namespace KubeOps.Abstractions.Entities.Attributes; + +/// +/// Defines length limits for properties. +/// +[AttributeUsage(AttributeTargets.Property)] +public class LengthAttribute : Attribute +{ + /// + /// Define the minimum length. + /// +#if NETSTANDARD + public long? MinLength { get; set; } +#else + public long? MinLength { get; init; } +#endif + + /// + /// Define the maximum length. + /// +#if NETSTANDARD + public long? MaxLength { get; set; } +#else + public long? MaxLength { get; init; } +#endif +} diff --git a/src/KubeOps.Abstractions/Entities/Attributes/MultipleOfAttribute.cs b/src/KubeOps.Abstractions/Entities/Attributes/MultipleOfAttribute.cs new file mode 100644 index 00000000..3f71e629 --- /dev/null +++ b/src/KubeOps.Abstractions/Entities/Attributes/MultipleOfAttribute.cs @@ -0,0 +1,18 @@ +namespace KubeOps.Abstractions.Entities.Attributes; + +/// +/// Defines the factor that a numeric value must adhere to. +/// +[AttributeUsage(AttributeTargets.Property)] +public class MultipleOfAttribute : Attribute +{ + public MultipleOfAttribute(double value) + { + Value = value; + } + + /// + /// The property should be a multiple of this value. + /// + public double Value { get; } +} diff --git a/src/KubeOps.Abstractions/Entities/Attributes/PatternAttribute.cs b/src/KubeOps.Abstractions/Entities/Attributes/PatternAttribute.cs new file mode 100644 index 00000000..a4f0ba34 --- /dev/null +++ b/src/KubeOps.Abstractions/Entities/Attributes/PatternAttribute.cs @@ -0,0 +1,18 @@ +namespace KubeOps.Abstractions.Entities.Attributes; + +/// +/// Define a regex validator for the property. +/// +[AttributeUsage(AttributeTargets.Property)] +public class PatternAttribute : Attribute +{ + public PatternAttribute(string regexPattern) + { + RegexPattern = regexPattern; + } + + /// + /// The regex pattern to be used. + /// + public string RegexPattern { get; } +} diff --git a/src/KubeOps.Abstractions/Entities/Attributes/PreserveUnknownFieldsAttribute.cs b/src/KubeOps.Abstractions/Entities/Attributes/PreserveUnknownFieldsAttribute.cs new file mode 100644 index 00000000..7e19c12f --- /dev/null +++ b/src/KubeOps.Abstractions/Entities/Attributes/PreserveUnknownFieldsAttribute.cs @@ -0,0 +1,10 @@ +namespace KubeOps.Abstractions.Entities.Attributes; + +/// +/// Defines that a property should keep unknown fields +/// so that kubernetes does not purge additional structures. +/// +[AttributeUsage(AttributeTargets.Property)] +public class PreserveUnknownFieldsAttribute : Attribute +{ +} diff --git a/src/KubeOps.Abstractions/Entities/Attributes/RangeMaximum.cs b/src/KubeOps.Abstractions/Entities/Attributes/RangeMaximum.cs new file mode 100644 index 00000000..b880fb34 --- /dev/null +++ b/src/KubeOps.Abstractions/Entities/Attributes/RangeMaximum.cs @@ -0,0 +1,24 @@ +namespace KubeOps.Abstractions.Entities.Attributes; + +/// +/// Defines a range maximum for a numeric property. +/// +[AttributeUsage(AttributeTargets.Property)] +public class RangeMaximumAttribute : Attribute +{ + public RangeMaximumAttribute(double maximum, bool exclusiveMaximum = false) + { + Maximum = maximum; + ExclusiveMaximum = exclusiveMaximum; + } + + /// + /// Maximum value to be set. + /// + public double Maximum { get; } + + /// + /// Defines if the maximum value is included or excluded. + /// + public bool ExclusiveMaximum { get; } +} diff --git a/src/KubeOps.Abstractions/Entities/Attributes/RangeMinimum.cs b/src/KubeOps.Abstractions/Entities/Attributes/RangeMinimum.cs new file mode 100644 index 00000000..26ea81ed --- /dev/null +++ b/src/KubeOps.Abstractions/Entities/Attributes/RangeMinimum.cs @@ -0,0 +1,24 @@ +namespace KubeOps.Abstractions.Entities.Attributes; + +/// +/// Defines a range minimum for a numeric property. +/// +[AttributeUsage(AttributeTargets.Property)] +public class RangeMinimumAttribute : Attribute +{ + public RangeMinimumAttribute(double minimum, bool exclusiveMinimum = false) + { + Minimum = minimum; + ExclusiveMinimum = exclusiveMinimum; + } + + /// + /// Minimum value to be set. + /// + public double Minimum { get; } + + /// + /// Defines if the minimum value is included or excluded. + /// + public bool ExclusiveMinimum { get; } +} diff --git a/src/KubeOps.Abstractions/Entities/Attributes/RequiredAttribute.cs b/src/KubeOps.Abstractions/Entities/Attributes/RequiredAttribute.cs new file mode 100644 index 00000000..329beb55 --- /dev/null +++ b/src/KubeOps.Abstractions/Entities/Attributes/RequiredAttribute.cs @@ -0,0 +1,9 @@ +namespace KubeOps.Abstractions.Entities.Attributes; + +/// +/// Defines a property of a specification as required. +/// +[AttributeUsage(AttributeTargets.Property)] +public class RequiredAttribute : Attribute +{ +} diff --git a/src/KubeOps.Abstractions/Entities/Attributes/StorageVersionAttribute.cs b/src/KubeOps.Abstractions/Entities/Attributes/StorageVersionAttribute.cs new file mode 100644 index 00000000..efe12bb0 --- /dev/null +++ b/src/KubeOps.Abstractions/Entities/Attributes/StorageVersionAttribute.cs @@ -0,0 +1,13 @@ +namespace KubeOps.Abstractions.Entities.Attributes; + +/// +/// This attribute marks an entity as the storage version of +/// an entity. Only one storage version must be set. +/// If none of the versions define this attribute, the "newest" +/// one is taken according to the kubernetes versioning rules. +/// GA > Beta > Alpha > non versions. +/// +[AttributeUsage(AttributeTargets.Class)] +public class StorageVersionAttribute : Attribute +{ +} diff --git a/src/KubeOps.Abstractions/Entities/EntityMetadata.cs b/src/KubeOps.Abstractions/Entities/EntityMetadata.cs new file mode 100644 index 00000000..67a65b33 --- /dev/null +++ b/src/KubeOps.Abstractions/Entities/EntityMetadata.cs @@ -0,0 +1,77 @@ +namespace KubeOps.Abstractions.Entities; + +#if NET +/// +/// Metadata for a given entity. +/// +/// The kind of the entity (e.g. deployment). +/// Version (e.g. v1 or v2-alpha). +/// The group in Kubernetes (e.g. "testing.dev"). +/// An optional plural name. Defaults to the singular name with an added "s". +public record EntityMetadata(string Kind, string Version, string? Group = null, string? Plural = null) +{ + /// + /// Kind of the entity when used in a list. + /// + public string ListKind => $"{Kind}List"; + + /// + /// Name of the singular entity. + /// + public string SingularName => Kind.ToLower(); + + /// + /// Name of the plural entity. + /// + public string PluralName => Plural ?? $"{Kind.ToLower()}s"; +} +#else +/// +/// Metadata for a given entity. +/// +public class EntityMetadata +{ + public EntityMetadata(string kind, string version, string? group = null, string? plural = null) + { + Kind = kind; + Version = version; + Group = group; + Plural = plural; + } + + /// + /// The kind of the entity (e.g. deployment). + /// + public string Kind { get; } + + /// + /// Version (e.g. v1 or v2-alpha). + /// + public string Version { get; } + + /// + /// The group in Kubernetes (e.g. "testing.dev"). + /// + public string? Group { get; } + + /// + /// An optional plural name. Defaults to the singular name with an added "s". + /// + public string? Plural { get; } + + /// + /// Kind of the entity when used in a list. + /// + public string ListKind => $"{Kind}List"; + + /// + /// Name of the singular entity. + /// + public string SingularName => Kind.ToLower(); + + /// + /// Name of the plural entity. + /// + public string PluralName => Plural ?? $"{Kind.ToLower()}s"; +} +#endif diff --git a/src/KubeOps.Abstractions/Entities/EntityScope.cs b/src/KubeOps.Abstractions/Entities/EntityScope.cs new file mode 100644 index 00000000..b7be754d --- /dev/null +++ b/src/KubeOps.Abstractions/Entities/EntityScope.cs @@ -0,0 +1,18 @@ +namespace KubeOps.Abstractions.Entities; + +/// +/// Scope of the resource. Custom entities (resources) in Kubernetes +/// can either be namespaced or cluster-wide. +/// +public enum EntityScope +{ + /// + /// The resource is namespace. + /// + Namespaced, + + /// + /// The resource is cluster-wide. + /// + Cluster, +} diff --git a/src/KubeOps.Abstractions/Entities/PrinterColumnPriority.cs b/src/KubeOps.Abstractions/Entities/PrinterColumnPriority.cs new file mode 100644 index 00000000..ec1af51d --- /dev/null +++ b/src/KubeOps.Abstractions/Entities/PrinterColumnPriority.cs @@ -0,0 +1,17 @@ +namespace KubeOps.Abstractions.Entities; + +/// +/// Specifies the priority of a column in an additional printer view. +/// +public enum PrinterColumnPriority +{ + /// + /// The column is displayed in the standard view. + /// + StandardView, + + /// + /// The column is displayed in the wide view. + /// + WideView, +} diff --git a/src/KubeOps.Abstractions/KubeOps.Abstractions.csproj b/src/KubeOps.Abstractions/KubeOps.Abstractions.csproj new file mode 100644 index 00000000..44b55d33 --- /dev/null +++ b/src/KubeOps.Abstractions/KubeOps.Abstractions.csproj @@ -0,0 +1,23 @@ + + + + netstandard2.0;netstandard2.1;net6.0;net7.0 + true + + + + KubeOps.Abstractions + Kubernetes Operator SDK Abstractions + + Abstractions for the Kubernetes Operator SDK. + Used by KubeOps in general. + + + + + + + + + + diff --git a/src/KubeOps.Abstractions/README.md b/src/KubeOps.Abstractions/README.md new file mode 100644 index 00000000..266bc94d --- /dev/null +++ b/src/KubeOps.Abstractions/README.md @@ -0,0 +1 @@ +all abstractions, interfaces and such for KubeOps diff --git a/src/KubeOps.Abstractions/Transpiler/ICrdTranspilerTypeHandler.cs b/src/KubeOps.Abstractions/Transpiler/ICrdTranspilerTypeHandler.cs new file mode 100644 index 00000000..1f217b70 --- /dev/null +++ b/src/KubeOps.Abstractions/Transpiler/ICrdTranspilerTypeHandler.cs @@ -0,0 +1,37 @@ +using k8s.Models; + +namespace KubeOps.Abstractions.Transpiler; + +/// +/// Type handler for the CRD transpiler. +/// +public interface ICrdTranspilerTypeHandler +{ + /// + /// Weather the type handler is exclusive. If an exclusive type handler + /// is found, no other type handler will be used. + /// +#if NETSTANDARD2_0 + bool IsExclusive { get; } +#else + bool IsExclusive { get => false; } +#endif + + /// + /// Weather the type handler can handle the given type. + /// + /// The type to check. + /// + /// True if the handler can handle the type of the given props, + /// otherwise false. + /// + bool CanHandleType(Type type); + + /// + /// Idempotent configuration of the given props. + /// Configures the props for the given type. + /// + /// The props for the JSON schema that need to be configured. + /// The configured props. + V1JSONSchemaProps Configure(V1JSONSchemaProps props); +} diff --git a/src/KubeOps.Cli/Commands/Entrypoint.cs b/src/KubeOps.Cli/Commands/Entrypoint.cs new file mode 100644 index 00000000..b835c6cf --- /dev/null +++ b/src/KubeOps.Cli/Commands/Entrypoint.cs @@ -0,0 +1,15 @@ +using McMaster.Extensions.CommandLineUtils; + +namespace KubeOps.Cli.Commands; + +[Command(Name = "kubeops", Description = "CLI for KubeOps.", UsePagerForHelpText = true)] +[Subcommand(typeof(Generator.Generator))] +[Subcommand(typeof(Utilities.Version))] +internal class Entrypoint +{ + public int OnExecute(CommandLineApplication app) + { + app.ShowHelp(); + return ExitCodes.UsageError; + } +} diff --git a/src/KubeOps.Cli/Commands/Generator/CrdGenerator.cs b/src/KubeOps.Cli/Commands/Generator/CrdGenerator.cs new file mode 100644 index 00000000..48c30cc6 --- /dev/null +++ b/src/KubeOps.Cli/Commands/Generator/CrdGenerator.cs @@ -0,0 +1,73 @@ +using KubeOps.Cli.Output; +using KubeOps.Cli.SyntaxObjects; +using KubeOps.Transpiler.Crds; + +using McMaster.Extensions.CommandLineUtils; + +namespace KubeOps.Cli.Commands.Generator; + +[Command("crd", "crds", Description = "Generates the needed CRD for kubernetes. (Aliases: crds)")] +internal class CrdGenerator +{ + private readonly ConsoleOutput _output; + private readonly ResultOutput _result; + + public CrdGenerator(ConsoleOutput output, ResultOutput result) + { + _output = output; + _result = result; + } + + [Option( + Description = "The path the command will write the files to. If empty, prints output to console.", + LongName = "out")] + public string? OutputPath { get; set; } + + [Option( + CommandOptionType.SingleValue, + Description = "Sets the output format for the generator.")] + public OutputFormat Format { get; set; } + + [Argument( + 0, + Description = + "Path to a *.csproj file to generate the CRD from. " + + "If omitted, the current directory is searched for one and the command fails if none is found.")] + public string? ProjectFile { get; set; } + + public async Task OnExecuteAsync() + { + _result.Format = Format; + var projectFile = ProjectFile ?? + Directory.EnumerateFiles( + Directory.GetCurrentDirectory(), + "*.csproj") + .FirstOrDefault(); + if (projectFile == null) + { + _output.WriteLine( + "No *.csproj file found. Either specify one or run the command in a directory with one.", + ConsoleColor.Red); + return ExitCodes.Error; + } + + _output.WriteLine($"Generate CRDs from project: {projectFile}."); + + var parser = await ProjectParser.CreateAsync(projectFile); + await foreach (var crd in parser.Entities().Select(CrdTranspiler.Create)) + { + _result.Add($"{crd.Metadata.Name.Replace('.', '_')}.{Format.ToString().ToLowerInvariant()}", crd); + } + + if (OutputPath is not null) + { + await _result.Write(OutputPath); + } + else + { + _result.Write(); + } + + return ExitCodes.Success; + } +} diff --git a/src/KubeOps.Cli/Commands/Generator/Generator.cs b/src/KubeOps.Cli/Commands/Generator/Generator.cs new file mode 100644 index 00000000..57441408 --- /dev/null +++ b/src/KubeOps.Cli/Commands/Generator/Generator.cs @@ -0,0 +1,19 @@ +using McMaster.Extensions.CommandLineUtils; + +namespace KubeOps.Cli.Commands.Generator; + +[Command("generator", "gen", "g", Description = "Generates elements related to an operator. (Aliases: gen, g)")] +[Subcommand(typeof(CrdGenerator))] + +// [Subcommand(typeof(DockerGenerator))] +// [Subcommand(typeof(InstallerGenerator))] +// [Subcommand(typeof(OperatorGenerator))] +// [Subcommand(typeof(RbacGenerator))] +internal class Generator +{ + public int OnExecute(CommandLineApplication app) + { + app.ShowHelp(); + return ExitCodes.UsageError; + } +} diff --git a/src/KubeOps.Cli/Commands/Utilities/Version.cs b/src/KubeOps.Cli/Commands/Utilities/Version.cs new file mode 100644 index 00000000..144453aa --- /dev/null +++ b/src/KubeOps.Cli/Commands/Utilities/Version.cs @@ -0,0 +1,30 @@ +using k8s; + +using McMaster.Extensions.CommandLineUtils; + +using Microsoft.Extensions.DependencyInjection; + +namespace KubeOps.Cli.Commands.Utilities; + +[Command( + "api-version", + "av", + Description = "Prints the actual server version of the connected kubernetes cluster. (Aliases: av)")] +internal class Version +{ + public async Task OnExecuteAsync(CommandLineApplication app) + { + var client = app.GetRequiredService(); + var version = await client.Version.GetCodeAsync(); + await app.Out.WriteLineAsync( + $""" + The Kubernetes API reported the following version: + Git-Version: {version.GitVersion} + Major: {version.Major} + Minor: {version.Minor} + Platform: {version.Platform} + """); + + return ExitCodes.Success; + } +} diff --git a/src/KubeOps.Cli/ExitCodes.cs b/src/KubeOps.Cli/ExitCodes.cs new file mode 100644 index 00000000..53c6d51a --- /dev/null +++ b/src/KubeOps.Cli/ExitCodes.cs @@ -0,0 +1,8 @@ +namespace KubeOps.Cli; + +internal static class ExitCodes +{ + public const int Success = 0; + public const int Error = 1; + public const int UsageError = 99; +} diff --git a/src/KubeOps.Cli/KubeOps.Cli.csproj b/src/KubeOps.Cli/KubeOps.Cli.csproj new file mode 100644 index 00000000..09f1b9d0 --- /dev/null +++ b/src/KubeOps.Cli/KubeOps.Cli.csproj @@ -0,0 +1,35 @@ + + + + Exe + net7.0 + true + false + + + + KubeOps.Cli + Kubernetes Operator SDK CLI + + CLI Dotnet Tool for the Kubernetes Operator SDK. + Helps with generating CRDs and other elements for the Operator. + + true + kubeops + + + + + + + + + + + + + + + + + diff --git a/src/KubeOps.Cli/Output/ConsoleOutput.cs b/src/KubeOps.Cli/Output/ConsoleOutput.cs new file mode 100644 index 00000000..0a0aa95f --- /dev/null +++ b/src/KubeOps.Cli/Output/ConsoleOutput.cs @@ -0,0 +1,42 @@ +using McMaster.Extensions.CommandLineUtils; + +namespace KubeOps.Cli.Output; + +internal class ConsoleOutput +{ + private readonly IConsole _console; + + public ConsoleOutput(IConsole console) => _console = console; + + public void Write( + string content, + ConsoleColor foreground = ConsoleColor.White, + ConsoleColor? background = null) + { + if (background != null) + { + _console.BackgroundColor = background.Value; + } + + _console.ForegroundColor = foreground; + _console.Write(content); + _console.ResetColor(); + } + + public void WriteLine( + string content, + ConsoleColor foreground = ConsoleColor.White, + ConsoleColor? background = null) + { + if (background != null) + { + _console.BackgroundColor = background.Value; + } + + _console.ForegroundColor = foreground; + _console.WriteLine(content); + _console.ResetColor(); + } + + public void WriteLine() => _console.WriteLine(); +} diff --git a/src/KubeOps.Cli/Output/OutputFormat.cs b/src/KubeOps.Cli/Output/OutputFormat.cs new file mode 100644 index 00000000..6fd38cb6 --- /dev/null +++ b/src/KubeOps.Cli/Output/OutputFormat.cs @@ -0,0 +1,14 @@ +namespace KubeOps.Cli.Output; + +internal enum OutputFormat +{ + /// + /// Format the output in Kubernetes YAML style. + /// + Yaml, + + /// + /// Format the output in Kubernetes JSON style. + /// + Json, +} diff --git a/src/KubeOps.Cli/Output/ResultOutput.cs b/src/KubeOps.Cli/Output/ResultOutput.cs new file mode 100644 index 00000000..81a0271e --- /dev/null +++ b/src/KubeOps.Cli/Output/ResultOutput.cs @@ -0,0 +1,48 @@ +using System.Text; + +using k8s; + +namespace KubeOps.Cli.Output; + +internal class ResultOutput +{ + private readonly ConsoleOutput _console; + private readonly IDictionary _files = new Dictionary(); + + public ResultOutput(ConsoleOutput console) => _console = console; + + public OutputFormat Format { get; set; } + + public void Add(string filename, object content) => _files.Add(filename, content); + + public async Task Write(string outputDirectory) + { + Directory.CreateDirectory(outputDirectory); + foreach (var (filename, content) in _files) + { + await using var file = File.Open( + Path.Join( + outputDirectory, + filename), + FileMode.Create); + await file.WriteAsync(Encoding.UTF8.GetBytes(Serialize(content))); + } + } + + public void Write() + { + foreach (var (filename, content) in _files) + { + _console.WriteLine(filename, ConsoleColor.Cyan); + _console.WriteLine(Serialize(content)); + _console.WriteLine(); + } + } + + private string Serialize(object data) => Format switch + { + OutputFormat.Yaml => KubernetesYaml.Serialize(data), + OutputFormat.Json => KubernetesJson.Serialize(data), + _ => throw new ArgumentException("Unknown output format."), + }; +} diff --git a/src/KubeOps.Cli/Program.cs b/src/KubeOps.Cli/Program.cs new file mode 100644 index 00000000..91ba567a --- /dev/null +++ b/src/KubeOps.Cli/Program.cs @@ -0,0 +1,22 @@ +using k8s; + +using KubeOps.Cli.Commands; +using KubeOps.Cli.Output; + +using McMaster.Extensions.CommandLineUtils; + +using Microsoft.Extensions.DependencyInjection; + +var services = new ServiceCollection() + .AddSingleton(new Kubernetes(KubernetesClientConfiguration.BuildDefaultConfig())) + .AddSingleton() + .AddSingleton() + .AddSingleton(PhysicalConsole.Singleton) + .BuildServiceProvider(); + +var app = new CommandLineApplication(); +app.Conventions + .UseDefaultConventions() + .UseConstructorInjection(services); + +await app.ExecuteAsync(args); diff --git a/src/KubeOps.Cli/README.md b/src/KubeOps.Cli/README.md new file mode 100644 index 00000000..0232731f --- /dev/null +++ b/src/KubeOps.Cli/README.md @@ -0,0 +1,2 @@ +this project is the CLI of kubeops. +used for all generation commands (generate crds and such) diff --git a/src/KubeOps.Cli/SyntaxObjects/ProjectParser.cs b/src/KubeOps.Cli/SyntaxObjects/ProjectParser.cs new file mode 100644 index 00000000..9aa93aaa --- /dev/null +++ b/src/KubeOps.Cli/SyntaxObjects/ProjectParser.cs @@ -0,0 +1,67 @@ +using System.Reflection; +using System.Text; + +using k8s.Models; + +using KubeOps.Abstractions.Entities.Attributes; + +using Microsoft.Build.Locator; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Emit; +using Microsoft.CodeAnalysis.MSBuild; + +namespace KubeOps.Cli.SyntaxObjects; + +internal sealed class ProjectParser : IDisposable +{ + private readonly MSBuildWorkspace _workspace; + private readonly Project _project; + + static ProjectParser() + { + MSBuildLocator.RegisterDefaults(); + } + + private ProjectParser(MSBuildWorkspace workspace, Project project) + { + _workspace = workspace; + _project = project; + } + + public static async Task CreateAsync(string projectFile) + { + var ws = MSBuildWorkspace.Create(); + var project = await ws.OpenProjectAsync(projectFile); + return new ProjectParser(ws, project); + } + + public async IAsyncEnumerable Entities() + { + var compilation = await _project.GetCompilationAsync(); + if (compilation is null) + { + yield break; + } + + using var assemblyStream = new MemoryStream(); + switch (compilation.Emit(assemblyStream)) + { + case { Success: false, Diagnostics: var diag }: + throw new AggregateException( + $"Compilation failed: {diag.Aggregate(new StringBuilder(), (sb, d) => sb.AppendLine(d.ToString()))}"); + } + + var assembly = Assembly.Load(assemblyStream.ToArray()); + foreach (var type in assembly + .DefinedTypes + .Where(t => t.GetCustomAttributes().Any()) + .Where(type => !type.GetCustomAttributes().Any())) + { + yield return type; + } + } + + public void Dispose() => _workspace.Dispose(); +} diff --git a/src/KubeOps.Generator/EntityDefinitions/AttributedEntity.cs b/src/KubeOps.Generator/EntityDefinitions/AttributedEntity.cs new file mode 100644 index 00000000..b8758231 --- /dev/null +++ b/src/KubeOps.Generator/EntityDefinitions/AttributedEntity.cs @@ -0,0 +1,10 @@ +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace KubeOps.Generator.EntityDefinitions; + +public record struct AttributedEntity( + ClassDeclarationSyntax Class, + string Kind, + string Version, + string? Group, + string? Plural); diff --git a/src/KubeOps.Generator/EntityDefinitions/EntityDefinitionGenerator.cs b/src/KubeOps.Generator/EntityDefinitions/EntityDefinitionGenerator.cs new file mode 100644 index 00000000..5eceb383 --- /dev/null +++ b/src/KubeOps.Generator/EntityDefinitions/EntityDefinitionGenerator.cs @@ -0,0 +1,115 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; + +namespace KubeOps.Generator.EntityDefinitions; + +[Generator] +public class EntityDefinitionGenerator : ISourceGenerator +{ + public void Initialize(GeneratorInitializationContext context) + { + context.RegisterForSyntaxNotifications(() => new KubernetesEntitySyntaxReceiver()); + } + + public void Execute(GeneratorExecutionContext context) + { + if (context.SyntaxContextReceiver is not KubernetesEntitySyntaxReceiver receiver) + { + return; + } + + var declaration = CompilationUnit() + .WithUsings( + List( + new List + { + UsingDirective(IdentifierName("KubeOps.Abstractions.Builder")), + UsingDirective(IdentifierName("KubeOps.Abstractions.Entities")), + })) + .WithMembers(SingletonList(ClassDeclaration("EntityDefinitions") + .WithModifiers(TokenList( + Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.StaticKeyword))) + .WithMembers( + List(receiver.Entities.Select(e => FieldDeclaration( + VariableDeclaration( + IdentifierName("EntityMetadata")) + .WithVariables( + SingletonSeparatedList( + VariableDeclarator(e.Class.Identifier) + .WithInitializer( + EqualsValueClause( + ImplicitObjectCreationExpression() + .WithArgumentList( + ArgumentList( + SeparatedList(new List + { + Argument(LiteralExpression( + SyntaxKind.StringLiteralExpression, + Literal(e.Kind))), + Argument(LiteralExpression( + SyntaxKind.StringLiteralExpression, + Literal(e.Version))), + Argument(e.Group switch + { + null => LiteralExpression( + SyntaxKind.NullLiteralExpression), + _ => LiteralExpression( + SyntaxKind.StringLiteralExpression, + Literal(e.Group)), + }), + Argument(e.Plural switch + { + null => LiteralExpression( + SyntaxKind.NullLiteralExpression), + _ => LiteralExpression( + SyntaxKind.StringLiteralExpression, + Literal(e.Plural)), + }), + })))))))) + .WithModifiers( + TokenList( + Token(SyntaxKind.PublicKeyword), + Token(SyntaxKind.StaticKeyword), + Token(SyntaxKind.ReadOnlyKeyword)))))) + .AddMembers(MethodDeclaration(IdentifierName("IOperatorBuilder"), "RegisterEntitiyMetadata") + .WithModifiers( + TokenList(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.StaticKeyword))) + .WithParameterList(ParameterList( + SingletonSeparatedList( + Parameter( + Identifier("builder")) + .WithModifiers( + TokenList( + Token(SyntaxKind.ThisKeyword))) + .WithType( + IdentifierName("IOperatorBuilder"))))) + .WithBody(Block( + receiver.Entities + .Select(e => ExpressionStatement( + InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + IdentifierName("builder"), + GenericName(Identifier("AddEntityMetadata")) + .WithTypeArgumentList( + TypeArgumentList( + SingletonSeparatedList( + IdentifierName(context.Compilation + .GetSemanticModel(e.Class.SyntaxTree) + .GetDeclaredSymbol(e.Class)! + .ToDisplayString(SymbolDisplayFormat + .FullyQualifiedFormat))))))) + .WithArgumentList( + ArgumentList( + SingletonSeparatedList( + Argument( + IdentifierName(e.Class.Identifier))))))) + .Append(ReturnStatement(IdentifierName("builder")))))))) + .NormalizeWhitespace(); + + context.AddSource("EntityDefinitions.g.cs", $"// \n\n{declaration}"); + } +} diff --git a/src/KubeOps.Generator/EntityDefinitions/KubernetesEntitySyntaxReceiver.cs b/src/KubeOps.Generator/EntityDefinitions/KubernetesEntitySyntaxReceiver.cs new file mode 100644 index 00000000..0456f4a1 --- /dev/null +++ b/src/KubeOps.Generator/EntityDefinitions/KubernetesEntitySyntaxReceiver.cs @@ -0,0 +1,38 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace KubeOps.Generator.EntityDefinitions; + +public class KubernetesEntitySyntaxReceiver : ISyntaxContextReceiver +{ + private const string KindName = "Kind"; + private const string GroupName = "Group"; + private const string PluralName = "Plural"; + private const string VersionName = "ApiVersion"; + private const string DefaultVersion = "v1"; + + public List Entities { get; } = new(); + + public void OnVisitSyntaxNode(GeneratorSyntaxContext context) + { + if (context.Node is not ClassDeclarationSyntax { AttributeLists.Count: > 0 } cls || + cls.AttributeLists.SelectMany(a => a.Attributes) + .FirstOrDefault(a => a.Name.ToString() == "KubernetesEntity") is not { } attr) + { + return; + } + + Entities.Add(new( + cls, + GetArgumentValue(attr, KindName) ?? cls.Identifier.ToString(), + GetArgumentValue(attr, VersionName) ?? DefaultVersion, + GetArgumentValue(attr, GroupName), + GetArgumentValue(attr, PluralName))); + } + + private static string? GetArgumentValue(AttributeSyntax attr, string argName) => + attr.ArgumentList?.Arguments.FirstOrDefault(a => a.NameEquals?.Name.ToString() == argName) is + { Expression: LiteralExpressionSyntax { Token: { ValueText: { } value } } } + ? value + : null; +} diff --git a/src/KubeOps.Generator/KubeOps.Generator.csproj b/src/KubeOps.Generator/KubeOps.Generator.csproj new file mode 100644 index 00000000..f20574ad --- /dev/null +++ b/src/KubeOps.Generator/KubeOps.Generator.csproj @@ -0,0 +1,27 @@ + + + + netstandard2.0 + true + true + true + false + + + + KubeOps.Generator + Kubernetes Operator SDK SourceGenerator + + Source Generator for the Kubernetes Operator SDK. + Helps with EntityMetadata and registering them + within the Operator. + + + + + + + + + + diff --git a/src/KubeOps.Generator/Properties/launchSettings.json b/src/KubeOps.Generator/Properties/launchSettings.json new file mode 100644 index 00000000..c3703633 --- /dev/null +++ b/src/KubeOps.Generator/Properties/launchSettings.json @@ -0,0 +1,9 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "profiles": { + "KubeOps.Generator": { + "commandName": "DebugRoslynComponent", + "targetProject": "../../examples/Operator/Operator.csproj" + } + } +} diff --git a/src/KubeOps.Generator/README.md b/src/KubeOps.Generator/README.md new file mode 100644 index 00000000..7487a200 --- /dev/null +++ b/src/KubeOps.Generator/README.md @@ -0,0 +1 @@ +generator diff --git a/src/KubeOps.Operator.Web/KubeOps.Operator.Web.csproj b/src/KubeOps.Operator.Web/KubeOps.Operator.Web.csproj new file mode 100644 index 00000000..44b237dc --- /dev/null +++ b/src/KubeOps.Operator.Web/KubeOps.Operator.Web.csproj @@ -0,0 +1,24 @@ + + + + net6.0;net7.0 + true + + + + KubeOps.Operator.Web + Kubernetes Operator SDK CustomResourceDefinition ASP.NET + + This is an operator sdk written in c#. + It enables a developer to create a custom controller for CRDs + (CustomResourceDefinitions) that runs on kubernetes. + This operator uses ASP.net to support webhooks and external + access to the operator. + + + + + + + + diff --git a/src/KubeOps.Operator.Web/README.md b/src/KubeOps.Operator.Web/README.md new file mode 100644 index 00000000..ad5332fc --- /dev/null +++ b/src/KubeOps.Operator.Web/README.md @@ -0,0 +1 @@ +operator web diff --git a/src/KubeOps.Operator/Builder/OperatorBuilder.cs b/src/KubeOps.Operator/Builder/OperatorBuilder.cs new file mode 100644 index 00000000..f82bbd75 --- /dev/null +++ b/src/KubeOps.Operator/Builder/OperatorBuilder.cs @@ -0,0 +1,46 @@ +using k8s; +using k8s.Models; + +using KubeOps.Abstractions.Builder; +using KubeOps.Abstractions.Controller; +using KubeOps.Abstractions.Entities; +using KubeOps.Operator.Client; +using KubeOps.Operator.Watcher; + +using Microsoft.Extensions.DependencyInjection; + +namespace KubeOps.Operator.Builder; + +internal class OperatorBuilder : IOperatorBuilder +{ + private readonly IKubernetesClientFactory _entityClientFactory = new KubernetesClientFactory(); + + public OperatorBuilder(IServiceCollection services) + { + Services = services; + Services.AddSingleton(_entityClientFactory); + } + + public IServiceCollection Services { get; } + + public IOperatorBuilder AddEntityMetadata(EntityMetadata metadata) + where TEntity : IKubernetesObject + { + _entityClientFactory.RegisterMetadata(metadata); + return this; + } + + public IOperatorBuilder AddController() + where TImplementation : class, IEntityController + where TEntity : IKubernetesObject + { + Services.AddScoped, TImplementation>(); + Services.AddHostedService>(); + return this; + } + + public IOperatorBuilder AddController(EntityMetadata metadata) + where TImplementation : class, IEntityController + where TEntity : IKubernetesObject => + AddController().AddEntityMetadata(metadata); +} diff --git a/src/KubeOps.Operator/Client/IKubernetesClientFactory.cs b/src/KubeOps.Operator/Client/IKubernetesClientFactory.cs new file mode 100644 index 00000000..d47399ac --- /dev/null +++ b/src/KubeOps.Operator/Client/IKubernetesClientFactory.cs @@ -0,0 +1,19 @@ +using System.Collections.Immutable; + +using k8s; +using k8s.Models; + +using KubeOps.Abstractions.Entities; + +namespace KubeOps.Operator.Client; + +public interface IKubernetesClientFactory +{ + IImmutableDictionary RegisteredMetadata { get; } + + void RegisterMetadata(EntityMetadata metadata) + where TEntity : IKubernetesObject; + + GenericClient GetClient(IKubernetes? kubernetes = null) + where TEntity : IKubernetesObject; +} diff --git a/src/KubeOps.Operator/Client/KubernetesClientFactory.cs b/src/KubeOps.Operator/Client/KubernetesClientFactory.cs new file mode 100644 index 00000000..d049436c --- /dev/null +++ b/src/KubeOps.Operator/Client/KubernetesClientFactory.cs @@ -0,0 +1,45 @@ +using System.Collections.Immutable; + +using k8s; +using k8s.Models; + +using KubeOps.Abstractions.Entities; + +namespace KubeOps.Operator.Client; + +internal class KubernetesClientFactory : IKubernetesClientFactory +{ + private readonly Dictionary _registeredMetadata = new(); + + public IImmutableDictionary RegisteredMetadata => _registeredMetadata.ToImmutableDictionary(); + + public void RegisterMetadata(EntityMetadata metadata) + where TEntity : IKubernetesObject + { + _registeredMetadata[typeof(TEntity)] = metadata; + } + + public GenericClient GetClient(IKubernetes? kubernetes = null) + where TEntity : IKubernetesObject + { + if (!_registeredMetadata.TryGetValue(typeof(TEntity), out var metadata)) + { + throw new InvalidOperationException( + $"No metadata registered for entity {typeof(TEntity).Name}. " + + "Please register metadata for this entity before using the client."); + } + + return metadata.Group switch + { + null => new GenericClient( + kubernetes ?? new Kubernetes(KubernetesClientConfiguration.BuildDefaultConfig()), + metadata.Version, + metadata.PluralName), + _ => new GenericClient( + kubernetes ?? new Kubernetes(KubernetesClientConfiguration.BuildDefaultConfig()), + metadata.Group, + metadata.Version, + metadata.PluralName), + }; + } +} diff --git a/src/KubeOps.Operator/Extensions/ServiceCollectionExtensions.cs b/src/KubeOps.Operator/Extensions/ServiceCollectionExtensions.cs new file mode 100644 index 00000000..b09d174d --- /dev/null +++ b/src/KubeOps.Operator/Extensions/ServiceCollectionExtensions.cs @@ -0,0 +1,17 @@ +using KubeOps.Abstractions.Builder; +using KubeOps.Operator.Builder; + +using Microsoft.Extensions.DependencyInjection; + +namespace KubeOps.Operator.Extensions; + +public static class ServiceCollectionExtensions +{ + /// + /// Add the Kubernetes operator to the dependency injection. + /// + /// . + /// An for further configuration and chaining. + public static IOperatorBuilder AddKubernetesOperator( + this IServiceCollection services) => new OperatorBuilder(services); +} diff --git a/src/KubeOps.Operator/KubeOps.Operator.csproj b/src/KubeOps.Operator/KubeOps.Operator.csproj new file mode 100644 index 00000000..a16dc43b --- /dev/null +++ b/src/KubeOps.Operator/KubeOps.Operator.csproj @@ -0,0 +1,28 @@ + + + + net6.0;net7.0 + true + + + + KubeOps.Operator + Kubernetes Operator SDK CustomResourceDefinition + + This is an operator sdk written in c#. + It enables a developer to create a custom controller for CRDs + (CustomResourceDefinitions) that runs on kubernetes. This operator + may run without ASP.net but needs the IHost of dotnet to run. + + + + + + + + + + + + + diff --git a/src/KubeOps.Operator/README.md b/src/KubeOps.Operator/README.md new file mode 100644 index 00000000..e196e4b5 --- /dev/null +++ b/src/KubeOps.Operator/README.md @@ -0,0 +1 @@ +operator diff --git a/src/KubeOps.Operator/Watcher/ResourceWatcher{TEntity}.cs b/src/KubeOps.Operator/Watcher/ResourceWatcher{TEntity}.cs new file mode 100644 index 00000000..bef1c028 --- /dev/null +++ b/src/KubeOps.Operator/Watcher/ResourceWatcher{TEntity}.cs @@ -0,0 +1,148 @@ +using System.Runtime.Serialization; +using System.Text.Json; + +using k8s; +using k8s.Models; + +using KubeOps.Abstractions.Controller; +using KubeOps.Operator.Client; + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; + +namespace KubeOps.Operator.Watcher; + +internal class ResourceWatcher : IHostedService + where TEntity : IKubernetesObject +{ + private readonly ILogger> _logger; + private readonly IServiceProvider _provider; + private readonly GenericClient _client; + + private Watcher? _watcher; + + public ResourceWatcher( + ILogger> logger, + IServiceProvider provider, + IKubernetesClientFactory factory) + { + _logger = logger; + _provider = provider; + _client = factory.GetClient(); + } + + public Task StartAsync(CancellationToken cancellationToken) + { + _logger.LogInformation("Starting resource watcher for {ResourceType}.", typeof(TEntity).Name); + WatchResource(); + return Task.CompletedTask; + } + + public Task StopAsync(CancellationToken cancellationToken) + { + _logger.LogInformation("Stopping resource watcher for {ResourceType}.", typeof(TEntity).Name); + StopWatching(); + return Task.CompletedTask; + } + + private void WatchResource() + { + if (_watcher != null) + { + if (!_watcher.Watching) + { + _watcher.Dispose(); + } + else + { + _logger.LogTrace("""Watcher for type "{type}" already running.""", typeof(TEntity)); + return; + } + } + + _watcher = _client.Watch(OnEvent, OnError, OnClosed); + } + + private void StopWatching() + { + _watcher?.Dispose(); + } + + private void OnClosed() + { + _logger.LogDebug("The server closed the connection. Trying to reconnect."); + WatchResource(); + } + + private void OnError(Exception e) + { + switch (e) + { + case SerializationException when + e.InnerException is JsonException && + e.InnerException.Message.Contains("The input does not contain any JSON tokens"): + _logger.LogDebug( + """The watcher received an empty response for resource "{resource}".""", + typeof(TEntity)); + return; + + case HttpRequestException when + e.InnerException is EndOfStreamException && + e.InnerException.Message.Contains("Attempted to read past the end of the stream."): + _logger.LogDebug( + """The watcher received a known error from the watched resource "{resource}". This indicates that there are no instances of this resource.""", + typeof(TEntity)); + return; + } + + _logger.LogError(e, """There was an error while watching the resource "{resource}".""", typeof(TEntity)); + WatchResource(); + } + + private async void OnEvent(WatchEventType type, TEntity entity) + { + _logger.LogTrace( + """Received watch event "{eventType}" for "{kind}/{name}".""", + type, + entity.Kind, + entity.Name()); + + if (type is WatchEventType.Bookmark or WatchEventType.Error) + { + return; + } + + await using var scope = _provider.CreateAsyncScope(); + var controller = scope.ServiceProvider.GetRequiredService>(); + try + { + switch (type) + { + case WatchEventType.Added: + case WatchEventType.Modified: + await controller.ReconcileAsync(entity); + break; + case WatchEventType.Deleted: + await controller.DeletedAsync(entity); + break; + default: + _logger.LogWarning( + """Received unknown watch event type "{eventType}" for "{kind}/{name}".""", + type, + entity.Kind, + entity.Name()); + break; + } + } + catch (Exception e) + { + _logger.LogWarning( + e, + "Reconciliation of {eventType} for {kind}/{name} failed.", + type, + entity.Kind, + entity.Name()); + } + } +} diff --git a/src/KubeOps.Transpiler/Crds/CrdConversionException.cs b/src/KubeOps.Transpiler/Crds/CrdConversionException.cs new file mode 100644 index 00000000..62ae630e --- /dev/null +++ b/src/KubeOps.Transpiler/Crds/CrdConversionException.cs @@ -0,0 +1,18 @@ +namespace KubeOps.Transpiler.Crds; + +public class CrdConversionException : Exception +{ + public CrdConversionException() + { + } + + public CrdConversionException(string message) + : base(message) + { + } + + public CrdConversionException(string message, Exception innerException) + : base(message, innerException) + { + } +} diff --git a/src/KubeOps.Transpiler/Crds/CrdPropertyTypeException.cs b/src/KubeOps.Transpiler/Crds/CrdPropertyTypeException.cs new file mode 100644 index 00000000..33e3994b --- /dev/null +++ b/src/KubeOps.Transpiler/Crds/CrdPropertyTypeException.cs @@ -0,0 +1,19 @@ +namespace KubeOps.Transpiler.Crds; + +public class CrdPropertyTypeException : Exception +{ + public CrdPropertyTypeException() + : this("The given property has an invalid type.") + { + } + + public CrdPropertyTypeException(string message) + : base(message) + { + } + + public CrdPropertyTypeException(string message, Exception innerException) + : base(message, innerException) + { + } +} diff --git a/src/KubeOps.Transpiler/Crds/CrdTranspiler.cs b/src/KubeOps.Transpiler/Crds/CrdTranspiler.cs new file mode 100644 index 00000000..18aff534 --- /dev/null +++ b/src/KubeOps.Transpiler/Crds/CrdTranspiler.cs @@ -0,0 +1,427 @@ +using System.Collections; +using System.Diagnostics.CodeAnalysis; +using System.Reflection; +using System.Text.Json.Serialization; + +using k8s; +using k8s.Models; + +using KubeOps.Abstractions.Entities; +using KubeOps.Abstractions.Entities.Attributes; + +using Namotion.Reflection; + +namespace KubeOps.Transpiler.Crds; + +public static class CrdTranspiler +{ + private const string Integer = "integer"; + private const string Number = "number"; + private const string String = "string"; + private const string Boolean = "boolean"; + private const string Object = "object"; + private const string Array = "array"; + + private const string Int32 = "int32"; + private const string Int64 = "int64"; + private const string Float = "float"; + private const string Double = "double"; + private const string DateTime = "date-time"; + + private static readonly string[] IgnoredToplevelProperties = { "metadata", "apiversion", "kind" }; + + public static V1CustomResourceDefinition Create(Type entityType) + { + var entityAttribute = entityType.GetCustomAttribute(); + if (entityAttribute == null) + { + throw new ArgumentException("The given type is not a valid Kubernetes entity.", nameof(entityType)); + } + + var entityMetadata = new EntityMetadata( + entityAttribute.Kind, + entityAttribute.ApiVersion, + string.IsNullOrWhiteSpace(entityAttribute.Group) ? null : entityAttribute.Group, + string.IsNullOrWhiteSpace(entityAttribute.PluralName) ? null : entityAttribute.PluralName); + var entityScope = entityType.GetCustomAttribute()?.Scope.ToString() ?? + default(EntityScope).ToString(); + + var crd = new V1CustomResourceDefinition(new()).Initialize(); + crd.Metadata.Name = $"{entityMetadata.PluralName}.{entityMetadata.Group}"; + + var shortNames = entityType.GetCustomAttributes(true) + .Aggregate( + new List(), + (list, attribute) => + { + list.AddRange(attribute.ShortNames); + return list; + }); + + var spec = crd.Spec; + spec.Group = entityMetadata.Group; + spec.Names = new V1CustomResourceDefinitionNames + { + Kind = entityMetadata.Kind, + ListKind = entityMetadata.ListKind, + Singular = entityMetadata.SingularName, + Plural = entityMetadata.PluralName, + ShortNames = shortNames.Any() ? shortNames : null, + }; + spec.Scope = entityScope; + + var version = new V1CustomResourceDefinitionVersion(entityMetadata.Version, true, true); + if (entityType.GetProperty("Status") != null || entityType.GetProperty("status") != null) + { + version.Subresources = new V1CustomResourceSubresources(null, new object()); + } + + var columns = new List(); + version.Schema = + new V1CustomResourceValidation(MapType(entityType, columns, string.Empty)); + version.AdditionalPrinterColumns = entityType + .GetCustomAttributes(true) + .Select(a => new V1CustomResourceColumnDefinition + { + Name = a.Name, + JsonPath = a.JsonPath, + Type = a.Type, + Description = a.Description, + Format = a.Format, + Priority = a.Priority switch + { + PrinterColumnPriority.StandardView => 0, + _ => 1, + }, + }) + .Concat(columns) + .ToList(); + + if (version.AdditionalPrinterColumns.Count == 0) + { + version.AdditionalPrinterColumns = null; + } + + spec.Versions = new[] { version }; + + crd.Validate(); + return crd; + } + + private static V1JSONSchemaProps MapType( + Type type, + IList additionalColumns, + string jsonPath) + { + var props = new V1JSONSchemaProps(); + + // this description is on the class + props.Description ??= type.GetCustomAttributes(true).FirstOrDefault()?.Description; + + var isSimpleType = IsSimpleType(type); + + if (type == typeof(V1ObjectMeta)) + { + props.Type = Object; + } + else if (type.IsArray) + { + props.Type = Array; + props.Items = MapType( + type.GetElementType() ?? throw new ArgumentNullException(nameof(type), "No Array Element Type found"), + additionalColumns, + jsonPath); + } + else if (!isSimpleType && type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IDictionary<,>)) + { + var genericTypes = type.GenericTypeArguments; + props.Type = Object; + props.AdditionalProperties = MapType(genericTypes[1], additionalColumns, jsonPath); + } + else if (!isSimpleType && + type.IsGenericType && + type.GetGenericTypeDefinition() == typeof(IEnumerable<>) && + type.GenericTypeArguments.Length == 1 && + type.GenericTypeArguments.Single().IsGenericType && + type.GenericTypeArguments.Single().GetGenericTypeDefinition() == typeof(KeyValuePair<,>)) + { + var genericTypes = type.GenericTypeArguments.Single().GenericTypeArguments; + props.Type = Object; + props.AdditionalProperties = MapType(genericTypes[1], additionalColumns, jsonPath); + } + else if (!isSimpleType && + (typeof(IDictionary).IsAssignableFrom(type) || + (type.IsGenericType && + type.GetGenericArguments().FirstOrDefault()?.IsGenericType == true && + type.GetGenericArguments().FirstOrDefault()?.GetGenericTypeDefinition() == + typeof(KeyValuePair<,>)))) + { + props.Type = Object; + props.XKubernetesPreserveUnknownFields = true; + } + else if (!isSimpleType && IsGenericEnumerableType(type, out Type? closingType)) + { + props.Type = Array; + props.Items = MapType(closingType, additionalColumns, jsonPath); + } + else if (type == typeof(IntstrIntOrString)) + { + props.XKubernetesIntOrString = true; + } + else if (typeof(IKubernetesObject).IsAssignableFrom(type) && + type is { IsAbstract: false, IsInterface: false } && + type.Assembly == typeof(IKubernetesObject).Assembly) + { + SetEmbeddedResourceProperties(props); + } + else if (!isSimpleType) + { + ProcessType(type, props, additionalColumns, jsonPath); + } + else if (type == typeof(int) || Nullable.GetUnderlyingType(type) == typeof(int)) + { + props.Type = Integer; + props.Format = Int32; + } + else if (type == typeof(long) || Nullable.GetUnderlyingType(type) == typeof(long)) + { + props.Type = Integer; + props.Format = Int64; + } + else if (type == typeof(float) || Nullable.GetUnderlyingType(type) == typeof(float)) + { + props.Type = Number; + props.Format = Float; + } + else if (type == typeof(double) || Nullable.GetUnderlyingType(type) == typeof(double)) + { + props.Type = Number; + props.Format = Double; + } + else if (type == typeof(string) || Nullable.GetUnderlyingType(type) == typeof(string)) + { + props.Type = String; + } + else if (type == typeof(bool) || Nullable.GetUnderlyingType(type) == typeof(bool)) + { + props.Type = Boolean; + } + else if (type == typeof(DateTime) || Nullable.GetUnderlyingType(type) == typeof(DateTime)) + { + props.Type = String; + props.Format = DateTime; + } + else if (type.IsEnum) + { + props.Type = String; + props.EnumProperty = new List(Enum.GetNames(type)); + } + else if (Nullable.GetUnderlyingType(type)?.IsEnum == true) + { + props.Type = String; + props.EnumProperty = new List(Enum.GetNames(Nullable.GetUnderlyingType(type)!)); + } + else + { + throw new CrdPropertyTypeException(); + } + + return props; + } + + private static V1JSONSchemaProps MapProperty( + PropertyInfo info, + IList additionalColumns, + string jsonPath) + { + V1JSONSchemaProps props; + try + { + props = MapType(info.PropertyType, additionalColumns, jsonPath); + } + catch (Exception ex) + { + throw new CrdConversionException( + $"""During conversion of the property "{info.Name}" with type "{info.PropertyType.Name}", an error occured.""", + ex); + } + + var contextual = info.ToContextualProperty(); + + // Check for nullability and nullable types + if (contextual.Nullability == Nullability.Nullable) + { + props.Nullable = true; + } + + // Get the description on the property + props.Description ??= info.GetCustomAttribute()?.Description; + var docsSummary = contextual.GetXmlDocsSummary(); + if (!string.IsNullOrWhiteSpace(docsSummary)) + { + props.Description ??= docsSummary; + } + + var externalDoc = info.GetCustomAttribute(); + if (externalDoc != null) + { + props.ExternalDocs = new V1ExternalDocumentation(externalDoc.Description, externalDoc.Url); + } + + // Get items (of array probably) description + var items = info.GetCustomAttribute(); + if (items != null) + { + props.MinItems = items.MinItems == -1 ? null : items.MinItems; + props.MaxItems = items.MaxItems == -1 ? null : items.MaxItems; + } + + // Get length description + var length = info.GetCustomAttribute(); + if (length != null) + { + props.MinLength = length.MinLength == -1 ? null : length.MinLength; + props.MaxLength = length.MaxLength == -1 ? null : length.MaxLength; + } + + // get multiple of description + var multipleOf = info.GetCustomAttribute(); + if (multipleOf != null) + { + props.MultipleOf = multipleOf.Value; + } + + // get pattern description + var pattern = info.GetCustomAttribute(); + if (pattern != null) + { + props.Pattern = pattern.RegexPattern; + } + + // get range max description + var rangeMax = info.GetCustomAttribute(); + if (rangeMax != null) + { + props.Maximum = rangeMax.Maximum; + props.ExclusiveMaximum = rangeMax.ExclusiveMaximum; + } + + // get range min description + var rangeMin = info.GetCustomAttribute(); + if (rangeMin != null) + { + props.Minimum = rangeMin.Minimum; + props.ExclusiveMinimum = rangeMin.ExclusiveMinimum; + } + + // check if preserve unknown is set + if (info.GetCustomAttribute() != null) + { + props.XKubernetesPreserveUnknownFields = true; + } + + // check if embedded resource is set + if (info.GetCustomAttribute() != null) + { + SetEmbeddedResourceProperties(props); + } + + // get additional printer column information + var additionalColumn = info.GetCustomAttribute(); + if (additionalColumn != null) + { + additionalColumns.Add( + new V1CustomResourceColumnDefinition + { + Name = additionalColumn.Name ?? info.Name, + Description = props.Description, + JsonPath = jsonPath, + Priority = additionalColumn.Priority switch + { + PrinterColumnPriority.StandardView => 0, + _ => 1, + }, + Type = props.Type, + Format = props.Format, + }); + } + + return props; + } + + private static void SetEmbeddedResourceProperties(V1JSONSchemaProps props) + { + props.Type = Object; + props.Properties = null; + props.XKubernetesPreserveUnknownFields = true; + props.XKubernetesEmbeddedResource = true; + } + + private static void ProcessType( + Type type, + V1JSONSchemaProps props, + IList additionalColumns, + string jsonPath) + { + props.Type = Object; + + props.Properties = new Dictionary( + type.GetProperties() + .Where( + info => jsonPath != string.Empty || + !IgnoredToplevelProperties.Contains(info.Name.ToLowerInvariant())) + .Where(info => info.GetCustomAttribute() == null) + .Select( + prop => KeyValuePair.Create( + GetPropertyName(prop), + MapProperty(prop, additionalColumns, $"{jsonPath}.{GetPropertyName(prop)}")))); + props.Required = type.GetProperties() + .Where( + prop => prop.GetCustomAttribute() != null && + prop.GetCustomAttribute() == null) + .Select(GetPropertyName) + .ToList(); + + if (props.Required.Count == 0) + { + props.Required = null; + } + } + + private static bool IsSimpleType(Type type) => + type.IsPrimitive || + new[] + { + typeof(string), typeof(decimal), typeof(DateTime), typeof(DateTimeOffset), typeof(TimeSpan), + typeof(Guid), + }.Contains(type) || + type.IsEnum || + Convert.GetTypeCode(type) != TypeCode.Object || + (type.IsGenericType && + type.GetGenericTypeDefinition() == typeof(Nullable<>) && + IsSimpleType(type.GetGenericArguments()[0])); + + private static string GetPropertyName(PropertyInfo property) + { + var attribute = property.GetCustomAttribute(); + var propertyName = attribute?.Name ?? property.Name; + return propertyName[..1].ToLowerInvariant() + propertyName[1..]; + } + + private static bool IsGenericEnumerableType(Type type, [NotNullWhen(true)] out Type? closingType) + { + if (type.IsGenericType && typeof(IEnumerable<>).IsAssignableFrom(type.GetGenericTypeDefinition())) + { + closingType = type.GetGenericArguments()[0]; + return true; + } + + closingType = type + .GetInterfaces() + .Where(t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(IEnumerable<>)) + .Select(t => t.GetGenericArguments()[0]) + .FirstOrDefault(); + + return closingType != null; + } +} diff --git a/src/KubeOps.Transpiler/KubeOps.Transpiler.csproj b/src/KubeOps.Transpiler/KubeOps.Transpiler.csproj new file mode 100644 index 00000000..1005f50c --- /dev/null +++ b/src/KubeOps.Transpiler/KubeOps.Transpiler.csproj @@ -0,0 +1,31 @@ + + + + netstandard2.1;net6.0;net7.0 + true + + + + KubeOps.Transpiler + Kubernetes Operator SDK Transpilation CRD + + Transpilation elements for the Kubernetes Operator SDK. + Enables the developer to create CRDs from types and other + Kubernetes related elements via reflection. + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/KubeOps.Transpiler/README.md b/src/KubeOps.Transpiler/README.md new file mode 100644 index 00000000..d9de50e1 --- /dev/null +++ b/src/KubeOps.Transpiler/README.md @@ -0,0 +1 @@ +transpiler :) diff --git a/test/KubeOps.Cli.Test/GlobalUsings.cs b/test/KubeOps.Cli.Test/GlobalUsings.cs new file mode 100644 index 00000000..e1065597 --- /dev/null +++ b/test/KubeOps.Cli.Test/GlobalUsings.cs @@ -0,0 +1 @@ +global using Xunit; diff --git a/test/KubeOps.Cli.Test/KubeOps.Cli.Test.csproj b/test/KubeOps.Cli.Test/KubeOps.Cli.Test.csproj new file mode 100644 index 00000000..5635d5cb --- /dev/null +++ b/test/KubeOps.Cli.Test/KubeOps.Cli.Test.csproj @@ -0,0 +1,25 @@ + + + + net7.0 + enable + enable + + false + true + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + diff --git a/test/KubeOps.Generator.Test/GlobalUsings.cs b/test/KubeOps.Generator.Test/GlobalUsings.cs new file mode 100644 index 00000000..e1065597 --- /dev/null +++ b/test/KubeOps.Generator.Test/GlobalUsings.cs @@ -0,0 +1 @@ +global using Xunit; diff --git a/test/KubeOps.Generator.Test/KubeOps.Generator.Test.csproj b/test/KubeOps.Generator.Test/KubeOps.Generator.Test.csproj new file mode 100644 index 00000000..5635d5cb --- /dev/null +++ b/test/KubeOps.Generator.Test/KubeOps.Generator.Test.csproj @@ -0,0 +1,25 @@ + + + + net7.0 + enable + enable + + false + true + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + diff --git a/test/KubeOps.Operator.Test/GlobalUsings.cs b/test/KubeOps.Operator.Test/GlobalUsings.cs new file mode 100644 index 00000000..e1065597 --- /dev/null +++ b/test/KubeOps.Operator.Test/GlobalUsings.cs @@ -0,0 +1 @@ +global using Xunit; diff --git a/test/KubeOps.Operator.Test/KubeOps.Operator.Test.csproj b/test/KubeOps.Operator.Test/KubeOps.Operator.Test.csproj new file mode 100644 index 00000000..5635d5cb --- /dev/null +++ b/test/KubeOps.Operator.Test/KubeOps.Operator.Test.csproj @@ -0,0 +1,25 @@ + + + + net7.0 + enable + enable + + false + true + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + diff --git a/test/KubeOps.Operator.Web.Test/GlobalUsings.cs b/test/KubeOps.Operator.Web.Test/GlobalUsings.cs new file mode 100644 index 00000000..e1065597 --- /dev/null +++ b/test/KubeOps.Operator.Web.Test/GlobalUsings.cs @@ -0,0 +1 @@ +global using Xunit; diff --git a/test/KubeOps.Operator.Web.Test/KubeOps.Operator.Web.Test.csproj b/test/KubeOps.Operator.Web.Test/KubeOps.Operator.Web.Test.csproj new file mode 100644 index 00000000..5635d5cb --- /dev/null +++ b/test/KubeOps.Operator.Web.Test/KubeOps.Operator.Web.Test.csproj @@ -0,0 +1,25 @@ + + + + net7.0 + enable + enable + + false + true + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + diff --git a/toc.yml b/toc.yml new file mode 100644 index 00000000..2244f25f --- /dev/null +++ b/toc.yml @@ -0,0 +1,18 @@ +- name: Documentation and Usage + href: docs/ +- name: Contribution + href: ./CONTRIBUTING.md +- name: Packages + items: + - name: KubeOps Abstractions + href: src/KubeOps.Abstractions/README.md + - name: KubeOps Cli + href: src/KubeOps.Cli/README.md + - name: KubeOps Generator + href: src/KubeOps.Generator/README.md + - name: KubeOps Operator + href: src/KubeOps.Operator/README.md + - name: KubeOps Operator Web + href: src/KubeOps.Operator.Web/README.md +- name: API Reference + href: docs/api/