func (sr *ScheduledResource) ResetStatus() {
	sr.Lock()
	defer sr.Unlock()
	sr.Error = nil
	sr.status = ""
}
ResetStatus resets cached status of scheduled resource
package scheduler
import (
	"fmt"
	"log"
	"sync"
	"time"
	"github.com/Mirantis/k8s-AppController/pkg/interfaces"
	"github.com/Mirantis/k8s-AppController/pkg/report"
	"github.com/Mirantis/k8s-AppController/pkg/resources"
	"k8s.io/client-go/pkg/api/errors"
	"k8s.io/client-go/pkg/api/unversioned"
)
const (
	CheckInterval = time.Millisecond * 1000
	WaitTimeout   = time.Second * 600
)
type ScheduledResource struct {
	Requires       []string
	RequiredBy     []string
	Started        bool
	Ignored        bool
	Error          error
	Existing       bool
	context        *graphContext
	usedInReplicas []string
	status         interfaces.ResourceStatus
	suffix         string
	interfaces.Resource
	Meta map[string]map[string]string
	sync.RWMutex
}
func (sr *ScheduledResource) Key() string {
	baseKey := sr.Resource.Key()
	if sr.suffix == "" {
		return baseKey
	}
	return baseKey + "/" + sr.suffix
}
func (sr *ScheduledResource) RequestCreation(toCreate chan *ScheduledResource) bool {
	sr.RLock()
	if sr.Started {
		sr.RUnlock()
		return true
	}
	sr.RUnlock()
	sr.Lock()
	defer sr.Unlock()
	if !sr.Started && !sr.IsBlocked() {
		sr.Started = true
		toCreate <- sr
		return true
	}
	return false
}
func isResourceFinished(sr *ScheduledResource, ch chan error) bool {
	status, err := sr.Status(nil)
	if err != nil {
		ch <- err
		return true
	}
	if status == interfaces.ResourceReady {
		ch <- nil
		return true
	}
	return false
}
func (sr *ScheduledResource) Wait(checkInterval time.Duration, timeout time.Duration, stopChan <-chan struct{}) (bool, error) {
	ch := make(chan error, 1)
	go func(ch chan error) {
		log.Printf("%s flow: waiting for %v to be created", sr.context.graph.graphOptions.FlowName, sr.Key())
		if isResourceFinished(sr, ch) {
			return
		}
		ticker := time.NewTicker(checkInterval)
		for {
			select {
			case <-stopChan:
				return
			case <-ticker.C:
				if isResourceFinished(sr, ch) {
					return
				}
			}
		}
	}(ch)
	select {
	case <-stopChan:
		return true, nil
	case err := <-ch:
		return false, err
	case <-time.After(timeout):
		e := fmt.Errorf("%s flow: timeout waiting for resource %s", sr.context.graph.graphOptions.FlowName, sr.Key())
		sr.Lock()
		defer sr.Unlock()
		sr.Error = e
		return false, e
	}
}
func (sr *ScheduledResource) Status(meta map[string]string) (interfaces.ResourceStatus, error) {
	sr.Lock()
	defer sr.Unlock()
	if sr.status != "" || sr.Error != nil {
		return sr.status, sr.Error
	}
	status, err := sr.Resource.Status(meta)
	if err == nil && status == interfaces.ResourceReady {
		sr.status = status
	}
	return status, err
}
func (sr *ScheduledResource) IsBlocked() bool {
	for _, reqKey := range sr.Requires {
		meta := sr.Meta[reqKey]
		_, onErrorSet := meta["on-error"]
		req := sr.context.graph.graph[reqKey]
		status, err := req.Status(meta)
		req.RLock()
		ignored := req.Ignored
		req.RUnlock()
		if err != nil && !onErrorSet && !ignored {
			return true
		} else if status == "ready" && onErrorSet {
			return true
		} else if err == nil && status != "ready" {
			return true
		}
	}
	return false
}