From c0219e6b92e52e50df769f4b7262d54796a6b72d Mon Sep 17 00:00:00 2001 From: Shyju Krishnankutty Date: Tue, 18 Jun 2024 17:25:54 -0700 Subject: [PATCH] Add `IsDisabled` property to worker description and skip if the value is True (#10231) * Adding support to skip a worker description when none of the profile conditions are met. * Adding release notes. * Changes to switch to "IsDisabled" property on worker description. * missed a file --- release_notes.md | 1 + .../ProcessManagement/WorkerDescription.cs | 5 +++ .../Profiles/WorkerDescriptionProfile.cs | 1 + .../Configuration/RpcWorkerConfigFactory.cs | 6 ++++ .../TestWorkers/worker1/1.bat | 0 .../TestWorkers/worker1/worker.config.json | 7 ++++ .../TestWorkers/worker2/2.bat | 0 .../TestWorkers/worker2/worker.config.json | 36 +++++++++++++++++++ .../WebJobs.Script.Tests.csproj | 1 + .../Rpc/RpcWorkerConfigFactoryTests.cs | 29 +++++++++++++++ 10 files changed, 86 insertions(+) create mode 100644 test/WebJobs.Script.Tests/TestWorkers/worker1/1.bat create mode 100644 test/WebJobs.Script.Tests/TestWorkers/worker1/worker.config.json create mode 100644 test/WebJobs.Script.Tests/TestWorkers/worker2/2.bat create mode 100644 test/WebJobs.Script.Tests/TestWorkers/worker2/worker.config.json diff --git a/release_notes.md b/release_notes.md index 05074c31b6..01dde680c4 100644 --- a/release_notes.md +++ b/release_notes.md @@ -15,4 +15,5 @@ - Fixed an issue leading to a race when invocation responses returned prior to HTTP requests being sent in proxied scenarios. - Language worker channels will not be started during placeholder mode if we are in-process (#10161) - Ordered invocations are now the default (#10201) +- Skip worker description if none of the profile conditions are met (#9932) - Fixed incorrect function count in the log message.(#10220) diff --git a/src/WebJobs.Script/Workers/ProcessManagement/WorkerDescription.cs b/src/WebJobs.Script/Workers/ProcessManagement/WorkerDescription.cs index 60d3b24239..87ce696414 100644 --- a/src/WebJobs.Script/Workers/ProcessManagement/WorkerDescription.cs +++ b/src/WebJobs.Script/Workers/ProcessManagement/WorkerDescription.cs @@ -45,6 +45,11 @@ public abstract class WorkerDescription /// public abstract bool UseStdErrorStreamForErrorsOnly { get; set; } + /// + /// Gets or sets a value indicating whether the worker description is disabled. + /// + public bool? IsDisabled { get; set; } + public abstract void ApplyDefaultsAndValidate(string workerDirectory, ILogger logger); internal void ThrowIfFileNotExists(string inputFile, string paramName) diff --git a/src/WebJobs.Script/Workers/Profiles/WorkerDescriptionProfile.cs b/src/WebJobs.Script/Workers/Profiles/WorkerDescriptionProfile.cs index fb01dadf5c..43e7acf905 100644 --- a/src/WebJobs.Script/Workers/Profiles/WorkerDescriptionProfile.cs +++ b/src/WebJobs.Script/Workers/Profiles/WorkerDescriptionProfile.cs @@ -81,6 +81,7 @@ public RpcWorkerDescription ApplyProfile(RpcWorkerDescription defaultWorkerDescr updatedDescription.Extensions = UseProfileOrDefault(ProfileDescription.Extensions, defaultWorkerDescription.Extensions) as List; updatedDescription.Language = UseProfileOrDefault(ProfileDescription.Language, defaultWorkerDescription.Language); updatedDescription.WorkerDirectory = UseProfileOrDefault(ProfileDescription.WorkerDirectory, defaultWorkerDescription.WorkerDirectory); + updatedDescription.IsDisabled = ProfileDescription.IsDisabled ?? defaultWorkerDescription.IsDisabled ?? false; return updatedDescription; } diff --git a/src/WebJobs.Script/Workers/Rpc/Configuration/RpcWorkerConfigFactory.cs b/src/WebJobs.Script/Workers/Rpc/Configuration/RpcWorkerConfigFactory.cs index 0760b6ade8..dbfc1e8be8 100644 --- a/src/WebJobs.Script/Workers/Rpc/Configuration/RpcWorkerConfigFactory.cs +++ b/src/WebJobs.Script/Workers/Rpc/Configuration/RpcWorkerConfigFactory.cs @@ -151,6 +151,12 @@ internal void AddProvider(string workerDir) // Validate workerDescription workerDescription.ApplyDefaultsAndValidate(Directory.GetCurrentDirectory(), _logger); + if (workerDescription.IsDisabled == true) + { + _logger.LogInformation("Skipping WorkerConfig for stack: {language} since it is disabled.", workerDescription.Language); + return; + } + if (ShouldAddWorkerConfig(workerDescription.Language)) { workerDescription.FormatWorkerPathIfNeeded(_systemRuntimeInformation, _environment, _logger); diff --git a/test/WebJobs.Script.Tests/TestWorkers/worker1/1.bat b/test/WebJobs.Script.Tests/TestWorkers/worker1/1.bat new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/WebJobs.Script.Tests/TestWorkers/worker1/worker.config.json b/test/WebJobs.Script.Tests/TestWorkers/worker1/worker.config.json new file mode 100644 index 0000000000..3e1dd5218c --- /dev/null +++ b/test/WebJobs.Script.Tests/TestWorkers/worker1/worker.config.json @@ -0,0 +1,7 @@ +{ + "description": { + "language": "foo", + "defaultExecutablePath": "%FUNCTIONS_WORKER_DIRECTORY%/1.bat", + "defaultWorkerPath": "1.bat" + } +} \ No newline at end of file diff --git a/test/WebJobs.Script.Tests/TestWorkers/worker2/2.bat b/test/WebJobs.Script.Tests/TestWorkers/worker2/2.bat new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/WebJobs.Script.Tests/TestWorkers/worker2/worker.config.json b/test/WebJobs.Script.Tests/TestWorkers/worker2/worker.config.json new file mode 100644 index 0000000000..f6359decd5 --- /dev/null +++ b/test/WebJobs.Script.Tests/TestWorkers/worker2/worker.config.json @@ -0,0 +1,36 @@ +{ + "description": { + "language": "bar" + }, + "profiles": [ + { + "profileName": "SpecificConditionProfile", + "conditions": [ + { + "conditionType": "environment", + "conditionName": "NON_EXISTING_ENV_VAR", + "conditionExpression": "(?i)true$" + } + ], + "description": { + "defaultExecutablePath": "%FUNCTIONS_WORKER_DIRECTORY%/2.bat", + "defaultWorkerPath": "2.bat" + } + }, + { + "profileName": "FallbackProfileToDisableWorker", + "conditions": [ + { + "conditionType": "environment", + "conditionName": "ENV_VAR_BAR", + "conditionExpression": "(?i)true$" + } + ], + "description": { + "defaultExecutablePath": "%FUNCTIONS_WORKER_DIRECTORY%/2.bat", + "defaultWorkerPath": "2.bat", + "isDisabled": true + } + } + ] +} \ No newline at end of file diff --git a/test/WebJobs.Script.Tests/WebJobs.Script.Tests.csproj b/test/WebJobs.Script.Tests/WebJobs.Script.Tests.csproj index 78bbdf9e62..e36642d6ed 100644 --- a/test/WebJobs.Script.Tests/WebJobs.Script.Tests.csproj +++ b/test/WebJobs.Script.Tests/WebJobs.Script.Tests.csproj @@ -78,6 +78,7 @@ + diff --git a/test/WebJobs.Script.Tests/Workers/Rpc/RpcWorkerConfigFactoryTests.cs b/test/WebJobs.Script.Tests/Workers/Rpc/RpcWorkerConfigFactoryTests.cs index 0f9a78df8e..98b8fa2c21 100644 --- a/test/WebJobs.Script.Tests/Workers/Rpc/RpcWorkerConfigFactoryTests.cs +++ b/test/WebJobs.Script.Tests/Workers/Rpc/RpcWorkerConfigFactoryTests.cs @@ -92,6 +92,35 @@ public void LanguageWorker_WorkersDir_NotSet() Assert.Equal(expectedWorkersDir, configFactory.WorkersDirPath); } + [Fact] + public void WorkerDescription_Skipped_When_Profile_Disables_Worker() + { + // The "TestWorkers" directory has 2 workers: "worker1" and "worker2". + // "worker2" has 2 profiles. The first profile will be skipped since the condition is not met. + // The second profile will be applied since the condition is met. The second profile updates + // the "IsDisabled" property to True and will cause the workerDescription to be skipped. + + var testPath = Path.GetDirectoryName(new Uri(typeof(RpcWorkerConfigFactoryTests).Assembly.Location).LocalPath); + var testWorkersDirectory = Path.Combine(testPath, "TestWorkers"); + var testEnvVariables = new Dictionary + { + { $"{RpcWorkerConstants.LanguageWorkersSectionName}:{WorkerConstants.WorkersDirectorySectionName}", testWorkersDirectory } + }; + var configBuilder = ScriptSettingsManager.CreateDefaultConfigurationBuilder() + .AddInMemoryCollection(testEnvVariables); + var config = configBuilder.Build(); + var scriptSettingsManager = new ScriptSettingsManager(config); + var testLogger = new TestLogger("test"); + _testEnvironment.SetEnvironmentVariable("ENV_VAR_BAR", "True"); + var configFactory = new RpcWorkerConfigFactory(config, testLogger, _testSysRuntimeInfo, _testEnvironment, new TestMetricsLogger(), _testWorkerProfileManager); + + var workerConfigs = configFactory.GetConfigs(); + + Assert.False(testLogger.GetLogMessages().Any(m => m.Exception != null), "There should not be an exception logged while executing GetConfigs method."); + Assert.Equal(1, workerConfigs.Count); + Assert.EndsWith("worker1\\1.bat", workerConfigs[0].Description.DefaultWorkerPath); + } + [Fact] public void JavaPath_FromEnvVars() {