Skip to content

Commit

Permalink
Merge pull request #351 from aws-samples/350-improvement-serverless-t…
Browse files Browse the repository at this point in the history
…est-workshop-ui-configuration-improvement

350 improvement serverless test workshop UI configuration improvement
  • Loading branch information
wtromano-aws authored Aug 21, 2024
2 parents a764910 + 8a534fd commit 778a716
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 296 deletions.
15 changes: 9 additions & 6 deletions workshops/serverless-testing-workshop/demo-app/urs-ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,19 @@
import uuid
import time
import requests
import boto3
import streamlit as st
from streamlit_js_eval import streamlit_js_eval

# Initialize Contexts
if 'api_endpoint_url' not in st.session_state:
if os.path.isfile("config.json"):
with open("config.json","r",encoding="utf-8") as f:
app_config = json.load(f)
st.session_state['api_endpoint_url'] = app_config["api_endpoint"].strip()
else:
try:
cfn_client = boto3.client('cloudformation')
response = cfn_client.describe_stacks(StackName=os.environ.get('BACKEND_STACK_NAME','urs-backend'))
for output in response['Stacks'][0]['Outputs']:
if output['OutputKey'] == 'ApiEndpoint':
st.session_state['api_endpoint_url'] = output['OutputValue']
except:
st.session_state['api_endpoint_url'] = "https://{APIGATEWAYID}.execute-api.{REGION}.amazonaws.com/Prod/"

if 'unicorn_art' not in st.session_state:
Expand Down Expand Up @@ -215,7 +218,7 @@ def update_unicorn_reserve_list():
key="api_endpoint_url",
on_change=update_api_endpoint
)

# File picker for uploading to the unicorn inventory
uploaded_file = st.file_uploader("Choose a CSV file for the Unicorn Inventory.", type=["csv"])
if uploaded_file is not None:
Expand Down
290 changes: 0 additions & 290 deletions workshops/serverless-testing-workshop/template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -242,293 +242,6 @@ Resources:
name:
- !Ref UnicornInventoryBucket

##################################################
##################################################
##### demo-app (begin)
##################################################
##################################################

#
# Networking
# VPC, 2 Public Subnets, S3/ECR/Cloudwatch Service Endpoints, Internet Gateway
#

StreamlitVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 192.168.0.0/24
EnableDnsHostnames : true
EnableDnsSupport : true

StreamlitSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref StreamlitVPC
CidrBlock: 192.168.0.0/25
AvailabilityZone: !Sub "${AWS::Region}b"

StreamlitSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref StreamlitVPC
CidrBlock: 192.168.0.128/25
AvailabilityZone: !Sub "${AWS::Region}c"

StreamlitInternetGateway:
Type: AWS::EC2::InternetGateway

StreamlitGatewayAttachment:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
InternetGatewayId: !Ref StreamlitInternetGateway
VpcId: !Ref StreamlitVPC

StreamlitSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: "Streamlit UI Security Group"
GroupName: !Sub "${AWS::StackName}-ds-sg"
SecurityGroupEgress:
- IpProtocol: tcp
FromPort: 0
ToPort: 65535
CidrIp: 0.0.0.0/0
Description: Allow outbound access
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: !Ref iECRStreamlitPort
ToPort: !Ref iECRStreamlitPort
CidrIp: 0.0.0.0/0
Description: Inbound only on Streamlit port
VpcId: !Ref StreamlitVPC

EndpointSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: "Streamlit UI Endpoint Security Group"
GroupName: !Sub "${AWS::StackName}-ep-sg"
SecurityGroupEgress:
- IpProtocol: tcp
FromPort: 0
ToPort: 65535
CidrIp: 0.0.0.0/0
Description: Allow outbound access
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 0
ToPort: 65535
SourceSecurityGroupId: !Ref StreamlitSecurityGroup
Description: Allow inbound from Streamlit sg only
VpcId: !Ref StreamlitVPC

StreamlitRouteTable:
Type: 'AWS::EC2::RouteTable'
Properties:
VpcId: !Ref StreamlitVPC

InternetGatewayRoute:
Type: AWS::EC2::Route
Properties:
GatewayId: !Ref StreamlitInternetGateway
RouteTableId: !Ref StreamlitRouteTable
DestinationCidrBlock: 0.0.0.0/0

SubnetRouteTableAssociation1:
Type: 'AWS::EC2::SubnetRouteTableAssociation'
Properties:
SubnetId: !Ref StreamlitSubnet1
RouteTableId: !Ref StreamlitRouteTable

SubnetRouteTableAssociation2:
Type: 'AWS::EC2::SubnetRouteTableAssociation'
Properties:
SubnetId: !Ref StreamlitSubnet2
RouteTableId: !Ref StreamlitRouteTable

StreamlitVPCEndpointECRApi:
Type: AWS::EC2::VPCEndpoint
Properties:
SecurityGroupIds:
- !Ref EndpointSecurityGroup
ServiceName: !Sub 'com.amazonaws.${AWS::Region}.ecr.api'
SubnetIds:
- !Ref StreamlitSubnet1
- !Ref StreamlitSubnet2
VpcEndpointType: Interface
VpcId: !Ref StreamlitVPC
PrivateDnsEnabled: true

