Files
AetherForge 5b5fc7c01c
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Add Emberwake Cloud Ecosystem deploy hub with AWS and generic spread templates.
Unified expandable panels with mermaid flows, ZIP export, connection tests, and Playwright smoke coverage.
2026-06-07 10:03:22 -07:00

109 lines
2.9 KiB
Go

// Package fargate generates standalone ECS Fargate burst-seeder task bundles.
package fargate
import (
"encoding/base64"
"encoding/json"
"fmt"
)
const (
DefaultTaskFamily = "aetherforge-burst-seeder"
DefaultImage = "public.ecr.aws/docker/library/nginx:alpine"
DefaultRegion = "us-east-1"
DefaultCluster = "aetherforge-burst"
)
type Options struct {
BuildID, Campaign, ServerURL, ShardToken, PayloadSHA256 string
PayloadSize, DataShards, ParityShards, TTLHours, TaskCount int
ShardURLs []string
SwarmMagnet string
Shards [][]byte
Region, Cluster, TaskFamily, Image string
}
type Bundle struct {
TaskDefinitionJSON, RunTaskScript, ShardManifestJSON []byte
ShardToken string
}
func GenerateBundle(opts Options) (*Bundle, error) {
opts = opts.withDefaults()
if len(opts.Shards) == 0 {
return nil, fmt.Errorf("fargate: shards required")
}
manifest, err := json.MarshalIndent(map[string]interface{}{
"token": opts.ShardToken, "shards_b64": encodeShards(opts.Shards), "ttl_hours": opts.TTLHours,
}, "", " ")
if err != nil {
return nil, err
}
taskDef, err := json.MarshalIndent(map[string]interface{}{
"family": opts.TaskFamily, "networkMode": "awsvpc", "requiresCompatibilities": []string{"FARGATE"},
"cpu": "256", "memory": "512",
"containerDefinitions": []map[string]interface{}{{
"name": "burst-seeder", "image": opts.Image, "essential": true,
"environment": []map[string]string{
{"name": "AF_SHARD_TOKEN", "value": opts.ShardToken},
{"name": "AF_SHARD_MANIFEST_B64", "value": base64.StdEncoding.EncodeToString(manifest)},
},
}},
}, "", " ")
if err != nil {
return nil, err
}
script := fmt.Sprintf(`#!/usr/bin/env bash
set -euo pipefail
aws ecs register-task-definition --region "${AWS_REGION:-%s}" --cli-input-json file://task-definition.json
aws ecs run-task --region "${AWS_REGION:-%s}" --cluster "${ECS_CLUSTER:-%s}" --launch-type FARGATE --task-definition %s --count ${ECS_TASK_COUNT:-%d}
`, opts.Region, opts.Region, opts.Cluster, opts.TaskFamily, opts.TaskCount)
return &Bundle{TaskDefinitionJSON: taskDef, RunTaskScript: []byte(script), ShardManifestJSON: manifest, ShardToken: opts.ShardToken}, nil
}
func (o Options) withDefaults() Options {
if o.TaskFamily == "" {
o.TaskFamily = DefaultTaskFamily
}
if o.Image == "" {
o.Image = DefaultImage
}
if o.Region == "" {
o.Region = DefaultRegion
}
if o.Cluster == "" {
o.Cluster = DefaultCluster
}
o.TTLHours = ClampTTLHours(o.TTLHours)
if o.TaskCount <= 0 {
o.TaskCount = 3
}
return o
}
func encodeShards(shards [][]byte) []string {
out := make([]string, len(shards))
for i, sh := range shards {
out[i] = base64.StdEncoding.EncodeToString(sh)
}
return out
}
func ClampTTLHours(h int) int {
if h < 2 {
return 2
}
if h > 4 {
return 4
}
return h
}
func BurstTaskDefinition(opts Options) ([]byte, error) {
b, err := GenerateBundle(opts)
if err != nil {
return nil, err
}
return b.TaskDefinitionJSON, nil
}