packages feed

aws-lambda-0.1.0.0: src/Aws/Lambda/Commands/UploadFunction.hs

-- Copyright (c) 2013-2014 PivotCloud, Inc.
--
-- Aws.Lambda.Commands.UploadFunction
--
-- Please feel free to contact us at licensing@pivotmail.com with any
-- contributions, additions, or other feedback; we would love to hear from
-- you.
--
-- 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.

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE UnicodeSyntax #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}

module Aws.Lambda.Commands.UploadFunction
( -- * Request
  UploadFunction(..)
  -- ** Lenses
, ufDescription
, ufFunctionName
, ufHandler
, ufMemorySize
, ufMode
, ufRole
, ufRuntime
, ufTimeout
, ufRawCode
, ufLastModified
) where

import Aws.Lambda.Core
import Aws.Lambda.Types

import qualified Codec.Archive.Zip as Z
import Control.Lens hiding ((<.>))
import Data.Aeson
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as LB
import qualified Data.Text as T
import Data.Time
import Data.Time.Clock.POSIX
import Network.HTTP.Types
import Prelude.Unicode
import System.FilePath

-- | Creates a new Lambda function or updates an existing function. The
-- function metadata is created from the request parameters, and the code for
-- the function is provided by a @.zip@ file in the request body. If the
-- function name already exists, the existing Lambda function is updated with
-- the new code and metadata.
--
-- This operation requires permission for the @lambda:UploadFunction@ action.
--
-- Note that these bindings take care of packaging up the function source code
-- as a @.zip@ file automatically.
--
data UploadFunction
  = UploadFunction
  { _ufDescription ∷ !T.Text
  -- ^ A short, user-defined function description. Lambda does not use this
  -- value. Assign a meaningful description as you see fit.

  , _ufFunctionName ∷ !T.Text
  -- ^ The name you want to assign to the function you are uploading.

  , _ufHandler ∷ !T.Text
  -- ^ The function that Lambda calls to begin execution. For Node.js, it is
  -- the @module-name.export@ value in your function

  , _ufMemorySize ∷ !Int
  -- ^ The amount of memory, in MB, your Lambda function is given. Lambda uses
  -- this memory size to infer the amount of CPU allocated to your function.
  -- Your function use-case determines your CPU and memory requirements. For
  -- example, database operation might need less memory compared to image
  -- processing function. The default value is 128 MB. The value must be a
  -- multiple of 64 MB.

  , _ufMode ∷ !FunctionMode
  -- ^ How the Lambda function will be invoked.

  , _ufRole ∷ !Arn
  -- ^ The Amazon Resource Name (ARN) of the IAM role that Lambda assumes when
  -- it executes your function to access any other Amazon Web Services (AWS)
  -- resources.

  , _ufRuntime ∷ !FunctionRuntime
  -- ^ The runtime environment for the Lambda function you are uploading.

  , _ufTimeout ∷ !Int
  -- ^ The function execution time at which Lambda should terminate the
  -- function. Because the execution time has cost implications, we recommend
  -- you set this value based on your expected execution time. The default is 3
  -- seconds.

  , _ufRawCode ∷ !B.ByteString
  -- ^ The raw code of the function (which will be packaged into a ZIP archive
  -- automatically).

  , _ufLastModified ∷ !UTCTime
  -- ^ The last-modified date to be assigned to the file in the ZIP archive.
  } deriving (Eq, Show)

makeLenses ''UploadFunction

newtype UploadFunctionResponse
  = UploadFunctionResponse
  { _ufrConfiguration ∷ FunctionConfiguration
  } deriving (Eq, Show, FromJSON)

instance LambdaTransaction UploadFunction B.ByteString UploadFunctionResponse where
  buildQuery uf =
    lambdaQuery' PUT ["functions", uf ^. ufFunctionName] archivedSource
      & lqParams
        %~ (at "Description" ?~ uf ^. ufDescription)
         ∘ (at "Handler" ?~ uf ^. ufHandler)
         ∘ (at "MemorySize" ?~ uf ^. ufMemorySize ∘ to (T.pack ∘ show))
         ∘ (at "Mode" ?~ uf ^. ufMode ∘ re _TextFunctionMode)
         ∘ (at "Role" ?~ uf ^. ufRole ∘ to arnToText)
         ∘ (at "Runtime" ?~ uf ^. ufRuntime ∘ re _TextFunctionRuntime)
         ∘ (at "Timeout" ?~ uf ^. ufTimeout ∘ to (T.pack ∘ show))
    where
      extension =
        case uf ^. ufRuntime of
          FunctionRuntimeNodeJs → "js"

      archivedSource =
        LB.toStrict ∘ Z.fromArchive ∘ flip Z.addEntryToArchive Z.emptyArchive $
          Z.toEntry
            (uf ^. ufFunctionName ∘ to T.unpack <.> extension)
            (uf ^. ufLastModified ∘ to (round ∘ utcTimeToPOSIXSeconds))
            (uf ^. ufRawCode ∘ to LB.fromStrict)