= AWS =
Amazon Web Services

Lambda Java samples:
 * https://docs.aws.amazon.com/lambda/latest/dg/lambda-samples.html
  * https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/java-basic/

== User credentials ==
 * https://docs.aws.amazon.com/general/latest/gr/root-vs-iam.html
 * https://docs.aws.amazon.com/general/latest/gr/aws-access-keys-best-practices.html
 * https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html

Instead of sharing the credentials of the AWS account root user, create individual IAM users, granting each user only the permissions they require.

Follow the best practice of using the root user only to create your first IAM user.

There are two types of credentials:
 * Root user credentials,  allow full access to all resources in the AWS account.
 * IAM credentials, control access to AWS services and resources for users in your AWS account

== Serverless blog web application architecture ==
 * https://github.com/aws-samples/lambda-refarch-webapp
 * https://s3.amazonaws.com/aws-lambda-serverless-web-refarch/RefArch_BlogApp_Serverless.png
  * Amazon Route 53 (routes to specific places based on region)
  * Amazon CloudFront (deliver static content per region hosted inside S3)
  * Amazon Simple Storage Service (S3)
  * Amazon Cognito (Authentication and authorization)
  * Amazon API Gateway (routes requests to backend logic)
  * AWS Lambda (backend business logic)
  * AWS DynamoDB (managed DB)
  * AWS Identity and Access Management (IAM) - web service to control access to AWS resources

== Localstack in Debian ==
 * https://github.com/localstack/localstack

LocalStack is a cloud service emulator that runs in a single container on your laptop or in your CI environment. With LocalStack, you can run your AWS applications or Lambdas entirely on your local machine without connecting to a remote cloud provider

{{{#!highlight sh
sudo apt install python3-pip
sudo apt install python-pip
pip3 install localstack
pip install localstack
.local/bin/localstack start
docker run --rm -it -p 4566:4566 -p 4571:4571 localstack/localstack
curl http://localhost:4566/health
pip3 install awscli 
pip3 install awscli-local
.local/bin/awslocal kinesis list-streams
.local/bin/awslocal s3api list-buckets
PATH=$PATH:/usr/sbin:~/.local/bin  in ~/.bashrc 
docker exec -it silly_greider bash 
awslocal s3api list-buckets
awslocal s3api create-bucket --bucket my-bucket --region us-east-1
# https://docs.aws.amazon.com/cli/latest/reference/s3api/
echo "test" > test.txt
awslocal s3api put-object --bucket my-bucket --key dir-1/test.txt --body test.txt 
awslocal s3api get-object --bucket my-bucket --key dir-1/test.txt test2.txt 
cat test2.txt 
}}}

=== Localstack - lambda and s3  ===
'''run.sh'''
{{{#!highlight bash
zip py-my-function.zip lambda_function.py
awslocal lambda delete-function --function-name py-my-function
awslocal lambda create-function --function-name py-my-function --zip-file fileb://py-my-function.zip --handler lambda_function.lambda_handler  --runtime python3.9 --role arn:aws:iam::000000000000:role/lambda-ex
awslocal lambda invoke --function-name py-my-function --payload '{ "first_name": "Bob","last_name":"Squarepants" }' response.json 
cat response.json
}}}

'''lambda_function.py'''
{{{#!highlight python
import boto3
import os

def lambda_handler(event, context):
    message = 'Hello {} {}!'.format(event['first_name'], event['last_name'])
    session = boto3.session.Session()

    s3_client = session.client(
        service_name='s3',
        aws_access_key_id=os.environ["AWS_ACCESS_KEY_ID"],
        aws_secret_access_key=os.environ["AWS_SECRET_ACCESS_KEY"],
        endpoint_url='http://localhost:4566',
    )

    buckets=[]
    for bucket in s3_client.list_buckets()['Buckets']:
        buckets.append(bucket['Name'])

    response = s3_client.create_bucket(Bucket='examplebucket')

    body = {
        'message' : message,
        'buckets' : buckets,
        'AWS_ACCESS_KEY_ID' : os.environ["AWS_ACCESS_KEY_ID"],
        'AWS_SECRET_ACCESS_KEY' : os.environ["AWS_SECRET_ACCESS_KEY"]
    }

    s3_client.put_object(Body=str(body), Bucket='examplebucket', Key='examplebucket/response.txt')
    return body
}}}

