feat: add scaleway.com cloud support
* cloud-init for scaleway * set ipv6 to the interface Signed-off-by: Serge Logvinov <serge.logvinov@sinextra.dev> Signed-off-by: Andrey Smirnov <andrey.smirnov@talos-systems.com>
This commit is contained in:
parent
f156ab1847
commit
3b5f4038de
@ -542,6 +542,8 @@ local release = {
|
||||
'_out/metal-libretech_all_h3_cc_h5-arm64.img.xz',
|
||||
'_out/openstack-amd64.tar.gz',
|
||||
'_out/openstack-arm64.tar.gz',
|
||||
'_out/scaleway-amd64.raw.xz',
|
||||
'_out/scaleway-arm64.raw.xz',
|
||||
'_out/talos-amd64.iso',
|
||||
'_out/talos-arm64.iso',
|
||||
'_out/talosctl-cni-bundle-amd64.tar.gz',
|
||||
|
@ -84,7 +84,7 @@ func runImageCmd() (err error) {
|
||||
|
||||
if options.ConfigSource == "" {
|
||||
switch p.Name() {
|
||||
case "aws", "azure", "digital-ocean", "gcp", "hcloud", "upcloud":
|
||||
case "aws", "azure", "digital-ocean", "gcp", "hcloud", "scaleway", "upcloud":
|
||||
options.ConfigSource = constants.ConfigNone
|
||||
case "vmware":
|
||||
options.ConfigSource = constants.ConfigGuestInfo
|
||||
@ -156,6 +156,19 @@ func finalize(platform runtime.Platform, img, arch string) (err error) {
|
||||
if err = tar(fmt.Sprintf("openstack-%s.tar.gz", arch), file, dir); err != nil {
|
||||
return err
|
||||
}
|
||||
case "scaleway":
|
||||
file = filepath.Join(outputArg, fmt.Sprintf("scaleway-%s.raw", arch))
|
||||
|
||||
err = os.Rename(img, file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Println("compressing image")
|
||||
|
||||
if err = xz(file); err != nil {
|
||||
return err
|
||||
}
|
||||
case "upcloud":
|
||||
file = filepath.Join(outputArg, fmt.Sprintf("upcloud-%s.raw", arch))
|
||||
|
||||
|
1
go.mod
1
go.mod
@ -67,6 +67,7 @@ require (
|
||||
github.com/rivo/tview v0.0.0-20210624165335-29d673af0ce2
|
||||
github.com/rs/xid v1.3.0
|
||||
github.com/ryanuber/columnize v2.1.2+incompatible
|
||||
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.7
|
||||
github.com/smira/go-xz v0.0.0-20201019130106-9921ed7a9935
|
||||
github.com/spf13/cobra v1.2.1
|
||||
github.com/stretchr/testify v1.7.0
|
||||
|
2
go.sum
2
go.sum
@ -1052,6 +1052,8 @@ github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiB
|
||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b h1:gQZ0qzfKHQIybLANtM3mBXNUtOfsCFXeTsnBqCsx1KM=
|
||||
github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.7 h1:Do8ksLD4Nr3pA0x0hnLOLftZgkiTDvwPDShRTUxtXpE=
|
||||
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.7/go.mod h1:CJJ5VAbozOl0yEw7nHB9+7BXTJbIn6h7W+f6Gau5IP8=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
|
@ -21,6 +21,7 @@ import (
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime/v1alpha1/platform/metal"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime/v1alpha1/platform/openstack"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime/v1alpha1/platform/packet"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime/v1alpha1/platform/scaleway"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime/v1alpha1/platform/upcloud"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime/v1alpha1/platform/vmware"
|
||||
"github.com/talos-systems/talos/pkg/machinery/constants"
|
||||
@ -71,6 +72,8 @@ func newPlatform(platform string) (p runtime.Platform, err error) {
|
||||
p = &openstack.Openstack{}
|
||||
case "packet":
|
||||
p = &packet.Packet{}
|
||||
case "scaleway":
|
||||
p = &scaleway.Scaleway{}
|
||||
case "upcloud":
|
||||
p = &upcloud.UpCloud{}
|
||||
case "vmware":
|
||||
|
@ -0,0 +1,170 @@
|
||||
// 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 scaleway
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
|
||||
"github.com/scaleway/scaleway-sdk-go/api/instance/v1"
|
||||
"github.com/talos-systems/go-procfs/procfs"
|
||||
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime/v1alpha1/platform/errors"
|
||||
"github.com/talos-systems/talos/pkg/download"
|
||||
"github.com/talos-systems/talos/pkg/machinery/config"
|
||||
"github.com/talos-systems/talos/pkg/machinery/config/configloader"
|
||||
"github.com/talos-systems/talos/pkg/machinery/config/types/v1alpha1"
|
||||
)
|
||||
|
||||
const (
|
||||
// ScalewayMetadataEndpoint is the local Scaleway endpoint.
|
||||
ScalewayMetadataEndpoint = "http://169.254.42.42/conf?format=json"
|
||||
)
|
||||
|
||||
// Scaleway is the concrete type that implements the runtime.Platform interface.
|
||||
type Scaleway struct{}
|
||||
|
||||
// Name implements the runtime.Platform interface.
|
||||
func (s *Scaleway) Name() string {
|
||||
return "scaleway"
|
||||
}
|
||||
|
||||
// ConfigurationNetwork implements the network configuration interface.
|
||||
func (s *Scaleway) ConfigurationNetwork(metadataConfig *instance.Metadata, confProvider config.Provider) (config.Provider, error) {
|
||||
var machineConfig *v1alpha1.Config
|
||||
|
||||
machineConfig, ok := confProvider.(*v1alpha1.Config)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unable to determine machine config type")
|
||||
}
|
||||
|
||||
if machineConfig.MachineConfig == nil {
|
||||
machineConfig.MachineConfig = &v1alpha1.MachineConfig{}
|
||||
}
|
||||
|
||||
if machineConfig.MachineConfig.MachineNetwork == nil {
|
||||
machineConfig.MachineConfig.MachineNetwork = &v1alpha1.NetworkConfig{}
|
||||
}
|
||||
|
||||
iface := v1alpha1.Device{
|
||||
DeviceInterface: "eth0",
|
||||
DeviceDHCP: true,
|
||||
}
|
||||
|
||||
if metadataConfig.IPv6.Address != "" {
|
||||
iface.DeviceAddresses = append(iface.DeviceAddresses,
|
||||
fmt.Sprintf("%s/%s", metadataConfig.IPv6.Address, metadataConfig.IPv6.Netmask),
|
||||
)
|
||||
|
||||
iface.DeviceRoutes = []*v1alpha1.Route{
|
||||
{
|
||||
RouteNetwork: "::/0",
|
||||
RouteGateway: metadataConfig.IPv6.Gateway,
|
||||
RouteMetric: 1024,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
machineConfig.MachineConfig.MachineNetwork.NetworkInterfaces = append(
|
||||
machineConfig.MachineConfig.MachineNetwork.NetworkInterfaces,
|
||||
&iface,
|
||||
)
|
||||
|
||||
return confProvider, nil
|
||||
}
|
||||
|
||||
// Configuration implements the runtime.Platform interface.
|
||||
func (s *Scaleway) Configuration(ctx context.Context) ([]byte, error) {
|
||||
log.Printf("fetching scaleway instance config from: %q ", ScalewayMetadataEndpoint)
|
||||
|
||||
metadataDl, err := download.Download(ctx, ScalewayMetadataEndpoint,
|
||||
download.WithErrorOnNotFound(errors.ErrNoConfigSource),
|
||||
download.WithErrorOnEmptyResponse(errors.ErrNoConfigSource))
|
||||
if err != nil {
|
||||
return nil, errors.ErrNoConfigSource
|
||||
}
|
||||
|
||||
metadata := &instance.Metadata{}
|
||||
if err = json.Unmarshal(metadataDl, metadata); err != nil {
|
||||
return nil, errors.ErrNoConfigSource
|
||||
}
|
||||
|
||||
log.Printf("fetching machine config from scaleway metadata server")
|
||||
|
||||
instanceAPI := instance.NewMetadataAPI()
|
||||
|
||||
machineConfigDl, err := instanceAPI.GetUserData("cloud-init")
|
||||
if err != nil {
|
||||
return nil, errors.ErrNoConfigSource
|
||||
}
|
||||
|
||||
confProvider, err := configloader.NewFromBytes(machineConfigDl)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
confProvider, err = s.ConfigurationNetwork(metadata, confProvider)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return confProvider.Bytes()
|
||||
}
|
||||
|
||||
// Mode implements the runtime.Platform interface.
|
||||
func (s *Scaleway) Mode() runtime.Mode {
|
||||
return runtime.ModeCloud
|
||||
}
|
||||
|
||||
// Hostname implements the runtime.Platform interface.
|
||||
func (s *Scaleway) Hostname(ctx context.Context) (hostname []byte, err error) {
|
||||
log.Printf("fetching hostname from: %q", ScalewayMetadataEndpoint)
|
||||
|
||||
metadataDl, err := download.Download(ctx, ScalewayMetadataEndpoint,
|
||||
download.WithErrorOnNotFound(errors.ErrNoExternalIPs),
|
||||
download.WithErrorOnEmptyResponse(errors.ErrNoExternalIPs))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
metadata := &instance.Metadata{}
|
||||
if err = json.Unmarshal(metadataDl, metadata); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return []byte(metadata.Hostname), nil
|
||||
}
|
||||
|
||||
// ExternalIPs implements the runtime.Platform interface.
|
||||
func (s *Scaleway) ExternalIPs(ctx context.Context) (addrs []net.IP, err error) {
|
||||
log.Printf("fetching external IP from: %q", ScalewayMetadataEndpoint)
|
||||
|
||||
metadataDl, err := download.Download(ctx, ScalewayMetadataEndpoint,
|
||||
download.WithErrorOnNotFound(errors.ErrNoExternalIPs),
|
||||
download.WithErrorOnEmptyResponse(errors.ErrNoExternalIPs))
|
||||
if err != nil {
|
||||
return addrs, err
|
||||
}
|
||||
|
||||
metadata := &instance.Metadata{}
|
||||
if err = json.Unmarshal(metadataDl, metadata); err != nil {
|
||||
return addrs, err
|
||||
}
|
||||
|
||||
addrs = append(addrs, net.ParseIP(metadata.PublicIP.Address))
|
||||
|
||||
return addrs, err
|
||||
}
|
||||
|
||||
// KernelArgs implements the runtime.Platform interface.
|
||||
func (s *Scaleway) KernelArgs() procfs.Parameters {
|
||||
return []*procfs.Parameter{
|
||||
procfs.NewParameter("console").Append("tty1").Append("ttyS0"),
|
||||
}
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
// 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 scaleway_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/scaleway/scaleway-sdk-go/api/instance/v1"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime/v1alpha1/platform/scaleway"
|
||||
"github.com/talos-systems/talos/pkg/machinery/config/types/v1alpha1"
|
||||
)
|
||||
|
||||
type ConfigSuite struct {
|
||||
suite.Suite
|
||||
}
|
||||
|
||||
func (suite *ConfigSuite) TestNetworkConfig() {
|
||||
cfg := []byte(`{
|
||||
"id": "11111111-1111-1111-1111-111111111111",
|
||||
"name": "scw-talos",
|
||||
"commercial_type": "DEV1-S",
|
||||
"hostname": "scw-talos",
|
||||
"tags": [],
|
||||
"state_detail": "booted",
|
||||
"public_ip": {
|
||||
"id": "11111111-1111-1111-1111-111111111111",
|
||||
"address": "11.22.222.222",
|
||||
"dynamic": false
|
||||
},
|
||||
"private_ip": "10.00.222.222",
|
||||
"ipv6": {
|
||||
"address": "2001:111:222:3333::1",
|
||||
"gateway": "2001:111:222:3333::",
|
||||
"netmask": "64"
|
||||
}
|
||||
}`)
|
||||
|
||||
metadata := &instance.Metadata{}
|
||||
err := json.Unmarshal(cfg, &metadata)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
p := &scaleway.Scaleway{}
|
||||
|
||||
defaultMachineConfig := &v1alpha1.Config{}
|
||||
|
||||
machineConfig := &v1alpha1.Config{
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineNetwork: &v1alpha1.NetworkConfig{
|
||||
NetworkInterfaces: []*v1alpha1.Device{
|
||||
{
|
||||
DeviceInterface: "eth0",
|
||||
DeviceDHCP: true,
|
||||
DeviceAddresses: []string{"2001:111:222:3333::1/64"},
|
||||
DeviceRoutes: []*v1alpha1.Route{
|
||||
{
|
||||
RouteNetwork: "::/0",
|
||||
RouteGateway: "2001:111:222:3333::",
|
||||
RouteMetric: 1024,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
result, err := p.ConfigurationNetwork(metadata, defaultMachineConfig)
|
||||
|
||||
suite.Require().NoError(err)
|
||||
suite.Assert().Equal(machineConfig, result)
|
||||
}
|
||||
|
||||
func TestConfigSuite(t *testing.T) {
|
||||
suite.Run(t, new(ConfigSuite))
|
||||
}
|
6
website/content/docs/v0.13/Cloud Platforms/scaleway.md
Normal file
6
website/content/docs/v0.13/Cloud Platforms/scaleway.md
Normal file
@ -0,0 +1,6 @@
|
||||
---
|
||||
title: "Scaleway"
|
||||
description: "Creating a cluster via the CLI (scw) on scaleway.com."
|
||||
---
|
||||
|
||||
Talos is known to work on scaleway.com; however, it is currently undocumented.
|
Loading…
x
Reference in New Issue
Block a user