Exemplo n.º 1
0
    def test_layer_is_not_cached(self):
        download_layers = LayerDownloader("/", ".")

        layer_path = Mock()
        layer_path.exists.return_value = False

        self.assertFalse(download_layers._is_layer_cached(layer_path))
Exemplo n.º 2
0
    def test_download_all_with_force(self, download_patch):
        download_patch.side_effect = ['/home/layer1', '/home/layer2']

        download_layers = LayerDownloader("/home", ".")

        acutal_results = download_layers.download_all(['layer1', 'layer2'], force=True)

        self.assertEquals(acutal_results, ['/home/layer1', '/home/layer2'])

        download_patch.assert_has_calls([call('layer1', True), call("layer2", True)])
Exemplo n.º 3
0
    def test_fetch_layer_uri_fails_with_no_creds(self):
        lambda_client_mock = Mock()
        lambda_client_mock.get_layer_version.side_effect = NoCredentialsError()
        download_layers = LayerDownloader("/", ".", lambda_client_mock)

        layer = Mock()
        layer.layer_arn = "arn"
        layer.version = 1

        with self.assertRaises(CredentialsRequired):
            download_layers._fetch_layer_uri(layer=layer)
Exemplo n.º 4
0
    def test_fetch_layer_uri_is_successful(self):
        lambda_client_mock = Mock()
        lambda_client_mock.get_layer_version.return_value = {"Content": {"Location": "some/uri"}}
        download_layers = LayerDownloader("/", ".", lambda_client_mock)

        layer = Mock()
        layer.layer_arn = "arn"
        layer.version = 1
        actual_uri = download_layers._fetch_layer_uri(layer=layer)

        self.assertEquals(actual_uri, "some/uri")
Exemplo n.º 5
0
    def test_fetch_layer_uri_fails_with_ResourceNotFoundException(self):
        lambda_client_mock = Mock()
        lambda_client_mock.get_layer_version.side_effect = ClientError(
            error_response={'Error': {'Code': 'ResourceNotFoundException'}}, operation_name="lambda")
        download_layers = LayerDownloader("/", ".", lambda_client_mock)

        layer = Mock()
        layer.layer_arn = "arn"
        layer.version = 1

        with self.assertRaises(ResourceNotFound):
            download_layers._fetch_layer_uri(layer=layer)
Exemplo n.º 6
0
    def test_fetch_layer_uri_re_raises_client_error(self):
        lambda_client_mock = Mock()
        lambda_client_mock.get_layer_version.side_effect = ClientError(
            error_response={'Error': {'Code': 'Unknown'}}, operation_name="lambda")
        download_layers = LayerDownloader("/", ".", lambda_client_mock)

        layer = Mock()
        layer.layer_arn = "arn"
        layer.version = 1

        with self.assertRaises(ClientError):
            download_layers._fetch_layer_uri(layer=layer)
Exemplo n.º 7
0
    def test_download_layer_that_is_cached(self, is_layer_cached_patch, create_cache_patch):
        is_layer_cached_patch.return_value = True

        download_layers = LayerDownloader("/home", ".")

        layer_mock = Mock()
        layer_mock.is_defined_within_template = False
        layer_mock.name = "layer1"

        actual = download_layers.download(layer_mock)

        self.assertEquals(actual.codeuri, '/home/layer1')

        create_cache_patch.assert_called_once_with("/home")
Exemplo n.º 8
0
    def test_create_cache(self, path_patch):
        cache_path_mock = Mock()
        path_patch.return_value = cache_path_mock

        self.assertIsNone(LayerDownloader._create_cache("./home"))

        path_patch.assert_called_once_with("./home")
        cache_path_mock.mkdir.assert_called_once_with(parents=True, exist_ok=True, mode=0o700)
Exemplo n.º 9
0
    def test_download_layer_that_was_template_defined(self, create_cache_patch, resolve_code_path_patch):

        download_layers = LayerDownloader("/home", ".")

        layer_mock = Mock()
        layer_mock.is_template_defined = True
        layer_mock.name = "layer1"
        layer_mock.codeuri = "/some/custom/path"

        resolve_code_path_patch.return_value = './some/custom/path'

        actual = download_layers.download(layer_mock)

        self.assertEquals(actual.codeuri, './some/custom/path')

        create_cache_patch.assert_not_called()
        resolve_code_path_patch.assert_called_once_with(".", "/some/custom/path")
Exemplo n.º 10
0
    def lambda_runtime(self):
        if not self._lambda_runtimes:
            layer_downloader = LayerDownloader(self._layer_cache_basedir, self.get_cwd())
            image_builder = LambdaImage(layer_downloader, self._skip_pull_image, self._force_image_build)
            self._lambda_runtimes = {
                ContainersMode.WARM: WarmLambdaRuntime(self._container_manager, image_builder),
                ContainersMode.COLD: LambdaRuntime(self._container_manager, image_builder),
            }

        return self._lambda_runtimes[self._containers_mode]
