Add support for creating network if it is missing
This commit is contained in:
parent
21d8384848
commit
91d5735ba8
|
@ -108,29 +108,48 @@ type SftpConfiguration struct {
|
||||||
ReadOnly bool `default:"false" yaml:"read_only"`
|
ReadOnly bool `default:"false" yaml:"read_only"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type dockerNetworkInterfaces struct {
|
||||||
|
V4 struct {
|
||||||
|
Subnet string `default:"172.18.0.0/16"`
|
||||||
|
Gateway string `default:"172.18.0.1"`
|
||||||
|
}
|
||||||
|
|
||||||
|
V6 struct {
|
||||||
|
Subnet string `default:"fdba:17c8:6c94::/64"`
|
||||||
|
Gateway string `default:"fdba:17c8:6c94::1011"`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type DockerNetworkConfiguration struct {
|
||||||
|
// The interface that should be used to create the network. Must not conflict
|
||||||
|
// with any other interfaces in use by Docker or on the system.
|
||||||
|
Interface string `default:"172.18.0.1"`
|
||||||
|
|
||||||
|
// The name of the network to use. If this network already exists it will not
|
||||||
|
// be created. If it is not found, a new network will be created using the interface
|
||||||
|
// defined.
|
||||||
|
Name string `default:"pterodactyl_nw"`
|
||||||
|
ISPN bool `default:"false" yaml:"ispn"`
|
||||||
|
Driver string `default:"bridge"`
|
||||||
|
IsInternal bool `default:"false" yaml:"is_internal"`
|
||||||
|
EnableICC bool `default:"true" yaml:"enable_icc"`
|
||||||
|
Interfaces *dockerNetworkInterfaces `yaml:"interfaces"`
|
||||||
|
}
|
||||||
|
|
||||||
// Defines the docker configuration used by the daemon when interacting with
|
// Defines the docker configuration used by the daemon when interacting with
|
||||||
// containers and networks on the system.
|
// containers and networks on the system.
|
||||||
type DockerConfiguration struct {
|
type DockerConfiguration struct {
|
||||||
// Network configuration that should be used when creating a new network
|
// Network configuration that should be used when creating a new network
|
||||||
// for containers run through the daemon.
|
// for containers run through the daemon.
|
||||||
Network struct {
|
Network *DockerNetworkConfiguration `yaml:"network"`
|
||||||
// The interface that should be used to create the network. Must not conflict
|
|
||||||
// with any other interfaces in use by Docker or on the system.
|
|
||||||
Interface string
|
|
||||||
|
|
||||||
// The name of the network to use. If this network already exists it will not
|
|
||||||
// be created. If it is not found, a new network will be created using the interface
|
|
||||||
// defined.
|
|
||||||
Name string
|
|
||||||
}
|
|
||||||
|
|
||||||
// If true, container images will be updated when a server starts if there
|
// If true, container images will be updated when a server starts if there
|
||||||
// is an update available. If false the daemon will not attempt updates and will
|
// is an update available. If false the daemon will not attempt updates and will
|
||||||
// defer to the host system to manage image updates.
|
// defer to the host system to manage image updates.
|
||||||
UpdateImages bool `yaml:"update_images"`
|
UpdateImages bool `default:"true" yaml:"update_images"`
|
||||||
|
|
||||||
// The location of the Docker socket.
|
// The location of the Docker socket.
|
||||||
Socket string
|
Socket string `default:"/var/run/docker.sock"`
|
||||||
|
|
||||||
// Defines the location of the timezone file on the host system that should
|
// Defines the location of the timezone file on the host system that should
|
||||||
// be mounted into the created containers so that they all use the same time.
|
// be mounted into the created containers so that they all use the same time.
|
||||||
|
@ -167,8 +186,11 @@ func (c *Configuration) SetDefaults() {
|
||||||
Username: "pterodactyl",
|
Username: "pterodactyl",
|
||||||
Data: "/srv/daemon-data",
|
Data: "/srv/daemon-data",
|
||||||
TimezonePath: "/etc/timezone",
|
TimezonePath: "/etc/timezone",
|
||||||
|
Sftp: &SftpConfiguration{},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defaults.SetDefaults(c.System.Sftp)
|
||||||
|
|
||||||
// By default the internal webserver should bind to all interfaces and
|
// By default the internal webserver should bind to all interfaces and
|
||||||
// be served on port 8080.
|
// be served on port 8080.
|
||||||
c.Api = &ApiConfiguration{
|
c.Api = &ApiConfiguration{
|
||||||
|
@ -195,11 +217,14 @@ func (c *Configuration) SetDefaults() {
|
||||||
c.Throttles.CheckInterval = 100
|
c.Throttles.CheckInterval = 100
|
||||||
|
|
||||||
// Configure the defaults for Docker connection and networks.
|
// Configure the defaults for Docker connection and networks.
|
||||||
c.Docker = &DockerConfiguration{}
|
c.Docker = &DockerConfiguration{
|
||||||
c.Docker.UpdateImages = true
|
Network: &DockerNetworkConfiguration{
|
||||||
c.Docker.Socket = "/var/run/docker.sock"
|
Interfaces: &dockerNetworkInterfaces{},
|
||||||
c.Docker.Network.Name = "pterodactyl_nw"
|
},
|
||||||
c.Docker.Network.Interface = "172.18.0.1"
|
}
|
||||||
|
defaults.SetDefaults(c.Docker)
|
||||||
|
defaults.SetDefaults(c.Docker.Network)
|
||||||
|
defaults.SetDefaults(c.Docker.Network.Interfaces)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reads the configuration from the provided file and returns the configuration
|
// Reads the configuration from the provided file and returns the configuration
|
||||||
|
@ -210,13 +235,8 @@ func ReadConfiguration(path string) (*Configuration, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
sftp :=new(SftpConfiguration)
|
|
||||||
defaults.SetDefaults(sftp)
|
|
||||||
|
|
||||||
c := new(Configuration)
|
c := new(Configuration)
|
||||||
c.System = new(SystemConfiguration)
|
c.SetDefaults()
|
||||||
c.System.Sftp = sftp
|
|
||||||
defaults.SetDefaults(c)
|
|
||||||
|
|
||||||
// Replace environment variables within the configuration file with their
|
// Replace environment variables within the configuration file with their
|
||||||
// values from the host system.
|
// values from the host system.
|
||||||
|
|
95
environment.go
Normal file
95
environment.go
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/docker/docker/api/types"
|
||||||
|
"github.com/docker/docker/api/types/network"
|
||||||
|
"github.com/docker/docker/client"
|
||||||
|
"github.com/pterodactyl/wings/config"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Configures the required network for the docker environment.
|
||||||
|
func ConfigureDockerEnvironment(c *config.DockerConfiguration) error {
|
||||||
|
// Ensure the required docker network exists on the system.
|
||||||
|
cli, err := client.NewClientWithOpts(client.FromEnv)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
resource, err := cli.NetworkInspect(context.Background(), c.Network.Name, types.NetworkInspectOptions{})
|
||||||
|
if err != nil && client.IsErrNotFound(err) {
|
||||||
|
zap.S().Infow("creating missing pterodactyl0 interface, this could take a few seconds...")
|
||||||
|
return createDockerNetwork(cli, c)
|
||||||
|
} else if err != nil {
|
||||||
|
zap.S().Fatalw("failed to create required docker network for containers", zap.Error(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
switch resource.Driver {
|
||||||
|
case "host":
|
||||||
|
c.Network.Interface = "127.0.0.1"
|
||||||
|
c.Network.ISPN = false
|
||||||
|
return nil
|
||||||
|
case "overlay":
|
||||||
|
case "weavemesh":
|
||||||
|
c.Network.Interface = ""
|
||||||
|
c.Network.ISPN = true
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
c.Network.ISPN = false
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a new network on the machine if one does not exist already.
|
||||||
|
func createDockerNetwork(cli *client.Client, c *config.DockerConfiguration) error {
|
||||||
|
_, err := cli.NetworkCreate(context.Background(), c.Network.Name, types.NetworkCreate{
|
||||||
|
Driver: c.Network.Driver,
|
||||||
|
EnableIPv6: true,
|
||||||
|
Internal: c.Network.IsInternal,
|
||||||
|
IPAM: &network.IPAM{
|
||||||
|
Config: []network.IPAMConfig{
|
||||||
|
{
|
||||||
|
Subnet: c.Network.Interfaces.V4.Subnet,
|
||||||
|
Gateway: c.Network.Interfaces.V4.Gateway,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Subnet: c.Network.Interfaces.V6.Subnet,
|
||||||
|
Gateway: c.Network.Interfaces.V6.Gateway,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Options: map[string]string{
|
||||||
|
"encryption": "false",
|
||||||
|
"com.docker.network.bridge.default_bridge": "false",
|
||||||
|
"com.docker.network.bridge.enable_icc": "true",
|
||||||
|
"com.docker.network.bridge.enable_ip_masquerade": "true",
|
||||||
|
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
|
||||||
|
"com.docker.network.bridge.name": "pterodactyl0",
|
||||||
|
"com.docker.network.driver.mtu": "1500",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch c.Network.Driver {
|
||||||
|
case "host":
|
||||||
|
c.Network.Interface = "127.0.0.1"
|
||||||
|
c.Network.ISPN = false
|
||||||
|
break
|
||||||
|
case "overlay":
|
||||||
|
case "weavemesh":
|
||||||
|
c.Network.Interface = ""
|
||||||
|
c.Network.ISPN = true
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
c.Network.Interface = c.Network.Interfaces.V4.Gateway
|
||||||
|
c.Network.ISPN = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
12
wings.go
12
wings.go
|
@ -12,6 +12,7 @@ import (
|
||||||
"github.com/remeh/sizedwaitgroup"
|
"github.com/remeh/sizedwaitgroup"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Entrypoint for the Wings application. Configures the logger and checks any
|
// Entrypoint for the Wings application. Configures the logger and checks any
|
||||||
|
@ -70,6 +71,15 @@ func main() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := ConfigureDockerEnvironment(c.Docker); err != nil {
|
||||||
|
zap.S().Fatalw("failed to configure docker environment", zap.Error(errors.WithStack(err)))
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := c.WriteToDisk(); err != nil {
|
||||||
|
zap.S().Errorw("failed to save configuration to disk", zap.Error(errors.WithStack(err)))
|
||||||
|
}
|
||||||
|
|
||||||
// Just for some nice log output.
|
// Just for some nice log output.
|
||||||
for _, s := range server.GetServers().All() {
|
for _, s := range server.GetServers().All() {
|
||||||
zap.S().Infow("loaded configuration for server", zap.String("server", s.Uuid))
|
zap.S().Infow("loaded configuration for server", zap.String("server", s.Uuid))
|
||||||
|
@ -143,7 +153,7 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
r := &Router{
|
r := &Router{
|
||||||
token: c.AuthenticationToken,
|
token: c.AuthenticationToken,
|
||||||
upgrader: websocket.Upgrader{
|
upgrader: websocket.Upgrader{
|
||||||
// Ensure that the websocket request is originating from the Panel itself,
|
// Ensure that the websocket request is originating from the Panel itself,
|
||||||
// and not some other location.
|
// and not some other location.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user