func (nc *nspawnCluster) WaitForNActiveUnits(m Member, count int) (map[string][]util.UnitState, error) { var nactive int states := make(map[string][]util.UnitState) timeout := 15 * time.Second alarm := time.After(timeout) ticker := time.Tick(250 * time.Millisecond) loop: for { select { case <-alarm: return nil, fmt.Errorf("failed to find %d active units within %v (last found: %d)", count, timeout, nactive) case <-ticker: stdout, _, err := nc.Fleetctl(m, "list-units", "--no-legend", "--full", "--fields", "unit,active,machine") stdout = strings.TrimSpace(stdout) if err != nil { continue } lines := strings.Split(stdout, "\n") allStates := util.ParseUnitStates(lines) active := util.FilterActiveUnits(allStates) nactive = len(active) if nactive != count { continue } for _, state := range active { name := state.Name if _, ok := states[name]; !ok { states[name] = []util.UnitState{} } states[name] = append(states[name], state) } break loop } } return states, nil }
func (nc *nspawnCluster) WaitForNActiveUnits(m Member, count int) (map[string][]util.UnitState, error) { var nactive int states := make(map[string][]util.UnitState) timeout, err := util.WaitForState( func() bool { stdout, _, err := nc.Fleetctl(m, "list-units", "--no-legend", "--full", "--fields", "unit,active,machine") stdout = strings.TrimSpace(stdout) if err != nil { return false } lines := strings.Split(stdout, "\n") allStates := util.ParseUnitStates(lines) active := util.FilterActiveUnits(allStates) nactive = len(active) if nactive != count { return false } for _, state := range active { name := state.Name if _, ok := states[name]; !ok { states[name] = []util.UnitState{} } states[name] = append(states[name], state) } return true }, ) if err != nil { return nil, fmt.Errorf("failed to find %d active units within %v (last found: %d)", count, timeout, nactive) } return states, nil }
// Start three machines and test template units based on machines Metadata func TestTemplatesWithSpecifiersInMetadata(t *testing.T) { cluster, err := platform.NewNspawnCluster("smoke") if err != nil { t.Fatal(err) } defer cluster.Destroy(t) members, err := platform.CreateNClusterMembers(cluster, 3) if err != nil { t.Fatal(err) } m0 := members[0] _, err = cluster.WaitForNMachines(m0, 3) if err != nil { t.Fatal(err) } // Submit one template if stdout, stderr, err := cluster.Fleetctl(m0, "submit", "fixtures/units/[email protected]"); err != nil { t.Fatalf("Unable to submit [email protected] template: \nstdout: %s\nstderr: %s\nerr: %v", stdout, stderr, err) } // Start units based on template in backward order for i := len(members) - 1; i >= 0; i-- { if stdout, stderr, err := cluster.Fleetctl(m0, "start", fmt.Sprintf("fixtures/units/metadata@smoke%s.service", members[i].ID())); err != nil { t.Fatalf("Unable to start template based unit: \nstdout: %s\nstderr: %s\nerr: %v", stdout, stderr, err) } } _, err = cluster.WaitForNActiveUnits(m0, 3) if err != nil { t.Fatal(err) } stdout, stderr, err := cluster.Fleetctl(m0, "list-units", "--no-legend", "--full", "--fields", "unit,active,machine") if err != nil { t.Fatalf("Unable to get submitted units: \nstdout: %s\nstderr: %s\nerr: %v", stdout, stderr, err) } ndesired := 3 stdout = strings.TrimSpace(stdout) lines := strings.Split(stdout, "\n") allStates := util.ParseUnitStates(lines) active := util.FilterActiveUnits(allStates) nactive := len(active) if nactive != ndesired { t.Fatalf("Failed to get %d active units: \nstdout: %s\nstderr: %s", ndesired, stdout, stderr) } for _, state := range active { re := regexp.MustCompile(`@([^.]*)`) desiredMachine := re.FindStringSubmatch(state.Name) if len(desiredMachine) < 2 { t.Fatalf("Cannot parse state.Name (%v): \nstdout: %s\nstderr: %s", state.Name, stdout, stderr) } currentMachine := fmt.Sprintf("smoke%s", state.Machine) if desiredMachine[1] != currentMachine { t.Fatalf("Template (%s) has been scheduled on wrong machine (%s): \nstdout: %s\nstderr: %s", state.Name, currentMachine, stdout, stderr) } } if stdout, stderr, err := cluster.Fleetctl(m0, "start", "--block-attempts=20", "fixtures/units/[email protected]"); err == nil { t.Fatalf("metadata@invalid unit should not be scheduled: \nstdout: %s\nstderr: %s", stdout, stderr) } }