package edge import "testing" // privateFleet publishes this edge's own file (annie, in ie, network // 10.0.0.0/16) and one file per case. func privateFleet(t *testing.T, m *homeMap) { t.Helper() putJSON(t, m.s, "control/edges/annie.json", `{"v":1,"box":"annie","eip":"1.1.1.1","private_ip":"10.0.1.1","private_cidr":"10.0.0.0/16","region":"eu-west-1","placement":"ie","hosts":{}}`) putJSON(t, m.s, "control/edges/betty.json", `{"v":1,"box":"betty","eip":"2.2.2.2","private_ip":"10.0.1.2","private_cidr":"10.0.0.0/16","region":"eu-west-1","placement":"ie","hosts":{"b.test":{"role":"home"}}}`) putJSON(t, m.s, "control/edges/carla.json", `{"v":1,"box":"carla","eip":"3.3.3.3","private_ip":"10.1.1.3","private_cidr":"10.1.0.0/16","region":"eu-west-2","placement":"uk","hosts":{"c.test":{"role":"home"}}}`) putJSON(t, m.s, "control/edges/dora.json", `{"v":1,"box":"dora","eip":"4.4.4.4","region":"eu-west-1","placement":"ie","hosts":{"d.test":{"role":"home"}}}`) putJSON(t, m.s, "control/edges/edna.json", `{"v":1,"box":"edna","eip":"5.5.5.5","private_ip":"10.0.1.5","region":"eu-west-1","placement":"fleet/shop","hosts":{"e.test":{"role":"home"}}}`) putJSON(t, m.s, "control/edges/fern.json", `{"v":1,"box":"fern","eip":"","private_ip":"10.0.1.6","region":"eu-west-1","placement":"ie","hosts":{"f.test":{"role":"home"}}}`) // Addresses a reader refuses: each falls back to the public address. putJSON(t, m.s, "control/edges/gail.json", `{"v":1,"box":"gail","eip":"7.7.7.7","private_ip":"10.0.1","region":"eu-west-1","placement":"ie","hosts":{"g.test":{"role":"home"}}}`) putJSON(t, m.s, "control/edges/hana.json", `{"v":1,"box":"hana","eip":"8.8.8.8","private_ip":"169.254.169.254","private_cidr":"169.254.0.0/16","region":"eu-west-1","placement":"ie","hosts":{"h.test":{"role":"home"}}}`) putJSON(t, m.s, "control/edges/iris.json", `{"v":1,"box":"iris","eip":"9.9.9.9","private_ip":"10.9.1.9","private_cidr":"10.9.0.0/16","region":"eu-west-1","placement":"ie","hosts":{"i.test":{"role":"home"}}}`) refreshHomeMap(t, m) } // Region HA spec 2 ยง6: with this edge's region HA on, a box in the same // region is dialled at its private address and a box in another region at // its own public address. An address that fails validation against this // edge's own network is refused, and the dial is public. func TestHomeMapDialsPrivateWithinTheRegionAndPublicBetween(t *testing.T) { m := newHomeMap(meshTestStore(t), "annie") m.privateDial = true privateFleet(t, m) for host, want := range map[string]string{ "b.test": "10.0.1.2", // same region and placement: private "c.test": "3.3.3.3", // another region: its own public address "d.test": "4.4.4.4", // a writer with no private_ip: public, as before "e.test": "5.5.5.5", // same AWS region, another placement: public "f.test": "10.0.1.6", // no public address, but private within the region "g.test": "7.7.7.7", // a malformed private address: refused "h.test": "8.8.8.8", // the metadata range: refused "i.test": "9.9.9.9", // outside this region's network: refused } { if addr, _, ok := m.Home(host); !ok || addr != want { t.Errorf("%s dials %q (ok=%v), want %q", host, addr, ok, want) } } // An edge whose own file is not in the map knows no region or network // of its own: every dial is public, and a box with no public address // is no target. ghost := newHomeMap(m.s, "ghost") ghost.privateDial = true refreshHomeMap(t, ghost) if addr, _, _ := ghost.Home("b.test"); addr != "2.2.2.2" { t.Errorf("without its own file: b.test dials %q, want 2.2.2.2", addr) } if _, _, ok := ghost.Home("f.test"); ok { t.Error("without its own file, a box with no public address became a target") } } // With this edge's region HA off, a peer publishing private_ip changes // nothing: every dial is public, as on main, during a mixed roll or a // rollback. func TestHomeMapWithRegionHAOffDialsPublicOnly(t *testing.T) { m := newHomeMap(meshTestStore(t), "annie") privateFleet(t, m) for host, want := range map[string]string{"b.test": "2.2.2.2", "c.test": "3.3.3.3", "d.test": "4.4.4.4"} { if addr, _, ok := m.Home(host); !ok || addr != want { t.Errorf("%s dials %q (ok=%v), want %q", host, addr, ok, want) } } if _, _, ok := m.Home("f.test"); ok { t.Error("a box with only a private address became a target with region HA off") } } func TestEdgeHomeMapFollowsRegionHA(t *testing.T) { e := &Edge{staticStore: meshTestStore(t), box: "annie"} t.Setenv("CARLOS_REGION_HA", "") if e.newHomeMap().privateDial { t.Fatal("region HA unset dials private") } t.Setenv("CARLOS_REGION_HA", "1") if !e.newHomeMap().privateDial { t.Fatal("region HA on does not dial private") } } // Astra 2a final review, P2: the home's placement code is "". Two home // boxes in one AWS region share a placement, so a home edge dials a home // peer at its private address, under the same guards as a named region: // the same AWS region, an address inside this edge's own network, and this // edge's region HA on. A home edge never dials a named-placement box // privately, nor a named edge a home box, though they share the AWS region // and the network. func TestHomeMapDialsHomeBoxesPrivately(t *testing.T) { m := newHomeMap(meshTestStore(t), "hilda") privateFleet(t, m) putJSON(t, m.s, "control/edges/hilda.json", `{"v":1,"box":"hilda","eip":"11.11.11.11","private_ip":"10.0.2.1","private_cidr":"10.0.0.0/16","region":"eu-west-1","placement":"","hosts":{}}`) putJSON(t, m.s, "control/edges/ivy.json", `{"v":1,"box":"ivy","eip":"12.12.12.12","private_ip":"10.0.2.2","private_cidr":"10.0.0.0/16","region":"eu-west-1","placement":"","hosts":{"ivy.test":{"role":"home"}}}`) putJSON(t, m.s, "control/edges/jill.json", `{"v":1,"box":"jill","eip":"","private_ip":"10.0.2.3","region":"eu-west-1","hosts":{"jill.test":{"role":"home"}}}`) putJSON(t, m.s, "control/edges/kim.json", `{"v":1,"box":"kim","eip":"14.14.14.14","private_ip":"10.0.2.4","region":"eu-west-2","placement":"","hosts":{"kim.test":{"role":"home"}}}`) putJSON(t, m.s, "control/edges/lou.json", `{"v":1,"box":"lou","eip":"15.15.15.15","private_ip":"10.9.2.5","region":"eu-west-1","placement":"","hosts":{"lou.test":{"role":"home"}}}`) homeWant := map[string]string{ "ivy.test": "10.0.2.2", // a home peer in the same region: private "jill.test": "10.0.2.3", // no public address, but private within the home "kim.test": "14.14.14.14", // a home box in another AWS region: public "lou.test": "15.15.15.15", // outside this edge's network: refused "b.test": "2.2.2.2", // a named placement (ie) in the same region: public } m.privateDial = true refreshHomeMap(t, m) for host, want := range homeWant { if addr, _, ok := m.Home(host); !ok || addr != want { t.Errorf("home edge: %s dials %q (ok=%v), want %q", host, addr, ok, want) } } // A named edge (annie, in ie, the same AWS region and network) dials // every home box at its public address. named := newHomeMap(m.s, "annie") named.privateDial = true refreshHomeMap(t, named) for host, want := range map[string]string{"ivy.test": "12.12.12.12", "b.test": "10.0.1.2"} { if addr, _, ok := named.Home(host); !ok || addr != want { t.Errorf("named edge: %s dials %q (ok=%v), want %q", host, addr, ok, want) } } if _, _, ok := named.Home("jill.test"); ok { t.Error("named edge: a home box with only a private address became a target") } // With this edge's region HA off, the home dials are public, as on main. off := newHomeMap(m.s, "hilda") refreshHomeMap(t, off) if addr, _, _ := off.Home("ivy.test"); addr != "12.12.12.12" { t.Errorf("region HA off: ivy.test dials %q, want 12.12.12.12", addr) } if _, _, ok := off.Home("jill.test"); ok { t.Error("region HA off: a home box with only a private address became a target") } }