Esempio n. 1
0
// processResource processes a single resource
func (c *Catalog) processResource(r resource.Resource) error {
	if err := r.Validate(); err != nil {
		return err
	}

	state, err := r.Evaluate()
	if err != nil {
		return err
	}

	if c.config.DryRun {
		return nil
	}

	// Current and wanted states for the resource
	want := utils.NewString(state.Want)
	current := utils.NewString(state.Current)

	// The list of present and absent states for the resource
	present := utils.NewList(r.GetPresentStates()...)
	absent := utils.NewList(r.GetAbsentStates()...)

	var action func() error
	switch {
	case want.IsInList(present) && current.IsInList(absent):
		action = r.Create
	case want.IsInList(absent) && current.IsInList(present):
		action = r.Delete
	case state.Outdated:
		action = r.Update
	}

	if action != nil {
		return action()
	}

	return nil
}
Esempio n. 2
0
// Validate validates the resource
func (b *Base) Validate() error {
	if b.Type == "" {
		return ErrInvalidType
	}

	if b.Name == "" {
		return ErrInvalidName
	}

	states := append(b.PresentStatesList, b.AbsentStatesList...)
	if !utils.NewList(states...).Contains(b.State) {
		return fmt.Errorf("Invalid state '%s'", b.State)
	}

	return nil
}
Esempio n. 3
0
// Validate validates the resource
func (b *Base) Validate() error {
	if b.Type == "" {
		return errors.New("Invalid resource type")
	}

	if b.Name == "" {
		return errors.New("Invalid resource name")
	}

	states := append(b.PresentStates, b.AbsentStates...)
	if !utils.NewList(states...).Contains(b.State) {
		return fmt.Errorf("Invalid state '%s'", b.State)
	}

	return nil
}
Esempio n. 4
0
// isHostsPropertySynced checks if the datastore is mounted on all hosts.
func (ds *DatastoreNfs) isHostsPropertySynced() (bool, error) {
	datastore, err := ds.finder.Datastore(ds.ctx, path.Join(ds.Path, ds.Name))
	if err != nil {
		if _, ok := err.(*find.NotFoundError); ok {
			return false, ErrResourceAbsent
		}
		return false, err
	}

	hosts, err := datastore.AttachedHosts(ds.ctx)
	if err != nil {
		return false, err
	}

	hostNames := make([]string, len(hosts))
	for _, obj := range hosts {
		name, err := obj.ObjectName(ds.ctx)
		if err != nil {
			return false, err
		}
		hostNames = append(hostNames, name)
	}

	isSynced := true
	hostsList := utils.NewList(hostNames...)
	for _, host := range ds.Hosts {
		if !hostsList.Contains(path.Base(host)) {
			ds.shouldMountOnHosts = append(ds.shouldMountOnHosts, host)
			isSynced = false
		}
	}

	for _, host := range ds.shouldMountOnHosts {
		Logf("%s datastore should be mounted on %s\n", ds.ID(), path.Base(host))
	}

	return isSynced, nil
}
Esempio n. 5
0
// execute processes a single resource
func (c *Catalog) execute(r resource.Resource) *StatusItem {
	if err := c.hasFailedDependencies(r); err != nil {
		return &StatusItem{Err: err}
	}

	if err := r.Validate(); err != nil {
		return &StatusItem{Err: err}
	}

	if err := r.Initialize(); err != nil {
		return &StatusItem{Err: err}
	}
	defer r.Close()

	state, err := r.Evaluate()
	if err != nil {
		return &StatusItem{Err: err}
	}

	if c.config.DryRun {
		return &StatusItem{}
	}

	// Current and wanted states for the resource
	want := utils.NewString(state.Want)
	current := utils.NewString(state.Current)

	// The list of present and absent states for the resource
	present := utils.NewList(r.PresentStates()...)
	absent := utils.NewList(r.AbsentStates()...)

	// Process resource
	id := r.ID()
	var action func() error
	switch {
	case want.IsInList(present) && current.IsInList(absent):
		action = r.Create
		c.config.Logger.Printf("%s is %s, should be %s\n", id, current, want)
	case want.IsInList(absent) && current.IsInList(present):
		action = r.Delete
		c.config.Logger.Printf("%s is %s, should be %s\n", id, current, want)
	default:
		// No-op: resource is in sync
	}

	stateChanged := false
	if action != nil {
		stateChanged = true
		if err := action(); err != nil {
			return &StatusItem{StateChanged: true, Err: err}
		}
	}

	// Process resource properties
	for _, p := range r.Properties() {
		synced, err := p.IsSynced()
		if err != nil {
			// Some properties make no sense if the resource is absent, e.g.
			// setting up file permissions requires that the file managed by the
			// resource is present, therefore we ignore errors for properties
			// which make no sense if the resource is absent.
			if err == resource.ErrResourceAbsent {
				continue
			}
			e := fmt.Errorf("unable to evaluate property %s: %s\n", p.Name, err)
			return &StatusItem{StateChanged: true, Err: e}
		}

		if !synced {
			stateChanged = true
			c.config.Logger.Printf("%s property '%s' is out of date\n", id, p.Name())
			if err := p.Set(); err != nil {
				e := fmt.Errorf("unable to set property %s: %s\n", p.Name, err)
				return &StatusItem{StateChanged: true, Err: e}
			}
		}
	}

	if err := c.runTriggers(r); err != nil {
		return &StatusItem{StateChanged: stateChanged, Err: err}
	}

	return &StatusItem{StateChanged: stateChanged, Err: nil}
}