#!/usr/bin/env perl

use strict;
use warnings;

use Getopt::Long;
use JSON;

my( $prettyPrint, $sourceBucket, $VERSION );
GetOptions(
	'pretty-print'	=> \$prettyPrint,
	'source-bucket'	=> \$sourceBucket,
	'version=s'		=> \$VERSION,
);
if(! $sourceBucket) { $sourceBucket = { "Fn::Join" => [ "-", [ "condor-annex", { "Ref" => "AWS::Region" } ] ] }; }
if(! $VERSION) {
	die( "You must specify --version.\n" );
}
my $sfrKey = "sfr-lease-${VERSION}.zip";
my $odiKey = "odi-lease-${VERSION}.zip";
my $ccKey = "check-connectivity-${VERSION}.zip";

	my $template;
	$template->{ AWSTemplateFormatVersion } = "2010-09-09";
	$template->{ Description } = "HTCondor Annex: Lambda Functions";

	$template->{ Parameters } = {
		"S3BucketName" => {
			Type => "String"
		},
		"S3FileName" => {
			Type => "String",
			Default => "config-*.tar.gz"
		}
	};

	$template->{ Outputs } = {
		sfrLeaseFunctionARN => {
			Value => { "Fn::GetAtt" => [ "sfrLeaseFunction", "Arn" ] }
		},
		odiLeaseFunctionARN => {
			Value => { "Fn::GetAtt" => [ "odiLeaseFunction", "Arn" ] }
		},
		ccFunctionARN => {
			Value => { "Fn::GetAtt" => [ "ccFunction", "Arn" ] }
		}
	};

	my $lambdaBasicExecutionPolicy = {
		PolicyName => "lambda_basic_execution",
		PolicyDocument => {
			Version => "2012-10-17",
			Statement => [ {
				Effect => "Allow",
				Action => [
					"logs:CreateLogGroup",
					"logs:CreateLogStream",
					"logs:PutLogEvents"
					],
				Resource => "arn:aws:logs:*:*:*"
			} ]
		}
	};

	my $assumeRoleFromLambda = {
		Version => "2012-10-17",
		Statement => [ {
			Effect => "Allow",
			Action => [ "sts:AssumeRole" ],
			Principal => { Service => [ "lambda.amazonaws.com" ] }
		} ]
	};

	$template->{ Resources }->{ ccFunctionRole } = {
		Type => "AWS::IAM::Role",
		Properties => {
			AssumeRolePolicyDocument => $assumeRoleFromLambda,
			Policies => [
				$lambdaBasicExecutionPolicy
			]
		}
	};

	my $resource = { "Fn::Join" => [ "", [
		"arn:aws:s3:::",
		{ "Ref" => "S3BucketName" },
		"/",
		{ "Ref" => "S3FileName" }
	] ] };

	$template->{ Resources }->{ LeaseFunctionRole } = {
		Type => "AWS::IAM::Role",
		Properties => {
			AssumeRolePolicyDocument => $assumeRoleFromLambda,
			Policies => [
				$lambdaBasicExecutionPolicy,
				{
					PolicyName => "LambdaLeasePolicy",
					PolicyDocument => {
						Version => "2012-10-17",
						Statement => [
							{
								Effect => "Allow",
								Action => [
									"events:*",

									"ec2:CancelSpotFleetRequests",
									"ec2:DescribeSpotFleetRequests",

									"ec2:DescribeInstances",
									"ec2:TerminateInstances",
								],
								Resource => "*"
							},
							{
								Effect => "Allow",
								Action => [
									"s3:DeleteObject",
								],
								Resource => $resource
							}
						]
					}
				}
			]
		}
	};

	$template->{ Resources }->{ sfrLeaseFunction } = {
		Type => "AWS::Lambda::Function",
		DependsOn => "LeaseFunctionRole",
		Properties => {
			Role => { "Fn::GetAtt" => [ "LeaseFunctionRole", "Arn" ] },
			Runtime => "nodejs18.x",
			Timeout => 60,
			Handler => "sfr-lease.handler",
			Code => {
				S3Bucket => $sourceBucket,
				S3Key => $sfrKey
			}
		}
	};

	$template->{ Resources }->{ odiLeaseFunction } = {
		Type => "AWS::Lambda::Function",
		DependsOn => "LeaseFunctionRole",
		Properties => {
			Role => { "Fn::GetAtt" => [ "LeaseFunctionRole", "Arn" ] },
			Runtime => "nodejs18.x",
			Timeout => 60,
			Handler => "odi-lease.handler",
			Code => {
				S3Bucket => $sourceBucket,
				S3Key => $odiKey
			}
		}
	};

	$template->{ Resources }->{ ccFunction } = {
		Type => "AWS::Lambda::Function",
		DependsOn => "ccFunctionRole",
		Properties => {
			FunctionName => "HTCondorAnnex-CheckConnectivity",
			Role => { "Fn::GetAtt" => [ "LeaseFunctionRole", "Arn" ] },
			Runtime => "python3.8",
			Timeout => 5,
			Handler => "check-connectivity.condor_ping_handler",
			Code => {
				S3Bucket => $sourceBucket,
				S3Key => $ccKey
			}
		}
	};

	$template->{ Resources }->{ sfrLeaseFunctionPermissions } = {
		Type => "AWS::Lambda::Permission",
		DependsOn => "sfrLeaseFunction",
		Properties => {
			Action => "lambda:InvokeFunction",
			FunctionName => { "Fn::GetAtt" => [ "sfrLeaseFunction", "Arn" ] },
			Principal => "events.amazonaws.com",
			SourceArn => { "Fn::Join" => [ ":", [ "arn:aws:events", { "Ref" => "AWS::Region" }, { "Ref" => "AWS::AccountId" }, "*" ] ] }
		}
	};

	$template->{ Resources }->{ odiLeaseFunctionPermissions } = {
		Type => "AWS::Lambda::Permission",
		DependsOn => "odiLeaseFunction",
		Properties => {
			Action => "lambda:InvokeFunction",
			FunctionName => { "Fn::GetAtt" => [ "odiLeaseFunction", "Arn" ] },
			Principal => "events.amazonaws.com",
			SourceArn => { "Fn::Join" => [ ":", [ "arn:aws:events", { "Ref" => "AWS::Region" }, { "Ref" => "AWS::AccountId" }, "*" ] ] }
		}
	};

if( defined( $prettyPrint ) ) {
	print( to_json( $template, { utf8 => 1, pretty => 1 } ) . "\n" );
} else {
	print( encode_json( $template ) . "\n" );
}

exit( 0 );
