# Task 051


Create an aws_lex_bot for ordering pizzas and include a lambda function. The Lambda function code should be packaged inline using a `data "archive_file"` resource (do not reference external zip files). Include a `aws_lambda_permission` resource to allow Lex to invoke the Lambda function.

## Intent

Has one resource "aws_lex_bot" with at least one "aws_lex_intent" resource and a "aws_lambda_function" resource with a "aws_lambda_permissions" resource

## Reference Terraform solution

terraform {
  required_version = ">= 1.15.0"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 6.0"
    }
  }
}

provider "aws" {
  region  = "us-east-1"
}

resource "aws_lambda_permission" "allow_lex_to_start_execution" {
  statement_id  = "AllowExecutionFromLex"
  action        = "lambda:InvokeFunction"
  function_name = aws_lambda_function.hello_pizza.function_name
  principal     = "lex.amazonaws.com"
  # source_arn    = "${aws_lex_bot.order_pizza.arn}:$LATEST"
}

data "archive_file" "hello_pizza" {
  type        = "zip"
  output_path = "${path.module}/hello_pizza.zip"

  source {
    content  = "def handler(event, context): return {'statusCode': 200}"
    filename = "hello_pizza.py"
  }
}

resource "aws_lambda_function" "hello_pizza" {
  function_name = "hello_pizza"
  role          = aws_iam_role.iam_exec_role.arn
  filename      = data.archive_file.hello_pizza.output_path
  source_code_hash = data.archive_file.hello_pizza.output_base64sha256
  handler       = "hello_pizza.handler"
  runtime       = "python3.12"
}

resource "aws_iam_role" "iam_exec_role" {
  name = "iam-exec-role"
  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = "sts:AssumeRole"
        Effect = "Allow"
        Sid    = ""
        Principal = {
          Service = "lambda.amazonaws.com"
        }
      },
    ]
  })
}

resource "aws_lex_intent" "OrderPizza" {
  name = "OrderPizza"

  sample_utterances = [
    "I would like to pick up a pizza",
    "I would like to order some pizzas",
  ]

  slot {
    name                     = "PizzaType"
    description              = "Type of pizza to order"
    slot_constraint          = "Required" 
    slot_type                = "AMAZON.AlphaNumeric"
    priority                 = 1
    value_elicitation_prompt {
      message {
        content             = "What type of pizza would you like?"
        content_type        = "PlainText"
      }
      max_attempts         = 2
    }
  }

  fulfillment_activity {
    type = "CodeHook"
    code_hook {
      uri            = aws_lambda_function.hello_pizza.arn
      message_version = "1.0"
    }
  }
}

resource "aws_lex_bot" "order_pizza" {
  name     = "OrderPizza"
  description  = "Orders a pizza from a local pizzeria"
  
  idle_session_ttl_in_seconds = 600
  locale = "en-US"

  child_directed = false

  voice_id = "Salli"
  process_behavior = "BUILD"

  clarification_prompt {
    max_attempts = 2
    message {
      content      = "I didn't understand that, can you please repeat?"
      content_type = "PlainText"
    }
  }
  
  abort_statement {
    message {
      content      = "Sorry, I could not understand. Goodbye."
      content_type = "PlainText"
    }
  }
  
  intent {
    intent_name    = aws_lex_intent.OrderPizza.name
    intent_version = aws_lex_intent.OrderPizza.version
  }

  # depends_on = [aws_lambda_permission.allow_lex_to_start_execution]
}


## OPA Rego validation policy

package terraform.policy

import rego.v1

default has_valid_resources = false

# Rule for multiple aws_lex_intent resources
has_valid_lex_intents if {
    count([intent | intent := input.planned_values.root_module.resources[_]; intent.type == "aws_lex_intent"; intent.values.name; intent.values.fulfillment_activity.code_hook])
}


# Check if AWS IAM Role for Lambda is being created 
aws_iam_role_lambda_valid(resources) if { 
	some resource in resources 
    resource.type == "aws_iam_role" 
    contains(resource.change.after.assume_role_policy,"lambda.amazonaws.com") 
} 

# Check if AWS Lambda function is being created 
aws_lambda_function_valid(resources) if { 
	some resource in resources 
    resource.type == "aws_lambda_function" 
}
# Rule for aws_lex_bot resource with specific arguments
has_valid_lex_bot_instance if {
    some i
    resource := input.planned_values.root_module.resources[i]
    resource.type == "aws_lex_bot"
    is_boolean(resource.values.child_directed)
    resource.values.clarification_prompt
    resource.values.abort_statement
    resource.values.name
    # is_boolean(resource.values.create_version)
    # resource.values.description
    # is_boolean(resource.values.detect_sentiment)
    # resource.values.idle_session_ttl_in_seconds
    # resource.values.process_behavior
    # resource.values.voice_id
    # resource.values.locale
    # is_boolean(resource.values.enable_model_improvements)
    # resource.values.nlu_intent_confidence_threshold
}

# Combined rule to ensure all conditions are met
has_valid_resources if {
    has_valid_lex_intents
    has_valid_lex_bot_instance
    aws_iam_role_lambda_valid(input.resource_changes) 
    aws_lambda_function_valid(input.resource_changes)
}

main if {
    has_valid_lex_intents
    has_valid_lex_bot_instance
    has_valid_resources
}