1
// Code generated by go run tools/import_commands.go --talos-version v1.7.1 health
4
// This Source Code Form is subject to the terms of the Mozilla Public
5
// License, v. 2.0. If a copy of the MPL was not distributed with this
6
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
17
"github.com/cosi-project/runtime/pkg/safe"
18
"github.com/spf13/cobra"
19
"google.golang.org/grpc/codes"
21
"github.com/siderolabs/talos/cmd/talosctl/pkg/talos/helpers"
22
"github.com/siderolabs/talos/pkg/cluster"
23
"github.com/siderolabs/talos/pkg/cluster/check"
24
"github.com/siderolabs/talos/pkg/cluster/sonobuoy"
25
clusterapi "github.com/siderolabs/talos/pkg/machinery/api/cluster"
26
"github.com/siderolabs/talos/pkg/machinery/client"
27
"github.com/siderolabs/talos/pkg/machinery/config/machine"
28
clusterres "github.com/siderolabs/talos/pkg/machinery/resources/cluster"
31
type clusterNodes struct {
33
ControlPlaneNodes []string
36
nodes []cluster.NodeInfo
37
nodesByType map[machine.Type][]cluster.NodeInfo
40
func (cl *clusterNodes) InitNodeInfos() error {
41
var initNodes []string
43
if cl.InitNode != "" {
44
initNodes = []string{cl.InitNode}
47
initNodeInfos, err := cluster.IPsToNodeInfos(initNodes)
52
controlPlaneNodeInfos, err := cluster.IPsToNodeInfos(cl.ControlPlaneNodes)
57
workerNodeInfos, err := cluster.IPsToNodeInfos(cl.WorkerNodes)
62
nodesByType := make(map[machine.Type][]cluster.NodeInfo)
63
nodesByType[machine.TypeInit] = initNodeInfos
64
nodesByType[machine.TypeControlPlane] = controlPlaneNodeInfos
65
nodesByType[machine.TypeWorker] = workerNodeInfos
66
cl.nodesByType = nodesByType
68
nodes := make([]cluster.NodeInfo, 0, len(initNodeInfos)+len(controlPlaneNodeInfos)+len(workerNodeInfos))
69
nodes = append(nodes, initNodeInfos...)
70
nodes = append(nodes, controlPlaneNodeInfos...)
71
nodes = append(nodes, workerNodeInfos...)
77
func (cl *clusterNodes) Nodes() []cluster.NodeInfo {
81
func (cl *clusterNodes) NodesByType(t machine.Type) []cluster.NodeInfo {
82
return cl.nodesByType[t]
85
var healthCmdFlags struct {
86
clusterState clusterNodes
87
clusterWaitTimeout time.Duration
94
// healthCmd represents the health command.
95
var healthCmd = &cobra.Command{
97
Short: "Check cluster health",
100
RunE: func(cmd *cobra.Command, args []string) error {
101
err := healthCmdFlags.clusterState.InitNodeInfos()
106
if err := runHealth(); err != nil {
110
if healthCmdFlags.runE2E {
118
func runHealth() error {
119
if healthCmdFlags.runOnServer {
120
return WithClient(healthOnServer)
123
return WithClientNoNodes(healthOnClient)
126
func healthOnClient(ctx context.Context, c *client.Client) error {
127
clientProvider := &cluster.ConfigClientProvider{
130
defer clientProvider.Close() //nolint:errcheck
132
clusterInfo, err := buildClusterInfo(healthCmdFlags.clusterState)
138
cluster.ClientProvider
142
ClientProvider: clientProvider,
143
K8sProvider: &cluster.KubernetesClient{
144
ClientProvider: clientProvider,
145
ForceEndpoint: healthCmdFlags.forceEndpoint,
150
// Run cluster readiness checks
151
checkCtx, checkCtxCancel := context.WithTimeout(ctx, healthCmdFlags.clusterWaitTimeout)
152
defer checkCtxCancel()
154
return check.Wait(checkCtx, &state, append(check.DefaultClusterChecks(), check.ExtraClusterChecks()...), check.StderrReporter())
157
func healthOnServer(ctx context.Context, c *client.Client) error {
158
if err := helpers.FailIfMultiNodes(ctx, "health"); err != nil {
162
controlPlaneNodes := healthCmdFlags.clusterState.ControlPlaneNodes
163
if healthCmdFlags.clusterState.InitNode != "" {
164
controlPlaneNodes = append(controlPlaneNodes, healthCmdFlags.clusterState.InitNode)
167
healthCheckClient, err := c.ClusterHealthCheck(ctx, healthCmdFlags.clusterWaitTimeout, &clusterapi.ClusterInfo{
168
ControlPlaneNodes: controlPlaneNodes,
169
WorkerNodes: healthCmdFlags.clusterState.WorkerNodes,
170
ForceEndpoint: healthCmdFlags.forceEndpoint,
176
if err := healthCheckClient.CloseSend(); err != nil {
181
msg, err := healthCheckClient.Recv()
183
if err == io.EOF || client.StatusCode(err) == codes.Canceled {
190
if msg.GetMetadata().GetError() != "" {
191
return fmt.Errorf("healthcheck error: %s", msg.GetMetadata().GetError())
194
fmt.Fprintln(os.Stderr, msg.GetMessage())
199
return WithClient(func(ctx context.Context, c *client.Client) error {
200
clientProvider := &cluster.ConfigClientProvider{
203
defer clientProvider.Close() //nolint:errcheck
205
state := &cluster.KubernetesClient{
206
ClientProvider: clientProvider,
207
ForceEndpoint: healthCmdFlags.forceEndpoint,
210
// Run cluster readiness checks
211
checkCtx, checkCtxCancel := context.WithTimeout(ctx, healthCmdFlags.clusterWaitTimeout)
212
defer checkCtxCancel()
214
options := sonobuoy.DefaultOptions()
215
options.UseSpinner = true
217
return sonobuoy.Run(checkCtx, state, options)
222
healthCmd.Flags().StringSliceVarP(&healthCmdFlags.configFiles,
223
"file", "f", nil, "specify config files or patches in a YAML file (can specify multiple)",
225
healthCmd.PreRunE = func(cmd *cobra.Command, args []string) error {
229
endpointsFromArgs := len(GlobalArgs.
231
for _, configFile := range healthCmdFlags.
233
if err := processModelineAndUpdateGlobals(configFile, nodesFromArgs, endpointsFromArgs,
241
addCommand(healthCmd)
242
healthCmd.Flags().StringVar(&healthCmdFlags.clusterState.InitNode, "init-node", "", "specify IPs of init node")
243
healthCmd.Flags().StringSliceVar(&healthCmdFlags.clusterState.ControlPlaneNodes, "control-plane-nodes", nil, "specify IPs of control plane nodes")
244
healthCmd.Flags().StringSliceVar(&healthCmdFlags.clusterState.WorkerNodes, "worker-nodes", nil, "specify IPs of worker nodes")
245
healthCmd.Flags().DurationVar(&healthCmdFlags.clusterWaitTimeout, "wait-timeout", 20*time.Minute, "timeout to wait for the cluster to be ready")
246
healthCmd.Flags().StringVar(&healthCmdFlags.forceEndpoint, "k8s-endpoint", "", "use endpoint instead of kubeconfig default")
247
healthCmd.Flags().BoolVar(&healthCmdFlags.runOnServer, "server", true, "run server-side check")
248
healthCmd.Flags().BoolVar(&healthCmdFlags.runE2E, "run-e2e", false, "run Kubernetes e2e test")
251
func buildClusterInfo(clusterState clusterNodes) (cluster.Info, error) {
252
// if nodes are set explicitly via command line args, use them
253
if len(clusterState.ControlPlaneNodes) > 0 || len(clusterState.WorkerNodes) > 0 {
254
return &clusterState, nil
257
// read members from the Talos API
259
var members []*clusterres.Member
261
err := WithClientNoNodes(func(ctx context.Context, c *client.Client) error {
262
items, err := safe.StateListAll[*clusterres.Member](ctx, c.COSI)
267
items.ForEach(func(item *clusterres.Member) { members = append(members, item) })
275
return check.NewDiscoveredClusterInfo(members)