// 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 docker implements Provisioner via docker. package docker import ( "bytes" "context" "os" "runtime" "github.com/docker/docker/client" "github.com/siderolabs/talos/pkg/machinery/config/types/v1alpha1" "github.com/siderolabs/talos/pkg/machinery/config/types/v1alpha1/generate" "github.com/siderolabs/talos/pkg/provision" ) type provisioner struct { client *client.Client } // NewProvisioner initializes docker provisioner. func NewProvisioner(ctx context.Context) (provision.Provisioner, error) { p := &provisioner{} var err error p.client, err = client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) if err != nil { return nil, err } return p, nil } // Close and release resources. func (p *provisioner) Close() error { if p.client != nil { return p.client.Close() } return nil } // GenOptions provides a list of additional config generate options. func (p *provisioner) GenOptions(networkReq provision.NetworkRequest) []generate.GenOption { nameservers := make([]string, 0, len(networkReq.Nameservers)) hasV4 := false hasV6 := false for _, subnet := range networkReq.CIDRs { if subnet.Addr().Is6() { hasV6 = true } else { hasV4 = true } } // filter nameservers by IPv4/IPv6 for i := range networkReq.Nameservers { if networkReq.Nameservers[i].Is6() && hasV6 { nameservers = append(nameservers, networkReq.Nameservers[i].String()) } else if networkReq.Nameservers[i].Is4() && hasV4 { nameservers = append(nameservers, networkReq.Nameservers[i].String()) } } return []generate.GenOption{ generate.WithNetworkOptions( v1alpha1.WithNetworkInterfaceIgnore("eth0"), v1alpha1.WithNetworkNameservers(nameservers...), ), } } // GetLoadBalancers returns internal/external loadbalancer endpoints. func (p *provisioner) GetLoadBalancers(networkReq provision.NetworkRequest) (internalEndpoint, externalEndpoint string) { // docker doesn't provide internal LB, so return empty string // external LB is always localhost for OS X where docker exposes ports switch runtime.GOOS { case "darwin", "windows": return "", "127.0.0.1" case "linux": if detectWSL() { return "", "127.0.0.1" } fallthrough default: return "", "" } } // UserDiskName not implemented for docker. func (p *provisioner) UserDiskName(index int) string { return "" } // GetFirstInterface returns first network interface name. func (p *provisioner) GetFirstInterface() string { return "eth0" } func detectWSL() bool { // "Official" way of detecting WSL https://github.com/Microsoft/WSL/issues/423#issuecomment-221627364 contents, err := os.ReadFile("/proc/sys/kernel/osrelease") if err == nil && (bytes.Contains(bytes.ToLower(contents), []byte("microsoft")) || bytes.Contains(bytes.ToLower(contents), []byte("wsl"))) { return true } return false }