示例#1
0
    def __init__(self, lambda_dir=None, env_file=None, env_vars=None,
                 role=None):

        if not env_file or env_file == self.DEFAULT_ENV_FILE:
            env_file = os.getenv('LAMBDA_ENV_FILE', '.env')

        yaep.populate_env(env_file)

        if not lambda_dir or lambda_dir == self.DEFAULT_LAMBDA_DIR:
            lambda_dir = yaep.env('LAMBDA_DIRECTORY', self.DEFAULT_LAMBDA_DIR)

        if not env_vars:
            # If there were no env_vars passed, look for them
            # in the ENV_VARS environment variable, and return
            # an empty list if they aren't there.
            env_vars = map(
                lambda x: x.strip(),
                filter(
                    None,
                    yaep.env('LAMBDA_ENV_VARS', '').split(',')
                )
            )

        self.env_vars = env_vars
        self.lambda_dir = lambda_dir
        self.client = boto3.client('lambda')
        self.role = role if role else yaep.env('LAMBDA_ROLE')
示例#2
0
 def test_populate_env(self):
     env_file = io.BytesIO('foo = bar\nbaz = biz\nBOO = FAR')
     with monkey_patch(yaep.yaep, 'open', lambda fn: env_file):
         yaep.yaep.populate_env()
         assert (yaep.env('foo') == 'bar')
         assert (yaep.env('baz') == 'biz')
         assert (yaep.env('BOO') == 'FAR')
示例#3
0
def verify_appid(appid=None):
    if env('SKILL_APPID') and appid:
        try:
            print "Verifying application ID..."
            verifier.verify_application_id(appid, env('SKILL_APPID'))
        except verifier.VerificationError as e:
            print e.args[0]
            raise
示例#4
0
def verify_application_id(candidate):
    if env('SKILL_APPID'):
        try:
            print "Verifying application ID..."
            if candidate not in env('SKILL_APPID'):
                raise ValueError("Application ID verification failed")
        except ValueError as e:
            print e.args[0]
            raise
示例#5
0
 def run_cases(self, test_cases, boolean_map=None):
     for given, expected in test_cases:
         try:
             assert (yaep.env('YAEP_TEST_NOT_THERE', given,
                              boolean_map) == expected)
         except AssertionError:
             print 'Error testing {} - expected {}, but got {}'.format(
                 given, str(expected),
                 str(yaep.env('YAEP_TEST_NOT_THERE', given)))
             raise
示例#6
0
def verify_application_id(candidate):
    """ verify app id """
    if env('SKILL_APPID'):
        try:
            print "Verifying application ID..."
            if candidate not in env('SKILL_APPID'):
                raise ValueError("Application ID verification failed")
            else:
                print "Application ID succesfully verified."

        except ValueError as e:
            print e.args[0]
            raise
示例#7
0
    def deploy(self, *lambdas):
        """Deploys lambdas to AWS"""

        if not self.role:
            logger.error('Missing AWS Role')
            raise ArgumentsError('Role required')

        logger.debug('Deploying lambda {}'.format(self.lambda_name))
        zfh = self.package()

        if self.lambda_name in self.get_function_names():
            logger.info('Updating {} lambda'.format(self.lambda_name))

            response = self.client.update_function_code(
                FunctionName=self.lambda_name,
                ZipFile=zfh.getvalue(),
                Publish=True)
        else:
            logger.info('Adding new {} lambda'.format(self.lambda_name))

            response = self.client.create_function(
                FunctionName=self.lambda_name,
                Runtime=yaep.env('LAMBDA_RUNTIME', 'python2.7'),
                Role=self.role,
                Handler=yaep.env('LAMBDA_HANDLER',
                                 'lambda_function.lambda_handler'),
                Code={
                    'ZipFile': zfh.getvalue(),
                },
                Description=yaep.env(
                    'LAMBDA_DESCRIPTION',
                    'Lambda code for {}'.format(self.lambda_name)),
                Timeout=yaep.env('LAMBDA_TIMEOUT',
                                 3,
                                 convert_booleans=False,
                                 type_class=int),
                MemorySize=yaep.env('LAMBDA_MEMORY_SIZE',
                                    128,
                                    convert_booleans=False,
                                    type_class=int),
                Publish=True)

        status_code = response.get('ResponseMetadata',
                                   {}).get('HTTPStatusCode')

        if status_code in [200, 201]:
            logger.info('Successfully deployed {} version {}'.format(
                self.lambda_name, response.get('Version', 'Unkown')))
        else:
            logger.error('Error deploying {}: {}'.format(
                self.lambda_name, response))
