Add Emberwake Cloud Ecosystem deploy hub with AWS and generic spread templates.
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Unified expandable panels with mermaid flows, ZIP export, connection tests, and Playwright smoke coverage.
This commit is contained in:
79
server/internal/erasure/s3_crr.go
Normal file
79
server/internal/erasure/s3_crr.go
Normal file
@@ -0,0 +1,79 @@
|
||||
package erasure
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type S3ShardConfig struct {
|
||||
ShardBucket string `json:"aws_s3_shard_bucket"`
|
||||
ShardRegion string `json:"aws_s3_shard_region"`
|
||||
CRRDestBucket string `json:"aws_s3_crr_dest_bucket"`
|
||||
CRRDestRegion string `json:"aws_s3_crr_dest_region"`
|
||||
CloudFrontDomain string `json:"aws_cloudfront_domain,omitempty"`
|
||||
ReplicationRoleARN string `json:"aws_s3_replication_role_arn,omitempty"`
|
||||
ReplicationAccountID string `json:"aws_account_id,omitempty"`
|
||||
}
|
||||
|
||||
func S3ShardKey(token, region string, shardIndex int, shardHash string) string {
|
||||
token = strings.TrimSpace(token)
|
||||
region = strings.TrimSpace(region)
|
||||
shardHash = strings.TrimSpace(strings.ToLower(shardHash))
|
||||
if token == "" || region == "" || shardHash == "" {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf("shards/%s/%s/%d-%s.bin", token, region, shardIndex, shardHash)
|
||||
}
|
||||
|
||||
func S3ShardMetadata(region string, shardIndex int, token, shardHash string) map[string]string {
|
||||
return map[string]string{
|
||||
"region": strings.TrimSpace(region),
|
||||
"shard-index": fmt.Sprintf("%d", shardIndex),
|
||||
"token": strings.TrimSpace(token),
|
||||
"shard-hash": strings.TrimSpace(strings.ToLower(shardHash)),
|
||||
"shard-advert": FormatShardAdvert(region, shardIndex),
|
||||
}
|
||||
}
|
||||
|
||||
func FormatShardAdvert(region string, shardIndex int) string {
|
||||
return fmt.Sprintf("%s:%d", strings.TrimSpace(region), shardIndex)
|
||||
}
|
||||
|
||||
func ParseShardAdvert(advert string) (region string, index int, ok bool) {
|
||||
advert = strings.TrimSpace(advert)
|
||||
colon := strings.LastIndex(advert, ":")
|
||||
if colon <= 0 {
|
||||
return "", 0, false
|
||||
}
|
||||
region = strings.TrimSpace(advert[:colon])
|
||||
if _, err := fmt.Sscanf(strings.TrimSpace(advert[colon+1:]), "%d", &index); err != nil {
|
||||
return "", 0, false
|
||||
}
|
||||
return region, index, region != ""
|
||||
}
|
||||
|
||||
func BuildS3CRRRule(cfg S3ShardConfig) (map[string]interface{}, error) {
|
||||
if cfg.ShardBucket == "" || cfg.ShardRegion == "" || cfg.CRRDestBucket == "" || cfg.CRRDestRegion == "" {
|
||||
return nil, fmt.Errorf("aws s3 shard source/dest bucket and regions required")
|
||||
}
|
||||
role := strings.TrimSpace(cfg.ReplicationRoleARN)
|
||||
if role == "" {
|
||||
acct := strings.TrimSpace(cfg.ReplicationAccountID)
|
||||
if acct == "" {
|
||||
acct = "ACCOUNT_ID"
|
||||
}
|
||||
role = fmt.Sprintf("arn:aws:iam::%s:role/aetherforge-s3-shard-replication", acct)
|
||||
}
|
||||
dest := strings.TrimSpace(cfg.CRRDestBucket)
|
||||
if !strings.HasPrefix(dest, "arn:") {
|
||||
dest = "arn:aws:s3:::" + dest
|
||||
}
|
||||
return map[string]interface{}{
|
||||
"Role": role,
|
||||
"Rules": []map[string]interface{}{{
|
||||
"ID": "aetherforge-erasure-shard-crr", "Status": "Enabled", "Priority": 1,
|
||||
"Filter": map[string]interface{}{"Prefix": "shards/"},
|
||||
"Destination": map[string]interface{}{"Bucket": dest},
|
||||
}},
|
||||
}, nil
|
||||
}
|
||||
33
server/internal/erasure/s3_crr_test.go
Normal file
33
server/internal/erasure/s3_crr_test.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package erasure
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestS3ShardKeyRegional(t *testing.T) {
|
||||
if got := S3ShardKey("tok", "eu-west-1", 2, "abc"); got != "shards/tok/eu-west-1/2-abc.bin" {
|
||||
t.Fatalf("key=%q", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormatParseShardAdvert(t *testing.T) {
|
||||
a := FormatShardAdvert("us-east-1", 3)
|
||||
r, i, ok := ParseShardAdvert(a)
|
||||
if !ok || r != "us-east-1" || i != 3 {
|
||||
t.Fatalf("r=%q i=%d", r, i)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildS3CRRRule(t *testing.T) {
|
||||
doc, err := BuildS3CRRRule(S3ShardConfig{
|
||||
ShardBucket: "p", ShardRegion: "us-east-1", CRRDestBucket: "r", CRRDestRegion: "eu-west-1",
|
||||
ReplicationAccountID: "111",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if role, _ := doc["Role"].(string); !strings.Contains(role, "111") {
|
||||
t.Fatalf("role=%q", role)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user