Exemplo n.º 11
0
    def test_download_layer_that_was_template_defined(self, create_cache_patch,
                                                      resolve_code_path_patch):

        download_layers = LayerDownloader("/home", ".")

        layer_mock = Mock()
        layer_mock.is_template_defined = True
        layer_mock.name = "layer1"
        layer_mock.codeuri = "/some/custom/path"

        resolve_code_path_patch.return_value = './some/custom/path'

        actual = download_layers.download(layer_mock)

        self.assertEquals(actual.codeuri, './some/custom/path')

        create_cache_patch.assert_not_called()
        resolve_code_path_patch.assert_called_once_with(
            ".", "/some/custom/path")
Exemplo n.º 12
0
    def test_create_cache(self, path_patch):
        cache_path_mock = Mock()
        path_patch.return_value = cache_path_mock

        self.assertIsNone(LayerDownloader._create_cache("./home"))

        path_patch.assert_called_once_with("./home")
        cache_path_mock.mkdir.assert_called_once_with(parents=True,
                                                      exist_ok=True,
                                                      mode=0o700)
Exemplo n.º 13
0
    def setUp(self):
        self.code_dir = {
            "echo": nodejs_lambda(ECHO_CODE),
            "sleep": nodejs_lambda(SLEEP_CODE),
            "envvar": nodejs_lambda(GET_ENV_VAR)
        }

        self.container_manager = ContainerManager()
        layer_downloader = LayerDownloader("./", "./")
        self.lambda_image = LambdaImage(layer_downloader, False, False)
        self.runtime = LambdaRuntime(self.container_manager, self.lambda_image)
Exemplo n.º 14
0
def make_service(function_provider, cwd):
    port = random_port()
    manager = ContainerManager()
    layer_downloader = LayerDownloader("./", "./")
    image_builder = LambdaImage(layer_downloader, False, False)
    local_runtime = LambdaRuntime(manager, image_builder)
    lambda_runner = LocalLambdaRunner(local_runtime=local_runtime, function_provider=function_provider, cwd=cwd)

    service = LocalLambdaInvokeService(lambda_runner, port=port, host="127.0.0.1")

    scheme = "http"
    url = "{}://127.0.0.1:{}".format(scheme, port)
    return service, port, url, scheme
Exemplo n.º 15
0
    def test_download_layer(self, is_layer_cached_patch, create_cache_patch,
                            fetch_layer_uri_patch, unzip_from_uri_patch):
        is_layer_cached_patch.return_value = False

        download_layers = LayerDownloader("/home", ".")

        layer_mock = Mock()
        layer_mock.is_defined_within_template = False
        layer_mock.name = "layer1"
        layer_mock.arn = "arn:layer:layer1:1"
        layer_mock.layer_arn = "arn:layer:layer1"

        fetch_layer_uri_patch.return_value = "layer/uri"

        actual = download_layers.download(layer_mock)

        self.assertEquals(actual.codeuri, "/home/layer1")

        create_cache_patch.assert_called_once_with("/home")
        fetch_layer_uri_patch.assert_called_once_with(layer_mock)
        unzip_from_uri_patch.assert_called_once_with("layer/uri",
                                                     '/home/layer1.zip',
                                                     unzip_output_dir='/home/layer1',
                                                     progressbar_label="Downloading arn:layer:layer1")
Exemplo n.º 16
0
    def test_download_layer(self, is_layer_cached_patch, create_cache_patch,
                            fetch_layer_uri_patch, unzip_from_uri_patch):
        is_layer_cached_patch.return_value = False

        download_layers = LayerDownloader("/home", ".")

        layer_mock = Mock()
        layer_mock.is_defined_within_template = False
        layer_mock.name = "layer1"
        layer_mock.arn = "arn:layer:layer1:1"
        layer_mock.layer_arn = "arn:layer:layer1"

        fetch_layer_uri_patch.return_value = "layer/uri"

        actual = download_layers.download(layer_mock)

        self.assertEquals(actual.codeuri, "/home/layer1")

        create_cache_patch.assert_called_once_with("/home")
        fetch_layer_uri_patch.assert_called_once_with(layer_mock)
        unzip_from_uri_patch.assert_called_once_with("layer/uri",
                                                     '/home/layer1.zip',
                                                     unzip_output_dir='/home/layer1',
                                                     progressbar_label="Downloading arn:layer:layer1")