示例#8
0
def wsgi_handler(environ, start_response):
    # Alexa requests come as POST messages with a request body
    try:
        length = int(environ.get('CONTENT_LENGTH', '0'))
    except ValueError:
        length = 0

    if length > 0:
        # Get the request body and parse out the Alexa JSON request
        body = environ['wsgi.input'].read(length)
        alexa_msg = json.loads(body)
        alexa_session = alexa_msg['session']
        alexa_request = alexa_msg['request']

        appid = alexa_msg['session']['application']['applicationId']
        print("wsgi_handler: applicationId=" + appid)

        # Verify the request is coming from Amazon and includes a valid signature.
        try:
            if env('SKILL_VERIFY_CERT'):
                print "Verifying certificate is valid..."
                cert_url = environ['HTTP_SIGNATURECERTCHAINURL']
                signature = environ['HTTP_SIGNATURE']
                cert = verifier.load_certificate(cert_url)
                verifier.verify_signature(cert, signature, body)
                timestamp = aniso8601.parse_datetime(
                    alexa_request['timestamp'])
                verifier.verify_timestamp(timestamp)
        except verifier.VerificationError as e:
            print e.args[0]
            raise

        # Verify the application ID is what the user expects
        verify_application_id(appid)

        if alexa_session['new']:
            on_session_started({'requestId': alexa_request['requestId']},
                               alexa_session)

        if alexa_request['type'] == 'LaunchRequest':
            # This is the type when you just say "Open <app>"
            response = prepare_help_message()

        elif alexa_request['type'] == 'IntentRequest':
            response = on_intent(alexa_request, alexa_session)

        else:
            response = build_alexa_response(
                "I received an unexpected request type.")

        start_response('200 OK',
                       [('Content-Type', 'application/json'),
                        ('Content-Length', str(len(json.dumps(response))))])
        return [json.dumps(response)]
    else:
        # This should never happen with a real Echo request but could happen
        # if your URL is accessed by a browser or otherwise.
        start_response('502 No content', [])
        return ['']
示例#9
0
    def package(self, name):
        """Packages lambda data for deployment into a zip"""
        logger.info('Packaging lambda {}'.format(name))
        src_dir = os.path.join(self.lambda_dir, name)
        zfh = io.BytesIO()

        with zipfile.ZipFile(zfh, 'w') as zf:
            self.add_directory_to_zip(src_dir, zf)

            # Construct a .env file in the archive with our
            # needed envrionment variables.
            envinfo = zipfile.ZipInfo('.env')
            envinfo.external_attr = 0644 << 16L
            zf.writestr(
                envinfo,
                '\n'.join(
                    '{} = {}'.format(key, yaep.env(key))
                    for key in self.env_vars
                )
            )

            if 'requirements.txt' in os.listdir(src_dir):
                with TemporaryDirectory() as temp_dir:
                    pip_args = [
                        'install',
                        '-r',
                        os.path.join(src_dir, 'requirements.txt'),
                        '-t',
                        temp_dir
                    ]

                    # Do pip install to temporary dir
                    if pip.main(pip_args) == 0:
                        self.add_directory_to_zip(temp_dir, zf)
                    else:
                        if sys.platform == 'darwin':
                            logger.error(
                                'A DistutilsOptionError about the prefix '
                                'can occur when you are on OS X and '
                                'installed Python via Homebrew.\nIf this '
                                'is you, please look at https://github.com'
                                '/Homebrew/brew/blob/master/share/doc/'
                                'homebrew/Homebrew-and-Python.md'
                                '#note-on-pip-install---user\n'
                                'If this is not you, please contact us '
                                ' for support.'
                            )
                        raise DependencyInstallationError(
                            'Failed to install dependencies of {}'.format(
                                name
                            )
                        )

        zfh.seek(0)

        return zfh
示例#10
0
    def __init__(self, lambda_dir=None, env_file=None, env_vars=None,
                 role=None, name=None):

        if not env_file or env_file == self.DEFAULT_ENV_FILE:
            env_file = os.path.realpath(os.getenv('LAMBDA_ENV_FILE', '.env'))
        else:
            # If they've specified a .env file, let's ensure it's there:
            env_file = os.path.realpath(env_file)
            if not os.path.exists(env_file):
                logger.error(
                    'Can\'t find Lambda env file at {}'.format(env_file)
                )
                raise ArgumentsError('Cannot find Env file')

        # Now load the .env file if it exists.
        if os.path.exists(env_file):
            yaep.populate_env(env_file)

        if not lambda_dir or lambda_dir == self.lambda_dir:
            lambda_dir = yaep.env('LAMBDA_DIRECTORY', self.lambda_dir)

        if not env_vars:
            # If there were no env_vars passed, look for them
            # in the ENV_VARS environment variable, and return
            # an empty list if they aren't there.
            env_vars = map(
                lambda x: x.strip(),
                filter(
                    None,
                    yaep.env('LAMBDA_ENV_VARS', '').split(',')
                )
            )

        self.env_vars = env_vars
        self.lambda_dir = lambda_dir
        self.lambda_name = name if name else yaep.env(
            'LAMBDA_NAME',
            os.path.basename(os.path.normpath(self.lambda_dir))
        )
        self.role = role if role else yaep.env('LAMBDA_ROLE')
        self.client = boto3.client('lambda')
