Пример #1
0
func newFakeRegistryForSsh() registry.Registry {
	machines := []machine.MachineState{
		{"c31e44e1-f858-436e-933e-59c642517860", "1.2.3.4", map[string]string{"ping": "pong"}, "", resource.ResourceTuple{}},
		{"595989bb-cbb7-49ce-8726-722d6e157b4e", "5.6.7.8", map[string]string{"foo": "bar"}, "", resource.ResourceTuple{}},
		{"hello.service", "8.7.6.5", map[string]string{"foo": "bar"}, "", resource.ResourceTuple{}},
	}

	jobs := []job.Job{
		*job.NewJob("j1.service", unit.Unit{}),
		*job.NewJob("j2.service", unit.Unit{}),
		*job.NewJob("hello.service", unit.Unit{}),
	}

	states := map[string]*unit.UnitState{
		"j1.service":    unit.NewUnitState("loaded", "active", "listening", &machines[0]),
		"j2.service":    unit.NewUnitState("loaded", "inactive", "dead", &machines[1]),
		"hello.service": unit.NewUnitState("loaded", "inactive", "dead", &machines[2]),
	}

	reg := registry.NewFakeRegistry()
	reg.SetMachines(machines)
	reg.SetUnitStates(states)
	reg.SetJobs(jobs)

	return reg
}
Пример #2
0
func newFakeRegistryForSsh() registry.Registry {
	// clear machineStates for every invocation
	machineStates = nil
	machines := []machine.MachineState{
		newMachineState("c31e44e1-f858-436e-933e-59c642517860", "1.2.3.4", map[string]string{"ping": "pong"}),
		newMachineState("595989bb-cbb7-49ce-8726-722d6e157b4e", "5.6.7.8", map[string]string{"foo": "bar"}),
		newMachineState("hello.service", "8.7.6.5", map[string]string{"foo": "bar"}),
	}

	jobs := []job.Job{
		*job.NewJob("j1.service", unit.Unit{}),
		*job.NewJob("j2.service", unit.Unit{}),
		*job.NewJob("hello.service", unit.Unit{}),
	}

	states := map[string]*unit.UnitState{
		"j1.service":    unit.NewUnitState("loaded", "active", "listening", machines[0].ID),
		"j2.service":    unit.NewUnitState("loaded", "inactive", "dead", machines[1].ID),
		"hello.service": unit.NewUnitState("loaded", "inactive", "dead", machines[2].ID),
	}

	reg := registry.NewFakeRegistry()
	reg.SetMachines(machines)
	reg.SetUnitStates(states)
	reg.SetJobs(jobs)

	return reg
}
Пример #3
0
// Assert that jobs and their peers are properly indexed
func TestGetJobsByPeer(t *testing.T) {
	state := NewState()

	u1 := unit.NewUnit(`[X-Fleet]
X-ConditionMachineOf=b
X-ConditionMachineOf=c
`)
	j1 := job.NewJob("a", *u1)
	state.TrackJob(j1)

	u2 := unit.NewUnit(`[X-Fleet]
X-ConditionMachineOf=c
`)
	j2 := job.NewJob("d", *u2)
	state.TrackJob(j2)

	peers := state.GetJobsByPeer("b")
	if len(peers) != 1 || peers[0] != "a" {
		t.Fatalf("Unexpected index of job peers %v", peers)
	}

	peers = state.GetJobsByPeer("c")
	if len(peers) != 2 || peers[0] != "a" || peers[1] != "d" {
		t.Fatalf("Unexpected index of job peers %v", peers)
	}
}
Пример #4
0
func (r *EtcdRegistry) getJobFromModel(jm jobModel) *job.Job {
	var err error
	var unit *unit.Unit

	// New-style Jobs should have a populated UnitHash, and the contents of the Unit are stored separately in the Registry
	if !jm.UnitHash.Empty() {
		unit = r.getUnitByHash(jm.UnitHash)
		if unit == nil {
			log.Warningf("No Unit found in Registry for Job(%s)", jm.Name)
			return nil
		}
		if unit.Hash() != jm.UnitHash {
			log.Errorf("Unit Hash %s does not match expected %s for Job(%s)!", unit.Hash(), jm.UnitHash, jm.Name)
			return nil
		}
	} else {
		// Old-style Jobs had "Payloads" instead of Units, also stored separately in the Registry
		unit, err = r.getUnitFromLegacyPayload(jm.Name)
		if err != nil {
			log.Errorf("Error retrieving legacy payload for Job(%s)", jm.Name)
			return nil
		} else if unit == nil {
			log.Warningf("No Payload found in Registry for Job(%s)", jm.Name)
			return nil
		}

		log.Infof("Migrating legacy Payload(%s)", jm.Name)
		if err := r.storeOrGetUnit(*unit); err != nil {
			log.Warningf("Unable to migrate legacy Payload: %v", err)
		}
	}

	return job.NewJob(jm.Name, *unit)
}
Пример #5
0
func TestSignJob(t *testing.T) {
	c, _ := initSign(t)

	u := unit.NewUnit("Echo")
	j := job.NewJob("echo.service", *u)

	data, err := marshal(u)
	if err != nil {
		t.Fatal("marshal error:", err)
	}

	expectedSig, err := c.keyring.Sign(testPublicKeys["rsa"], data)
	if err != nil {
		t.Fatal("sign error:", err)
	}

	s, err := c.SignJob(j)
	if err != nil {
		t.Fatal("sign payload error:", err)
	}
	if s.Tag != TagForJob("echo.service") {
		t.Fatal("sign tag error:", err)
	}

	if len(s.Signatures) != 1 {
		t.Fatal("expect 1 signature instead of", len(s.Signatures))
	}
	if bytes.Compare(s.Signatures[0].Blob, expectedSig.Blob) != 0 {
		t.Fatal("wrong signature")
	}
}
Пример #6
0
func newTestJobWithMachineMetadata(metadata string) *job.Job {
	contents := fmt.Sprintf(`
[X-Fleet]
%s
`, metadata)

	return job.NewJob("pong.service", *unit.NewUnit(contents))
}
Пример #7
0
func TestFakeRegistryJobLifecycle(t *testing.T) {
	reg := NewFakeRegistry()

	jobs, err := reg.Jobs()
	if err != nil {
		t.Fatalf("Received error while calling Jobs: %v", err)
	}
	if !reflect.DeepEqual([]job.Job{}, jobs) {
		t.Fatalf("Expected no jobs, got %v", jobs)
	}

	u, _ := unit.NewUnit("")
	j1 := job.NewJob("job1.service", *u)
	err = reg.CreateJob(j1)
	if err != nil {
		t.Fatalf("Received error while calling CreateJob: %v", err)
	}

	jobs, err = reg.Jobs()
	if err != nil {
		t.Fatalf("Received error while calling Jobs: %v", err)
	}
	if len(jobs) != 1 {
		t.Fatalf("Expected 1 Job, got %v", jobs)
	}
	if jobs[0].Name != "job1.service" {
		t.Fatalf("Expected Job with name \"job1.service\", got %q", jobs[0].Name)
	}

	err = reg.ScheduleJob("job1.service", "XXX")
	if err != nil {
		t.Fatalf("Received error while calling ScheduleJob: %v", err)
	}

	j, err := reg.Job("job1.service")
	if err != nil {
		t.Fatalf("Received error while calling JobTarget: %v", err)
	}
	if j.TargetMachineID != "XXX" {
		t.Fatalf("Job should be scheduled to XXX, got %v", j.TargetMachineID)
	}

	err = reg.DestroyJob("job1.service")
	if err != nil {
		t.Fatalf("Received error while calling DestroyJob: %v", err)
	}

	jobs, err = reg.Jobs()
	if err != nil {
		t.Fatalf("Received error while calling Jobs: %v", err)
	}
	if !reflect.DeepEqual([]job.Job{}, jobs) {
		t.Fatalf("Expected no jobs, got %v", jobs)
	}
}
Пример #8
0
func TestListUnitsFieldsToStrings(t *testing.T) {
	j := job.NewJob("test", *unit.NewUnit(""))
	for _, tt := range []string{"state", "load", "active", "sub", "desc", "machine"} {
		f := listUnitsFields[tt](j, false)
		assertEqual(t, tt, "-", f)
	}

	f := listUnitsFields["unit"](j, false)
	assertEqual(t, "unit", "test", f)

	j = job.NewJob("test", *unit.NewUnit(`[Unit]
Description=some description`))
	d := listUnitsFields["desc"](j, false)
	assertEqual(t, "desc", "some description", d)

	for _, state := range []job.JobState{job.JobStateLoaded, job.JobStateInactive, job.JobStateLaunched} {
		j.State = &state
		f := listUnitsFields["state"](j, false)
		assertEqual(t, "state", string(state), f)
	}

	j.UnitState = unit.NewUnitState("foo", "bar", "baz", nil)
	for k, want := range map[string]string{
		"load":    "foo",
		"active":  "bar",
		"sub":     "baz",
		"machine": "-",
	} {
		got := listUnitsFields[k](j, false)
		assertEqual(t, k, want, got)
	}

	j.UnitState.MachineState = &machine.MachineState{"some-id", "1.2.3.4", nil, "", resource.ResourceTuple{}}
	ms := listUnitsFields["machine"](j, true)
	assertEqual(t, "machine", "some-id/1.2.3.4", ms)

	uh := "f035b2f14edc4d23572e5f3d3d4cb4f78d0e53c3"
	fuh := listUnitsFields["hash"](j, true)
	suh := listUnitsFields["hash"](j, false)
	assertEqual(t, "hash", uh, fuh)
	assertEqual(t, "hash", uh[:7], suh)
}
Пример #9
0
func createJob(jobName string, unit *unit.Unit) (*job.Job, error) {
	j := job.NewJob(jobName, *unit)

	if err := registryCtl.CreateJob(j); err != nil {
		return nil, fmt.Errorf("failed creating job %s: %v", j.Name, err)
	}

	log.V(1).Infof("Created Job(%s) in Registry", j.Name)

	return j, nil
}
Пример #10
0
func newTestJobFromUnitContents(t *testing.T, name, contents string) *job.Job {
	u, err := unit.NewUnitFile(contents)
	if err != nil {
		t.Fatalf("error creating Unit from %q: %v", contents, err)
	}
	j := job.NewJob(name, *u)
	if j == nil {
		t.Fatalf("error creating Job %q from %q", name, u)
	}
	return j
}
Пример #11
0
func newTestRegistryForListUnits(jobs []job.Job) registry.Registry {
	j := []job.Job{*job.NewJob("pong.service", *unit.NewUnit("Echo"))}

	if jobs != nil {
		for _, job := range jobs {
			j = append(j, job)
		}
	}

	return TestRegistry{jobs: j}
}
Пример #12
0
func newTestRegistryForSsh() registry.Registry {
	machines := []machine.MachineState{
		machine.MachineState{"c31e44e1-f858-436e-933e-59c642517860", "1.2.3.4", map[string]string{"ping": "pong"}, ""},
		machine.MachineState{"595989bb-cbb7-49ce-8726-722d6e157b4e", "5.6.7.8", map[string]string{"foo": "bar"}, ""},
		machine.MachineState{"hello.service", "8.7.6.5", map[string]string{"foo": "bar"}, ""},
	}

	jobs := []job.Job{
		*job.NewJob("j1.service", unit.Unit{}),
		*job.NewJob("j2.service", unit.Unit{}),
		*job.NewJob("hello.service", unit.Unit{}),
	}

	states := map[string]*unit.UnitState{
		"j1.service":    unit.NewUnitState("loaded", "active", "listening", &machines[0]),
		"j2.service":    unit.NewUnitState("loaded", "inactive", "dead", &machines[1]),
		"hello.service": unit.NewUnitState("loaded", "inactive", "dead", &machines[2]),
	}

	return TestRegistry{machines: machines, jobStates: states, jobs: jobs}
}
Пример #13
0
func TestAbleToRunConditionMachineIDMatch(t *testing.T) {
	u := unit.NewUnit(`[X-Fleet]
X-ConditionMachineID=XYZ
`)
	job := job.NewJob("example.service", *u)

	mach := &machine.FakeMachine{machine.MachineState{ID: "XYZ"}}
	agent := Agent{Machine: mach, state: NewState()}
	if !agent.ableToRun(job) {
		t.Fatalf("Agent should be able to run job")
	}
}
Пример #14
0
func TestAbleToRunConditionMachineIDMismatch(t *testing.T) {
	u := unit.NewUnit(`[X-Fleet]
X-ConditionMachineID=XYZ
`)
	job := job.NewJob("example.service", *u)

	mach := machine.New(machine.MachineState{ID: "123"})
	agent := Agent{machine: mach, state: NewState()}
	if agent.AbleToRun(job) {
		t.Fatalf("Agent should not be able to run job")
	}
}
Пример #15
0
func TestAbleToRunConditionMachineBootIDMismatch(t *testing.T) {
	uf := unit.NewSystemdUnitFile(`[X-Fleet]
X-ConditionMachineBootID=XYZ
`)
	payload := job.NewJobPayload("example.service", *uf)
	job := job.NewJob("example.service", make(map[string][]string, 0), payload, nil)

	mach := machine.New("123", "", make(map[string]string, 0))
	agent := Agent{machine: mach, state: NewState()}
	if agent.AbleToRun(job) {
		t.Fatalf("Agent should not be able to run job")
	}
}
Пример #16
0
// Assert that no jobs are returned for unknown peers
func TestGetJobsByPeerUnknown(t *testing.T) {
	u := unit.NewUnit(`[X-Fleet]
X-ConditionMachineOf=b
`)
	j := job.NewJob("a", *u)

	state := NewState()
	state.TrackJob(j)

	peers := state.GetJobsByPeer("c")
	if len(peers) != 0 {
		t.Fatalf("Unexpected index of job peers %v", peers)
	}
}
Пример #17
0
func newFakeRegistryForListUnits(jobs []job.Job) registry.Registry {
	j := []job.Job{*job.NewJob("pong.service", *unit.NewUnit("Echo"))}

	if jobs != nil {
		for _, job := range jobs {
			j = append(j, job)
		}
	}

	reg := registry.NewFakeRegistry()
	reg.SetJobs(j)

	return reg
}
Пример #18
0
// Assert that existing jobs and potential jobs that do not conflict do not
// trigger a match
func TestHasConflictNoMatch(t *testing.T) {
	state := NewState()

	u := unit.NewUnit(`[X-Fleet]`)
	j := job.NewJob("example.service", *u)
	state.TrackJob(j)
	state.SetTargetState(j.Name, job.JobStateLoaded)

	agent := Agent{state: state}

	matched, name := agent.HasConflict("other.service", []string{})
	if matched {
		t.Errorf("Expected no match, but got conflict with %s", name)
	}
}
Пример #19
0
func (ur *unitsResource) create(rw http.ResponseWriter, item string, ds job.JobState, u *unit.Unit) {
	j := job.NewJob(item, *u)

	if err := ur.reg.CreateJob(j); err != nil {
		log.Errorf("Failed creating Job(%s) in Registry: %v", j.Name, err)
		sendError(rw, http.StatusInternalServerError, nil)
		return
	}

	if err := ur.reg.SetJobTargetState(j.Name, ds); err != nil {
		log.Errorf("Failed setting target state of Job(%s): %v", j.Name, err)
		sendError(rw, http.StatusInternalServerError, nil)
		return
	}

	rw.WriteHeader(http.StatusNoContent)
}
Пример #20
0
func TestJobDescription(t *testing.T) {
	contents := `[Unit]
Description=PING
`
	jp := job.NewJobPayload("ping.service", *unit.NewSystemdUnitFile(contents))
	j := []job.Job{*job.NewJob("ping.service", map[string][]string{}, jp, nil)}
	registryCtl = newTestRegistryForListUnits(nil, j)

	names, _ := findAllUnits()
	if len(names) != 3 {
		t.Errorf("Expected to find three units: %v\n", names)
	}

	if names["ping.service"] != "PING" {
		t.Errorf("Expected to have `PING` as a description, but it was %s\n", names["ping.service"])
	}
}
Пример #21
0
// Assert that a potential conflict is triggered against the existing job name
func TestHasConflictPotentialMatch(t *testing.T) {
	state := NewState()

	u := unit.NewUnit(`[X-Fleet]`)
	j := job.NewJob("example.service", *u)
	state.TrackJob(j)
	state.SetTargetState(j.Name, job.JobStateLoaded)

	agent := Agent{state: state}

	matched, name := agent.HasConflict("other.service", []string{"example.service"})
	if !matched {
		t.Errorf("Expected conflict with 'example.service', no conflict reported")
	} else if name != "example.service" {
		t.Errorf("Expected conflict with 'example.service', but conflict found with %s", name)
	}
}
Пример #22
0
func TestHasConflictIgnoresBids(t *testing.T) {
	state := NewState()

	u := unit.NewUnit(`[X-Fleet]
X-Conflicts=other.service
`)
	j := job.NewJob("example.service", *u)
	state.TrackJob(j)
	state.TrackBid(j.Name)

	agent := Agent{state: state}

	matched, name := agent.HasConflict("other.service", []string{})
	if matched {
		t.Errorf("Expected no conflict, but got conflict with %s", name)
	}
}
Пример #23
0
func (r *EtcdRegistry) getJobFromObjectNode(node *etcd.Node) (*job.Job, error) {
	var err error
	var jm jobModel
	if err = unmarshal(node.Value, &jm); err != nil {
		return nil, err
	}

	var unit *unit.Unit

	// New-style Jobs should have a populated UnitHash, and the contents of the Unit are stored separately in the Registry
	if !jm.UnitHash.Empty() {
		unit = r.getUnitByHash(jm.UnitHash)
		if unit == nil {
			log.Warningf("No Unit found in Registry for Job(%s)", jm.Name)
			return nil, nil
		}
		if unit.Hash() != jm.UnitHash {
			log.Errorf("Unit Hash %s does not match expected %s for Job(%s)!", unit.Hash(), jm.UnitHash, jm.Name)
			return nil, nil
		}
	} else {
		// Old-style Jobs had "Payloads" instead of Units, also stored separately in the Registry
		unit, err = r.getUnitFromLegacyPayload(jm.Name)
		if err != nil {
			log.Errorf("Error retrieving legacy payload for Job(%s)", jm.Name)
			return nil, nil
		} else if unit == nil {
			log.Warningf("No Payload found in Registry for Job(%s)", jm.Name)
			return nil, nil
		}

		log.Infof("Migrating legacy Payload(%s)", jm.Name)
		if err := r.storeOrGetUnit(*unit); err != nil {
			log.Warningf("Unable to migrate legacy Payload: %v", err)
		}

		jm.UnitHash = unit.Hash()
		log.Infof("Updating Job(%s) with legacy payload Hash(%s)", jm.Name, jm.UnitHash)
		if err := r.updateJobObjectNode(&jm, node.ModifiedIndex); err != nil {
			log.Warningf("Unable to update Job(%s) with legacy payload Hash(%s): %v", jm.Name, jm.UnitHash, err)
		}
	}

	return job.NewJob(jm.Name, *unit), nil
}
Пример #24
0
func TestJobDescription(t *testing.T) {
	contents := `[Unit]
Description=PING
`
	j := []job.Job{*job.NewJob("ping.service", *unit.NewUnit(contents))}
	registryCtl = newFakeRegistryForListUnits(j)

	jobs, _, _ := findAllUnits()
	if len(jobs) != 2 {
		t.Errorf("Expected to find two units: %v\n", jobs)
	}

	ping := jobs["ping.service"]
	desc := ping.Unit.Description()
	if desc != "PING" {
		t.Errorf("Expected to have `PING` as a description, but it was %s\n", desc)
	}
}
Пример #25
0
func newTestRegistryForListUnits(payloads []job.JobPayload, jobs []job.Job) Registry {
	j := []job.Job{*job.NewJob("pong.service", map[string][]string{}, nil, nil)}
	p := []job.JobPayload{*job.NewJobPayload("echo.service", *unit.NewSystemdUnitFile("Echo"))}

	if payloads != nil {
		for _, jp := range payloads {
			p = append(p, jp)
		}
	}

	if jobs != nil {
		for _, job := range jobs {
			j = append(j, job)
		}
	}

	return TestRegistry{jobs: j, payloads: p}
}
Пример #26
0
func TestFakeRegistryJobLifecycle(t *testing.T) {
	reg := NewFakeRegistry()

	jobs, err := reg.GetAllJobs()
	if err != nil {
		t.Fatalf("Received error while calling GetAllJobs: %v", err)
	}
	if !reflect.DeepEqual([]job.Job{}, jobs) {
		t.Fatalf("Expected no jobs, got %v", jobs)
	}

	j1 := job.NewJob("job1.service", *unit.NewUnit(""))
	err = reg.CreateJob(j1)
	if err != nil {
		t.Fatalf("Received error while calling CreateJob: %v", err)
	}

	jobs, err = reg.GetAllJobs()
	if err != nil {
		t.Fatalf("Received error while calling GetAllJobs: %v", err)
	}
	if len(jobs) != 1 {
		t.Fatalf("Expected 1 Job, got %v", jobs)
	}
	if jobs[0].Name != "job1.service" {
		t.Fatalf("Expected Job with name \"job1.service\", got %q", jobs[0].Name)
	}

	err = reg.DestroyJob("job1.service")
	if err != nil {
		t.Fatalf("Received error while calling DestroyJob: %v", err)
	}

	jobs, err = reg.GetAllJobs()
	if err != nil {
		t.Fatalf("Received error while calling GetAllJobs: %v", err)
	}
	if !reflect.DeepEqual([]job.Job{}, jobs) {
		t.Fatalf("Expected no jobs, got %v", jobs)
	}
}
Пример #27
0
func TestVerifyJob(t *testing.T) {
	c, v := initSign(t)

	u, err := unit.NewUnit("Echo")
	if err != nil {
		t.Fatalf("unexpected error creating new unit: %v", err)
	}
	j := job.NewJob("echo.service", *u)

	data, err := marshal(u)
	if err != nil {
		t.Fatal("marshal error:", err)
	}

	v.pubkeys = append(v.pubkeys, testPublicKeys["rsa"])
	signature, err := c.keyring.Sign(testPublicKeys["rsa"], data)
	if err != nil {
		t.Fatal("sign error:", err)
	}

	ss := &SignatureSet{TagForJob("echo.service"), []*gossh.Signature{signature}}

	ok, err := v.VerifyJob(j, ss)
	if err != nil {
		t.Fatal("error verifying job:", err)
	}
	if !ok {
		t.Fatal("job verification failed")
	}

	ss.Tag = ""
	ok, err = v.VerifyJob(j, ss)
	if err == nil || ok == true {
		t.Fatal("should fail on job verification")
	}

	ok, err = v.VerifyJob(j, nil)
	if err == nil || ok == true {
		t.Fatal("should fail on job verification")
	}
}
Пример #28
0
func startUnitAction(c *cli.Context) {
	var err error
	r := getRegistry()

	payloads := make([]job.JobPayload, len(c.Args()))
	for i, v := range c.Args() {
		name := path.Base(v)
		payload := r.GetPayload(name)
		if payload == nil {
			payload, err = getJobPayloadFromFile(v)
			if err != nil {
				fmt.Println(err.Error())
				return
			}

			err = r.CreatePayload(payload)
			if err != nil {
				fmt.Printf("Creation of payload %s failed: %v\n", payload.Name, err)
				return
			}
		}

		payloads[i] = *payload
	}

	requirements := parseRequirements(c.String("require"))

	// TODO: This must be done in a transaction!
	for _, jp := range payloads {
		j := job.NewJob(jp.Name, requirements, &jp, nil)
		err := r.CreateJob(j)
		if err != nil {
			fmt.Printf("Creation of job %s failed: %v\n", j.Name, err)
		}
	}
}
Пример #29
0
func startUnitAction(c *cli.Context) {
	var err error

	// If signing is explicitly set to on, verification will be done also.
	toSign := c.Bool("sign")
	var sc *sign.SignatureCreator
	var sv *sign.SignatureVerifier
	if toSign {
		var err error
		sc, err = sign.NewSignatureCreatorFromSSHAgent()
		if err != nil {
			fmt.Println("Fail to create SignatureCreator:", err)
			return
		}
		sv, err = sign.NewSignatureVerifierFromSSHAgent()
		if err != nil {
			fmt.Println("Fail to create SignatureVerifier:", err)
			return
		}
	}

	payloads := make([]job.JobPayload, len(c.Args()))
	for i, v := range c.Args() {
		name := path.Base(v)
		payload := registryCtl.GetPayload(name)
		if payload == nil {
			payload, err = getJobPayloadFromFile(v)
			if err != nil {
				fmt.Println(err.Error())
				return
			}

			err = registryCtl.CreatePayload(payload)
			if err != nil {
				fmt.Printf("Creation of payload %s failed: %v\n", payload.Name, err)
				return
			}
			if toSign {
				s, err := sc.SignPayload(payload)
				if err != nil {
					fmt.Printf("Creation of sign for payload %s failed: %v\n", payload.Name, err)
					return
				}
				registryCtl.CreateSignatureSet(s)
			}
		}
		if toSign {
			s := registryCtl.GetSignatureSetOfPayload(name)
			ok, err := sv.VerifyPayload(payload, s)
			if !ok || err != nil {
				fmt.Printf("Check of payload %s failed: %v\n", payload.Name, err)
				return
			}
		}

		payloads[i] = *payload
	}

	requirements := parseRequirements(c.String("require"))

	// TODO: This must be done in a transaction!
	for _, jp := range payloads {
		j := job.NewJob(jp.Name, requirements, &jp, nil)
		err := registryCtl.CreateJob(j)
		if err != nil {
			fmt.Printf("Creation of job %s failed: %v\n", j.Name, err)
		}
	}
}
Пример #30
0
func TestSystemdUnitFlow(t *testing.T) {
	uDir, err := ioutil.TempDir("", "fleet-")
	if err != nil {
		t.Fatalf("Failed creating tempdir: %v", err)
	}
	defer os.RemoveAll(uDir)

	mgr, err := systemd.NewSystemdUnitManager(uDir, false)
	if err != nil {
		t.Fatalf("Failed initializing SystemdUnitManager: %v", err)
	}

	units, err := mgr.Units()
	if err != nil {
		t.Fatalf("Failed calling Units(): %v", err)
	}

	if len(units) > 0 {
		t.Fatalf("Expected no units to be returned, got %v", units)
	}

	contents := `[Service]
ExecStart=/usr/bin/sleep 3000
`
	name := fmt.Sprintf("fleet-unit-%d.service", rand.Int63())
	uf, err := unit.NewUnitFile(contents)
	if err != nil {
		t.Fatalf("Invalid unit file: %v", err)
	}
	hash := uf.Hash().String()
	j := job.NewJob(name, *uf)

	if err := mgr.Load(j.Name, j.Unit); err != nil {
		t.Fatalf("Failed loading job: %v", err)
	}

	units, err = mgr.Units()
	if err != nil {
		t.Fatalf("Failed calling Units(): %v", err)
	}

	if !reflect.DeepEqual([]string{name}, units) {
		t.Fatalf("Expected [hello.service], got %v", units)
	}

	err = waitForUnitState(mgr, name, unit.UnitState{"loaded", "inactive", "dead", "", hash, ""})
	if err != nil {
		t.Error(err.Error())
	}

	mgr.TriggerStart(name)

	err = waitForUnitState(mgr, name, unit.UnitState{"loaded", "active", "running", "", hash, ""})
	if err != nil {
		t.Error(err.Error())
	}

	mgr.TriggerStop(name)

	mgr.Unload(name)

	units, err = mgr.Units()
	if err != nil {
		t.Fatalf("Failed calling Units(): %v", err)
	}

	if len(units) > 0 {
		t.Fatalf("Expected no units to be returned, got %v", units)
	}
}