Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/actions/spelling/allow.txt
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ MAKEINTRESOURCE
makemsix
MANIFESTSCHEMA
MANIFESTVERSION
Memberwise
meme
metadatas
Minimatch
Expand Down
1 change: 1 addition & 0 deletions .github/actions/spelling/expect.txt
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ ICONDIRENTRY
ICONIMAGE
icu
idl
IDSC
idx
IFACEMETHODIMP
iid
Expand Down
6 changes: 6 additions & 0 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,12 @@ jobs:
displayName: Clean up Sysinternals PsTools
condition: succeededOrFailed()

# Install DSC v3 preview until the DSC v3 processor handles that on its own
- powershell: |
Install-WinGetPackage -Id Microsoft.DSC.Preview -Source winget
displayName: Install DSC v3
condition: succeededOrFailed()

- task: PowerShell@2
displayName: Run Unit Tests Packaged
inputs:
Expand Down
17 changes: 3 additions & 14 deletions doc/Settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -355,25 +355,14 @@ You can enable the feature as shown below.
},
```

### configuration03
### dsc3

This feature enables the configuration schema 0.3.
This feature enables support for DSC v3 integration.
You can enable the feature as shown below.

```json
"experimentalFeatures": {
"configuration03": true
},
```

### configureSelfElevate

This feature enables configure commands to request elevation as needed.
Currently, this means that properly attributed configuration units (and only those) will be run through an elevated process while the rest are run from the current context.

```json
"experimentalFeatures": {
"configureSelfElevate": true
"dsc3": true
},
```

Expand Down
2 changes: 2 additions & 0 deletions src/AppInstallerCLICore/Argument.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,8 @@ namespace AppInstaller::CLI
return { type, "disable"_liv, ArgTypeCategory::None, ArgTypeExclusiveSet::StubType };
case Execution::Args::Type::ConfigurationModulePath:
return { type, "module-path"_liv };
case Execution::Args::Type::ConfigurationProcessorPath:
return { type, "processor-path"_liv };
case Execution::Args::Type::ConfigurationExportPackageId:
return { type, "package-id"_liv };
case Execution::Args::Type::ConfigurationExportModule:
Expand Down
4 changes: 3 additions & 1 deletion src/AppInstallerCLICore/Commands/ConfigureCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ namespace AppInstaller::CLI
return {
Argument{ Execution::Args::Type::ConfigurationFile, Resource::String::ConfigurationFileArgumentDescription, ArgumentType::Positional },
Argument{ Execution::Args::Type::ConfigurationModulePath, Resource::String::ConfigurationModulePath, ArgumentType::Positional },
Argument{ Execution::Args::Type::ConfigurationProcessorPath, Resource::String::ConfigurationProcessorPath, ArgumentType::Standard, Argument::Visibility::Help },
Argument{ Execution::Args::Type::ConfigurationHistoryItem, Resource::String::ConfigurationHistoryItemArgumentDescription, ArgumentType::Standard, Argument::Visibility::Help },
Argument{ Execution::Args::Type::ConfigurationAcceptWarning, Resource::String::ConfigurationAcceptWarningArgumentDescription, ArgumentType::Flag },
Argument{ Execution::Args::Type::ConfigurationSuppressPrologue, Resource::String::ConfigurationSuppressPrologueArgumentDescription, ArgumentType::Flag, Argument::Visibility::Help },
Expand Down Expand Up @@ -77,8 +78,9 @@ namespace AppInstaller::CLI
context <<
VerifyIsFullPackage <<
VerifyFileOrUri(Execution::Args::Type::ConfigurationFile) <<
CreateConfigurationProcessor <<
CreateConfigurationProcessorWithoutFactory <<
OpenConfigurationSet <<
CreateConfigurationProcessor <<
ShowConfigurationSet <<
ShowConfigurationSetConflicts <<
ConfirmConfigurationProcessing(true) <<
Expand Down
4 changes: 3 additions & 1 deletion src/AppInstallerCLICore/Commands/ConfigureShowCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ namespace AppInstaller::CLI
// Required for now, make exclusive when history implemented
Argument{ Execution::Args::Type::ConfigurationFile, Resource::String::ConfigurationFileArgumentDescription, ArgumentType::Positional },
Argument{ Execution::Args::Type::ConfigurationModulePath, Resource::String::ConfigurationModulePath, ArgumentType::Positional },
Argument{ Execution::Args::Type::ConfigurationProcessorPath, Resource::String::ConfigurationProcessorPath, ArgumentType::Standard, Argument::Visibility::Help },
Argument{ Execution::Args::Type::ConfigurationHistoryItem, Resource::String::ConfigurationHistoryItemArgumentDescription, ArgumentType::Standard, Argument::Visibility::Help },
};
}
Expand All @@ -39,8 +40,9 @@ namespace AppInstaller::CLI
context <<
VerifyIsFullPackage <<
VerifyFileOrUri(Execution::Args::Type::ConfigurationFile) <<
CreateConfigurationProcessor <<
CreateConfigurationProcessorWithoutFactory <<
OpenConfigurationSet <<
CreateConfigurationProcessor <<
ShowConfigurationSet;
}

Expand Down
4 changes: 3 additions & 1 deletion src/AppInstallerCLICore/Commands/ConfigureTestCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ namespace AppInstaller::CLI
return {
Argument{ Execution::Args::Type::ConfigurationFile, Resource::String::ConfigurationFileArgumentDescription, ArgumentType::Positional },
Argument{ Execution::Args::Type::ConfigurationModulePath, Resource::String::ConfigurationModulePath, ArgumentType::Positional },
Argument{ Execution::Args::Type::ConfigurationProcessorPath, Resource::String::ConfigurationProcessorPath, ArgumentType::Standard, Argument::Visibility::Help },
Argument{ Execution::Args::Type::ConfigurationHistoryItem, Resource::String::ConfigurationHistoryItemArgumentDescription, ArgumentType::Standard, Argument::Visibility::Help },
Argument{ Execution::Args::Type::ConfigurationAcceptWarning, Resource::String::ConfigurationAcceptWarningArgumentDescription, ArgumentType::Flag },
};
Expand All @@ -39,8 +40,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 @@ -14,6 +14,7 @@ namespace AppInstaller::CLI
return {
Argument{ Execution::Args::Type::ConfigurationFile, Resource::String::ConfigurationFileArgumentDescription, ArgumentType::Positional, true },
Argument{ Execution::Args::Type::ConfigurationModulePath, Resource::String::ConfigurationModulePath, ArgumentType::Positional },
Argument{ Execution::Args::Type::ConfigurationProcessorPath, Resource::String::ConfigurationProcessorPath, ArgumentType::Standard, Argument::Visibility::Help },
};
}

Expand All @@ -37,8 +38,9 @@ namespace AppInstaller::CLI
context <<
VerifyIsFullPackage <<
VerifyFileOrUri(Execution::Args::Type::ConfigurationFile) <<
CreateConfigurationProcessor <<
CreateConfigurationProcessorWithoutFactory <<
OpenConfigurationSet <<
CreateConfigurationProcessor <<
ValidateConfigurationSetSemantics <<
ValidateConfigurationSetUnitProcessors <<
ValidateConfigurationSetUnitContents <<
Expand Down
75 changes: 68 additions & 7 deletions src/AppInstallerCLICore/ConfigurationDynamicRuntimeFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "Public/ConfigurationSetProcessorFactoryRemoting.h"
#include <AppInstallerErrors.h>
#include <AppInstallerLanguageUtilities.h>
#include <AppInstallerLogging.h>
#include <AppInstallerStrings.h>
#include <winget/ILifetimeWatcher.h>
#include <winget/Security.h>
Expand Down Expand Up @@ -43,9 +44,9 @@ namespace AppInstaller::CLI::ConfigurationRemoting
// have this implementation leverage that one with an event handler for the packaged specifics.
// TODO: Add SetProcessorFactory::IPwshConfigurationSetProcessorFactoryProperties and pass values along to sets on creation
// 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
struct DynamicFactory : winrt::implements<DynamicFactory, IConfigurationSetProcessorFactory, SetProcessorFactory::IPwshConfigurationSetProcessorFactoryProperties, Collections::IMap<winrt::hstring, winrt::hstring>, winrt::cloaked<WinRT::ILifetimeWatcher>>, WinRT::LifetimeWatcherBase
{
DynamicFactory();
DynamicFactory(ProcessorEngine processorEngine);

IConfigurationSetProcessor CreateSetProcessor(const ConfigurationSet& configurationSet);

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

// Implement a subset of IMap to enable property bag semantics
uint32_t Size() { THROW_HR(E_NOTIMPL); }
void Clear() { THROW_HR(E_NOTIMPL); }
Collections::IMapView<winrt::hstring, winrt::hstring> GetView() { THROW_HR(E_NOTIMPL); }
bool HasKey(winrt::hstring) { THROW_HR(E_NOTIMPL); }
void Remove(winrt::hstring) { THROW_HR(E_NOTIMPL); }

bool Insert(winrt::hstring key, winrt::hstring value)
{
auto result = m_defaultRemoteFactory.as<Collections::IMap<winrt::hstring, winrt::hstring>>().Insert(key, value);
m_factoryMapValues[key] = value;
return result;
}

winrt::hstring Lookup(winrt::hstring key)
{
return m_defaultRemoteFactory.as<Collections::IMap<winrt::hstring, winrt::hstring>>().Lookup(key);
}

ProcessorEngine Engine() const
{
return m_processorEngine;
}

winrt::hstring GetFactoryMapValue(winrt::hstring key)
{
auto itr = m_factoryMapValues.find(key);
return itr != m_factoryMapValues.end() ? itr->second : winrt::hstring{};
}

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

struct DynamicProcessorInfo
Expand Down Expand Up @@ -277,6 +310,27 @@ namespace AppInstaller::CLI::ConfigurationRemoting
json["modulePath"] = locationString;
}

// Ensure that we always pass a path to the executable
if (m_dynamicFactory->Engine() == ProcessorEngine::DSCv3)
{
winrt::hstring dscExecutablePathPropertyName = ToHString(PropertyName::DscExecutablePath);
winrt::hstring dscExecutablePath = m_dynamicFactory->GetFactoryMapValue(dscExecutablePathPropertyName);

if (dscExecutablePath.empty())
{
dscExecutablePath = m_dynamicFactory->Lookup(ToHString(PropertyName::FoundDscExecutablePath));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the FoundDscExecutablePath always exist?

}

if (dscExecutablePath.empty())
{
// This is backstop to prevent a case where dsc.exe not found.
AICLI_LOG(Config, Error, << "Could not find dsc.exe, it must be provided by the user.");
THROW_WIN32(ERROR_FILE_NOT_FOUND);
}

json["processorPath"] = Utility::ConvertToUTF8(dscExecutablePath);
}

Json::StreamWriterBuilder writerBuilder;
writerBuilder.settings_["indentation"] = "\t";
return Json::writeString(writerBuilder, json);
Expand Down Expand Up @@ -337,7 +391,7 @@ namespace AppInstaller::CLI::ConfigurationRemoting
useRunAs = !m_enableTestMode;
#endif

factory = CreateOutOfProcessFactory(useRunAs, SerializeSetProperties(), SerializeHighIntegrityLevelSet());
factory = CreateOutOfProcessFactory(m_dynamicFactory->Engine(), useRunAs, SerializeSetProperties(), SerializeHighIntegrityLevelSet());
}
else
{
Expand All @@ -346,6 +400,7 @@ namespace AppInstaller::CLI::ConfigurationRemoting

if (factory)
{
factory.MinimumLevel(m_dynamicFactory->MinimumLevel());
factoryDiagnosticsEventRevoker = factory.Diagnostics(winrt::auto_revoke,
[weak_this{ get_weak() }](const IInspectable&, const IDiagnosticInformation& information)
{
Expand Down Expand Up @@ -373,9 +428,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 @@ -413,6 +469,11 @@ namespace AppInstaller::CLI::ConfigurationRemoting
void DynamicFactory::MinimumLevel(DiagnosticLevel value)
{
m_minimumLevel = value;

if (m_defaultRemoteFactory)
{
m_defaultRemoteFactory.MinimumLevel(value);
}
}

HRESULT STDMETHODCALLTYPE DynamicFactory::SetLifetimeWatcher(IUnknown* watcher)
Expand All @@ -437,8 +498,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);
}
}
Loading
Loading