Andrey Smirnov 50a2410482
feat: add operating system version field to discovery
Fixes #4232

The result:

```
talosctl -n 172.20.0.2 get members
NODE         NAMESPACE   TYPE     ID                       VERSION   HOSTNAME                 MACHINE TYPE   OS                                           ADDRESSES
172.20.0.2   cluster     Member   talos-default-master-1   2         talos-default-master-1   controlplane   Talos (v0.13.0-alpha.0-13-gfdd80a12-dirty)   ["172.20.0.2","fdd1:f54:2697:3902:44f8:92ff:fe2e:1aea"]
172.20.0.2   cluster     Member   talos-default-worker-1   1         talos-default-worker-1   worker         Talos (v0.13.0-alpha.0-13-gfdd80a12-dirty)   ["172.20.0.3","fdd1:f54:2697:3902:d4ba:55ff:fe8a:f551"]
172.20.0.2   cluster     Member   talos-default-worker-2   1         talos-default-worker-2   worker         Talos (v0.13.0-alpha.0-13-gfdd80a12-dirty)   ["172.20.0.4","fdd1:f54:2697:3902:e00d:f4ff:fecf:51c8"]
```

Signed-off-by: Andrey Smirnov <andrey.smirnov@talos-systems.com>
2021-09-17 15:44:33 +03:00

108 lines
2.7 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 cluster
import (
"fmt"
"github.com/cosi-project/runtime/pkg/resource"
"github.com/cosi-project/runtime/pkg/resource/meta"
"inet.af/netaddr"
"github.com/talos-systems/talos/pkg/machinery/config/types/v1alpha1/machine"
)
// MemberType is type of Member resource.
const MemberType = resource.Type("Members.cluster.talos.dev")
// Member resource contains information about discovered cluster members.
//
// Members are usually derived from Affiliates.
type Member struct {
md resource.Metadata
spec MemberSpec
}
// MemberSpec describes Member state.
type MemberSpec struct {
NodeID string `yaml:"nodeId"`
Addresses []netaddr.IP `yaml:"addresses"`
Hostname string `yaml:"hostname"`
MachineType machine.Type `yaml:"machineType"`
OperatingSystem string `yaml:"operatingSystem"`
}
// NewMember initializes a Member resource.
func NewMember(namespace resource.Namespace, id resource.ID) *Member {
r := &Member{
md: resource.NewMetadata(namespace, MemberType, id, resource.VersionUndefined),
spec: MemberSpec{},
}
r.md.BumpVersion()
return r
}
// Metadata implements resource.Resource.
func (r *Member) Metadata() *resource.Metadata {
return &r.md
}
// Spec implements resource.Resource.
func (r *Member) Spec() interface{} {
return r.spec
}
func (r *Member) String() string {
return fmt.Sprintf("cluster.Member(%q)", r.md.ID())
}
// DeepCopy implements resource.Resource.
func (r *Member) DeepCopy() resource.Resource {
return &Member{
md: r.md,
spec: MemberSpec{
NodeID: r.spec.NodeID,
Addresses: append([]netaddr.IP(nil), r.spec.Addresses...),
Hostname: r.spec.Hostname,
MachineType: r.spec.MachineType,
OperatingSystem: r.spec.OperatingSystem,
},
}
}
// ResourceDefinition implements meta.ResourceDefinitionProvider interface.
func (r *Member) ResourceDefinition() meta.ResourceDefinitionSpec {
return meta.ResourceDefinitionSpec{
Type: MemberType,
Aliases: []resource.Type{},
DefaultNamespace: NamespaceName,
PrintColumns: []meta.PrintColumn{
{
Name: "Hostname",
JSONPath: `{.hostname}`,
},
{
Name: "Machine Type",
JSONPath: `{.machineType}`,
},
{
Name: "OS",
JSONPath: `{.operatingSystem}`,
},
{
Name: "Addresses",
JSONPath: `{.addresses}`,
},
},
}
}
// TypedSpec allows to access the Spec with the proper type.
func (r *Member) TypedSpec() *MemberSpec {
return &r.spec
}