1
0
mirror of https://github.com/rancher/types.git synced 2025-06-01 10:05:07 +00:00
types/status/status.go

318 lines
7.4 KiB
Go
Raw Normal View History

2017-11-15 23:59:47 +00:00
package status
import (
"strings"
2017-12-04 23:42:18 +00:00
"time"
"encoding/json"
2017-11-15 23:59:47 +00:00
"github.com/rancher/norman/types/convert"
2017-11-29 21:38:39 +00:00
"github.com/rancher/norman/types/values"
"github.com/sirupsen/logrus"
2017-11-15 23:59:47 +00:00
)
type status struct {
Conditions []condition `json:"conditions"`
}
2017-11-15 23:59:47 +00:00
type condition struct {
2018-06-05 04:44:54 +00:00
Reason string
2017-11-15 23:59:47 +00:00
Type string
Status string
Message string
}
2018-01-12 10:01:35 +00:00
// True ==
// False == error
// Unknown == transitioning
var transitioningMap = map[string]string{
2018-02-24 06:14:06 +00:00
"Active": "activating",
2018-03-31 10:15:08 +00:00
"AddonDeploy": "provisioning",
"AgentDeployed": "provisioning",
2018-02-24 06:14:06 +00:00
"BackingNamespaceCreated": "configuring",
2018-07-03 08:30:15 +00:00
"Built": "building",
2018-03-31 10:15:08 +00:00
"CertsGenerated": "provisioning",
2018-02-24 06:14:06 +00:00
"ConfigOK": "configuring",
"Created": "creating",
"CreatorMadeOwner": "configuring",
2018-02-24 06:14:06 +00:00
"DefaultNamespaceAssigned": "configuring",
"DefaultNetworkPolicyCreated": "configuring",
"DefaultProjectCreated": "configuring",
"DockerProvisioned": "provisioning",
"Deployed": "deploying",
2018-07-11 20:55:08 +00:00
"Drained": "draining",
2018-02-24 06:14:06 +00:00
"Downloaded": "downloading",
2018-03-31 10:15:08 +00:00
"etcd": "provisioning",
2018-02-24 06:14:06 +00:00
"Inactive": "deactivating",
"Initialized": "initializing",
2018-03-27 08:19:30 +00:00
"Installed": "installing",
2018-02-24 06:14:06 +00:00
"NodesCreated": "provisioning",
"Pending": "pending",
"PodScheduled": "scheduling",
"Provisioned": "provisioning",
2018-04-19 18:50:37 +00:00
"Refreshed": "refreshed",
2018-02-24 06:14:06 +00:00
"Registered": "registering",
"Removed": "removing",
"Saved": "saving",
"Updated": "updating",
"Updating": "updating",
2018-03-22 23:02:15 +00:00
"Waiting": "waiting",
"InitialRolesPopulated": "activating",
2019-03-28 13:16:41 +00:00
"ScalingActive": "pending",
"AbleToScale": "pending",
2019-12-12 22:14:43 +00:00
"RunCompleted": "running",
2018-01-12 10:01:35 +00:00
}
// True == error
// False ==
// Unknown ==
var reverseErrorMap = map[string]bool{
"OutOfDisk": true,
"MemoryPressure": true,
"DiskPressure": true,
"NetworkUnavailable": true,
"KernelHasNoDeadlock": true,
"Unschedulable": true,
"ReplicaFailure": true,
}
// True ==
// False == error
// Unknown ==
var errorMapping = map[string]bool{
2018-03-24 06:02:31 +00:00
"Failed": true,
"Progressing": true,
2018-01-12 10:01:35 +00:00
}
// True ==
// False == transitioning
2018-02-20 19:42:31 +00:00
// Unknown == error
2018-01-12 10:01:35 +00:00
var doneMap = map[string]string{
2018-06-19 19:50:22 +00:00
"Completed": "activating",
"Ready": "unavailable",
"Available": "updating",
"Progressing": "inactive",
2018-03-23 23:22:50 +00:00
}
// True == transitioning
// False ==
// Unknown ==
2018-03-24 06:02:31 +00:00
var progressMap = map[string]string{}
2018-01-12 10:01:35 +00:00
func concat(str, next string) string {
if str == "" {
return next
}
if next == "" {
return str
}
2018-07-25 08:43:08 +00:00
if strings.EqualFold(str, next) {
return str
}
2018-03-31 10:15:08 +00:00
return str + "; " + next
2017-11-15 23:59:47 +00:00
}
func Set(data map[string]interface{}) {
genericStatus(data)
2018-06-05 04:44:54 +00:00
loadBalancerStatus(data)
}
2018-06-05 04:44:54 +00:00
func loadBalancerStatus(data map[string]interface{}) {
if data["state"] == "active" && data["kind"] == "Service" && values.GetValueN(data, "spec", "serviceKind") == "LoadBalancer" {
addresses, ok := values.GetSlice(data, "status", "loadBalancer", "ingress")
if !ok || len(addresses) == 0 {
data["state"] = "pending"
data["transitioning"] = "yes"
2018-06-19 19:50:22 +00:00
data["transitioningMessage"] = "Load balancer is being provisioned"
}
}
}
func genericStatus(data map[string]interface{}) {
if data == nil {
return
}
2018-02-20 19:42:31 +00:00
val, conditionsOk := values.GetValue(data, "status", "conditions")
var conditions []condition
convert.ToObj(val, &conditions)
statusAnn, annOK := values.GetValue(data, "metadata", "annotations", "cattle.io/status")
if annOK {
status := &status{}
s, ok := statusAnn.(string)
if ok {
err := json.Unmarshal([]byte(s), status)
if err != nil {
logrus.Warnf("Unable to unmarshal cattle status %v. Error: %v", s, err)
}
}
if len(status.Conditions) > 0 {
conditions = append(conditions, status.Conditions...)
}
}
2017-11-15 23:59:47 +00:00
state := ""
error := false
transitioning := false
message := ""
2018-01-12 10:01:35 +00:00
for _, c := range conditions {
2018-06-05 04:44:54 +00:00
if (errorMapping[c.Type] && c.Status == "False") || c.Reason == "Error" {
2018-01-12 10:01:35 +00:00
error = true
message = c.Message
break
2017-11-15 23:59:47 +00:00
}
2018-01-12 10:01:35 +00:00
}
2017-11-15 23:59:47 +00:00
2018-01-12 10:01:35 +00:00
if !error {
for _, c := range conditions {
if reverseErrorMap[c.Type] && c.Status == "True" {
error = true
message = concat(message, c.Message)
2017-12-27 16:48:28 +00:00
}
2017-11-15 23:59:47 +00:00
}
2018-01-12 10:01:35 +00:00
}
2017-11-15 23:59:47 +00:00
2018-01-12 10:01:35 +00:00
for _, c := range conditions {
newState, ok := transitioningMap[c.Type]
if !ok {
continue
2017-11-15 23:59:47 +00:00
}
2018-01-12 10:01:35 +00:00
if c.Status == "False" {
2017-11-15 23:59:47 +00:00
error = true
2018-01-12 10:01:35 +00:00
state = newState
message = concat(message, c.Message)
} else if c.Status == "Unknown" && state == "" {
transitioning = true
state = newState
message = concat(message, c.Message)
}
}
for _, c := range conditions {
if state != "" {
break
}
newState, ok := doneMap[c.Type]
if !ok {
continue
}
if c.Status == "False" {
transitioning = true
state = newState
message = concat(message, c.Message)
2018-02-20 19:42:31 +00:00
} else if c.Status == "Unknown" {
error = true
state = newState
message = concat(message, c.Message)
2017-11-15 23:59:47 +00:00
}
}
2018-03-23 23:22:50 +00:00
for _, c := range conditions {
if state != "" {
break
}
newState, ok := progressMap[c.Type]
if !ok {
continue
}
if c.Status == "True" {
transitioning = true
state = newState
message = concat(message, c.Message)
}
}
2017-11-15 23:59:47 +00:00
if state == "" {
val, ok := values.GetValue(data, "spec", "active")
if ok {
if convert.ToBool(val) {
state = "active"
} else {
state = "inactive"
}
}
}
2018-04-26 23:56:50 +00:00
phase, ok := values.GetValueN(data, "status", "phase").(string)
if phase != "" && ok {
if phase == "Succeeded" {
state = "succeeded"
transitioning = false
2018-04-26 23:56:50 +00:00
} else if state == "" {
state = phase
}
}
2018-01-30 15:52:55 +00:00
apiVersion, _ := values.GetValueN(data, "apiVersion").(string)
2018-02-01 22:15:48 +00:00
if state == "" && conditionsOk && len(conditions) == 0 && strings.Contains(apiVersion, "cattle.io") {
if val, ok := values.GetValue(data, "metadata", "created"); ok {
if i, err := convert.ToTimestamp(val); err == nil {
2018-01-12 10:01:35 +00:00
if time.Unix(i/1000, 0).Add(5 * time.Second).After(time.Now()) {
state = "initializing"
transitioning = true
}
2017-12-14 20:49:44 +00:00
}
}
}
2017-12-14 20:49:44 +00:00
if state == "" {
state = "active"
2017-11-15 23:59:47 +00:00
}
if error {
data["transitioning"] = "error"
} else if transitioning {
data["transitioning"] = "yes"
} else {
data["transitioning"] = "no"
}
2018-01-17 01:06:45 +00:00
data["state"] = strings.ToLower(state)
2017-11-15 23:59:47 +00:00
data["transitioningMessage"] = message
2018-03-23 23:22:50 +00:00
2018-04-26 23:56:50 +00:00
val, ok = values.GetValue(data, "metadata", "removed")
2018-03-23 23:22:50 +00:00
if ok && val != "" && val != nil {
data["state"] = "removing"
data["transitioning"] = "yes"
finalizers, ok := values.GetStringSlice(data, "metadata", "finalizers")
if !ok {
finalizers, ok = values.GetStringSlice(data, "spec", "finalizers")
}
msg := message
for _, cond := range conditions {
if cond.Type == "Removed" && (cond.Status == "Unknown" || cond.Status == "False") && cond.Message != "" {
msg = cond.Message
}
}
if ok && len(finalizers) > 0 {
parts := strings.Split(finalizers[0], "controller.cattle.io/")
f := parts[len(parts)-1]
2018-06-19 19:50:22 +00:00
if f == "foregroundDeletion" {
f = "object cleanup"
}
2018-03-23 23:22:50 +00:00
if len(msg) > 0 {
msg = msg + "; waiting on " + f
} else {
msg = "waiting on " + f
}
data["transitioningMessage"] = msg
if i, err := convert.ToTimestamp(val); err == nil {
if time.Unix(i/1000, 0).Add(5 * time.Minute).Before(time.Now()) {
data["transitioning"] = "error"
}
}
}
return
}
2017-11-15 23:59:47 +00:00
}