mirror of
https://github.com/siderolabs/talos.git
synced 2025-10-17 18:41:16 +02:00
This moves our test scripts to using the bootstrap API. Some automation around invoking the bootstrap API was also added to give the same ease of use when creating clusters with the CLI. Signed-off-by: Andrew Rynhard <andrew@andrewrynhard.com>
139 lines
3.5 KiB
Go
139 lines
3.5 KiB
Go
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
// Package check provides set of checks to verify cluster readiness.
|
|
package check
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"sort"
|
|
|
|
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime"
|
|
"github.com/talos-systems/talos/pkg/client"
|
|
)
|
|
|
|
// ErrServiceNotFound is an error that indicates that a service was not found.
|
|
var ErrServiceNotFound = fmt.Errorf("service not found")
|
|
|
|
// ServiceStateAssertion checks whether service reached some specified state.
|
|
//
|
|
//nolint: gocyclo
|
|
func ServiceStateAssertion(ctx context.Context, cluster ClusterInfo, service string, states ...string) error {
|
|
cli, err := cluster.Client()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var node string
|
|
|
|
switch {
|
|
case len(cluster.NodesByType(runtime.MachineTypeInit)) > 0:
|
|
nodes := cluster.NodesByType(runtime.MachineTypeInit)
|
|
if len(nodes) != 1 {
|
|
return fmt.Errorf("expected 1 init node, got %d", len(nodes))
|
|
}
|
|
|
|
node = nodes[0]
|
|
case len(cluster.NodesByType(runtime.MachineTypeControlPlane)) > 0:
|
|
nodes := cluster.NodesByType(runtime.MachineTypeControlPlane)
|
|
|
|
sort.Strings(nodes)
|
|
|
|
node = nodes[0]
|
|
default:
|
|
return fmt.Errorf("no bootstrap node found")
|
|
}
|
|
|
|
nodeCtx := client.WithNodes(ctx, node)
|
|
|
|
servicesInfo, err := cli.ServiceInfo(nodeCtx, service)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
serviceOk := false
|
|
|
|
acceptedStates := map[string]struct{}{}
|
|
for _, state := range states {
|
|
acceptedStates[state] = struct{}{}
|
|
}
|
|
|
|
for _, serviceInfo := range servicesInfo {
|
|
if len(serviceInfo.Service.Events.Events) == 0 {
|
|
return fmt.Errorf("no events recorded yet for service %q", service)
|
|
}
|
|
|
|
lastEvent := serviceInfo.Service.Events.Events[len(serviceInfo.Service.Events.Events)-1]
|
|
if _, ok := acceptedStates[lastEvent.State]; !ok {
|
|
return fmt.Errorf("service %q not in expected state %q: current state [%s] %s", service, states, lastEvent.State, lastEvent.Msg)
|
|
}
|
|
|
|
serviceOk = true
|
|
}
|
|
|
|
if !serviceOk {
|
|
return ErrServiceNotFound
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// ServiceHealthAssertion checks whether service reached some specified state.
|
|
//nolint: gocyclo
|
|
func ServiceHealthAssertion(ctx context.Context, cluster ClusterInfo, service string, setters ...Option) error {
|
|
opts := DefaultOptions()
|
|
|
|
for _, setter := range setters {
|
|
if err := setter(opts); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
cli, err := cluster.Client()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var nodes []string
|
|
|
|
if len(opts.Types) > 0 {
|
|
for _, t := range opts.Types {
|
|
nodes = append(nodes, cluster.NodesByType(t)...)
|
|
}
|
|
} else {
|
|
nodes = cluster.Nodes()
|
|
}
|
|
|
|
count := len(nodes)
|
|
|
|
nodesCtx := client.WithNodes(ctx, nodes...)
|
|
|
|
servicesInfo, err := cli.ServiceInfo(nodesCtx, service)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if len(servicesInfo) != count {
|
|
return fmt.Errorf("expected a response with %d node(s), got %d", count, len(servicesInfo))
|
|
}
|
|
|
|
for _, serviceInfo := range servicesInfo {
|
|
if len(serviceInfo.Service.Events.Events) == 0 {
|
|
return fmt.Errorf("no events recorded yet for service %q", service)
|
|
}
|
|
|
|
lastEvent := serviceInfo.Service.Events.Events[len(serviceInfo.Service.Events.Events)-1]
|
|
if lastEvent.State != "Running" {
|
|
return fmt.Errorf("service %q not in expected state %q: current state [%s] %s", service, "Running", lastEvent.State, lastEvent.Msg)
|
|
}
|
|
|
|
if !serviceInfo.Service.GetHealth().GetHealthy() {
|
|
return fmt.Errorf("service is not healthy: %s", service)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|