Exemplo n.º 17
0
    def test_debug_port_is_created_on_host(self):

        layer_downloader = LayerDownloader("./", "./")
        image_builder = LambdaImage(layer_downloader, False, False)
        container = LambdaContainer(self.runtime, self.handler, self.code_dir, self.layers, image_builder, debug_options=self.debug_context)

        with self._create(container):

            container.start()

            # After container is started, query the container to make sure it is bound to the right ports
            port_binding = self.docker_client.api.port(container.id, self.debug_port)
            self.assertIsNotNone(port_binding, "Container must be bound to a port on host machine")
            self.assertEquals(1, len(port_binding), "Only one port must be bound to the container")
            self.assertEquals(port_binding[0]["HostPort"], str(self.debug_port))
Exemplo n.º 18
0
    def test_must_invoke(self):
        input_event = '"some data"'
        expected_env_vars = {
            "var1": "override_value1",
            "var2": "shell_env_value2"
        }

        manager = ContainerManager()
        layer_downloader = LayerDownloader("./", "./")
        lambda_image = LambdaImage(layer_downloader, False, False)
        local_runtime = LambdaRuntime(manager, lambda_image)
        runner = LocalLambdaRunner(local_runtime,
                                   self.mock_function_provider,
                                   self.cwd,
                                   self.env_var_overrides,
                                   debug_context=None)

        # Append the real AWS credentials to the expected values.
        creds = runner.get_aws_creds()
        # default value for creds is not configured by the test. But coming from a downstream class
        expected_env_vars["AWS_SECRET_ACCESS_KEY"] = creds.get(
            "secret", "defaultsecret")
        expected_env_vars["AWS_ACCESS_KEY_ID"] = creds.get("key", "defaultkey")
        expected_env_vars["AWS_REGION"] = creds.get("region", "us-east-1")

        stdout_stream = io.BytesIO()
        stderr_stream = io.BytesIO()

        stdout_stream_writer = StreamWriter(stdout_stream)
        stderr_stream_writer = StreamWriter(stderr_stream)
        runner.invoke(self.function_name,
                      input_event,
                      stdout=stdout_stream_writer,
                      stderr=stderr_stream_writer)

        # stderr is where the Lambda container runtime logs are available. It usually contains requestId, start time
        # etc. So it is non-zero in size
        self.assertGreater(len(stderr_stream.getvalue().strip()), 0,
                           "stderr stream must contain data")

        # This should contain all the environment variables passed to the function
        actual_output = json.loads(
            stdout_stream.getvalue().strip().decode("utf-8"))

        for key, value in expected_env_vars.items():
            self.assertTrue(key in actual_output,
                            "Key '{}' must be in function output".format(key))
            self.assertEqual(actual_output.get(key), value)
Exemplo n.º 19
0
    def test_container_is_attached_to_network(self):
        layer_downloader = LayerDownloader("./", "./")
        image_builder = LambdaImage(layer_downloader, False, False)
        container = LambdaContainer(self.runtime, self.handler, self.code_dir, self.layers, image_builder)

        with self._network_create() as network:

            # Ask the container to attach to the network
            container.network_id = network.id
            with self._create(container):

                container.start()

                # Now that the container has been created, it would be connected to the network
                # Fetch the latest information about this network from server
                network.reload()

                self.assertEquals(1, len(network.containers))
                self.assertEquals(container.id, network.containers[0].id)
Exemplo n.º 20
0
    def test_basic_creation(self):
        """
        A docker container must be successfully created
        """
        layer_downloader = LayerDownloader("./", "./")
        image_builder = LambdaImage(layer_downloader, False, False)
        container = LambdaContainer(self.runtime, self.handler, self.code_dir, self.layers, image_builder)

        self.assertIsNone(container.id, "Container must not have ID before creation")

        # Create the container and verify its properties
        with self._create(container):
            self.assertIsNotNone(container.id, "Container must have an ID")

            # Call Docker API to make sure container indeed exists
            actual_container = self.docker_client.containers.get(container.id)
            self.assertEquals(actual_container.status, "created")
            self.assertTrue(self.expected_docker_image in actual_container.image.tags,
                            "Image name of the container must be " + self.expected_docker_image)
Exemplo n.º 21
0
    def local_lambda_runner(self):
        """
        Returns an instance of the runner capable of running Lambda functions locally

        :return samcli.commands.local.lib.local_lambda.LocalLambdaRunner: Runner configured to run Lambda functions
            locally
        """

        layer_downloader = LayerDownloader(self._layer_cache_basedir,
                                           self.get_cwd())
        image_builder = LambdaImage(layer_downloader, self._skip_pull_image,
                                    self._force_image_build)

        lambda_runtime = LambdaRuntime(self._container_manager, image_builder)
        return LocalLambdaRunner(local_runtime=lambda_runtime,
                                 function_provider=self._function_provider,
                                 cwd=self.get_cwd(),
                                 env_vars_values=self._env_vars_value,
                                 debug_context=self._debug_context)
