1
0
mirror of https://github.com/rancher/norman.git synced 2025-07-03 10:38:15 +00:00
norman/condition/condition.go

155 lines
3.2 KiB
Go
Raw Normal View History

2017-12-16 08:26:07 +00:00
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
}
2017-12-18 22:16:28 +00:00
func (c Cond) Do(obj runtime.Object, f func() (runtime.Object, error)) error {
2017-12-16 08:26:07 +00:00
c.Unknown(obj)
2017-12-18 22:16:28 +00:00
newObj, err := f()
if newObj != nil {
obj = newObj
}
if err != nil {
2017-12-16 08:26:07 +00:00
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:]...)
}