Skip to content

Commit

Permalink
add API events (#1425)
Browse files Browse the repository at this point in the history
  • Loading branch information
whummer committed Jul 14, 2019
1 parent 214d75a commit 64bdb7e
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 13 deletions.
12 changes: 12 additions & 0 deletions localstack/services/apigateway/apigateway_listener.py
Expand Up @@ -11,6 +11,7 @@
from localstack.utils import common
from localstack.utils.aws import aws_stack
from localstack.utils.common import to_str
from localstack.utils.analytics import event_publisher
from localstack.services.awslambda import lambda_api
from localstack.services.kinesis import kinesis_listener
from localstack.services.generic_proxy import ProxyListener
Expand Down Expand Up @@ -173,6 +174,17 @@ def return_response(self, method, path, data, headers, response):
response._content = json.dumps(result)
return response

# publish event
if method == 'POST' and path == '/restapis':
content = json.loads(to_str(response.content))
event_publisher.fire_event(event_publisher.EVENT_APIGW_CREATE_API,
payload={'a': event_publisher.get_hash(content['id'])})
api_regex = r'^/restapis/([a-zA-Z0-9\-]+)$'
if method == 'DELETE' and re.match(api_regex, path):
api_id = re.sub(api_regex, r'\1', path)
event_publisher.fire_event(event_publisher.EVENT_APIGW_DELETE_API,
payload={'a': event_publisher.get_hash(api_id)})


# instantiate listener
UPDATE_APIGATEWAY = ProxyListenerApiGateway()
9 changes: 9 additions & 0 deletions localstack/services/sns/sns_listener.py
Expand Up @@ -10,6 +10,7 @@
from localstack.constants import TEST_AWS_ACCOUNT_ID, MOTO_ACCOUNT_ID
from localstack.utils.aws import aws_stack
from localstack.utils.common import short_uid, to_str
from localstack.utils.analytics import event_publisher
from localstack.services.awslambda import lambda_api
from localstack.services.generic_proxy import ProxyListener

Expand Down Expand Up @@ -115,6 +116,14 @@ def return_response(self, method, path, data, headers, response):
response_data = xmltodict.parse(response.content)
topic_arn = response_data['CreateTopicResponse']['CreateTopicResult']['TopicArn']
do_create_topic(topic_arn)
# publish event
event_publisher.fire_event(event_publisher.EVENT_SNS_CREATE_TOPIC,
payload={'t': event_publisher.get_hash(topic_arn)})
if req_action == 'DeleteTopic' and response.status_code < 400:
# publish event
topic_arn = (req_data.get('TargetArn') or req_data.get('TopicArn'))[0]
event_publisher.fire_event(event_publisher.EVENT_SNS_DELETE_TOPIC,
payload={'t': event_publisher.get_hash(topic_arn)})


# instantiate listener
Expand Down
22 changes: 14 additions & 8 deletions localstack/services/stepfunctions/stepfunctions_listener.py
@@ -1,19 +1,25 @@
import json
import logging
from localstack.utils.common import to_str
from localstack.utils.analytics import event_publisher
from localstack.services.generic_proxy import ProxyListener

LOG = logging.getLogger(__name__)


class ProxyListenerStepFunctions(ProxyListener):

# TODO: listener methods currently disabled

def forward_request_DISABLED(self, method, path, data, headers):
LOG.debug('StepFunctions request: %s %s %s', method, path, data)
return True

def return_response_DISABLED(self, method, path, data, headers, response):
LOG.debug('StepFunctions response: %s %s %s %s', method, path, response.status_code, response.content)
def return_response(self, method, path, data, headers, response):
data = json.loads(to_str(data or '{}'))
name = data.get('name') or (data.get('stateMachineArn') or '').split(':')[-1]

# publish event
if headers.get('X-Amz-Target') == 'AWSStepFunctions.CreateStateMachine':
event_publisher.fire_event(event_publisher.EVENT_STEPFUNCTIONS_CREATE_SM,
payload={'m': event_publisher.get_hash(name)})
elif headers.get('X-Amz-Target') == 'AWSStepFunctions.DeleteStateMachine':
event_publisher.fire_event(event_publisher.EVENT_STEPFUNCTIONS_DELETE_SM,
payload={'m': event_publisher.get_hash(name)})


# instantiate listener
Expand Down
12 changes: 11 additions & 1 deletion localstack/utils/analytics/event_publisher.py
Expand Up @@ -20,8 +20,14 @@
EVENT_LAMBDA_DELETE_FUNC = 'lmb.df'
EVENT_SQS_CREATE_QUEUE = 'sqs.cq'
EVENT_SQS_DELETE_QUEUE = 'sqs.dq'
EVENT_SNS_CREATE_TOPIC = 'sns.ct'
EVENT_SNS_DELETE_TOPIC = 'sns.dt'
EVENT_S3_CREATE_BUCKET = 's3.cb'
EVENT_S3_DELETE_BUCKET = 's3.db'
EVENT_STEPFUNCTIONS_CREATE_SM = 'stf.cm'
EVENT_STEPFUNCTIONS_DELETE_SM = 'stf.dm'
EVENT_APIGW_CREATE_API = 'agw.ca'
EVENT_APIGW_DELETE_API = 'agw.da'
EVENT_DYNAMODB_CREATE_TABLE = 'ddb.ct'
EVENT_DYNAMODB_DELETE_TABLE = 'ddb.dt'

Expand Down Expand Up @@ -153,6 +159,10 @@ def fire_event(event_type, payload=None):
if not SENDER_THREAD:
SENDER_THREAD = FuncThread(poll_and_send_messages, {})
SENDER_THREAD.start()
api_key = read_api_key_safe()
if not api_key:
# only store events if API key has been specified
return
if payload is None:
payload = {}
if isinstance(payload, dict):
Expand All @@ -161,5 +171,5 @@ def fire_event(event_type, payload=None):
if os.environ.get(ENV_INTERNAL_TEST_RUN):
payload['int'] = True

event = AnalyticsEvent(event_type=event_type, payload=payload)
event = AnalyticsEvent(event_type=event_type, payload=payload, api_key=api_key)
EVENT_QUEUE.put_nowait(event)
9 changes: 5 additions & 4 deletions localstack/utils/aws/aws_stack.py
Expand Up @@ -7,9 +7,10 @@
import logging
import six
from localstack import config
from localstack.constants import (REGION_LOCAL, DEFAULT_REGION, LOCALHOST, MOTO_ACCOUNT_ID,
ENV_DEV, APPLICATION_AMZ_JSON_1_1, APPLICATION_AMZ_JSON_1_0,
APPLICATION_X_WWW_FORM_URLENCODED, TEST_AWS_ACCOUNT_ID)
from localstack.constants import (
REGION_LOCAL, DEFAULT_REGION, LOCALHOST, MOTO_ACCOUNT_ID,
ENV_DEV, APPLICATION_AMZ_JSON_1_1, APPLICATION_AMZ_JSON_1_0,
APPLICATION_X_WWW_FORM_URLENCODED, TEST_AWS_ACCOUNT_ID)
from localstack.utils.common import (
run_safe, to_str, is_string, is_string_or_bytes, make_http_request,
timestamp, is_port_open, get_service_protocol)
Expand Down Expand Up @@ -247,8 +248,8 @@ def check_valid_region(headers):

def fix_account_id_in_arns(response, colon_delimiter=':', existing=None, replace=None):
""" Fix the account ID in the ARNs returned in the given Flask response or string """
existing = existing if isinstance(existing, list) else [existing]
existing = existing or ['123456789', MOTO_ACCOUNT_ID]
existing = existing if isinstance(existing, list) else [existing]
replace = replace or TEST_AWS_ACCOUNT_ID
is_str_obj = is_string_or_bytes(response)
content = to_str(response if is_str_obj else response._content)
Expand Down

0 comments on commit 64bdb7e

Please sign in to comment.