Exemplo n.º 22
0
    def setUp(self):
        self.code_dir = nodejs_lambda(SLEEP_CODE)

        Input = namedtuple("Input", ["timeout", "sleep", "check_stdout"])
        self.inputs = [
            Input(sleep=1, timeout=10, check_stdout=True),
            Input(sleep=2, timeout=10, check_stdout=True),
            Input(sleep=3, timeout=10, check_stdout=True),
            Input(sleep=5, timeout=10, check_stdout=True),
            Input(sleep=8, timeout=10, check_stdout=True),
            Input(sleep=13, timeout=12, check_stdout=False),  # Must timeout
            Input(sleep=21, timeout=20, check_stdout=False),  # Must timeout. So stdout will be empty
        ]
        random.shuffle(self.inputs)

        container_manager = ContainerManager()
        layer_downloader = LayerDownloader("./", "./")
        self.lambda_image = LambdaImage(layer_downloader, False, False)
        self.runtime = LambdaRuntime(container_manager, self.lambda_image)
    def test_function_result_is_available_in_stdout_and_logs_in_stderr(self):

        # This is the JSON result from Lambda function
        # Convert to proper binary type to be compatible with Python 2 & 3
        expected_output = b'{"a":"b"}'
        expected_stderr = b"**This string is printed from Lambda function**"

        layer_downloader = LayerDownloader("./", "./")
        image_builder = LambdaImage(layer_downloader, False)
        container = LambdaContainer(self.runtime, self.handler, self.code_dir,
                                    self.layers, image_builder)
        stdout_stream = io.BytesIO()
        stderr_stream = io.BytesIO()

        with self._create(container):

            container.start()
            container.wait_for_logs(stdout=stdout_stream, stderr=stderr_stream)

            function_output = stdout_stream.getvalue()
            function_stderr = stderr_stream.getvalue()

            self.assertEquals(function_output.strip(), expected_output)
            self.assertIn(expected_stderr, function_stderr)
Exemplo n.º 24
0
    def test_initialization(self):
        download_layers = LayerDownloader("/some/path", ".")

        self.assertEquals(download_layers.layer_cache, "/some/path")
    def setUp(self):
        self.host = "127.0.0.1"
        self.port = random.randint(30000, 40000)  # get a random port
        self.url = "http://{}:{}".format(self.host, self.port)

        self.code_abs_path = nodejs_lambda(API_GATEWAY_ECHO_EVENT)

        # Let's convert this absolute path to relative path. Let the parent be the CWD, and codeuri be the folder
        self.cwd = os.path.dirname(self.code_abs_path)
        self.code_uri = os.path.relpath(
            self.code_abs_path,
            self.cwd)  # Get relative path with respect to CWD

        # Setup a static file in the directory
        self.static_dir = "mystaticdir"
        self.static_file_name = "myfile.txt"
        self.static_file_content = "This is a static file"
        self._setup_static_file(
            os.path.join(
                self.cwd,
                self.static_dir),  # Create static directory with in cwd
            self.static_file_name,
            self.static_file_content,
        )

        # Create one Lambda function
        self.function_name = "name"
        self.function = provider.Function(
            name=self.function_name,
            runtime="nodejs4.3",
            memory=256,
            timeout=5,
            handler="index.handler",
            codeuri=self.code_uri,
            environment={},
            rolearn=None,
            layers=[],
        )
        self.mock_function_provider = Mock()
        self.mock_function_provider.get.return_value = self.function

        # Setup two APIs pointing to the same function
        routes = [
            Route(path="/get",
                  methods=["GET"],
                  function_name=self.function_name),
            Route(path="/post",
                  methods=["POST"],
                  function_name=self.function_name),
        ]
        api = Api(routes=routes)

        self.api_provider_mock = Mock()
        self.api_provider_mock.get_all.return_value = api

        # Now wire up the Lambda invoker and pass it through the context
        self.lambda_invoke_context_mock = Mock()
        manager = ContainerManager()
        layer_downloader = LayerDownloader("./", "./")
        lambda_image = LambdaImage(layer_downloader, False, False)
        local_runtime = LambdaRuntime(manager, lambda_image)
        lambda_runner = LocalLambdaRunner(local_runtime,
                                          self.mock_function_provider,
                                          self.cwd,
                                          debug_context=None)
        self.lambda_invoke_context_mock.local_lambda_runner = lambda_runner
        self.lambda_invoke_context_mock.get_cwd.return_value = self.cwd