示例#11
0
    def __init__(self,
                 lambda_dir=None,
                 env_file=None,
                 env_vars=None,
                 role=None,
                 name=None):

        if not env_file or env_file == self.DEFAULT_ENV_FILE:
            env_file = os.path.realpath(os.getenv('LAMBDA_ENV_FILE', '.env'))
        else:
            # If they've specified a .env file, let's ensure it's there:
            env_file = os.path.realpath(env_file)
            if not os.path.exists(env_file):
                logger.error(
                    'Can\'t find Lambda env file at {}'.format(env_file))
                raise ArgumentsError('Cannot find Env file')

        # Now load the .env file if it exists.
        if os.path.exists(env_file):
            yaep.populate_env(env_file)

        if not lambda_dir or lambda_dir == self.lambda_dir:
            lambda_dir = yaep.env('LAMBDA_DIRECTORY', self.lambda_dir)

        if not env_vars:
            # If there were no env_vars passed, look for them
            # in the ENV_VARS environment variable, and return
            # an empty list if they aren't there.
            env_vars = map(
                lambda x: x.strip(),
                filter(None,
                       yaep.env('LAMBDA_ENV_VARS', '').split(',')))

        self.env_vars = env_vars
        self.lambda_dir = lambda_dir
        self.lambda_name = name if name else yaep.env(
            'LAMBDA_NAME', os.path.basename(os.path.normpath(self.lambda_dir)))
        self.role = role if role else yaep.env('LAMBDA_ROLE')
        self.client = boto3.client('lambda')
示例#12
0
 def test_sticky(self):
     assert (os.getenv('FOOC') is None)
     yaep.env('FOOC', 'bar', sticky=True)
     assert (os.getenv('FOOC') == 'bar')
示例#13
0
 def test_not_in_env(self):
     assert (yaep.env('FOOA') is None)
示例#14
0
    def deploy(self, *lambdas):
        """Deploys lambdas to AWS"""

        if not self.role:
            logger.error('Missing AWS Role')
            raise ArgumentsError('Role required')

        logger.debug('Deploying lambda {}'.format(self.lambda_name))
        zfh = self.package()

        if self.lambda_name in self.get_function_names():
            logger.info('Updating {} lambda'.format(self.lambda_name))

            response = self.client.update_function_code(
                FunctionName=self.lambda_name,
                ZipFile=zfh.getvalue(),
                Publish=True
            )
        else:
            logger.info('Adding new {} lambda'.format(self.lambda_name))

            response = self.client.create_function(
                FunctionName=self.lambda_name,
                Runtime=yaep.env(
                    'LAMBDA_RUNTIME',
                    'python2.7'
                ),
                Role=self.role,
                Handler=yaep.env(
                    'LAMBDA_HANDLER',
                    'lambda_function.lambda_handler'
                ),
                Code={
                    'ZipFile': zfh.getvalue(),
                },
                Description=yaep.env(
                    'LAMBDA_DESCRIPTION',
                    'Lambda code for {}'.format(self.lambda_name)
                ),
                Timeout=yaep.env(
                    'LAMBDA_TIMEOUT',
                    3,
                    convert_booleans=False,
                    type_class=int
                ),
                MemorySize=yaep.env(
                    'LAMBDA_MEMORY_SIZE',
                    128,
                    convert_booleans=False,
                    type_class=int
                ),
                Publish=True
            )

        status_code = response.get(
            'ResponseMetadata', {}
        ).get('HTTPStatusCode')

        if status_code in [200, 201]:
            logger.info('Successfully deployed {} version {}'.format(
                self.lambda_name,
                response.get('Version', 'Unkown')
            ))
        else:
            logger.error('Error deploying {}: {}'.format(
                self.lambda_name,
                response
            ))
示例#15
0
 def test_type_class(self):
     os.environ['FOOE'] = '5'
     assert (yaep.env('FOOE') == '5')
     assert (yaep.env('FOOE', type_class=int) == 5)
示例#16
0
 def test_raise_unset_exception(self):
     with self.assertRaises(yaep.exceptions.UnsetException):
         yaep.env('BEER', default=yaep.exceptions.UnsetException)
