Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion cmd/config.cluster.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,17 @@ lets_encrypt:
email_id: will_be_overridden
account_private_key_path: /etc/swiftwave/letsencrypt/account.key
haproxy:
service_name: haproxy
service_name: swiftwave_haproxy
image: ghcr.io/swiftwave-org/haproxy:2.9
unix_socket_path: /etc/swiftwave/haproxy/dataplaneapi.sock # should end with dataplaneapi.sock
user: will_be_overridden
password: will_be_overridden
data_dir: /var/lib/swiftwave/haproxy
udp_proxy:
service_name: swiftwave_udp_proxy
image: ghcr.io/swiftwave-org/udpproxy:latest
unix_socket_path: /etc/swiftwave/udpproxy/api.sock
data_dir: /var/lib/swiftwave/udpproxy
postgresql:
auto_start_local_postgres: false # true or false
host: 127.0.0.1
Expand Down
7 changes: 6 additions & 1 deletion cmd/config.standalone.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,17 @@ lets_encrypt:
email_id: will_be_overridden
account_private_key_path: /etc/swiftwave/letsencrypt/account.key
haproxy:
service_name: haproxy
service_name: swiftwave_haproxy
image: ghcr.io/swiftwave-org/haproxy:2.9
unix_socket_path: /etc/swiftwave/haproxy/dataplaneapi.sock
user: will_be_overridden
password: will_be_overridden
data_dir: /var/lib/swiftwave/haproxy
udp_proxy:
service_name: swiftwave_udp_proxy
image: ghcr.io/swiftwave-org/udpproxy:latest
unix_socket_path: /etc/swiftwave/udpproxy/api.sock
data_dir: /var/lib/swiftwave/udpproxy
postgresql:
auto_start_local_postgres: true # true or false
host: 127.0.0.1
Expand Down
51 changes: 41 additions & 10 deletions cmd/haproxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package cmd
import (
"errors"
"fmt"
"github.com/swiftwave-org/swiftwave/swiftwave_service/core"
"github.com/swiftwave-org/swiftwave/system_config"
"io"
"net/http"
Expand Down Expand Up @@ -81,19 +82,49 @@ var haproxyStartCmd = &cobra.Command{
printError("Error : " + err.Error())
return
}
// Fetch hostname
hostname, err := os.Hostname()
if err != nil {
printError("failed to fetch hostname")
return
}
// Find out required ports
ports := []uint{80, 443}
dbClient, err := getDBClient()
if err == nil {
var ingressRules []core.IngressRule
tx := dbClient.Select("port").Where("port IS NOT NULL").Where("protocol != udp").Find(&ingressRules)
if tx.Error == nil {
if ingressRules != nil {
for _, ingressRule := range ingressRules {
ports = append(ports, ingressRule.Port)
}
}
}
}
// Start HAProxy service
dockerCmd := exec.Command("docker", "service", "create",
args1 := []string{
"service", "create",
"--name", systemConfig.HAProxyConfig.ServiceName,
"--mode", "global",
"--mode", "replicated",
"--replicas", "1",
"--network", systemConfig.ServiceConfig.NetworkName,
"--mount", "type=bind,source="+systemConfig.HAProxyConfig.DataDir+",destination=/etc/haproxy",
"--mount", "type=bind,source="+unixSocketMountDir+",destination=/home/",
"--publish", "mode=host,target=80,published=80",
"--publish", "mode=host,target=443,published=443",
"--env", "ADMIN_USER="+systemConfig.HAProxyConfig.User,
"--env", "ADMIN_PASSWORD="+systemConfig.HAProxyConfig.Password,
"--env", "SWIFTWAVE_SERVICE_ENDPOINT="+systemConfig.ServiceConfig.AddressOfCurrentNode+":"+strconv.Itoa(systemConfig.ServiceConfig.BindPort),
dockerImage)
"--constraint", "node.hostname==" + hostname,
"--mount", "type=bind,source=" + systemConfig.HAProxyConfig.DataDir + ",destination=/etc/haproxy",
"--mount", "type=bind,source=" + unixSocketMountDir + ",destination=/home/",
}
args2 := make([]string, 0, len(ports))
for _, port := range ports {
args2 = append(args2, "--publish", "mode=host,protocol=tcp,target="+strconv.Itoa(int(port))+",published="+strconv.Itoa(int(port)))
}
args3 := []string{
"--env", "ADMIN_USER=" + systemConfig.HAProxyConfig.User,
"--env", "ADMIN_PASSWORD=" + systemConfig.HAProxyConfig.Password,
"--env", "SWIFTWAVE_SERVICE_ENDPOINT=" + systemConfig.ServiceConfig.AddressOfCurrentNode + ":" + strconv.Itoa(systemConfig.ServiceConfig.BindPort),
dockerImage,
}
finalArgs := append(append(args1, args2...), args3...)
dockerCmd := exec.Command("docker", finalArgs...)
dockerCmd.Stdout = os.Stdout
dockerCmd.Stderr = os.Stderr
dockerCmd.Stdin = os.Stdin
Expand Down
1 change: 1 addition & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ func init() {
rootCmd.AddCommand(deleteUserCmd)
rootCmd.AddCommand(startCmd)
rootCmd.AddCommand(haproxyCmd)
rootCmd.AddCommand(udpProxyCmd)
rootCmd.AddCommand(postgresCmd)
rootCmd.AddCommand(generateTLSCommand)
rootCmd.AddCommand(dbMigrateCmd)
Expand Down
25 changes: 25 additions & 0 deletions cmd/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,19 @@ var setupCmd = &cobra.Command{
printSuccess("Created HAProxy unix socket directory [" + dir + "]")
}
}
// Create udp_proxy.unix_socket_path base directory if it doesn't exist
dir = systemConfig.UDPProxyConfig.UnixSocketPath
dir = filepath.Dir(dir)
if checkIfFolderExists(dir) {
printSuccess("UDP Proxy unix socket directory [" + dir + "] already exists")
} else {
err := createFolder(dir)
if err != nil {
printError("Failed to create UDP Proxy unix socket directory [" + dir + "]")
} else {
printSuccess("Created UDP Proxy unix socket directory [" + dir + "]")
}
}
// Create service.data_dir if it doesn't exist
dir = systemConfig.ServiceConfig.DataDir
if checkIfFolderExists(dir) {
Expand Down Expand Up @@ -87,6 +100,18 @@ var setupCmd = &cobra.Command{
printSuccess("Created HAProxy SSL directory [" + dir + "]")
}
}
// Create udp_proxy.data_dir if it doesn't exist
dir = systemConfig.UDPProxyConfig.DataDir
if checkIfFolderExists(dir) {
printSuccess("UDP Proxy data directory [" + dir + "] already exists")
} else {
err := createFolder(dir)
if err != nil {
printError("Failed to create UDP Proxy data directory [" + dir + "]")
} else {
printSuccess("Created UDP Proxy data directory [" + dir + "]")
}
}
// Create the swarm network if it doesn't exist
dockerManager, err := containermanger.NewDockerManager(systemConfig.ServiceConfig.DockerUnixSocketPath)
if err != nil {
Expand Down
48 changes: 48 additions & 0 deletions cmd/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ package cmd

import (
"github.com/spf13/cobra"
containermanger "github.com/swiftwave-org/swiftwave/container_manager"
swiftwave "github.com/swiftwave-org/swiftwave/swiftwave_service"
"os"
"os/exec"
)

var startCmd = &cobra.Command{
Expand All @@ -11,6 +14,51 @@ var startCmd = &cobra.Command{
Long: `Start swiftwave service`,
Run: func(cmd *cobra.Command, args []string) {
systemConfig.IsDevelopmentMode = isDevelopmentMode(cmd)
binaryPath, err := os.Executable()
if err != nil {
printError("Failed to get swiftwave binary path")
return
}
if !isHaproxyRunning() {
printInfo("Starting HAProxy service")
c := exec.Command(binaryPath, "haproxy", "start")
c.Stdout = os.Stdout
c.Stderr = os.Stderr
if err := c.Run(); err != nil {
printError("Failed to start HAProxy service")
return
}
}
if !isUDPProxyRunning() {
printInfo("Starting UDPProxy service")
c := exec.Command(binaryPath, "udpproxy", "start")
c.Stdout = os.Stdout
c.Stderr = os.Stderr
if err := c.Run(); err != nil {
printError("Failed to start UDPProxy service")
return
}
}
swiftwave.Start(systemConfig)
},
}

func isHaproxyRunning() bool {
dockerManager, err := containermanger.NewDockerManager(systemConfig.ServiceConfig.DockerUnixSocketPath)
if err != nil {
printError("Failed to connect to docker daemon")
return false
}
_, err = dockerManager.GetService(systemConfig.HAProxyConfig.ServiceName)
return err == nil
}

func isUDPProxyRunning() bool {
dockerManager, err := containermanger.NewDockerManager(systemConfig.ServiceConfig.DockerUnixSocketPath)
if err != nil {
printError("Failed to connect to docker daemon")
return false
}
_, err = dockerManager.GetService(systemConfig.UDPProxyConfig.ServiceName)
return err == nil
}
147 changes: 147 additions & 0 deletions cmd/udp_proxy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
package cmd

import (
"github.com/fatih/color"
"github.com/spf13/cobra"
containermanger "github.com/swiftwave-org/swiftwave/container_manager"
"github.com/swiftwave-org/swiftwave/swiftwave_service/core"
"os"
"os/exec"
"path/filepath"
"strconv"
)

func init() {
udpProxyCmd.AddCommand(udpProxyStatusCmd)
udpProxyCmd.AddCommand(udpProxyStartCmd)
udpProxyCmd.AddCommand(udpProxyStopCmd)
}

var udpProxyCmd = &cobra.Command{
Use: "udpproxy",
Short: "Manage UDP Proxy service",
Long: "Manage UDP Proxy service",
}

// Start command
var udpProxyStartCmd = &cobra.Command{
Use: "start",
Short: "Start UDP Proxy service",
Long: "Start UDP Proxy service",
Run: func(cmd *cobra.Command, args []string) {
// Delete socket file if it already exists
if checkIfFileExists(systemConfig.UDPProxyConfig.UnixSocketPath) {
err := os.Remove(systemConfig.UDPProxyConfig.UnixSocketPath)
if err != nil {
printError("Failed to remove socket file > " + systemConfig.UDPProxyConfig.UnixSocketPath)
return
}
}
dockerImage := systemConfig.UDPProxyConfig.DockerImage
// base directory for socket file
unixSocketMountDir := filepath.Dir(systemConfig.UDPProxyConfig.UnixSocketPath)
// Fetch hostname
hostname, err := os.Hostname()
if err != nil {
printError("failed to fetch hostname")
return
}
// Find out required ports
ports := []uint{}
dbClient, err := getDBClient()
if err == nil {
var ingressRules []core.IngressRule
tx := dbClient.Select("port").Where("port IS NOT NULL").Where("protocol = ?", "udp").Find(&ingressRules)
if tx.Error == nil {
if ingressRules != nil {
for _, ingressRule := range ingressRules {
ports = append(ports, ingressRule.Port)
}
}
}
}
// Start HAProxy service
args1 := []string{
"service", "create",
"--name", systemConfig.UDPProxyConfig.ServiceName,
"--mode", "replicated",
"--replicas", "1",
"--network", systemConfig.ServiceConfig.NetworkName,
"--constraint", "node.hostname==" + hostname,
"--mount", "type=bind,source=" + unixSocketMountDir + ",destination=/etc/udpproxy",
"--mount", "type=bind,source=" + systemConfig.UDPProxyConfig.DataDir + ",destination=/var/lib/udpproxy",
}
args2 := make([]string, 0, len(ports))
for _, port := range ports {
args2 = append(args2, "--publish", "mode=host,protocol=udp,target="+strconv.Itoa(int(port))+",published="+strconv.Itoa(int(port)))
}
args3 := []string{
"--env", "SWIFTWAVE_SERVICE_ENDPOINT=" + systemConfig.ServiceConfig.AddressOfCurrentNode + ":" + strconv.Itoa(systemConfig.ServiceConfig.BindPort),
dockerImage,
}
finalArgs := append(append(args1, args2...), args3...)
dockerCmd := exec.Command("docker", finalArgs...)
dockerCmd.Stdout = os.Stdout
dockerCmd.Stderr = os.Stderr
dockerCmd.Stdin = os.Stdin
err = dockerCmd.Run()
if err != nil {
printError("Failed to start UDP Proxy service")
return
}
printSuccess("Started UDP Proxy service")
},
}

// Stop command
var udpProxyStopCmd = &cobra.Command{
Use: "stop",
Short: "Stop UDP Proxy service",
Long: "Stop UDP Proxy service",
Run: func(cmd *cobra.Command, args []string) {
// Stop HAProxy service
dockerCmd := exec.Command("docker", "service", "rm", systemConfig.UDPProxyConfig.ServiceName)
err := dockerCmd.Run()
if err != nil {
printError("Failed to stop UDP Proxy service")
return
}
printSuccess("Stopped UDP Proxy service")
},
}

// Status command
var udpProxyStatusCmd = &cobra.Command{
Use: "status",
Short: "Show UDP Proxy service status",
Long: "Show UDP Proxy service status",
Run: func(cmd *cobra.Command, args []string) {
// Show HAProxy service status
dockerManager, err := containermanger.NewDockerManager(systemConfig.ServiceConfig.DockerUnixSocketPath)
if err != nil {
printError("Failed to connect to docker daemon")
return
}
serviceDetails, err := dockerManager.GetService(systemConfig.UDPProxyConfig.ServiceName)
if err != nil {
printError("UDP Proxy service is not running")
return
}
// Check realtime status of HAProxy service
info, err := dockerManager.RealtimeInfoService(systemConfig.UDPProxyConfig.ServiceName, false)
if err != nil {
printError("Failed to get realtime info of UDP Proxy service")
return
}
// Print service status
printSuccess("UDP Proxy service is running")
printInfo("Service : " + systemConfig.UDPProxyConfig.ServiceName)
printInfo("Image : " + removeHashFromDockerImageName(serviceDetails.Image))
printInfo("Running replicas : " + strconv.Itoa(info.RunningReplicas))
color.Green("\n--------------Node Names-------------")
for _, placementInfo := range info.PlacementInfos {
printInfo(placementInfo.NodeName + " (" + placementInfo.NodeID + ")")
}
color.Green("------------------------------------")
},
}
2 changes: 1 addition & 1 deletion container_manager/ports.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
func (m Manager) FetchPublishedHostPorts(service_name string) ([]int, error) {
serviceData, _, err := m.client.ServiceInspectWithRaw(m.ctx, service_name, types.ServiceInspectOptions{})
if err != nil {
return nil, errors.New("error getting swarm server version")
return nil, errors.New("error getting service details > " + service_name)
}
ports := []int{}
for _, port := range serviceData.Endpoint.Ports {
Expand Down
2 changes: 2 additions & 0 deletions container_manager/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,8 @@ func (m Manager) serviceToServiceSpec(service Service) swarm.ServiceSpec {
Mode: swarm.SeccompModeDefault,
},
},
CapabilityAdd: service.Capabilities,
Sysctls: service.Sysctls,
},
// Set network name
Networks: networkAttachmentConfigs,
Expand Down
2 changes: 2 additions & 0 deletions container_manager/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ type Service struct {
Image string `json:"image"`
Command []string `json:"command,omitempty"`
Env map[string]string `json:"env,omitempty"`
Capabilities []string `json:"capabilities,omitempty"`
Sysctls map[string]string `json:"sysctl,omitempty"`
VolumeMounts []VolumeMount `json:"volumemounts,omitempty"`
Networks []string `json:"networks,omitempty"`
DeploymentMode DeploymentMode `json:"deploymentmode"`
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ require (
github.com/hashicorp/go-set v0.1.14
github.com/labstack/echo-jwt/v4 v4.2.0
github.com/labstack/echo/v4 v4.11.4
github.com/lib/pq v1.10.9
github.com/mholt/acmez v1.2.0
github.com/rabbitmq/amqp091-go v1.9.0
github.com/spf13/cobra v1.8.0
Expand Down
Loading