Skip to content
This repository has been archived by the owner on Mar 25, 2024. It is now read-only.

Commit

Permalink
Merge pull request #1092 from ibuildthecloud/kubeconfig
Browse files Browse the repository at this point in the history
Move status logic to wrangler
  • Loading branch information
ibuildthecloud committed Feb 14, 2020
2 parents 1fd17e4 + 308d0bc commit 540555f
Show file tree
Hide file tree
Showing 11 changed files with 777 additions and 303 deletions.
1 change: 1 addition & 0 deletions go.mod
Expand Up @@ -13,6 +13,7 @@ require (
github.com/knative/pkg v0.0.0-20190817231834-12ee58e32cc8
github.com/pkg/errors v0.8.1
github.com/rancher/norman v0.0.0-20200211155126-fc45a55d4dfd
github.com/rancher/wrangler v0.4.2-0.20200214231136-099089b8a398
github.com/sirupsen/logrus v1.4.2
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c // indirect
k8s.io/api v0.17.2
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Expand Up @@ -472,6 +472,8 @@ github.com/rancher/pkg v0.0.0-20190514055449-b30ab9de040e h1:j6+HqCET/NLPBtew2m5
github.com/rancher/pkg v0.0.0-20190514055449-b30ab9de040e/go.mod h1:XbYHTPaXuw8ZY9bylhYKQh/nJxDaTKk3YhAxPl4Qy/k=
github.com/rancher/wrangler v0.4.1 h1:kQLE6syPbX4ciwU4OF+EHIPT9zj6r6pyN83u9Gsv5eg=
github.com/rancher/wrangler v0.4.1/go.mod h1:1cR91WLhZgkZ+U4fV9nVuXqKurWbgXcIReU4wnQvTN8=
github.com/rancher/wrangler v0.4.2-0.20200214231136-099089b8a398 h1:1C/Fp1aSEL4Pl4hzlQsdaqzcCB9qMgalbVkvzzPIrPk=
github.com/rancher/wrangler v0.4.2-0.20200214231136-099089b8a398/go.mod h1:1cR91WLhZgkZ+U4fV9nVuXqKurWbgXcIReU4wnQvTN8=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M=
github.com/rlmcpherson/s3gof3r v0.5.0/go.mod h1:s7vv7SMDPInkitQMuZzH615G7yWHdrU2r/Go7Bo71Rs=
Expand Down
310 changes: 8 additions & 302 deletions status/status.go
Expand Up @@ -3,315 +3,21 @@ package status
import (
"strings"

"time"

"encoding/json"

"github.com/rancher/norman/types/convert"
"github.com/rancher/norman/types/values"
"github.com/sirupsen/logrus"
"github.com/rancher/wrangler/pkg/summary"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
)

type status struct {
Conditions []condition `json:"conditions"`
}

type condition struct {
Reason string
Type string
Status string
Message string
}

// True ==
// False == error
// Unknown == transitioning
var transitioningMap = map[string]string{
"Active": "activating",
"AddonDeploy": "provisioning",
"AgentDeployed": "provisioning",
"BackingNamespaceCreated": "configuring",
"Built": "building",
"CertsGenerated": "provisioning",
"ConfigOK": "configuring",
"Created": "creating",
"CreatorMadeOwner": "configuring",
"DefaultNamespaceAssigned": "configuring",
"DefaultNetworkPolicyCreated": "configuring",
"DefaultProjectCreated": "configuring",
"DockerProvisioned": "provisioning",
"Deployed": "deploying",
"Drained": "draining",
"Downloaded": "downloading",
"etcd": "provisioning",
"Inactive": "deactivating",
"Initialized": "initializing",
"Installed": "installing",
"NodesCreated": "provisioning",
"Pending": "pending",
"PodScheduled": "scheduling",
"Provisioned": "provisioning",
"Refreshed": "refreshed",
"Registered": "registering",
"Removed": "removing",
"Saved": "saving",
"Updated": "updating",
"Updating": "updating",
"Waiting": "waiting",
"InitialRolesPopulated": "activating",
"ScalingActive": "pending",
"AbleToScale": "pending",
"RunCompleted": "running",
}

// 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{
"Failed": true,
"Progressing": true,
}

// True ==
// False == transitioning
// Unknown == error
var doneMap = map[string]string{
"Completed": "activating",
"Ready": "unavailable",
"Available": "updating",
"Progressing": "inactive",
}

// True == transitioning
// False ==
// Unknown ==
var progressMap = map[string]string{}

func concat(str, next string) string {
if str == "" {
return next
}
if next == "" {
return str
}
if strings.EqualFold(str, next) {
return str
}
return str + "; " + next
}

func Set(data map[string]interface{}) {
genericStatus(data)
loadBalancerStatus(data)
}

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"
data["transitioningMessage"] = "Load balancer is being provisioned"
}
}
}

func genericStatus(data map[string]interface{}) {
if data == nil {
return
}

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...)
}
}

state := ""
error := false
transitioning := false
message := ""

for _, c := range conditions {
if (errorMapping[c.Type] && c.Status == "False") || c.Reason == "Error" {
error = true
message = c.Message
break
}
}

if !error {
for _, c := range conditions {
if reverseErrorMap[c.Type] && c.Status == "True" {
error = true
message = concat(message, c.Message)
}
}
}

for _, c := range conditions {
newState, ok := transitioningMap[c.Type]
if !ok {
continue
}

if c.Status == "False" {
error = true
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)
} else if c.Status == "Unknown" {
error = true
state = newState
message = concat(message, c.Message)
}
}

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

if state == "" {
val, ok := values.GetValue(data, "spec", "active")
if ok {
if convert.ToBool(val) {
state = "active"
} else {
state = "inactive"
}
}
}

phase, ok := values.GetValueN(data, "status", "phase").(string)
if phase != "" && ok {
if phase == "Succeeded" {
state = "succeeded"
transitioning = false
} else if state == "" {
state = phase
}
}

apiVersion, _ := values.GetValueN(data, "apiVersion").(string)
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 {
if time.Unix(i/1000, 0).Add(5 * time.Second).After(time.Now()) {
state = "initializing"
transitioning = true
}
}
}
}

if state == "" {
state = "active"
}

if error {
summary := summary.Summarize(&unstructured.Unstructured{Object: data})
data["state"] = summary.State
data["transitioning"] = "no"
if summary.Error {
data["transitioning"] = "error"
} else if transitioning {
data["transitioning"] = "yes"
} else {
data["transitioning"] = "no"
}

data["state"] = strings.ToLower(state)
data["transitioningMessage"] = message

val, ok = values.GetValue(data, "metadata", "removed")
if ok && val != "" && val != nil {
data["state"] = "removing"
} else if summary.Transitioning {
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]

if f == "foregroundDeletion" {
f = "object cleanup"
}

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
}
data["transitioningMessage"] = strings.Join(summary.Message, "; ")
}

0 comments on commit 540555f

Please sign in to comment.