talm

Форк
0
/
imported_health.go 
276 строк · 7.6 Кб
1
// Code generated by go run tools/import_commands.go --talos-version v1.7.1 health
2
// DO NOT EDIT.
3

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/.
7

8
package commands
9

10
import (
11
	"context"
12
	"fmt"
13
	"io"
14
	"os"
15
	"time"
16

17
	"github.com/cosi-project/runtime/pkg/safe"
18
	"github.com/spf13/cobra"
19
	"google.golang.org/grpc/codes"
20

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"
29
)
30

31
type clusterNodes struct {
32
	InitNode          string
33
	ControlPlaneNodes []string
34
	WorkerNodes       []string
35

36
	nodes       []cluster.NodeInfo
37
	nodesByType map[machine.Type][]cluster.NodeInfo
38
}
39

40
func (cl *clusterNodes) InitNodeInfos() error {
41
	var initNodes []string
42

43
	if cl.InitNode != "" {
44
		initNodes = []string{cl.InitNode}
45
	}
46

47
	initNodeInfos, err := cluster.IPsToNodeInfos(initNodes)
48
	if err != nil {
49
		return err
50
	}
51

52
	controlPlaneNodeInfos, err := cluster.IPsToNodeInfos(cl.ControlPlaneNodes)
53
	if err != nil {
54
		return err
55
	}
56

57
	workerNodeInfos, err := cluster.IPsToNodeInfos(cl.WorkerNodes)
58
	if err != nil {
59
		return err
60
	}
61

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
67

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...)
72
	cl.nodes = nodes
73

74
	return nil
75
}
76

77
func (cl *clusterNodes) Nodes() []cluster.NodeInfo {
78
	return cl.nodes
79
}
80

81
func (cl *clusterNodes) NodesByType(t machine.Type) []cluster.NodeInfo {
82
	return cl.nodesByType[t]
83
}
84

85
var healthCmdFlags struct {
86
	clusterState       clusterNodes
87
	clusterWaitTimeout time.Duration
88
	forceEndpoint      string
89
	runOnServer        bool
90
	runE2E             bool
91
	configFiles        []string
92
}
93

94
// healthCmd represents the health command.
95
var healthCmd = &cobra.Command{
96
	Use:   "health",
97
	Short: "Check cluster health",
98
	Long:  ``,
99
	Args:  cobra.NoArgs,
100
	RunE: func(cmd *cobra.Command, args []string) error {
101
		err := healthCmdFlags.clusterState.InitNodeInfos()
102
		if err != nil {
103
			return err
104
		}
105

106
		if err := runHealth(); err != nil {
107
			return err
108
		}
109

110
		if healthCmdFlags.runE2E {
111
			return runE2E()
112
		}
113

114
		return nil
115
	},
116
}
117

118
func runHealth() error {
119
	if healthCmdFlags.runOnServer {
120
		return WithClient(healthOnServer)
121
	}
122

123
	return WithClientNoNodes(healthOnClient)
124
}
125

126
func healthOnClient(ctx context.Context, c *client.Client) error {
127
	clientProvider := &cluster.ConfigClientProvider{
128
		DefaultClient: c,
129
	}
130
	defer clientProvider.Close() //nolint:errcheck
131

132
	clusterInfo, err := buildClusterInfo(healthCmdFlags.clusterState)
133
	if err != nil {
134
		return err
135
	}
136

137
	state := struct {
138
		cluster.ClientProvider
139
		cluster.K8sProvider
140
		cluster.Info
141
	}{
142
		ClientProvider: clientProvider,
143
		K8sProvider: &cluster.KubernetesClient{
144
			ClientProvider: clientProvider,
145
			ForceEndpoint:  healthCmdFlags.forceEndpoint,
146
		},
147
		Info: clusterInfo,
148
	}
149

150
	// Run cluster readiness checks
151
	checkCtx, checkCtxCancel := context.WithTimeout(ctx, healthCmdFlags.clusterWaitTimeout)
152
	defer checkCtxCancel()
153

154
	return check.Wait(checkCtx, &state, append(check.DefaultClusterChecks(), check.ExtraClusterChecks()...), check.StderrReporter())
155
}
156

