Skip to content

Commit

Permalink
Add IConfiguration interface microsoft#1838
Browse files Browse the repository at this point in the history
  • Loading branch information
BernieWhite committed Jun 25, 2024
1 parent db596be commit 406ecb3
Show file tree
Hide file tree
Showing 14 changed files with 231 additions and 109 deletions.
10 changes: 10 additions & 0 deletions docs/concepts/feature-flagging.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Feature flagging

!!! Abstract
Feature flags are a way to enable or disable functionality.
Rule and module authors can use feature flags to toggle functionality on or off.

## Using feature flags in emitters

When an emitter is executed `IEmitterContext` is passed into each call.
This context includes a `Configuration` property that exposes `IConfiguration`.
2 changes: 1 addition & 1 deletion src/PSRule.Types/Emitters/IEmitterContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public interface IEmitterContext
void Emit(ITargetObject value);

/// <summary>
///
/// Determine if a specified path should be queued for processing.
/// </summary>
bool ShouldQueue(string path);
}
4 changes: 0 additions & 4 deletions src/PSRule.Types/PSRule.Types.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,4 @@
</EmbeddedResource>
</ItemGroup>

<ItemGroup>
<Folder Include="Runtime\" />
</ItemGroup>

</Project>
63 changes: 63 additions & 0 deletions src/PSRule.Types/Runtime/IConfiguration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

namespace PSRule.Runtime;

/// <summary>
/// Access configuration values at runtime.
/// </summary>
public interface IConfiguration
{
/// <summary>
/// Try to the configuration item if it exists.
/// </summary>
/// <param name="configurationKey">The name of the configuration item.</param>
/// <param name="defaultValue">The default value to use if the configuration item does not exist.</param>
/// <returns>Returns the configuration item or the specified default value.</returns>
object? GetValueOrDefault(string configurationKey, object? defaultValue = default);

/// <summary>
/// Get the specified configuration item as a string if it exists.
/// </summary>
/// <param name="configurationKey">The name of the configuration item.</param>
/// <param name="defaultValue">The default value to use if the configuration item does not exist.</param>
/// <returns>Returns the configuration item or the specified default value.</returns>
string? GetStringOrDefault(string configurationKey, string? defaultValue = default);

/// <summary>
/// Get the specified configuration item as a boolean if it exists.
/// </summary>
/// <param name="configurationKey">The name of the configuration item.</param>
/// <param name="defaultValue">The default value to use if the configuration item does not exist.</param>
/// <returns>Returns the configuration item or the specified default value.</returns>
bool? GetBoolOrDefault(string configurationKey, bool? defaultValue = default);

/// <summary>
/// Get the specified configuration item as an integer if it exists.
/// </summary>
/// <param name="configurationKey">The name of the configuration item.</param>
/// <param name="defaultValue">The default value to use if the configuration item does not exist.</param>
/// <returns>Returns the configuration item or the specified default value.</returns>
int? GetIntegerOrDefault(string configurationKey, int? defaultValue = default);

/// <summary>
/// Get the specified configuration item as a string array.
/// </summary>
/// <param name="configurationKey">The name of the configuration item.</param>
/// <returns>
/// Returns an array of strings.
/// If the configuration key does not exist and empty array is returned.
/// If the configuration key is a string, an array with a single element is returned.
/// </returns>
string[] GetStringValues(string configurationKey);

/// <summary>
/// Check if specified configuration item is enabled.
/// </summary>
/// <remarks>
/// Use this method to check if a feature is enabled.
/// </remarks>
/// <param name="configurationKey">The name of the configuration item.</param>
/// <returns>Returns <c>true</c> when the configuration item exists and it set to <c>true</c>. Otherwise <c>false</c> is returned.</returns>
bool IsEnabled(string configurationKey);
}
5 changes: 3 additions & 2 deletions src/PSRule/Pipeline/Emitters/EmitterContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the MIT License.

using System.Collections.Concurrent;
using PSRule.Configuration;
using PSRule.Data;
using PSRule.Emitters;
using PSRule.Options;
Expand All @@ -19,8 +20,8 @@ internal sealed class EmitterContext : BaseEmitterContext
/// <summary>
/// Create an instance containing context for an <see cref="IEmitter"/>.
/// </summary>
internal EmitterContext(ConcurrentQueue<ITargetObject> queue, PathFilter inputFilter, InputFormat? inputFormat, string objectPath, bool? shouldEmitFile)
: base(inputFormat ?? InputFormat.None, objectPath, shouldEmitFile ?? false)
internal EmitterContext(ConcurrentQueue<ITargetObject> queue, PathFilter inputFilter, PSRuleOption option)
: base(option?.Input?.Format ?? InputFormat.None, option?.Input?.ObjectPath, option?.Input?.FileObjects ?? false)
{
_Queue = queue;
_InputFilter = inputFilter;
Expand Down
9 changes: 1 addition & 8 deletions src/PSRule/Pipeline/GetTargetPipelineBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,6 @@ protected override PipelineInputStream PrepareReader()
return PipelineReceiverActions.ConvertFromPowerShellData(sourceObject, next);
});
}
//else if (Option.Input.Format == InputFormat.Detect && _InputPath != null)
//{
// AddVisitTargetObjectAction((sourceObject, next) =>
// {
// return PipelineReceiverActions.DetectInputFormat(sourceObject, next);
// });
//}
return new PipelineInputStream(VisitTargetObject, _InputPath, GetInputObjectSourceFilter(), Option.Input.Format, Option.Input.ObjectPath, Option.Input.FileObjects);
return new PipelineInputStream(VisitTargetObject, _InputPath, GetInputObjectSourceFilter(), Option);
}
}
28 changes: 28 additions & 0 deletions src/PSRule/Pipeline/IInvokePipelineBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

