ProcessorSettings.cs (8905B)
1 // ----------------------------------------------------------------------------- 2 // <copyright file="ProcessorSettings.cs" company="Microsoft Corporation"> 3 // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 4 // </copyright> 5 // ----------------------------------------------------------------------------- 6 7 namespace Microsoft.Management.Configuration.Processor.DSCv3.Helpers 8 { 9 using System; 10 using System.Collections.Generic; 11 using System.IO; 12 using System.Text; 13 using Microsoft.Management.Configuration.Processor.DSCv3.Model; 14 using Microsoft.Management.Configuration.Processor.Helpers; 15 16 /// <summary> 17 /// Contains settings for the DSC v3 processor components to share. 18 /// </summary> 19 internal class ProcessorSettings 20 { 21 private readonly object dscV3Lock = new (); 22 private readonly object defaultPathLock = new (); 23 24 private FindDscPackageStateMachine dscPackageStateMachine = new (); 25 private IDSCv3? dscV3 = null; 26 private string? defaultPath = null; 27 28 private Dictionary<string, ResourceDetails> resourceDetailsDictionary = new (); 29 30 /// <summary> 31 /// Gets or sets the path to the DSC v3 executable. 32 /// </summary> 33 public string? DscExecutablePath { get; set; } 34 35 /// <summary> 36 /// Gets the path to the DSC v3 executable. 37 /// </summary> 38 public string EffectiveDscExecutablePath 39 { 40 get 41 { 42 if (this.DscExecutablePath != null) 43 { 44 return this.DscExecutablePath; 45 } 46 47 lock (this.defaultPathLock) 48 { 49 if (this.defaultPath != null) 50 { 51 return this.defaultPath; 52 } 53 } 54 55 string? localDefaultPath = this.GetFoundDscExecutablePath(); 56 57 if (localDefaultPath == null) 58 { 59 throw new FileNotFoundException("Could not find DSC v3 executable path."); 60 } 61 62 lock (this.defaultPathLock) 63 { 64 if (this.defaultPath == null) 65 { 66 this.defaultPath = localDefaultPath; 67 } 68 69 return this.defaultPath; 70 } 71 } 72 } 73 74 /// <summary> 75 /// Gets an object for interacting with the DSC executable at EffectiveDscExecutablePath. 76 /// </summary> 77 [System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1623:Property summary documentation should match accessors", Justification = "Set is only provided for tests.")] 78 public IDSCv3 DSCv3 79 { 80 get 81 { 82 lock (this.dscV3Lock) 83 { 84 if (this.dscV3 == null) 85 { 86 this.dscV3 = IDSCv3.Create(this); 87 } 88 89 return this.dscV3; 90 } 91 } 92 93 #if !AICLI_DISABLE_TEST_HOOKS 94 set 95 { 96 lock (this.dscV3Lock) 97 { 98 this.dscV3 = value; 99 } 100 } 101 #endif 102 } 103 104 /// <summary> 105 /// Gets or sets the diagnostics sink to use. 106 /// </summary> 107 public IDiagnosticsSink? DiagnosticsSink { get; set; } = null; 108 109 /// <summary> 110 /// Gets or sets a value indicating whether the processor should produce more verbose output. 111 /// </summary> 112 public bool DiagnosticTraceEnabled { get; set; } = false; 113 114 /// <summary> 115 /// Find the DSC v3 executable. 116 /// </summary> 117 /// <returns>The full path to the dsc.exe executable, or null if not found.</returns> 118 public string? GetFoundDscExecutablePath() 119 { 120 return this.dscPackageStateMachine.DscExecutablePath; 121 } 122 123 /// <summary> 124 /// Invokes a step in the DSC search state machine. 125 /// </summary> 126 /// <returns>The transition to take in the state machine.</returns> 127 public FindDscPackageStateMachine.Transition PumpFindDscStateMachine() 128 { 129 return this.dscPackageStateMachine.DetermineNextTransition(); 130 } 131 132 /// <summary> 133 /// Create a deep copy of this settings object. 134 /// </summary> 135 /// <returns>A deep copy of this object.</returns> 136 public ProcessorSettings Clone() 137 { 138 ProcessorSettings result = new ProcessorSettings(); 139 140 result.resourceDetailsDictionary = this.resourceDetailsDictionary; 141 result.DiagnosticsSink = this.DiagnosticsSink; 142 result.DscExecutablePath = this.DscExecutablePath; 143 result.DiagnosticTraceEnabled = this.DiagnosticTraceEnabled; 144 #if !AICLI_DISABLE_TEST_HOOKS 145 result.dscV3 = this.DSCv3; 146 #endif 147 148 return result; 149 } 150 151 /// <summary> 152 /// Gets a string representation of this object. 153 /// </summary> 154 /// <returns>A string representation of this object.</returns> 155 public override string ToString() 156 { 157 StringBuilder sb = new StringBuilder(); 158 159 sb.Append("EffectiveDscExecutablePath: "); 160 sb.AppendLine(this.EffectiveDscExecutablePath); 161 162 sb.Append("DiagnosticTraceLevel: "); 163 sb.Append(this.DiagnosticTraceEnabled); 164 165 return sb.ToString(); 166 } 167 168 /// <summary> 169 /// Gets the ResourceDetails for a configuration unit. 170 /// </summary> 171 /// <param name="configurationUnitInternal">The configuration unit to find details for.</param> 172 /// <param name="detailFlags">The level of detail to get.</param> 173 /// <returns>The ResourceDetails for the unit, or null if not found.</returns> 174 public ResourceDetails? GetResourceDetails(ConfigurationUnitInternal configurationUnitInternal, ConfigurationUnitDetailFlags detailFlags) 175 { 176 ResourceDetails? result = null; 177 bool inDictionary = false; 178 179 lock (this.resourceDetailsDictionary) 180 { 181 inDictionary = this.resourceDetailsDictionary.TryGetValue(configurationUnitInternal.QualifiedName, out result); 182 } 183 184 if (result == null) 185 { 186 result = new ResourceDetails(configurationUnitInternal.QualifiedName); 187 } 188 189 result.EnsureDetails(this, detailFlags); 190 191 if (result.Exists) 192 { 193 if (!inDictionary) 194 { 195 lock (this.resourceDetailsDictionary) 196 { 197 this.resourceDetailsDictionary.Add(configurationUnitInternal.QualifiedName, result); 198 } 199 } 200 201 return result; 202 } 203 else 204 { 205 return null; 206 } 207 } 208 209 /// <summary> 210 /// Gets all ResourceDetails matching find options. 211 /// </summary> 212 /// <param name="findOptions">The find options.</param> 213 /// <returns>A list of ResourceDetails.</returns> 214 public List<ResourceDetails> FindAllResourceDetails(FindUnitProcessorsOptions findOptions) 215 { 216 List<ResourceDetails> result = new List<ResourceDetails>(); 217 218 var resourceItemList = this.DSCv3.GetAllResources(ProcessorRunSettings.CreateFromFindUnitProcessorsOptions(findOptions)); 219 220 foreach (var item in resourceItemList) 221 { 222 ResourceDetails? details = null; 223 bool inDictionary = false; 224 lock (this.resourceDetailsDictionary) 225 { 226 inDictionary = this.resourceDetailsDictionary.TryGetValue(item.Type, out details); 227 } 228 229 if (details == null) 230 { 231 details = new ResourceDetails(item.Type); 232 } 233 234 if (!details.Exists) 235 { 236 details.SetResourceListItem(item); 237 } 238 239 details.EnsureDetails(this, findOptions.UnitDetailFlags); 240 241 if (!inDictionary) 242 { 243 lock (this.resourceDetailsDictionary) 244 { 245 this.resourceDetailsDictionary.Add(item.Type, details); 246 } 247 } 248 249 result.Add(details); 250 } 251 252 return result; 253 } 254 } 255 }