mirror of
https://github.com/rancher/norman.git
synced 2025-08-31 14:51:57 +00:00
Conditions framework
This commit is contained in:
149
condition/condition.go
Normal file
149
condition/condition.go
Normal file
@@ -0,0 +1,149 @@
|
||||
package condition
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/rancher/norman/controller"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
type Cond string
|
||||
|
||||
func (c Cond) True(obj runtime.Object) {
|
||||
setStatus(obj, string(c), "True")
|
||||
}
|
||||
|
||||
func (c Cond) IsTrue(obj runtime.Object) bool {
|
||||
return getStatus(obj, string(c)) == "True"
|
||||
}
|
||||
|
||||
func (c Cond) False(obj runtime.Object) {
|
||||
setStatus(obj, string(c), "False")
|
||||
}
|
||||
|
||||
func (c Cond) IsFalse(obj runtime.Object) bool {
|
||||
return getStatus(obj, string(c)) == "False"
|
||||
}
|
||||
|
||||
func (c Cond) Unknown(obj runtime.Object) {
|
||||
setStatus(obj, string(c), "Unknown")
|
||||
}
|
||||
|
||||
func (c Cond) IsUnknown(obj runtime.Object) bool {
|
||||
return getStatus(obj, string(c)) == "Unknown"
|
||||
}
|
||||
|
||||
func (c Cond) Reason(obj runtime.Object, reason string) {
|
||||
cond := findOrCreateCond(obj, string(c))
|
||||
getFieldValue(cond, "Reason").SetString(reason)
|
||||
touchTS(cond)
|
||||
}
|
||||
|
||||
func (c Cond) GetReason(obj runtime.Object) string {
|
||||
cond := findOrCreateCond(obj, string(c))
|
||||
return getFieldValue(cond, "Reason").String()
|
||||
}
|
||||
|
||||
func (c Cond) Once(obj runtime.Object, f func() (runtime.Object, error)) (runtime.Object, error) {
|
||||
if c.IsFalse(obj) {
|
||||
return obj, &controller.ForgetError{
|
||||
Err: errors.New(c.GetReason(obj)),
|
||||
}
|
||||
}
|
||||
|
||||
if c.IsTrue(obj) {
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
c.Unknown(obj)
|
||||
newObj, err := f()
|
||||
if newObj != nil {
|
||||
obj = newObj
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
c.False(obj)
|
||||
c.Reason(obj, err.Error())
|
||||
return obj, err
|
||||
}
|
||||
c.True(obj)
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
func (c Cond) Do(obj runtime.Object, f func() error) error {
|
||||
c.Unknown(obj)
|
||||
if err := f(); err != nil {
|
||||
c.False(obj)
|
||||
c.Reason(obj, err.Error())
|
||||
return err
|
||||
}
|
||||
c.True(obj)
|
||||
return nil
|
||||
}
|
||||
|
||||
func touchTS(value reflect.Value) {
|
||||
now := time.Now().Format(time.RFC3339)
|
||||
getFieldValue(value, "LastUpdateTime").SetString(now)
|
||||
}
|
||||
|
||||
func getStatus(obj interface{}, condName string) string {
|
||||
cond := findOrCreateCond(obj, condName)
|
||||
return getFieldValue(cond, "Status").String()
|
||||
}
|
||||
|
||||
func setStatus(obj interface{}, condName, status string) {
|
||||
cond := findOrCreateCond(obj, condName)
|
||||
getFieldValue(cond, "Status").SetString(status)
|
||||
touchTS(cond)
|
||||
}
|
||||
|
||||
func findOrCreateCond(obj interface{}, condName string) reflect.Value {
|
||||
condSlice := getValue(obj, "Status", "Conditions")
|
||||
cond := findCond(condSlice, condName)
|
||||
if cond != nil {
|
||||
return *cond
|
||||
}
|
||||
|
||||
newCond := reflect.New(condSlice.Type().Elem()).Elem()
|
||||
newCond.FieldByName("Type").SetString(condName)
|
||||
newCond.FieldByName("Status").SetString("Unknown")
|
||||
condSlice.Set(reflect.Append(condSlice, newCond))
|
||||
return newCond
|
||||
}
|
||||
|
||||
func findCond(val reflect.Value, name string) *reflect.Value {
|
||||
for i := 0; i < val.Len(); i++ {
|
||||
cond := val.Index(i)
|
||||
typeVal := getFieldValue(cond, "Type")
|
||||
if typeVal.String() == name {
|
||||
return &cond
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getValue(obj interface{}, name ...string) reflect.Value {
|
||||
v := reflect.ValueOf(obj)
|
||||
t := v.Type()
|
||||
if t.Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
t = v.Type()
|
||||
}
|
||||
|
||||
field := v.FieldByName(name[0])
|
||||
if len(name) == 1 {
|
||||
return field
|
||||
}
|
||||
return getFieldValue(field, name[1:]...)
|
||||
}
|
||||
|
||||
func getFieldValue(v reflect.Value, name ...string) reflect.Value {
|
||||
field := v.FieldByName(name[0])
|
||||
if len(name) == 1 {
|
||||
return field
|
||||
}
|
||||
return getFieldValue(field, name[1:]...)
|
||||
}
|
Reference in New Issue
Block a user