mirror of
https://github.com/replicatedhq/troubleshoot.git
synced 2026-08-27 00:37:20 +00:00
Deployment and statefulset
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
package analyzer
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
troubleshootv1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1"
|
||||
)
|
||||
|
||||
func commonStatus(outcomes []*troubleshootv1beta1.Outcome, readyReplicas int) (*AnalyzeResult, error) {
|
||||
result := &AnalyzeResult{}
|
||||
|
||||
// ordering from the spec is important, the first one that matches returns
|
||||
for _, outcome := range outcomes {
|
||||
if outcome.Fail != nil {
|
||||
if outcome.Fail.When == "" {
|
||||
result.IsFail = true
|
||||
result.Message = outcome.Fail.Message
|
||||
result.URI = outcome.Fail.URI
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
match, err := compareActualToWhen(outcome.Fail.When, readyReplicas)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to parse fail range")
|
||||
}
|
||||
|
||||
if match {
|
||||
result.IsFail = true
|
||||
result.Message = outcome.Fail.Message
|
||||
result.URI = outcome.Fail.URI
|
||||
|
||||
return result, nil
|
||||
}
|
||||
} else if outcome.Warn != nil {
|
||||
if outcome.Warn.When == "" {
|
||||
result.IsWarn = true
|
||||
result.Message = outcome.Warn.Message
|
||||
result.URI = outcome.Warn.URI
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
match, err := compareActualToWhen(outcome.Warn.When, readyReplicas)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to parse warn range")
|
||||
}
|
||||
|
||||
if match {
|
||||
result.IsWarn = true
|
||||
result.Message = outcome.Warn.Message
|
||||
result.URI = outcome.Warn.URI
|
||||
|
||||
return result, nil
|
||||
}
|
||||
} else if outcome.Pass != nil {
|
||||
if outcome.Pass.When == "" {
|
||||
result.IsPass = true
|
||||
result.Message = outcome.Pass.Message
|
||||
result.URI = outcome.Pass.URI
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
match, err := compareActualToWhen(outcome.Pass.When, readyReplicas)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to parse pass range")
|
||||
}
|
||||
|
||||
if match {
|
||||
result.IsPass = true
|
||||
result.Message = outcome.Pass.Message
|
||||
result.URI = outcome.Pass.URI
|
||||
|
||||
return result, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func compareActualToWhen(when string, actual int) (bool, error) {
|
||||
parts := strings.Split(strings.TrimSpace(when), " ")
|
||||
|
||||
// we can make this a lot more flexible
|
||||
if len(parts) != 2 {
|
||||
return false, errors.New("unable to parse when range")
|
||||
}
|
||||
|
||||
value, err := strconv.Atoi(parts[1])
|
||||
if err != nil {
|
||||
return false, errors.New("unable to parse when value")
|
||||
}
|
||||
|
||||
switch parts[0] {
|
||||
case "=":
|
||||
fallthrough
|
||||
case "==":
|
||||
fallthrough
|
||||
case "===":
|
||||
return actual == value, nil
|
||||
|
||||
case "<":
|
||||
return actual < value, nil
|
||||
|
||||
case ">":
|
||||
return actual > value, nil
|
||||
|
||||
case "<=":
|
||||
return actual <= value, nil
|
||||
|
||||
case ">=":
|
||||
return actual >= value, nil
|
||||
}
|
||||
|
||||
return false, errors.Errorf("unknown comparator: %q", parts[0])
|
||||
}
|
||||
@@ -4,8 +4,6 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
troubleshootv1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1"
|
||||
@@ -24,14 +22,10 @@ func deploymentStatus(analyzer *troubleshootv1beta1.DeploymentStatus, getCollect
|
||||
}
|
||||
|
||||
var status *appsv1.DeploymentStatus
|
||||
if analyzer.Name != "" {
|
||||
for _, deployment := range deployments {
|
||||
if deployment.Name == analyzer.Name {
|
||||
status = &deployment.Status
|
||||
}
|
||||
for _, deployment := range deployments {
|
||||
if deployment.Name == analyzer.Name {
|
||||
status = &deployment.Status
|
||||
}
|
||||
} else if analyzer.Selector != nil {
|
||||
|
||||
}
|
||||
|
||||
if status == nil {
|
||||
@@ -42,112 +36,5 @@ func deploymentStatus(analyzer *troubleshootv1beta1.DeploymentStatus, getCollect
|
||||
}, nil
|
||||
}
|
||||
|
||||
result := &AnalyzeResult{}
|
||||
|
||||
// ordering from the spec is important, the first one that matches returns
|
||||
for _, outcome := range analyzer.Outcomes {
|
||||
if outcome.Fail != nil {
|
||||
if outcome.Fail.When == "" {
|
||||
result.IsFail = true
|
||||
result.Message = outcome.Fail.Message
|
||||
result.URI = outcome.Fail.URI
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
match, err := compareActualToWhen(outcome.Fail.When, int(status.ReadyReplicas))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to parse fail range")
|
||||
}
|
||||
|
||||
if match {
|
||||
result.IsFail = true
|
||||
result.Message = outcome.Fail.Message
|
||||
result.URI = outcome.Fail.URI
|
||||
|
||||
return result, nil
|
||||
}
|
||||
} else if outcome.Warn != nil {
|
||||
if outcome.Warn.When == "" {
|
||||
result.IsWarn = true
|
||||
result.Message = outcome.Warn.Message
|
||||
result.URI = outcome.Warn.URI
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
match, err := compareActualToWhen(outcome.Warn.When, int(status.ReadyReplicas))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to parse warn range")
|
||||
}
|
||||
|
||||
if match {
|
||||
result.IsWarn = true
|
||||
result.Message = outcome.Warn.Message
|
||||
result.URI = outcome.Warn.URI
|
||||
|
||||
return result, nil
|
||||
}
|
||||
} else if outcome.Pass != nil {
|
||||
if outcome.Pass.When == "" {
|
||||
result.IsPass = true
|
||||
result.Message = outcome.Pass.Message
|
||||
result.URI = outcome.Pass.URI
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
match, err := compareActualToWhen(outcome.Pass.When, int(status.ReadyReplicas))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to parse pass range")
|
||||
}
|
||||
|
||||
if match {
|
||||
result.IsPass = true
|
||||
result.Message = outcome.Pass.Message
|
||||
result.URI = outcome.Pass.URI
|
||||
|
||||
return result, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func compareActualToWhen(when string, actual int) (bool, error) {
|
||||
parts := strings.Split(strings.TrimSpace(when), " ")
|
||||
|
||||
// we can make this a lot more flexible
|
||||
if len(parts) != 2 {
|
||||
return false, errors.New("unable to parse when range")
|
||||
}
|
||||
|
||||
value, err := strconv.Atoi(parts[1])
|
||||
if err != nil {
|
||||
return false, errors.New("unable to parse when value")
|
||||
}
|
||||
|
||||
switch parts[0] {
|
||||
case "=":
|
||||
fallthrough
|
||||
case "==":
|
||||
fallthrough
|
||||
case "===":
|
||||
return actual == value, nil
|
||||
|
||||
case "<":
|
||||
return actual < value, nil
|
||||
|
||||
case ">":
|
||||
return actual > value, nil
|
||||
|
||||
case "<=":
|
||||
return actual <= value, nil
|
||||
|
||||
case ">=":
|
||||
return actual >= value, nil
|
||||
}
|
||||
|
||||
return false, errors.Errorf("unknown comparator: %q", parts[0])
|
||||
return commonStatus(analyzer.Outcomes, int(status.ReadyReplicas))
|
||||
}
|
||||
|
||||
@@ -1,11 +1,40 @@
|
||||
package analyzer
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"path"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
troubleshootv1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
)
|
||||
|
||||
func statefulsetStatus(analyzer *troubleshootv1beta1.StatefulsetStatus, getCollectedFileContents func(string) ([]byte, error)) (*AnalyzeResult, error) {
|
||||
collected, err := getCollectedFileContents(path.Join("cluster-resources", "statefulsets", fmt.Sprintf("%s.json", analyzer.Namespace)))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to read collected deployments from namespace")
|
||||
}
|
||||
|
||||
return nil, errors.New("not implemented")
|
||||
var statefulsets []appsv1.StatefulSet
|
||||
if err := json.Unmarshal(collected, &statefulsets); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to unmarshal statefulset list")
|
||||
}
|
||||
|
||||
var status *appsv1.StatefulSetStatus
|
||||
for _, statefulset := range statefulsets {
|
||||
if statefulset.Name == analyzer.Name {
|
||||
status = &statefulset.Status
|
||||
}
|
||||
}
|
||||
|
||||
if status == nil {
|
||||
// there's not an error, but maybe the requested statefulset is not even deployed
|
||||
return &AnalyzeResult{
|
||||
IsFail: true,
|
||||
Message: "not found",
|
||||
}, nil
|
||||
}
|
||||
|
||||
return commonStatus(analyzer.Outcomes, int(status.ReadyReplicas))
|
||||
}
|
||||
|
||||
@@ -54,16 +54,14 @@ type DeploymentStatus struct {
|
||||
AnalyzeMeta `json:",inline" yaml:",inline"`
|
||||
Outcomes []*Outcome `json:"outcomes" yaml:"outcomes"`
|
||||
Namespace string `json:"namespace" yaml:"namespace"`
|
||||
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||
Selector []string `json:"selector,omitempty" yaml:"selector,omitempty"`
|
||||
Name string `json:"name" yaml:"name"`
|
||||
}
|
||||
|
||||
type StatefulsetStatus struct {
|
||||
AnalyzeMeta `json:",inline" yaml:",inline"`
|
||||
Outcomes []*Outcome `json:"outcomes" yaml:"outcomes"`
|
||||
Namespace string `json:"namespace" yaml:"namespace"`
|
||||
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||
Selector []string `json:"selector,omitempty" yaml:"selector,omitempty"`
|
||||
Name string `json:"name" yaml:"name"`
|
||||
}
|
||||
|
||||
type AnalyzeMeta struct {
|
||||
|
||||
@@ -756,11 +756,6 @@ func (in *DeploymentStatus) DeepCopyInto(out *DeploymentStatus) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if in.Selector != nil {
|
||||
in, out := &in.Selector, &out.Selector
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeploymentStatus.
|
||||
@@ -1364,11 +1359,6 @@ func (in *StatefulsetStatus) DeepCopyInto(out *StatefulsetStatus) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if in.Selector != nil {
|
||||
in, out := &in.Selector, &out.Selector
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StatefulsetStatus.
|
||||
|
||||
Reference in New Issue
Block a user