Merge pull request #367 from areed/longhorn-replica-analyzer

Analyze longhorn replica
This commit is contained in:
Andrew Reed
2021-05-27 15:07:54 -05:00
committed by GitHub
3 changed files with 153 additions and 3 deletions

View File

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

View File

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

View File

@@ -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,