Spaces:
Runtime error
Runtime error
| import boto3 | |
| import json | |
| import subprocess | |
| import os | |
| import re | |
| def b64text(txt): | |
| """Generate Base 64 encoded CF json for a multiline string, subbing in values where appropriate""" | |
| lines = [] | |
| for line in txt.splitlines(True): | |
| if "${" in line: | |
| lines.append({"Fn::Sub": line}) | |
| else: | |
| lines.append(line) | |
| return {"Fn::Base64": {"Fn::Join": ["", lines]}} | |
| path = os.path.dirname(os.path.realpath(__file__)) | |
| version = subprocess.check_output(f"{path}/version").decode("ascii").strip() | |
| with open(f"{path}/templates/docker-compose.yml") as f: | |
| docker_compose_file = str(f.read()) | |
| cloud_config_script = """ | |
| #cloud-config | |
| cloud_final_modules: | |
| - [scripts-user, always] | |
| """ | |
| cloud_init_script = f""" | |
| #!/bin/bash | |
| amazon-linux-extras install docker | |
| usermod -a -G docker ec2-user | |
| curl -L https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose | |
| chmod +x /usr/local/bin/docker-compose | |
| ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose | |
| systemctl enable docker | |
| systemctl start docker | |
| cat << EOF > /home/ec2-user/docker-compose.yml | |
| {docker_compose_file} | |
| EOF | |
| mkdir /home/ec2-user/config | |
| docker-compose -f /home/ec2-user/docker-compose.yml up -d | |
| """ | |
| userdata = f"""Content-Type: multipart/mixed; boundary="//" | |
| MIME-Version: 1.0 | |
| --// | |
| Content-Type: text/cloud-config; charset="us-ascii" | |
| MIME-Version: 1.0 | |
| Content-Transfer-Encoding: 7bit | |
| Content-Disposition: attachment; filename="cloud-config.txt" | |
| {cloud_config_script} | |
| --// | |
| Content-Type: text/x-shellscript; charset="us-ascii" | |
| MIME-Version: 1.0 | |
| Content-Transfer-Encoding: 7bit | |
| Content-Disposition: attachment; filename="userdata.txt" | |
| {cloud_init_script} | |
| --//-- | |
| """ | |
| cf = { | |
| "AWSTemplateFormatVersion": "2010-09-09", | |
| "Description": "Create a stack that runs Chroma hosted on a single instance", | |
| "Parameters": { | |
| "KeyName": { | |
| "Description": "Name of an existing EC2 KeyPair to enable SSH access to the instance", | |
| "Type": "String", | |
| "ConstraintDescription": "If present, must be the name of an existing EC2 KeyPair.", | |
| "Default": "", | |
| }, | |
| "InstanceType": { | |
| "Description": "EC2 instance type", | |
| "Type": "String", | |
| "Default": "t3.small", | |
| }, | |
| "ChromaVersion": { | |
| "Description": "Chroma version to install", | |
| "Type": "String", | |
| "Default": version, | |
| }, | |
| }, | |
| "Conditions": { | |
| "HasKeyName": {"Fn::Not": [{"Fn::Equals": [{"Ref": "KeyName"}, ""]}]}, | |
| }, | |
| "Resources": { | |
| "ChromaInstance": { | |
| "Type": "AWS::EC2::Instance", | |
| "Properties": { | |
| "ImageId": { | |
| "Fn::FindInMap": ["Region2AMI", {"Ref": "AWS::Region"}, "AMI"] | |
| }, | |
| "InstanceType": {"Ref": "InstanceType"}, | |
| "UserData": b64text(userdata), | |
| "SecurityGroupIds": [{"Ref": "ChromaInstanceSecurityGroup"}], | |
| "KeyName": { | |
| "Fn::If": [ | |
| "HasKeyName", | |
| {"Ref": "KeyName"}, | |
| {"Ref": "AWS::NoValue"}, | |
| ] | |
| }, | |
| "BlockDeviceMappings": [ | |
| { | |
| "DeviceName": { | |
| "Fn::FindInMap": [ | |
| "Region2AMI", | |
| {"Ref": "AWS::Region"}, | |
| "RootDeviceName", | |
| ] | |
| }, | |
| "Ebs": {"VolumeSize": 24}, | |
| } | |
| ], | |
| }, | |
| }, | |
| "ChromaInstanceSecurityGroup": { | |
| "Type": "AWS::EC2::SecurityGroup", | |
| "Properties": { | |
| "GroupDescription": "Chroma Instance Security Group", | |
| "SecurityGroupIngress": [ | |
| { | |
| "IpProtocol": "tcp", | |
| "FromPort": "22", | |
| "ToPort": "22", | |
| "CidrIp": "0.0.0.0/0", | |
| }, | |
| { | |
| "IpProtocol": "tcp", | |
| "FromPort": "8000", | |
| "ToPort": "8000", | |
| "CidrIp": "0.0.0.0/0", | |
| }, | |
| ], | |
| }, | |
| }, | |
| }, | |
| "Outputs": { | |
| "ServerIp": { | |
| "Description": "IP address of the Chroma server", | |
| "Value": {"Fn::GetAtt": ["ChromaInstance", "PublicIp"]}, | |
| } | |
| }, | |
| "Mappings": {"Region2AMI": {}}, | |
| } | |
| # Populate the Region2AMI mappings | |
| regions = boto3.client("ec2", region_name="us-east-1").describe_regions()["Regions"] | |
| for region in regions: | |
| region_name = region["RegionName"] | |
| ami_result = boto3.client("ec2", region_name=region_name).describe_images( | |
| Owners=["137112412989"], | |
| Filters=[ | |
| {"Name": "name", "Values": ["amzn2-ami-kernel-5.10-hvm-*-x86_64-gp2"]}, | |
| {"Name": "root-device-type", "Values": ["ebs"]}, | |
| {"Name": "virtualization-type", "Values": ["hvm"]}, | |
| ], | |
| ) | |
| img = ami_result["Images"][0] | |
| ami_id = img["ImageId"] | |
| root_device_name = img["BlockDeviceMappings"][0]["DeviceName"] | |
| cf["Mappings"]["Region2AMI"][region_name] = { | |
| "AMI": ami_id, | |
| "RootDeviceName": root_device_name, | |
| } | |
| # Write the CF json to a file | |
| json.dump(cf, open("/tmp/chroma.cf.json", "w"), indent=4) | |
| # upload to S3 | |
| s3 = boto3.client("s3", region_name="us-east-1") | |
| s3.upload_file( | |
| "/tmp/chroma.cf.json", | |
| "public.trychroma.com", | |
| f"cloudformation/{version}/chroma.cf.json", | |
| ) | |
| # Upload to s3 under /latest version only if this is a release | |
| pattern = re.compile(r"^\d+\.\d+\.\d+$") | |
| if pattern.match(version): | |
| s3.upload_file( | |
| "/tmp/chroma.cf.json", | |
| "public.trychroma.com", | |
| "cloudformation/latest/chroma.cf.json", | |
| ) | |
| else: | |
| print(f"Version {version} is not a 3-part semver, not uploading to /latest") | |