1+ import { Context } from 'aws-lambda' ;
2+ import {
3+ SSMProvider ,
4+ } from '../../src/ssm' ;
5+ import {
6+ SSMGetOptionsInterface ,
7+ SSMGetMultipleOptionsInterface ,
8+ SSMGetParametersByNameOptionsInterface
9+ } from '../../src/types' ;
10+ import { TinyLogger } from '../helpers/tinyLogger' ;
11+ import { middleware } from '../helpers/sdkMiddlewareRequestCounter' ;
12+ import { SSMClient } from '@aws-sdk/client-ssm' ;
13+
14+ // We use a custom logger to log pure JSON objects to stdout
15+ const logger = new TinyLogger ( ) ;
16+
17+ const defaultProvider = new SSMProvider ( ) ;
18+ // Provider test 8, 9
19+ const customClient = new SSMClient ( { } ) ;
20+ customClient . middlewareStack . use ( middleware ) ;
21+ const providerWithMiddleware = new SSMProvider ( {
22+ awsSdkV3Client : customClient
23+ } ) ;
24+
25+ const paramA = process . env . PARAM_A ?? 'my-param' ;
26+ const paramB = process . env . PARAM_B ?? 'my-param' ;
27+ const paramEncryptedA = process . env . PARAM_ENCRYPTED_A ?? 'my-encrypted-param' ;
28+ const paramEncryptedB = process . env . PARAM_ENCRYPTED_B ?? 'my-encrypted-param' ;
29+
30+ // Use provider specified, or default to main one & return it with cache cleared
31+ const resolveProvider = ( provider ?: SSMProvider ) : SSMProvider => {
32+ const resolvedProvider = provider ? provider : defaultProvider ;
33+ resolvedProvider . clearCache ( ) ;
34+
35+ return resolvedProvider ;
36+ } ;
37+
38+ // Helper function to call get() and log the result
39+ const _call_get = async (
40+ paramName : string ,
41+ testName : string ,
42+ options ?: SSMGetOptionsInterface ,
43+ provider ?: SSMProvider
44+ ) : Promise < void > => {
45+ try {
46+ const currentProvider = resolveProvider ( provider ) ;
47+
48+ const parameterValue = await currentProvider . get ( paramName , options ) ;
49+ logger . log ( {
50+ test : testName ,
51+ value : parameterValue
52+ } ) ;
53+ } catch ( err ) {
54+ logger . log ( {
55+ test : testName ,
56+ error : err . message
57+ } ) ;
58+ }
59+ } ;
60+
61+ // Helper function to call getMultiple() and log the result
62+ const _call_get_multiple = async (
63+ paramPath : string ,
64+ testName : string ,
65+ options ?: SSMGetMultipleOptionsInterface ,
66+ provider ?: SSMProvider
67+ ) : Promise < void > => {
68+ try {
69+ const currentProvider = resolveProvider ( provider ) ;
70+
71+ const parameterValues = await currentProvider . getMultiple (
72+ paramPath ,
73+ options
74+ ) ;
75+ logger . log ( {
76+ test : testName ,
77+ value : parameterValues
78+ } ) ;
79+ } catch ( err ) {
80+ logger . log ( {
81+ test : testName ,
82+ error : err . message
83+ } ) ;
84+ }
85+ } ;
86+
87+ // Helper function to call getParametersByName() and log the result
88+ const _call_get_parameters_by_name = async (
89+ params : Record < string , SSMGetParametersByNameOptionsInterface > ,
90+ testName : string ,
91+ options ?: SSMGetParametersByNameOptionsInterface ,
92+ provider ?: SSMProvider
93+ ) : Promise < void > => {
94+ try {
95+ const currentProvider = resolveProvider ( provider ) ;
96+
97+ const parameterValues = await currentProvider . getParametersByName ( params , options ) ;
98+ logger . log ( {
99+ test : testName ,
100+ value : parameterValues
101+ } ) ;
102+ } catch ( err ) {
103+ logger . log ( {
104+ test : testName ,
105+ error : err . message
106+ } ) ;
107+ }
108+ } ;
109+
110+ export const handler = async ( _event : unknown , _context : Context ) : Promise < void > => {
111+ // Test 1 - get a single parameter by name with default options
112+ await _call_get ( paramA , 'get' ) ;
113+
114+ // Test 2 - get a single parameter by name with decrypt
115+ await _call_get ( paramEncryptedA , 'get-decrypt' , { decrypt : true } ) ;
116+
117+ // Test 3 - get multiple parameters by path with default options
118+ // Get path (/param/get)
119+ const parameterPath = paramA . substring ( 0 , paramA . lastIndexOf ( '/' ) ) ;
120+ await _call_get_multiple ( parameterPath , 'get-multiple' ) ;
121+
122+ // Test 4 - get multiple parameters by path recursively (aka. get all parameters under a path recursively)
123+ // Get parameters root (i.e. from /param/get/a & /param/get/b to /param)
124+ const parameterRoot = paramA . substring (
125+ 0 ,
126+ paramA . substring ( 1 , paramA . length ) . indexOf ( '/' ) + 1
127+ ) ;
128+ await _call_get_multiple ( parameterRoot , 'get-multiple-recursive' , { recursive : true } ) ;
129+
130+ // Test 5 - get multiple parameters by path with decrypt
131+ // Get parameters path (i.e. from /param/get/a & /param/get/b to /param/get)
132+ const parameterPathDecrypt = paramEncryptedA . substring ( 0 , paramEncryptedA . lastIndexOf ( '/' ) ) ;
133+ await _call_get_multiple ( parameterPathDecrypt , 'get-multiple-decrypt' , { decrypt : true } ) ;
134+
135+ // Test 6 - get multiple parameters by name with default options
136+ await _call_get_parameters_by_name ( {
137+ [ paramA ] : { } ,
138+ [ paramB ] : { } ,
139+ } , 'get-multiple-by-name' ) ;
140+
141+ // Test 7 - get multiple parameters by name, some of them encrypted and some not
142+ await _call_get_parameters_by_name ( {
143+ [ paramA ] : { } ,
144+ [ paramEncryptedA ] : { decrypt : true } ,
145+ [ paramEncryptedB ] : { decrypt : true } ,
146+ } , 'get-multiple-by-name-mixed-decrypt' ) ;
147+
148+ // Test 8
149+ // get parameter twice with middleware, which counts the number of requests, we check later if we only called SSM API once
150+ try {
151+ providerWithMiddleware . clearCache ( ) ;
152+ middleware . counter = 0 ;
153+ await providerWithMiddleware . get ( paramA ) ;
154+ await providerWithMiddleware . get ( paramA ) ;
155+ logger . log ( {
156+ test : 'get-cached' ,
157+ value : middleware . counter // should be 1
158+ } ) ;
159+ } catch ( err ) {
160+ logger . log ( {
161+ test : 'get-cached' ,
162+ error : err . message
163+ } ) ;
164+ }
165+
166+ // Test 9
167+ // get parameter twice, but force fetch 2nd time, we count number of SDK requests and check that we made two API calls
168+ try {
169+ providerWithMiddleware . clearCache ( ) ;
170+ middleware . counter = 0 ;
171+ await providerWithMiddleware . get ( paramA ) ;
172+ await providerWithMiddleware . get ( paramA , { forceFetch : true } ) ;
173+ logger . log ( {
174+ test : 'get-forced' ,
175+ value : middleware . counter // should be 2
176+ } ) ;
177+ } catch ( err ) {
178+ logger . log ( {
179+ test : 'get-forced' ,
180+ error : err . message
181+ } ) ;
182+ }
183+ } ;
0 commit comments