Skip to content

Commit

Permalink
Plumbing for DSCv3 processor and some initial implementation bits
Browse files Browse the repository at this point in the history
  • Loading branch information
JohnMcPMS committed Feb 12, 2025
1 parent a43fa8b commit 008efd2
Show file tree
Hide file tree
Showing 22 changed files with 754 additions and 68 deletions.
3 changes: 2 additions & 1 deletion src/AppInstallerCLICore/Commands/ConfigureCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,9 @@ namespace AppInstaller::CLI
context <<
VerifyIsFullPackage <<
VerifyFileOrUri(Execution::Args::Type::ConfigurationFile) <<
CreateConfigurationProcessor <<
CreateConfigurationProcessorWithoutFactory <<
OpenConfigurationSet <<
CreateConfigurationProcessor <<
ShowConfigurationSet <<
ShowConfigurationSetConflicts <<
ConfirmConfigurationProcessing(true) <<
Expand Down
3 changes: 2 additions & 1 deletion src/AppInstallerCLICore/Commands/ConfigureShowCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ namespace AppInstaller::CLI
context <<
VerifyIsFullPackage <<
VerifyFileOrUri(Execution::Args::Type::ConfigurationFile) <<
CreateConfigurationProcessor <<
CreateConfigurationProcessorWithoutFactory <<
OpenConfigurationSet <<
CreateConfigurationProcessor <<
ShowConfigurationSet;
}

Expand Down
3 changes: 2 additions & 1 deletion src/AppInstallerCLICore/Commands/ConfigureTestCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ namespace AppInstaller::CLI
context <<
VerifyIsFullPackage <<
VerifyFileOrUri(Execution::Args::Type::ConfigurationFile) <<
CreateConfigurationProcessor <<
CreateConfigurationProcessorWithoutFactory <<
OpenConfigurationSet <<
CreateConfigurationProcessor <<
ShowConfigurationSet <<
ShowConfigurationSetConflicts <<
ConfirmConfigurationProcessing(false) <<
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,9 @@ namespace AppInstaller::CLI
context <<
VerifyIsFullPackage <<
VerifyFileOrUri(Execution::Args::Type::ConfigurationFile) <<
CreateConfigurationProcessor <<
CreateConfigurationProcessorWithoutFactory <<
OpenConfigurationSet <<
CreateConfigurationProcessor <<
ValidateConfigurationSetSemantics <<
ValidateConfigurationSetUnitProcessors <<
ValidateConfigurationSetUnitContents <<
Expand Down
19 changes: 13 additions & 6 deletions src/AppInstallerCLICore/ConfigurationDynamicRuntimeFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ namespace AppInstaller::CLI::ConfigurationRemoting
// In turn, any properties must only be set via the command line (or eventual UI requests to the user).
struct DynamicFactory : winrt::implements<DynamicFactory, IConfigurationSetProcessorFactory, SetProcessorFactory::IPwshConfigurationSetProcessorFactoryProperties, winrt::cloaked<WinRT::ILifetimeWatcher>>, WinRT::LifetimeWatcherBase
{
DynamicFactory();
DynamicFactory(ProcessorEngine processorEngine);

IConfigurationSetProcessor CreateSetProcessor(const ConfigurationSet& configurationSet);

Expand Down Expand Up @@ -105,6 +105,11 @@ namespace AppInstaller::CLI::ConfigurationRemoting
m_customLocation = value;
}

ProcessorEngine Engine() const
{
return m_processorEngine;
}

private:
IConfigurationSetProcessorFactory m_defaultRemoteFactory;
winrt::event<EventHandler<IDiagnosticInformation>> m_diagnostics;
Expand All @@ -113,6 +118,7 @@ namespace AppInstaller::CLI::ConfigurationRemoting
DiagnosticLevel m_minimumLevel = DiagnosticLevel::Informational;
SetProcessorFactory::PwshConfigurationProcessorLocation m_location = SetProcessorFactory::PwshConfigurationProcessorLocation::Default;
winrt::hstring m_customLocation;
ProcessorEngine m_processorEngine;
};

struct DynamicProcessorInfo
Expand Down Expand Up @@ -337,7 +343,7 @@ namespace AppInstaller::CLI::ConfigurationRemoting
useRunAs = !m_enableTestMode;
#endif

factory = CreateOutOfProcessFactory(useRunAs, SerializeSetProperties(), SerializeHighIntegrityLevelSet());
factory = CreateOutOfProcessFactory(m_dynamicFactory->Engine(), useRunAs, SerializeSetProperties(), SerializeHighIntegrityLevelSet());
}
else
{
Expand Down Expand Up @@ -373,9 +379,10 @@ namespace AppInstaller::CLI::ConfigurationRemoting
#endif
};

