winget-cli

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

DscTestJsonResource.cpp (7096B)


      1 // Copyright (c) Microsoft Corporation.
      2 // Licensed under the MIT License.
      3 #include "pch.h"
      4 #include "DscTestJsonResource.h"
      5 #include "DscComposableObject.h"
      6 #include <AppInstallerRuntime.h>
      7 
      8 using namespace AppInstaller::Utility::literals;
      9 
     10 namespace AppInstaller::CLI
     11 {
     12     namespace
     13     {
     14         WINGET_DSC_DEFINE_COMPOSABLE_PROPERTY_FLAGS(PropertyProperty, std::string, Property, "property", DscComposablePropertyFlag::Required | DscComposablePropertyFlag::CopyToOutput, "The JSON property name."_lis);
     15         WINGET_DSC_DEFINE_COMPOSABLE_PROPERTY(ValueProperty, Json::Value, Value, "value", "The value for the JSON property."_lis);
     16 
     17         using TestJsonObject = DscComposableObject<StandardExistProperty, PropertyProperty, ValueProperty>;
     18 
     19         struct TestJsonFunctionData
     20         {
     21             TestJsonFunctionData()
     22             {
     23                 InitializeFileData();
     24             }
     25 
     26             TestJsonFunctionData(const std::optional<Json::Value>& json) : Input(json), Output(Input.CopyForOutput())
     27             {
     28                 InitializeFileData();
     29             }
     30 
     31             TestJsonObject Input;
     32             TestJsonObject Output;
     33             std::filesystem::path FilePath;
     34             Json::Value RootValue;
     35 
     36             static std::filesystem::path GetFilePath()
     37             {
     38                 std::filesystem::path result = Runtime::GetPathTo(Runtime::PathName::LocalState);
     39                 result /= "test-json-file.json";
     40                 return result;
     41             }
     42 
     43             // Fills the Output object with the current state
     44             void Get()
     45             {
     46                 const std::string& propertyName = Input.Property().value();
     47                 const Json::Value* propertyValue = RootValue.find(propertyName.data(), propertyName.data() + propertyName.length());
     48 
     49                 if (propertyValue)
     50                 {
     51                     Output.Exist(true);
     52 
     53                     Output.Value(*propertyValue);
     54                 }
     55                 else
     56                 {
     57                     Output.Exist(false);
     58                 }
     59             }
     60 
     61         private:
     62             void InitializeFileData()
     63             {
     64                 FilePath = GetFilePath();
     65                 RootValue = GetJsonFromFile();
     66             }
     67 
     68             Json::Value GetJsonFromFile() const
     69             {
     70                 Json::Value result;
     71                 Json::CharReaderBuilder builder;
     72                 Json::String errors;
     73 
     74                 std::ifstream stream{ FilePath, std::ios::binary };
     75 
     76                 if (stream)
     77                 {
     78                     if (!Json::parseFromStream(builder, stream, &result, &errors))
     79                     {
     80                         AICLI_LOG(CLI, Warning, << "Failed to read test JSON file: " << errors);
     81                         result = Json::Value{};
     82                     }
     83                 }
     84                 else
     85                 {
     86                     AICLI_LOG(CLI, Warning, << "Couldn't open test JSON file: " << FilePath);
     87                 }
     88 
     89                 return result;
     90             }
     91         };
     92     }
     93 
     94     DscTestJsonResource::DscTestJsonResource(std::string_view parent) :
     95         DscCommandBase(parent, "test-json", DscResourceKind::Resource,
     96             DscFunctions::Get | DscFunctions::Set | DscFunctions::Export | DscFunctions::Schema,
     97             DscFunctionModifiers::HandlesExist | DscFunctionModifiers::ReturnsState)
     98     {
     99     }
    100 
    101     std::vector<Argument> DscTestJsonResource::GetArguments() const
    102     {
    103         auto result = DscCommandBase::GetArguments();
    104         result.emplace_back(Execution::Args::Type::DscResourceFunctionDelete, Resource::String::DscResourceFunctionDescriptionDelete, ArgumentType::Flag);
    105         return result;
    106     }
    107 
    108     Resource::LocString DscTestJsonResource::ShortDescription() const
    109     {
    110         return "[TEST] JSON content resource"_lis;
    111     }
    112 
    113     Resource::LocString DscTestJsonResource::LongDescription() const
    114     {
    115         return "[TEST] This resource is only available for tests. It provides JSON content configuration of a well known file."_lis;
    116     }
    117 
    118     void DscTestJsonResource::ExecuteInternal(Execution::Context& context) const
    119     {
    120         if (context.Args.Contains(Execution::Args::Type::DscResourceFunctionDelete))
    121         {
    122             std::filesystem::remove_all(TestJsonFunctionData::GetFilePath());
    123             return;
    124         }
    125 
    126         DscCommandBase::ExecuteInternal(context);
    127     }
    128 
    129     std::string DscTestJsonResource::ResourceType() const
    130     {
    131         return "TestJSON";
    132     }
    133 
    134     void DscTestJsonResource::ResourceFunctionGet(Execution::Context& context) const
    135     {
    136         if (auto json = GetJsonFromInput(context))
    137         {
    138             TestJsonFunctionData data{ json };
    139 
    140             data.Get();
    141 
    142             WriteJsonOutputLine(context, data.Output.ToJson());
    143         }
    144     }
    145 
    146     void DscTestJsonResource::ResourceFunctionSet(Execution::Context& context) const
    147     {
    148         if (auto json = GetJsonFromInput(context))
    149         {
    150             TestJsonFunctionData data{ json };
    151 
    152             data.Get();
    153 
    154             if (data.RootValue.isNull())
    155             {
    156                 data.RootValue = Json::Value{ Json::objectValue };
    157             }
    158 
    159             if (data.Input.ShouldExist())
    160             {
    161                 data.RootValue[data.Input.Property().value()] = data.Input.Value().value_or(Json::Value{ Json::nullValue });
    162                 data.Output.Exist(true);
    163                 data.Output.Value(data.RootValue[data.Input.Property().value()]);
    164             }
    165             else if (data.Output.Exist().value())
    166             {
    167                 data.RootValue.removeMember(data.Input.Property().value());
    168                 data.Output.Exist(false);
    169             }
    170 
    171             std::ofstream stream{ data.FilePath, std::ios::binary };
    172 
    173             Json::StreamWriterBuilder writerBuilder;
    174             writerBuilder.settings_["indentation"] = "  ";
    175 
    176             stream << Json::writeString(writerBuilder, data.RootValue);
    177 
    178             WriteJsonOutputLine(context, data.Output.ToJson());
    179         }
    180     }
    181 
    182     void DscTestJsonResource::ResourceFunctionExport(Execution::Context& context) const
    183     {
    184         TestJsonFunctionData data;
    185 
    186         if (data.RootValue.isObject())
    187         {
    188             for (const auto& member : data.RootValue.getMemberNames())
    189             {
    190                 const Json::Value* memberValue = data.RootValue.find(member.data(), member.data() + member.length());
    191 
    192                 if (memberValue)
    193                 {
    194                     TestJsonObject output;
    195                     output.Property(member);
    196                     output.Value(*memberValue);
    197 
    198                     WriteJsonOutputLine(context, output.ToJson());
    199                 }
    200             }
    201         }
    202     }
    203 
    204     void DscTestJsonResource::ResourceFunctionSchema(Execution::Context& context) const
    205     {
    206         WriteJsonOutputLine(context, TestJsonObject::Schema(ResourceType()));
    207     }
    208 }