namespace PSRule.Pipeline;

/// <summary>
/// A helper to build a pipeline for executing rules and conventions within a PSRule sandbox.
/// </summary>
public interface IInvokePipelineBuilder : IPipelineBuilder
{
/// <summary>
/// Configures paths that will be scanned for input.
/// </summary>
/// <param name="path">An array of relative or absolute path specs to be scanned. Directories will be recursively scanned for all files not excluded matching the file path spec.</param>
void InputPath(string[] path);

/// <summary>
/// Configures a variable that will receive all results in addition to the host context.
/// </summary>
/// <param name="variableName">The name of the variable to set.</param>
void ResultVariable(string variableName);

/// <summary>
/// Unblocks PowerShell sources from trusted publishers that originate from an Internet zone.
/// </summary>
/// <param name="publisher">The trusted publisher to unblock.</param>
void UnblockPublisher(string publisher);
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using PSRule.Configuration;
Expand All @@ -7,30 +7,6 @@

namespace PSRule.Pipeline;

/// <summary>
/// A helper to build a pipeline for executing rules and conventions within a PSRule sandbox.
/// </summary>
public interface IInvokePipelineBuilder : IPipelineBuilder
{
/// <summary>
/// Configures paths that will be scanned for input.
/// </summary>
/// <param name="path">An array of relative or absolute path specs to be scanned. Directories will be recursively scanned for all files not excluded matching the file path spec.</param>
void InputPath(string[] path);

/// <summary>
/// Configures a variable that will receive all results in addition to the host context.
/// </summary>
/// <param name="variableName">The name of the variable to set.</param>
void ResultVariable(string variableName);

/// <summary>
/// Unblocks PowerShell sources from trusted publishers that originate from an Internet zone.
/// </summary>
/// <param name="publisher">The trusted publisher to unblock.</param>
void UnblockPublisher(string publisher);
}

internal abstract class InvokePipelineBuilderBase : PipelineBuilderBase, IInvokePipelineBuilder
{
protected InputPathBuilder _InputPath;
Expand Down Expand Up @@ -190,22 +166,6 @@ protected override PipelineInputStream PrepareReader()
return PipelineReceiverActions.ConvertFromPowerShellData(sourceObject, next);
});
}
//else if (Option.Input.Format == InputFormat.Detect && _InputPath != null)
//{
// AddVisitTargetObjectAction((sourceObject, next) =>
// {
// return PipelineReceiverActions.DetectInputFormat(sourceObject, next);
// });
//}
return new PipelineInputStream(VisitTargetObject, _InputPath, GetInputObjectSourceFilter(), Option.Input.Format, Option.Input.ObjectPath, Option.Input.FileObjects);
return new PipelineInputStream(VisitTargetObject, _InputPath, GetInputObjectSourceFilter(), Option);
}
}

/// <summary>
/// A helper to construct the pipeline for Invoke-PSRule.
/// </summary>
internal sealed class InvokeRulePipelineBuilder : InvokePipelineBuilderBase
{
internal InvokeRulePipelineBuilder(Source[] source, IHostContext hostContext)
: base(source, hostContext) { }
}
13 changes: 13 additions & 0 deletions src/PSRule/Pipeline/InvokeRulePipelineBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

namespace PSRule.Pipeline;

/// <summary>
/// A helper to construct the pipeline for Invoke-PSRule.
/// </summary>
internal sealed class InvokeRulePipelineBuilder : InvokePipelineBuilderBase
{
internal InvokeRulePipelineBuilder(Source[] source, IHostContext hostContext)
: base(source, hostContext) { }
}
2 changes: 1 addition & 1 deletion src/PSRule/Pipeline/PipelineBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ protected string ResolveBaselineGroup(string name)

protected virtual PipelineInputStream PrepareReader()
{
return new PipelineInputStream(null, null, GetInputObjectSourceFilter(), Option.Input.Format, Option.Input.ObjectPath, Option.Input.FileObjects);
return new PipelineInputStream(null, null, GetInputObjectSourceFilter(), Option);
}

protected virtual PipelineWriter PrepareWriter()
Expand Down
6 changes: 3 additions & 3 deletions src/PSRule/Pipeline/PipelineInputStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

using System.Collections.Concurrent;
using System.Management.Automation;
using PSRule.Configuration;
using PSRule.Data;
using PSRule.Options;
using PSRule.Pipeline.Emitters;

namespace PSRule.Pipeline;
Expand All @@ -22,13 +22,13 @@ internal sealed class PipelineInputStream
private readonly ConcurrentQueue<ITargetObject> _Queue;
private readonly EmitterCollection _EmitterCollection;

public PipelineInputStream(VisitTargetObject input, InputPathBuilder inputPath, PathFilter inputFilter, InputFormat? inputFormat, string objectPath, bool? shouldEmitFile)
public PipelineInputStream(VisitTargetObject input, InputPathBuilder inputPath, PathFilter inputFilter, PSRuleOption option)
{
_Input = input;
_InputPath = inputPath;
_InputFilter = inputFilter;
_Queue = new ConcurrentQueue<ITargetObject>();
_EmitterCollection = new EmitterBuilder().Build(new EmitterContext(_Queue, inputFilter, inputFormat, objectPath, shouldEmitFile));
_EmitterCollection = new EmitterBuilder().Build(new EmitterContext(_Queue, inputFilter, option));
}

public int Count => _Queue.Count;
Expand Down
Loading

0 comments on commit 406ecb3

Please sign in to comment.