157
func healthOnServer(ctx context.Context, c *client.Client) error {
158
	if err := helpers.FailIfMultiNodes(ctx, "health"); err != nil {
159
		return err
160
	}
161

162
	controlPlaneNodes := healthCmdFlags.clusterState.ControlPlaneNodes
163
	if healthCmdFlags.clusterState.InitNode != "" {
164
		controlPlaneNodes = append(controlPlaneNodes, healthCmdFlags.clusterState.InitNode)
165
	}
166

167
	healthCheckClient, err := c.ClusterHealthCheck(ctx, healthCmdFlags.clusterWaitTimeout, &clusterapi.ClusterInfo{
168
		ControlPlaneNodes: controlPlaneNodes,
169
		WorkerNodes:       healthCmdFlags.clusterState.WorkerNodes,
170
		ForceEndpoint:     healthCmdFlags.forceEndpoint,
171
	})
172
	if err != nil {
173
		return err
174
	}
175

176
	if err := healthCheckClient.CloseSend(); err != nil {
177
		return err
178
	}
179

180
	for {
181
		msg, err := healthCheckClient.Recv()
182
		if err != nil {
183
			if err == io.EOF || client.StatusCode(err) == codes.Canceled {
184
				return nil
185
			}
186

187
			return err
188
		}
189

190
		if msg.GetMetadata().GetError() != "" {
191
			return fmt.Errorf("healthcheck error: %s", msg.GetMetadata().GetError())
192
		}
193

194
		fmt.Fprintln(os.Stderr, msg.GetMessage())
195
	}
196
}
197

198
func runE2E() error {
199
	return WithClient(func(ctx context.Context, c *client.Client) error {
200
		clientProvider := &cluster.ConfigClientProvider{
201
			DefaultClient: c,
202
		}
203
		defer clientProvider.Close() //nolint:errcheck
204

205
		state := &cluster.KubernetesClient{
206
			ClientProvider: clientProvider,
207
			ForceEndpoint:  healthCmdFlags.forceEndpoint,
208
		}
209

210
		// Run cluster readiness checks
211
		checkCtx, checkCtxCancel := context.WithTimeout(ctx, healthCmdFlags.clusterWaitTimeout)
212
		defer checkCtxCancel()
213

214
		options := sonobuoy.DefaultOptions()
215
		options.UseSpinner = true
216

217
		return sonobuoy.Run(checkCtx, state, options)
218
	})
219
}
220

221
func init() {
222
	healthCmd.Flags().StringSliceVarP(&healthCmdFlags.configFiles,
223
		"file", "f", nil, "specify config files or patches in a YAML file (can specify multiple)",
224
	)
225
	healthCmd.PreRunE = func(cmd *cobra.Command, args []string) error {
226
		nodesFromArgs :=
227
			len(GlobalArgs.
228
				Nodes) > 0
229
		endpointsFromArgs := len(GlobalArgs.
230
			Endpoints) > 0
231
		for _, configFile := range healthCmdFlags.
232
			configFiles {
233
			if err := processModelineAndUpdateGlobals(configFile, nodesFromArgs, endpointsFromArgs,
234
				false); err != nil {
235
				return err
236
			}
237
		}
238
		return nil
239
	}
240

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")
249
}
250

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
255
	}
256

257
	// read members from the Talos API
258

259
	var members []*clusterres.Member
260

261
	err := WithClientNoNodes(func(ctx context.Context, c *client.Client) error {
262
		items, err := safe.StateListAll[*clusterres.Member](ctx, c.COSI)
263
		if err != nil {
264
			return err
265
		}
266

267
		items.ForEach(func(item *clusterres.Member) { members = append(members, item) })
268

269
		return nil
270
	})
271
	if err != nil {
272
		return nil, err
273
	}
274

275
	return check.NewDiscoveredClusterInfo(members)
276
}
277

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.