mirror of
https://github.com/replicatedhq/troubleshoot.git
synced 2026-04-15 07:16:34 +00:00
Merge pull request #367 from areed/longhorn-replica-analyzer
Analyze longhorn replica
This commit is contained in:
@@ -1,14 +1,18 @@
|
||||
package analyzer
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
longhornv1beta1 "github.com/longhorn/longhorn-manager/k8s/pkg/apis/longhorn/v1beta1"
|
||||
longhorntypes "github.com/longhorn/longhorn-manager/types"
|
||||
"github.com/pkg/errors"
|
||||
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
|
||||
"github.com/replicatedhq/troubleshoot/pkg/collect"
|
||||
"github.com/replicatedhq/troubleshoot/pkg/redact"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
@@ -17,14 +21,17 @@ func longhorn(analyzer *troubleshootv1beta2.LonghornAnalyze, getCollectedFileCon
|
||||
if analyzer.Namespace != "" {
|
||||
ns = analyzer.Namespace
|
||||
}
|
||||
|
||||
// get nodes.longhorn.io
|
||||
nodesDir := collect.GetLonghornNodesDirectory(ns)
|
||||
glob := filepath.Join(nodesDir, "*")
|
||||
nodesYaml, err := findFiles(glob)
|
||||
nodesGlob := filepath.Join(nodesDir, "*")
|
||||
nodesYaml, err := findFiles(nodesGlob)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to find longhorn nodes files under %s", nodesDir)
|
||||
}
|
||||
nodes := []*longhornv1beta1.Node{}
|
||||
for key, nodeYaml := range nodesYaml {
|
||||
nodeYaml = stripRedactedLines(nodeYaml)
|
||||
node := &longhornv1beta1.Node{}
|
||||
err := yaml.Unmarshal(nodeYaml, node)
|
||||
if err != nil {
|
||||
@@ -33,12 +40,34 @@ func longhorn(analyzer *troubleshootv1beta2.LonghornAnalyze, getCollectedFileCon
|
||||
nodes = append(nodes, node)
|
||||
}
|
||||
|
||||
// get replicas.longhorn.io
|
||||
replicasDir := collect.GetLonghornReplicasDirectory(ns)
|
||||
replicasGlob := filepath.Join(replicasDir, "*")
|
||||
replicasYaml, err := findFiles(replicasGlob)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to find longhorn replicas files under %s", replicasDir)
|
||||
}
|
||||
replicas := []*longhornv1beta1.Replica{}
|
||||
for key, replicaYaml := range replicasYaml {
|
||||
replicaYaml = stripRedactedLines(replicaYaml)
|
||||
replica := &longhornv1beta1.Replica{}
|
||||
err := yaml.Unmarshal(replicaYaml, replica)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to unmarshal replica yaml from %s", key)
|
||||
}
|
||||
replicas = append(replicas, replica)
|
||||
}
|
||||
|
||||
results := []*AnalyzeResult{}
|
||||
|
||||
for _, node := range nodes {
|
||||
results = append(results, analyzeLonghornNodeSchedulable(node))
|
||||
}
|
||||
|
||||
for _, replica := range replicas {
|
||||
results = append(results, analyzeLonghornReplica(replica))
|
||||
}
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
@@ -67,3 +96,46 @@ func analyzeLonghornNodeSchedulable(node *longhornv1beta1.Node) *AnalyzeResult {
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func analyzeLonghornReplica(replica *longhornv1beta1.Replica) *AnalyzeResult {
|
||||
result := &AnalyzeResult{
|
||||
Title: fmt.Sprintf("Longhorn Replica: %s", replica.Name),
|
||||
}
|
||||
|
||||
if replica.Spec.FailedAt != "" {
|
||||
result.IsWarn = true
|
||||
result.Message = fmt.Sprintf("Longhorn replica %s failed at %s", replica.Name, replica.Spec.FailedAt)
|
||||
return result
|
||||
}
|
||||
|
||||
desired := replica.Spec.InstanceSpec.DesireState
|
||||
actual := replica.Status.InstanceStatus.CurrentState
|
||||
|
||||
if desired != actual {
|
||||
result.IsWarn = true
|
||||
result.Message = fmt.Sprintf("Longhorn replica %s current status %q, should be %q", replica.Name, actual, desired)
|
||||
return result
|
||||
}
|
||||
|
||||
result.IsPass = true
|
||||
result.Message = fmt.Sprintf("Replica is %s", actual)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func stripRedactedLines(yaml []byte) []byte {
|
||||
buf := bytes.NewBuffer(yaml)
|
||||
scanner := bufio.NewScanner(buf)
|
||||
|
||||
out := []byte{}
|
||||
|
||||
for scanner.Scan() {
|
||||
if strings.Contains(scanner.Text(), redact.MASK_TEXT) {
|
||||
continue
|
||||
}
|
||||
out = append(out, scanner.Bytes()...)
|
||||
out = append(out, '\n')
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
@@ -64,3 +64,81 @@ func TestAnalyzeLonghornNodeSchedulable(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAnalyzeLonghornReplica(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
replica *longhornv1beta1.Replica
|
||||
expect *AnalyzeResult
|
||||
}{
|
||||
{
|
||||
name: "running",
|
||||
replica: &longhornv1beta1.Replica{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "pvc-uuid-1",
|
||||
},
|
||||
Spec: longhorntypes.ReplicaSpec{
|
||||
InstanceSpec: longhorntypes.InstanceSpec{
|
||||
DesireState: longhorntypes.InstanceStateRunning,
|
||||
},
|
||||
},
|
||||
Status: longhorntypes.ReplicaStatus{
|
||||
InstanceStatus: longhorntypes.InstanceStatus{
|
||||
CurrentState: longhorntypes.InstanceStateRunning,
|
||||
},
|
||||
},
|
||||
},
|
||||
expect: &AnalyzeResult{
|
||||
Title: "Longhorn Replica: pvc-uuid-1",
|
||||
IsPass: true,
|
||||
Message: "Replica is running",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "stopped",
|
||||
replica: &longhornv1beta1.Replica{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "pvc-uuid-1",
|
||||
},
|
||||
Spec: longhorntypes.ReplicaSpec{
|
||||
InstanceSpec: longhorntypes.InstanceSpec{
|
||||
DesireState: longhorntypes.InstanceStateRunning,
|
||||
},
|
||||
},
|
||||
Status: longhorntypes.ReplicaStatus{
|
||||
InstanceStatus: longhorntypes.InstanceStatus{
|
||||
CurrentState: longhorntypes.InstanceStateStopped,
|
||||
},
|
||||
},
|
||||
},
|
||||
expect: &AnalyzeResult{
|
||||
Title: "Longhorn Replica: pvc-uuid-1",
|
||||
IsWarn: true,
|
||||
Message: `Longhorn replica pvc-uuid-1 current status "stopped", should be "running"`,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "failed",
|
||||
replica: &longhornv1beta1.Replica{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "pvc-uuid-1",
|
||||
},
|
||||
Spec: longhorntypes.ReplicaSpec{
|
||||
FailedAt: "20210527T19:43:35",
|
||||
},
|
||||
},
|
||||
expect: &AnalyzeResult{
|
||||
Title: "Longhorn Replica: pvc-uuid-1",
|
||||
IsWarn: true,
|
||||
Message: "Longhorn replica pvc-uuid-1 failed at 20210527T19:43:35",
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
got := analyzeLonghornReplica(test.replica)
|
||||
|
||||
assert.Equal(t, test.expect, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ import (
|
||||
|
||||
var scheme = runtime.NewScheme()
|
||||
var codecs = serializer.NewCodecFactory(scheme)
|
||||
var parameterCodec = runtime.NewParameterCodec(scheme)
|
||||
|
||||
var localSchemeBuilder = runtime.SchemeBuilder{
|
||||
troubleshootv1beta1.AddToScheme,
|
||||
troubleshootv1beta2.AddToScheme,
|
||||
|
||||
Reference in New Issue
Block a user