Toggle navigation
Toggle navigation
This project
Loading...
Sign in
서승완
/
kappa
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Graphs
Network
Create a new issue
Commits
Issue Boards
Authored by
Mitch Garnaat
2015-11-06 20:03:47 -0500
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
0718d025caa28a068362b2b3108feda67fdc61a6
0718d025
1 parent
75651bf1
Add the ability to generate the config files based on the environment specified.
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
94 additions
and
49 deletions
kappa/context.py
kappa/function.py
kappa/policy.py
kappa/scripts/cli.py
kappa/context.py
View file @
0718d02
...
...
@@ -25,12 +25,13 @@ import kappa.role
LOG
=
logging
.
getLogger
(
__name__
)
DebugFmtString
=
'
%(asctime)
s -
%(name)
s -
%(levelname)
s -
%(message)
s'
InfoFmtString
=
'
\t
%(message)
s'
InfoFmtString
=
'
...
%(message)
s'
class
Context
(
object
):
def
__init__
(
self
,
config_file
,
environment
=
None
,
debug
=
False
):
def
__init__
(
self
,
config_file
,
environment
=
None
,
debug
=
False
,
force
=
False
):
if
debug
:
self
.
set_logger
(
'kappa'
,
logging
.
DEBUG
)
else
:
...
...
@@ -38,6 +39,7 @@ class Context(object):
self
.
_load_cache
()
self
.
config
=
yaml
.
load
(
config_file
)
self
.
environment
=
environment
self
.
force
=
force
self
.
policy
=
kappa
.
policy
.
Policy
(
self
,
self
.
config
[
'environments'
][
self
.
environment
])
self
.
role
=
kappa
.
role
.
Role
(
...
...
@@ -173,6 +175,9 @@ class Context(object):
def
invoke
(
self
):
return
self
.
function
.
invoke
()
def
test
(
self
):
return
self
.
function
.
invoke
()
def
dryrun
(
self
):
return
self
.
function
.
dryrun
()
...
...
kappa/function.py
View file @
0718d02
...
...
@@ -16,6 +16,7 @@ import logging
import
os
import
zipfile
import
time
import
shutil
from
botocore.exceptions
import
ClientError
...
...
@@ -122,7 +123,7 @@ class Function(object):
return
self
.
_log
def
tail
(
self
):
LOG
.
debug
(
'tailing function:
%
s'
,
self
.
name
)
LOG
.
info
(
'tailing function:
%
s'
,
self
.
name
)
return
self
.
log
.
tail
()
def
_zip_lambda_dir
(
self
,
zipfile_name
,
lambda_dir
):
...
...
@@ -175,8 +176,17 @@ class Function(object):
except
Exception
:
LOG
.
exception
(
'Unable to add permission'
)
def
_copy_config_file
(
self
):
config_name
=
'{}_config.json'
.
format
(
self
.
_context
.
environment
)
config_path
=
os
.
path
.
join
(
self
.
path
,
config_name
)
if
os
.
path
.
exists
(
config_path
):
dest_path
=
os
.
path
.
join
(
self
.
path
,
'config.json'
)
LOG
.
info
(
'copy {} to {}'
.
format
(
config_path
,
dest_path
))
shutil
.
copyfile
(
config_path
,
dest_path
)
def
create
(
self
):
LOG
.
debug
(
'creating
%
s'
,
self
.
zipfile_name
)
LOG
.
info
(
'creating function
%
s'
,
self
.
name
)
self
.
_copy_config_file
()
self
.
zip_lambda_function
(
self
.
zipfile_name
,
self
.
path
)
with
open
(
self
.
zipfile_name
,
'rb'
)
as
fp
:
exec_role
=
self
.
_context
.
exec_role_arn
...
...
@@ -198,15 +208,26 @@ class Function(object):
LOG
.
exception
(
'Unable to upload zip file'
)
self
.
add_permissions
()
def
_do_update
(
self
):
do_update
=
False
if
self
.
_context
.
force
:
do_update
=
True
else
:
stats
=
os
.
stat
(
self
.
zipfile_name
)
if
self
.
_context
.
cache
.
get
(
'zipfile_size'
)
!=
stats
.
st_size
:
self
.
_context
.
cache
[
'zipfile_size'
]
=
stats
.
st_size
do_update
=
True
return
do_update
def
update
(
self
):
LOG
.
debug
(
'updating
%
s'
,
self
.
zipfile_name
)
self
.
zip_lambda_function
(
self
.
zipfile_name
,
self
.
path
)
stats
=
os
.
stat
(
self
.
zipfile_name
)
if
self
.
_context
.
cache
.
get
(
'zipfile_size'
)
!=
stats
.
st_size
:
self
.
_context
.
cache
[
'zipfile_size'
]
=
stats
.
st_size
LOG
.
info
(
'updating
%
s'
,
self
.
name
)
self
.
_copy_config_file
()
if
self
.
_do_update
():
self
.
_context
.
save_cache
()
with
open
(
self
.
zipfile_name
,
'rb'
)
as
fp
:
try
:
LOG
.
info
(
'uploading new function zipfile
%
s'
,
self
.
zipfile_name
)
zipdata
=
fp
.
read
()
response
=
self
.
_lambda_client
.
call
(
'update_function_code'
,
...
...
@@ -214,9 +235,9 @@ class Function(object):
ZipFile
=
zipdata
)
LOG
.
debug
(
response
)
except
Exception
:
LOG
.
exception
(
'
U
nable to update zip file'
)
LOG
.
exception
(
'
u
nable to update zip file'
)
else
:
LOG
.
info
(
'
Code
has not changed'
)
LOG
.
info
(
'
function
has not changed'
)
def
deploy
(
self
):
if
self
.
exists
():
...
...
@@ -224,7 +245,7 @@ class Function(object):
return
self
.
create
()
def
publish_version
(
self
,
description
):
LOG
.
debug
(
'publishing version of
%
s'
,
self
.
name
)
LOG
.
info
(
'publishing version of
%
s'
,
self
.
name
)
try
:
response
=
self
.
_lambda_client
.
call
(
'publish_version'
,
...
...
@@ -237,7 +258,7 @@ class Function(object):
return
response
[
'Version'
]
def
list_versions
(
self
):
LOG
.
debug
(
'listing versions of
%
s'
,
self
.
name
)
LOG
.
info
(
'listing versions of
%
s'
,
self
.
name
)
try
:
response
=
self
.
_lambda_client
.
call
(
'list_versions_by_function'
,
...
...
@@ -248,7 +269,7 @@ class Function(object):
return
response
[
'Versions'
]
def
create_alias
(
self
,
name
,
description
,
version
=
None
):
LOG
.
debug
(
'creating alias of
%
s'
,
self
.
name
)
LOG
.
info
(
'creating alias of
%
s'
,
self
.
name
)
if
version
is
None
:
version
=
self
.
version
try
:
...
...
@@ -263,7 +284,7 @@ class Function(object):
LOG
.
exception
(
'Unable to create alias'
)
def
list_aliases
(
self
):
LOG
.
debug
(
'listing aliases of
%
s'
,
self
.
name
)
LOG
.
info
(
'listing aliases of
%
s'
,
self
.
name
)
try
:
response
=
self
.
_lambda_client
.
call
(
'list_aliases'
,
...
...
@@ -279,7 +300,7 @@ class Function(object):
self
.
create_alias
(
name
,
description
,
version
)
def
delete
(
self
):
LOG
.
debug
(
'deleting function
%
s'
,
self
.
name
)
LOG
.
info
(
'deleting function
%
s'
,
self
.
name
)
response
=
None
try
:
response
=
self
.
_lambda_client
.
call
(
...
...
@@ -291,7 +312,6 @@ class Function(object):
return
response
def
status
(
self
):
LOG
.
debug
(
'getting status for function
%
s'
,
self
.
name
)
try
:
response
=
self
.
_lambda_client
.
call
(
'get_function'
,
...
...
kappa/policy.py
View file @
0718d02
...
...
@@ -121,10 +121,10 @@ class Policy(object):
LOG
.
exception
(
'Error creating new Policy version'
)
def
deploy
(
self
):
LOG
.
debug
(
'deploying policy
%
s'
,
self
.
name
)
LOG
.
info
(
'deploying policy
%
s'
,
self
.
name
)
document
=
self
.
document
()
if
not
document
:
LOG
.
debug
(
'not a custom policy, no need to create it'
)
LOG
.
info
(
'not a custom policy, no need to create it'
)
return
policy
=
self
.
exists
()
if
policy
:
...
...
@@ -138,7 +138,7 @@ class Policy(object):
self
.
_context
.
save_cache
()
self
.
_add_policy_version
()
else
:
LOG
.
info
(
'
P
olicy unchanged'
)
LOG
.
info
(
'
p
olicy unchanged'
)
else
:
# create a new policy
try
:
...
...
@@ -157,7 +157,7 @@ class Policy(object):
# This indicates that it was a custom policy created by kappa.
document
=
self
.
document
()
if
self
.
arn
and
document
:
LOG
.
debug
(
'deleting policy
%
s'
,
self
.
name
)
LOG
.
info
(
'deleting policy
%
s'
,
self
.
name
)
response
=
self
.
_iam_client
.
call
(
'delete_policy'
,
PolicyArn
=
self
.
arn
)
LOG
.
debug
(
response
)
...
...
kappa/scripts/cli.py
View file @
0718d02
...
...
@@ -35,12 +35,18 @@ from kappa.context import Context
'--environment'
,
help
=
'Specify which environment to work with'
)
@click.option
(
'--force/--no-force'
,
default
=
False
,
help
=
'Force an update of the Lambda function'
)
@click.pass_context
def
cli
(
ctx
,
config
=
None
,
debug
=
False
,
environment
=
None
):
def
cli
(
ctx
,
config
=
None
,
debug
=
False
,
environment
=
None
,
force
=
None
):
config
=
config
ctx
.
obj
[
'debug'
]
=
debug
ctx
.
obj
[
'config'
]
=
config
ctx
.
obj
[
'environment'
]
=
environment
ctx
.
obj
[
'force'
]
=
force
@cli.command
()
...
...
@@ -48,10 +54,10 @@ def cli(ctx, config=None, debug=False, environment=None):
def
deploy
(
ctx
):
"""Deploy the Lambda function and any policies and roles required"""
context
=
Context
(
ctx
.
obj
[
'config'
],
ctx
.
obj
[
'environment'
],
ctx
.
obj
[
'debug'
])
click
.
echo
(
'deploying
...
'
)
ctx
.
obj
[
'debug'
]
,
ctx
.
obj
[
'force'
]
)
click
.
echo
(
'deploying'
)
context
.
deploy
()
click
.
echo
(
'
...
done'
)
click
.
echo
(
'done'
)
@cli.command
()
...
...
@@ -59,10 +65,10 @@ def deploy(ctx):
def
tag
(
ctx
):
"""Deploy the Lambda function and any policies and roles required"""
context
=
Context
(
ctx
.
obj
[
'config'
],
ctx
.
obj
[
'environment'
],
ctx
.
obj
[
'debug'
])
click
.
echo
(
'
deploying...
'
)
ctx
.
obj
[
'debug'
]
,
ctx
.
obj
[
'force'
]
)
click
.
echo
(
'
tagging
'
)
context
.
deploy
()
click
.
echo
(
'
...
done'
)
click
.
echo
(
'done'
)
@cli.command
()
...
...
@@ -70,13 +76,27 @@ def tag(ctx):
def
invoke
(
ctx
):
"""Invoke the command synchronously"""
context
=
Context
(
ctx
.
obj
[
'config'
],
ctx
.
obj
[
'environment'
],
ctx
.
obj
[
'debug'
])
click
.
echo
(
'invoking
...
'
)
ctx
.
obj
[
'debug'
]
,
ctx
.
obj
[
'force'
]
)
click
.
echo
(
'invoking'
)
response
=
context
.
invoke
()
log_data
=
base64
.
b64decode
(
response
[
'LogResult'
])
click
.
echo
(
log_data
)
click
.
echo
(
response
[
'Payload'
]
.
read
())
click
.
echo
(
'...done'
)
click
.
echo
(
'done'
)
@cli.command
()
@click.pass_context
def
test
(
ctx
):
"""Test the command synchronously"""
context
=
Context
(
ctx
.
obj
[
'config'
],
ctx
.
obj
[
'environment'
],
ctx
.
obj
[
'debug'
],
ctx
.
obj
[
'force'
])
click
.
echo
(
'testing'
)
response
=
context
.
test
()
log_data
=
base64
.
b64decode
(
response
[
'LogResult'
])
click
.
echo
(
log_data
)
click
.
echo
(
response
[
'Payload'
]
.
read
())
click
.
echo
(
'done'
)
@cli.command
()
...
...
@@ -84,11 +104,11 @@ def invoke(ctx):
def
dryrun
(
ctx
):
"""Show you what would happen but don't actually do anything"""
context
=
Context
(
ctx
.
obj
[
'config'
],
ctx
.
obj
[
'environment'
],
ctx
.
obj
[
'debug'
])
click
.
echo
(
'invoking dryrun
...
'
)
ctx
.
obj
[
'debug'
]
,
ctx
.
obj
[
'force'
]
)
click
.
echo
(
'invoking dryrun'
)
response
=
context
.
dryrun
()
click
.
echo
(
response
)
click
.
echo
(
'
...
done'
)
click
.
echo
(
'done'
)
@cli.command
()
...
...
@@ -96,11 +116,11 @@ def dryrun(ctx):
def
invoke_async
(
ctx
):
"""Invoke the Lambda function asynchronously"""
context
=
Context
(
ctx
.
obj
[
'config'
],
ctx
.
obj
[
'environment'
],
ctx
.
obj
[
'debug'
])
click
.
echo
(
'invoking async
...
'
)
ctx
.
obj
[
'debug'
]
,
ctx
.
obj
[
'force'
]
)
click
.
echo
(
'invoking async'
)
response
=
context
.
invoke_async
()
click
.
echo
(
response
)
click
.
echo
(
'
...
done'
)
click
.
echo
(
'done'
)
@cli.command
()
...
...
@@ -108,12 +128,12 @@ def invoke_async(ctx):
def
tail
(
ctx
):
"""Show the last 10 lines of the log file"""
context
=
Context
(
ctx
.
obj
[
'config'
],
ctx
.
obj
[
'environment'
],
ctx
.
obj
[
'debug'
])
click
.
echo
(
'tailing logs
...
'
)
ctx
.
obj
[
'debug'
]
,
ctx
.
obj
[
'force'
]
)
click
.
echo
(
'tailing logs'
)
for
e
in
context
.
tail
()[
-
10
:]:
ts
=
datetime
.
utcfromtimestamp
(
e
[
'timestamp'
]
//
1000
)
.
isoformat
()
click
.
echo
(
"{}: {}"
.
format
(
ts
,
e
[
'message'
]))
click
.
echo
(
'
...
done'
)
click
.
echo
(
'done'
)
@cli.command
()
...
...
@@ -159,10 +179,10 @@ def status(ctx):
def
delete
(
ctx
):
"""Delete the Lambda function and related policies and roles"""
context
=
Context
(
ctx
.
obj
[
'config'
],
ctx
.
obj
[
'environment'
],
ctx
.
obj
[
'debug'
])
click
.
echo
(
'deleting
...
'
)
ctx
.
obj
[
'debug'
]
,
ctx
.
obj
[
'force'
]
)
click
.
echo
(
'deleting'
)
context
.
delete
()
click
.
echo
(
'
...
done'
)
click
.
echo
(
'done'
)
@cli.command
()
...
...
@@ -170,10 +190,10 @@ def delete(ctx):
def
add_event_sources
(
ctx
):
"""Add any event sources specified in the config file"""
context
=
Context
(
ctx
.
obj
[
'config'
],
ctx
.
obj
[
'environment'
],
ctx
.
obj
[
'debug'
])
click
.
echo
(
'adding event sources
...
'
)
ctx
.
obj
[
'debug'
]
,
ctx
.
obj
[
'force'
]
)
click
.
echo
(
'adding event sources'
)
context
.
add_event_sources
()
click
.
echo
(
'
...
done'
)
click
.
echo
(
'done'
)
@cli.command
()
...
...
@@ -181,10 +201,10 @@ def add_event_sources(ctx):
def
update_event_sources
(
ctx
):
"""Update event sources specified in the config file"""
context
=
Context
(
ctx
.
obj
[
'config'
],
ctx
.
obj
[
'environment'
],
ctx
.
obj
[
'debug'
])
click
.
echo
(
'updating event sources
...
'
)
ctx
.
obj
[
'debug'
]
,
ctx
.
obj
[
'force'
]
)
click
.
echo
(
'updating event sources'
)
context
.
update_event_sources
()
click
.
echo
(
'
...
done'
)
click
.
echo
(
'done'
)
cli
(
obj
=
{})
...
...
Please
register
or
login
to post a comment