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
2016-02-09 15:21:37 -0500
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
9ba7028fa2b9793fe7029dea1ee6c709970758c6
9ba7028f
1 parent
3249d0c8
Adding missing file.
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
268 additions
and
0 deletions
kappa/restapi.py
kappa/restapi.py
0 → 100644
View file @
9ba7028
# Copyright (c) 2014, 2015 Mitch Garnaat
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import
logging
from
botocore.exceptions
import
ClientError
import
kappa.awsclient
import
kappa.log
LOG
=
logging
.
getLogger
(
__name__
)
class
RestApi
(
object
):
def
__init__
(
self
,
context
,
config
):
self
.
_context
=
context
self
.
_config
=
config
self
.
_apigateway_client
=
kappa
.
awsclient
.
create_client
(
'apigateway'
,
context
.
session
)
self
.
_api
=
None
self
.
_resources
=
None
self
.
_resource
=
None
@property
def
arn
(
self
):
_
,
_
,
_
,
region
,
account
,
_
=
self
.
_context
.
function
.
arn
.
split
(
':'
,
5
)
arn
=
'arn:aws:execute-api:{}:{}:{}/*/*/{}'
.
format
(
region
,
account
,
self
.
api_id
,
self
.
resource_name
)
return
arn
@property
def
api_name
(
self
):
return
self
.
_config
[
'name'
]
@property
def
description
(
self
):
return
self
.
_config
[
'description'
]
@property
def
resource_name
(
self
):
return
self
.
_config
[
'resource'
][
'name'
]
@property
def
parent_resource
(
self
):
return
self
.
_config
[
'resource'
][
'parent'
]
@property
def
full_path
(
self
):
parts
=
self
.
parent_resource
.
split
(
'/'
)
parts
.
append
(
self
.
resource_name
)
return
'/'
.
join
(
parts
)
@property
def
api_id
(
self
):
api
=
self
.
_get_api
()
return
api
.
get
(
'id'
)
@property
def
resource_id
(
self
):
resources
=
self
.
_get_resources
()
return
resources
.
get
(
self
.
full_path
)
.
get
(
'id'
)
def
_get_api
(
self
):
if
self
.
_api
is
None
:
try
:
response
=
self
.
_apigateway_client
.
call
(
'get_rest_apis'
)
LOG
.
debug
(
response
)
for
item
in
response
[
'items'
]:
if
item
[
'name'
]
==
self
.
api_name
:
self
.
_api
=
item
except
Exception
:
LOG
.
exception
(
'Error finding restapi'
)
return
self
.
_api
def
_get_resources
(
self
):
if
self
.
_resources
is
None
:
try
:
response
=
self
.
_apigateway_client
.
call
(
'get_resources'
,
restApiId
=
self
.
api_id
)
LOG
.
debug
(
response
)
self
.
_resources
=
{}
for
item
in
response
[
'items'
]:
self
.
_resources
[
item
[
'path'
]]
=
item
except
Exception
:
LOG
.
exception
(
'Unable to find resources for:
%
s'
,
self
.
api_name
)
return
self
.
_resources
def
create_restapi
(
self
):
if
not
self
.
api_exists
():
LOG
.
info
(
'creating restapi
%
s'
,
self
.
api_name
)
try
:
response
=
self
.
_apigateway_client
.
call
(
'create_rest_api'
,
name
=
self
.
api_name
,
description
=
self
.
description
)
LOG
.
debug
(
response
)
except
Exception
:
LOG
.
exception
(
'Unable to create new restapi'
)
def
create_resource_path
(
self
):
path
=
self
.
full_path
parts
=
path
.
split
(
'/'
)
resources
=
self
.
_get_resources
()
parent
=
None
build_path
=
[]
for
part
in
parts
:
LOG
.
debug
(
'part=
%
s'
,
part
)
build_path
.
append
(
part
)
LOG
.
debug
(
'build_path=
%
s'
,
build_path
)
full_path
=
'/'
.
join
(
build_path
)
LOG
.
debug
(
'full_path=
%
s'
,
full_path
)
if
full_path
is
''
:
parent
=
resources
[
'/'
]
else
:
if
full_path
not
in
resources
and
parent
:
try
:
response
=
self
.
_apigateway_client
.
call
(
'create_resource'
,
restApiId
=
self
.
api_id
,
parentId
=
parent
[
'id'
],
pathPart
=
part
)
LOG
.
debug
(
response
)
resources
[
full_path
]
=
response
except
Exception
:
LOG
.
exception
(
'Unable to create new resource'
)
parent
=
resources
[
full_path
]
self
.
_item
=
resources
[
path
]
def
create_method
(
self
,
method
,
config
):
LOG
.
info
(
'creating method:
%
s'
,
method
)
try
:
response
=
self
.
_apigateway_client
.
call
(
'put_method'
,
restApiId
=
self
.
api_id
,
resourceId
=
self
.
resource_id
,
httpMethod
=
method
,
authorizationType
=
config
.
get
(
'authorization_type'
),
apiKeyRequired
=
config
.
get
(
'apikey_required'
,
False
)
)
LOG
.
debug
(
response
)
LOG
.
debug
(
'now create integration'
)
uri
=
'arn:aws:apigateway:{}:'
.
format
(
self
.
_apigateway_client
.
region_name
)
uri
+=
'lambda:path/2015-03-31/functions/'
uri
+=
self
.
_context
.
function
.
arn
uri
+=
':${stageVariables.environment}/invocations'
LOG
.
debug
(
uri
)
response
=
self
.
_apigateway_client
.
call
(
'put_integration'
,
restApiId
=
self
.
api_id
,
resourceId
=
self
.
resource_id
,
httpMethod
=
method
,
integrationHttpMethod
=
method
,
type
=
'AWS'
,
uri
=
uri
)
except
Exception
:
LOG
.
exception
(
'Unable to create integration:
%
s'
,
method
)
def
create_deployment
(
self
):
LOG
.
info
(
'creating a deployment for
%
s to stage:
%
s'
,
self
.
api_name
,
self
.
_context
.
environment
)
try
:
response
=
self
.
_apigateway_client
.
call
(
'create_deployment'
,
restApiId
=
self
.
api_id
,
stageName
=
self
.
_context
.
environment
)
LOG
.
debug
(
response
)
LOG
.
info
(
'Now deployed to:
%
s'
,
self
.
deployment_uri
)
except
Exception
:
LOG
.
exception
(
'Unable to create a deployment'
)
def
create_methods
(
self
):
resource_config
=
self
.
_config
[
'resource'
]
for
method
in
resource_config
.
get
(
'methods'
,
dict
()):
if
not
self
.
method_exists
():
method_config
=
resource_config
[
'methods'
][
method
]
self
.
create_method
(
method
,
method_config
)
def
api_exists
(
self
):
return
self
.
_get_api
()
def
resource_exists
(
self
):
resources
=
self
.
_get_resources
()
return
resources
.
get
(
self
.
full_path
)
def
method_exists
(
self
,
method
):
exists
=
False
resource
=
self
.
resource_exists
()
if
resource
:
methods
=
resource
.
get
(
'resourceMethods'
)
if
methods
:
for
method_name
in
methods
:
if
method_name
==
method
:
exists
=
True
return
exists
def
find_parent_resource_id
(
self
):
parent_id
=
None
resources
=
self
.
_get_resources
()
for
item
in
resources
:
if
item
[
'path'
]
==
self
.
parent
:
parent_id
=
item
[
'id'
]
return
parent_id
def
api_update
(
self
):
LOG
.
info
(
'updating restapi
%
s'
,
self
.
api_name
)
def
resource_update
(
self
):
LOG
.
info
(
'updating resource
%
s'
,
self
.
full_path
)
def
add_permission
(
self
):
LOG
.
info
(
'Adding permission for APIGateway to call function'
)
self
.
_context
.
function
.
add_permission
(
action
=
'lambda:InvokeFunction'
,
principal
=
'apigateway.amazonaws.com'
,
source_arn
=
self
.
arn
)
def
deploy
(
self
):
if
self
.
api_exists
():
self
.
api_update
()
else
:
self
.
create_restapi
()
if
self
.
resource_exists
():
self
.
resource_update
()
else
:
self
.
create_resource_path
()
self
.
create_methods
()
self
.
add_permission
()
def
delete
(
self
):
LOG
.
info
(
'deleting resource
%
s'
,
self
.
resource_name
)
try
:
response
=
self
.
_apigateway_client
.
call
(
'delete_resource'
,
restApiId
=
self
.
api_id
,
resourceId
=
self
.
resource_id
)
LOG
.
debug
(
response
)
except
ClientError
:
LOG
.
exception
(
'Unable to delete resource '
,
self
.
resource_name
)
return
response
def
status
(
self
):
try
:
response
=
self
.
_apigateway_client
.
call
(
'delete_'
,
FunctionName
=
self
.
name
)
LOG
.
debug
(
response
)
except
ClientError
:
LOG
.
exception
(
'function
%
s not found'
,
self
.
name
)
response
=
None
return
response
Please
register
or
login
to post a comment