winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

ResourceDetails.cs (7575B)


      1 // -----------------------------------------------------------------------------
      2 // <copyright file="ResourceDetails.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 Microsoft.Management.Configuration.Processor.DSCv3.Model;
     11     using Microsoft.Management.Configuration.Processor.Helpers;
     12     using Microsoft.Management.Configuration.Processor.Unit;
     13 
     14     /// <summary>
     15     /// Cached data about a resource.
     16     /// </summary>
     17     internal class ResourceDetails
     18     {
     19         private readonly string resourceTypeName;
     20 
     21         private object detailsUpdateLock = new object();
     22         private IResourceListItem? resourceListItem = null;
     23 
     24         /// <summary>
     25         /// The current level of detail stored by this object.
     26         ///
     27         /// The method of discovery for each of the levels in ConfigurationUnitDetailFlags:
     28         ///     None: No details, either because the resource was not found or EnsureDetails has not been called.
     29         ///     Local: `resource list` is used to determine the details. An embedded schema may enable "Load" details level.
     30         ///            Property information may not be available at this level.
     31         ///     Catalog: Same as local; there is currently no catalog to query against.
     32         ///     Download: Same as local; there is currently no catalog to find anything to download.
     33         ///     Load: `resource schema` is used to get the full schema for the resource.
     34         ///           This ensures that property information is available.
     35         /// </summary>
     36         private ConfigurationUnitDetailFlags currentDetailLevel = ConfigurationUnitDetailFlags.None;
     37 
     38         /// <summary>
     39         /// Initializes a new instance of the <see cref="ResourceDetails"/> class.
     40         /// </summary>
     41         /// <param name="resourceTypeName">The resource type name.</param>
     42         public ResourceDetails(string resourceTypeName)
     43         {
     44             this.resourceTypeName = resourceTypeName;
     45         }
     46 
     47         /// <summary>
     48         /// Gets a value indicating whether this resource exists.
     49         /// Will be false until EnsureDetails is called and the resource is found.
     50         /// </summary>
     51         public bool Exists
     52         {
     53             get
     54             {
     55                 lock (this.detailsUpdateLock)
     56                 {
     57                     return this.currentDetailLevel != ConfigurationUnitDetailFlags.None;
     58                 }
     59             }
     60         }
     61 
     62         /// <summary>
     63         /// Gets the path of the resource.
     64         /// </summary>
     65         public string? Path
     66         {
     67             get
     68             {
     69                 lock (this.detailsUpdateLock)
     70                 {
     71                     return this.resourceListItem?.Path;
     72                 }
     73             }
     74         }
     75 
     76         /// <summary>
     77         /// Sets the resource list item directly to avoid duplicate "dsc resource list" calls.
     78         /// </summary>
     79         /// <param name="item">The resource list item.</param>
     80         public void SetResourceListItem(IResourceListItem item)
     81         {
     82             lock (this.detailsUpdateLock)
     83             {
     84                 if (this.resourceListItem != null)
     85                 {
     86                     throw new InvalidOperationException("Resource list item is already set");
     87                 }
     88 
     89                 this.resourceListItem = item;
     90                 this.currentDetailLevel |= ConfigurationUnitDetailFlags.Local;
     91             }
     92         }
     93 
     94         /// <summary>
     95         /// Ensures that the given detail level is present.
     96         /// </summary>
     97         /// <param name="processorSettings">The processor settings to use when getting details.</param>
     98         /// <param name="detailFlags">The detail level flags.</param>
     99         public void EnsureDetails(ProcessorSettings processorSettings, ConfigurationUnitDetailFlags detailFlags)
    100         {
    101             if (this.DetailsNeededFor(detailFlags, ConfigurationUnitDetailFlags.Local))
    102             {
    103                 // If we can't get local details, then exit until we have more options.
    104                 if (!this.GetLocalDetails(processorSettings))
    105                 {
    106                     return;
    107                 }
    108             }
    109 
    110             if (this.DetailsNeededFor(detailFlags, ConfigurationUnitDetailFlags.Load))
    111             {
    112                 this.GetLoadDetails(processorSettings);
    113             }
    114         }
    115 
    116         /// <summary>
    117         /// Gets a ConfigurationUnitProcessorDetails populated with all available data.
    118         /// </summary>
    119         /// <returns>A ConfigurationUnitProcessorDetails populated with all available data.</returns>
    120         public ConfigurationUnitProcessorDetails? GetConfigurationUnitProcessorDetails()
    121         {
    122             if (!this.Exists)
    123             {
    124                 return null;
    125             }
    126 
    127             ConfigurationUnitProcessorDetails result = new ConfigurationUnitProcessorDetails() { UnitType = this.resourceTypeName };
    128 
    129             lock (this.detailsUpdateLock)
    130             {
    131                 if (this.resourceListItem != null)
    132                 {
    133                     result.UnitType = this.resourceListItem.Type;
    134                     result.IsGroup = IsGroup(this.resourceListItem.Kind);
    135                     result.Version = this.resourceListItem.Version;
    136                     result.UnitDescription = this.resourceListItem.Description;
    137                     result.Author = this.resourceListItem.Author;
    138                     result.Path = this.resourceListItem.Path;
    139 
    140                     result.IsLocal = true;
    141                 }
    142             }
    143 
    144             return result;
    145         }
    146 
    147         private static bool IsGroup(ResourceKind kind) => kind switch
    148         {
    149             ResourceKind.Adapter => true,
    150             ResourceKind.Group => true,
    151             _ => false,
    152         };
    153 
    154         private bool DetailsNeededFor(ConfigurationUnitDetailFlags detailFlags, ConfigurationUnitDetailFlags targetLevel)
    155         {
    156             if (!detailFlags.HasFlag(targetLevel))
    157             {
    158                 return false;
    159             }
    160 
    161             lock (this.detailsUpdateLock)
    162             {
    163                 return !this.currentDetailLevel.HasFlag(targetLevel);
    164             }
    165         }
    166 
    167         private bool GetLocalDetails(ProcessorSettings processorSettings)
    168         {
    169             IResourceListItem? resourceListItem = processorSettings.DSCv3.GetResourceByType(this.resourceTypeName, null);
    170 
    171             if (resourceListItem != null)
    172             {
    173                 // TODO: Attempt to extract embedded schema to avoid the need for Load.
    174                 lock (this.detailsUpdateLock)
    175                 {
    176                     if (!this.currentDetailLevel.HasFlag(ConfigurationUnitDetailFlags.Local))
    177                     {
    178                         this.resourceListItem = resourceListItem;
    179                         this.currentDetailLevel |= ConfigurationUnitDetailFlags.Local;
    180                     }
    181                 }
    182 
    183                 return true;
    184             }
    185             else
    186             {
    187                 return false;
    188             }
    189         }
    190 
    191         private void GetLoadDetails(ProcessorSettings processorSettings)
    192         {
    193             throw new NotImplementedException();
    194         }
    195     }
    196 }