Skip to content

Commit 05898b0

Browse files
authored
Merge pull request #202 from aws/asmarp/sync-v3-v4
Sync `dev` and `v4sdk-development`
2 parents 11b4cd6 + ee61dcf commit 05898b0

File tree

10 files changed

+455
-88
lines changed

10 files changed

+455
-88
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
name: Change File Included in PR
2+
3+
on:
4+
pull_request:
5+
types: [opened, synchronize, reopened, labeled]
6+
7+
jobs:
8+
check-files-in-directory:
9+
if: ${{ !contains(github.event.pull_request.labels.*.name, 'Release Not Needed') && !contains(github.event.pull_request.labels.*.name, 'Release PR') }}
10+
name: Change File Included in PR
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- name: Checkout PR code
15+
uses: actions/checkout@v3
16+
17+
- name: Get List of Changed Files
18+
id: changed-files
19+
uses: tj-actions/changed-files@4edd678ac3f81e2dc578756871e4d00c19191daf #v45
20+
21+
- name: Check for Change File(s) in .autover/changes/
22+
run: |
23+
DIRECTORY=".autover/changes/"
24+
if echo "${{ steps.changed-files.outputs.all_changed_files }}" | grep -q "$DIRECTORY"; then
25+
echo "✅ One or more change files in '$DIRECTORY' are included in this PR."
26+
else
27+
echo "❌ No change files in '$DIRECTORY' are included in this PR."
28+
echo "Refer to the 'Adding a change file to your contribution branch' section of https://github.com/aws/aws-dotnet-extensions-configuration/blob/master/CONTRIBUTING.md"
29+
exit 1
30+
fi

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## Release 2025-02-20
2+
3+
### Amazon.Extensions.Configuration.SystemsManager (6.3.0)
4+
* Add opt-in JsonOrStringParameterProcessor processor supporting parameters being either strings or JSON
5+
16
## Release 2024-10-17
27

