-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
StackSettingsConfigValueYamlConverter.cs
87 lines (74 loc) · 3.5 KB
/
StackSettingsConfigValueYamlConverter.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
// Copyright 2016-2021, Pulumi Corporation
using System;
using System.Collections.Generic;
using System.Text.Json;
using YamlDotNet.Core;
using YamlDotNet.Core.Events;
using YamlDotNet.Serialization;
namespace Pulumi.Automation.Serialization.Yaml
{
internal class StackSettingsConfigValueYamlConverter : IYamlTypeConverter
{
private static readonly Type _type = typeof(StackSettingsConfigValue);
public bool Accepts(Type type) => type == _type;
public object ReadYaml(IParser parser, Type type)
{
// check if plain string
if (parser.Accept<Scalar>(out var stringValue))
{
parser.MoveNext();
return new StackSettingsConfigValue(stringValue.Value, false);
}
var deserializer = new Deserializer();
// check whether it is an object with a single property called "secure"
// this means we have a secret value serialized into the value
if (parser.TryConsume<MappingStart>(out var _))
{
var dictionaryFromYaml = new Dictionary<string, object?>();
// in which case, check whether it is a secure value
while (parser.TryConsume<Scalar>(out var firstPropertyName))
{
if (string.Equals("Secure", firstPropertyName.Value, StringComparison.OrdinalIgnoreCase))
{
// secure string
if (!parser.TryConsume<Scalar>(out var securePropertyValue))
throw new YamlException($"Unable to deserialize [{type.FullName}] as a secure string. Expecting a string secret.");
// needs to be 1 mapping end and then return
parser.Require<MappingEnd>();
parser.MoveNext();
return new StackSettingsConfigValue(securePropertyValue.Value, true);
}
// not a secure string, so we need to add first value to the dictionary
dictionaryFromYaml.Add(firstPropertyName.Value, deserializer.Deserialize<object?>(parser));
}
parser.Require<MappingEnd>();
parser.MoveNext();
// serialize the dictionary back into the value as JSON
var serializedDictionary = JsonSerializer.Serialize(dictionaryFromYaml);
return new StackSettingsConfigValue(serializedDictionary, false);
}
// for anything else, i.e. arrays, parse the contents as is and serialize it a JSON string
var deserializedFromYaml = deserializer.Deserialize<object?>(parser);
var serializedToJson = JsonSerializer.Serialize(deserializedFromYaml);
return new StackSettingsConfigValue(serializedToJson, false);
}
public void WriteYaml(IEmitter emitter, object? value, Type type)
{
if (!(value is StackSettingsConfigValue configValue))
return;
// secure string
if (configValue.IsSecure)
{
emitter.Emit(new MappingStart(null, null, false, MappingStyle.Block));
emitter.Emit(new Scalar("secure"));
emitter.Emit(new Scalar(configValue.Value));
emitter.Emit(new MappingEnd());
}
// plain string
else
{
emitter.Emit(new Scalar(configValue.Value));
}
}
}
}