1
16
17 package apimachinery
18
19 import (
20 "context"
21 "fmt"
22 "strings"
23 "time"
24
25 "k8s.io/apimachinery/pkg/util/sets"
26 "k8s.io/apimachinery/pkg/util/wait"
27 clientset "k8s.io/client-go/kubernetes"
28 restclient "k8s.io/client-go/rest"
29 "k8s.io/kubernetes/test/e2e/framework"
30 admissionapi "k8s.io/pod-security-admission/api"
31
32 "github.com/onsi/ginkgo/v2"
33 )
34
35 var (
36 requiredHealthzChecks = sets.NewString(
37 "[+]ping ok",
38 "[+]log ok",
39 "[+]etcd ok",
40 "[+]poststarthook/start-apiserver-admission-initializer ok",
41 "[+]poststarthook/generic-apiserver-start-informers ok",
42 "[+]poststarthook/start-apiextensions-informers ok",
43 "[+]poststarthook/start-apiextensions-controllers ok",
44 "[+]poststarthook/crd-informer-synced ok",
45 "[+]poststarthook/bootstrap-controller ok",
46 "[+]poststarthook/start-system-namespaces-controller ok",
47 "[+]poststarthook/start-service-ip-repair-controllers ok",
48 "[+]poststarthook/scheduling/bootstrap-system-priority-classes ok",
49 "[+]poststarthook/start-cluster-authentication-info-controller ok",
50 "[+]poststarthook/start-kube-aggregator-informers ok",
51 "[+]poststarthook/apiservice-registration-controller ok",
52 "[+]poststarthook/apiservice-status-available-controller ok",
53 "[+]poststarthook/kube-apiserver-autoregistration ok",
54 "[+]autoregister-completion ok",
55 "[+]poststarthook/apiservice-openapi-controller ok",
56 )
57 requiredLivezChecks = sets.NewString(
58 "[+]ping ok",
59 "[+]log ok",
60 "[+]etcd ok",
61 "[+]poststarthook/start-apiserver-admission-initializer ok",
62 "[+]poststarthook/generic-apiserver-start-informers ok",
63 "[+]poststarthook/start-apiextensions-informers ok",
64 "[+]poststarthook/start-apiextensions-controllers ok",
65 "[+]poststarthook/crd-informer-synced ok",
66 "[+]poststarthook/bootstrap-controller ok",
67 "[+]poststarthook/start-system-namespaces-controller ok",
68 "[+]poststarthook/start-service-ip-repair-controllers ok",
69 "[+]poststarthook/scheduling/bootstrap-system-priority-classes ok",
70 "[+]poststarthook/start-cluster-authentication-info-controller ok",
71 "[+]poststarthook/start-kube-aggregator-informers ok",
72 "[+]poststarthook/apiservice-registration-controller ok",
73 "[+]poststarthook/apiservice-status-available-controller ok",
74 "[+]poststarthook/kube-apiserver-autoregistration ok",
75 "[+]autoregister-completion ok",
76 "[+]poststarthook/apiservice-openapi-controller ok",
77 )
78 requiredReadyzChecks = sets.NewString(
79 "[+]ping ok",
80 "[+]log ok",
81 "[+]etcd ok",
82 "[+]informer-sync ok",
83 "[+]poststarthook/start-apiserver-admission-initializer ok",
84 "[+]poststarthook/generic-apiserver-start-informers ok",
85 "[+]poststarthook/start-apiextensions-informers ok",
86 "[+]poststarthook/start-apiextensions-controllers ok",
87 "[+]poststarthook/crd-informer-synced ok",
88 "[+]poststarthook/bootstrap-controller ok",
89 "[+]poststarthook/start-system-namespaces-controller ok",
90 "[+]poststarthook/start-service-ip-repair-controllers ok",
91 "[+]poststarthook/scheduling/bootstrap-system-priority-classes ok",
92 "[+]poststarthook/start-cluster-authentication-info-controller ok",
93 "[+]poststarthook/start-kube-aggregator-informers ok",
94 "[+]poststarthook/apiservice-registration-controller ok",
95 "[+]poststarthook/apiservice-status-available-controller ok",
96 "[+]poststarthook/kube-apiserver-autoregistration ok",
97 "[+]autoregister-completion ok",
98 "[+]poststarthook/apiservice-openapi-controller ok",
99 )
100 )
101
102 func testPath(ctx context.Context, client clientset.Interface, path string, requiredChecks sets.String) error {
103 var result restclient.Result
104 err := wait.Poll(100*time.Millisecond, 30*time.Second, func() (bool, error) {
105 result = client.CoreV1().RESTClient().Get().RequestURI(path).Do(ctx)
106 status := 0
107 result.StatusCode(&status)
108 return status == 200, nil
109 })
110 if err != nil {
111 return err
112 }
113 body, err := result.Raw()
114 if err != nil {
115 return err
116 }
117 checks := sets.NewString(strings.Split(string(body), "\n")...)
118 if missing := requiredChecks.Difference(checks); missing.Len() > 0 {
119 return fmt.Errorf("missing required %s checks: %v in: %s", path, missing, string(body))
120 }
121 return nil
122 }
123
124 var _ = SIGDescribe("health handlers", func() {
125 f := framework.NewDefaultFramework("health")
126 f.NamespacePodSecurityLevel = admissionapi.LevelPrivileged
127
128 ginkgo.It("should contain necessary checks", func(ctx context.Context) {
129 ginkgo.By("/health")
130 err := testPath(ctx, f.ClientSet, "/healthz?verbose=1", requiredHealthzChecks)
131 framework.ExpectNoError(err)
132
133 ginkgo.By("/livez")
134 err = testPath(ctx, f.ClientSet, "/livez?verbose=1", requiredLivezChecks)
135 framework.ExpectNoError(err)
136
137 ginkgo.By("/readyz")
138 err = testPath(ctx, f.ClientSet, "/readyz?verbose=1", requiredReadyzChecks)
139 framework.ExpectNoError(err)
140 })
141 })
142
View as plain text