package console import ( "strings" "testing" "github.com/carlosframework/platform/internal/economics" "github.com/carlosframework/platform/internal/infraview" "github.com/carlosframework/platform/internal/status" ) // sharedAccountFixture is the shape this whole feature exists for: one // account carrying a CARLOS deployment AND something else. It is modelled on // Tito's real account — a CARLOS box beside a Kubernetes estate, one DNS zone // answering for both, and a bucket named as if it were CARLOS's that the // console was never told about. func sharedAccountFixture() ArchInput { inv := &infraview.Inventory{Provider: "aws", Account: "665106592142", Resources: []infraview.Resource{ // One zone, both estates. This is the coupling that makes the two // halves one account rather than two. {Kind: infraview.KindDNSZone, ID: "Z1", Name: "tito.io", Attrs: map[string]string{"record_count": "202"}}, // --- the CARLOS half ------------------------------------------ {Kind: infraview.KindMachine, ID: "i-carlos", Name: "carlos-tito-ie", Region: "eu-west-1", Attrs: map[string]string{ "type": "t4g.medium", "state": "running", "public_ip": "52.0.0.1", "security_groups": "sg-carlos", "iam_profile": "arn:aws:iam::665106592142:instance-profile/carlos-tito-host-ie", }}, {Kind: infraview.KindIP, ID: "eip-carlos", Attrs: map[string]string{"address": "52.0.0.1", "attached_to": "i-carlos"}}, {Kind: infraview.KindDisk, ID: "vol-carlos", Attrs: map[string]string{"size_gb": "40", "attached_to": "i-carlos"}}, {Kind: infraview.KindFirewall, ID: "sg-carlos", Name: "carlos-tito-ie"}, {Kind: infraview.KindIdentity, ID: "arn:aws:iam::665106592142:role/carlos-tito-host-ie", Name: "carlos-tito-host-ie", Attrs: map[string]string{"kind": "role"}}, {Kind: infraview.KindAlarm, ID: "alarm-carlos", Name: "auto-recover-ie", Attrs: map[string]string{"target": "i-carlos", "state": "OK"}}, {Kind: infraview.KindDNSRecord, ID: "rec-carlos", Name: "go.tito.io", Attrs: map[string]string{"zone": "tito.io", "type": "A", "value": "52.0.0.1"}}, {Kind: infraview.KindBucket, ID: "carlos-tito-platform", Name: "carlos-tito-platform"}, // --- everything else the account carries ----------------------- {Kind: infraview.KindMachine, ID: "i-eks", Name: "workers-a-03", Region: "eu-west-1", Attrs: map[string]string{ "type": "m5.large", "state": "running", "public_ip": "52.0.0.9", "security_groups": "sg-eks", "iam_profile": "arn:aws:iam::665106592142:instance-profile/eks-2acb3b4e", }}, {Kind: infraview.KindFirewall, ID: "sg-eks", Name: "eks-cluster-sg"}, {Kind: infraview.KindIdentity, ID: "arn:aws:iam::665106592142:role/eks-node-role", Name: "eks-node-role", Attrs: map[string]string{"kind": "role"}}, {Kind: infraview.KindDNSRecord, ID: "rec-legacy", Name: "ti.to", Attrs: map[string]string{"zone": "tito.io", "type": "A", "value": "52.0.0.9"}}, {Kind: infraview.KindNetwork, ID: "vpc-1", Name: "tito-production"}, // A bucket the console was NEVER told about, wearing the CARLOS // name. It is the whole reason this file matches on joins rather // than on names: nothing here can prove it belongs to CARLOS. {Kind: infraview.KindBucket, ID: "carlos-tito-se-665106592142", Name: "carlos-tito-se-665106592142"}, }} return ArchInput{ Inv: inv, Bucket: "carlos-tito-platform", Fleet: &status.Fleet{Boxes: []status.FleetBox{{Label: "carlos-tito-ie", Region: "eu-west-1"}}}, Hosts: []HostRow{{Label: "carlos-tito-ie", Region: "eu-west-1", Metrics: &status.BoxMetrics{ Release: "abc1234", InstanceID: "i-carlos", }}}, Rates: economics.RateCard{Boxes: map[string]economics.BoxSpec{ "": {HourUSD: 0.02, Cores: 2, MemGB: 4, EBSGB: 40}, }, EBSGBMonthUSD: 0.088}, } } // The membership closure, one join at a time. Each of these is a hop the // console can PROVE; the failure this pins is a join quietly widening into a // name match, which would make every row on the page a guess. func TestEstateClosureReachesWhatItCanProve(t *testing.T) { v := BuildArch(sharedAccountFixture()) // Keyed by (table, name) rather than name alone: on the real estate a // security group is named after the box it guards, so "carlos-tito-ie" // is both a machine and a firewall — and the fixture keeps that. rows := bankOfEachRow(v) for _, c := range []struct{ table, name, want, why string }{ {"Compute", "carlos-tito-ie", "CARLOS", "the box itself reported this machine id"}, {"Compute", "vol-carlos", "CARLOS", "a disk attached to a reported machine"}, {"Network", "eip-carlos", "CARLOS", "an address attached to a reported machine"}, {"Alarms", "auto-recover-ie", "CARLOS", "an alarm watching a reported machine"}, {"Network", "carlos-tito-ie", "CARLOS", "a security group the machine itself named"}, {"Identity", "carlos-tito-host-ie", "CARLOS", "the role behind the machine's instance profile"}, {"DNS", "go.tito.io", "CARLOS", "a record resolving to a CARLOS address"}, {"DNS", "tito.io", "CARLOS", "the zone holding such a record"}, {"Storage", "carlos-tito-platform", "CARLOS", "the deployment bucket the console is configured with"}, {"Compute", "workers-a-03", "rest", "a machine no box reports"}, {"Network", "eks-cluster-sg", "rest", "a security group no CARLOS machine names"}, {"Identity", "eks-node-role", "rest", "a role no CARLOS instance profile names"}, {"DNS", "ti.to", "rest", "a record resolving into the other estate"}, {"Network", "tito-production", "rest", "a VPC nothing joins it to CARLOS"}, // The load-bearing one. This bucket is named exactly as CARLOS's // own buckets are, and it still lands in the other half, because // the console cannot trace a path to it. A page that put it in // CARLOS would be reading a naming convention, and the day // somebody renames a bucket that page becomes confidently wrong. {"Storage", "carlos-tito-se-665106592142", "rest", "a carlos-NAMED bucket the console cannot prove is its own"}, } { if got := rows[c.table+"/"+c.name]; got != c.want { t.Errorf("%s %s is in %q, want %q — %s", c.table, c.name, got, c.want, c.why) } } } // bankOfEachRow maps "