{-# LANGUAGE DataKinds                   #-}
{-# LANGUAGE DeriveGeneric               #-}
{-# LANGUAGE FlexibleInstances           #-}
{-# LANGUAGE GeneralizedNewtypeDeriving  #-}
{-# LANGUAGE LambdaCase                  #-}
{-# LANGUAGE NoImplicitPrelude           #-}
{-# LANGUAGE OverloadedStrings           #-}
{-# LANGUAGE RecordWildCards             #-}
{-# LANGUAGE TypeFamilies                #-}

{-# OPTIONS_GHC -fno-warn-unused-imports #-}

-- Module      : Network.AWS.EMR.RunJobFlow
-- Copyright   : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
-- License     : This Source Code Form is subject to the terms of
--               the Mozilla Public License, v. 2.0.
--               A copy of the MPL can be found in the LICENSE file or
--               you can obtain it at http://mozilla.org/MPL/2.0/.
-- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>
-- Stability   : experimental
-- Portability : non-portable (GHC extensions)
--
-- Derived from AWS service descriptions, licensed under Apache 2.0.

-- | RunJobFlow creates and starts running a new job flow. The job flow will run
-- the steps specified. Once the job flow completes, the cluster is stopped and
-- the HDFS partition is lost. To prevent loss of data, configure the last step
-- of the job flow to store results in Amazon S3. If the 'JobFlowInstancesConfig' 'KeepJobFlowAliveWhenNoSteps' parameter is set to 'TRUE', the job flow will transition to the WAITING state
-- rather than shutting down once the steps have completed.
--
-- For additional protection, you can set the 'JobFlowInstancesConfig' 'TerminationProtected' parameter to 'TRUE' to lock the job flow and prevent it from being terminated
-- by API call, user intervention, or in the event of a job flow error.
--
-- A maximum of 256 steps are allowed in each job flow.
--
-- If your job flow is long-running (such as a Hive data warehouse) or complex,
-- you may require more than 256 steps to process your data. You can bypass the
-- 256-step limitation in various ways, including using the SSH shell to connect
-- to the master node and submitting queries directly to the software running on
-- the master node, such as Hive and Hadoop. For more information on how to do
-- this, go to <http://docs.aws.amazon.com/ElasticMapReduce/latest/DeveloperGuide/AddMoreThan256Steps.html Add More than 256 Steps to a Job Flow> in the /Amazon ElasticMapReduce Developer's Guide/.
--
-- For long running job flows, we recommend that you periodically store your
-- results.
--
-- <http://docs.aws.amazon.com/ElasticMapReduce/latest/API/API_RunJobFlow.html>
module Network.AWS.EMR.RunJobFlow
    (
    -- * Request
      RunJobFlow
    -- ** Request constructor
    , runJobFlow
    -- ** Request lenses
    , rjfAdditionalInfo
    , rjfAmiVersion
    , rjfBootstrapActions
    , rjfInstances
    , rjfJobFlowRole
    , rjfLogUri
    , rjfName
    , rjfNewSupportedProducts
    , rjfServiceRole
    , rjfSteps
    , rjfSupportedProducts
    , rjfTags
    , rjfVisibleToAllUsers

    -- * Response
    , RunJobFlowResponse
    -- ** Response constructor
    , runJobFlowResponse
    -- ** Response lenses
    , rjfrJobFlowId
    ) where

import Network.AWS.Data (Object)
import Network.AWS.Prelude
import Network.AWS.Request.JSON
import Network.AWS.EMR.Types
import qualified GHC.Exts

data RunJobFlow = RunJobFlow
    { _rjfAdditionalInfo       :: Maybe Text
    , _rjfAmiVersion           :: Maybe Text
    , _rjfBootstrapActions     :: List "BootstrapActions" BootstrapActionConfig
    , _rjfInstances            :: JobFlowInstancesConfig
    , _rjfJobFlowRole          :: Maybe Text
    , _rjfLogUri               :: Maybe Text
    , _rjfName                 :: Text
    , _rjfNewSupportedProducts :: List "NewSupportedProducts" SupportedProductConfig
    , _rjfServiceRole          :: Maybe Text
    , _rjfSteps                :: List "Steps" StepConfig
    , _rjfSupportedProducts    :: List "SupportedProducts" Text
    , _rjfTags                 :: List "Tags" Tag
    , _rjfVisibleToAllUsers    :: Maybe Bool
    } deriving (Eq, Read, Show)

-- | 'RunJobFlow' constructor.
--
-- The fields accessible through corresponding lenses are:
--
-- * 'rjfAdditionalInfo' @::@ 'Maybe' 'Text'
--
-- * 'rjfAmiVersion' @::@ 'Maybe' 'Text'
--
-- * 'rjfBootstrapActions' @::@ ['BootstrapActionConfig']
--
-- * 'rjfInstances' @::@ 'JobFlowInstancesConfig'
--
-- * 'rjfJobFlowRole' @::@ 'Maybe' 'Text'
--
-- * 'rjfLogUri' @::@ 'Maybe' 'Text'
--
-- * 'rjfName' @::@ 'Text'
--
-- * 'rjfNewSupportedProducts' @::@ ['SupportedProductConfig']
--
-- * 'rjfServiceRole' @::@ 'Maybe' 'Text'
--
-- * 'rjfSteps' @::@ ['StepConfig']
--
-- * 'rjfSupportedProducts' @::@ ['Text']
--
-- * 'rjfTags' @::@ ['Tag']
--
-- * 'rjfVisibleToAllUsers' @::@ 'Maybe' 'Bool'
--
runJobFlow :: Text -- ^ 'rjfName'
           -> JobFlowInstancesConfig -- ^ 'rjfInstances'
           -> RunJobFlow
runJobFlow p1 p2 = RunJobFlow
    { _rjfName                 = p1
    , _rjfInstances            = p2
    , _rjfLogUri               = Nothing
    , _rjfAdditionalInfo       = Nothing
    , _rjfAmiVersion           = Nothing
    , _rjfSteps                = mempty
    , _rjfBootstrapActions     = mempty
    , _rjfSupportedProducts    = mempty
    , _rjfNewSupportedProducts = mempty
    , _rjfVisibleToAllUsers    = Nothing
    , _rjfJobFlowRole          = Nothing
    , _rjfServiceRole          = Nothing
    , _rjfTags                 = mempty
    }

-- | A JSON string for selecting additional features.
rjfAdditionalInfo :: Lens' RunJobFlow (Maybe Text)
rjfAdditionalInfo =
    lens _rjfAdditionalInfo (\s a -> s { _rjfAdditionalInfo = a })

-- | The version of the Amazon Machine Image (AMI) to use when launching Amazon
-- EC2 instances in the job flow. The following values are valid:
--
-- "latest" (uses the latest AMI) The version number of the AMI to use, for
-- example, "2.0"  If the AMI supports multiple versions of Hadoop (for example,
-- AMI 1.0 supports both Hadoop 0.18 and 0.20) you can use the 'JobFlowInstancesConfig' 'HadoopVersion' parameter to modify the version of Hadoop from the defaults
-- shown above.
--
-- For details about the AMI versions currently supported by Amazon Elastic
-- MapReduce, go to <http://docs.aws.amazon.com/ElasticMapReduce/latest/DeveloperGuide/EnvironmentConfig_AMIVersion.html#ami-versions-supported AMI Versions Supported in Elastic MapReduce> in the /AmazonElastic MapReduce Developer's Guide./
rjfAmiVersion :: Lens' RunJobFlow (Maybe Text)
rjfAmiVersion = lens _rjfAmiVersion (\s a -> s { _rjfAmiVersion = a })

-- | A list of bootstrap actions that will be run before Hadoop is started on the
-- cluster nodes.
rjfBootstrapActions :: Lens' RunJobFlow [BootstrapActionConfig]
rjfBootstrapActions =
    lens _rjfBootstrapActions (\s a -> s { _rjfBootstrapActions = a })
        . _List

-- | A specification of the number and type of Amazon EC2 instances on which to
-- run the job flow.
rjfInstances :: Lens' RunJobFlow JobFlowInstancesConfig
rjfInstances = lens _rjfInstances (\s a -> s { _rjfInstances = a })

-- | An IAM role for the job flow. The EC2 instances of the job flow assume this
-- role. The default role is 'EMRJobflowDefault'. In order to use the default
-- role, you must have already created it using the CLI.
rjfJobFlowRole :: Lens' RunJobFlow (Maybe Text)
rjfJobFlowRole = lens _rjfJobFlowRole (\s a -> s { _rjfJobFlowRole = a })

-- | The location in Amazon S3 to write the log files of the job flow. If a value
-- is not provided, logs are not created.
rjfLogUri :: Lens' RunJobFlow (Maybe Text)
rjfLogUri = lens _rjfLogUri (\s a -> s { _rjfLogUri = a })

-- | The name of the job flow.
rjfName :: Lens' RunJobFlow Text
rjfName = lens _rjfName (\s a -> s { _rjfName = a })

-- | A list of strings that indicates third-party software to use with the job
-- flow that accepts a user argument list. EMR accepts and forwards the argument
-- list to the corresponding installation script as bootstrap action arguments.
-- For more information, see <http://docs.aws.amazon.com/ElasticMapReduce/latest/DeveloperGuide/emr-mapr.html Launch a Job Flow on the MapR Distribution forHadoop>. Currently supported values are:
--
-- "mapr-m3" - launch the job flow using MapR M3 Edition. "mapr-m5" - launch
-- the job flow using MapR M5 Edition. "mapr" with the user arguments specifying
-- "--edition,m3" or "--edition,m5" - launch the job flow using MapR M3 or M5
-- Edition respectively.
rjfNewSupportedProducts :: Lens' RunJobFlow [SupportedProductConfig]
rjfNewSupportedProducts =
    lens _rjfNewSupportedProducts (\s a -> s { _rjfNewSupportedProducts = a })
        . _List

-- | The IAM role that will be assumed by the Amazon EMR service to access AWS
-- resources on your behalf.
rjfServiceRole :: Lens' RunJobFlow (Maybe Text)
rjfServiceRole = lens _rjfServiceRole (\s a -> s { _rjfServiceRole = a })

-- | A list of steps to be executed by the job flow.
rjfSteps :: Lens' RunJobFlow [StepConfig]
rjfSteps = lens _rjfSteps (\s a -> s { _rjfSteps = a }) . _List

-- | A list of strings that indicates third-party software to use with the job
-- flow. For more information, go to <http://docs.aws.amazon.com/ElasticMapReduce/latest/DeveloperGuide/emr-supported-products.html Use Third Party Applications with Amazon EMR>
-- . Currently supported values are:
--
-- "mapr-m3" - launch the job flow using MapR M3 Edition. "mapr-m5" - launch
-- the job flow using MapR M5 Edition.
rjfSupportedProducts :: Lens' RunJobFlow [Text]
rjfSupportedProducts =
    lens _rjfSupportedProducts (\s a -> s { _rjfSupportedProducts = a })
        . _List

-- | A list of tags to associate with a cluster and propagate to Amazon EC2
-- instances.
rjfTags :: Lens' RunJobFlow [Tag]
rjfTags = lens _rjfTags (\s a -> s { _rjfTags = a }) . _List

-- | Whether the job flow is visible to all IAM users of the AWS account
-- associated with the job flow. If this value is set to 'true', all IAM users of
-- that AWS account can view and (if they have the proper policy permissions
-- set) manage the job flow. If it is set to 'false', only the IAM user that
-- created the job flow can view and manage it.
rjfVisibleToAllUsers :: Lens' RunJobFlow (Maybe Bool)
rjfVisibleToAllUsers =
    lens _rjfVisibleToAllUsers (\s a -> s { _rjfVisibleToAllUsers = a })

newtype RunJobFlowResponse = RunJobFlowResponse
    { _rjfrJobFlowId :: Maybe Text
    } deriving (Eq, Ord, Read, Show, Monoid)

-- | 'RunJobFlowResponse' constructor.
--
-- The fields accessible through corresponding lenses are:
--
-- * 'rjfrJobFlowId' @::@ 'Maybe' 'Text'
--
runJobFlowResponse :: RunJobFlowResponse
runJobFlowResponse = RunJobFlowResponse
    { _rjfrJobFlowId = Nothing
    }

-- | An unique identifier for the job flow.
rjfrJobFlowId :: Lens' RunJobFlowResponse (Maybe Text)
rjfrJobFlowId = lens _rjfrJobFlowId (\s a -> s { _rjfrJobFlowId = a })

instance ToPath RunJobFlow where
    toPath = const "/"

instance ToQuery RunJobFlow where
    toQuery = const mempty

instance ToHeaders RunJobFlow

instance ToJSON RunJobFlow where
    toJSON RunJobFlow{..} = object
        [ "Name"                 .= _rjfName
        , "LogUri"               .= _rjfLogUri
        , "AdditionalInfo"       .= _rjfAdditionalInfo
        , "AmiVersion"           .= _rjfAmiVersion
        , "Instances"            .= _rjfInstances
        , "Steps"                .= _rjfSteps
        , "BootstrapActions"     .= _rjfBootstrapActions
        , "SupportedProducts"    .= _rjfSupportedProducts
        , "NewSupportedProducts" .= _rjfNewSupportedProducts
        , "VisibleToAllUsers"    .= _rjfVisibleToAllUsers
        , "JobFlowRole"          .= _rjfJobFlowRole
        , "ServiceRole"          .= _rjfServiceRole
        , "Tags"                 .= _rjfTags
        ]

instance AWSRequest RunJobFlow where
    type Sv RunJobFlow = EMR
    type Rs RunJobFlow = RunJobFlowResponse

    request  = post "RunJobFlow"
    response = jsonResponse

instance FromJSON RunJobFlowResponse where
    parseJSON = withObject "RunJobFlowResponse" $ \o -> RunJobFlowResponse
        <$> o .:? "JobFlowId"