StreamlitVPCEndpointDocker:
Type: AWS::EC2::VPCEndpoint
Properties:
SecurityGroupIds:
- !Ref EndpointSecurityGroup
ServiceName: !Sub 'com.amazonaws.${AWS::Region}.ecr.dkr'
SubnetIds:
- !Ref StreamlitSubnet1
- !Ref StreamlitSubnet2
VpcEndpointType: Interface
VpcId: !Ref StreamlitVPC
PrivateDnsEnabled: true

StreamlitVPCEndpointLogs:
Type: AWS::EC2::VPCEndpoint
Properties:
SecurityGroupIds:
- !Ref EndpointSecurityGroup
ServiceName: !Sub 'com.amazonaws.${AWS::Region}.logs'
SubnetIds:
- !Ref StreamlitSubnet1
- !Ref StreamlitSubnet2
VpcEndpointType: Interface
VpcId: !Ref StreamlitVPC
PrivateDnsEnabled: true

StreamlitVPCEndpointS3:
Type: AWS::EC2::VPCEndpoint
Properties:
ServiceName: !Sub 'com.amazonaws.${AWS::Region}.s3'
VpcEndpointType: Gateway
VpcId: !Ref StreamlitVPC
RouteTableIds:
- !Ref StreamlitRouteTable

LoadBalancer:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Subnets:
- !Ref StreamlitSubnet1
- !Ref StreamlitSubnet2
SecurityGroups:
- !Ref StreamlitSecurityGroup

LoadBalancerListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
LoadBalancerArn: !Ref LoadBalancer
Port: !Ref iECRStreamlitPort
Protocol: HTTP
DefaultActions:
- Type: forward
TargetGroupArn: !Ref TargetGroup

TargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
Name: !Sub "${AWS::StackName}-tg-http"
VpcId: !Ref StreamlitVPC
Port: !Ref iECRStreamlitPort
Protocol: HTTP
TargetType: ip
HealthCheckEnabled: true
HealthCheckIntervalSeconds: 60
HealthCheckPath: "/_stcore/health"
HealthCheckPort: !Ref iECRStreamlitPort
HealthCheckProtocol: HTTP
TargetGroupAttributes:
- Key: stickiness.enabled
Value: "true"
- Key: stickiness.type
Value: lb_cookie
- Key: stickiness.lb_cookie.duration_seconds
Value: "86500"

ECSTask:
Type: AWS::ECS::TaskDefinition
DependsOn: LoadBalancerListener
Properties:
RequiresCompatibilities:
- FARGATE
Cpu: '2048'
Memory: '4096'
NetworkMode: awsvpc
RuntimePlatform:
CpuArchitecture: "X86_64"
OperatingSystemFamily: "LINUX"
ExecutionRoleArn: !Ref ExecutionRole
TaskRoleArn: !Ref TaskRole
ContainerDefinitions:
- Name: "streamlit"
Image: !Sub "${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/docsearch-ecr"
MemoryReservation: 2048
Cpu: 2048
Memory: 4096
Essential: true
PortMappings:
- ContainerPort: !Ref iECRStreamlitPort
LogConfiguration:
LogDriver: awslogs
Options:
awslogs-create-group: "true"
awslogs-group: !Sub "/ecs/${AWS::StackName}-ECSTask"
awslogs-region: !Sub "${AWS::Region}"
awslogs-stream-prefix: "ecs"

ECSCluster:
Type: 'AWS::ECS::Cluster'
Properties:
ClusterName: !Sub "${AWS::StackName}-cluster"

ECSService:
Type: 'AWS::ECS::Service'
Properties:
Cluster: !Ref ECSCluster
TaskDefinition: !Ref ECSTask
DesiredCount: 1
LaunchType: FARGATE
ServiceName: !Sub "${AWS::StackName}-svc"
SchedulingStrategy: "REPLICA"
LoadBalancers:
- ContainerName: "streamlit"
ContainerPort: !Ref iECRStreamlitPort
TargetGroupArn: !Ref TargetGroup
HealthCheckGracePeriodSeconds: 50
NetworkConfiguration:
AwsvpcConfiguration:
AssignPublicIp: ENABLED
SecurityGroups:
- !Ref StreamlitSecurityGroup
Subnets:
- !Ref StreamlitSubnet1
- !Ref StreamlitSubnet2

ExecutionRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub "${AWS::StackName}-execution-role"
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: ecs-tasks.amazonaws.com
Action: 'sts:AssumeRole'
Policies:
- PolicyName: root
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- "ecr:GetAuthorizationToken"
- "ecr:BatchCheckLayerAvailability"
- "ecr:GetDownloadUrlForLayer"
- "ecr:BatchGetImage"
- "logs:CreateLogStream"
- "logs:PutLogEvents"
- "logs:CreateLogGroup"
Resource: '*'

TaskRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub "${AWS::StackName}-task-role"
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: ecs-tasks.amazonaws.com
Action: 'sts:AssumeRole'

Outputs:
# ServerlessRestApi is an implicit API created out of Events key under Serverless::Function
# Find out more about other implicit resources you can reference within SAM
Expand All @@ -548,6 +261,3 @@ Outputs:
GetFileValidatorARN:
Description: "ARN of the Lambda function required in the 'OPTIONAL: Invoke a Lambda function in the cloud' section."
Value: !GetAtt FileValidator.Arn
oUiDnsName:
Description: Host UI web link name
Value: !Sub "http://${LoadBalancer.DNSName}:${iECRStreamlitPort}"

0 comments on commit 778a716

Please sign in to comment.