Example #1
0
func mapJobToSchema(j *job.Job) (*schema.Unit, error) {
	su := schema.Unit{
		Name:            j.Name,
		FileHash:        j.Unit.Hash().String(),
		FileContents:    encodeUnitContents(&j.Unit),
		TargetMachineID: j.TargetMachineID,
		DesiredState:    string(j.TargetState),
	}

	if j.State != nil {
		su.CurrentState = string(*(j.State))
	}

	if j.UnitState != nil {
		su.Systemd = &schema.SystemdState{
			LoadState:   j.UnitState.LoadState,
			ActiveState: j.UnitState.ActiveState,
			SubState:    j.UnitState.SubState,
		}
		if j.UnitState.MachineID != "" {
			su.Systemd.MachineID = j.UnitState.MachineID
		}
	}

	return &su, nil
}
func TestListUnitFilesFieldsToStrings(t *testing.T) {
	u := schema.Unit{
		Name:    "foo.service",
		Options: []*schema.UnitOption{},
	}

	for k, v := range map[string]string{
		"hash":     "da39a3e",
		"desc":     "-",
		"dstate":   "-",
		"tmachine": "-",
		"state":    "-",
	} {
		f := listUnitFilesFields[k](u, false)
		assertEqual(t, k, v, f)
	}

	f := listUnitFilesFields["unit"](u, false)
	assertEqual(t, "unit", u.Name, f)

	u = schema.Unit{
		Name: "foo.service",
		Options: []*schema.UnitOption{
			&schema.UnitOption{Section: "Unit", Name: "Description", Value: "some description"},
		},
	}

	d := listUnitFilesFields["desc"](u, false)
	assertEqual(t, "desc", "some description", d)

	for _, state := range []job.JobState{job.JobStateLoaded, job.JobStateInactive, job.JobStateLaunched} {
		u.CurrentState = string(state)
		f := listUnitFilesFields["state"](u, false)
		assertEqual(t, "state", string(state), f)
	}

	// machineStates must be initialized since cAPI is not set
	machineStates = map[string]*machine.MachineState{}

	u.MachineID = "some-id"
	ms := listUnitFilesFields["tmachine"](u, true)
	assertEqual(t, "machine", "some-id", ms)

	u.MachineID = "other-id"
	machineStates = map[string]*machine.MachineState{
		"other-id": &machine.MachineState{
			ID:       "other-id",
			PublicIP: "1.2.3.4",
		},
	}
	ms = listUnitFilesFields["tmachine"](u, true)
	assertEqual(t, "machine", "other-id/1.2.3.4", ms)

	uh := "a0f275d46bc6ee0eca06be7c339913c07d99c0c7"
	fuh := listUnitFilesFields["hash"](u, true)
	suh := listUnitFilesFields["hash"](u, false)
	assertEqual(t, "hash", uh, fuh)
	assertEqual(t, "hash", uh[:7], suh)
}
Example #3
0
func (ur *unitsResource) set(rw http.ResponseWriter, req *http.Request, item string) {
	if err := validateContentType(req); err != nil {
		sendError(rw, http.StatusUnsupportedMediaType, err)
		return
	}

	var su schema.Unit
	dec := json.NewDecoder(req.Body)
	err := dec.Decode(&su)
	if err != nil {
		sendError(rw, http.StatusBadRequest, fmt.Errorf("unable to decode body: %v", err))
		return
	}
	if su.Name == "" {
		su.Name = item
	}
	if item != su.Name {
		sendError(rw, http.StatusBadRequest, fmt.Errorf("name in URL %q differs from unit name in request body %q", item, su.Name))
		return
	}
	if err := ValidateName(su.Name); err != nil {
		sendError(rw, http.StatusBadRequest, err)
		return
	}

	eu, err := ur.cAPI.Unit(su.Name)
	if err != nil {
		log.Errorf("Failed fetching Unit(%s) from Registry: %v", su.Name, err)
		sendError(rw, http.StatusInternalServerError, nil)
		return
	}

	if eu == nil {
		if len(su.Options) == 0 {
			err := errors.New("unit does not exist and options field empty")
			sendError(rw, http.StatusConflict, err)
		} else if err := ValidateOptions(su.Options); err != nil {
			sendError(rw, http.StatusBadRequest, err)
		} else {
			ur.create(rw, su.Name, &su)
		}
		return
	}

	if len(su.DesiredState) == 0 {
		err := errors.New("must provide DesiredState to update existing unit")
		sendError(rw, http.StatusConflict, err)
		return
	}

	un := unit.NewUnitNameInfo(su.Name)
	if un.IsTemplate() && job.JobState(su.DesiredState) != job.JobStateInactive {
		err := fmt.Errorf("cannot activate template %q", su.Name)
		sendError(rw, http.StatusBadRequest, err)
		return
	}

	ur.update(rw, su.Name, su.DesiredState)
}
Example #4
0
func (d *deployer) deployUnit(wantedUnit *schema.Unit) error {
	currentUnit, err := d.fleetapi.Unit(wantedUnit.Name)
	if err != nil {
		return err
	}
	if currentUnit == nil {
		err := d.fleetapi.CreateUnit(wantedUnit)
		if err != nil {
			return err
		}
		return nil
	}

	wuf := schema.MapSchemaUnitOptionsToUnitFile(wantedUnit.Options)
	cuf := schema.MapSchemaUnitOptionsToUnitFile(currentUnit.Options)
	if wuf.Hash() != cuf.Hash() {
		log.Printf("INFO Service %s differs from the cluster version", wantedUnit.Name)
		wantedUnit.DesiredState = "inactive"
		err = d.fleetapi.DestroyUnit(wantedUnit.Name)
		if err != nil {
			return err
		}
		err = d.fleetapi.CreateUnit(wantedUnit)
		if err != nil {
			return err
		}
	}
	return nil
}
Example #5
0
// MakeUnitChain creates the unit files of the benchmark units.
func (b *Builder) MakeUnitChain(id string) []schema.Unit {
	unitsList := []schema.Unit{}

	// 3 dependsOn 2; 2 dependsOn 1; 1 dependsOn 0
	// 0 after 1; 1 after 2 ; 2 after 3

	for i := b.instanceGroupSize - 1; i >= 0; i-- {
		name := fmt.Sprintf("%s-%d@%s.service", b.unitPrefix, i, id)
		unit := schema.Unit{
			Name: name,
		}
		if b.app.Type == "unitfiles" && b.unitFile != nil {
			unit.Options = b.buildCustomService()
		} else if b.app.Type == "docker" {
			unit.Options = b.buildDockerService()
		} else if b.app.Type == "rkt" {
			unit.Options = b.buildRktService()
		} else {
			unit.Options = b.buildShellService()
		}

		if i > 0 {
			depName := fmt.Sprintf("%s-%d@%s.service", b.unitPrefix, i-1, id)
			unit.Options = append(unit.Options,
				&schema.UnitOption{
					Section: "X-Fleet",
					Name:    "MachineOf",
					Value:   depName,
				},
			)
		}
		unitsList = append(unitsList, unit)
	}

	if len(unitsList) > 1 {
		for i := 0; i < (len(unitsList) - 1); i++ {
			depName := unitsList[i+1].Name
			unitsList[i].Options = append(unitsList[i].Options,
				&schema.UnitOption{
					Section: "Unit",
					Name:    "Before",
					Value:   depName,
				},
				&schema.UnitOption{
					Section: "Unit",
					Name:    "BindTo",
					Value:   depName,
				},
			)
		}
	}

	return unitsList
}
Example #6
0
func (ur *unitsResource) set(rw http.ResponseWriter, req *http.Request, item string) {
	if err := validateContentType(req); err != nil {
		sendError(rw, http.StatusUnsupportedMediaType, err)
		return
	}

	var su schema.Unit
	dec := json.NewDecoder(req.Body)
	err := dec.Decode(&su)
	if err != nil {
		sendError(rw, http.StatusBadRequest, fmt.Errorf("unable to decode body: %v", err))
		return
	}
	if su.Name == "" {
		su.Name = item
	}
	if item != su.Name {
		sendError(rw, http.StatusBadRequest, fmt.Errorf("name in URL %q differs from unit name in request body %q", item, su.Name))
		return
	}
	if err := ValidateName(su.Name); err != nil {
		sendError(rw, http.StatusBadRequest, err)
		return
	}

	eu, err := ur.cAPI.Unit(su.Name)
	if err != nil {
		log.Errorf("Failed fetching Unit(%s) from Registry: %v", su.Name, err)
		sendError(rw, http.StatusInternalServerError, nil)
		return
	}

	newUnit := false
	if eu == nil {
		if len(su.Options) == 0 {
			err := errors.New("unit does not exist and options field empty")
			sendError(rw, http.StatusConflict, err)
			return
		} else if err := ValidateOptions(su.Options); err != nil {
			sendError(rw, http.StatusBadRequest, err)
			return
		} else {
			// New valid unit
			newUnit = true
		}
	} else if eu.Name == su.Name && len(su.Options) > 0 {
		// There is already a unit with the same name that
		// was submitted before. Check their hashes, if they do
		// not match then this is probably a new version which
		// needs its own new unit entry.
		// In the other case if su.Options == 0 then probably we
		// don't want to update the Unit options nor its content
		// but only set the target job state of the
		// corresponding unit, in this case just ignore.
		a := schema.MapSchemaUnitOptionsToUnitFile(su.Options)
		b := schema.MapSchemaUnitOptionsToUnitFile(eu.Options)
		newUnit = !unit.MatchUnitFiles(a, b)
	}

	if newUnit {
		ur.create(rw, su.Name, &su)
		return
	}

	if len(su.DesiredState) == 0 {
		err := errors.New("must provide DesiredState to update existing unit")
		sendError(rw, http.StatusConflict, err)
		return
	}

	un := unit.NewUnitNameInfo(su.Name)
	if un.IsTemplate() && job.JobState(su.DesiredState) != job.JobStateInactive {
		err := fmt.Errorf("cannot activate template %q", su.Name)
		sendError(rw, http.StatusBadRequest, err)
		return
	}

	ur.update(rw, su.Name, su.DesiredState)
}