-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #64 from Zenika/master
Release v1.7.0
- Loading branch information
Showing
38 changed files
with
3,864 additions
and
2,383 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,11 @@ | ||
<component name="ProjectRunConfigurationManager"> | ||
<configuration default="false" name="Run Back" type="GoApplicationRunConfiguration" factoryName="Go Application"> | ||
<configuration default="false" name="Run back" type="GoApplicationRunConfiguration" factoryName="Go Application"> | ||
<module name="karto" /> | ||
<working_directory value="$PROJECT_DIR$/back" /> | ||
<go_parameters value="-i" /> | ||
<kind value="PACKAGE" /> | ||
<filePath value="$PROJECT_DIR$/back" /> | ||
<package value="karto" /> | ||
<directory value="$PROJECT_DIR$" /> | ||
<filePath value="$PROJECT_DIR$/back/main.go" /> | ||
<method v="2" /> | ||
</configuration> | ||
</component> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package health | ||
|
||
import ( | ||
corev1 "k8s.io/api/core/v1" | ||
"karto/analyzer/health/podhealth" | ||
"karto/types" | ||
) | ||
|
||
type ClusterState struct { | ||
Pods []*corev1.Pod | ||
} | ||
|
||
type AnalysisResult struct { | ||
Pods []*types.PodHealth | ||
} | ||
|
||
type Analyzer interface { | ||
Analyze(clusterState ClusterState) AnalysisResult | ||
} | ||
|
||
type analyzerImpl struct { | ||
podHealthAnalyzer podhealth.Analyzer | ||
} | ||
|
||
func NewAnalyzer(podHealthAnalyzer podhealth.Analyzer) Analyzer { | ||
return analyzerImpl{ | ||
podHealthAnalyzer: podHealthAnalyzer, | ||
} | ||
} | ||
|
||
func (analyzer analyzerImpl) Analyze(clusterState ClusterState) AnalysisResult { | ||
podHealths := analyzer.podHealthOfAllPods(clusterState.Pods) | ||
return AnalysisResult{ | ||
Pods: podHealths, | ||
} | ||
} | ||
|
||
func (analyzer analyzerImpl) podHealthOfAllPods(pods []*corev1.Pod) []*types.PodHealth { | ||
podHealths := make([]*types.PodHealth, 0) | ||
for _, pod := range pods { | ||
podHealth := analyzer.podHealthAnalyzer.Analyze(pod) | ||
podHealths = append(podHealths, podHealth) | ||
} | ||
return podHealths | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
package health | ||
|
||
import ( | ||
"github.com/google/go-cmp/cmp" | ||
corev1 "k8s.io/api/core/v1" | ||
"karto/analyzer/health/podhealth" | ||
"karto/testutils" | ||
"karto/types" | ||
"reflect" | ||
"testing" | ||
) | ||
|
||
func TestAnalyze(t *testing.T) { | ||
type args struct { | ||
clusterState ClusterState | ||
} | ||
type mocks struct { | ||
podHealth []mockPodHealthAnalyzerCall | ||
} | ||
k8sPod1 := testutils.NewPodBuilder().WithContainerStatus(true, false, 0).Build() | ||
k8sPod2 := testutils.NewPodBuilder().WithContainerStatus(true, false, 0). | ||
WithContainerStatus(false, false, 0).Build() | ||
podRef1 := types.PodRef{Name: k8sPod1.Name, Namespace: k8sPod1.Namespace} | ||
podRef2 := types.PodRef{Name: k8sPod2.Name, Namespace: k8sPod2.Namespace} | ||
podHealth1 := &types.PodHealth{Pod: podRef1, Containers: 1, ContainersRunning: 1, ContainersReady: 0, | ||
ContainersWithoutRestart: 1} | ||
podHealth2 := &types.PodHealth{Pod: podRef2, Containers: 2, ContainersRunning: 1, ContainersReady: 0, | ||
ContainersWithoutRestart: 2} | ||
tests := []struct { | ||
name string | ||
mocks mocks | ||
args args | ||
expectedAnalysisResult AnalysisResult | ||
}{ | ||
{ | ||
name: "delegates to sub-analyzers and merges results", | ||
mocks: mocks{ | ||
podHealth: []mockPodHealthAnalyzerCall{ | ||
{ | ||
args: mockPodHealthAnalyzerCallArgs{ | ||
pod: k8sPod1, | ||
}, | ||
returnValue: podHealth1, | ||
}, | ||
{ | ||
args: mockPodHealthAnalyzerCallArgs{ | ||
pod: k8sPod2, | ||
}, | ||
returnValue: podHealth2, | ||
}, | ||
}, | ||
}, | ||
args: args{ | ||
clusterState: ClusterState{ | ||
Pods: []*corev1.Pod{k8sPod1, k8sPod2}, | ||
}, | ||
}, | ||
expectedAnalysisResult: AnalysisResult{ | ||
Pods: []*types.PodHealth{podHealth1, podHealth2}, | ||
}, | ||
}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
podHealthAnalyzer := createMockPodHealthAnalyzer(t, tt.mocks.podHealth) | ||
analyzer := NewAnalyzer(podHealthAnalyzer) | ||
analysisResult := analyzer.Analyze(tt.args.clusterState) | ||
if diff := cmp.Diff(tt.expectedAnalysisResult, analysisResult); diff != "" { | ||
t.Errorf("Analyze() result mismatch (-want +got):\n%s", diff) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
type mockPodHealthAnalyzerCallArgs struct { | ||
pod *corev1.Pod | ||
} | ||
|
||
type mockPodHealthAnalyzerCall struct { | ||
args mockPodHealthAnalyzerCallArgs | ||
returnValue *types.PodHealth | ||
} | ||
|
||
type mockPodHealthAnalyzer struct { | ||
t *testing.T | ||
calls []mockPodHealthAnalyzerCall | ||
} | ||
|
||
func (mock mockPodHealthAnalyzer) Analyze(pod *corev1.Pod) *types.PodHealth { | ||
for _, call := range mock.calls { | ||
if reflect.DeepEqual(call.args.pod, pod) { | ||
return call.returnValue | ||
} | ||
} | ||
mock.t.Fatalf("mockPodHealthAnalyzer was called with unexpected arguments:\n\tpod: %s\n", pod) | ||
return nil | ||
} | ||
|
||
func createMockPodHealthAnalyzer(t *testing.T, calls []mockPodHealthAnalyzerCall) podhealth.Analyzer { | ||
return mockPodHealthAnalyzer{ | ||
t: t, | ||
calls: calls, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package podhealth | ||
|
||
import ( | ||
corev1 "k8s.io/api/core/v1" | ||
"karto/types" | ||
) | ||
|
||
type Analyzer interface { | ||
Analyze(pod *corev1.Pod) *types.PodHealth | ||
} | ||
|
||
type analyzerImpl struct{} | ||
|
||
func NewAnalyzer() Analyzer { | ||
return analyzerImpl{} | ||
} | ||
|
||
func (analyzer analyzerImpl) Analyze(pod *corev1.Pod) *types.PodHealth { | ||
var containers, running, ready, withoutRestart int32 | ||
for _, containerStatus := range pod.Status.ContainerStatuses { | ||
containers++ | ||
if containerStatus.State.Running != nil { | ||
running++ | ||
} | ||
if containerStatus.Ready { | ||
ready++ | ||
} | ||
if containerStatus.RestartCount == 0 { | ||
withoutRestart++ | ||
} | ||
} | ||
return &types.PodHealth{ | ||
Pod: analyzer.toPodRef(pod), | ||
Containers: containers, | ||
ContainersRunning: running, | ||
ContainersReady: ready, | ||
ContainersWithoutRestart: withoutRestart, | ||
} | ||
} | ||
|
||
func (analyzer analyzerImpl) toPodRef(pod *corev1.Pod) types.PodRef { | ||
return types.PodRef{ | ||
Name: pod.Name, | ||
Namespace: pod.Namespace, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
package podhealth | ||
|
||
import ( | ||
"github.com/google/go-cmp/cmp" | ||
corev1 "k8s.io/api/core/v1" | ||
"karto/testutils" | ||
"karto/types" | ||
"testing" | ||
) | ||
|
||
func TestAnalyze(t *testing.T) { | ||
type args struct { | ||
pod *corev1.Pod | ||
} | ||
tests := []struct { | ||
name string | ||
args args | ||
expectedPodHealth *types.PodHealth | ||
}{ | ||
{ | ||
name: "pod health is the aggregation of its container statuses", | ||
args: args{ | ||
pod: testutils.NewPodBuilder().WithName("pod1"). | ||
WithContainerStatus(true, true, 0). | ||
WithContainerStatus(true, true, 0). | ||
Build(), | ||
}, | ||
expectedPodHealth: &types.PodHealth{ | ||
Pod: types.PodRef{Name: "pod1", Namespace: "default"}, | ||
Containers: 2, | ||
ContainersRunning: 2, | ||
ContainersReady: 2, | ||
ContainersWithoutRestart: 2, | ||
}, | ||
}, | ||
{ | ||
name: "only containers with a Running state are counted as running", | ||
args: args{ | ||
pod: testutils.NewPodBuilder().WithName("pod1"). | ||
WithContainerStatus(true, true, 0). | ||
WithContainerStatus(false, true, 0). | ||
Build(), | ||
}, | ||
expectedPodHealth: &types.PodHealth{ | ||
Pod: types.PodRef{Name: "pod1", Namespace: "default"}, | ||
Containers: 2, | ||
ContainersRunning: 1, | ||
ContainersReady: 2, | ||
ContainersWithoutRestart: 2, | ||
}, | ||
}, | ||
{ | ||
name: "only containers marked as ready are counted as ready", | ||
args: args{ | ||
pod: testutils.NewPodBuilder().WithName("pod1"). | ||
WithContainerStatus(true, false, 0). | ||
WithContainerStatus(true, true, 0). | ||
Build(), | ||
}, | ||
expectedPodHealth: &types.PodHealth{ | ||
Pod: types.PodRef{Name: "pod1", Namespace: "default"}, | ||
Containers: 2, | ||
ContainersRunning: 2, | ||
ContainersReady: 1, | ||
ContainersWithoutRestart: 2, | ||
}, | ||
}, | ||
{ | ||
name: "only containers with zero restarts are counted as without restarts", | ||
args: args{ | ||
pod: testutils.NewPodBuilder().WithName("pod1"). | ||
WithContainerStatus(true, true, 0). | ||
WithContainerStatus(true, true, 2). | ||
Build(), | ||
}, | ||
expectedPodHealth: &types.PodHealth{ | ||
Pod: types.PodRef{Name: "pod1", Namespace: "default"}, | ||
Containers: 2, | ||
ContainersRunning: 2, | ||
ContainersReady: 2, | ||
ContainersWithoutRestart: 1, | ||
}, | ||
}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
analyzer := NewAnalyzer() | ||
podHealth := analyzer.Analyze(tt.args.pod) | ||
if diff := cmp.Diff(tt.expectedPodHealth, podHealth); diff != "" { | ||
t.Errorf("Analyze() result mismatch (-want +got):\n%s", diff) | ||
} | ||
}) | ||
} | ||
} |
Oops, something went wrong.