Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

350 improvement serverless test workshop UI configuration improvement #351

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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}"