Jose Diaz-Gonzalez
Committed by GitHub

Merge pull request #66 from josegonzalez/packaging

Packaging Improvements
......@@ -4,8 +4,8 @@ python:
- "3.3"
- "3.4"
- "3.5"
cache: pip
install:
- pip install -r requirements.txt
- pip install coverage python-coveralls
- pip install -r requirements-dev.txt
script: nosetests tests/unit --cover-erase --with-coverage --cover-package kappa
after_success: coveralls
......
include README.md
include LICENSE
include requirements.txt
include kappa/_version
recursive-include samples *.js *.py *.yml *.cf *.json *.txt
......
=====
kappa
=====
[![Build Status](https://travis-ci.org/garnaat/kappa.svg?branch=develop)](https://travis-ci.org/garnaat/kappa)
.. image:: https://travis-ci.org/garnaat/kappa.svg?branch=develop
:target: https://travis-ci.org/garnaat/kappa
[![Code Health](https://landscape.io/github/garnaat/kappa/develop/landscape.svg)](https://landscape.io/github/garnaat/kappa/develop)
.. image:: https://landscape.io/github/garnaat/kappa/develop/landscape.svg
:target: https://landscape.io/github/garnaat/kappa/develop
**Kappa** is a command line tool that (hopefully) makes it easier to
deploy, update, and test functions for AWS Lambda.
......@@ -12,10 +15,8 @@ There are quite a few steps involved in developing a Lambda function.
You have to:
* Write the function itself
* Create the IAM role required by the Lambda function itself (the executing
role) to allow it access to any resources it needs to do its job
* Add additional permissions to the Lambda function if it is going to be used
in a Push model (e.g. S3, SNS) rather than a Pull model.
* Create the IAM role required by the Lambda function itself (the executing role) to allow it access to any resources it needs to do its job
* Add additional permissions to the Lambda function if it is going to be used in a Push model (e.g. S3, SNS) rather than a Pull model.
* Zip the function and any dependencies and upload it to AWS Lambda
* Test the function with mock data
* Retrieve the output of the function from CloudWatch Logs
......@@ -34,19 +35,19 @@ If you need to make changes, kappa will allow you to easily update your Lambda
function with new code or update your event sources as needed.
Installation
------------
============
The quickest way to get kappa is to install the latest stable version via pip:
The quickest way to get kappa is to install the latest stable version via pip::
pip install kappa
Or for the development version:
Or for the development version::
pip install git+https://github.com/garnaat/kappa.git
Quick Start
-----------
===========
To get a feel for how kappa works, let's take a look at a very simple example
contained in the ``samples/simple`` directory of the kappa distribution. This
......@@ -54,61 +55,61 @@ example is so simple, in fact, that it doesn't really do anything. It's just a
small Lambda function (written in Python) that accepts some JSON input, logs
that input to CloudWatch logs, and returns a JSON document back.
The structure of the directory is:
The structure of the directory is::
```
simple/
├── _src
│   ├── README.md
│   ├── requirements.txt
│   ├── setup.cfg
│   └── simple.py
├── _tests
│   └── test_one.json
└── kappa.yml.sample
```
simple/
├── _src
│   ├── README.md
│   ├── requirements.txt
│   ├── setup.cfg
│   └── simple.py
├── _tests
│   └── test_one.json
└── kappa.yml.sample
Within the directory we see:
* `kappa.yml.sample` which is a sample YAML configuration file for the project
* `_src` which is a directory containing the source code for the Lambda function
* `_test` which is a directory containing some test data
* ``kappa.yml.sample`` which is a sample YAML configuration file for the project
* ``_src`` which is a directory containing the source code for the Lambda function
* ``_test`` which is a directory containing some test data
The first step is to make a copy of the sample configuration file:
$ cd simple
$ cp kappa.yml.sample kappa.yml
.. code-block:: bash
cd simple
cp kappa.yml.sample kappa.yml
Now you will need to edit ``kappa.yml`` slightly for your use. The file looks
like this:
```
---
name: kappa-simple
environments:
dev:
profile: <your profile here>
region: <your region here>
policy:
resources:
- arn: arn:aws:logs:*:*:*
actions:
- "*"
prod:
profile: <your profile here>
region: <your region here>
policy:
resources:
- arn: arn:aws:logs:*:*:*
actions:
- "*"
lambda:
description: A very simple Kappa example
handler: simple.handler
runtime: python2.7
memory_size: 128
timeout: 3
```
.. code-block:: yaml
---
name: kappa-simple
environments:
dev:
profile: <your profile here>
region: <your region here>
policy:
resources:
- arn: arn:aws:logs:*:*:*
actions:
- "*"
prod:
profile: <your profile here>
region: <your region here>
policy:
resources:
- arn: arn:aws:logs:*:*:*
actions:
- "*"
lambda:
description: A very simple Kappa example
handler: simple.handler
runtime: python2.7
memory_size: 128
timeout: 3
The ``name`` at the top is just a name used for this Lambda function and other
things we create that are related to this Lambda function (e.g. roles,
......@@ -123,12 +124,14 @@ section also includes a ``policy`` section. This is where we tell kappa about
AWS resources that our Lambda function needs access to and what kind of access
it requires. For example, your Lambda function may need to read from an SNS
topic or write to a DynamoDB table and this is where you would provide the ARN
([Amazon Resource Name](http://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html))
(`Amazon Resource Name`_)
that identify those resources. Since this is a very simple example, the only
resource listed here is for CloudWatch logs so that our Lambda function is able
to write to the CloudWatch log group that will be created for it automatically
by AWS Lambda.
.. _`Amazon Resource Name`: http://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html
The ``lambda`` section contains the configuration information about our Lambda
function. These values are passed to Lambda when we create the function and
can be updated at any time after.
......@@ -142,28 +145,27 @@ typing.
Once you have made the necessary modifications, you should be ready to deploy
your Lambda function to the AWS Lambda service. To do so, just do this:
```
$ kappa deploy
```
.. code-block:: bash
kappa deploy
This assumes you want to deploy the default environment called ``dev`` and that
you have named your config file ``kappa.yml``. If, instead, you called your
environment ``test`` and named your config file foo.yml, you would do this:
```
$ kappa --env test --config foo.yml deploy
```
.. code-block:: bash
kappa --env test --config foo.yml deploy
In either case, you should see output that looks something like this:
```
$ kappa deploy
deploying
...deploying policy kappa-simple-dev
...creating function kappa-simple-dev
done
$
```
.. code-block:: bash
kappa deploy
# deploying
# ...deploying policy kappa-simple-dev
# ...creating function kappa-simple-dev
# done
So, what kappa has done is it has created a new Managed Policy called
``kappa-simple-dev`` that grants access to the CloudWatch Logs service. It has
......@@ -173,19 +175,18 @@ Lambda called kappa-simple-dev.
To test this out, try this:
```
$ kappa invoke _tests/test_one.json
invoking
START RequestId: 0f2f9ecf-9df7-11e5-ae87-858fbfb8e85f Version: $LATEST
[DEBUG] 2015-12-08T22:00:15.363Z 0f2f9ecf-9df7-11e5-ae87-858fbfb8e85f {u'foo': u'bar', u'fie': u'baz'}
END RequestId: 0f2f9ecf-9df7-11e5-ae87-858fbfb8e85f
REPORT RequestId: 0f2f9ecf-9df7-11e5-ae87-858fbfb8e85f Duration: 0.40 ms Billed Duration: 100 ms Memory Size: 256 MB Max Memory Used: 23 MB
.. code-block:: bash
Response:
{"status": "success"}
done
$
```
kappa invoke _tests/test_one.json
# invoking
# START RequestId: 0f2f9ecf-9df7-11e5-ae87-858fbfb8e85f Version: $LATEST
# [DEBUG] 2015-12-08T22:00:15.363Z 0f2f9ecf-9df7-11e5-ae87-858fbfb8e85f {u'foo': u'bar', u'fie': u'baz'}
# END RequestId: 0f2f9ecf-9df7-11e5-ae87-858fbfb8e85f
# REPORT RequestId: 0f2f9ecf-9df7-11e5-ae87-858fbfb8e85f Duration: 0.40 ms Billed Duration: 100 ms Memory Size: 256 MB Max Memory Used: 23 MB
#
# Response:
# {"status": "success"}
# done
We have just called our Lambda function, passing in the contents of the file
``_tests/test_one.json`` as input to our function. We can see the output of
......@@ -198,7 +199,9 @@ Need to make a change in your function, your list of resources, or your
function configuration? Just go ahead and make the change and then re-run the
``deploy`` command:
$ kappa deploy
.. code-block:: bash
kappa deploy
Kappa will figure out what has changed and make the necessary updates for you.
......@@ -206,34 +209,34 @@ That gives you a quick overview of kappa. To learn more about it, I recommend
you check out the tutorial.
Policies
--------
========
Hands up who loves writing IAM policies. Yeah, that's what I thought. With
Kappa, there is a simplified way of writing policies and granting your Lambda
function the permissions it needs.
The simplified version allows you to specify, in your `kappa.yml` file, the
The simplified version allows you to specify, in your ``kappa.yml`` file, the
ARN of the resource you want to access, and then a list of the API methods you
want to allow. For example:
```
policy:
resources:
- arn: arn:aws:logs:*:*:*
actions:
- "*"
```
.. code-block:: yaml
policy:
resources:
- arn: arn:aws:logs:*:*:*
actions:
- "*"
To express this using the official IAM policy format, you can instead use a
statement:
```
policy:
statements:
- Effect: Allow
Resource: "*"
Action:
- "logs:*"
```
.. code-block:: yaml
policy:
statements:
- Effect: Allow
Resource: "*"
Action:
- "logs:*"
Both of these do the same thing.
......
......@@ -12,19 +12,23 @@
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys
import os
import shlex
import sys
assert os
assert shlex
assert sys
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))
# sys.path.insert(0, os.path.abspath('.'))
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'
# needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
......@@ -42,7 +46,7 @@ templates_path = ['_templates']
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
......@@ -70,9 +74,9 @@ language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
......@@ -80,27 +84,27 @@ exclude_patterns = ['_build']
# The reST default role (used for this markup: `text`) to use for all
# documents.
#default_role = None
# default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# modindex_common_prefix = []
# If true, keep warnings as "system message" paragraphs in the built documents.
#keep_warnings = False
# keep_warnings = False
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = False
......@@ -115,26 +119,26 @@ html_theme = 'alabaster'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
# html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
# html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
......@@ -144,62 +148,62 @@ html_static_path = ['_static']
# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.
#html_extra_path = []
# html_extra_path = []
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# html_additional_pages = {}
# If false, no module index is generated.
#html_domain_indices = True
# html_domain_indices = True
# If false, no index is generated.
#html_use_index = True
# html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
# html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# html_file_suffix = None
# Language to be used for generating the HTML full-text search index.
# Sphinx supports the following languages:
# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr'
#html_search_language = 'en'
# html_search_language = 'en'
# A dictionary with options for the search language support, empty by default.
# Now only 'ja' uses this config value
#html_search_options = {'type': 'default'}
# html_search_options = {'type': 'default'}
# The name of a javascript file (relative to the configuration directory) that
# implements a search results scorer. If empty, the default will be used.
#html_search_scorer = 'scorer.js'
# html_search_scorer = 'scorer.js'
# Output file base name for HTML help builder.
htmlhelp_basename = 'kappadoc'
......@@ -207,46 +211,46 @@ htmlhelp_basename = 'kappadoc'
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# The paper size ('letterpaper' or 'a4paper').
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
# The font size ('10pt', '11pt' or '12pt').
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
# Additional stuff for the LaTeX preamble.
# 'preamble': '',
# Latex figure (float) alignment
#'figure_align': 'htbp',
# Latex figure (float) alignment
# 'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'kappa.tex', u'kappa Documentation',
u'Mitch Garnaat', 'manual'),
(master_doc, 'kappa.tex', u'kappa Documentation',
u'Mitch Garnaat', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# latex_show_urls = False
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# latex_domain_indices = True
# -- Options for manual page output ---------------------------------------
......@@ -259,7 +263,7 @@ man_pages = [
]
# If true, show URL addresses after external links.
#man_show_urls = False
# man_show_urls = False
# -- Options for Texinfo output -------------------------------------------
......@@ -268,19 +272,19 @@ man_pages = [
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'kappa', u'kappa Documentation',
author, 'kappa', 'One line description of project.',
'Miscellaneous'),
(master_doc, 'kappa', u'kappa Documentation',
author, 'kappa', 'One line description of project.',
'Miscellaneous'),
]
# Documents to append as an appendix to all manuals.
#texinfo_appendices = []
# texinfo_appendices = []
# If false, no module index is generated.
#texinfo_domain_indices = True
# texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'
# texinfo_show_urls = 'footnote'
# If true, do not generate a @detailmenu in the "Top" node's menu.
#texinfo_no_detailmenu = False
# texinfo_no_detailmenu = False
......
......@@ -12,6 +12,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import os
__version__ = open(os.path.join(os.path.dirname(__file__), '_version')).read()
__version__ = '0.3.1'
......
0.3.1
\ No newline at end of file
......@@ -190,10 +190,12 @@ class Context(object):
def list_event_sources(self):
event_sources = []
for event_source in self.event_sources:
event_sources.append({'arn': event_source.arn,
'starting_position': event_source.starting_position,
'batch_size': event_source.batch_size,
'enabled': event_source.enabled})
event_sources.append({
'arn': event_source.arn,
'starting_position': event_source.starting_position,
'batch_size': event_source.batch_size,
'enabled': event_source.enabled
})
return event_sources
def enable_event_sources(self):
......
......@@ -224,10 +224,12 @@ class Function(object):
excluded_dirs.append(subdir)
for excluded in excluded_dirs:
subdirs.remove(excluded)
try:
dir_path = os.path.relpath(root, relroot)
dir_path = os.path.normpath(os.path.splitdrive(dir_path)[1])
dir_path = os.path.normpath(
os.path.splitdrive(dir_path)[1]
)
while dir_path[0] in (os.sep, os.altsep):
dir_path = dir_path[1:]
dir_path += '/'
......@@ -251,7 +253,7 @@ class Function(object):
LOG.debug('zipfile_name=%s', zipfile_name)
with zipfile.ZipFile(zipfile_name, 'a',
compression=zipfile.ZIP_DEFLATED) as zf:
try:
try:
zf.getinfo(lambda_file)
except KeyError:
zf.write(lambda_file)
......
......@@ -53,17 +53,17 @@ class Log(object):
LOG.info(
'log group %s has not been created yet', self.log_group_name)
return []
latest_stream = None
latest = None
streams = self.streams()
for stream in streams:
if not latest_stream:
latest_stream = stream
elif stream['lastEventTimestamp'] > latest_stream['lastEventTimestamp']:
latest_stream = stream
if not latest:
latest = stream
elif stream['lastEventTimestamp'] > latest['lastEventTimestamp']:
latest = stream
response = self._log_client.call(
'get_log_events',
logGroupName=self.log_group_name,
logStreamName=latest_stream['logStreamName'])
logStreamName=latest['logStreamName'])
LOG.debug(response)
return response['events']
......
......@@ -88,7 +88,7 @@ def tail(ctx):
"""Show the last 10 lines of the log file"""
click.echo('tailing logs')
for e in ctx.tail()[-10:]:
ts = datetime.utcfromtimestamp(e['timestamp']//1000).isoformat()
ts = datetime.utcfromtimestamp(e['timestamp'] // 1000).isoformat()
click.echo("{}: {}".format(ts, e['message']))
click.echo('done')
......
#!/usr/bin/env bash
set -eo pipefail; [[ $RELEASE_TRACE ]] && set -x
PACKAGE_NAME='kappa'
INIT_PACKAGE_NAME='kappa'
PUBLIC="true"
# Colors
COLOR_OFF="\033[0m" # unsets color to term fg color
RED="\033[0;31m" # red
GREEN="\033[0;32m" # green
YELLOW="\033[0;33m" # yellow
MAGENTA="\033[0;35m" # magenta
CYAN="\033[0;36m" # cyan
# ensure wheel is available
pip install wheel > /dev/null
# ensure Pygment is available
pip install Pygments > /dev/null
command -v gitchangelog >/dev/null 2>&1 || {
echo -e "${RED}WARNING: Missing gitchangelog binary, please run: pip install gitchangelog==2.2.0${COLOR_OFF}\n"
exit 1
}
command -v rst-lint > /dev/null || {
echo -e "${RED}WARNING: Missing rst-lint binary, please run: pip install restructuredtext_lint${COLOR_OFF}\n"
exit 1
}
if [[ "$@" != "major" ]] && [[ "$@" != "minor" ]] && [[ "$@" != "patch" ]]; then
echo -e "${RED}WARNING: Invalid release type, must specify 'major', 'minor', or 'patch'${COLOR_OFF}\n"
exit 1
fi
echo -e "\n${GREEN}STARTING RELEASE PROCESS${COLOR_OFF}\n"
set +e;
git status | grep "working directory clean" &> /dev/null
if [ ! $? -eq 0 ]; then # working directory is NOT clean
echo -e "${RED}WARNING: You have uncomitted changes, you may have forgotten something${COLOR_OFF}\n"
exit 1
fi
set -e;
echo -e "${YELLOW}--->${COLOR_OFF} Updating local copy"
git pull -q origin master
git fetch --tags > /dev/null
echo -e "${YELLOW}--->${COLOR_OFF} Retrieving release versions"
current_version=$(cat ${INIT_PACKAGE_NAME}/__init__.py |grep '__version__ ='|sed 's/[^0-9.]//g')
major=$(echo $current_version | awk '{split($0,a,"."); print a[1]}')
minor=$(echo $current_version | awk '{split($0,a,"."); print a[2]}')
patch=$(echo $current_version | awk '{split($0,a,"."); print a[3]}')
if [[ "$@" == "major" ]]; then
major=$(($major + 1));
minor="0"
patch="0"
elif [[ "$@" == "minor" ]]; then
minor=$(($minor + 1));
patch="0"
elif [[ "$@" == "patch" ]]; then
patch=$(($patch + 1));
fi
next_version="${major}.${minor}.${patch}"
echo -e "${YELLOW} >${COLOR_OFF} ${MAGENTA}${current_version}${COLOR_OFF} -> ${MAGENTA}${next_version}${COLOR_OFF}"
echo -e "${YELLOW}--->${COLOR_OFF} Ensuring readme passes lint checks (if this fails, run rst-lint)"
rst-lint README.rst > /dev/null
echo -e "${YELLOW}--->${COLOR_OFF} Creating necessary temp file"
tempfoo=$(basename $0)
TMPFILE=$(mktemp /tmp/${tempfoo}.XXXXXX) || {
echo -e "${RED}WARNING: Cannot create temp file using mktemp in /tmp dir ${COLOR_OFF}\n"
exit 1
}
find_this="__version__ = '$current_version'"
replace_with="__version__ = '$next_version'"
echo -e "${YELLOW}--->${COLOR_OFF} Updating ${INIT_PACKAGE_NAME}/__init__.py"
sed "s/$find_this/$replace_with/" ${INIT_PACKAGE_NAME}/__init__.py > $TMPFILE && mv $TMPFILE ${INIT_PACKAGE_NAME}/__init__.py
echo -e "${YELLOW}--->${COLOR_OFF} Updating README.rst"
find_this="${PACKAGE_NAME}.git@$current_version"
replace_with="${PACKAGE_NAME}.git@$next_version"
sed "s/$find_this/$replace_with/" README.rst > $TMPFILE && mv $TMPFILE README.rst
find_this="${PACKAGE_NAME}==$current_version"
replace_with="${PACKAGE_NAME}==$next_version"
sed "s/$find_this/$replace_with/" README.rst > $TMPFILE && mv $TMPFILE README.rst
if [ -f docs/conf.py ]; then
echo -e "${YELLOW}--->${COLOR_OFF} Updating docs"
find_this="version = '${current_version}'"
replace_with="version = '${next_version}'"
sed "s/$find_this/$replace_with/" docs/conf.py > $TMPFILE && mv $TMPFILE docs/conf.py
find_this="release = '${current_version}'"
replace_with="release = '${next_version}'"
sed "s/$find_this/$replace_with/" docs/conf.py > $TMPFILE && mv $TMPFILE docs/conf.py
fi
echo -e "${YELLOW}--->${COLOR_OFF} Updating CHANGES.rst for new release"
version_header="$next_version ($(date +%F))"
set +e; dashes=$(yes '-'|head -n ${#version_header}|tr -d '\n') ; set -e
gitchangelog |sed "4s/.*/$version_header/"|sed "5s/.*/$dashes/" > $TMPFILE && mv $TMPFILE CHANGES.rst
echo -e "${YELLOW}--->${COLOR_OFF} Adding changed files to git"
git add CHANGES.rst README.rst ${INIT_PACKAGE_NAME}/__init__.py
if [ -f docs/conf.py ]; then git add docs/conf.py; fi
echo -e "${YELLOW}--->${COLOR_OFF} Creating release"
git commit -q -m "Release version $next_version"
echo -e "${YELLOW}--->${COLOR_OFF} Tagging release"
git tag -a $next_version -m "Release version $next_version"
echo -e "${YELLOW}--->${COLOR_OFF} Pushing release and tags to github"
git push -q origin master && git push -q --tags
if [[ "$PUBLIC" == "true" ]]; then
echo -e "${YELLOW}--->${COLOR_OFF} Creating python release"
cp README.rst README
python setup.py sdist bdist_wheel upload > /dev/null
rm README
else
echo -e "${YELLOW}--->${COLOR_OFF} Creating local python dist and wheel for manual release"
python setup.py sdist bdist_wheel > /dev/null
fi
echo -e "\n${CYAN}RELEASED VERSION ${next_version}${COLOR_OFF}\n"
-r requirements.txt
coverage==4.1
mock>=1.0.1
nose==1.3.1
python-coveralls==2.7.0
requests==2.10.0
sh==1.11
tox==1.7.1
PyYAML>=3.11
boto3>=1.2.3
click>=5.1
placebo>=0.8.1
click==5.1
PyYAML>=3.11
mock>=1.0.1
nose==1.3.1
tox==1.7.1
......
......@@ -21,6 +21,7 @@ def foobar():
def _get(event, context):
assert context
customer_id = event.get('id')
if customer_id is None:
raise Exception('No id provided for GET operation')
......@@ -32,6 +33,7 @@ def _get(event, context):
def _post(event, context):
assert context
item = event['json_body']
if item is None:
raise Exception('No json_body found in event')
......@@ -41,6 +43,7 @@ def _post(event, context):
def _put(event, context):
assert context
data = _get(event, context)
id_ = data.get('id')
data.update(event['json_body'])
......@@ -51,6 +54,7 @@ def _put(event, context):
def handler(event, context):
assert context
LOG.info(event)
http_method = event.get('http_method')
if not http_method:
......
......@@ -5,5 +5,6 @@ LOG.setLevel(logging.DEBUG)
def handler(event, context):
assert context
LOG.debug(event)
return {'status': 'success'}
......
......@@ -6,6 +6,7 @@ LOG.setLevel(logging.INFO)
def handler(event, context):
assert context
for record in event['Records']:
start_time = record['Sns']['Timestamp']
LOG.info('start_time: %s', start_time)
......
#!/usr/bin/env python
from setuptools import setup, find_packages
from kappa import __version__
import os
requires = [
'boto3>=1.2.2',
'placebo>=0.4.1',
'click>=5.0',
'PyYAML>=3.11'
]
try:
from setuptools import setup
except ImportError:
from distutils.core import setup
def open_file(fname):
return open(os.path.join(os.path.dirname(__file__), fname))
def run_setup():
setup(
name='kappa',
version=__version__,
description='A CLI tool for AWS Lambda developers',
long_description=open_file('README.rst').read(),
url='https://github.com/garnaat/kappa',
author='Mitch Garnaat',
author_email='mitch@garnaat.com',
license='Apache License 2.0',
packages=['kappa', 'kappa.scripts'],
package_data={'kappa': ['_version']},
package_dir={'kappa': 'kappa'},
entry_points="""
[console_scripts]
kappa=kappa.scripts.cli:cli
""",
install_requires=open_file('requirements.txt').readlines(),
test_suite='tests',
include_package_data=True,
zip_safe=True,
classifiers=(
'Development Status :: 3 - Alpha',
'Intended Audience :: Developers',
'Intended Audience :: System Administrators',
'Natural Language :: English',
'License :: OSI Approved :: Apache Software License',
'Programming Language :: Python',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5'
),
)
setup(
name='kappa',
version=open(os.path.join('kappa', '_version')).read().strip(),
description='A CLI tool for AWS Lambda developers',
long_description=open('README.md').read(),
author='Mitch Garnaat',
author_email='mitch@garnaat.com',
url='https://github.com/garnaat/kappa',
packages=find_packages(exclude=['tests*']),
package_data={'kappa': ['_version']},
package_dir={'kappa': 'kappa'},
entry_points="""
[console_scripts]
kappa=kappa.scripts.cli:cli
""",
install_requires=requires,
license=open("LICENSE").read(),
classifiers=(
'Development Status :: 3 - Alpha',
'Intended Audience :: Developers',
'Intended Audience :: System Administrators',
'Natural Language :: English',
'License :: OSI Approved :: Apache Software License',
'Programming Language :: Python',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5'
),
)
if __name__ == '__main__':
run_setup()
......