AWSTemplateFormatVersion: '2010-09-09'
Description: DuckDB quack server on EC2, TLS via a Let's Encrypt IP certificate; URI + token surfaced via stack Outputs.

Parameters:
  machinetype:
    Type: String
    Default: t4g.small
    Description: EC2 instance type, e.g. r8g.2xlarge (arm64 / Graviton, the AMI is arm64)
  maxduration:
    Type: Number
    Default: 8
    MinValue: 0
    MaxValue: 144
    Description: Auto shutdown (instance terminates) after this many hours; 0 = never. Max 144 = within the 6-day IP cert.

Mappings:
  # Region -> quack AMI (built from image/bake.sh). Copy to more regions with `aws ec2 copy-image`.
  RegionAmi:
    us-east-1:    { ami: ami-014f043952d1ce0cc }
    us-east-2:    { ami: ami-09270f865097fdc8a }
    us-west-1:    { ami: ami-05de9badf7f26c35e }
    us-west-2:    { ami: ami-079aeda744ac852ce }
    eu-central-1: { ami: ami-0e19777a60db60313 }

Resources:
  QuackSG:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: quack - HTTPS, plus HTTP for the ACME http-01 challenge
      SecurityGroupIngress:
        - { IpProtocol: tcp, FromPort: 443, ToPort: 443, CidrIp: 0.0.0.0/0 }
        - { IpProtocol: tcp, FromPort: 80, ToPort: 80, CidrIp: 0.0.0.0/0 }

  ReadyHandle:
    Type: AWS::CloudFormation::WaitConditionHandle

  Ready:
    Type: AWS::CloudFormation::WaitCondition
    DependsOn: QuackInstance
    Properties:
      Handle: !Ref ReadyHandle
      Timeout: '600'
      Count: 1

  QuackInstance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !FindInMap [RegionAmi, !Ref "AWS::Region", ami]
      InstanceType: !Ref machinetype
      InstanceInitiatedShutdownBehavior: terminate
      MetadataOptions:
        HttpTokens: required
      SecurityGroupIds:
        - !Ref QuackSG
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-quack"
      # User-data is DuckDB SQL, run by the AMI's quack-boot once the TLS cert is in place (see image/quack-boot.sh).
      UserData:
        Fn::Base64: !Sub |
          .sh 'h=${maxduration}; [ "$h" -gt 0 ] && shutdown -h +$((h*60)) || true'
          SET VARIABLE my_token = replace(cast(uuid() as varchar), '-', '');
          CALL quack_serve('quack:127.0.0.1:1294', allow_other_hostname=true, disable_ssl=true, token=getvariable('my_token'));
          CALL quack_identify(
            name     => '${AWS::StackName}',
            provider => 'ec2',
            region   => '${AWS::Region}',
            meta     => '{"stack_id":"${AWS::StackId}","machine_type":"${machinetype}","max_duration_hours":${maxduration}}'
          );
          COPY (SELECT getvariable('my_token')) TO '/run/quack/token' (HEADER false);
          .sh 'curl -sS -X PUT -H "Content-Type:" --data "{\"Status\":\"SUCCESS\",\"Reason\":\"ready\",\"UniqueId\":\"1\",\"Data\":\"$(cat /run/quack/token)\"}" "${ReadyHandle}"'

Outputs:
  InstanceId:
    Value: !Ref QuackInstance
  PublicIp:
    Value: !GetAtt QuackInstance.PublicIp
  QuackURI:
    Description: ATTACH this with TYPE quack and the token below.
    Value: !Sub "quack:${QuackInstance.PublicIp}:443"
  Token:
    Description: "Per-instance token (JSON-wrapped as {\"1\":\"<token>\"})."
    Value: !GetAtt Ready.Data