== Access localstack from docker container ==
{{{#!highlight bash
docker run -d --name localstack --rm -it -p 4566:4566 -p 4571:4571 localstack/localstack # run container
docker exec -it localstack bash # connect to container
lsb_release -a
curl http://localhost:4566/health
awslocal s3api list-buckets
awslocal s3api create-bucket --bucket my-bucket
echo "test" > test.txt
awslocal s3api put-object --bucket my-bucket --key dir-1/test.txt --body test.txt
awslocal s3api get-object --bucket my-bucket --key dir-1/test.txt test2.txt
cat test2.txt 
apt install nano vim yajl-tools -y
# https://hub.docker.com/r/localstack/localstack
# https://github.com/localstack/localstack
node -v # v14.18.1
python -V # Python 3.8.12
pip3 freeze
curl http://localhost:4566/health | json_reformat
awslocal ec2 run-instances --image-id prod-df2jln3gjtwps --count 1 --instance-type t2.micro
awslocal ec2 describe-instances --filters "Name=instance-type,Values=t2.micro" --query "Reservations[].Instances[].InstanceId"
awslocal ec2 describe-instances
}}}

== Localstack - java8 ==

=== build.sh ===
{{{#!highlight sh
FUNCTION_NAME=lambda-function
awslocal lambda delete-function --function-name $FUNCTION_NAME
sleep 5
mvn clean install
sleep 5
awslocal lambda create-function --function-name $FUNCTION_NAME \
  --zip-file fileb://target/lambda-function-1.0-SNAPSHOT.jar \
  --handler com.mooo.bitarus.Handler --runtime java8 \
  --role arn:aws:iam::000000000000:role/lambda-ex --timeout 30
#awslocal lambda update-function-configuration --function-name $FUNCTION_NAME \
#  --timeout 15
sleep 15
}}}

=== latest_log.sh ===
{{{#!highlight sh
LOG_GROUP="/aws/lambda/lambda-function"
LOG_STREAM=$(awslocal logs describe-log-streams \
  --log-group-name $LOG_GROUP \
  --order-by LastEventTime --descending | \
  grep logStreamName | head -1 | awk '//{print $2}' | sed "s/,//g" | sed 's/\"//g' )
echo $LOG_GROUP
echo $LOG_STREAM
awslocal logs get-log-events --log-group-name $LOG_GROUP \
  --log-stream-name "$LOG_STREAM" \
  | grep message \
  | sed 's/"message"\://g' \
  | sed 's/             //g'
}}}

=== pom.xml ===
{{{#!highlight xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mooo.bitarus</groupId>
  <artifactId>lambda-function</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>lambda-function</name>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>
  <dependencies>
    <dependency>
      <groupId>com.amazonaws</groupId>
      <artifactId>aws-lambda-java-core</artifactId>
      <version>1.2.1</version>
    </dependency>
    <dependency>
      <groupId>com.google.code.gson</groupId>
      <artifactId>gson</artifactId>
      <version>2.8.9</version>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.22.2</version>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>3.2.2</version>
        <configuration>
          <createDependencyReducedPom>false</createDependencyReducedPom>
        </configuration>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>shade</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.1</version>
        <configuration>
           <source>1.8</source>
           <target>1.8</target>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>
}}}

=== run.sh ===
{{{#!highlight sh
awslocal lambda invoke --function-name lambda-function \
  --payload '{ "first_name": "Bob","last_name":"Marley" }' response.json 
cat response.json
}}}

=== src/main/java/com/mooo/bitarus/Handler.java ===
{{{#!highlight java
package com.mooo.bitarus;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.LambdaLogger;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.util.Map;
import java.util.HashMap;

public class Handler implements RequestHandler<Map<String,String>, String>{
  Gson gson = new GsonBuilder().setPrettyPrinting().create();
  @Override
  public String handleRequest(Map<String,String> event, Context context)
  {
    LambdaLogger logger = context.getLogger();
    System.out.println(">>> sout test");
    logger.log("Stuff logged");
    String response = "Java Lambda invocation response 3";
    logger.log( event.get("first_name") );
    logger.log("EVENT TYPE: " + event.getClass());
    Map<String,String> hashReturn = new java.util.HashMap<String,String>();
    hashReturn.put("response",response);
    return gson.toJson(hashReturn);
  }
}
}}}