-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathexample_test.go
More file actions
124 lines (107 loc) · 3.15 KB
/
example_test.go
File metadata and controls
124 lines (107 loc) · 3.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package framework_test
import (
"context"
"fmt"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/deckhouse/module-sdk/pkg"
objectpatch "github.com/deckhouse/module-sdk/pkg/object-patch"
"github.com/deckhouse/module-sdk/testing/framework"
)
// TestExample_DeckhouseStyle is a comprehensive end-to-end example mirroring
// how a deckhouse hook test is typically written. It is intentionally verbose
// to serve as documentation.
//
// The hook under test counts the number of running pods in the "default"
// namespace, writes the count to values, and creates a status ConfigMap.
func TestExample_DeckhouseStyle(t *testing.T) {
// 1. Hook config — same as in production code.
cfg := &pkg.HookConfig{
Metadata: pkg.HookMetadata{Name: "pod-counter"},
Kubernetes: []pkg.KubernetesConfig{
{
Name: "pods",
APIVersion: "v1",
Kind: "Pod",
NamespaceSelector: &pkg.NamespaceSelector{
NameSelector: &pkg.NameSelector{MatchNames: []string{"default"}},
},
JqFilter: `{name: .metadata.name, phase: .status.phase}`,
},
},
}
type podSnap struct {
Name string `json:"name"`
Phase string `json:"phase"`
}
// 2. Hook handler — also same as in production code.
handler := func(_ context.Context, input *pkg.HookInput) error {
pods, err := objectpatch.UnmarshalToStruct[podSnap](input.Snapshots, "pods")
if err != nil {
return err
}
var running int
for _, p := range pods {
if p.Phase == "Running" {
running++
}
}
input.Values.Set("podCounter.running", running)
input.PatchCollector.Create(&corev1.ConfigMap{
TypeMeta: metav1.TypeMeta{APIVersion: "v1", Kind: "ConfigMap"},
ObjectMeta: metav1.ObjectMeta{Name: "pod-counter-status", Namespace: "default"},
Data: map[string]string{"running": fmt.Sprintf("%d", running)},
})
return nil
}
// 3. Initialise the framework as in deckhouse: HookExecutionConfigInit.
hec := framework.HookExecutionConfigInit(t, cfg, handler, `{}`, `{}`)
// 4. Describe the cluster state with YAML.
hec.KubeStateSet(`
---
apiVersion: v1
kind: Pod
metadata:
name: app-1
namespace: default
status:
phase: Running
---
apiVersion: v1
kind: Pod
metadata:
name: app-2
namespace: default
status:
phase: Pending
---
apiVersion: v1
kind: Pod
metadata:
name: kube-proxy
namespace: kube-system
status:
phase: Running
`)
// 5. Run the hook.
hec.RunHook()
// 6. Inspect the results.
require.NoError(t, hec.HookError())
// Snapshots respect the namespace selector.
require.Len(t, hec.Snapshots().Get("pods"), 2)
// Values produced by the hook.
assert.Equal(t, int64(1), hec.ValuesGet("podCounter.running").Int())
// Patch operations recorded.
ops := hec.PatchedOperations()
require.Len(t, ops, 1)
assert.Equal(t, framework.PatchTypeCreate, ops[0].Type)
// And the create operation has actually been applied to the fake cluster:
cm := hec.KubernetesResource("ConfigMap", "default", "pod-counter-status")
require.NotNil(t, cm)
data, _ := cm.Object["data"].(map[string]any)
require.NotNil(t, data)
assert.Equal(t, "1", data["running"])
}