diff --git a/api/resource/definitions/runtime/runtime.proto b/api/resource/definitions/runtime/runtime.proto index 39afe0ca2..5c9fffe99 100755 --- a/api/resource/definitions/runtime/runtime.proto +++ b/api/resource/definitions/runtime/runtime.proto @@ -54,6 +54,7 @@ message PlatformMetadataSpec { string instance_type = 5; string instance_id = 6; string provider_id = 7; + bool spot = 8; } // UnmetCondition is a failure which prevents machine from being ready at the stage. diff --git a/internal/app/machined/pkg/runtime/v1alpha1/platform/aws/aws.go b/internal/app/machined/pkg/runtime/v1alpha1/platform/aws/aws.go index 6ea942505..d8dd5fd44 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/platform/aws/aws.go +++ b/internal/app/machined/pkg/runtime/v1alpha1/platform/aws/aws.go @@ -64,13 +64,20 @@ func (a *AWS) ParseMetadata(metadata *MetadataConfig) (*runtime.PlatformNetworkC networkConfig.Hostnames = append(networkConfig.Hostnames, hostnameSpec) } - if metadata.PublicIPv4 != "" { - ip, err := netip.ParseAddr(metadata.PublicIPv4) - if err != nil { - return nil, err - } + publicIPs := []string{} - networkConfig.ExternalIPs = append(networkConfig.ExternalIPs, ip) + if metadata.PublicIPv4 != "" { + publicIPs = append(publicIPs, metadata.PublicIPv4) + } + + if metadata.PublicIPv6 != "" { + publicIPs = append(publicIPs, metadata.PublicIPv6) + } + + for _, ipStr := range publicIPs { + if ip, err := netip.ParseAddr(ipStr); err == nil { + networkConfig.ExternalIPs = append(networkConfig.ExternalIPs, ip) + } } networkConfig.Metadata = &runtimeres.PlatformMetadataSpec{ @@ -81,6 +88,7 @@ func (a *AWS) ParseMetadata(metadata *MetadataConfig) (*runtime.PlatformNetworkC InstanceType: metadata.InstanceType, InstanceID: metadata.InstanceID, ProviderID: fmt.Sprintf("aws://%s/%s", metadata.Zone, metadata.InstanceID), + Spot: metadata.InstanceLifeCycle == "spot", } return networkConfig, nil diff --git a/internal/app/machined/pkg/runtime/v1alpha1/platform/aws/metadata.go b/internal/app/machined/pkg/runtime/v1alpha1/platform/aws/metadata.go index 268cd7f27..835d4bd07 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/platform/aws/metadata.go +++ b/internal/app/machined/pkg/runtime/v1alpha1/platform/aws/metadata.go @@ -14,13 +14,14 @@ import ( // MetadataConfig represents a metadata AWS instance. type MetadataConfig struct { - Hostname string `json:"hostname,omitempty"` - InstanceID string `json:"instance-id,omitempty"` - InstanceType string `json:"instance-type,omitempty"` - PublicIPv4 string `json:"public-ipv4,omitempty"` - PublicIPv6 string `json:"ipv6,omitempty"` - Region string `json:"region,omitempty"` - Zone string `json:"zone,omitempty"` + Hostname string `json:"hostname,omitempty"` + InstanceID string `json:"instance-id,omitempty"` + InstanceType string `json:"instance-type,omitempty"` + InstanceLifeCycle string `json:"instance-life-cycle,omitempty"` + PublicIPv4 string `json:"public-ipv4,omitempty"` + PublicIPv6 string `json:"ipv6,omitempty"` + Region string `json:"region,omitempty"` + Zone string `json:"zone,omitempty"` } //nolint:gocyclo @@ -53,6 +54,10 @@ func (a *AWS) getMetadata(ctx context.Context) (*MetadataConfig, error) { return nil, err } + if metadata.InstanceLifeCycle, err = getMetadataKey("instance-life-cycle"); err != nil { + return nil, err + } + if metadata.InstanceID, err = getMetadataKey("instance-id"); err != nil { return nil, err } diff --git a/internal/app/machined/pkg/runtime/v1alpha1/platform/azure/azure.go b/internal/app/machined/pkg/runtime/v1alpha1/platform/azure/azure.go index 7dc2316ad..37f7bd6f0 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/platform/azure/azure.go +++ b/internal/app/machined/pkg/runtime/v1alpha1/platform/azure/azure.go @@ -89,18 +89,16 @@ func (a *Azure) ParseMetadata(metadata *ComputeMetadata, interfaceAddresses []Ne networkConfig.Hostnames = append(networkConfig.Hostnames, hostnameSpec) } + publicIPs := []string{} + // external IP for _, iface := range interfaceAddresses { for _, ipv4addr := range iface.IPv4.IPAddresses { - if ip, err := netip.ParseAddr(ipv4addr.PublicIPAddress); err == nil { - networkConfig.ExternalIPs = append(networkConfig.ExternalIPs, ip) - } + publicIPs = append(publicIPs, ipv4addr.PublicIPAddress) } for _, ipv6addr := range iface.IPv6.IPAddresses { - if ip, err := netip.ParseAddr(ipv6addr.PublicIPAddress); err == nil { - networkConfig.ExternalIPs = append(networkConfig.ExternalIPs, ip) - } + publicIPs = append(publicIPs, ipv6addr.PublicIPAddress) } } @@ -124,6 +122,12 @@ func (a *Azure) ParseMetadata(metadata *ComputeMetadata, interfaceAddresses []Ne } } + for _, ipStr := range publicIPs { + if ip, err := netip.ParseAddr(ipStr); err == nil { + networkConfig.ExternalIPs = append(networkConfig.ExternalIPs, ip) + } + } + zone := metadata.FaultDomain if metadata.Zone != "" { zone = fmt.Sprintf("%s-%s", metadata.Location, metadata.Zone) @@ -137,6 +141,7 @@ func (a *Azure) ParseMetadata(metadata *ComputeMetadata, interfaceAddresses []Ne InstanceType: metadata.VMSize, InstanceID: metadata.ResourceID, ProviderID: fmt.Sprintf("azure://%s", metadata.ResourceID), + Spot: metadata.EvictionPolicy != "", } return &networkConfig, nil diff --git a/internal/app/machined/pkg/runtime/v1alpha1/platform/azure/metadata.go b/internal/app/machined/pkg/runtime/v1alpha1/platform/azure/metadata.go index 94877f0f5..361e8fdf9 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/platform/azure/metadata.go +++ b/internal/app/machined/pkg/runtime/v1alpha1/platform/azure/metadata.go @@ -47,6 +47,7 @@ type ComputeMetadata struct { ResourceID string `json:"resourceId,omitempty"` VMScaleSetName string `json:"vmScaleSetName,omitempty"` SubscriptionID string `json:"subscriptionId,omitempty"` + EvictionPolicy string `json:"evictionPolicy,omitempty"` } func (a *Azure) getMetadata(ctx context.Context) (*ComputeMetadata, error) { diff --git a/internal/app/machined/pkg/runtime/v1alpha1/platform/digitalocean/digitalocean.go b/internal/app/machined/pkg/runtime/v1alpha1/platform/digitalocean/digitalocean.go index 2dc85b92c..58ff783e8 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/platform/digitalocean/digitalocean.go +++ b/internal/app/machined/pkg/runtime/v1alpha1/platform/digitalocean/digitalocean.go @@ -71,6 +71,8 @@ func (d *DigitalOcean) ParseMetadata(metadata *MetadataConfig) (*runtime.Platfor ConfigLayer: network.ConfigPlatform, }) + publicIPs := []string{} + for _, iface := range metadata.Interfaces["public"] { if iface.IPv4 != nil { ifAddr, err := utils.IPPrefixFrom(iface.IPv4.IPAddress, iface.IPv4.Netmask) @@ -78,7 +80,7 @@ func (d *DigitalOcean) ParseMetadata(metadata *MetadataConfig) (*runtime.Platfor return nil, fmt.Errorf("failed to parse ip address: %w", err) } - networkConfig.ExternalIPs = append(networkConfig.ExternalIPs, ifAddr.Addr()) + publicIPs = append(publicIPs, iface.IPv4.IPAddress) networkConfig.Addresses = append(networkConfig.Addresses, network.AddressSpecSpec{ @@ -134,6 +136,7 @@ func (d *DigitalOcean) ParseMetadata(metadata *MetadataConfig) (*runtime.Platfor return nil, fmt.Errorf("failed to parse ip address: %w", err) } + publicIPs = append(publicIPs, iface.IPv6.IPAddress) networkConfig.Addresses = append(networkConfig.Addresses, network.AddressSpecSpec{ ConfigLayer: network.ConfigPlatform, @@ -215,6 +218,12 @@ func (d *DigitalOcean) ParseMetadata(metadata *MetadataConfig) (*runtime.Platfor } } + for _, ipStr := range publicIPs { + if ip, err := netip.ParseAddr(ipStr); err == nil { + networkConfig.ExternalIPs = append(networkConfig.ExternalIPs, ip) + } + } + networkConfig.Metadata = &runtimeres.PlatformMetadataSpec{ Platform: d.Name(), Hostname: metadata.Hostname, diff --git a/internal/app/machined/pkg/runtime/v1alpha1/platform/digitalocean/testdata/expected.yaml b/internal/app/machined/pkg/runtime/v1alpha1/platform/digitalocean/testdata/expected.yaml index 08d86f559..1d18f8ae8 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/platform/digitalocean/testdata/expected.yaml +++ b/internal/app/machined/pkg/runtime/v1alpha1/platform/digitalocean/testdata/expected.yaml @@ -88,6 +88,7 @@ timeServers: [] operators: [] externalIPs: - 128.199.52.32 + - 2a03:b0c0:2:d0::1478:3001 metadata: platform: digital-ocean hostname: debian-s-1vcpu-512mb-10gb-ams3-01 diff --git a/internal/app/machined/pkg/runtime/v1alpha1/platform/equinixmetal/equinix.go b/internal/app/machined/pkg/runtime/v1alpha1/platform/equinixmetal/equinix.go index cad101432..417451787 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/platform/equinixmetal/equinix.go +++ b/internal/app/machined/pkg/runtime/v1alpha1/platform/equinixmetal/equinix.go @@ -205,11 +205,17 @@ func (p *EquinixMetal) ParseMetadata(ctx context.Context, equinixMetadata *Metad // 2. addresses + publicIPs := []string{} + for _, addr := range equinixMetadata.Network.Addresses { if !(addr.Enabled && addr.Management) { continue } + if addr.Public { + publicIPs = append(publicIPs, addr.Address) + } + ipAddr, err := netip.ParsePrefix(fmt.Sprintf("%s/%d", addr.Address, addr.CIDR)) if err != nil { return nil, err @@ -232,6 +238,12 @@ func (p *EquinixMetal) ParseMetadata(ctx context.Context, equinixMetadata *Metad ) } + for _, ipStr := range publicIPs { + if ip, err := netip.ParseAddr(ipStr); err == nil { + networkConfig.ExternalIPs = append(networkConfig.ExternalIPs, ip) + } + } + // 3. routes for _, addr := range equinixMetadata.Network.Addresses { diff --git a/internal/app/machined/pkg/runtime/v1alpha1/platform/equinixmetal/testdata/expected.yaml b/internal/app/machined/pkg/runtime/v1alpha1/platform/equinixmetal/testdata/expected.yaml index 4607b41e8..208513b3b 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/platform/equinixmetal/testdata/expected.yaml +++ b/internal/app/machined/pkg/runtime/v1alpha1/platform/equinixmetal/testdata/expected.yaml @@ -102,7 +102,9 @@ hostnames: resolvers: [] timeServers: [] operators: [] -externalIPs: [] +externalIPs: + - 147.75.78.41 + - 2604:1380:45d1:fd00::11 metadata: platform: equinixMetal hostname: infra-green-ci diff --git a/internal/app/machined/pkg/runtime/v1alpha1/platform/exoscale/exoscale.go b/internal/app/machined/pkg/runtime/v1alpha1/platform/exoscale/exoscale.go index 9a943058e..fc84b15ca 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/platform/exoscale/exoscale.go +++ b/internal/app/machined/pkg/runtime/v1alpha1/platform/exoscale/exoscale.go @@ -42,12 +42,9 @@ func (e *Exoscale) ParseMetadata(metadata *MetadataConfig) (*runtime.PlatformNet } if metadata.PublicIPv4 != "" { - ip, err := netip.ParseAddr(metadata.PublicIPv4) - if err != nil { - return nil, err + if ip, err := netip.ParseAddr(metadata.PublicIPv4); err == nil { + networkConfig.ExternalIPs = append(networkConfig.ExternalIPs, ip) } - - networkConfig.ExternalIPs = append(networkConfig.ExternalIPs, ip) } networkConfig.Metadata = &runtimeres.PlatformMetadataSpec{ diff --git a/internal/app/machined/pkg/runtime/v1alpha1/platform/gcp/gcp.go b/internal/app/machined/pkg/runtime/v1alpha1/platform/gcp/gcp.go index 6b48b82ae..db017c6cf 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/platform/gcp/gcp.go +++ b/internal/app/machined/pkg/runtime/v1alpha1/platform/gcp/gcp.go @@ -10,6 +10,7 @@ import ( "fmt" "log" "net/netip" + "strconv" "strings" "cloud.google.com/go/compute/metadata" @@ -46,13 +47,10 @@ func (g *GCP) ParseMetadata(metadata *MetadataConfig) (*runtime.PlatformNetworkC networkConfig.Hostnames = append(networkConfig.Hostnames, hostnameSpec) } - if metadata.PublicIPv4 != "" { - ip, err := netip.ParseAddr(metadata.PublicIPv4) - if err != nil { - return nil, err - } + publicIPs := []string{} - networkConfig.ExternalIPs = append(networkConfig.ExternalIPs, ip) + if metadata.PublicIPv4 != "" { + publicIPs = append(publicIPs, metadata.PublicIPv4) } dns, _ := netip.ParseAddr(gcpResolverServer) //nolint:errcheck @@ -73,6 +71,14 @@ func (g *GCP) ParseMetadata(metadata *MetadataConfig) (*runtime.PlatformNetworkC region = region[:idx] } + for _, ipStr := range publicIPs { + if ip, err := netip.ParseAddr(ipStr); err == nil { + networkConfig.ExternalIPs = append(networkConfig.ExternalIPs, ip) + } + } + + preempted, _ := strconv.ParseBool(metadata.Preempted) //nolint:errcheck + networkConfig.Metadata = &runtimeres.PlatformMetadataSpec{ Platform: g.Name(), Hostname: metadata.Hostname, @@ -81,6 +87,7 @@ func (g *GCP) ParseMetadata(metadata *MetadataConfig) (*runtime.PlatformNetworkC InstanceType: metadata.InstanceType, InstanceID: metadata.InstanceID, ProviderID: fmt.Sprintf("gce://%s/%s/%s", metadata.ProjectID, metadata.Zone, metadata.Name), + Spot: preempted, } return networkConfig, nil diff --git a/internal/app/machined/pkg/runtime/v1alpha1/platform/gcp/metadata.go b/internal/app/machined/pkg/runtime/v1alpha1/platform/gcp/metadata.go index 46de9afa5..b1d169919 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/platform/gcp/metadata.go +++ b/internal/app/machined/pkg/runtime/v1alpha1/platform/gcp/metadata.go @@ -25,6 +25,7 @@ type MetadataConfig struct { InstanceType string `json:"machine-type"` InstanceID string `json:"id"` PublicIPv4 string `json:"external-ip"` + Preempted string `json:"preempted"` } func (g *GCP) getMetadata(context.Context) (*MetadataConfig, error) { @@ -66,5 +67,10 @@ func (g *GCP) getMetadata(context.Context) (*MetadataConfig, error) { } } + meta.Preempted, err = metadata.Get("instance/scheduling/preemptible") + if err != nil { + return nil, err + } + return &meta, nil } diff --git a/internal/app/machined/pkg/runtime/v1alpha1/platform/gcp/testdata/metadata.json b/internal/app/machined/pkg/runtime/v1alpha1/platform/gcp/testdata/metadata.json index b579ce73d..d864fabed 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/platform/gcp/testdata/metadata.json +++ b/internal/app/machined/pkg/runtime/v1alpha1/platform/gcp/testdata/metadata.json @@ -4,5 +4,6 @@ "id": "0", "zone": "us-central1-a", "name": "my-server", - "machine-type": "n1-standard-1" -} + "machine-type": "n1-standard-1", + "preempted": "FALSE" +} \ No newline at end of file diff --git a/internal/app/machined/pkg/runtime/v1alpha1/platform/hcloud/hcloud.go b/internal/app/machined/pkg/runtime/v1alpha1/platform/hcloud/hcloud.go index fbde91bcd..94aeb5f93 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/platform/hcloud/hcloud.go +++ b/internal/app/machined/pkg/runtime/v1alpha1/platform/hcloud/hcloud.go @@ -10,6 +10,7 @@ import ( "fmt" "log" "net/netip" + "strings" "github.com/cosi-project/runtime/pkg/state" "github.com/siderolabs/go-procfs/procfs" @@ -49,10 +50,10 @@ func (h *Hcloud) ParseMetadata(unmarshalledNetworkConfig *NetworkConfig, metadat networkConfig.Hostnames = append(networkConfig.Hostnames, hostnameSpec) } + publicIPs := []string{} + if metadata.PublicIPv4 != "" { - if ip, err := netip.ParseAddr(metadata.PublicIPv4); err == nil { - networkConfig.ExternalIPs = append(networkConfig.ExternalIPs, ip) - } + publicIPs = append(publicIPs, metadata.PublicIPv4) } for _, ntwrk := range unmarshalledNetworkConfig.Config { @@ -85,7 +86,9 @@ func (h *Hcloud) ParseMetadata(unmarshalledNetworkConfig *NetworkConfig, metadat } family := nethelpers.FamilyInet4 + if ipAddr.Addr().Is6() { + publicIPs = append(publicIPs, strings.SplitN(subnet.Address, "/", 2)[0]) family = nethelpers.FamilyInet6 } @@ -124,6 +127,12 @@ func (h *Hcloud) ParseMetadata(unmarshalledNetworkConfig *NetworkConfig, metadat } } + for _, ipStr := range publicIPs { + if ip, err := netip.ParseAddr(ipStr); err == nil { + networkConfig.ExternalIPs = append(networkConfig.ExternalIPs, ip) + } + } + networkConfig.Metadata = &runtimeres.PlatformMetadataSpec{ Platform: h.Name(), Hostname: metadata.Hostname, diff --git a/internal/app/machined/pkg/runtime/v1alpha1/platform/hcloud/testdata/expected.yaml b/internal/app/machined/pkg/runtime/v1alpha1/platform/hcloud/testdata/expected.yaml index 7fa86026e..8c2544cc7 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/platform/hcloud/testdata/expected.yaml +++ b/internal/app/machined/pkg/runtime/v1alpha1/platform/hcloud/testdata/expected.yaml @@ -40,6 +40,7 @@ operators: layer: platform externalIPs: - 1.2.3.4 + - 2a01:4f8:1:2::1 metadata: platform: hcloud hostname: talos.fqdn diff --git a/internal/app/machined/pkg/runtime/v1alpha1/platform/nocloud/metadata.go b/internal/app/machined/pkg/runtime/v1alpha1/platform/nocloud/metadata.go index 74442c19c..1f66f4677 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/platform/nocloud/metadata.go +++ b/internal/app/machined/pkg/runtime/v1alpha1/platform/nocloud/metadata.go @@ -92,8 +92,12 @@ type Bonds struct { // MetadataConfig holds meta info. type MetadataConfig struct { - Hostname string `yaml:"hostname,omitempty"` - InstanceID string `yaml:"instance-id,omitempty"` + Hostname string `yaml:"hostname,omitempty"` + InstanceID string `yaml:"instance-id,omitempty"` + InstanceType string `yaml:"instance-type,omitempty"` + ProviderID string `yaml:"provider-id,omitempty"` + Region string `yaml:"region,omitempty"` + Zone string `yaml:"zone,omitempty"` } func (n *Nocloud) configFromNetwork(ctx context.Context, metaBaseURL string) (metaConfig []byte, networkConfig []byte, machineConfig []byte, err error) { diff --git a/internal/app/machined/pkg/runtime/v1alpha1/platform/nocloud/nocloud.go b/internal/app/machined/pkg/runtime/v1alpha1/platform/nocloud/nocloud.go index 2b00f0c54..ed2f2920e 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/platform/nocloud/nocloud.go +++ b/internal/app/machined/pkg/runtime/v1alpha1/platform/nocloud/nocloud.go @@ -58,9 +58,13 @@ func (n *Nocloud) ParseMetadata(unmarshalledNetworkConfig *NetworkConfig, metada } networkConfig.Metadata = &runtimeres.PlatformMetadataSpec{ - Platform: n.Name(), - Hostname: metadata.Hostname, - InstanceID: metadata.InstanceID, + Platform: n.Name(), + Hostname: metadata.Hostname, + InstanceID: metadata.InstanceID, + InstanceType: metadata.InstanceType, + ProviderID: metadata.ProviderID, + Region: metadata.Region, + Zone: metadata.Zone, } return networkConfig, nil diff --git a/internal/app/machined/pkg/runtime/v1alpha1/platform/scaleway/scaleway.go b/internal/app/machined/pkg/runtime/v1alpha1/platform/scaleway/scaleway.go index dcc1e26f8..f8b9065dd 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/platform/scaleway/scaleway.go +++ b/internal/app/machined/pkg/runtime/v1alpha1/platform/scaleway/scaleway.go @@ -34,6 +34,8 @@ func (s *Scaleway) Name() string { } // ParseMetadata converts Scaleway platform metadata into platform network config. +// +//nolint:gocyclo func (s *Scaleway) ParseMetadata(metadata *instance.Metadata) (*runtime.PlatformNetworkConfig, error) { networkConfig := &runtime.PlatformNetworkConfig{} @@ -49,13 +51,10 @@ func (s *Scaleway) ParseMetadata(metadata *instance.Metadata) (*runtime.Platform networkConfig.Hostnames = append(networkConfig.Hostnames, hostnameSpec) } - if metadata.PublicIP.Address != "" { - ip, err := netip.ParseAddr(metadata.PublicIP.Address) - if err != nil { - return nil, err - } + publicIPs := []string{} - networkConfig.ExternalIPs = append(networkConfig.ExternalIPs, ip) + if metadata.PublicIP.Address != "" { + publicIPs = append(publicIPs, metadata.PublicIP.Address) } networkConfig.Links = append(networkConfig.Links, network.LinkSpecSpec{ @@ -102,6 +101,7 @@ func (s *Scaleway) ParseMetadata(metadata *instance.Metadata) (*runtime.Platform addr := netip.PrefixFrom(ip, bits) + publicIPs = append(publicIPs, metadata.IPv6.Address) networkConfig.Addresses = append(networkConfig.Addresses, network.AddressSpecSpec{ ConfigLayer: network.ConfigPlatform, @@ -139,6 +139,12 @@ func (s *Scaleway) ParseMetadata(metadata *instance.Metadata) (*runtime.Platform zoneParts = zoneParts[:2] } + for _, ipStr := range publicIPs { + if ip, err := netip.ParseAddr(ipStr); err == nil { + networkConfig.ExternalIPs = append(networkConfig.ExternalIPs, ip) + } + } + networkConfig.Metadata = &runtimeres.PlatformMetadataSpec{ Platform: s.Name(), Hostname: metadata.Hostname, diff --git a/internal/app/machined/pkg/runtime/v1alpha1/platform/scaleway/testdata/expected.yaml b/internal/app/machined/pkg/runtime/v1alpha1/platform/scaleway/testdata/expected.yaml index 39b137ff0..31201ed79 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/platform/scaleway/testdata/expected.yaml +++ b/internal/app/machined/pkg/runtime/v1alpha1/platform/scaleway/testdata/expected.yaml @@ -53,9 +53,12 @@ operators: layer: platform externalIPs: - 11.22.222.222 + - 2001:111:222:3333::1 metadata: platform: scaleway hostname: scw-talos + region: zone-name + zone: zone-name-1 instanceType: DEV1-S instanceId: 11111111-1111-1111-1111-111111111111 - providerId: scaleway://instance//11111111-1111-1111-1111-111111111111 + providerId: scaleway://instance/zone-name-1/11111111-1111-1111-1111-111111111111 diff --git a/internal/app/machined/pkg/runtime/v1alpha1/platform/scaleway/testdata/metadata.json b/internal/app/machined/pkg/runtime/v1alpha1/platform/scaleway/testdata/metadata.json index bbe8e2b29..b7bc97ad8 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/platform/scaleway/testdata/metadata.json +++ b/internal/app/machined/pkg/runtime/v1alpha1/platform/scaleway/testdata/metadata.json @@ -15,5 +15,8 @@ "address": "2001:111:222:3333::1", "gateway": "2001:111:222:3333::", "netmask": "64" + }, + "location": { + "zone_id": "zone-name-1" } -} +} \ No newline at end of file diff --git a/internal/app/machined/pkg/runtime/v1alpha1/platform/upcloud/testdata/expected.yaml b/internal/app/machined/pkg/runtime/v1alpha1/platform/upcloud/testdata/expected.yaml index 778b31e84..6a962b9a3 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/platform/upcloud/testdata/expected.yaml +++ b/internal/app/machined/pkg/runtime/v1alpha1/platform/upcloud/testdata/expected.yaml @@ -73,6 +73,7 @@ operators: layer: platform externalIPs: - 185.70.197.2 + - 2a04:3544:8000:1000:0:1111:2222:3333 metadata: platform: upcloud hostname: talos diff --git a/internal/app/machined/pkg/runtime/v1alpha1/platform/upcloud/upcloud.go b/internal/app/machined/pkg/runtime/v1alpha1/platform/upcloud/upcloud.go index 5719b1150..d7fb3bfd9 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/platform/upcloud/upcloud.go +++ b/internal/app/machined/pkg/runtime/v1alpha1/platform/upcloud/upcloud.go @@ -48,7 +48,10 @@ func (u *UpCloud) ParseMetadata(metadata *MetadataConfig) (*runtime.PlatformNetw networkConfig.Hostnames = append(networkConfig.Hostnames, hostnameSpec) } - var dnsIPs []netip.Addr + var ( + publicIPs []string + dnsIPs []netip.Addr + ) firstIP := true @@ -67,12 +70,7 @@ func (u *UpCloud) ParseMetadata(metadata *MetadataConfig) (*runtime.PlatformNetw for _, ip := range addr.IPAddresses { if firstIP { - ipAddr, err := netip.ParseAddr(ip.Address) - if err != nil { - return nil, err - } - - networkConfig.ExternalIPs = append(networkConfig.ExternalIPs, ipAddr) + publicIPs = append(publicIPs, ip.Address) firstIP = false } @@ -109,7 +107,9 @@ func (u *UpCloud) ParseMetadata(metadata *MetadataConfig) (*runtime.PlatformNetw ipPrefix := netip.PrefixFrom(addr, ntwrk.Bits()) family := nethelpers.FamilyInet4 + if addr.Is6() { + publicIPs = append(publicIPs, ip.Address) family = nethelpers.FamilyInet6 } @@ -157,6 +157,12 @@ func (u *UpCloud) ParseMetadata(metadata *MetadataConfig) (*runtime.PlatformNetw }) } + for _, ipStr := range publicIPs { + if ip, err := netip.ParseAddr(ipStr); err == nil { + networkConfig.ExternalIPs = append(networkConfig.ExternalIPs, ip) + } + } + networkConfig.Metadata = &runtimeres.PlatformMetadataSpec{ Platform: u.Name(), Hostname: metadata.Hostname, diff --git a/internal/app/machined/pkg/runtime/v1alpha1/platform/vultr/testdata/expected.yaml b/internal/app/machined/pkg/runtime/v1alpha1/platform/vultr/testdata/expected.yaml index b07ee51d2..f7d68a6ba 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/platform/vultr/testdata/expected.yaml +++ b/internal/app/machined/pkg/runtime/v1alpha1/platform/vultr/testdata/expected.yaml @@ -1,4 +1,10 @@ addresses: + - address: 95.111.222.111/23 + linkName: eth0 + family: inet4 + scope: global + flags: permanent + layer: platform - address: 10.7.96.3/20 linkName: eth1 family: inet4 @@ -20,22 +26,28 @@ links: kind: "" type: netrom layer: platform -routes: [] +routes: + - family: inet4 + dst: "" + src: "" + gateway: 95.111.222.1 + outLinkName: eth0 + table: main + scope: global + type: unicast + flags: "" + protocol: static + layer: platform hostnames: - hostname: talos domainname: "" layer: platform resolvers: [] timeServers: [] -operators: - - operator: dhcp4 - linkName: eth0 - requireUp: true - dhcp4: - routeMetric: 1024 - layer: platform +operators: [] externalIPs: - - 1.2.3.4 + - 95.111.222.111 + - 2001:19f0:5001:2095:1111:2222:3333:4444 metadata: platform: vultr hostname: talos diff --git a/internal/app/machined/pkg/runtime/v1alpha1/platform/vultr/vultr.go b/internal/app/machined/pkg/runtime/v1alpha1/platform/vultr/vultr.go index c92e55d22..3fac94b50 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/platform/vultr/vultr.go +++ b/internal/app/machined/pkg/runtime/v1alpha1/platform/vultr/vultr.go @@ -7,7 +7,6 @@ package vultr import ( "context" - stderrors "errors" "fmt" "log" "net" @@ -36,13 +35,9 @@ func (v *Vultr) Name() string { // ParseMetadata converts Vultr platform metadata into platform network config. // //nolint:gocyclo -func (v *Vultr) ParseMetadata(extIP []byte, metadata *metadata.MetaData) (*runtime.PlatformNetworkConfig, error) { +func (v *Vultr) ParseMetadata(metadata *metadata.MetaData) (*runtime.PlatformNetworkConfig, error) { networkConfig := &runtime.PlatformNetworkConfig{} - if ip, err := netip.ParseAddr(string(extIP)); err == nil { - networkConfig.ExternalIPs = append(networkConfig.ExternalIPs, ip) - } - if metadata.Hostname != "" { hostnameSpec := network.HostnameSpecSpec{ ConfigLayer: network.ConfigPlatform, @@ -55,6 +50,8 @@ func (v *Vultr) ParseMetadata(extIP []byte, metadata *metadata.MetaData) (*runti networkConfig.Hostnames = append(networkConfig.Hostnames, hostnameSpec) } + publicIPs := []string{} + for i, addr := range metadata.Interfaces { iface := fmt.Sprintf("eth%d", i) @@ -71,42 +68,77 @@ func (v *Vultr) ParseMetadata(extIP []byte, metadata *metadata.MetaData) (*runti networkConfig.Links = append(networkConfig.Links, link) if addr.IPv4.Address != "" { - if addr.NetworkType != "private" { - networkConfig.Operators = append(networkConfig.Operators, network.OperatorSpecSpec{ - Operator: network.OperatorDHCP4, - LinkName: iface, - RequireUp: true, - DHCP4: network.DHCP4OperatorSpec{ - RouteMetric: 1024, - }, - ConfigLayer: network.ConfigPlatform, - }) - } else { - ip, err := netip.ParseAddr(addr.IPv4.Address) - if err != nil { - return nil, err - } - - netmask, err := netip.ParseAddr(addr.IPv4.Netmask) - if err != nil { - return nil, err - } - - mask, _ := netmask.MarshalBinary() //nolint:errcheck // never fails - ones, _ := net.IPMask(mask).Size() - ipAddr := netip.PrefixFrom(ip, ones) - - networkConfig.Addresses = append(networkConfig.Addresses, - network.AddressSpecSpec{ - ConfigLayer: network.ConfigPlatform, - LinkName: iface, - Address: ipAddr, - Scope: nethelpers.ScopeGlobal, - Flags: nethelpers.AddressFlags(nethelpers.AddressPermanent), - Family: nethelpers.FamilyInet4, - }, - ) + if addr.NetworkType == "public" { + publicIPs = append(publicIPs, addr.IPv4.Address) } + + ip, err := netip.ParseAddr(addr.IPv4.Address) + if err != nil { + return nil, err + } + + netmask, err := netip.ParseAddr(addr.IPv4.Netmask) + if err != nil { + return nil, err + } + + mask, _ := netmask.MarshalBinary() //nolint:errcheck // never fails + ones, _ := net.IPMask(mask).Size() + ipAddr := netip.PrefixFrom(ip, ones) + + networkConfig.Addresses = append(networkConfig.Addresses, + network.AddressSpecSpec{ + ConfigLayer: network.ConfigPlatform, + LinkName: iface, + Address: ipAddr, + Scope: nethelpers.ScopeGlobal, + Flags: nethelpers.AddressFlags(nethelpers.AddressPermanent), + Family: nethelpers.FamilyInet4, + }, + ) + + if addr.IPv4.Gateway != "" { + gw, err := netip.ParseAddr(addr.IPv4.Gateway) + if err != nil { + return nil, err + } + + route := network.RouteSpecSpec{ + ConfigLayer: network.ConfigPlatform, + Gateway: gw, + OutLinkName: iface, + Table: nethelpers.TableMain, + Protocol: nethelpers.ProtocolStatic, + Type: nethelpers.TypeUnicast, + Family: nethelpers.FamilyInet4, + } + + route.Normalize() + + networkConfig.Routes = append(networkConfig.Routes, route) + } + } else { + networkConfig.Operators = append(networkConfig.Operators, network.OperatorSpecSpec{ + Operator: network.OperatorDHCP4, + LinkName: iface, + RequireUp: true, + DHCP4: network.DHCP4OperatorSpec{ + RouteMetric: 1024, + }, + ConfigLayer: network.ConfigPlatform, + }) + } + + if addr.IPv6.Address != "" { + if addr.NetworkType == "public" { + publicIPs = append(publicIPs, addr.IPv6.Address) + } + } + } + + for _, ipStr := range publicIPs { + if ip, err := netip.ParseAddr(ipStr); err == nil { + networkConfig.ExternalIPs = append(networkConfig.ExternalIPs, ip) } } @@ -151,14 +183,7 @@ func (v *Vultr) NetworkConfiguration(ctx context.Context, _ state.State, ch chan return err } - extIP, err := download.Download(ctx, VultrExternalIPEndpoint, - download.WithErrorOnNotFound(errors.ErrNoExternalIPs), - download.WithErrorOnEmptyResponse(errors.ErrNoExternalIPs)) - if err != nil && !stderrors.Is(err, errors.ErrNoExternalIPs) { - return err - } - - networkConfig, err := v.ParseMetadata(extIP, metadata) + networkConfig, err := v.ParseMetadata(metadata) if err != nil { return err } diff --git a/internal/app/machined/pkg/runtime/v1alpha1/platform/vultr/vultr_test.go b/internal/app/machined/pkg/runtime/v1alpha1/platform/vultr/vultr_test.go index 39c421813..7fe3cebc9 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/platform/vultr/vultr_test.go +++ b/internal/app/machined/pkg/runtime/v1alpha1/platform/vultr/vultr_test.go @@ -30,7 +30,7 @@ func TestParseMetadata(t *testing.T) { require.NoError(t, json.Unmarshal(rawMetadata, &metadata)) - networkConfig, err := p.ParseMetadata([]byte("1.2.3.4"), &metadata) + networkConfig, err := p.ParseMetadata(&metadata) require.NoError(t, err) marshaled, err := yaml.Marshal(networkConfig) diff --git a/pkg/machinery/api/resource/definitions/runtime/runtime.pb.go b/pkg/machinery/api/resource/definitions/runtime/runtime.pb.go index be0c7ee61..e30bf4ebb 100644 --- a/pkg/machinery/api/resource/definitions/runtime/runtime.pb.go +++ b/pkg/machinery/api/resource/definitions/runtime/runtime.pb.go @@ -396,6 +396,7 @@ type PlatformMetadataSpec struct { InstanceType string `protobuf:"bytes,5,opt,name=instance_type,json=instanceType,proto3" json:"instance_type,omitempty"` InstanceId string `protobuf:"bytes,6,opt,name=instance_id,json=instanceId,proto3" json:"instance_id,omitempty"` ProviderId string `protobuf:"bytes,7,opt,name=provider_id,json=providerId,proto3" json:"provider_id,omitempty"` + Spot bool `protobuf:"varint,8,opt,name=spot,proto3" json:"spot,omitempty"` } func (x *PlatformMetadataSpec) Reset() { @@ -479,6 +480,13 @@ func (x *PlatformMetadataSpec) GetProviderId() string { return "" } +func (x *PlatformMetadataSpec) GetSpot() bool { + if x != nil { + return x.Spot + } + return false +} + // UnmetCondition is a failure which prevents machine from being ready at the stage. type UnmetCondition struct { state protoimpl.MessageState @@ -590,7 +598,7 @@ var file_resource_definitions_runtime_runtime_proto_rawDesc = []byte{ 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xe1, 0x01, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xf5, 0x01, 0x0a, 0x14, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x53, 0x70, 0x65, 0x63, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, @@ -605,16 +613,17 @@ var file_resource_definitions_runtime_runtime_proto_rawDesc = []byte{ 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, - 0x64, 0x22, 0x3c, 0x0a, 0x0e, 0x55, 0x6e, 0x6d, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, - 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x42, - 0x4c, 0x5a, 0x4a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x69, - 0x64, 0x65, 0x72, 0x6f, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x74, 0x61, 0x6c, 0x6f, 0x73, 0x2f, 0x70, - 0x6b, 0x67, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x72, 0x79, 0x2f, 0x61, 0x70, 0x69, - 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x64, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x70, 0x6f, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x04, 0x73, 0x70, 0x6f, 0x74, 0x22, 0x3c, 0x0a, 0x0e, 0x55, 0x6e, 0x6d, 0x65, 0x74, 0x43, 0x6f, + 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, + 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, + 0x73, 0x6f, 0x6e, 0x42, 0x4c, 0x5a, 0x4a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x73, 0x69, 0x64, 0x65, 0x72, 0x6f, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x74, 0x61, 0x6c, + 0x6f, 0x73, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x72, 0x79, + 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, 0x64, 0x65, + 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, + 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/pkg/machinery/api/resource/definitions/runtime/runtime_vtproto.pb.go b/pkg/machinery/api/resource/definitions/runtime/runtime_vtproto.pb.go index 3e7fc2576..100420eb5 100644 --- a/pkg/machinery/api/resource/definitions/runtime/runtime_vtproto.pb.go +++ b/pkg/machinery/api/resource/definitions/runtime/runtime_vtproto.pb.go @@ -373,6 +373,16 @@ func (m *PlatformMetadataSpec) MarshalToSizedBufferVT(dAtA []byte) (int, error) i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if m.Spot { + i-- + if m.Spot { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x40 + } if len(m.ProviderId) > 0 { i -= len(m.ProviderId) copy(dAtA[i:], m.ProviderId) @@ -651,6 +661,9 @@ func (m *PlatformMetadataSpec) SizeVT() (n int) { if l > 0 { n += 1 + l + sov(uint64(l)) } + if m.Spot { + n += 2 + } if m.unknownFields != nil { n += len(m.unknownFields) } @@ -1679,6 +1692,26 @@ func (m *PlatformMetadataSpec) UnmarshalVT(dAtA []byte) error { } m.ProviderId = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 8: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Spot", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Spot = bool(v != 0) default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) diff --git a/pkg/machinery/resources/runtime/platform_metadata.go b/pkg/machinery/resources/runtime/platform_metadata.go index 1f827951b..485716e22 100644 --- a/pkg/machinery/resources/runtime/platform_metadata.go +++ b/pkg/machinery/resources/runtime/platform_metadata.go @@ -33,6 +33,7 @@ type PlatformMetadataSpec struct { InstanceType string `yaml:"instanceType,omitempty" protobuf:"5"` InstanceID string `yaml:"instanceId,omitempty" protobuf:"6"` ProviderID string `yaml:"providerId,omitempty" protobuf:"7"` + Spot bool `yaml:"spot,omitempty" protobuf:"8"` } // NewPlatformMetadataSpec initializes a MetadataSpec resource. @@ -51,7 +52,24 @@ func (PlatformMetadataRD) ResourceDefinition(resource.Metadata, PlatformMetadata return meta.ResourceDefinitionSpec{ Type: PlatformMetadataType, DefaultNamespace: NamespaceName, - PrintColumns: []meta.PrintColumn{}, + PrintColumns: []meta.PrintColumn{ + { + Name: "Platform", + JSONPath: `{.platform}`, + }, + { + Name: "Type", + JSONPath: `{.instanceType}`, + }, + { + Name: "Region", + JSONPath: `{.region}`, + }, + { + Name: "Zone", + JSONPath: `{.zone}`, + }, + }, } } diff --git a/website/content/v1.3/reference/api.md b/website/content/v1.3/reference/api.md index 4bf955a5d..f849c1294 100644 --- a/website/content/v1.3/reference/api.md +++ b/website/content/v1.3/reference/api.md @@ -3149,6 +3149,7 @@ PlatformMetadataSpec describes platform metadata properties. | instance_type | [string](#string) | | | | instance_id | [string](#string) | | | | provider_id | [string](#string) | | | +| spot | [bool](#bool) | | |