// 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 }
// 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 }
// 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 }
// 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 }
// 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} }