Skip to content

Commit

Permalink
added more test, the ability to use parameters and ref (references), …
Browse files Browse the repository at this point in the history
…added custom valley properties
  • Loading branch information
bjinwright committed Oct 8, 2017
1 parent 1326851 commit 975dbee
Show file tree
Hide file tree
Showing 14 changed files with 147 additions and 379 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ __pycache__/

# C extensions
*.so

*.ipynb
*.idea/
# Distribution / packaging
.Python
Expand Down
20 changes: 19 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,20 @@ f = Function('testpublish',Handler='s3imageresize.handler',
s.add_resource(f)
```

##### add_parameter(parameter)

Add a parameter class to the template

###### Example

```python
import sammy as sm

s = sm.SAM(render_type='json')

s.add_parameter(sm.Parameter(name='Bucket',Type='String'))
```

##### get_template_dict()

Returns Python *dict* object representation of the template.
Expand Down Expand Up @@ -133,4 +147,8 @@ This class represents a simple DynamoDB table
from sammy import SimpleTable

ddb = SimpleTable('maintable',PrimaryKey={'Name':'_id','Type':'String'})
```
```

### Ref

This class represents a reference to
105 changes: 48 additions & 57 deletions sammy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,6 @@
}
RENDER_FORMATS = {'json':'json','yaml':'yaml'}

def ref_constructor(loader, node):
value = loader.construct_scalar(node)
return '!Ref {}'.format(value)

yaml.add_constructor(u'!Ref',ref_constructor)

def ref_short_constructor(loader,node):
value = loader.construct_scalar(node)
return '!{}'.format(value)

yaml.add_constructor(u'!',ref_short_constructor)

def remove_nulls(obj_dict):
null_keys = []
for k, v in obj_dict.items():
Expand All @@ -51,29 +39,30 @@ def __init__(self,**kwargs):
self.validate()


class CodeURI(SAMSchema):
Bucket = CharProperty(required=True)
Key = CharProperty(required=True)
class Ref(SAMSchema):
Ref = CharProperty(required=True)


class S3URI(SAMSchema):
Bucket = CharForeignProperty(Ref,required=True)
Key = CharForeignProperty(Ref,required=True)

def to_dict(self):
obj = remove_nulls(self._data.copy())
name = obj.pop('name')
return {
'name':name,
'r':obj
}
return obj


class S3KeyFilter(SAMSchema):
S3Key = CharProperty()
S3Key = CharForeignProperty(Ref)


class Environment(SAMSchema):
Variables = DictProperty(required=True)


class Parameter(SAMSchema):
name = CharProperty(required=True)
Type = CharProperty(required=True)
name = CharForeignProperty(Ref,required=True)
Type = CharForeignProperty(Ref,required=True)

def to_dict(self):
obj = remove_nulls(self._data.copy())
Expand All @@ -86,7 +75,7 @@ def to_dict(self):
class Resource(SAMSchema):
_resource_type = None

name = CharProperty(required=True)
name = CharForeignProperty(Ref,required=True)

def to_dict(self):
obj = remove_nulls(self._data.copy())
Expand All @@ -96,7 +85,6 @@ def to_dict(self):
}
if len(obj.keys()) > 0:
r_attrs['Properties'] = {k: v for k, v in obj.items() if v}

return {
'name':name,
'r':r_attrs
Expand All @@ -110,7 +98,7 @@ def add_attr(self,k,v):
class EventSchema(SAMSchema):
_event_type = None

name = CharProperty(required=True)
name = CharForeignProperty(Ref,required=True)

def to_dict(self):
obj = remove_nulls(self._data.copy())
Expand All @@ -128,55 +116,55 @@ def to_dict(self):
class APIEvent(EventSchema):
_event_type = 'Api'

Path = CharProperty(required=True)
Method = CharProperty(required=True,choices=API_METHODS)
RestApiId = CharProperty()
Path = CharForeignProperty(Ref,required=True)
Method = CharForeignProperty(Ref,required=True,choices=API_METHODS)
RestApiId = CharForeignProperty(Ref)


class S3Event(EventSchema):
_event_type = 'S3'

Bucket = CharProperty(required=True)
Bucket = CharForeignProperty(Ref,required=True)
Events = ListProperty(required=True)
Filter = ForeignProperty(S3KeyFilter)


class SNSEvent(EventSchema):
_event_type = 'SNS'

Topic = CharProperty(required=True)
Topic = CharForeignProperty(Ref,required=True)


class KinesisEvent(EventSchema):
_event_type = 'Kinesis'

Stream = CharProperty(required=True)
StartingPosition = CharProperty(required=True)
Stream = CharForeignProperty(Ref,required=True)
StartingPosition = CharForeignProperty(Ref,required=True)
BatchSize = IntegerProperty()


class DynamoDBEvent(EventSchema):
_event_type = 'DynamoDB'

Stream = CharProperty(required=True)
StartingPosition = CharProperty(required=True)
Stream = CharForeignProperty(Ref,required=True)
StartingPosition = CharForeignProperty(Ref,required=True)
BatchSize = IntegerProperty()


class ScheduleEvent(EventSchema):
Schedule = CharProperty(required=True)
Input = CharProperty()
Schedule = CharForeignProperty(Ref,required=True)
Input = CharForeignProperty(Ref)


class CloudWatchEvent(EventSchema):
Pattern = DictProperty(required=True)
Input = CharProperty()
InputPath = CharProperty()
Input = CharForeignProperty(Ref)
InputPath = CharForeignProperty(Ref)


class IoTRuleEvent(EventSchema):
Sql = CharProperty(required=True)
AwsIotSqlVersion = CharProperty()
Sql = CharForeignProperty(Ref,required=True)
AwsIotSqlVersion = CharForeignProperty(Ref)


class AlexaSkillEvent(EventSchema):
Expand All @@ -186,8 +174,8 @@ class AlexaSkillEvent(EventSchema):
class DeadLetterQueueSchema(SAMSchema):
_dlq_type = None

name = CharProperty(required=True)
TargetArn = CharProperty(required=True)
name = CharForeignProperty(Ref,required=True)
TargetArn = CharForeignProperty(Ref,required=True)

def to_dict(self):
obj = remove_nulls(self._data.copy())
Expand All @@ -211,24 +199,25 @@ class SQSLetterQueue(DeadLetterQueueSchema):
class Function(Resource):
_resource_type = 'AWS::Serverless::Function'

Handler = CharProperty(required=True)
Runtime = CharProperty(required=True,max_length=15)
CodeUri = CharForeignProperty(CodeURI)
FunctionName = CharProperty()
Description = CharProperty()
Handler = CharForeignProperty(Ref,required=True)
Runtime = CharForeignProperty(Ref,required=True,max_length=15)
CodeUri = ForeignProperty(S3URI)
FunctionName = CharForeignProperty(Ref)
Description = CharForeignProperty(Ref)
MemorySize = IntegerProperty()
Timeout = IntegerProperty()
Role = CharProperty()
Policies = CharProperty()
Role = CharForeignProperty(Ref)
Policies = CharForeignProperty(Ref)
Environment = ForeignProperty(Environment)
VpcConfig = DictProperty()
Events = ForeignInstanceListProperty(EventSchema)
Tags = DictProperty()
Tracing = CharProperty()
KmsKeyArn = CharProperty()
Tracing = CharForeignProperty(Ref)
KmsKeyArn = CharForeignProperty(Ref)
DeadLetterQueue = ForeignInstanceListProperty(DeadLetterQueueSchema)

def to_dict(self):

obj = super(Function, self).to_dict()
try:
events = [i.to_dict() for i in obj['r']['Properties'].pop('Events')]
Expand All @@ -241,17 +230,18 @@ def to_dict(self):
obj['r']['Properties']['DeadLetterQueue'] = {i.get('name'):i.get('r') for i in dlq}
except KeyError:
pass

return obj


class API(Resource):
_resource_type = "AWS::Serverless::Api"

StageName = CharProperty(required=True)
DefinitionUri = CharProperty()
StageName = CharForeignProperty(Ref,required=True)
DefinitionUri = CharForeignProperty(Ref)
DefinitionBody = DictProperty()
CacheClusterEnabled = BooleanProperty()
CacheClusterSize = CharProperty()
CacheClusterSize = CharForeignProperty(Ref)
Variables = DictProperty()


Expand Down Expand Up @@ -326,12 +316,13 @@ def get_template(self):
else:
return self.to_yaml()

def publish(self, stack_name):
def publish(self, stack_name,**kwargs):
param_list = [{'ParameterKey':k,'ParameterValue':v} for k,v in kwargs.items()]
d = Deployer(boto3.client('cloudformation'))
result = d.create_and_wait_for_changeset(
stack_name=stack_name,
cfn_template=self.get_template(),
parameter_values=[],
parameter_values=param_list,
capabilities=['CAPABILITY_IAM'])
d.execute_changeset(result.changeset_id, stack_name)
d.wait_for_execute(stack_name, result.changeset_type)
Expand Down
5 changes: 3 additions & 2 deletions sammy/custom_properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from valley.mixins import ListMixin
from valley.properties import BaseProperty, MultiProperty
from valley.utils.json_utils import ValleyEncoder
from valley.validators import ForeignListValidator, StringValidator
from valley.validators import ForeignListValidator, StringValidator, ForeignValidator


class ForeignSubclassListValidator(ForeignListValidator):
Expand All @@ -19,6 +19,7 @@ def validate(self, value, key):
)



class ForeignSubclassListMixin(ListMixin):

def get_validators(self):
Expand Down Expand Up @@ -53,7 +54,7 @@ class CharForeignProperty(MultiProperty):
def __init__(self,foreign_class,**kwargs):

super(CharForeignProperty, self).__init__(
validators=[ForeignSubclassListValidator(foreign_class),
validators=[ForeignValidator(foreign_class),
StringValidator()],**kwargs)


6 changes: 3 additions & 3 deletions sammy/examples/alexa_skill.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@

sam.add_resource(sm.Function(
name='AlexaSkillFunction',
CodeUri='s3://<bucket>/alexa_skill.zip',
Handler='index.handler',
Runtime='nodejs4.3',
CodeUri=sm.S3URI(Bucket='<bucket>',Key='sammytest.zip'),
Handler='sample.handler',
Runtime='python3.6',
Events=[sm.AlexaSkillEvent(name='AlexaSkillEvent')]
))
18 changes: 9 additions & 9 deletions sammy/examples/api_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,31 @@

sam.add_resource(sm.Function(
name='GetFunction',
CodeUri='s3://<bucket>/api_backend.zip',
CodeUri=sm.S3URI(Bucket='<bucket>',Key='sammytest.zip'),
Handler='index.get',
Runtime='nodejs6.10',
Runtime='python3.6',
Policies='AmazonDynamoDBReadOnlyAccess',
Environment=sm.Environment(Variables={'TABLE_NAME':'!Ref Table'}),
Environment=sm.Environment(Variables={'TABLE_NAME':sm.Ref(Ref='Table')}),
Events=[sm.APIEvent(name='GetResource',Path='/resource/{resourceId}',Method='get')]
))

sam.add_resource(sm.Function(
name='PutFunction',
Handler='index.put',
Runtime='nodejs6.10',
CodeUri='s3://<bucket>/api_backend.zip',
Runtime='python3.6',
CodeUri=sm.S3URI(Bucket='<bucket>',Key='sammytest.zip'),
Policies='AmazonDynamoDBFullAccess',
Environment=sm.Environment(Variables={'TABLE_NAME':'!Ref Table'}),
Environment=sm.Environment(Variables={'TABLE_NAME':sm.Ref(Ref='Table')}),
Events=[sm.APIEvent(name='PutResource',Path='/resource/{resourceId}',Method='put')]
))

sam.add_resource(sm.Function(
name='DeleteFunction',
Handler='index.delete',
Runtime='nodejs6.10',
CodeUri='s3://<bucket>/api_backend.zip',
Runtime='python3.6',
CodeUri=sm.S3URI(Bucket='<bucket>',Key='sammytest.zip'),
Policies='AmazonDynamoDBFullAccess',
Environment=sm.Environment(Variables={'TABLE_NAME':'!Ref Table'}),
Environment=sm.Environment(Variables={'TABLE_NAME':sm.Ref(Ref='Table')}),
Events=[sm.APIEvent(name='DeleteResource',Path='/resource/{resourceId}',Method='delete')]
))

Expand Down
6 changes: 3 additions & 3 deletions sammy/examples/hello_world.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import sammy as sm


sam = sm.SAM(Description='A hello world application.')
sam = sm.SAM(Description='A hello world application.',render_type='yaml')

sam.add_parameter(sm.Parameter(name='Bucket',Type='String'))

sam.add_parameter(sm.Parameter(name='CodeZipKey',Type='String'))

sam.add_resource(
sm.Function(name='HelloWorldFunction',
Handler='index.handler', Runtime='nodejs4.3', CodeURI=sm.CodeURI(
Bucket='!Bucket',Key='!CodeZipKey')))
Handler='sample.handler', Runtime='python3.6', CodeUri=sm.S3URI(
Bucket=sm.Ref(Ref='Bucket'),Key=sm.Ref(Ref='CodeZipKey'))))
Loading

0 comments on commit 975dbee

Please sign in to comment.