38
### Amazon.Extensions.Configuration.SystemsManager (7.0.0-preview.1)
Lines changed: 16 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
/*
22
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3-
*
3+
*
44
* Licensed under the Apache License, Version 2.0 (the "License").
55
* You may not use this file except in compliance with the License.
66
* A copy of the License is located at
7-
*
7+
*
88
* http://aws.amazon.com/apache2.0
9-
*
9+
*
1010
* or in the "license" file accompanying this file. This file is distributed
1111
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
1212
* express or implied. See the License for the specific language governing
@@ -19,6 +19,7 @@
1919
using Amazon.SimpleSystemsManagement;
2020
using Amazon.SimpleSystemsManagement.Model;
2121
using Microsoft.Extensions.Configuration;
22+
using static Amazon.Extensions.Configuration.SystemsManager.Utils.ParameterProcessorUtil;
2223

2324
namespace Amazon.Extensions.Configuration.SystemsManager
2425
{
@@ -33,10 +34,11 @@ public class DefaultParameterProcessor : IParameterProcessor
3334

3435
public virtual bool IncludeParameter(Parameter parameter, string path) => true;
3536

37+
/// Get the extra prefix if the path is subset of parameter name.
3638
public virtual string GetKey(Parameter parameter, string path)
3739
{
38-
var name = parameter.Name.StartsWith(path, StringComparison.OrdinalIgnoreCase)
39-
? parameter.Name.Substring(path.Length)
40+
var name = parameter.Name.StartsWith(path, StringComparison.OrdinalIgnoreCase)
41+
? parameter.Name.Substring(path.Length)
4042
: parameter.Name;
4143
#if NETCOREAPP3_1_OR_GREATER
4244
return name.TrimStart('/').Replace("/", KeyDelimiter, StringComparison.InvariantCulture);
@@ -47,51 +49,25 @@ public virtual string GetKey(Parameter parameter, string path)
4749

4850
public virtual string GetValue(Parameter parameter, string path) => parameter.Value;
4951

50-
private IEnumerable<KeyValuePair<string, string>> ParseStringList(Parameter parameter, string path)
51-
{
52-
// Items in a StringList must be separated by a comma (,).
53-
// You can't use other punctuation or special characters to escape items in the list.
54-
// If you have a parameter value that requires a comma, then use the String type.
55-
// https://docs.aws.amazon.com/systems-manager/latest/userguide/param-create-cli.html#param-create-cli-stringlist
56-
return parameter.Value.Split(',').Select((value, idx) =>
57-
new KeyValuePair<string, string>($"{GetKey(parameter, path)}:{idx}", value));
58-
}
59-
6052
public virtual IDictionary<string, string> ProcessParameters(IEnumerable<Parameter> parameters, string path)
6153
{
62-
var result = new List<KeyValuePair<string, string>>();
54+
var result = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
55+
6356
foreach (var parameter in parameters.Where(parameter => IncludeParameter(parameter, path)))
6457
{
58+
var keyPrefix = GetKey(parameter, path);
59+
var value = GetValue(parameter, path);
60+
6561
if (parameter.Type == ParameterType.StringList)
6662
{
67-
var parameterList = ParseStringList(parameter, path);
68-
69-
// Check for duplicate parameter keys.
70-
var stringListKeys = parameterList.Select(p => p.Key);
71-
var duplicateKeys = result.Where(r => stringListKeys.Contains(r.Key, StringComparer.OrdinalIgnoreCase)).Select(r => r.Key);
72-
if (duplicateKeys.Count() > 0)
73-
{
74-
throw new DuplicateParameterException($"Duplicate parameters '{string.Join(";", duplicateKeys)}' found. Parameter keys are case-insensitive.");
75-
}
76-
77-
result.AddRange(parameterList);
63+
ParseStringListParameter(keyPrefix, value, result);
64+
continue;
7865
}
79-
else
80-
{
81-
string parameterKey = GetKey(parameter, path);
8266

83-
// Check for duplicate parameter key.
84-
if (result.Any(r => string.Equals(r.Key, parameterKey, StringComparison.OrdinalIgnoreCase)))
85-
{
86-
throw new DuplicateParameterException($"Duplicate parameter '{parameterKey}' found. Parameter keys are case-insensitive.");
87-
}
88-
89-
result.Add(new KeyValuePair<string, string>(parameterKey, GetValue(parameter, path)));
90-
}
67+
ParseStringParameter(keyPrefix, value, result);
9168
}
9269

93-
return result.ToDictionary(parameter => parameter.Key, parameter => parameter.Value,
94-
StringComparer.OrdinalIgnoreCase);
70+
return result;
9571
}
9672
}
9773
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text.Json;
5+
using Amazon.SimpleSystemsManagement;
6+
using Amazon.SimpleSystemsManagement.Model;
7+
using static Amazon.Extensions.Configuration.SystemsManager.Utils.ParameterProcessorUtil;
8+
9+
namespace Amazon.Extensions.Configuration.SystemsManager
10+
{
11+
/// <inheritdoc />
12+
/// <summary>
13+
/// A processor that prioritizes JSON parameters but falls back to string parameters,
14+
/// in accordance with Systems Manager's suggested naming conventions
15+
/// </summary>
16+
public class JsonOrStringParameterProcessor : DefaultParameterProcessor
17+
{
18+
public override IDictionary<string, string> ProcessParameters(IEnumerable<Parameter> parameters, string path)
19+
{
20+
var result = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
21+
22+
foreach (var parameter in parameters.Where(parameter => IncludeParameter(parameter, path)))
23+
{
24+
var keyPrefix = GetKey(parameter, path);
25+
var value = GetValue(parameter, path);
26+
27+
if (parameter.Type == ParameterType.StringList)
28+
{
29+
ParseStringListParameter(keyPrefix, value, result);
30+
continue;
31+
}
32+
33+
try
34+
{
35+
ParseJsonParameter(keyPrefix, value, result);
36+
}
37+
catch (JsonException)
38+
{
39+
ParseStringParameter(keyPrefix, value, result);
40+
}
41+
}
42+
43+
return result;
44+
}
45+
}
46+
}
Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
/*
22
* Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3-
*
3+
*
44
* Licensed under the Apache License, Version 2.0 (the "License").
55
* You may not use this file except in compliance with the License.
66
* A copy of the License is located at
7-
*
7+
*
88
* http://aws.amazon.com/apache2.0
9-
*
9+
*
1010
* or in the "license" file accompanying this file. This file is distributed
1111
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
1212
* express or implied. See the License for the specific language governing
@@ -16,42 +16,31 @@
1616
using System;
1717
using System.Collections.Generic;
1818
using System.Linq;
19-
using Amazon.Extensions.Configuration.SystemsManager.Internal;
2019
using Amazon.SimpleSystemsManagement.Model;
21-
using Microsoft.Extensions.Configuration;
20+
using static Amazon.Extensions.Configuration.SystemsManager.Utils.ParameterProcessorUtil;
2221

2322
namespace Amazon.Extensions.Configuration.SystemsManager
2423
{
2524
/// <inheritdoc />
2625
/// <summary>
27-
/// Default parameter processor based on Systems Manager's suggested naming convention
26+
/// A processor specifically designed for handling JSON parameters,
27+
/// following Systems Manager's recommended naming conventions
2828
/// </summary>
2929
public class JsonParameterProcessor : DefaultParameterProcessor
3030
{
3131
public override IDictionary<string, string> ProcessParameters(IEnumerable<Parameter> parameters, string path)
3232
{
33-
var outputDictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
34-
foreach (Parameter parameter in parameters.Where(parameter => IncludeParameter(parameter, path)))
35-
{
36-
// Get the extra prefix if the path is subset of paramater name.
37-
string prefix = GetKey(parameter, path);
38-
39-
var parameterDictionary = JsonConfigurationParser.Parse(parameter.Value);
40-
foreach (var keyValue in parameterDictionary)
41-
{
42-
string key = (!string.IsNullOrEmpty(prefix) ? ConfigurationPath.Combine(prefix, keyValue.Key) : keyValue.Key);
33+
var result = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
4334

44-
// Check for duplicate parameter key.
45-
if (outputDictionary.ContainsKey(key))
46-
{
47-
throw new DuplicateParameterException($"Duplicate parameter '{key}' found. Parameter keys are case-insensitive.");
48-
}
35+
foreach (var parameter in parameters.Where(parameter => IncludeParameter(parameter, path)))
36+
{
37+
var keyPrefix = GetKey(parameter, path);
38+
var value = GetValue(parameter, path);
4939

50-
outputDictionary.Add(key, keyValue.Value);
51-
}
40+
ParseJsonParameter(keyPrefix, value, result);
5241
}
5342

54-
return outputDictionary;
43+
return result;
5544
}
5645
}
5746
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using Amazon.Extensions.Configuration.SystemsManager.Internal;
4+
using Microsoft.Extensions.Configuration;
5+
using System.Text.Json;
6+
7+
namespace Amazon.Extensions.Configuration.SystemsManager.Utils
8+
{
9+
public static class ParameterProcessorUtil
10+
{
11+
/// <summary>
12+
/// Parses the SSM parameter as JSON
13+
/// </summary>
14+
/// <param name="keyPrefix">prefix to add in configution key</param>
15+
/// <param name="value">SSM parameter value</param>
16+
/// <param name="result">append the parsed JSON value into</param>
17+
/// <exception cref="DuplicateParameterException">SSM parameter key is already present in <paramref name="result"/></exception>
18+
/// <exception cref="JsonException"><paramref name="value" /> does not represent a valid single JSON value.</exception>
19+
public static void ParseJsonParameter(string keyPrefix, string value, IDictionary<string, string> result)
20+
{
21+
foreach (var kv in JsonConfigurationParser.Parse(value))
22+
{
23+
var key = !string.IsNullOrEmpty(keyPrefix) ? ConfigurationPath.Combine(keyPrefix, kv.Key) : kv.Key;
24+
if (result.ContainsKey(key))
25+
{
26+
throw new DuplicateParameterException($"Duplicate parameter '{key}' found. Parameter keys are case-insensitive.");
27+
}
28+
29+
result.Add(key, kv.Value);
30+
}
31+
}
32+
33+
/// <summary>
34+
/// Parses the StringList SSM parameter as List of String
35+
/// <br/><br/>
36+
/// Items in a StringList must be separated by a comma (,).
37+
/// You can't use other punctuation or special characters to escape items in the list.
38+
/// If you have a parameter value that requires a comma, then use the String type.
39+
/// https://docs.aws.amazon.com/systems-manager/latest/userguide/param-create-cli.html#param-create-cli-stringlist
40+
/// </summary>
41+
/// <param name="keyPrefix">prefix to add in configution key</param>
42+
/// <param name="value">SSM parameter</param>
43+
/// <param name="result">append the parsed string list value into</param>
44+
/// <exception cref="DuplicateParameterException">SSM parameter key is already present in <paramref name="result"/></exception>
45+
public static void ParseStringListParameter(string keyPrefix, string value, IDictionary<string, string> result)
46+
{
47+
var configKeyValuePairs = value
48+
.Split(',')
49+
.Select((eachValue, idx) => new KeyValuePair<string, string>($"{keyPrefix}{ConfigurationPath.KeyDelimiter}{idx}", eachValue));
50+
51+
foreach (var kv in configKeyValuePairs)
52+
{
53+
if (result.ContainsKey(kv.Key))
54+
{
55+
throw new DuplicateParameterException($"Duplicate parameter '{kv.Key}' found. Parameter keys are case-insensitive.");
56+
}
57+
58+
result.Add(kv.Key, kv.Value);
59+
}
60+
}
61+
62+
/// <summary>
63+
/// Parses the SSM parameter as String
64+
/// </summary>
65+
/// <param name="key">key to be used for configution key</param>
66+
/// <param name="value">SSM parameter</param>
67+
/// <param name="result">append the parsed string value into</param>
68+
/// <exception cref="DuplicateParameterException">SSM parameter key is already present in <paramref name="result"/></exception>
69+
public static void ParseStringParameter(string key, string value, IDictionary<string, string> result)
70+
{
71+
if (result.ContainsKey(key))
72+
{
73+
throw new DuplicateParameterException($"Duplicate parameter '{key}' found. Parameter keys are case-insensitive.");
74+
}
75+
76+
result.Add(key, value);
77+
}
78+
}
79+
}

0 commit comments

Comments
 (0)