@@ -0,0 +1,100 @@
import boto3
from botocore .exceptions import ClientError
import datetime
class SSMParameterStore (object ):
"""
Provide a dictionary-like interface to access AWS SSM Parameter Store
"""
def __init__ (self , prefix = None , ssm_client = None , ttl = None ):
self ._prefix = (prefix or "" ).rstrip ("/" ) + "/"
self ._client = ssm_client or boto3 .client ('ssm' )
self ._keys = None
self ._substores = {}
self ._ttl = ttl
def get (self , name , ** kwargs ):
assert name , 'Name can not be empty'
if self ._keys is None :
self .refresh ()
abs_key = "%s%s" % (self ._prefix , name )
if name not in self ._keys :
if 'default' in kwargs :
return kwargs ['default' ]
raise KeyError (name )
elif self ._keys [name ]['type' ] == 'prefix' :
if abs_key not in self ._substores :
store = self .__class__ (prefix = abs_key , ssm_client = self ._client , ttl = self ._ttl )
self ._substores [abs_key ] = store
return self ._substores [abs_key ]
else :
return self ._get_value (name , abs_key )
def refresh (self ):
self ._keys = {}
self ._substores = {}
responses = self ._client .describe_parameters (
ParameterFilters = [
dict (Key = "Path" , Option = "Recursive" , Values = [self ._prefix ])
]
)
for p in responses [u'Parameters' ]:
paths = p ['Name' ][len (self ._prefix ):].split ('/' )
name = paths [0 ]
# this is a prefix
if len (paths ) > 1 :
self ._keys [name ] = {'type' : 'prefix' }
else :
self ._keys [name ] = {'type' : 'parameter' , 'expire' : None }
def keys (self ):
if self ._keys is None :
self .refresh ()
return self ._keys .keys ()
def _get_value (self , name , abs_key ):
entry = self ._keys [name ]
# simple ttl
if self ._ttl == False or (entry ['expire' ] and entry ['expire' ] <= datetime .datetime .now ()):
entry .pop ('value' , None )
if 'value' not in entry :
parameter = self ._client .get_parameter (Name = abs_key , WithDecryption = True )['Parameter' ]
value = parameter ['Value' ]
if parameter ['Type' ] == 'StringList' :
value = value .split ("," )
entry ['value' ] = value
if self ._ttl :
entry ['expire' ] = datetime .datetime .now () + datetime .timedelta (seconds = self ._ttl )
else :
entry ['expire' ] = None
return entry ['value' ]
def __contains__ (self , name ):
try :
self .get (name )
return True
except :
return False
def __getitem__ (self , name ):
return self .get (name )
def __setitem__ (self , key , value ):
raise NotImplementedError ()
def __delitem__ (self , name ):
raise NotImplementedError ()
def __repr__ (self ):
return 'ParameterStore[%s]' % self ._prefix