/
connection.go
156 lines (126 loc) · 4.11 KB
/
connection.go
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// 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 installer
import (
"context"
"net"
"github.com/cosi-project/runtime/pkg/safe"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
"github.com/siderolabs/talos/pkg/machinery/api/machine"
"github.com/siderolabs/talos/pkg/machinery/api/storage"
"github.com/siderolabs/talos/pkg/machinery/client"
"github.com/siderolabs/talos/pkg/machinery/nethelpers"
"github.com/siderolabs/talos/pkg/machinery/resources/network"
)
// Connection unifies clients for bootstrap node and the node which is being configured.
type Connection struct {
nodeEndpoint string
bootstrapEndpoint string
nodeClient *client.Client
bootstrapClient *client.Client
nodeCtx context.Context //nolint:containedctx
bootstrapCtx context.Context //nolint:containedctx
dryRun bool
}
// NewConnection creates new installer connection.
func NewConnection(ctx context.Context, nodeClient *client.Client, endpoint string, options ...Option) (
*Connection,
error,
) {
c := &Connection{
nodeEndpoint: endpoint,
nodeClient: nodeClient,
nodeCtx: ctx,
}
for _, opt := range options {
err := opt(c)
if err != nil {
return nil, err
}
}
return c, nil
}
// GenerateConfiguration calls GenerateConfiguration on the target/bootstrap node.
func (c *Connection) GenerateConfiguration(
req *machine.GenerateConfigurationRequest,
callOptions ...grpc.CallOption,
) (*machine.GenerateConfigurationResponse, error) {
if c.bootstrapClient != nil {
return c.bootstrapClient.GenerateConfiguration(c.bootstrapCtx, req, callOptions...)
}
return c.nodeClient.GenerateConfiguration(c.nodeCtx, req, callOptions...)
}
// ApplyConfiguration calls ApplyConfiguration on the target node using appropriate node context.
func (c *Connection) ApplyConfiguration(
req *machine.ApplyConfigurationRequest,
callOptions ...grpc.CallOption,
) (*machine.ApplyConfigurationResponse, error) {
return c.nodeClient.ApplyConfiguration(c.nodeCtx, req, callOptions...)
}
// Disks get disks list from the target node.
func (c *Connection) Disks(callOptions ...grpc.CallOption) (*storage.DisksResponse, error) {
return c.nodeClient.Disks(c.nodeCtx, callOptions...)
}
// Link a subset of fields from LinkStatus resource.
type Link struct {
Name string
Physical bool
Up bool
HardwareAddr net.HardwareAddr
MTU int
}
// Links gets a list of network interfaces.
func (c *Connection) Links() ([]Link, error) {
ctx := c.nodeCtx
md, _ := metadata.FromOutgoingContext(c.nodeCtx)
if nodes := md["nodes"]; len(nodes) > 0 {
ctx = client.WithNode(ctx, nodes[0])
}
items, err := safe.StateListAll[*network.LinkStatus](ctx, c.nodeClient.COSI)
if err != nil {
return nil, err
}
it := items.Iterator()
var links []Link
for it.Next() {
var link Link
link.Name = it.Value().Metadata().ID()
link.Physical = it.Value().TypedSpec().Physical()
link.MTU = int(it.Value().TypedSpec().MTU)
switch it.Value().TypedSpec().OperationalState { //nolint:exhaustive
case nethelpers.OperStateUnknown:
link.Up = true
case nethelpers.OperStateUp:
link.Up = true
default:
link.Up = false
}
link.HardwareAddr = net.HardwareAddr(it.Value().TypedSpec().HardwareAddr)
links = append(links, link)
}
return links, nil
}
// ExpandingCluster check if bootstrap node is set.
func (c *Connection) ExpandingCluster() bool {
return c.bootstrapClient != nil
}
// Option represents a single connection option.
type Option func(c *Connection) error
// WithBootstrapNode configures bootstrap node endpoint.
func WithBootstrapNode(ctx context.Context, bootstrapClient *client.Client, bootstrapNode string) Option {
return func(c *Connection) error {
c.bootstrapEndpoint = bootstrapNode
c.bootstrapClient = bootstrapClient
c.bootstrapCtx = ctx
return nil
}
}
// WithDryRun enables dry run mode in the installer.
func WithDryRun(dryRun bool) Option {
return func(c *Connection) error {
c.dryRun = dryRun
return nil
}
}