示例#17
0
    def package(self):
        """Packages lambda data for deployment into a zip"""
        logger.info('Packaging lambda {}'.format(self.lambda_name))
        zfh = io.BytesIO()

        if os.path.exists(os.path.join(self.lambda_dir, '.env')):
            logger.warn(
                'A .env file exists in your Lambda directory - be '
                'careful that it does not contain any secrets you '
                'don\'t want uploaded to AWS!'
            )

        with zipfile.ZipFile(zfh, 'w') as zf:
            self.add_directory_to_zip(self.lambda_dir, zf)

            # Construct a .env file in the archive with our
            # needed envrionment variables.
            envinfo = zipfile.ZipInfo('.env')
            envinfo.external_attr = 0644 << 16L
            zf.writestr(
                envinfo,
                '\n'.join(
                    '{} = {}'.format(key, yaep.env(key))
                    for key in self.env_vars
                )
            )

            if 'requirements.txt' in os.listdir(self.lambda_dir):
                with TemporaryDirectory() as temp_dir:
                    pip_args = [
                        'install',
                        '-r',
                        os.path.join(self.lambda_dir, 'requirements.txt'),
                        '-t',
                        temp_dir
                    ]

                    # Do pip install to temporary dir
                    if pip.main(pip_args) == 0:
                        self.add_directory_to_zip(temp_dir, zf)
                    else:
                        if sys.platform == 'darwin':
                            logger.error(
                                'A DistutilsOptionError about the prefix '
                                'can occur when you are on OS X and '
                                'installed Python via Homebrew.\nIf this '
                                'is you, please look at https://github.com'
                                '/Homebrew/brew/blob/master/share/doc/'
                                'homebrew/Homebrew-and-Python.md'
                                '#note-on-pip-install---user\n'
                                'If this is not you, please contact us '
                                ' for support.'
                            )
                        raise DependencyInstallationError(
                            'Failed to install dependencies of {}'.format(
                                self.lambda_name
                            )
                        )

        zfh.seek(0)

        return zfh
示例#18
0
 def test_default(self):
     assert (yaep.env('FOOB', 'bar') == 'bar')
示例#19
0
    def deploy(self, *lambdas):
        """Deploys lambdas to AWS"""

        if not self.role:
            raise ArgumentsError('Role required')

        lambda_dirs = filter(
            lambda dir: (
                os.path.isdir(dir) and
                (not lambdas or dir in lambdas) and
                not dir.startswith('.')
            ),
            os.listdir(self.lambda_dir)
        )

        for missing in [m for m in lambdas if m not in lambda_dirs]:
            logger.warn('Lambda {} not found, skipping.'.format(missing))

        for lambda_name in lambda_dirs:
            logger.debug('Deploying lambda {}'.format(lambda_name))
            zfh = self.package(lambda_name)

            if lambda_name in self.get_function_names():
                logger.info('Updating {} lambda'.format(lambda_name))

                response = self.client.update_function_code(
                    FunctionName=lambda_name,
                    ZipFile=zfh.getvalue(),
                    Publish=True
                )
            else:
                logger.info('Adding new {} lambda'.format(lambda_name))

                response = self.client.create_function(
                    FunctionName=lambda_name,
                    Runtime=yaep.env(
                        'LAMBDA_RUNTIME',
                        'python2.7'
                    ),
                    Role=self.role,
                    Handler=yaep.env(
                        'LAMBDA_HANDLER',
                        'lambda_function.lambda_handler'
                    ),
                    Code={
                        'ZipFile': zfh.getvalue(),
                    },
                    Description=yaep.env(
                        'LAMBDA_DESCRIPTION',
                        'Lambda code for {}'.format(lambda_name)
                    ),
                    Timeout=yaep.env(
                        'LAMBDA_TIMEOUT',
                        3,
                        convert_booleans=False,
                        type_class=int
                    ),
                    MemorySize=yaep.env(
                        'LAMBDA_MEMORY_SIZE',
                        128,
                        convert_booleans=False,
                        type_class=int
                    ),
                    Publish=True
                )

            status_code = response.get(
                'ResponseMetadata', {}
            ).get('HTTPStatusCode')

            if status_code in [200, 201]:
                logger.info('Successfully deployed {} version {}'.format(
                    lambda_name,
                    response.get('Version', 'Unkown')
                ))
            else:
                logger.error('Error deploying {}: {}'.format(
                    lambda_name,
                    response
                ))
示例#20
0
def verify_appid(appid=None):
    if appid != env('SKILL_APPID'):
        raise ValueError("Invalid Application ID")
示例#21
0
 def test_convert_boolean(self):
     yaep.env('FOOD', 'True', sticky=True)
     assert (yaep.env('FOOD') is True)
     assert (yaep.env('FOOD', convert_booleans=False) == 'True')