DynamicFactory::DynamicFactory()
DynamicFactory::DynamicFactory(ProcessorEngine processorEngine)
{
m_defaultRemoteFactory = CreateOutOfProcessFactory();
m_processorEngine = processorEngine;
m_defaultRemoteFactory = CreateOutOfProcessFactory(processorEngine);

if (m_defaultRemoteFactory)
{
Expand Down Expand Up @@ -437,8 +444,8 @@ namespace AppInstaller::CLI::ConfigurationRemoting
catch (...) {}
}

winrt::Microsoft::Management::Configuration::IConfigurationSetProcessorFactory CreateDynamicRuntimeFactory()
winrt::Microsoft::Management::Configuration::IConfigurationSetProcessorFactory CreateDynamicRuntimeFactory(ProcessorEngine processorEngine)
{
return winrt::make<anonymous::DynamicFactory>();
return winrt::make<anonymous::DynamicFactory>(processorEngine);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

using namespace winrt::Windows::Foundation;
using namespace winrt::Microsoft::Management::Configuration;
using namespace std::string_view_literals;

namespace AppInstaller::CLI::ConfigurationRemoting
{
Expand All @@ -22,6 +23,19 @@ namespace AppInstaller::CLI::ConfigurationRemoting
// The string used to divide the arguments sent to the remote server
constexpr std::wstring_view s_ArgumentsDivider = L"\n~~~~~~\n";

std::wstring_view ToString(ProcessorEngine value)
{
switch (value)
{
case ProcessorEngine::PowerShell:
return L"pwsh"sv;
case ProcessorEngine::DSCv3:
return L"dscv3"sv;
default:
THROW_HR(E_UNEXPECTED);
}
}

// A helper with a convenient function that we use to receive the remote factory object.
struct RemoteFactoryCallback : winrt::implements<RemoteFactoryCallback, IConfigurationStatics>
{
Expand Down Expand Up @@ -121,7 +135,7 @@ namespace AppInstaller::CLI::ConfigurationRemoting
// Represents a remote factory object that was created from a specific process.
struct RemoteFactory : winrt::implements<RemoteFactory, IConfigurationSetProcessorFactory, SetProcessorFactory::IPwshConfigurationSetProcessorFactoryProperties, winrt::cloaked<WinRT::ILifetimeWatcher>>, WinRT::LifetimeWatcherBase
{
RemoteFactory(bool useRunAs, const std::string& properties, const std::string& restrictions)
RemoteFactory(ProcessorEngine processorEngine, bool useRunAs, const std::string& properties, const std::string& restrictions)
{
AICLI_LOG(Config, Verbose, << "Launching process for configuration processing...");

Expand Down Expand Up @@ -162,7 +176,7 @@ namespace AppInstaller::CLI::ConfigurationRemoting
// ~~~~~~
// YAML configuration set definition
std::wostringstream argumentsStream;
argumentsStream << s_RemoteServerFileName << L' ' << marshalledCallback << L' ' << completionEventName << L' ' << GetCurrentProcessId();
argumentsStream << s_RemoteServerFileName << L' ' << marshalledCallback << L' ' << completionEventName << L' ' << GetCurrentProcessId() << L' ' << ToString(processorEngine);

if (!properties.empty() && !restrictions.empty())
{
Expand Down Expand Up @@ -298,9 +312,33 @@ namespace AppInstaller::CLI::ConfigurationRemoting
};
}

IConfigurationSetProcessorFactory CreateOutOfProcessFactory(bool useRunAs, const std::string& properties, const std::string& restrictions)
IConfigurationSetProcessorFactory CreateOutOfProcessFactory(ProcessorEngine processorEngine, bool useRunAs, const std::string& properties, const std::string& restrictions)
{
return winrt::make<RemoteFactory>(processorEngine, useRunAs, properties, restrictions);
}

ProcessorEngine DetermineProcessorEngine(ConfigurationSet set)
{
return winrt::make<RemoteFactory>(useRunAs, properties, restrictions);
Utility::Version schemaVersion{ Utility::ConvertToUTF8(set.SchemaVersion()) };

if (schemaVersion <= Utility::Version{ "0.3" })
{
// Default to PowerShell
ProcessorEngine result = ProcessorEngine::PowerShell;

winrt::hstring processorIdentifier = set.Environment().ProcessorIdentifier();
if (processorIdentifier == L"dscv3")
{
result = ProcessorEngine::DSCv3;
}

return result;
}
else
{
// Intentionally fail out here until a decision is made.
THROW_HR(E_NOTIMPL);
}
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/AppInstallerCLICore/ConfigureExportCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,9 @@ namespace AppInstaller::CLI
context <<
VerifyIsFullPackage <<
SearchSourceForPackageExport <<
CreateConfigurationProcessor <<
CreateConfigurationProcessorWithoutFactory <<
CreateOrOpenConfigurationSet <<
CreateConfigurationProcessor <<
PopulateConfigurationSetForExport <<
WriteConfigFile;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,23 @@

namespace AppInstaller::CLI::ConfigurationRemoting
{
// The processor engine being used by the factory.
enum class ProcessorEngine
{
// Uses PowerShell DSC v2.
PowerShell,
// Uses DSC v3.
DSCv3,
};

// Determines the appropriate processor engine to use for the given configuration set.
ProcessorEngine DetermineProcessorEngine(winrt::Microsoft::Management::Configuration::ConfigurationSet set);

// Creates a factory in another process
winrt::Microsoft::Management::Configuration::IConfigurationSetProcessorFactory CreateOutOfProcessFactory(bool useRunAs = false, const std::string& properties = {}, const std::string& restrictions = {});
winrt::Microsoft::Management::Configuration::IConfigurationSetProcessorFactory CreateOutOfProcessFactory(ProcessorEngine processorEngine, bool useRunAs = false, const std::string& properties = {}, const std::string& restrictions = {});

// Creates a factory that can route configurations to the appropriate internal factory.
winrt::Microsoft::Management::Configuration::IConfigurationSetProcessorFactory CreateDynamicRuntimeFactory();
winrt::Microsoft::Management::Configuration::IConfigurationSetProcessorFactory CreateDynamicRuntimeFactory(ProcessorEngine processorEngine);
}

// Export for use by the out of process factory server to report its initialization.
Expand Down
29 changes: 23 additions & 6 deletions src/AppInstallerCLICore/Workflows/ConfigurationFlow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,19 +104,29 @@ namespace AppInstaller::CLI::Workflow
}
#endif

// The configuration set must have already been opened to create the proper factory.
THROW_WIN32_IF(ERROR_INVALID_STATE, !context.Contains(Data::ConfigurationContext));
const auto& configurationContext = context.Get<Data::ConfigurationContext>();
THROW_WIN32_IF(ERROR_INVALID_STATE, !configurationContext.Set());

IConfigurationSetProcessorFactory factory;
ConfigurationRemoting::ProcessorEngine processorEngine = ConfigurationRemoting::DetermineProcessorEngine(configurationContext.Set());

// Since downgrading is not currently supported, only use dynamic if running limited.
if (Runtime::IsRunningWithLimitedToken())
{
factory = ConfigurationRemoting::CreateDynamicRuntimeFactory();
factory = ConfigurationRemoting::CreateDynamicRuntimeFactory(processorEngine);
}
else
{
factory = ConfigurationRemoting::CreateOutOfProcessFactory();
factory = ConfigurationRemoting::CreateOutOfProcessFactory(processorEngine);
}

if (processorEngine == ConfigurationRemoting::ProcessorEngine::PowerShell)
{
Configuration::SetModulePath(context, factory);
}

Configuration::SetModulePath(context, factory);
return factory;
}

Expand All @@ -136,10 +146,17 @@ namespace AppInstaller::CLI::Workflow
context.GetThreadGlobals().GetDiagnosticLogger().Write(Logging::Channel::Config, anon::ConvertLevel(diagnostics.Level()), Utility::ConvertToUTF8(diagnostics.Message()));
});

ConfigurationContext configurationContext;
configurationContext.Processor(std::move(processor));
if (context.Contains(Data::ConfigurationContext))
{
context.Get<Data::ConfigurationContext>().Processor(std::move(processor));
}
else
{
ConfigurationContext configurationContext;
configurationContext.Processor(std::move(processor));

context.Add<Data::ConfigurationContext>(std::move(configurationContext));
context.Add<Data::ConfigurationContext>(std::move(configurationContext));
}
}

winrt::hstring GetValueSetString(const ValueSet& valueSet, std::wstring_view value)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ namespace AppInstaller::Configuration
{
constexpr std::wstring_view PowerShellHandlerIdentifier = L"pwsh";
constexpr std::wstring_view DynamicRuntimeHandlerIdentifier = L"{73fea39f-6f4a-41c9-ba94-6fd14d633e40}";
constexpr std::wstring_view DSCv3HandlerIdentifier = L"{dbb2ac6d-1b58-4b05-9c50-b463cc434771}";
constexpr std::wstring_view DSCv3DynamicRuntimeHandlerIdentifier = L"{5f83e564-ca26-41ca-89db-36f5f0517ffd}";
}
Loading

0 comments on commit 008efd2

Please sign in to comment.