From 50b2aa7ed4cba38032c396e10b70e1b9d8be59e2 Mon Sep 17 00:00:00 2001 From: Mitch Garnaat Date: Tue, 28 Apr 2015 05:49:51 -0700 Subject: [PATCH] Updating samples and fixing some bugs found in the process. --- kappa/context.py | 4 --- kappa/event_source.py | 2 +- kappa/policy.py | 39 ++++++++++++++------- samples/kinesis/config.yml | 13 +++++-- samples/s3/config.yml | 15 +++++--- samples/s3/examplefolder/CreateThumbnail.js | 4 ++- samples/sns/config.yml | 3 ++ samples/sns/input.json | 21 +++++++++++ 8 files changed, 76 insertions(+), 25 deletions(-) create mode 100644 samples/sns/input.json diff --git a/kappa/context.py b/kappa/context.py index 9a0985a..f25db6e 100644 --- a/kappa/context.py +++ b/kappa/context.py @@ -57,10 +57,6 @@ def profile(self): def region(self): return self.config.get('region', None) - @property - def cfn_config(self): - return self.config.get('cloudformation', None) - @property def lambda_config(self): return self.config.get('lambda', None) diff --git a/kappa/event_source.py b/kappa/event_source.py index 45620f6..9ff7e47 100644 --- a/kappa/event_source.py +++ b/kappa/event_source.py @@ -213,4 +213,4 @@ def remove(self, function): def status(self, function): LOG.debug('status for SNS notification for %s', function.name) - return self.exist(function) + return self.exists(function) diff --git a/kappa/policy.py b/kappa/policy.py index 69856e5..057f3a9 100644 --- a/kappa/policy.py +++ b/kappa/policy.py @@ -20,8 +20,6 @@ class Policy(object): - Path = '/kappa/' - def __init__(self, context, config): self._context = context self._config = config @@ -39,7 +37,11 @@ def description(self): @property def document(self): - return self._config['document'] + return self._config.get('document', None) + + @property + def path(self): + return self._config.get('path', '/kappa/') @property def arn(self): @@ -49,25 +51,36 @@ def arn(self): self._arn = policy.get('Arn', None) return self._arn - def exists(self): + def _find_all_policies(self): + # boto3 does not currently do pagination for ListPolicies + # so we have to do it ourselves + policies = [] try: - response = self._iam_svc.list_policies(PathPrefix=self.Path) - LOG.debug(response) - for policy in response['Policies']: - if policy['PolicyName'] == self.name: - return policy + response = self._iam_svc.list_policies() + policies += response['Policies'] + while response['IsTruncated']: + LOG.debug('getting another page of policies') + response = self._iam_svc.list_policies( + Marker=response['Marker']) + policies += response['Policies'] except Exception: LOG.exception('Error listing policies') + return policies + + def exists(self): + for policy in self._find_all_policies(): + if policy['PolicyName'] == self.name: + return policy return None def create(self): LOG.debug('creating policy %s', self.name) policy = self.exists() - if not policy: + if not policy and self.document: with open(self.document, 'rb') as fp: try: response = self._iam_svc.create_policy( - Path=self.Path, PolicyName=self.name, + Path=self.path, PolicyName=self.name, PolicyDocument=fp.read(), Description=self.description) LOG.debug(response) @@ -76,7 +89,9 @@ def create(self): def delete(self): response = None - if self.arn: + # Only delete the policy if it has a document associated with it. + # This indicates that it was a custom policy created by kappa. + if self.arn and self.document: LOG.debug('deleting policy %s', self.name) response = self._iam_svc.delete_policy(PolicyArn=self.arn) LOG.debug(response) diff --git a/samples/kinesis/config.yml b/samples/kinesis/config.yml index edca66e..3113dde 100644 --- a/samples/kinesis/config.yml +++ b/samples/kinesis/config.yml @@ -1,9 +1,16 @@ --- +# Change the profile and region to suit your application profile: personal region: us-east-1 iam: - role_name: KinesisSampleRole - role_policy: AWSLambdaKinesisExecutionRole + # In this case, we are using an existing managed policy so we just + # need to put the name of that policy here. + policy: + name: AWSLambdaKinesisExecutionRole + # The name of the IAM role used for executing the Lambda function. + # The policy listed above will be attached to this role once it is created. + role: + name: KinesisSampleRole lambda: name: KinesisSample zipfile_name: KinesisSample.zip @@ -15,6 +22,8 @@ lambda: timeout: 3 event_sources: - + # You need to change this arn to point to your own kinesis + # stream that you have created separately. arn: arn:aws:kinesis:us-east-1:084307701560:stream/lambdastream starting_position: TRIM_HORIZON batch_size: 100 diff --git a/samples/s3/config.yml b/samples/s3/config.yml index ee52571..fe64e34 100644 --- a/samples/s3/config.yml +++ b/samples/s3/config.yml @@ -1,11 +1,16 @@ --- +# Change profile and region to suit your application profile: personal region: us-east-1 -cloudformation: - template: roles.cf - stack_name: TestS3 - exec_role: ExecRole - invoke_role: InvokeRole +iam: + # In this case, we are using an existing managed policy so we just + # need to put the name of that policy here. + policy: + name: AWSLambdaExecute + # The name of the IAM role used for executing the Lambda function. + # The policy listed above will be attached to this role once it is created. + role: + name: KappaS3SampleRole lambda: name: S3Sample zipfile_name: S3Sample.zip diff --git a/samples/s3/examplefolder/CreateThumbnail.js b/samples/s3/examplefolder/CreateThumbnail.js index 5bfbc1d..cfb198f 100644 --- a/samples/s3/examplefolder/CreateThumbnail.js +++ b/samples/s3/examplefolder/CreateThumbnail.js @@ -16,7 +16,9 @@ exports.handler = function(event, context) { // Read options from the event. console.log("Reading options from event:\n", util.inspect(event, {depth: 5})); var srcBucket = event.Records[0].s3.bucket.name; - var srcKey = event.Records[0].s3.object.key; + // Object key may have spaces or unicode non-ASCII characters. + var srcKey = + decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, " ")); var dstBucket = srcBucket + "resized"; var dstKey = "resized-" + srcKey; diff --git a/samples/sns/config.yml b/samples/sns/config.yml index ee3648d..3a5d427 100644 --- a/samples/sns/config.yml +++ b/samples/sns/config.yml @@ -1,4 +1,5 @@ --- +# change profile and region to suit your needs profile: personal region: us-east-1 resources: resources.json @@ -24,9 +25,11 @@ lambda: statement_id: sns_invoke action: lambda:invokeFunction principal: sns.amazonaws.com + # change this to refer to your own SNS topic source_arn: arn:aws:sns:us-east-1:084307701560:lambda_topic event_sources: - + # change this to refer to your own SNS topic arn: arn:aws:sns:us-east-1:084307701560:lambda_topic test_data: input.json \ No newline at end of file diff --git a/samples/sns/input.json b/samples/sns/input.json new file mode 100644 index 0000000..6872de3 --- /dev/null +++ b/samples/sns/input.json @@ -0,0 +1,21 @@ +{ + "Records":[ + { + "EventSource":"aws:sns", + "EventVersion": "1.0", + "EventSubscriptionArn": "arn:aws:sns:us-east-1:123456789012:lambda_topic:0b6941c3-f04d-4d3e-a66d-b1df00e1e381", + "Sns":{ + "Type" : "Notification", + "MessageId" : "e70fa8dd-0d77-5944-8862-e569494b48b5", + "TopicArn" : "arn:aws:sns:us-east-1:658794617753:lambda-chat", + "Message" : "{\"name\":\"Mitch Garnaat\",\"message\":\"just testing this out\"}", + "Timestamp" : "2015-04-24T13:15:40.632Z", + "Channel" : "foo", + "SignatureVersion" : "1", + "Signature" : "n0zU4mvKQT5vy6RbDK3BoiWQrFBirbaIGRQOVXE4Vx1XE0SrsXBo4mPm2eDMgjFboP0RJxRCvkFpN07mbnVOIoT2UWKVD2hU1vLdTlEPE4ppSSx17KzhABsOuA8XwijL3hm4cpVHmCmhNXcKekC+fGCryjf9cxr6ODm45PxxE4WLSak85uLzgWhfbAEgPqD2Q/Fa3NwJIyBkZWEdlpJCeaZb4gCzPauvcynRyzWS+e+76WpXMgInCU2y7lhtajDpHrDlZ13UvHOWAQONFRGJXsxFeP370tnzVKfdfMPNbmr4gb3dk+VP0+PsyrIakqp31cO5umUZwSeVZaXLQLewmg==", + "SigningCertURL" : "https://sns.us-east-1.amazonaws.com/SimpleNotificationService-d6d679a1d18e95c2f9ffcf11f4f9e198.pem", + "UnsubscribeURL" : "https://sns.us-east-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-1:658794617753:lambda-chat:f1bde0aa-11eb-4417-a9cf-6a00c6aac0a7" + } + } + ] +}