-
Notifications
You must be signed in to change notification settings - Fork 57
Add missing functions for SSM Parameter Store #91
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -47,6 +47,136 @@ component { | |
| return apiCall( requestSettings, 'GetParameters', payload ); | ||
| } | ||
|
|
||
| /** | ||
| * Get parameters by path. | ||
| * https://docs.aws.amazon.com/systems-manager/latest/APIReference/API_GetParametersByPath.html | ||
| * @Path The hierarchy for the parameter. Hierarchies start with a forward slash (/). | ||
| * @Recursive Retrieve all parameters within a hierarchy. | ||
| * @WithDecryption Return decrypted secure string value. Return decrypted values for secure string parameters. | ||
| * @MaxResults The maximum number of items to return. | ||
| * @NextToken The token for the next set of items to return. (For pagination.) | ||
| */ | ||
| public any function getParametersByPath( | ||
| required string Path, | ||
| boolean Recursive, | ||
| boolean WithDecryption, | ||
| numeric MaxResults, | ||
| string NextToken | ||
| ) { | ||
| var requestSettings = api.resolveRequestSettings( argumentCollection = arguments ); | ||
| var payload = { 'Path': arguments.Path }; | ||
| if ( !isNull( arguments.Recursive ) ) { | ||
| payload[ 'Recursive' ] = arguments.Recursive; | ||
| } | ||
| if ( !isNull( arguments.WithDecryption ) ) { | ||
| payload[ 'WithDecryption' ] = arguments.WithDecryption; | ||
| } | ||
| if ( !isNull( arguments.MaxResults ) ) { | ||
| payload[ 'MaxResults' ] = arguments.MaxResults; | ||
| } | ||
| if ( !isNull( arguments.NextToken ) ) { | ||
| payload[ 'NextToken' ] = arguments.NextToken; | ||
| } | ||
| return apiCall( requestSettings, 'GetParametersByPath', payload ); | ||
| } | ||
|
|
||
| /** | ||
| * Retrieves all parameters from a specified path. | ||
| * Handles pagination to ensure all parameters within the path are fetched. | ||
| * @Path The hierarchy path to query parameters. Must start with a forward slash (e.g., "/production"). | ||
| * @Recursive If true, retrieves parameters from the entire hierarchy under the specified path. | ||
| * @withDecryption If true, retrieves decrypted values for secure string parameters. | ||
| */ | ||
| public array function getAllParametersByPath( | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not sure about adding this method. I don't think there are any other places in the code base where there is a method that calls the API multiple times (potentially) before returning. I know other libraries do add iterators, so maybe there is a place for this, but it is not something that has been done before. I would have expected the iteration to be implemented in your own calling code.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Its your decision. Remove or not? I typically create a helper function to handle common repetitive tasks, especially when reusing the same library across multiple projects. SSM's 10 parameter limit is quite low by pagination standards. My use case is that I store application configurations by path in the parameter store and always end up with more than 10 i need to retrieve.
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I understand the low parameter limit is annoying, but for now I'd like to leave helper functions like this, that don't actually call the API themselves, out of the library. |
||
| required string path, | ||
| required boolean recursive, | ||
| required boolean withDecryption | ||
| ) { | ||
| var allParameters = []; | ||
| var nextToken = ""; | ||
| var parametersResponse = {}; | ||
|
|
||
| // Initial loop condition | ||
| var continueLoop = true; | ||
|
|
||
| while (continueLoop) { | ||
| // Make the API call to get parameters by path | ||
| parametersResponse = getParametersByPath( | ||
| Path = arguments.path, | ||
| Recursive = arguments.recursive, | ||
| WithDecryption = arguments.withDecryption, | ||
| MaxResults = 10, // Maximum items per call | ||
| NextToken = nextToken | ||
| ); | ||
|
|
||
| // Append the retrieved parameters to the results array, merging arrays into a flat array | ||
| if (structKeyExists(parametersResponse.data, "Parameters")) { | ||
| arrayAppend(allParameters, parametersResponse.data.Parameters, true); | ||
| } | ||
|
|
||
| // Update nextToken and determine if the loop should continue | ||
| if (structKeyExists(parametersResponse.data, "NextToken")) { | ||
| nextToken = parametersResponse.data.NextToken; | ||
| } else { | ||
| continueLoop = false; | ||
| } | ||
| } | ||
|
|
||
| return allParameters; | ||
| } | ||
|
|
||
| /** | ||
| * Add or update a parameter in the Parameter Store. | ||
| * https://docs.aws.amazon.com/systems-manager/latest/APIReference/API_PutParameter.html | ||
| * @Name The name of the parameter to create or update. | ||
| * @Value The parameter value. | ||
| * @Type The type of parameter. Valid values are String, StringList, and SecureString. | ||
| * @Overwrite Overwrite an existing parameter of the same name. | ||
| */ | ||
| public any function putParameter( | ||
| required string Name, | ||
| required string Value, | ||
| required string Type, | ||
| boolean Overwrite | ||
| ) { | ||
| var requestSettings = api.resolveRequestSettings( argumentCollection = arguments ); | ||
| var payload = { | ||
| 'Name': arguments.Name, | ||
| 'Value': (len(arguments.Value) ? arguments.Value : " "), | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the idea here with the overwrite of the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. SSM doesn't allow empty values. They must have a length greater than or equal to 1.
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd rather leave this choice up to the calling code - whatever that passes in as the value should be passed on to API. I don't want to change the |
||
| 'Type': arguments.Type | ||
| }; | ||
| if ( !isNull( arguments.Overwrite ) ) { | ||
| payload[ 'Overwrite' ] = arguments.Overwrite; | ||
| } | ||
| return apiCall( requestSettings, 'PutParameter', payload ); | ||
| } | ||
|
|
||
| /** | ||
| * Delete a parameter from the Parameter Store. | ||
| * https://docs.aws.amazon.com/systems-manager/latest/APIReference/API_DeleteParameter.html | ||
| * @Name The name of the parameter to delete. | ||
| */ | ||
| public any function deleteParameter( | ||
| required string Name | ||
| ) { | ||
| var requestSettings = api.resolveRequestSettings( argumentCollection = arguments ); | ||
| var payload = { 'Name': arguments.Name }; | ||
| return apiCall( requestSettings, 'DeleteParameter', payload ); | ||
| } | ||
|
|
||
| /** | ||
| * Delete multiple parameters from the Parameter Store. | ||
| * https://docs.aws.amazon.com/systems-manager/latest/APIReference/API_DeleteParameters.html | ||
| * @Names The names of the parameters to delete. | ||
| */ | ||
| public any function deleteParameters( | ||
| required array Names | ||
| ) { | ||
| var requestSettings = api.resolveRequestSettings( argumentCollection = arguments ); | ||
| var payload = { 'Names': arguments.Names }; | ||
| return apiCall( requestSettings, 'DeleteParameters', payload ); | ||
| } | ||
|
|
||
| public string function getHost( | ||
| required string region | ||
| ) { | ||
|
|
@@ -81,4 +211,4 @@ component { | |
| return apiResponse; | ||
| } | ||
|
|
||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can the four null checks above be combined into a for loop? e.g.:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure. I just code in the same style and patterns I see in the library. Line 168 of personalize.cfc or Line 235 in connect.cfc for instance. Can i blame Eric Peterson? :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair point 😁 I haven't been consistent about asking for this. But I do prefer the style above.