From 56f1660814fe611dad48c9e9601eed53b28e52ae Mon Sep 17 00:00:00 2001 From: Adam Friedman Date: Tue, 16 Jan 2024 12:01:05 +1100 Subject: [PATCH 01/10] Add DI registration methods for named KubeClientOptions from pod service account --- .../ClientRegistrationExtensions.cs | 35 ------ ...KubeClientOptionsRegistrationExtensions.cs | 118 ++++++++++++++++++ src/KubeClient/KubeClientOptions.cs | 63 ++++++---- .../TestBase.cs | 2 +- 4 files changed, 158 insertions(+), 60 deletions(-) diff --git a/src/KubeClient.Extensions.DependencyInjection/ClientRegistrationExtensions.cs b/src/KubeClient.Extensions.DependencyInjection/ClientRegistrationExtensions.cs index 0eff62f3..0b87d952 100644 --- a/src/KubeClient.Extensions.DependencyInjection/ClientRegistrationExtensions.cs +++ b/src/KubeClient.Extensions.DependencyInjection/ClientRegistrationExtensions.cs @@ -154,41 +154,6 @@ public static IServiceCollection AddKubeClient(this IServiceCollection services, return services; } - /// - /// Add named to the service collection. - /// - /// - /// The service collection to configure. - /// - /// - /// A name used to resolve the options. - /// - /// - /// A delegate that performs required configuration of the . - /// - /// - /// The configured service collection. - /// - public static IServiceCollection AddKubeClientOptions(this IServiceCollection services, string name, Action configure) - { - if (services == null) - throw new ArgumentNullException(nameof(services)); - - if (String.IsNullOrWhiteSpace(name)) - throw new ArgumentException("Argument cannot be null, empty, or entirely composed of whitespace: 'name'.", nameof(name)); - - if (configure == null) - throw new ArgumentNullException(nameof(configure)); - - services.Configure(name, options => - { - configure(options); - options.EnsureValid(); - }); - - return services; - } - /// /// Add support for named Kubernetes client instances. /// diff --git a/src/KubeClient.Extensions.DependencyInjection/KubeClientOptionsRegistrationExtensions.cs b/src/KubeClient.Extensions.DependencyInjection/KubeClientOptionsRegistrationExtensions.cs index 3faeb924..e7574937 100644 --- a/src/KubeClient.Extensions.DependencyInjection/KubeClientOptionsRegistrationExtensions.cs +++ b/src/KubeClient.Extensions.DependencyInjection/KubeClientOptionsRegistrationExtensions.cs @@ -12,6 +12,70 @@ namespace KubeClient /// public static class KubeClientOptionsRegistrationExtensions { + /// + /// Add to the service collection. + /// + /// + /// The service collection to configure. + /// + /// + /// A delegate that performs required configuration of the . + /// + /// + /// The configured service collection. + /// + public static IServiceCollection AddKubeClientOptions(this IServiceCollection services, Action configure) + { + if (services == null) + throw new ArgumentNullException(nameof(services)); + + if (configure == null) + throw new ArgumentNullException(nameof(configure)); + + services.Configure(options => + { + configure(options); + options.EnsureValid(); + }); + + return services; + } + + /// + /// Add named to the service collection. + /// + /// + /// The service collection to configure. + /// + /// + /// A name used to resolve the options. + /// + /// + /// A delegate that performs required configuration of the . + /// + /// + /// The configured service collection. + /// + public static IServiceCollection AddKubeClientOptions(this IServiceCollection services, string name, Action configure) + { + if (services == null) + throw new ArgumentNullException(nameof(services)); + + if (String.IsNullOrWhiteSpace(name)) + throw new ArgumentException("Argument cannot be null, empty, or entirely composed of whitespace: 'name'.", nameof(name)); + + if (configure == null) + throw new ArgumentNullException(nameof(configure)); + + services.Configure(name, options => + { + configure(options); + options.EnsureValid(); + }); + + return services; + } + /// /// Add from local Kubernetes client configuration. /// @@ -210,5 +274,59 @@ public static IServiceCollection AddKubeClientOptionsFromKubeConfig(this IServic return services; } + + /// + /// Add from the pod service account. + /// + /// + /// The service collection to configure. + /// + /// + /// The configured service collection. + /// + public static IServiceCollection AddKubeClientOptionsFromPodServiceAccount(this IServiceCollection services) + { + if (services == null) + throw new ArgumentNullException(nameof(services)); + + services.AddKubeClientOptions(kubeClientOptions => + { + KubeClientOptions fromPodServiceAccount = KubeClientOptions.FromPodServiceAccount(); + + fromPodServiceAccount.CopyTo(kubeClientOptions); + }); + + return services; + } + + /// + /// Add named from the pod service account. + /// + /// + /// The service collection to configure. + /// + /// + /// The name used to resolve these options. + /// + /// + /// The configured service collection. + /// + public static IServiceCollection AddKubeClientOptionsFromPodServiceAccount(this IServiceCollection services, string name) + { + if (services == null) + throw new ArgumentNullException(nameof(services)); + + if (String.IsNullOrWhiteSpace(name)) + throw new ArgumentException($"Argument cannot be null, empty, or entirely composed of whitespace: {nameof(name)}.", nameof(name)); + + services.AddKubeClientOptions(name, kubeClientOptions => + { + KubeClientOptions fromPodServiceAccount = KubeClientOptions.FromPodServiceAccount(); + + fromPodServiceAccount.CopyTo(kubeClientOptions); + }); + + return services; + } } } diff --git a/src/KubeClient/KubeClientOptions.cs b/src/KubeClient/KubeClientOptions.cs index 03c482ba..c56a5289 100644 --- a/src/KubeClient/KubeClientOptions.cs +++ b/src/KubeClient/KubeClientOptions.cs @@ -134,36 +134,51 @@ public KubeClientOptions(string apiEndPoint) public Dictionary EnvironmentVariables { get; set; } /// - /// Create a copy of the . + /// Create a copy of the . /// - /// The new . + /// + /// The new . + /// public KubeClientOptions Clone() { - var clonedOptions = new KubeClientOptions - { - AccessToken = AccessToken, - AccessTokenCommand = AccessTokenCommand, - AccessTokenCommandArguments = AccessTokenCommandArguments, - AccessTokenExpirySelector = AccessTokenExpirySelector, - AccessTokenSelector = AccessTokenSelector, - AllowInsecure = AllowInsecure, - ApiEndPoint = ApiEndPoint, - AuthStrategy = AuthStrategy, - CertificationAuthorityCertificate = CertificationAuthorityCertificate, - ClientCertificate = ClientCertificate, - InitialAccessToken = InitialAccessToken, - InitialTokenExpiryUtc = InitialTokenExpiryUtc, - KubeNamespace = KubeNamespace, - LoggerFactory = LoggerFactory, - LogHeaders = LogHeaders, - LogPayloads = LogPayloads, - EnvironmentVariables = EnvironmentVariables - }; - clonedOptions.ModelTypeAssemblies.AddRange(ModelTypeAssemblies); - + var clonedOptions = new KubeClientOptions(); + + CopyTo(clonedOptions); + return clonedOptions; } + /// + /// Copy all properties from the to other . + /// + /// + /// The target . + /// + public void CopyTo(KubeClientOptions toOptions) + { + if (toOptions == null) + throw new ArgumentNullException(nameof(toOptions)); + + toOptions.AccessToken = AccessToken; + toOptions.AccessTokenCommand = AccessTokenCommand; + toOptions.AccessTokenCommandArguments = AccessTokenCommandArguments; + toOptions.AccessTokenExpirySelector = AccessTokenExpirySelector; + toOptions.AccessTokenSelector = AccessTokenSelector; + toOptions.AllowInsecure = AllowInsecure; + toOptions.ApiEndPoint = ApiEndPoint; + toOptions.AuthStrategy = AuthStrategy; + toOptions.CertificationAuthorityCertificate = CertificationAuthorityCertificate; + toOptions.ClientCertificate = ClientCertificate; + toOptions.InitialAccessToken = InitialAccessToken; + toOptions.InitialTokenExpiryUtc = InitialTokenExpiryUtc; + toOptions.KubeNamespace = KubeNamespace; + toOptions.LoggerFactory = LoggerFactory; + toOptions.LogHeaders = LogHeaders; + toOptions.LogPayloads = LogPayloads; + toOptions.EnvironmentVariables = EnvironmentVariables; + toOptions.ModelTypeAssemblies.AddRange(ModelTypeAssemblies); + } + /// /// Ensure that the are valid. /// diff --git a/test/KubeClient.Extensions.WebSockets.Tests/TestBase.cs b/test/KubeClient.Extensions.WebSockets.Tests/TestBase.cs index 00fc9b2d..300d9b4a 100644 --- a/test/KubeClient.Extensions.WebSockets.Tests/TestBase.cs +++ b/test/KubeClient.Extensions.WebSockets.Tests/TestBase.cs @@ -50,7 +50,7 @@ protected TestBase(ITestOutputHelper testOutput) Assert.True(CurrentTest != null, "Cannot retrieve current test from ITestOutputHelper."); Disposal.Add( - Log.BeginScope("CurrentTest", CurrentTest.DisplayName) + Log.BeginScope("CurrentTest {CurrentTest}", CurrentTest.DisplayName) ); } From d7e51adabe65c460b1d30a593a95faf3f855e103 Mon Sep 17 00:00:00 2001 From: Adam Friedman Date: Tue, 16 Jan 2024 12:13:30 +1100 Subject: [PATCH 02/10] Add initial Azure Pipelines configuration --- azure-pipelines.yml | 87 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 azure-pipelines.yml diff --git a/azure-pipelines.yml b/azure-pipelines.yml new file mode 100644 index 00000000..6e23eefb --- /dev/null +++ b/azure-pipelines.yml @@ -0,0 +1,87 @@ +trigger: + branches: + include: + - master + + tags: + include: + - 'v*' + +pr: + branches: + include: + - master + +pool: + vmImage: ubuntu-latest + +variables: + buildConfiguration: 'Release' + +steps: +- task: gitversion/setup@0 + displayName: 'Install GitVersion' + + inputs: + versionSpec: 5.x + +- task: GitVersion/execute@0 + displayName: 'Determine build version' + name: GitVersion + +- task: DotNetCoreCLI@2 + displayName: 'Restore packages' + + inputs: + command: 'restore' + projects: './KubeClient.sln' + restoreArguments: '/p:VersionPrefix="$(GitVersion.MajorMinorPatch)" /p:VersionSuffix="$(GitVersion.PreReleaseTag)"' + +- task: DotNetCoreCLI@2 + displayName: 'Build solution' + + inputs: + command: 'build' + projects: './KubeClient.sln' + arguments: '--configuration "$(buildConfiguration)" /p:VersionPrefix="$(GitVersion.MajorMinorPatch)" /p:VersionSuffix="$(GitVersion.PreReleaseTag)"' + +- task: DotNetCoreCLI@2 + displayName: 'Run tests' + + inputs: + command: 'test' + projects: './KubeClient.sln' + arguments: '--configuration "$(buildConfiguration)" /p:VersionPrefix="$(GitVersion.MajorMinorPatch)" /p:VersionSuffix="$(GitVersion.PreReleaseTag)"' + +- task: DotNetCoreCLI@2 + displayName: 'Create packages' + + inputs: + command: 'pack' + projects: './KubeClient.sln' + arguments: '--configuration "$(buildConfiguration)" -o "$(Build.ArtifactStagingDirectory)" /p:VersionPrefix="$(GitVersion.MajorMinorPatch)" /p:VersionSuffix="$(GitVersion.PreReleaseTag)"' + modifyOutputPath: false + +- task: PublishBuildArtifacts@1 + displayName: 'Publish packages as artifact' + + inputs: + PathtoPublish: '$(Build.ArtifactStagingDirectory)/*.nupkg' + ArtifactName: 'packages' + publishLocation: 'Container' + +- task: GitHubRelease@1 + displayName: 'Create GitHub release from tag' + + condition: contains(variables['Build.SourceBranch'], 'refs/tags/v') + + inputs: + gitHubConnection: 'github.com_tintoy' + repositoryName: '$(Build.Repository.Name)' + action: 'create' + target: '$(Build.SourceVersion)' + tagSource: 'gitTag' + tagPattern: '^v\d+\.\d+.\d+(-[A-Za-z0-9%\.]+)?$' + addChangeLog: true + assets: '$(Build.ArtifactStagingDirectory)/*.nupkg' + assetUploadMode: replace From 6f51dd0347e33395a188e3b5fdab64a075cd7224 Mon Sep 17 00:00:00 2001 From: Adam Friedman Date: Tue, 16 Jan 2024 12:50:24 +1100 Subject: [PATCH 03/10] Configure branches for CI --- azure-pipelines.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 6e23eefb..4a59f375 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -2,6 +2,8 @@ trigger: branches: include: - master + - develop + - release/* tags: include: From ea1117bdaacbffd2e651aaa80b9e870887f48b9e Mon Sep 17 00:00:00 2001 From: Adam Friedman Date: Tue, 16 Jan 2024 12:54:56 +1100 Subject: [PATCH 04/10] Update GitHub connection name --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 4a59f375..01e1652f 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -78,7 +78,7 @@ steps: condition: contains(variables['Build.SourceBranch'], 'refs/tags/v') inputs: - gitHubConnection: 'github.com_tintoy' + gitHubConnection: 'tintoy' repositoryName: '$(Build.Repository.Name)' action: 'create' target: '$(Build.SourceVersion)' From f4b6160db466c18e95fa0c4ae7d7761b3f7e6cd9 Mon Sep 17 00:00:00 2001 From: Adam Friedman Date: Tue, 16 Jan 2024 13:13:21 +1100 Subject: [PATCH 05/10] Update GitVersion configuration to work with newer version of tooling --- GitVersion.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/GitVersion.yml b/GitVersion.yml index 5a482697..2a21b26b 100644 --- a/GitVersion.yml +++ b/GitVersion.yml @@ -15,6 +15,8 @@ branches: track-merge-target: false tracks-release-branches: false is-release-branch: false + is-mainline: true + source-branches: [ 'develop' ] develop: regex: develop @@ -25,8 +27,7 @@ branches: track-merge-target: true tracks-release-branches: true is-release-branch: false - is-source-branch-for: - - master + source-branches: [ 'feature' ] feature: mode: ContinuousDeployment @@ -35,8 +36,6 @@ branches: increment: Minor prevent-increment-of-merged-branch-version: false track-merge-target: false - is-source-branch-for: - - develop pull-request: regex: (pull|pull\-request|pr)[/-] From 0faf103ae75dd9d5be2f69661956aadb816cdc53 Mon Sep 17 00:00:00 2001 From: Adam Friedman Date: Tue, 16 Jan 2024 13:34:43 +1100 Subject: [PATCH 06/10] Attempt to use a wildcard for test projects when running "dotnet test" in CI --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 01e1652f..7c2e30b0 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -44,7 +44,7 @@ steps: inputs: command: 'build' - projects: './KubeClient.sln' + projects: './test/*.Tests/*.Tests.csproj' arguments: '--configuration "$(buildConfiguration)" /p:VersionPrefix="$(GitVersion.MajorMinorPatch)" /p:VersionSuffix="$(GitVersion.PreReleaseTag)"' - task: DotNetCoreCLI@2 From 4666c6743e8eabe293062d057bb1abf2e232dd5f Mon Sep 17 00:00:00 2001 From: Adam Friedman Date: Tue, 16 Jan 2024 13:41:46 +1100 Subject: [PATCH 07/10] Use wildcard for "dotnet test", not "dotnet build: --- azure-pipelines.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 7c2e30b0..3dd05650 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -36,7 +36,7 @@ steps: inputs: command: 'restore' - projects: './KubeClient.sln' + projects: '$(Build.SourcesDirectory)/KubeClient.sln' restoreArguments: '/p:VersionPrefix="$(GitVersion.MajorMinorPatch)" /p:VersionSuffix="$(GitVersion.PreReleaseTag)"' - task: DotNetCoreCLI@2 @@ -44,7 +44,7 @@ steps: inputs: command: 'build' - projects: './test/*.Tests/*.Tests.csproj' + projects: '$(Build.SourcesDirectory)/KubeClient.sln' arguments: '--configuration "$(buildConfiguration)" /p:VersionPrefix="$(GitVersion.MajorMinorPatch)" /p:VersionSuffix="$(GitVersion.PreReleaseTag)"' - task: DotNetCoreCLI@2 @@ -52,7 +52,7 @@ steps: inputs: command: 'test' - projects: './KubeClient.sln' + projects: '$(Build.SourcesDirectory)/test/KubeClient.*.Tests/*.csproj' arguments: '--configuration "$(buildConfiguration)" /p:VersionPrefix="$(GitVersion.MajorMinorPatch)" /p:VersionSuffix="$(GitVersion.PreReleaseTag)"' - task: DotNetCoreCLI@2 @@ -60,7 +60,7 @@ steps: inputs: command: 'pack' - projects: './KubeClient.sln' + projects: '$(Build.SourcesDirectory)/KubeClient.sln' arguments: '--configuration "$(buildConfiguration)" -o "$(Build.ArtifactStagingDirectory)" /p:VersionPrefix="$(GitVersion.MajorMinorPatch)" /p:VersionSuffix="$(GitVersion.PreReleaseTag)"' modifyOutputPath: false From 05f3bf2996a3bf531d99001833f6c06e1cfbfb3d Mon Sep 17 00:00:00 2001 From: Adam Friedman Date: Tue, 16 Jan 2024 13:54:32 +1100 Subject: [PATCH 08/10] Publish packages folder as artifact --- azure-pipelines.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 3dd05650..27cc54f3 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -61,14 +61,14 @@ steps: inputs: command: 'pack' projects: '$(Build.SourcesDirectory)/KubeClient.sln' - arguments: '--configuration "$(buildConfiguration)" -o "$(Build.ArtifactStagingDirectory)" /p:VersionPrefix="$(GitVersion.MajorMinorPatch)" /p:VersionSuffix="$(GitVersion.PreReleaseTag)"' + arguments: '--configuration "$(buildConfiguration)" -o "$(Build.ArtifactStagingDirectory)/packages" /p:VersionPrefix="$(GitVersion.MajorMinorPatch)" /p:VersionSuffix="$(GitVersion.PreReleaseTag)"' modifyOutputPath: false - task: PublishBuildArtifacts@1 displayName: 'Publish packages as artifact' inputs: - PathtoPublish: '$(Build.ArtifactStagingDirectory)/*.nupkg' + PathtoPublish: '$(Build.ArtifactStagingDirectory)/packages' ArtifactName: 'packages' publishLocation: 'Container' @@ -85,5 +85,5 @@ steps: tagSource: 'gitTag' tagPattern: '^v\d+\.\d+.\d+(-[A-Za-z0-9%\.]+)?$' addChangeLog: true - assets: '$(Build.ArtifactStagingDirectory)/*.nupkg' + assets: '$(Build.ArtifactStagingDirectory)/packages/*.nupkg' assetUploadMode: replace From 824d5e1885c0d7fa50002fb3775b4283b06c2611 Mon Sep 17 00:00:00 2001 From: Adam Friedman Date: Tue, 16 Jan 2024 14:00:22 +1100 Subject: [PATCH 09/10] Azure DevOps task overrides the bloody output directory --- azure-pipelines.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 27cc54f3..24c220a8 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -61,8 +61,8 @@ steps: inputs: command: 'pack' projects: '$(Build.SourcesDirectory)/KubeClient.sln' - arguments: '--configuration "$(buildConfiguration)" -o "$(Build.ArtifactStagingDirectory)/packages" /p:VersionPrefix="$(GitVersion.MajorMinorPatch)" /p:VersionSuffix="$(GitVersion.PreReleaseTag)"' - modifyOutputPath: false + arguments: '--configuration "$(buildConfiguration)" /p:VersionPrefix="$(GitVersion.MajorMinorPatch)" /p:VersionSuffix="$(GitVersion.PreReleaseTag)"' + outputDir: '$(Build.ArtifactStagingDirectory)/packages' - task: PublishBuildArtifacts@1 displayName: 'Publish packages as artifact' From 486ed3bbdc0afd09b13823079d0ceb0ee334323a Mon Sep 17 00:00:00 2001 From: Adam Friedman Date: Tue, 16 Jan 2024 14:14:26 +1100 Subject: [PATCH 10/10] Use environment variable to propagate package version info --- azure-pipelines.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 24c220a8..68635501 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -31,6 +31,13 @@ steps: displayName: 'Determine build version' name: GitVersion +- script: | + BUILD_SEMVER="$(GitVersion.FullSemVer)" + + echo "##vso[task.setvariable variable=BUILD_SEMVER]$BUILD_SEMVER" + echo "BUILD_SEMVER='$BUILD_SEMVER'" + displayName: Set environment variables from build version + - task: DotNetCoreCLI@2 displayName: 'Restore packages' @@ -61,8 +68,11 @@ steps: inputs: command: 'pack' projects: '$(Build.SourcesDirectory)/KubeClient.sln' - arguments: '--configuration "$(buildConfiguration)" /p:VersionPrefix="$(GitVersion.MajorMinorPatch)" /p:VersionSuffix="$(GitVersion.PreReleaseTag)"' + + arguments: '--configuration "$(buildConfiguration)"' outputDir: '$(Build.ArtifactStagingDirectory)/packages' + versioningScheme: byEnvVar + versionEnvVar: BUILD_SEMVER - task: PublishBuildArtifacts@1 displayName: 'Publish packages as artifact'