From 26fddb4c4e3579ea68361bad99749675e3df0e3f Mon Sep 17 00:00:00 2001 From: tanmoysrt <57363826+tanmoysrt@users.noreply.github.com> Date: Fri, 14 Mar 2025 14:32:42 +0530 Subject: [PATCH 1/7] refactor: comment problematic parts --- agent/cli.go | 6 +- .../analytics_service_token.operations.go | 16 - swiftwave_service/core/models.go | 10 +- swiftwave_service/core/pv.operations.go | 4 +- swiftwave_service/core/server.operations.go | 75 +-- swiftwave_service/core/types.go | 20 +- swiftwave_service/core/utils.go | 2 +- .../cronjob/server_status_monitor.go | 93 ++-- .../cronjob/sync_backup_proxy_server.go | 167 +++---- swiftwave_service/cronjob/sync_proxy_state.go | 472 +++++++++--------- .../graphql/graphql_object_mapper.go | 62 +-- swiftwave_service/graphql/helpers.go | 35 +- .../graphql/persistent_volume.resolvers.go | 48 +- swiftwave_service/graphql/server.resolvers.go | 159 +++--- swiftwave_service/manager/docker.go | 33 +- swiftwave_service/manager/haproxy.go | 23 +- swiftwave_service/manager/udpproxy.go | 27 +- swiftwave_service/stack_parser/utils.go | 142 +++--- .../process_application_delete_request.go | 99 ++-- .../process_application_deploy_request.go | 81 +-- ..._install_dependencies_on_server_request.go | 179 ++++--- .../worker/process_pv_backup_request.go | 162 +++--- .../worker/process_pv_restore_request.go | 88 ++-- .../worker/process_setup_proxy_request.go | 211 ++++---- .../worker/process_setup_server_request.go | 318 ++++++------ 25 files changed, 1231 insertions(+), 1301 deletions(-) diff --git a/agent/cli.go b/agent/cli.go index 0bc285573d..6c114dc37a 100644 --- a/agent/cli.go +++ b/agent/cli.go @@ -26,9 +26,9 @@ func init() { setupCmd.Flags().String("auth-token-hash", "", "Auth token hash") setupCmd.Flags().String("wireguard-private-key", "", "Wireguard private key") - setupCmd.Flags().String("wireguard-address", "", "Wireguard address") - setupCmd.Flags().String("docker-network-gateway-address", "", "Docker network gateway address") - setupCmd.Flags().String("docker-network-subnet", "", "Docker network subnet") + setupCmd.Flags().String("wireguard-address", "", "Wireguard address ip/cidr") + setupCmd.Flags().String("docker-network-gateway-address", "", "Docker network gateway address (ip)") + setupCmd.Flags().String("docker-network-subnet", "", "Docker network subnet ip/cidr") setupCmd.Flags().String("swiftwave-service-address", "", "Swiftwave service address ip:port") setupCmd.Flags().Bool("enable-haproxy", false, "Enable haproxy") diff --git a/swiftwave_service/core/analytics_service_token.operations.go b/swiftwave_service/core/analytics_service_token.operations.go index 1e3ad8b3ee..8a821c6ac8 100644 --- a/swiftwave_service/core/analytics_service_token.operations.go +++ b/swiftwave_service/core/analytics_service_token.operations.go @@ -9,22 +9,6 @@ import ( "gorm.io/gorm" ) -func ValidateAnalyticsServiceToken(ctx context.Context, db gorm.DB, id string, token string) (verified bool, serverHostName string, err error) { - // fetch token from database - var tokenData AnalyticsServiceToken - tx := db.Where("id = ? AND token = ?", id, token).First(&tokenData) - if tx.Error != nil { - return false, "", tx.Error - } - // fetch hostname from database - var server Server - tx = db.Select("host_name").Where("id = ?", tokenData.ServerID).First(&server) - if tx.Error != nil { - return false, "", tx.Error - } - return true, server.HostName, nil -} - func FetchAnalyticsServiceToken(ctx context.Context, db gorm.DB, serverId uint) (*AnalyticsServiceToken, error) { // check if token exists var tokenData AnalyticsServiceToken diff --git a/swiftwave_service/core/models.go b/swiftwave_service/core/models.go index b443116fb3..c4de9bb675 100644 --- a/swiftwave_service/core/models.go +++ b/swiftwave_service/core/models.go @@ -9,14 +9,10 @@ import ( // Server hold information about server type Server struct { ID uint `json:"id" gorm:"primaryKey"` - IP string `json:"ip" gorm:"unique"` - HostName string `json:"host_name"` - User string `json:"user"` - SSHPort int `json:"ssh_port" gorm:"default:22"` - MaintenanceMode bool `json:"maintenance_mode" gorm:"default:false"` + Name string `json:"name" gorm:"unique"` + PublicIP string `json:"public_ip" gorm:"not null"` + WireguardConfig WireguardConfig `json:"wireguard_config" gorm:"embedded;embeddedPrefix:wireguard_"` ScheduleDeployments bool `json:"schedule_deployments" gorm:"default:true"` - DockerUnixSocketPath string `json:"docker_unix_socket_path"` - SwarmMode SwarmMode `json:"swarm_mode"` ProxyConfig ProxyConfig `json:"proxy_config" gorm:"embedded;embeddedPrefix:proxy_"` Status ServerStatus `json:"status"` LastPing time.Time `json:"last_ping"` diff --git a/swiftwave_service/core/pv.operations.go b/swiftwave_service/core/pv.operations.go index 757da1cf39..cad8fda2d5 100644 --- a/swiftwave_service/core/pv.operations.go +++ b/swiftwave_service/core/pv.operations.go @@ -73,7 +73,7 @@ func (persistentVolume *PersistentVolume) Create(ctx context.Context, db gorm.DB // check if any server is offline for _, server := range servers { if server.Status == ServerOffline { - return fmt.Errorf("server %s is offline", server.IP) + return fmt.Errorf("server %s [%d] is offline", server.Name, server.ID) } } // create docker manager for all servers @@ -84,7 +84,7 @@ func (persistentVolume *PersistentVolume) Create(ctx context.Context, db gorm.DB if err != nil { return err } - dockerManagers[server.IP] = *dockerManager + dockerManagers[server.Name] = *dockerManager } } diff --git a/swiftwave_service/core/server.operations.go b/swiftwave_service/core/server.operations.go index f95efaecb5..d69ab82057 100644 --- a/swiftwave_service/core/server.operations.go +++ b/swiftwave_service/core/server.operations.go @@ -2,7 +2,6 @@ package core import ( "errors" - "fmt" "net" "time" @@ -11,12 +10,9 @@ import ( // CreateServer creates a new server in the database func CreateServer(db *gorm.DB, server *Server) error { - if server.IP == "" { + if server.PublicIP == "" { return errors.New("IP is required") } - if server.User == "" { - return errors.New("user is required") - } server.LastPing = time.Now() return db.Create(server).Error } @@ -27,24 +23,25 @@ func DeleteServer(db *gorm.DB, id uint) error { if err != nil { return err } - var applications []Application - - tx := db.Raw("SELECT name FROM applications WHERE preferred_server_hostnames @> ARRAY[?]", server.HostName).Scan(&applications) - if tx.Error != nil { - return fmt.Errorf("failed to fetch linked apps : %s", tx.Error.Error()) - } - if len(applications) > 0 { - applicationString := "" - for i, application := range applications { - applicationString = applicationString + application.Name - if i != len(applications)-1 { - applicationString = applicationString + ", " - } else { - applicationString = applicationString + " " - } - } - return fmt.Errorf("server is linked to application(s) : %s\nPlease remove this server from preferred servers of the application(s) before deleting the server", applicationString) - } + // TODO handle later + //var applications []Application + // + //tx := db.Raw("SELECT name FROM applications WHERE preferred_server_hostnames @> ARRAY[?]", server.HostName).Scan(&applications) + //if tx.Error != nil { + // return fmt.Errorf("failed to fetch linked apps : %s", tx.Error.Error()) + //} + //if len(applications) > 0 { + // applicationString := "" + // for i, application := range applications { + // applicationString = applicationString + application.Name + // if i != len(applications)-1 { + // applicationString = applicationString + ", " + // } else { + // applicationString = applicationString + " " + // } + // } + // return fmt.Errorf("server is linked to application(s) : %s\nPlease remove this server from preferred servers of the application(s) before deleting the server", applicationString) + //} return db.Delete(server).Error } @@ -134,24 +131,6 @@ func FetchAllOnlineServers(db *gorm.DB) ([]Server, error) { return servers, err } -// FetchSwarmManager fetches the swarm manager from the database -func FetchSwarmManager(db *gorm.DB) (Server, error) { - var server Server - // The reason behind using Order("RANDOM()") is - // if any swarm manager is down, the next one will be used - // so remove the possibility of complete failure - err := db.Where("status = ?", ServerOnline).Where("swarm_mode = ?", SwarmManager).Order("RANDOM()").First(&server).Error - return server, err -} - -// FetchSwarmManagerExceptServer fetches the swarm manager from the database except the given server -func FetchSwarmManagerExceptServer(db *gorm.DB, serverId uint) (Server, error) { - var swarmManager Server - err := db.Where("status = ?", ServerOnline).Where("swarm_mode = ?", SwarmManager).Where("id != ?", serverId).Order("RANDOM()").First(&swarmManager).Error - return swarmManager, err - -} - // FetchProxyActiveServers fetches all active servers from the database func FetchProxyActiveServers(db *gorm.DB) ([]Server, error) { isAnyActiveProxyServerOffline, err := IsAnyActiveProxyServerOffline(db) @@ -222,17 +201,3 @@ func MarkServerAsOffline(db *gorm.DB, server *Server) error { func ChangeProxyType(db *gorm.DB, server *Server, proxyType ProxyType) error { return db.Model(server).Update("proxy_type", proxyType).Error } - -// FetchDisabledDeploymentServerHostNames fetches the hostnames of all servers that are not in deployment mode -func FetchDisabledDeploymentServerHostNames(db *gorm.DB) ([]string, error) { - var disabledServers []Server - err := db.Where("schedule_deployments = ?", false).Select("host_name").Distinct("host_name").Find(&disabledServers).Error - if err != nil { - return nil, err - } - var hostNames []string - for _, server := range disabledServers { - hostNames = append(hostNames, server.HostName) - } - return hostNames, nil -} diff --git a/swiftwave_service/core/types.go b/swiftwave_service/core/types.go index 7bd63513e3..c68156aa0b 100644 --- a/swiftwave_service/core/types.go +++ b/swiftwave_service/core/types.go @@ -30,14 +30,6 @@ const ( ServerOffline ServerStatus = "offline" ) -// SwarmMode : mode of the swarm -type SwarmMode string - -const ( - SwarmManager SwarmMode = "manager" - SwarmWorker SwarmMode = "worker" -) - // ProxyType : type of the proxy type ProxyType string @@ -53,6 +45,18 @@ type ProxyConfig struct { Type ProxyType `json:"type" gorm:"default:'active'"` } +// ************************************************************************************* // +// Wireguard Configuration // +// ************************************************************************************* // + +// WireguardConfig represents the configuration structure for a WireGuard VPN connection. +type WireguardConfig struct { + PublicKey string `json:"public_key"` + PrivateKey string `json:"private_key"` + IP string `json:"ip"` + Port int `json:"port"` +} + // ************************************************************************************* // // Application Level Table // // ************************************************************************************* // diff --git a/swiftwave_service/core/utils.go b/swiftwave_service/core/utils.go index 83257ca151..b12b539552 100644 --- a/swiftwave_service/core/utils.go +++ b/swiftwave_service/core/utils.go @@ -58,7 +58,7 @@ func (domain *Domain) IsIPv4() bool { // IsLocalhost check if the domain is localhost func (server *Server) IsLocalhost() bool { // if `localhost` or `127.0.0.1` or `0.0.0.0` - return server.IP == "localhost" || server.IP == "127.0.0.1" || server.IP == "0.0.0.0" + return server.PublicIP == "localhost" || server.PublicIP == "127.0.0.1" || server.PublicIP == "0.0.0.0" } func (d *DockerProxyConfig) Equal(other *DockerProxyConfig) bool { diff --git a/swiftwave_service/cronjob/server_status_monitor.go b/swiftwave_service/cronjob/server_status_monitor.go index f0aa601da8..11f50a635d 100644 --- a/swiftwave_service/cronjob/server_status_monitor.go +++ b/swiftwave_service/cronjob/server_status_monitor.go @@ -1,12 +1,9 @@ package cronjob import ( - "bytes" - "strings" "sync" "time" - "github.com/swiftwave-org/swiftwave/pkg/ssh_toolkit" "github.com/swiftwave-org/swiftwave/swiftwave_service/core" "github.com/swiftwave-org/swiftwave/swiftwave_service/logger" ) @@ -48,52 +45,54 @@ func (m Manager) monitorServerStatus() { } func (m Manager) checkAndUpdateServerStatus(server core.Server) { - if m.isServerOnline(server) { - if server.Status != core.ServerOnline { - err := core.MarkServerAsOnline(&m.ServiceManager.DbClient, &server) - if err != nil { - logger.CronJobLoggerError.Println("DB Error : Failed to mark server as online >", server.HostName, err) - } else { - logger.CronJobLogger.Println("Server marked as online >", server.HostName) - } - } - } else { - if server.Status != core.ServerOffline { - err := core.MarkServerAsOffline(&m.ServiceManager.DbClient, &server) - if err != nil { - logger.CronJobLoggerError.Println("DB Error : Failed to mark server as offline >", server.HostName, err) - } else { - logger.CronJobLogger.Println("Server marked as offline >", server.HostName) - } - } else { - logger.CronJobLogger.Println("Server already offline >", server.HostName) - } - } + // TODO fix + //if m.isServerOnline(server) { + // if server.Status != core.ServerOnline { + // err := core.MarkServerAsOnline(&m.ServiceManager.DbClient, &server) + // if err != nil { + // logger.CronJobLoggerError.Println("DB Error : Failed to mark server as online >", server.HostName, err) + // } else { + // logger.CronJobLogger.Println("Server marked as online >", server.HostName) + // } + // } + //} else { + // if server.Status != core.ServerOffline { + // err := core.MarkServerAsOffline(&m.ServiceManager.DbClient, &server) + // if err != nil { + // logger.CronJobLoggerError.Println("DB Error : Failed to mark server as offline >", server.HostName, err) + // } else { + // logger.CronJobLogger.Println("Server marked as offline >", server.HostName) + // } + // } else { + // logger.CronJobLogger.Println("Server already offline >", server.HostName) + // } + //} } func (m Manager) isServerOnline(server core.Server) bool { - retries := 3 // try for 3 times before giving up - if server.Status == core.ServerOffline { - /** - * If server is offline, try only once - * Else, it will take total 30 seconds (3 retries * 10 seconds of default SSH timeout) - */ - retries = 1 - } - // try for 3 times - for i := 0; i < retries; i++ { - cmd := "echo ok" - stdoutBuf := new(bytes.Buffer) - stderrBuf := new(bytes.Buffer) - err := ssh_toolkit.ExecCommandOverSSHWithOptions(cmd, stdoutBuf, stderrBuf, 3, server.IP, server.SSHPort, server.User, m.Config.SystemConfig.SshPrivateKey, false) - if err != nil { - logger.CronJobLoggerError.Println("Error while checking if server is online", server.HostName, err.Error()) - time.Sleep(1 * time.Second) - continue - } - if strings.Compare(strings.TrimSpace(stdoutBuf.String()), "ok") == 0 { - return true - } - } + // TODO fix + //retries := 3 // try for 3 times before giving up + //if server.Status == core.ServerOffline { + // /** + // * If server is offline, try only once + // * Else, it will take total 30 seconds (3 retries * 10 seconds of default SSH timeout) + // */ + // retries = 1 + //} + //// try for 3 times + //for i := 0; i < retries; i++ { + // cmd := "echo ok" + // stdoutBuf := new(bytes.Buffer) + // stderrBuf := new(bytes.Buffer) + // err := ssh_toolkit.ExecCommandOverSSHWithOptions(cmd, stdoutBuf, stderrBuf, 3, server.IP, server.SSHPort, server.User, m.Config.SystemConfig.SshPrivateKey, false) + // if err != nil { + // logger.CronJobLoggerError.Println("Error while checking if server is online", server.HostName, err.Error()) + // time.Sleep(1 * time.Second) + // continue + // } + // if strings.Compare(strings.TrimSpace(stdoutBuf.String()), "ok") == 0 { + // return true + // } + //} return false } diff --git a/swiftwave_service/cronjob/sync_backup_proxy_server.go b/swiftwave_service/cronjob/sync_backup_proxy_server.go index a8582c3ce5..aa35822f9e 100644 --- a/swiftwave_service/cronjob/sync_backup_proxy_server.go +++ b/swiftwave_service/cronjob/sync_backup_proxy_server.go @@ -1,12 +1,8 @@ package cronjob import ( - "context" "time" - containermanger "github.com/swiftwave-org/swiftwave/pkg/container_manager" - "github.com/swiftwave-org/swiftwave/pkg/ssh_toolkit" - "github.com/swiftwave-org/swiftwave/swiftwave_service/core" "github.com/swiftwave-org/swiftwave/swiftwave_service/logger" ) @@ -19,85 +15,86 @@ func (m Manager) SyncBackupProxyServer() { } func (m Manager) syncBackupProxyServer() { - // Pick any active proxy server - activeProxyServer, err := core.FetchRandomActiveProxyServer(&m.ServiceManager.DbClient) - if err != nil { - logger.CronJobLoggerError.Println("Failed to fetch random active proxy server", err.Error()) - return - } - // copy haproxy config to local server - err = ssh_toolkit.CopyFolderFromRemoteServer(m.Config.LocalConfig.ServiceConfig.HAProxyDataDirectoryPath, m.Config.LocalConfig.ServiceConfig.HAProxyDataDirectoryPath, activeProxyServer.IP, activeProxyServer.SSHPort, activeProxyServer.User, m.Config.SystemConfig.SshPrivateKey) - if err != nil { - logger.CronJobLoggerError.Println("Failed to copy haproxy config from remote server", err.Error()) - return - } else { - logger.CronJobLogger.Println("Copied haproxy config from remote server", activeProxyServer.HostName) - } - // copy udpproxy config to local server - err = ssh_toolkit.CopyFolderFromRemoteServer(m.Config.LocalConfig.ServiceConfig.UDPProxyDataDirectoryPath, m.Config.LocalConfig.ServiceConfig.UDPProxyDataDirectoryPath, activeProxyServer.IP, activeProxyServer.SSHPort, activeProxyServer.User, m.Config.SystemConfig.SshPrivateKey) - if err != nil { - logger.CronJobLoggerError.Println("Failed to copy udpproxy config from remote server", err.Error()) - return - } else { - logger.CronJobLogger.Println("Copied udpproxy config from remote server", activeProxyServer.HostName) - } - // fetch all backup proxy servers - backupServers, err := core.FetchBackupProxyServers(&m.ServiceManager.DbClient) - if err != nil { - logger.CronJobLoggerError.Println("Failed to fetch backup proxy servers", err.Error()) - return - } - // copy haproxy config to all backup proxy servers - for _, backupServer := range backupServers { - err = ssh_toolkit.CopyFolderToRemoteServer(m.Config.LocalConfig.ServiceConfig.HAProxyDataDirectoryPath, m.Config.LocalConfig.ServiceConfig.HAProxyDataDirectoryPath, backupServer.IP, backupServer.SSHPort, backupServer.User, m.Config.SystemConfig.SshPrivateKey) - if err != nil { - logger.CronJobLoggerError.Println("Failed to copy haproxy config to remote server", backupServer.HostName, "\n", err.Error()) - } else { - logger.CronJobLogger.Println("Copied haproxy config to remote server", backupServer.HostName) - } - } - // copy udpproxy config to all backup proxy servers - for _, backupServer := range backupServers { - err = ssh_toolkit.CopyFolderToRemoteServer(m.Config.LocalConfig.ServiceConfig.UDPProxyDataDirectoryPath, m.Config.LocalConfig.ServiceConfig.UDPProxyDataDirectoryPath, backupServer.IP, backupServer.SSHPort, backupServer.User, m.Config.SystemConfig.SshPrivateKey) - if err != nil { - logger.CronJobLoggerError.Println("Failed to copy udpproxy config to remote server", backupServer.HostName, "\n", err.Error()) - } else { - logger.CronJobLogger.Println("Copied udpproxy config to remote server", backupServer.HostName) - } - } - - // reload proxies on backup server - for _, server := range backupServers { - // open ssh connection to backup proxy server for docker - conn, err := ssh_toolkit.NetConnOverSSH("unix", server.DockerUnixSocketPath, 5, server.IP, server.SSHPort, server.User, m.Config.SystemConfig.SshPrivateKey) - if err != nil { - logger.CronJobLoggerError.Println("Failed to open ssh connection to backup proxy server", server.HostName, "\n", err.Error()) - continue - } - dockerManager, err := containermanger.New(context.Background(), conn) - if err != nil { - logger.CronJobLoggerError.Println("Failed to create docker manager for backup proxy server", server.HostName, "\n", err.Error()) - continue - } - // remove udpproxy containers from all backup proxy servers, to trigger reload - err = dockerManager.RemoveServiceContainers(m.Config.LocalConfig.ServiceConfig.UDPProxyServiceName) - if err != nil { - logger.CronJobLoggerError.Println("Failed to remove udpproxy containers from backup proxy server", server.HostName, "\n", err.Error()) - } else { - logger.CronJobLogger.Println("Removed udpproxy containers from backup proxy server", server.HostName, " for a force reload") - } - // reload haproxy on backup proxy serverskill -SIGUSR2 1 - err = dockerManager.RunCommandInServiceContainers(m.Config.LocalConfig.ServiceConfig.HAProxyServiceName, []string{"kill", "-SIGUSR2", "1"}) - if err != nil { - logger.CronJobLoggerError.Println("Failed to reload haproxy on backup proxy server", server.HostName, "\n", err.Error()) - } else { - logger.CronJobLogger.Println("Reloaded haproxy on backup proxy server", server.HostName) - } - err = conn.Close() - if err != nil { - logger.CronJobLoggerError.Println("Failed to close ssh connection to backup proxy server", server.HostName, "\n", err.Error()) - } else { - logger.CronJobLogger.Println("Closed ssh connection to backup proxy server", server.HostName) - } - } + // TODO fix + //// Pick any active proxy server + //activeProxyServer, err := core.FetchRandomActiveProxyServer(&m.ServiceManager.DbClient) + //if err != nil { + // logger.CronJobLoggerError.Println("Failed to fetch random active proxy server", err.Error()) + // return + //} + //// copy haproxy config to local server + //err = ssh_toolkit.CopyFolderFromRemoteServer(m.Config.LocalConfig.ServiceConfig.HAProxyDataDirectoryPath, m.Config.LocalConfig.ServiceConfig.HAProxyDataDirectoryPath, activeProxyServer.IP, activeProxyServer.SSHPort, activeProxyServer.User, m.Config.SystemConfig.SshPrivateKey) + //if err != nil { + // logger.CronJobLoggerError.Println("Failed to copy haproxy config from remote server", err.Error()) + // return + //} else { + // logger.CronJobLogger.Println("Copied haproxy config from remote server", activeProxyServer.HostName) + //} + //// copy udpproxy config to local server + //err = ssh_toolkit.CopyFolderFromRemoteServer(m.Config.LocalConfig.ServiceConfig.UDPProxyDataDirectoryPath, m.Config.LocalConfig.ServiceConfig.UDPProxyDataDirectoryPath, activeProxyServer.IP, activeProxyServer.SSHPort, activeProxyServer.User, m.Config.SystemConfig.SshPrivateKey) + //if err != nil { + // logger.CronJobLoggerError.Println("Failed to copy udpproxy config from remote server", err.Error()) + // return + //} else { + // logger.CronJobLogger.Println("Copied udpproxy config from remote server", activeProxyServer.HostName) + //} + //// fetch all backup proxy servers + //backupServers, err := core.FetchBackupProxyServers(&m.ServiceManager.DbClient) + //if err != nil { + // logger.CronJobLoggerError.Println("Failed to fetch backup proxy servers", err.Error()) + // return + //} + //// copy haproxy config to all backup proxy servers + //for _, backupServer := range backupServers { + // err = ssh_toolkit.CopyFolderToRemoteServer(m.Config.LocalConfig.ServiceConfig.HAProxyDataDirectoryPath, m.Config.LocalConfig.ServiceConfig.HAProxyDataDirectoryPath, backupServer.IP, backupServer.SSHPort, backupServer.User, m.Config.SystemConfig.SshPrivateKey) + // if err != nil { + // logger.CronJobLoggerError.Println("Failed to copy haproxy config to remote server", backupServer.HostName, "\n", err.Error()) + // } else { + // logger.CronJobLogger.Println("Copied haproxy config to remote server", backupServer.HostName) + // } + //} + //// copy udpproxy config to all backup proxy servers + //for _, backupServer := range backupServers { + // err = ssh_toolkit.CopyFolderToRemoteServer(m.Config.LocalConfig.ServiceConfig.UDPProxyDataDirectoryPath, m.Config.LocalConfig.ServiceConfig.UDPProxyDataDirectoryPath, backupServer.IP, backupServer.SSHPort, backupServer.User, m.Config.SystemConfig.SshPrivateKey) + // if err != nil { + // logger.CronJobLoggerError.Println("Failed to copy udpproxy config to remote server", backupServer.HostName, "\n", err.Error()) + // } else { + // logger.CronJobLogger.Println("Copied udpproxy config to remote server", backupServer.HostName) + // } + //} + // + //// reload proxies on backup server + //for _, server := range backupServers { + // // open ssh connection to backup proxy server for docker + // conn, err := ssh_toolkit.NetConnOverSSH("unix", server.DockerUnixSocketPath, 5, server.IP, server.SSHPort, server.User, m.Config.SystemConfig.SshPrivateKey) + // if err != nil { + // logger.CronJobLoggerError.Println("Failed to open ssh connection to backup proxy server", server.HostName, "\n", err.Error()) + // continue + // } + // dockerManager, err := containermanger.New(context.Background(), conn) + // if err != nil { + // logger.CronJobLoggerError.Println("Failed to create docker manager for backup proxy server", server.HostName, "\n", err.Error()) + // continue + // } + // // remove udpproxy containers from all backup proxy servers, to trigger reload + // err = dockerManager.RemoveServiceContainers(m.Config.LocalConfig.ServiceConfig.UDPProxyServiceName) + // if err != nil { + // logger.CronJobLoggerError.Println("Failed to remove udpproxy containers from backup proxy server", server.HostName, "\n", err.Error()) + // } else { + // logger.CronJobLogger.Println("Removed udpproxy containers from backup proxy server", server.HostName, " for a force reload") + // } + // // reload haproxy on backup proxy serverskill -SIGUSR2 1 + // err = dockerManager.RunCommandInServiceContainers(m.Config.LocalConfig.ServiceConfig.HAProxyServiceName, []string{"kill", "-SIGUSR2", "1"}) + // if err != nil { + // logger.CronJobLoggerError.Println("Failed to reload haproxy on backup proxy server", server.HostName, "\n", err.Error()) + // } else { + // logger.CronJobLogger.Println("Reloaded haproxy on backup proxy server", server.HostName) + // } + // err = conn.Close() + // if err != nil { + // logger.CronJobLoggerError.Println("Failed to close ssh connection to backup proxy server", server.HostName, "\n", err.Error()) + // } else { + // logger.CronJobLogger.Println("Closed ssh connection to backup proxy server", server.HostName) + // } + //} } diff --git a/swiftwave_service/cronjob/sync_proxy_state.go b/swiftwave_service/cronjob/sync_proxy_state.go index 3a0944a075..4cb86a6443 100644 --- a/swiftwave_service/cronjob/sync_proxy_state.go +++ b/swiftwave_service/cronjob/sync_proxy_state.go @@ -1,15 +1,10 @@ package cronjob import ( - "context" - "fmt" "strings" "time" "github.com/docker/docker/api/types/swarm" - containermanger "github.com/swiftwave-org/swiftwave/pkg/container_manager" - "github.com/swiftwave-org/swiftwave/pkg/ssh_toolkit" - "github.com/swiftwave-org/swiftwave/swiftwave_service/core" "github.com/swiftwave-org/swiftwave/swiftwave_service/logger" ) @@ -22,239 +17,240 @@ func (m Manager) SyncProxy() { } func (m Manager) syncProxy() { - // create context - ctx := context.Background() - // fetch all servers hostnames - servers, err := core.FetchAllServers(&m.ServiceManager.DbClient) - if err != nil { - logger.CronJobLoggerError.Println("Failed to fetch all proxy servers", err.Error()) - return - } - - // fetch a swarm manager - swarmManager, err := core.FetchSwarmManager(&m.ServiceManager.DbClient) - if err != nil { - logger.CronJobLoggerError.Println("Failed to fetch swarm manager", err.Error()) - return - } - // create conn over ssh - conn, err := ssh_toolkit.NetConnOverSSH("unix", swarmManager.DockerUnixSocketPath, 5, swarmManager.IP, swarmManager.SSHPort, "root", m.Config.SystemConfig.SshPrivateKey) - if err != nil { - logger.CronJobLoggerError.Println("Failed to create conn over ssh", err.Error()) - return - } - defer func() { - err := conn.Close() - if err != nil { - logger.CronJobLoggerError.Println("Failed to close conn", err.Error()) - } - }() - // create docker client - dockerClient, err := containermanger.New(ctx, conn) - if err != nil { - logger.CronJobLoggerError.Println("Failed to create docker client", err.Error()) - return - } - if len(servers) == 0 { - // delete haproxy and udpproxy services - err = dockerClient.RemoveService(m.Config.LocalConfig.ServiceConfig.HAProxyServiceName) - if err != nil { - logger.CronJobLoggerError.Println("Failed to remove haproxy service", err.Error()) - } else { - logger.CronJobLogger.Println("Removed haproxy service") - } - err = dockerClient.RemoveService(m.Config.LocalConfig.ServiceConfig.UDPProxyServiceName) - if err != nil { - logger.CronJobLoggerError.Println("Failed to remove udpproxy service", err.Error()) - } else { - logger.CronJobLogger.Println("Removed udpproxy service") - } - return - } - // prepare placement constraints - var placementConstraints []string - for _, proxyServer := range servers { - if !proxyServer.ProxyConfig.Enabled { - placementConstraints = append(placementConstraints, "node.hostname!="+proxyServer.HostName) - } - } - // haproxy - haProxyEnvironmentVariables := map[string]string{ - "ADMIN_USERNAME": m.Config.SystemConfig.HAProxyConfig.Username, - "ADMIN_PASSWORD": m.Config.SystemConfig.HAProxyConfig.Password, - "SWIFTWAVE_SERVICE_ENDPOINT": fmt.Sprintf("%s:%d", m.Config.LocalConfig.ManagementNodeAddressConsideringTunnelling(), m.Config.LocalConfig.ManagementNodePortConsideringTunnelling()), - "SWIFTWAVE_SERVICE_ADDRESS": m.Config.LocalConfig.ManagementNodeAddressConsideringTunnelling(), - } - // Try to fetch info about haproxy service - haproxyService, err := dockerClient.GetService(m.Config.LocalConfig.ServiceConfig.HAProxyServiceName) - if err != nil { - // create haproxy service - err = dockerClient.CreateService(containermanger.Service{ - Name: m.Config.LocalConfig.ServiceConfig.HAProxyServiceName, - Image: m.Config.SystemConfig.HAProxyConfig.Image, - DeploymentMode: containermanger.DeploymentModeGlobal, - PlacementConstraints: placementConstraints, - Env: haProxyEnvironmentVariables, - Networks: []string{m.Config.SystemConfig.NetworkName}, - VolumeBinds: []containermanger.VolumeBind{ - { - Source: m.Config.LocalConfig.ServiceConfig.HAProxyDataDirectoryPath, - Target: "/etc/haproxy", - }, - { - Source: m.Config.LocalConfig.ServiceConfig.HAProxyUnixSocketDirectory, - Target: "/home", - }, - }, - }, "", "", true) - if err != nil { - logger.CronJobLoggerError.Println("Failed to create haproxy service", err.Error()) - } else { - logger.CronJobLogger.Println("Created haproxy service") - } - } else { - // check if env variables, image or placement constraints have changed - if !isSameMap(haproxyService.Env, haProxyEnvironmentVariables) || strings.Compare(getImageNameFromImageWithSHA(haproxyService.Image), m.Config.SystemConfig.HAProxyConfig.Image) != 0 || !isListSame(haproxyService.PlacementConstraints, placementConstraints) { - logger.CronJobLogger.Println("Updating haproxy service") - // update haproxy service - haproxyService.Env = haProxyEnvironmentVariables - haproxyService.Image = m.Config.SystemConfig.HAProxyConfig.Image - haproxyService.PlacementConstraints = placementConstraints - err = dockerClient.UpdateService(haproxyService, "", "", true) - if err != nil { - logger.CronJobLoggerError.Println("Failed to update haproxy service", err.Error()) - } else { - logger.CronJobLogger.Println("Updated haproxy service") - } - } else { - logger.CronJobLogger.Println("No change in haproxy service") - } - } - // udp proxy - udpProxyEnvironmentVariables := map[string]string{ - "SWIFTWAVE_SERVICE_ENDPOINT": fmt.Sprintf("%s:%d", m.Config.LocalConfig.ManagementNodeAddressConsideringTunnelling(), m.Config.LocalConfig.ManagementNodePortConsideringTunnelling()), - } - // Try to fetch info about udpproxy service - udpproxyService, err := dockerClient.GetService(m.Config.LocalConfig.ServiceConfig.UDPProxyServiceName) - if err != nil { - // create udpproxy service - err = dockerClient.CreateService(containermanger.Service{ - Name: m.Config.LocalConfig.ServiceConfig.UDPProxyServiceName, - Image: m.Config.SystemConfig.UDPProxyConfig.Image, - DeploymentMode: containermanger.DeploymentModeGlobal, - PlacementConstraints: placementConstraints, - Env: udpProxyEnvironmentVariables, - Networks: []string{m.Config.SystemConfig.NetworkName}, - VolumeBinds: []containermanger.VolumeBind{ - { - Source: m.Config.LocalConfig.ServiceConfig.UDPProxyUnixSocketDirectory, - Target: "/etc/udpproxy", - }, - { - Source: m.Config.LocalConfig.ServiceConfig.UDPProxyDataDirectoryPath, - Target: "/var/lib/udpproxy", - }, - }, - }, "", "", true) - if err != nil { - logger.CronJobLoggerError.Println("Failed to create udpproxy service", err.Error()) - } else { - logger.CronJobLogger.Println("Created udpproxy service") - } - } else { - // check if env variables, image or placement constraints have changed - if !isSameMap(udpproxyService.Env, udpProxyEnvironmentVariables) || strings.Compare(getImageNameFromImageWithSHA(udpproxyService.Image), m.Config.SystemConfig.UDPProxyConfig.Image) != 0 || !isListSame(udpproxyService.PlacementConstraints, placementConstraints) { - // update udpproxy service - udpproxyService.Env = udpProxyEnvironmentVariables - udpproxyService.Image = m.Config.SystemConfig.UDPProxyConfig.Image - udpproxyService.PlacementConstraints = placementConstraints - err = dockerClient.UpdateService(udpproxyService, "", "", true) - if err != nil { - logger.CronJobLoggerError.Println("Failed to update udpproxy service", err.Error()) - } else { - logger.CronJobLogger.Println("Updated udpproxy service") - } - } else { - logger.CronJobLogger.Println("No change in udpproxy service") - } - } - - // PORT EXPOSER - - // fetch all exposed tcp ports - tcpPorts, err := core.FetchAllExposedTCPPorts(ctx, m.ServiceManager.DbClient) - if err != nil { - logger.CronJobLoggerError.Println("Failed to fetch all exposed tcp ports", err.Error()) - return - } - // add port 80 and 443 - tcpPorts = append(tcpPorts, 80, 443) - tcpPorts = removeDuplicatesInt(tcpPorts) - tcpPortsRule := make([]swarm.PortConfig, 0) - for _, port := range tcpPorts { - tcpPortsRule = append(tcpPortsRule, swarm.PortConfig{ - Protocol: swarm.PortConfigProtocolTCP, - PublishMode: swarm.PortConfigPublishModeHost, - TargetPort: uint32(port), - PublishedPort: uint32(port), - }) - } - // fetch all exposed udp ports - udpPorts, err := core.FetchAllExposedUDPPorts(ctx, m.ServiceManager.DbClient) - udpPorts = removeDuplicatesInt(udpPorts) - if err != nil { - logger.CronJobLoggerError.Println("Failed to fetch all exposed udp ports", err.Error()) - return - } - udpPortsRule := make([]swarm.PortConfig, 0) - for _, port := range udpPorts { - udpPortsRule = append(udpPortsRule, swarm.PortConfig{ - Protocol: swarm.PortConfigProtocolUDP, - PublishMode: swarm.PortConfigPublishModeHost, - TargetPort: uint32(port), - PublishedPort: uint32(port), - }) - } - - // fetch exposed tcp ports of haproxy service - existingTcpPortRules, err := dockerClient.FetchPublishedPortRules(m.Config.LocalConfig.ServiceConfig.HAProxyServiceName) - if err != nil { - logger.CronJobLoggerError.Println("Failed to fetch exposed tcp ports of haproxy service", err.Error()) - return - } else { - // check if exposed tcp ports are changed - if !isPortListSame(existingTcpPortRules, tcpPortsRule) { - // update exposed tcp ports - err = dockerClient.UpdatePublishedHostPorts(m.Config.LocalConfig.ServiceConfig.HAProxyServiceName, tcpPortsRule) - if err != nil { - logger.CronJobLoggerError.Println("Failed to update exposed tcp ports of haproxy service", err.Error()) - } else { - logger.CronJobLogger.Println("Updated exposed tcp ports of haproxy service") - } - } else { - logger.CronJobLogger.Println("No change in exposed tcp ports of haproxy service") - } - } - - // fetch exposed udp ports of udpproxy service - existingUdpPortRules, err := dockerClient.FetchPublishedPortRules(m.Config.LocalConfig.ServiceConfig.UDPProxyServiceName) - if err != nil { - logger.CronJobLoggerError.Println("Failed to fetch exposed udp ports of udpproxy service", err.Error()) - return - } else { - // check if exposed udp ports are changed - if !isPortListSame(existingUdpPortRules, udpPortsRule) { - // update exposed udp ports - err = dockerClient.UpdatePublishedHostPorts(m.Config.LocalConfig.ServiceConfig.UDPProxyServiceName, udpPortsRule) - if err != nil { - logger.CronJobLoggerError.Println("Failed to update exposed udp ports of udpproxy service", err.Error()) - } else { - logger.CronJobLogger.Println("Updated exposed udp ports of udpproxy service") - } - } else { - logger.CronJobLogger.Println("No change in exposed udp ports of udpproxy service") - } - } + // TODO fix + //// create context + //ctx := context.Background() + //// fetch all servers hostnames + //servers, err := core.FetchAllServers(&m.ServiceManager.DbClient) + //if err != nil { + // logger.CronJobLoggerError.Println("Failed to fetch all proxy servers", err.Error()) + // return + //} + // + //// fetch a swarm manager + //swarmManager, err := core.FetchSwarmManager(&m.ServiceManager.DbClient) + //if err != nil { + // logger.CronJobLoggerError.Println("Failed to fetch swarm manager", err.Error()) + // return + //} + //// create conn over ssh + //conn, err := ssh_toolkit.NetConnOverSSH("unix", swarmManager.DockerUnixSocketPath, 5, swarmManager.IP, swarmManager.SSHPort, "root", m.Config.SystemConfig.SshPrivateKey) + //if err != nil { + // logger.CronJobLoggerError.Println("Failed to create conn over ssh", err.Error()) + // return + //} + //defer func() { + // err := conn.Close() + // if err != nil { + // logger.CronJobLoggerError.Println("Failed to close conn", err.Error()) + // } + //}() + //// create docker client + //dockerClient, err := containermanger.New(ctx, conn) + //if err != nil { + // logger.CronJobLoggerError.Println("Failed to create docker client", err.Error()) + // return + //} + //if len(servers) == 0 { + // // delete haproxy and udpproxy services + // err = dockerClient.RemoveService(m.Config.LocalConfig.ServiceConfig.HAProxyServiceName) + // if err != nil { + // logger.CronJobLoggerError.Println("Failed to remove haproxy service", err.Error()) + // } else { + // logger.CronJobLogger.Println("Removed haproxy service") + // } + // err = dockerClient.RemoveService(m.Config.LocalConfig.ServiceConfig.UDPProxyServiceName) + // if err != nil { + // logger.CronJobLoggerError.Println("Failed to remove udpproxy service", err.Error()) + // } else { + // logger.CronJobLogger.Println("Removed udpproxy service") + // } + // return + //} + //// prepare placement constraints + //var placementConstraints []string + //for _, proxyServer := range servers { + // if !proxyServer.ProxyConfig.Enabled { + // placementConstraints = append(placementConstraints, "node.hostname!="+proxyServer.HostName) + // } + //} + //// haproxy + //haProxyEnvironmentVariables := map[string]string{ + // "ADMIN_USERNAME": m.Config.SystemConfig.HAProxyConfig.Username, + // "ADMIN_PASSWORD": m.Config.SystemConfig.HAProxyConfig.Password, + // "SWIFTWAVE_SERVICE_ENDPOINT": fmt.Sprintf("%s:%d", m.Config.LocalConfig.ManagementNodeAddressConsideringTunnelling(), m.Config.LocalConfig.ManagementNodePortConsideringTunnelling()), + // "SWIFTWAVE_SERVICE_ADDRESS": m.Config.LocalConfig.ManagementNodeAddressConsideringTunnelling(), + //} + //// Try to fetch info about haproxy service + //haproxyService, err := dockerClient.GetService(m.Config.LocalConfig.ServiceConfig.HAProxyServiceName) + //if err != nil { + // // create haproxy service + // err = dockerClient.CreateService(containermanger.Service{ + // Name: m.Config.LocalConfig.ServiceConfig.HAProxyServiceName, + // Image: m.Config.SystemConfig.HAProxyConfig.Image, + // DeploymentMode: containermanger.DeploymentModeGlobal, + // PlacementConstraints: placementConstraints, + // Env: haProxyEnvironmentVariables, + // Networks: []string{m.Config.SystemConfig.NetworkName}, + // VolumeBinds: []containermanger.VolumeBind{ + // { + // Source: m.Config.LocalConfig.ServiceConfig.HAProxyDataDirectoryPath, + // Target: "/etc/haproxy", + // }, + // { + // Source: m.Config.LocalConfig.ServiceConfig.HAProxyUnixSocketDirectory, + // Target: "/home", + // }, + // }, + // }, "", "", true) + // if err != nil { + // logger.CronJobLoggerError.Println("Failed to create haproxy service", err.Error()) + // } else { + // logger.CronJobLogger.Println("Created haproxy service") + // } + //} else { + // // check if env variables, image or placement constraints have changed + // if !isSameMap(haproxyService.Env, haProxyEnvironmentVariables) || strings.Compare(getImageNameFromImageWithSHA(haproxyService.Image), m.Config.SystemConfig.HAProxyConfig.Image) != 0 || !isListSame(haproxyService.PlacementConstraints, placementConstraints) { + // logger.CronJobLogger.Println("Updating haproxy service") + // // update haproxy service + // haproxyService.Env = haProxyEnvironmentVariables + // haproxyService.Image = m.Config.SystemConfig.HAProxyConfig.Image + // haproxyService.PlacementConstraints = placementConstraints + // err = dockerClient.UpdateService(haproxyService, "", "", true) + // if err != nil { + // logger.CronJobLoggerError.Println("Failed to update haproxy service", err.Error()) + // } else { + // logger.CronJobLogger.Println("Updated haproxy service") + // } + // } else { + // logger.CronJobLogger.Println("No change in haproxy service") + // } + //} + //// udp proxy + //udpProxyEnvironmentVariables := map[string]string{ + // "SWIFTWAVE_SERVICE_ENDPOINT": fmt.Sprintf("%s:%d", m.Config.LocalConfig.ManagementNodeAddressConsideringTunnelling(), m.Config.LocalConfig.ManagementNodePortConsideringTunnelling()), + //} + //// Try to fetch info about udpproxy service + //udpproxyService, err := dockerClient.GetService(m.Config.LocalConfig.ServiceConfig.UDPProxyServiceName) + //if err != nil { + // // create udpproxy service + // err = dockerClient.CreateService(containermanger.Service{ + // Name: m.Config.LocalConfig.ServiceConfig.UDPProxyServiceName, + // Image: m.Config.SystemConfig.UDPProxyConfig.Image, + // DeploymentMode: containermanger.DeploymentModeGlobal, + // PlacementConstraints: placementConstraints, + // Env: udpProxyEnvironmentVariables, + // Networks: []string{m.Config.SystemConfig.NetworkName}, + // VolumeBinds: []containermanger.VolumeBind{ + // { + // Source: m.Config.LocalConfig.ServiceConfig.UDPProxyUnixSocketDirectory, + // Target: "/etc/udpproxy", + // }, + // { + // Source: m.Config.LocalConfig.ServiceConfig.UDPProxyDataDirectoryPath, + // Target: "/var/lib/udpproxy", + // }, + // }, + // }, "", "", true) + // if err != nil { + // logger.CronJobLoggerError.Println("Failed to create udpproxy service", err.Error()) + // } else { + // logger.CronJobLogger.Println("Created udpproxy service") + // } + //} else { + // // check if env variables, image or placement constraints have changed + // if !isSameMap(udpproxyService.Env, udpProxyEnvironmentVariables) || strings.Compare(getImageNameFromImageWithSHA(udpproxyService.Image), m.Config.SystemConfig.UDPProxyConfig.Image) != 0 || !isListSame(udpproxyService.PlacementConstraints, placementConstraints) { + // // update udpproxy service + // udpproxyService.Env = udpProxyEnvironmentVariables + // udpproxyService.Image = m.Config.SystemConfig.UDPProxyConfig.Image + // udpproxyService.PlacementConstraints = placementConstraints + // err = dockerClient.UpdateService(udpproxyService, "", "", true) + // if err != nil { + // logger.CronJobLoggerError.Println("Failed to update udpproxy service", err.Error()) + // } else { + // logger.CronJobLogger.Println("Updated udpproxy service") + // } + // } else { + // logger.CronJobLogger.Println("No change in udpproxy service") + // } + //} + // + //// PORT EXPOSER + // + //// fetch all exposed tcp ports + //tcpPorts, err := core.FetchAllExposedTCPPorts(ctx, m.ServiceManager.DbClient) + //if err != nil { + // logger.CronJobLoggerError.Println("Failed to fetch all exposed tcp ports", err.Error()) + // return + //} + //// add port 80 and 443 + //tcpPorts = append(tcpPorts, 80, 443) + //tcpPorts = removeDuplicatesInt(tcpPorts) + //tcpPortsRule := make([]swarm.PortConfig, 0) + //for _, port := range tcpPorts { + // tcpPortsRule = append(tcpPortsRule, swarm.PortConfig{ + // Protocol: swarm.PortConfigProtocolTCP, + // PublishMode: swarm.PortConfigPublishModeHost, + // TargetPort: uint32(port), + // PublishedPort: uint32(port), + // }) + //} + //// fetch all exposed udp ports + //udpPorts, err := core.FetchAllExposedUDPPorts(ctx, m.ServiceManager.DbClient) + //udpPorts = removeDuplicatesInt(udpPorts) + //if err != nil { + // logger.CronJobLoggerError.Println("Failed to fetch all exposed udp ports", err.Error()) + // return + //} + //udpPortsRule := make([]swarm.PortConfig, 0) + //for _, port := range udpPorts { + // udpPortsRule = append(udpPortsRule, swarm.PortConfig{ + // Protocol: swarm.PortConfigProtocolUDP, + // PublishMode: swarm.PortConfigPublishModeHost, + // TargetPort: uint32(port), + // PublishedPort: uint32(port), + // }) + //} + // + //// fetch exposed tcp ports of haproxy service + //existingTcpPortRules, err := dockerClient.FetchPublishedPortRules(m.Config.LocalConfig.ServiceConfig.HAProxyServiceName) + //if err != nil { + // logger.CronJobLoggerError.Println("Failed to fetch exposed tcp ports of haproxy service", err.Error()) + // return + //} else { + // // check if exposed tcp ports are changed + // if !isPortListSame(existingTcpPortRules, tcpPortsRule) { + // // update exposed tcp ports + // err = dockerClient.UpdatePublishedHostPorts(m.Config.LocalConfig.ServiceConfig.HAProxyServiceName, tcpPortsRule) + // if err != nil { + // logger.CronJobLoggerError.Println("Failed to update exposed tcp ports of haproxy service", err.Error()) + // } else { + // logger.CronJobLogger.Println("Updated exposed tcp ports of haproxy service") + // } + // } else { + // logger.CronJobLogger.Println("No change in exposed tcp ports of haproxy service") + // } + //} + // + //// fetch exposed udp ports of udpproxy service + //existingUdpPortRules, err := dockerClient.FetchPublishedPortRules(m.Config.LocalConfig.ServiceConfig.UDPProxyServiceName) + //if err != nil { + // logger.CronJobLoggerError.Println("Failed to fetch exposed udp ports of udpproxy service", err.Error()) + // return + //} else { + // // check if exposed udp ports are changed + // if !isPortListSame(existingUdpPortRules, udpPortsRule) { + // // update exposed udp ports + // err = dockerClient.UpdatePublishedHostPorts(m.Config.LocalConfig.ServiceConfig.UDPProxyServiceName, udpPortsRule) + // if err != nil { + // logger.CronJobLoggerError.Println("Failed to update exposed udp ports of udpproxy service", err.Error()) + // } else { + // logger.CronJobLogger.Println("Updated exposed udp ports of udpproxy service") + // } + // } else { + // logger.CronJobLogger.Println("No change in exposed udp ports of udpproxy service") + // } + //} } diff --git a/swiftwave_service/graphql/graphql_object_mapper.go b/swiftwave_service/graphql/graphql_object_mapper.go index be800658a3..3f212d3dab 100644 --- a/swiftwave_service/graphql/graphql_object_mapper.go +++ b/swiftwave_service/graphql/graphql_object_mapper.go @@ -809,39 +809,43 @@ func stackToApplicationsInput(applicationGroupID *string, record *stack_parser.S // newServerInputToDatabaseObject converts NewServerInput to ServerDatabaseObject func newServerInputToDatabaseObject(record *model.NewServerInput) *core.Server { - return &core.Server{ - IP: record.IP, - SSHPort: record.SSHPort, - HostName: "", - User: record.User, - ScheduleDeployments: false, - MaintenanceMode: false, - DockerUnixSocketPath: "", - SwarmMode: core.SwarmMode(model.SwarmModeWorker), - ProxyConfig: core.ProxyConfig{ - Enabled: false, - Type: core.ProxyType(model.ProxyTypeActive), - }, - Status: core.ServerStatus(model.ServerStatusNeedsSetup), - } + // TODO fix + //return &core.Server{ + // IP: record.IP, + // SSHPort: record.SSHPort, + // HostName: "", + // User: record.User, + // ScheduleDeployments: false, + // MaintenanceMode: false, + // DockerUnixSocketPath: "", + // SwarmMode: core.SwarmMode(model.SwarmModeWorker), + // ProxyConfig: core.ProxyConfig{ + // Enabled: false, + // Type: core.ProxyType(model.ProxyTypeActive), + // }, + // Status: core.ServerStatus(model.ServerStatusNeedsSetup), + //} + return nil } // serverToGraphqlObject converts Server to ServerGraphqlObject func serverToGraphqlObject(record *core.Server) *model.Server { - return &model.Server{ - ID: record.ID, - IP: record.IP, - SSHPort: record.SSHPort, - Hostname: record.HostName, - User: record.User, - ScheduleDeployments: record.ScheduleDeployments, - MaintenanceMode: record.MaintenanceMode, - DockerUnixSocketPath: record.DockerUnixSocketPath, - SwarmMode: model.SwarmMode(record.SwarmMode), - ProxyType: model.ProxyType(record.ProxyConfig.Type), - ProxyEnabled: record.ProxyConfig.Enabled, - Status: model.ServerStatus(record.Status), - } + // TODO fix + //return &model.Server{ + // ID: record.ID, + // IP: record.IP, + // SSHPort: record.SSHPort, + // Hostname: record.HostName, + // User: record.User, + // ScheduleDeployments: record.ScheduleDeployments, + // MaintenanceMode: record.MaintenanceMode, + // DockerUnixSocketPath: record.DockerUnixSocketPath, + // SwarmMode: model.SwarmMode(record.SwarmMode), + // ProxyType: model.ProxyType(record.ProxyConfig.Type), + // ProxyEnabled: record.ProxyConfig.Enabled, + // Status: model.ServerStatus(record.Status), + //} + return nil } // serverLogToGraphqlObject converts ServerLog to ServerLogGraphqlObject diff --git a/swiftwave_service/graphql/helpers.go b/swiftwave_service/graphql/helpers.go index 8b501000ed..58338ed941 100644 --- a/swiftwave_service/graphql/helpers.go +++ b/swiftwave_service/graphql/helpers.go @@ -17,7 +17,6 @@ import ( haproxymanager "github.com/swiftwave-org/swiftwave/pkg/haproxy_manager" "github.com/swiftwave-org/swiftwave/swiftwave_service/core" "github.com/swiftwave-org/swiftwave/swiftwave_service/graphql/model" - "github.com/swiftwave-org/swiftwave/swiftwave_service/logger" "github.com/swiftwave-org/swiftwave/swiftwave_service/manager" "gorm.io/gorm" ) @@ -56,22 +55,24 @@ func sanitizeFileName(fileName string) string { } func FetchDockerManager(ctx context.Context, db *gorm.DB) (*containermanger.Manager, error) { - // Fetch a random swarm manager - swarmManagerServer, err := core.FetchSwarmManager(db) - if err != nil { - if errors.Is(err, gorm.ErrRecordNotFound) { - // no online swarm manager - logger.GraphQLLogger.Println("failed to fetch docker manager due to no online swarm manager") - return nil, errors.New("failed to fetch docker manager due to no online swarm manager") - } - return nil, errors.New("failed to fetch swarm manager") - } - // Fetch docker manager - dockerManager, err := manager.DockerClient(ctx, swarmManagerServer) - if err != nil { - return nil, errors.New("failed to fetch docker manager") - } - return dockerManager, nil + return nil, nil + // TODO fix + //// Fetch a random swarm manager + //swarmManagerServer, err := core.FetchSwarmManager(db) + //if err != nil { + // if errors.Is(err, gorm.ErrRecordNotFound) { + // // no online swarm manager + // logger.GraphQLLogger.Println("failed to fetch docker manager due to no online swarm manager") + // return nil, errors.New("failed to fetch docker manager due to no online swarm manager") + // } + // return nil, errors.New("failed to fetch swarm manager") + //} + //// Fetch docker manager + //dockerManager, err := manager.DockerClient(ctx, swarmManagerServer) + //if err != nil { + // return nil, errors.New("failed to fetch docker manager") + //} + //return dockerManager, nil } func AppendPublicSSHKeyLocally(pubKey string) error { diff --git a/swiftwave_service/graphql/persistent_volume.resolvers.go b/swiftwave_service/graphql/persistent_volume.resolvers.go index 2349486d5e..09b95bf1c6 100644 --- a/swiftwave_service/graphql/persistent_volume.resolvers.go +++ b/swiftwave_service/graphql/persistent_volume.resolvers.go @@ -6,8 +6,6 @@ package graphql import ( "context" - "errors" - "github.com/swiftwave-org/swiftwave/swiftwave_service/core" "github.com/swiftwave-org/swiftwave/swiftwave_service/graphql/model" "github.com/swiftwave-org/swiftwave/swiftwave_service/manager" @@ -111,28 +109,30 @@ func (r *queryResolver) PersistentVolume(ctx context.Context, id uint) (*model.P // PersistentVolumeSizeMb is the resolver for the persistentVolumeSizeMb field. func (r *queryResolver) PersistentVolumeSizeMb(ctx context.Context, id uint) (float64, error) { - // fetch record - var record core.PersistentVolume - err := record.FindById(ctx, r.ServiceManager.DbClient, id) - if err != nil { - return 0, err - } - // Fetch a random swarm manager - swarmManagerServer, err := core.FetchSwarmManager(&r.ServiceManager.DbClient) - if err != nil { - return 0, errors.New("failed to fetch swarm manager") - } - // Fetch docker manager - dockerManager, err := manager.DockerClient(ctx, swarmManagerServer) - if err != nil { - return 0, errors.New("failed to fetch docker manager") - } - // fetch size - size, err := dockerManager.SizeVolume(record.Name, swarmManagerServer.IP, swarmManagerServer.SSHPort, swarmManagerServer.User, r.Config.SystemConfig.SshPrivateKey) - if err != nil { - return 0, err - } - return size, nil + // TODO fix + //// fetch record + //var record core.PersistentVolume + //err := record.FindById(ctx, r.ServiceManager.DbClient, id) + //if err != nil { + // return 0, err + //} + //// Fetch a random swarm manager + //swarmManagerServer, err := core.FetchSwarmManager(&r.ServiceManager.DbClient) + //if err != nil { + // return 0, errors.New("failed to fetch swarm manager") + //} + //// Fetch docker manager + //dockerManager, err := manager.DockerClient(ctx, swarmManagerServer) + //if err != nil { + // return 0, errors.New("failed to fetch docker manager") + //} + //// fetch size + //size, err := dockerManager.SizeVolume(record.Name, swarmManagerServer.IP, swarmManagerServer.SSHPort, swarmManagerServer.User, r.Config.SystemConfig.SshPrivateKey) + //if err != nil { + // return 0, err + //} + //return size, nil + return 0, nil } // IsExistPersistentVolume is the resolver for the isExistPersistentVolume field. diff --git a/swiftwave_service/graphql/server.resolvers.go b/swiftwave_service/graphql/server.resolvers.go index 4c7fdf4464..89fb493129 100644 --- a/swiftwave_service/graphql/server.resolvers.go +++ b/swiftwave_service/graphql/server.resolvers.go @@ -16,8 +16,6 @@ import ( "github.com/swiftwave-org/swiftwave/swiftwave_service/core" "github.com/swiftwave-org/swiftwave/swiftwave_service/graphql/model" "github.com/swiftwave-org/swiftwave/swiftwave_service/logger" - swiftwaveServiceManagerDocker "github.com/swiftwave-org/swiftwave/swiftwave_service/manager" - "gorm.io/gorm" ) // CreateServer is the resolver for the createServer field. @@ -54,63 +52,64 @@ func (r *mutationResolver) DeleteServer(ctx context.Context, id uint) (bool, err // 7. Remove from swarm cluster // 8. Remove from the database - server, err := core.FetchServerByID(&r.ServiceManager.DbClient, id) - if err != nil { - return false, err - } - // If `need_setup`, delete it from database - if server.Status == core.ServerNeedsSetup { - err = core.DeleteServer(&r.ServiceManager.DbClient, id) - if err != nil { - return false, err - } - return true, nil - } - // If `preparing`, it can't be deleted - if server.Status == core.ServerPreparing { - return false, errors.New("server is preparing, you can delete it only after it come out of `preparing` status") - } - // If it's the last server, then delete it from db - servers, err := core.FetchAllServers(&r.ServiceManager.DbClient) - if err != nil { - return false, err - } - if len(servers) == 1 { - err = core.DeleteServer(&r.ServiceManager.DbClient, id) - if err != nil { - return false, err - } - return true, nil - } - // if not the last server, then required additional steps - if server.SwarmMode == core.SwarmManager { - return false, errors.New("from 'Actions' menu, demote this server to 'Swarm Worker' mode to proceed for deletion") - } - if server.ProxyConfig.Enabled { - return false, errors.New("from 'Actions' menu, disable ingress proxy on this server to proceed for deletion") - } - // fetch another swarm manager - otherSwarmManager, err := core.FetchSwarmManagerExceptServer(&r.ServiceManager.DbClient, id) - if err != nil { - if errors.Is(err, gorm.ErrRecordNotFound) { - return false, errors.New("no other swarm manager found to proceed for deletion") - } - } - // fetch docker manager - dockerManager, err := swiftwaveServiceManagerDocker.DockerClient(ctx, otherSwarmManager) - if err != nil { - return false, err - } - // remove from swarm cluster - err = dockerManager.RemoveNode(server.HostName) - if err != nil { - return false, err - } - // remove from local database - err = core.DeleteServer(&r.ServiceManager.DbClient, id) - if err != nil { - return false, err - } + // TODO fix + //server, err := core.FetchServerByID(&r.ServiceManager.DbClient, id) + //if err != nil { + // return false, err + //} + //// If `need_setup`, delete it from database + //if server.Status == core.ServerNeedsSetup { + // err = core.DeleteServer(&r.ServiceManager.DbClient, id) + // if err != nil { + // return false, err + // } + // return true, nil + //} + //// If `preparing`, it can't be deleted + //if server.Status == core.ServerPreparing { + // return false, errors.New("server is preparing, you can delete it only after it come out of `preparing` status") + //} + //// If it's the last server, then delete it from db + //servers, err := core.FetchAllServers(&r.ServiceManager.DbClient) + //if err != nil { + // return false, err + //} + //if len(servers) == 1 { + // err = core.DeleteServer(&r.ServiceManager.DbClient, id) + // if err != nil { + // return false, err + // } + // return true, nil + //} + //// if not the last server, then required additional steps + //if server.SwarmMode == core.SwarmManager { + // return false, errors.New("from 'Actions' menu, demote this server to 'Swarm Worker' mode to proceed for deletion") + //} + //if server.ProxyConfig.Enabled { + // return false, errors.New("from 'Actions' menu, disable ingress proxy on this server to proceed for deletion") + //} + //// fetch another swarm manager + //otherSwarmManager, err := core.FetchSwarmManagerExceptServer(&r.ServiceManager.DbClient, id) + //if err != nil { + // if errors.Is(err, gorm.ErrRecordNotFound) { + // return false, errors.New("no other swarm manager found to proceed for deletion") + // } + //} + //// fetch docker manager + //dockerManager, err := swiftwaveServiceManagerDocker.DockerClient(ctx, otherSwarmManager) + //if err != nil { + // return false, err + //} + //// remove from swarm cluster + //err = dockerManager.RemoveNode(server.HostName) + //if err != nil { + // return false, err + //} + //// remove from local database + //err = core.DeleteServer(&r.ServiceManager.DbClient, id) + //if err != nil { + // return false, err + //} return true, nil } @@ -140,15 +139,15 @@ func (r *mutationResolver) ChangeServerIPAddress(ctx context.Context, id uint, i if len(ip) == 0 { return false, errors.New("IP is required") } - if strings.Compare(server.IP, ip) == 0 { - return false, errors.New("IP is already " + server.IP) + if strings.Compare(server.PublicIP, ip) == 0 { + return false, errors.New("IP is already " + server.PublicIP) } err = core.ChangeServerIP(&r.ServiceManager.DbClient, server, ip) if err != nil { return false, err } // Exit process - logger.GraphQLLoggerError.Println("Server " + server.HostName + " IP changed to " + ip + "\nRestarting swiftwave in 2 seconds to take effect") + logger.GraphQLLoggerError.Println("Server " + server.Name + " IP changed to " + ip + "\nRestarting swiftwave in 2 seconds to take effect") // Restart swiftwave service go func() { <-time.After(2 * time.Second) @@ -267,23 +266,25 @@ func (r *queryResolver) ServerLatestDiskUsage(ctx context.Context, id uint) (*mo // SwarmNodeStatus is the resolver for the swarmNodeStatus field. func (r *serverResolver) SwarmNodeStatus(ctx context.Context, obj *model.Server) (string, error) { - server, err := core.FetchServerByID(&r.ServiceManager.DbClient, obj.ID) - if err != nil { - return "", nil - } - if server.Status != core.ServerOnline { - return "", nil - } - // Fetch any swarm manager - swarmManagerServer, err := core.FetchSwarmManager(&r.ServiceManager.DbClient) - if err != nil { - return "", nil - } - manager, err := swiftwaveServiceManagerDocker.DockerClient(ctx, swarmManagerServer) - if err != nil { - return "", nil - } - return manager.FetchNodeStatus(server.HostName) + // TODO fix + //server, err := core.FetchServerByID(&r.ServiceManager.DbClient, obj.ID) + //if err != nil { + // return "", nil + //} + //if server.Status != core.ServerOnline { + // return "", nil + //} + //// Fetch any swarm manager + //swarmManagerServer, err := core.FetchSwarmManager(&r.ServiceManager.DbClient) + //if err != nil { + // return "", nil + //} + //manager, err := swiftwaveServiceManagerDocker.DockerClient(ctx, swarmManagerServer) + //if err != nil { + // return "", nil + //} + //return manager.FetchNodeStatus(server.HostName) + return "hello", nil } // Logs is the resolver for the logs field. diff --git a/swiftwave_service/manager/docker.go b/swiftwave_service/manager/docker.go index fc8052e6fd..905e4f7446 100644 --- a/swiftwave_service/manager/docker.go +++ b/swiftwave_service/manager/docker.go @@ -4,26 +4,27 @@ import ( "context" containermanger "github.com/swiftwave-org/swiftwave/pkg/container_manager" - "github.com/swiftwave-org/swiftwave/pkg/ssh_toolkit" - "github.com/swiftwave-org/swiftwave/swiftwave_service/config" "github.com/swiftwave-org/swiftwave/swiftwave_service/core" ) func DockerClient(ctx context.Context, server core.Server) (*containermanger.Manager, error) { // Fetch config - c, err := config.Fetch() - if err != nil { - return nil, err - } + //c, err := config.Fetch() + //if err != nil { + // return nil, err + //} // Create Net.Conn over SSH - conn, err := ssh_toolkit.NetConnOverSSH("unix", server.DockerUnixSocketPath, 5, server.IP, server.SSHPort, server.User, c.SystemConfig.SshPrivateKey) - if err != nil { - return nil, err - } - // Create Docker client - manager, err := containermanger.New(ctx, conn) - if err != nil { - return nil, err - } - return manager, nil + // TODO fix + //conn, err := ssh_toolkit.NetConnOverSSH("unix", server.DockerUnixSocketPath, 5, server.IP, server.SSHPort, server.User, c.SystemConfig.SshPrivateKey) + //if err != nil { + // return nil, err + //} + //// Create Docker client + //manager, err := containermanger.New(ctx, conn) + //if err != nil { + // return nil, err + //} + //return manager, nil + + return nil, nil } diff --git a/swiftwave_service/manager/haproxy.go b/swiftwave_service/manager/haproxy.go index 509e895d59..d8a04f0285 100644 --- a/swiftwave_service/manager/haproxy.go +++ b/swiftwave_service/manager/haproxy.go @@ -3,23 +3,22 @@ package manager import ( "context" haproxymanager "github.com/swiftwave-org/swiftwave/pkg/haproxy_manager" - "github.com/swiftwave-org/swiftwave/pkg/ssh_toolkit" - "github.com/swiftwave-org/swiftwave/swiftwave_service/config" "github.com/swiftwave-org/swiftwave/swiftwave_service/core" - "net" ) func HAProxyClient(_ context.Context, server core.Server) (*haproxymanager.Manager, error) { // Fetch config - c, err := config.Fetch() - if err != nil { - return nil, err - } - // Create client - manager := haproxymanager.New(func() (net.Conn, error) { - return ssh_toolkit.NetConnOverSSH("unix", c.LocalConfig.ServiceConfig.HAProxyUnixSocketPath, 50, server.IP, server.SSHPort, server.User, c.SystemConfig.SshPrivateKey) - }, c.SystemConfig.HAProxyConfig.Username, c.SystemConfig.HAProxyConfig.Password) - return &manager, nil + //c, err := config.Fetch() + //if err != nil { + // return nil, err + //} + //// Create client + //manager := haproxymanager.New(func() (net.Conn, error) { + // return ssh_toolkit.NetConnOverSSH("unix", c.LocalConfig.ServiceConfig.HAProxyUnixSocketPath, 50, server.IP, server.SSHPort, server.User, c.SystemConfig.SshPrivateKey) + //}, c.SystemConfig.HAProxyConfig.Username, c.SystemConfig.HAProxyConfig.Password) + //return &manager, nil + + return nil, nil } func HAProxyClients(ctx context.Context, servers []core.Server) ([]*haproxymanager.Manager, error) { diff --git a/swiftwave_service/manager/udpproxy.go b/swiftwave_service/manager/udpproxy.go index bddab05f91..17e7fefb2b 100644 --- a/swiftwave_service/manager/udpproxy.go +++ b/swiftwave_service/manager/udpproxy.go @@ -2,24 +2,23 @@ package manager import ( "context" - "github.com/swiftwave-org/swiftwave/pkg/ssh_toolkit" - "github.com/swiftwave-org/swiftwave/swiftwave_service/config" - "github.com/swiftwave-org/swiftwave/swiftwave_service/core" "github.com/swiftwave-org/swiftwave/pkg/udp_proxy_manager" - "net" + "github.com/swiftwave-org/swiftwave/swiftwave_service/core" ) func UDPProxyClient(_ context.Context, server core.Server) (*udp_proxy_manager.Manager, error) { - // Fetch config - c, err := config.Fetch() - if err != nil { - return nil, err - } - // Create Net.Conn over SSH - manager := udp_proxy_manager.New(func() (net.Conn, error) { - return ssh_toolkit.NetConnOverSSH("unix", c.LocalConfig.ServiceConfig.UDPProxyUnixSocketPath, 20, server.IP, server.SSHPort, server.User, c.SystemConfig.SshPrivateKey) - }) - return &manager, nil + // TODO fix + //// Fetch config + //c, err := config.Fetch() + //if err != nil { + // return nil, err + //} + //// Create Net.Conn over SSH + //manager := udp_proxy_manager.New(func() (net.Conn, error) { + // return ssh_toolkit.NetConnOverSSH("unix", c.LocalConfig.ServiceConfig.UDPProxyUnixSocketPath, 20, server.IP, server.SSHPort, server.User, c.SystemConfig.SshPrivateKey) + //}) + //return &manager, nil + return nil, nil } func UDPProxyClients(ctx context.Context, servers []core.Server) ([]*udp_proxy_manager.Manager, error) { diff --git a/swiftwave_service/stack_parser/utils.go b/swiftwave_service/stack_parser/utils.go index ea91b3c12d..c8415fb108 100644 --- a/swiftwave_service/stack_parser/utils.go +++ b/swiftwave_service/stack_parser/utils.go @@ -1,11 +1,8 @@ package stack_parser import ( - "context" "errors" "fmt" - "github.com/swiftwave-org/swiftwave/swiftwave_service/core" - "github.com/swiftwave-org/swiftwave/swiftwave_service/manager" "github.com/swiftwave-org/swiftwave/swiftwave_service/service_manager" "math/rand" "regexp" @@ -162,75 +159,76 @@ func (s *Stack) FillAndVerifyVariables(variableMapping *map[string]string, servi service.CustomHealthCheck.TestCommand = newHealthCheckTestCommand stackCopy.Services[serviceName] = service } - // check if docs present - if stackCopy.Docs != nil { - // fetch a swarm manager server - server, err := core.FetchSwarmManager(&serviceManager.DbClient) - if err != nil { - return nil, errors.New("error in fetching swarm manager") - } - // fetch docker manager - dockerManager, err := manager.DockerClient(context.Background(), server) - if err != nil { - return nil, errors.New("error in connecting to docker manager") - } - // verify the type of variables - for variableKey, variable := range stackCopy.Docs.Variables { - // check if variableKey is present in variableMapping - if _, ok := (*variableMapping)[variableKey]; ok { - if variable.Type == DocsVariableTypeInteger { - _, err := stringToInteger((*variableMapping)[variableKey]) - if err != nil { - return nil, errors.New("variable " + variableKey + " should be integer") - } - } else if variable.Type == DocsVariableTypeFloat { - _, err := strconv.ParseFloat((*variableMapping)[variableKey], 64) - if err != nil { - return nil, errors.New("variable " + variableKey + " should be float") - } - } else if variable.Type == DocsVariableTypeOptions { - isValid := false - for _, option := range variable.Options { - if option.Value == (*variableMapping)[variableKey] { - isValid = true - break - } - } - if !isValid { - return nil, errors.New("variable " + variableKey + " should be one of the provided options") - } - } else if variable.Type == DocsVariableTypeVolume { - val := (*variableMapping)[variableKey] - isExist, err := core.IsExistPersistentVolume(context.Background(), serviceManager.DbClient, val, *dockerManager) - if err != nil { - return nil, errors.New("error in checking volume " + val) - } - if !isExist { - return nil, errors.New("volume " + val + " doesn't exist. Create it or choose another volume") - } - } else if variable.Type == DocsVariableTypeText { - // do nothing, just for the sake of completeness - } else if variable.Type == DocsVariableTypeApplication { - val := (*variableMapping)[variableKey] - isExist, err := core.IsExistApplicationName(context.Background(), serviceManager.DbClient, *dockerManager, val) - if err != nil { - return nil, errors.New("error in checking application " + val) - } - if !isExist { - return nil, errors.New("application " + val + " doesn't exist. Create it or choose another application") - } - } else if variable.Type == DocsVariableTypeServer { - val := (*variableMapping)[variableKey] - _, err := core.FetchServerIDByHostName(&serviceManager.DbClient, val) - if err != nil { - return nil, errors.New("invalid server " + val + " provided") - } - } else { - return nil, errors.New("invalid variable type") - } - } - } - } + // TODO fix + //// check if docs present + //if stackCopy.Docs != nil { + // // fetch a swarm manager server + // server, err := core.FetchSwarmManager(&serviceManager.DbClient) + // if err != nil { + // return nil, errors.New("error in fetching swarm manager") + // } + // // fetch docker manager + // dockerManager, err := manager.DockerClient(context.Background(), server) + // if err != nil { + // return nil, errors.New("error in connecting to docker manager") + // } + // // verify the type of variables + // for variableKey, variable := range stackCopy.Docs.Variables { + // // check if variableKey is present in variableMapping + // if _, ok := (*variableMapping)[variableKey]; ok { + // if variable.Type == DocsVariableTypeInteger { + // _, err := stringToInteger((*variableMapping)[variableKey]) + // if err != nil { + // return nil, errors.New("variable " + variableKey + " should be integer") + // } + // } else if variable.Type == DocsVariableTypeFloat { + // _, err := strconv.ParseFloat((*variableMapping)[variableKey], 64) + // if err != nil { + // return nil, errors.New("variable " + variableKey + " should be float") + // } + // } else if variable.Type == DocsVariableTypeOptions { + // isValid := false + // for _, option := range variable.Options { + // if option.Value == (*variableMapping)[variableKey] { + // isValid = true + // break + // } + // } + // if !isValid { + // return nil, errors.New("variable " + variableKey + " should be one of the provided options") + // } + // } else if variable.Type == DocsVariableTypeVolume { + // val := (*variableMapping)[variableKey] + // isExist, err := core.IsExistPersistentVolume(context.Background(), serviceManager.DbClient, val, *dockerManager) + // if err != nil { + // return nil, errors.New("error in checking volume " + val) + // } + // if !isExist { + // return nil, errors.New("volume " + val + " doesn't exist. Create it or choose another volume") + // } + // } else if variable.Type == DocsVariableTypeText { + // // do nothing, just for the sake of completeness + // } else if variable.Type == DocsVariableTypeApplication { + // val := (*variableMapping)[variableKey] + // isExist, err := core.IsExistApplicationName(context.Background(), serviceManager.DbClient, *dockerManager, val) + // if err != nil { + // return nil, errors.New("error in checking application " + val) + // } + // if !isExist { + // return nil, errors.New("application " + val + " doesn't exist. Create it or choose another application") + // } + // } else if variable.Type == DocsVariableTypeServer { + // val := (*variableMapping)[variableKey] + // _, err := core.FetchServerIDByHostName(&serviceManager.DbClient, val) + // if err != nil { + // return nil, errors.New("invalid server " + val + " provided") + // } + // } else { + // return nil, errors.New("invalid variable type") + // } + // } + // } + //} return stackCopy, nil } diff --git a/swiftwave_service/worker/process_application_delete_request.go b/swiftwave_service/worker/process_application_delete_request.go index 846161d34d..965a23bd5f 100644 --- a/swiftwave_service/worker/process_application_delete_request.go +++ b/swiftwave_service/worker/process_application_delete_request.go @@ -2,59 +2,56 @@ package worker import ( "context" - "errors" - "github.com/swiftwave-org/swiftwave/swiftwave_service/core" - "github.com/swiftwave-org/swiftwave/swiftwave_service/manager" - "gorm.io/gorm" - "log" ) func (m Manager) DeleteApplication(request DeleteApplicationRequest, ctx context.Context, _ context.CancelFunc) error { - dbWithoutTx := m.ServiceManager.DbClient - // fetch the swarm server - swarmManager, err := core.FetchSwarmManager(&dbWithoutTx) - if err != nil { - return err - } - // create docker manager - dockerManager, err := manager.DockerClient(context.Background(), swarmManager) - if err != nil { - return err - } - // find application - var application core.Application - err = application.FindById(ctx, m.ServiceManager.DbClient, request.Id) - if err != nil { - if errors.Is(err, gorm.ErrRecordNotFound) { - // return nil as don't want to requeue the job - return nil - } else { - return err - } - } - // start a db transaction - tx := dbWithoutTx.Begin() - // delete application - err = application.HardDelete(ctx, *tx, *dockerManager) - if err != nil { - tx.Rollback() - return err - } - - // commit the transaction - err = tx.Commit().Error - if err != nil { - return err - } - - // delete application from swarm manager - err = dockerManager.RemoveService(application.Name) - if err != nil { - log.Println("[WARN] error deleting application from swarm manager : " + application.Name) - } - // remove docker proxy - dockerManager.RemoveDockerProxy(application.DockerProxyServiceName()) - // prune config mounts - dockerManager.PruneConfig(application.ID) return nil + // TODO fix + //dbWithoutTx := m.ServiceManager.DbClient + //// fetch the swarm server + //swarmManager, err := core.FetchSwarmManager(&dbWithoutTx) + //if err != nil { + // return err + //} + //// create docker manager + //dockerManager, err := manager.DockerClient(context.Background(), swarmManager) + //if err != nil { + // return err + //} + //// find application + //var application core.Application + //err = application.FindById(ctx, m.ServiceManager.DbClient, request.Id) + //if err != nil { + // if errors.Is(err, gorm.ErrRecordNotFound) { + // // return nil as don't want to requeue the job + // return nil + // } else { + // return err + // } + //} + //// start a db transaction + //tx := dbWithoutTx.Begin() + //// delete application + //err = application.HardDelete(ctx, *tx, *dockerManager) + //if err != nil { + // tx.Rollback() + // return err + //} + // + //// commit the transaction + //err = tx.Commit().Error + //if err != nil { + // return err + //} + // + //// delete application from swarm manager + //err = dockerManager.RemoveService(application.Name) + //if err != nil { + // log.Println("[WARN] error deleting application from swarm manager : " + application.Name) + //} + //// remove docker proxy + //dockerManager.RemoveDockerProxy(application.DockerProxyServiceName()) + //// prune config mounts + //dockerManager.PruneConfig(application.ID) + //return nil } diff --git a/swiftwave_service/worker/process_application_deploy_request.go b/swiftwave_service/worker/process_application_deploy_request.go index bcd793c8ac..2f269eef05 100644 --- a/swiftwave_service/worker/process_application_deploy_request.go +++ b/swiftwave_service/worker/process_application_deploy_request.go @@ -5,7 +5,6 @@ import ( "errors" haproxymanager "github.com/swiftwave-org/swiftwave/pkg/haproxy_manager" "github.com/swiftwave-org/swiftwave/swiftwave_service/logger" - "github.com/swiftwave-org/swiftwave/swiftwave_service/manager" "log" "strings" @@ -15,43 +14,44 @@ import ( ) func (m Manager) DeployApplication(request DeployApplicationRequest, _ context.Context, _ context.CancelFunc) error { - // fetch the swarm server - swarmManager, err := core.FetchSwarmManager(&m.ServiceManager.DbClient) - if err != nil { - return err - } - // create docker manager - dockerManager, err := manager.DockerClient(context.Background(), swarmManager) - if err != nil { - return err - } - // fetch all proxy servers - proxyServers := make([]core.Server, 0) - if !request.IgnoreProxyUpdate { - proxyServers, err = core.FetchProxyActiveServers(&m.ServiceManager.DbClient) - if err != nil { - return err - } - } - // fetch all haproxy managers - haproxyManagers, err := manager.HAProxyClients(context.Background(), proxyServers) - if err != nil { - return err - } - err = m.deployApplicationHelper(request, dockerManager, haproxyManagers) - if err != nil { - // mark as failed - ctx := context.Background() - addPersistentDeploymentLog(m.ServiceManager.DbClient, m.ServiceManager.PubSubClient, request.DeploymentId, "Deployment failed > \n"+err.Error()+"\n", false) - deployment := &core.Deployment{} - deployment.ID = request.DeploymentId - err = deployment.UpdateStatus(ctx, m.ServiceManager.DbClient, core.DeploymentStatusFailed) - if err != nil { - log.Println("failed to update deployment status to failed", err) - } - } - // prune config mounts - dockerManager.PruneConfig(request.AppId) + // TODO fix + //// fetch the swarm server + //swarmManager, err := core.FetchSwarmManager(&m.ServiceManager.DbClient) + //if err != nil { + // return err + //} + //// create docker manager + //dockerManager, err := manager.DockerClient(context.Background(), swarmManager) + //if err != nil { + // return err + //} + //// fetch all proxy servers + //proxyServers := make([]core.Server, 0) + //if !request.IgnoreProxyUpdate { + // proxyServers, err = core.FetchProxyActiveServers(&m.ServiceManager.DbClient) + // if err != nil { + // return err + // } + //} + //// fetch all haproxy managers + //haproxyManagers, err := manager.HAProxyClients(context.Background(), proxyServers) + //if err != nil { + // return err + //} + //err = m.deployApplicationHelper(request, dockerManager, haproxyManagers) + //if err != nil { + // // mark as failed + // ctx := context.Background() + // addPersistentDeploymentLog(m.ServiceManager.DbClient, m.ServiceManager.PubSubClient, request.DeploymentId, "Deployment failed > \n"+err.Error()+"\n", false) + // deployment := &core.Deployment{} + // deployment.ID = request.DeploymentId + // err = deployment.UpdateStatus(ctx, m.ServiceManager.DbClient, core.DeploymentStatusFailed) + // if err != nil { + // log.Println("failed to update deployment status to failed", err) + // } + //} + //// prune config mounts + //dockerManager.PruneConfig(request.AppId) return nil } @@ -199,7 +199,10 @@ func (m Manager) deployApplicationHelper(request DeployApplicationRequest, docke } // prepare placement constraints var placementConstraints = make([]string, 0) - disabledServerHostnames, err := core.FetchDisabledDeploymentServerHostNames(&m.ServiceManager.DbClient) + // TODO fix + //disabledServerHostnames, err := core.FetchDisabledDeploymentServerHostNames(&m.ServiceManager.DbClient) + disabledServerHostnames := make([]string, 0) + err = nil if err != nil { addPersistentDeploymentLog(dbWithoutTx, pubSubClient, deployment.ID, "Failed to fetch disabled deployment servers\nPlease check database connection\n", false) return err diff --git a/swiftwave_service/worker/process_install_dependencies_on_server_request.go b/swiftwave_service/worker/process_install_dependencies_on_server_request.go index 5e6a3dac13..4fe32b562e 100644 --- a/swiftwave_service/worker/process_install_dependencies_on_server_request.go +++ b/swiftwave_service/worker/process_install_dependencies_on_server_request.go @@ -1,101 +1,96 @@ package worker import ( - "bytes" "context" - "errors" - "github.com/swiftwave-org/swiftwave/pkg/ssh_toolkit" - "github.com/swiftwave-org/swiftwave/swiftwave_service/core" - "gorm.io/gorm" - "time" ) func (m Manager) InstallDependenciesOnServer(request InstallDependenciesOnServerRequest, ctx context.Context, _ context.CancelFunc) error { - // fetch server - server, err := core.FetchServerByID(&m.ServiceManager.DbClient, request.ServerId) - if err != nil { - if errors.Is(err, gorm.ErrRecordNotFound) { - return nil - } - return err - } - // fetch server log - serverLog, err := core.FetchServerLogByID(&m.ServiceManager.DbClient, request.LogId) - if err != nil { - if errors.Is(err, gorm.ErrRecordNotFound) { - return nil - } - return err - } - // log - logText := "Installing dependencies on server\n" - // spawn a goroutine to update server log each 5 seconds - go func() { - lastSent := time.Now() - for { - select { - case <-ctx.Done(): - return - default: - if time.Since(lastSent) > 5*time.Second { - serverLog.Content = logText - _ = serverLog.Update(&m.ServiceManager.DbClient) - lastSent = time.Now() - } - } - } - }() - // defer to push final log - defer func() { - serverLog.Content = logText - _ = serverLog.Update(&m.ServiceManager.DbClient) - }() - - detectedOS, err := ssh_toolkit.DetectOS(5, server.IP, server.SSHPort, server.User, m.Config.SystemConfig.SshPrivateKey) - if err != nil { - logText += "Error detecting OS: " + err.Error() + "\n" - return nil - } - - // command - var command string - for _, dependency := range core.RequiredServerDependencies { - isExists := false - // check if dependency is already installed [ignore init] - if dependency != "init" { - stdoutBuffer := new(bytes.Buffer) - err = ssh_toolkit.ExecCommandOverSSH(core.DependencyCheckCommands[dependency], stdoutBuffer, nil, 5, server.IP, server.SSHPort, server.User, m.Config.SystemConfig.SshPrivateKey) - if err == nil { - isExists = stdoutBuffer.String() != "" - } - } - // install dependency - if isExists { - logText += "Dependency " + dependency + " is already installed\n" - continue - } else { - logText += "Installing dependency " + dependency + "\n" - stdoutBuffer := new(bytes.Buffer) - stderrBuffer := new(bytes.Buffer) - if detectedOS == ssh_toolkit.DebianBased { - command = core.DebianDependenciesInstallCommands[dependency] - } else if detectedOS == ssh_toolkit.FedoraBased { - command = core.FedoraDependenciesInstallCommands[dependency] - } else { - logText += "Unknown OS: " + string(detectedOS) + "\n" - continue - } - err = ssh_toolkit.ExecCommandOverSSH(command, stdoutBuffer, stderrBuffer, 5, server.IP, server.SSHPort, server.User, m.Config.SystemConfig.SshPrivateKey) - logText += stdoutBuffer.String() + "\n" - logText += stderrBuffer.String() + "\n" - logText += "\n" - if err != nil { - logText += "Error installing dependency " + dependency + ": " + err.Error() + "\n" + stderrBuffer.String() + "\n" - return nil - } else { - logText += "Dependency " + dependency + " installed successfully\n" - } - } - } + // TODO fix + //// fetch server + //server, err := core.FetchServerByID(&m.ServiceManager.DbClient, request.ServerId) + //if err != nil { + // if errors.Is(err, gorm.ErrRecordNotFound) { + // return nil + // } + // return err + //} + //// fetch server log + //serverLog, err := core.FetchServerLogByID(&m.ServiceManager.DbClient, request.LogId) + //if err != nil { + // if errors.Is(err, gorm.ErrRecordNotFound) { + // return nil + // } + // return err + //} + //// log + //logText := "Installing dependencies on server\n" + //// spawn a goroutine to update server log each 5 seconds + //go func() { + // lastSent := time.Now() + // for { + // select { + // case <-ctx.Done(): + // return + // default: + // if time.Since(lastSent) > 5*time.Second { + // serverLog.Content = logText + // _ = serverLog.Update(&m.ServiceManager.DbClient) + // lastSent = time.Now() + // } + // } + // } + //}() + //// defer to push final log + //defer func() { + // serverLog.Content = logText + // _ = serverLog.Update(&m.ServiceManager.DbClient) + //}() + // + //detectedOS, err := ssh_toolkit.DetectOS(5, server.IP, server.SSHPort, server.User, m.Config.SystemConfig.SshPrivateKey) + //if err != nil { + // logText += "Error detecting OS: " + err.Error() + "\n" + // return nil + //} + // + //// command + //var command string + //for _, dependency := range core.RequiredServerDependencies { + // isExists := false + // // check if dependency is already installed [ignore init] + // if dependency != "init" { + // stdoutBuffer := new(bytes.Buffer) + // err = ssh_toolkit.ExecCommandOverSSH(core.DependencyCheckCommands[dependency], stdoutBuffer, nil, 5, server.IP, server.SSHPort, server.User, m.Config.SystemConfig.SshPrivateKey) + // if err == nil { + // isExists = stdoutBuffer.String() != "" + // } + // } + // // install dependency + // if isExists { + // logText += "Dependency " + dependency + " is already installed\n" + // continue + // } else { + // logText += "Installing dependency " + dependency + "\n" + // stdoutBuffer := new(bytes.Buffer) + // stderrBuffer := new(bytes.Buffer) + // if detectedOS == ssh_toolkit.DebianBased { + // command = core.DebianDependenciesInstallCommands[dependency] + // } else if detectedOS == ssh_toolkit.FedoraBased { + // command = core.FedoraDependenciesInstallCommands[dependency] + // } else { + // logText += "Unknown OS: " + string(detectedOS) + "\n" + // continue + // } + // err = ssh_toolkit.ExecCommandOverSSH(command, stdoutBuffer, stderrBuffer, 5, server.IP, server.SSHPort, server.User, m.Config.SystemConfig.SshPrivateKey) + // logText += stdoutBuffer.String() + "\n" + // logText += stderrBuffer.String() + "\n" + // logText += "\n" + // if err != nil { + // logText += "Error installing dependency " + dependency + ": " + err.Error() + "\n" + stderrBuffer.String() + "\n" + // return nil + // } else { + // logText += "Dependency " + dependency + " installed successfully\n" + // } + // } + //} return nil } diff --git a/swiftwave_service/worker/process_pv_backup_request.go b/swiftwave_service/worker/process_pv_backup_request.go index 2ceeb03dd2..09c8db69d1 100644 --- a/swiftwave_service/worker/process_pv_backup_request.go +++ b/swiftwave_service/worker/process_pv_backup_request.go @@ -2,96 +2,92 @@ package worker import ( "context" - "github.com/google/uuid" "github.com/swiftwave-org/swiftwave/swiftwave_service/core" - "github.com/swiftwave-org/swiftwave/swiftwave_service/logger" - "github.com/swiftwave-org/swiftwave/swiftwave_service/manager" - "github.com/swiftwave-org/swiftwave/swiftwave_service/uploader" "gorm.io/gorm" "log" "os" - "path/filepath" ) func (m Manager) PersistentVolumeBackup(request PersistentVolumeBackupRequest, ctx context.Context, _ context.CancelFunc) error { - dbWithoutTx := m.ServiceManager.DbClient - // fetch persistent volume backup - var persistentVolumeBackup core.PersistentVolumeBackup - err := persistentVolumeBackup.FindById(ctx, dbWithoutTx, request.Id) - if err != nil { - return nil - } - // check status should be pending - if persistentVolumeBackup.Status != core.BackupPending { - return nil - } - // fetch persistent volume - var persistentVolume core.PersistentVolume - err = persistentVolume.FindById(ctx, dbWithoutTx, persistentVolumeBackup.PersistentVolumeID) - if err != nil { - return nil - } - // fetch swarm server - server, err := core.FetchSwarmManager(&dbWithoutTx) - if err != nil { - return err - } - dockerManager, err := manager.DockerClient(ctx, server) - if err != nil { - return err - } - // generate a random filename - backupFileName := persistentVolume.Name + "_" + uuid.NewString() + ".tar.gz" - backupFilePath := filepath.Join(m.Config.LocalConfig.ServiceConfig.PVBackupDirectoryPath, backupFileName) - // create backup - err = dockerManager.BackupVolume(persistentVolume.Name, backupFilePath, server.IP, server.SSHPort, server.User, m.Config.SystemConfig.SshPrivateKey) - if err != nil { - logger.CronJobLoggerError.Println("error while creating backup > " + err.Error()) - markPVBackupRequestAsFailed(dbWithoutTx, persistentVolumeBackup) - return nil - } - // fetch size - size, err := sizeOfFileInMB(backupFilePath) - if err != nil { - logger.CronJobLoggerError.Println("error while getting backup file size > " + err.Error()) - markPVBackupRequestAsFailed(dbWithoutTx, persistentVolumeBackup) - return nil - } - if persistentVolumeBackup.Type == core.S3Backup { - // upload to s3 - backupFileReader, err := os.Open(backupFilePath) - if err != nil { - logger.CronJobLoggerError.Println("error while opening backup file > " + err.Error()) - markPVBackupRequestAsFailed(dbWithoutTx, persistentVolumeBackup) - return nil - } - defer func() { - err := backupFileReader.Close() - if err != nil { - log.Println("failed to close backup file reader " + err.Error()) - } - }() - s3Config := m.Config.SystemConfig.PersistentVolumeBackupConfig.S3BackupConfig - err = uploader.UploadFileToS3(backupFileReader, backupFileName, s3Config.Bucket, s3Config) - if err != nil { - log.Println("error while uploading backup to s3 > " + err.Error()) - markPVBackupRequestAsFailed(dbWithoutTx, persistentVolumeBackup) - return nil - } - // remove the backup file - err = os.Remove(backupFilePath) - if err != nil { - log.Println("failed to remove backup file " + err.Error()) - } - } - // update status - persistentVolumeBackup.Status = core.BackupSuccess - persistentVolumeBackup.File = backupFileName - persistentVolumeBackup.FileSizeMB = size - err = persistentVolumeBackup.Update(ctx, dbWithoutTx) - if err != nil { - return err - } + // TODO fix + //dbWithoutTx := m.ServiceManager.DbClient + //// fetch persistent volume backup + //var persistentVolumeBackup core.PersistentVolumeBackup + //err := persistentVolumeBackup.FindById(ctx, dbWithoutTx, request.Id) + //if err != nil { + // return nil + //} + //// check status should be pending + //if persistentVolumeBackup.Status != core.BackupPending { + // return nil + //} + //// fetch persistent volume + //var persistentVolume core.PersistentVolume + //err = persistentVolume.FindById(ctx, dbWithoutTx, persistentVolumeBackup.PersistentVolumeID) + //if err != nil { + // return nil + //} + //// fetch swarm server + //server, err := core.FetchSwarmManager(&dbWithoutTx) + //if err != nil { + // return err + //} + //dockerManager, err := manager.DockerClient(ctx, server) + //if err != nil { + // return err + //} + //// generate a random filename + //backupFileName := persistentVolume.Name + "_" + uuid.NewString() + ".tar.gz" + //backupFilePath := filepath.Join(m.Config.LocalConfig.ServiceConfig.PVBackupDirectoryPath, backupFileName) + //// create backup + //err = dockerManager.BackupVolume(persistentVolume.Name, backupFilePath, server.IP, server.SSHPort, server.User, m.Config.SystemConfig.SshPrivateKey) + //if err != nil { + // logger.CronJobLoggerError.Println("error while creating backup > " + err.Error()) + // markPVBackupRequestAsFailed(dbWithoutTx, persistentVolumeBackup) + // return nil + //} + //// fetch size + //size, err := sizeOfFileInMB(backupFilePath) + //if err != nil { + // logger.CronJobLoggerError.Println("error while getting backup file size > " + err.Error()) + // markPVBackupRequestAsFailed(dbWithoutTx, persistentVolumeBackup) + // return nil + //} + //if persistentVolumeBackup.Type == core.S3Backup { + // // upload to s3 + // backupFileReader, err := os.Open(backupFilePath) + // if err != nil { + // logger.CronJobLoggerError.Println("error while opening backup file > " + err.Error()) + // markPVBackupRequestAsFailed(dbWithoutTx, persistentVolumeBackup) + // return nil + // } + // defer func() { + // err := backupFileReader.Close() + // if err != nil { + // log.Println("failed to close backup file reader " + err.Error()) + // } + // }() + // s3Config := m.Config.SystemConfig.PersistentVolumeBackupConfig.S3BackupConfig + // err = uploader.UploadFileToS3(backupFileReader, backupFileName, s3Config.Bucket, s3Config) + // if err != nil { + // log.Println("error while uploading backup to s3 > " + err.Error()) + // markPVBackupRequestAsFailed(dbWithoutTx, persistentVolumeBackup) + // return nil + // } + // // remove the backup file + // err = os.Remove(backupFilePath) + // if err != nil { + // log.Println("failed to remove backup file " + err.Error()) + // } + //} + //// update status + //persistentVolumeBackup.Status = core.BackupSuccess + //persistentVolumeBackup.File = backupFileName + //persistentVolumeBackup.FileSizeMB = size + //err = persistentVolumeBackup.Update(ctx, dbWithoutTx) + //if err != nil { + // return err + //} return nil } diff --git a/swiftwave_service/worker/process_pv_restore_request.go b/swiftwave_service/worker/process_pv_restore_request.go index 9f1dd5c385..1decc44e85 100644 --- a/swiftwave_service/worker/process_pv_restore_request.go +++ b/swiftwave_service/worker/process_pv_restore_request.go @@ -3,55 +3,53 @@ package worker import ( "context" "github.com/swiftwave-org/swiftwave/swiftwave_service/core" - "github.com/swiftwave-org/swiftwave/swiftwave_service/manager" "gorm.io/gorm" - "os" - "path/filepath" ) func (m Manager) PersistentVolumeRestore(request PersistentVolumeRestoreRequest, ctx context.Context, _ context.CancelFunc) error { - dbWithoutTx := m.ServiceManager.DbClient - // fetch persistent volume restore - var persistentVolumeRestore core.PersistentVolumeRestore - err := persistentVolumeRestore.FindById(ctx, dbWithoutTx, request.Id) - if err != nil { - return nil - } - // check status should be uploaded - if persistentVolumeRestore.Status != core.RestorePending { - return nil - } - // fetch persistent volume - var persistentVolume core.PersistentVolume - err = persistentVolume.FindById(ctx, dbWithoutTx, persistentVolumeRestore.PersistentVolumeID) - if err != nil { - return nil - } - // fetch swarm server - server, err := core.FetchSwarmManager(&dbWithoutTx) - if err != nil { - return err - } - dockerManager, err := manager.DockerClient(ctx, server) - if err != nil { - return err - } - // restore backup - localRestoreFilePath := filepath.Join(m.Config.LocalConfig.ServiceConfig.PVRestoreDirectoryPath, persistentVolumeRestore.File) - err = dockerManager.RestoreVolume(persistentVolume.Name, localRestoreFilePath, server.IP, server.SSHPort, server.User, m.Config.SystemConfig.SshPrivateKey) - if err != nil { - markPVRestoreRequestAsFailed(dbWithoutTx, persistentVolumeRestore) - _ = os.RemoveAll(localRestoreFilePath) - return nil - } - // update status - persistentVolumeRestore.Status = core.RestoreSuccess - err = persistentVolumeRestore.Update(ctx, dbWithoutTx, m.Config.LocalConfig.ServiceConfig.PVRestoreDirectoryPath) - if err != nil { - return err - } - // remove local file - _ = os.RemoveAll(localRestoreFilePath) + // TODO fix + //dbWithoutTx := m.ServiceManager.DbClient + //// fetch persistent volume restore + //var persistentVolumeRestore core.PersistentVolumeRestore + //err := persistentVolumeRestore.FindById(ctx, dbWithoutTx, request.Id) + //if err != nil { + // return nil + //} + //// check status should be uploaded + //if persistentVolumeRestore.Status != core.RestorePending { + // return nil + //} + //// fetch persistent volume + //var persistentVolume core.PersistentVolume + //err = persistentVolume.FindById(ctx, dbWithoutTx, persistentVolumeRestore.PersistentVolumeID) + //if err != nil { + // return nil + //} + //// fetch swarm server + //server, err := core.FetchSwarmManager(&dbWithoutTx) + //if err != nil { + // return err + //} + //dockerManager, err := manager.DockerClient(ctx, server) + //if err != nil { + // return err + //} + //// restore backup + //localRestoreFilePath := filepath.Join(m.Config.LocalConfig.ServiceConfig.PVRestoreDirectoryPath, persistentVolumeRestore.File) + //err = dockerManager.RestoreVolume(persistentVolume.Name, localRestoreFilePath, server.IP, server.SSHPort, server.User, m.Config.SystemConfig.SshPrivateKey) + //if err != nil { + // markPVRestoreRequestAsFailed(dbWithoutTx, persistentVolumeRestore) + // _ = os.RemoveAll(localRestoreFilePath) + // return nil + //} + //// update status + //persistentVolumeRestore.Status = core.RestoreSuccess + //err = persistentVolumeRestore.Update(ctx, dbWithoutTx, m.Config.LocalConfig.ServiceConfig.PVRestoreDirectoryPath) + //if err != nil { + // return err + //} + //// remove local file + //_ = os.RemoveAll(localRestoreFilePath) return nil } diff --git a/swiftwave_service/worker/process_setup_proxy_request.go b/swiftwave_service/worker/process_setup_proxy_request.go index 2d94c714b1..2d95e7a68b 100644 --- a/swiftwave_service/worker/process_setup_proxy_request.go +++ b/swiftwave_service/worker/process_setup_proxy_request.go @@ -4,11 +4,7 @@ import ( "context" "errors" "fmt" - "github.com/swiftwave-org/swiftwave/pkg/ssh_toolkit" "github.com/swiftwave-org/swiftwave/swiftwave_service/config" - "github.com/swiftwave-org/swiftwave/swiftwave_service/core" - "github.com/swiftwave-org/swiftwave/swiftwave_service/logger" - "gorm.io/gorm" "io" "log" "net/http" @@ -16,115 +12,116 @@ import ( "os/exec" "strconv" "strings" - "time" ) func (m Manager) SetupAndEnableProxy(request SetupAndEnableProxyRequest, ctx context.Context, cancelCtx context.CancelFunc) error { - // fetch server - server, err := core.FetchServerByID(&m.ServiceManager.DbClient, request.ServerId) - if err != nil { - if errors.Is(err, gorm.ErrRecordNotFound) { - return nil - } - return err - } - err = m.setupAndEnableProxy(request, ctx, cancelCtx) - if err == nil { - // mark server as proxy enabled - server.ProxyConfig.Enabled = true - server.ProxyConfig.SetupRunning = false - err = core.UpdateServer(&m.ServiceManager.DbClient, server) - if err != nil { - logger.WorkerLoggerError.Println("Failed to update server "+server.HostName+" proxy config", err.Error()) - } else { - logger.WorkerLogger.Println("Proxy config updated for server " + server.HostName) - } - } + // TODO fix + //// fetch server + //server, err := core.FetchServerByID(&m.ServiceManager.DbClient, request.ServerId) + //if err != nil { + // if errors.Is(err, gorm.ErrRecordNotFound) { + // return nil + // } + // return err + //} + //err = m.setupAndEnableProxy(request, ctx, cancelCtx) + //if err == nil { + // // mark server as proxy enabled + // server.ProxyConfig.Enabled = true + // server.ProxyConfig.SetupRunning = false + // err = core.UpdateServer(&m.ServiceManager.DbClient, server) + // if err != nil { + // logger.WorkerLoggerError.Println("Failed to update server "+server.HostName+" proxy config", err.Error()) + // } else { + // logger.WorkerLogger.Println("Proxy config updated for server " + server.HostName) + // } + //} return nil } func (m Manager) setupAndEnableProxy(request SetupAndEnableProxyRequest, ctx context.Context, _ context.CancelFunc) error { - // fetch server - server, err := core.FetchServerByID(&m.ServiceManager.DbClient, request.ServerId) - if err != nil { - if errors.Is(err, gorm.ErrRecordNotFound) { - return nil - } - return err - } - // fetch server log - serverLog, err := core.FetchServerLogByID(&m.ServiceManager.DbClient, request.LogId) - if err != nil { - if errors.Is(err, gorm.ErrRecordNotFound) { - return nil - } - return err - } - // log - logText := "Starting proxy setup on server " + server.HostName + "\n" - // spawn a goroutine to update server log each 5 seconds - go func() { - lastSent := time.Now() - for { - select { - case <-ctx.Done(): - return - default: - if time.Since(lastSent) > 5*time.Second { - serverLog.Content = logText - _ = serverLog.Update(&m.ServiceManager.DbClient) - lastSent = time.Now() - } - } - } - }() - // defer to push final log - defer func() { - serverLog.Content = logText - _ = serverLog.Update(&m.ServiceManager.DbClient) - }() - // fill local haproxy configuration (will be skipped anyhow if already exists) - err = generateDefaultHAProxyConfiguration(m.Config) - if err != nil { - logText += "Failed to generate default haproxy configuration: " + err.Error() + "\n" - return err - } - // check if any proxy server is already running - servers, err := core.FetchAllProxyServers(&m.ServiceManager.DbClient) - if err != nil { - logText += "Failed to fetch all proxy servers: " + err.Error() + "\n" - return err - } - - if len(servers) > 0 { - var chosenServer core.Server - // try to find out an active proxy server - activeProxyServer, err := core.FetchRandomActiveProxyServer(&m.ServiceManager.DbClient) - if err == nil { - chosenServer = activeProxyServer - } else { - // if no active proxy server found, choose a random one - chosenServer = servers[0] - } - // copy haproxy directory to the management server - logText += "Copying haproxy config from server " + chosenServer.HostName + " to local\n" - err = ssh_toolkit.CopyFolderFromRemoteServer(m.Config.LocalConfig.ServiceConfig.HAProxyDataDirectoryPath, m.Config.LocalConfig.ServiceConfig.HAProxyDataDirectoryPath, chosenServer.IP, chosenServer.SSHPort, chosenServer.User, m.Config.SystemConfig.SshPrivateKey) - if err != nil { - logText += "Failed to copy haproxy config from server " + chosenServer.HostName + " to " + server.HostName + "\n" - logText += "Error: " + err.Error() + "\n" - return err - } - } - // copy haproxy directory to the server - logText += "Copying haproxy config from local to server " + server.HostName + "\n" - err = ssh_toolkit.CopyFolderToRemoteServer(m.Config.LocalConfig.ServiceConfig.HAProxyDataDirectoryPath, m.Config.LocalConfig.ServiceConfig.HAProxyDataDirectoryPath, server.IP, server.SSHPort, server.User, m.Config.SystemConfig.SshPrivateKey) - if err != nil { - logText += "Failed to copy haproxy config from local to server " + server.HostName + "\n" - logText += "Error: " + err.Error() + "\n" - return err - } - - logText += "Copied haproxy config from local to server " + server.HostName + "\n" - log.Println("Copied haproxy config from local to server " + server.HostName) + // TODO fix + //// fetch server + //server, err := core.FetchServerByID(&m.ServiceManager.DbClient, request.ServerId) + //if err != nil { + // if errors.Is(err, gorm.ErrRecordNotFound) { + // return nil + // } + // return err + //} + //// fetch server log + //serverLog, err := core.FetchServerLogByID(&m.ServiceManager.DbClient, request.LogId) + //if err != nil { + // if errors.Is(err, gorm.ErrRecordNotFound) { + // return nil + // } + // return err + //} + //// log + //logText := "Starting proxy setup on server " + server.HostName + "\n" + //// spawn a goroutine to update server log each 5 seconds + //go func() { + // lastSent := time.Now() + // for { + // select { + // case <-ctx.Done(): + // return + // default: + // if time.Since(lastSent) > 5*time.Second { + // serverLog.Content = logText + // _ = serverLog.Update(&m.ServiceManager.DbClient) + // lastSent = time.Now() + // } + // } + // } + //}() + //// defer to push final log + //defer func() { + // serverLog.Content = logText + // _ = serverLog.Update(&m.ServiceManager.DbClient) + //}() + //// fill local haproxy configuration (will be skipped anyhow if already exists) + //err = generateDefaultHAProxyConfiguration(m.Config) + //if err != nil { + // logText += "Failed to generate default haproxy configuration: " + err.Error() + "\n" + // return err + //} + //// check if any proxy server is already running + //servers, err := core.FetchAllProxyServers(&m.ServiceManager.DbClient) + //if err != nil { + // logText += "Failed to fetch all proxy servers: " + err.Error() + "\n" + // return err + //} + // + //if len(servers) > 0 { + // var chosenServer core.Server + // // try to find out an active proxy server + // activeProxyServer, err := core.FetchRandomActiveProxyServer(&m.ServiceManager.DbClient) + // if err == nil { + // chosenServer = activeProxyServer + // } else { + // // if no active proxy server found, choose a random one + // chosenServer = servers[0] + // } + // // copy haproxy directory to the management server + // logText += "Copying haproxy config from server " + chosenServer.HostName + " to local\n" + // err = ssh_toolkit.CopyFolderFromRemoteServer(m.Config.LocalConfig.ServiceConfig.HAProxyDataDirectoryPath, m.Config.LocalConfig.ServiceConfig.HAProxyDataDirectoryPath, chosenServer.IP, chosenServer.SSHPort, chosenServer.User, m.Config.SystemConfig.SshPrivateKey) + // if err != nil { + // logText += "Failed to copy haproxy config from server " + chosenServer.HostName + " to " + server.HostName + "\n" + // logText += "Error: " + err.Error() + "\n" + // return err + // } + //} + //// copy haproxy directory to the server + //logText += "Copying haproxy config from local to server " + server.HostName + "\n" + //err = ssh_toolkit.CopyFolderToRemoteServer(m.Config.LocalConfig.ServiceConfig.HAProxyDataDirectoryPath, m.Config.LocalConfig.ServiceConfig.HAProxyDataDirectoryPath, server.IP, server.SSHPort, server.User, m.Config.SystemConfig.SshPrivateKey) + //if err != nil { + // logText += "Failed to copy haproxy config from local to server " + server.HostName + "\n" + // logText += "Error: " + err.Error() + "\n" + // return err + //} + // + //logText += "Copied haproxy config from local to server " + server.HostName + "\n" + //log.Println("Copied haproxy config from local to server " + server.HostName) return nil } diff --git a/swiftwave_service/worker/process_setup_server_request.go b/swiftwave_service/worker/process_setup_server_request.go index dee8fb950d..171ab8abe0 100644 --- a/swiftwave_service/worker/process_setup_server_request.go +++ b/swiftwave_service/worker/process_setup_server_request.go @@ -1,12 +1,8 @@ package worker import ( - "bytes" "context" "errors" - "fmt" - containermanger "github.com/swiftwave-org/swiftwave/pkg/container_manager" - "github.com/swiftwave-org/swiftwave/pkg/ssh_toolkit" "github.com/swiftwave-org/swiftwave/swiftwave_service/core" "github.com/swiftwave-org/swiftwave/swiftwave_service/logger" "gorm.io/gorm" @@ -36,6 +32,7 @@ func (m Manager) SetupServer(request SetupServerRequest, ctx context.Context, _ func (m Manager) setupServerHelper(request SetupServerRequest, ctx context.Context, _ context.CancelFunc) error { // fetch server server, err := core.FetchServerByID(&m.ServiceManager.DbClient, request.ServerId) + _ = server if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil @@ -93,167 +90,170 @@ func (m Manager) setupServerHelper(request SetupServerRequest, ctx context.Conte } for _, dir := range directories { - stdoutBuf := bytes.Buffer{} - stderrBuf := bytes.Buffer{} - err := ssh_toolkit.ExecCommandOverSSH(fmt.Sprintf("mkdir -p %s && chmod -R 0711 %s", dir, dir), &stdoutBuf, &stderrBuf, 5, server.IP, server.SSHPort, server.User, m.Config.SystemConfig.SshPrivateKey) - if err != nil { - logText += "Failed to create folder " + dir + "\n" - logText += stdoutBuf.String() + "\n" + stderrBuf.String() + "\n" - return err - } else { - logText += "Folder created > " + dir + "\n" - } + _ = dir + // TODO fix + //stdoutBuf := bytes.Buffer{} + //stderrBuf := bytes.Buffer{} + //err := ssh_toolkit.ExecCommandOverSSH(fmt.Sprintf("mkdir -p %s && chmod -R 0711 %s", dir, dir), &stdoutBuf, &stderrBuf, 5, server.IP, server.SSHPort, server.User, m.Config.SystemConfig.SshPrivateKey) + //if err != nil { + // logText += "Failed to create folder " + dir + "\n" + // logText += stdoutBuf.String() + "\n" + stderrBuf.String() + "\n" + // return err + //} else { + // logText += "Folder created > " + dir + "\n" + //} } - // check docker socket - conn, err := ssh_toolkit.NetConnOverSSH("unix", server.DockerUnixSocketPath, 5, server.IP, server.SSHPort, server.User, m.Config.SystemConfig.SshPrivateKey) - if err != nil { - logText += "Failed to connect to docker socket\n" - logText += fmt.Sprintf("%s should have acess to %s\n", server.User, server.DockerUnixSocketPath) - logText += err.Error() + "\n" - return err - } + // TODO fix + //// check docker socket + //conn, err := ssh_toolkit.NetConnOverSSH("unix", server.DockerUnixSocketPath, 5, server.IP, server.SSHPort, server.User, m.Config.SystemConfig.SshPrivateKey) + //if err != nil { + // logText += "Failed to connect to docker socket\n" + // logText += fmt.Sprintf("%s should have acess to %s\n", server.User, server.DockerUnixSocketPath) + // logText += err.Error() + "\n" + // return err + //} - // create a docker client - dockerClient, err := containermanger.New(ctx, conn) - if err != nil { - logText += "Failed to create docker client\n" - logText += err.Error() + "\n" - return err - } + //// create a docker client + //dockerClient, err := containermanger.New(ctx, conn) + //if err != nil { + // logText += "Failed to create docker client\n" + // logText += err.Error() + "\n" + // return err + //} + // + //defer func() { + // _ = dockerClient.Close() + //}() + // + //// Try to list volume [just to check if the docker client is working] + //_, err = dockerClient.FetchVolumes() + //if err != nil { + // logText += "Failed to connect to docker daemon\n" + // logText += err.Error() + "\n" + // return err + //} else { + // logText += "Docker client connected\n" + //} + // + //// Proceed request logic (reject in any other case) + //// - if, want to be manager + //// - if, there are some managers already, need to be online any of them + //// - if, no servers, then it will be the first manager + //// - if, want to be worker + //// - there need to be at least one manager + //var swarmManagerServer *core.Server + //if server.SwarmMode == core.SwarmManager { + // // Check if there are some servers already + // exists, err := core.IsPreparedServerExists(&m.ServiceManager.DbClient) + // if err != nil { + // logText += "Failed to check if there are some servers already\n" + // logText += err.Error() + "\n" + // return err + // } + // if exists { + // // Try to find out if there is any manager online + // r, err := core.FetchSwarmManager(&m.ServiceManager.DbClient) + // if err != nil { + // logText += "Failed to find out if there is any swarm manager online\n" + // logText += err.Error() + "\n" + // return err + // } + // swarmManagerServer = &r + // } + //} else { + // // Check if there is any manager + // r, err := core.FetchSwarmManager(&m.ServiceManager.DbClient) + // if err != nil { + // logText += "Failed to find out if there is any swarm manager\n" + // logText += err.Error() + "\n" + // return err + // } + // swarmManagerServer = &r + //} - defer func() { - _ = dockerClient.Close() - }() + //if swarmManagerServer == nil && server.SwarmMode == core.SwarmWorker { + // logText += "No manager found\n" + // logText += "At least one active swarm manager is required in cluster to add a worker\n" + // return err + //} - // Try to list volume [just to check if the docker client is working] - _, err = dockerClient.FetchVolumes() - if err != nil { - logText += "Failed to connect to docker daemon\n" - logText += err.Error() + "\n" - return err - } else { - logText += "Docker client connected\n" - } + //// NOTE: From here, if `swarmManagerServer` is nil, then this new server can be initialized as first swarm manager + //if swarmManagerServer == nil { + // // Initialize as first swarm manager + // err = dockerClient.InitializeAsManager(request.AdvertiseIP) + // if err != nil { + // logText += "Failed to initialize as first swarm manager\n" + // logText += err.Error() + "\n" + // return err + // } + //} else { + // // Get docker client of swarm manager + // swarmManagerConn, err := ssh_toolkit.NetConnOverSSH("unix", swarmManagerServer.DockerUnixSocketPath, 5, swarmManagerServer.IP, swarmManagerServer.SSHPort, swarmManagerServer.User, m.Config.SystemConfig.SshPrivateKey) + // if err != nil { + // logText += "Failed to connect to swarm manager\n" + // logText += err.Error() + "\n" + // return err + // } + // swarmManagerDockerClient, err := containermanger.New(ctx, swarmManagerConn) + // if err != nil { + // logText += "Failed to create docker client for swarm manager\n" + // logText += err.Error() + "\n" + // return err + // } + // // Fetch cluster join token from swarm manager + // var joinToken string + // if server.SwarmMode == core.SwarmManager { + // token, err := swarmManagerDockerClient.GenerateManagerJoinToken() + // if err != nil { + // logText += "Failed to generate manager join token\n" + // logText += err.Error() + "\n" + // return err + // } + // joinToken = token + // } else { + // token, err := swarmManagerDockerClient.GenerateWorkerJoinToken() + // if err != nil { + // logText += "Failed to generate worker join token\n" + // logText += err.Error() + "\n" + // return err + // } + // joinToken = token + // } + // // Add node to swarm cluster + // err = dockerClient.JoinSwarm(fmt.Sprintf("%s:2377", swarmManagerServer.IP), joinToken, request.AdvertiseIP) + // if err != nil { + // logText += "Failed to join swarm cluster\n" + // logText += err.Error() + "\n" + // return err + // } + //} - // Proceed request logic (reject in any other case) - // - if, want to be manager - // - if, there are some managers already, need to be online any of them - // - if, no servers, then it will be the first manager - // - if, want to be worker - // - there need to be at least one manager - var swarmManagerServer *core.Server - if server.SwarmMode == core.SwarmManager { - // Check if there are some servers already - exists, err := core.IsPreparedServerExists(&m.ServiceManager.DbClient) - if err != nil { - logText += "Failed to check if there are some servers already\n" - logText += err.Error() + "\n" - return err - } - if exists { - // Try to find out if there is any manager online - r, err := core.FetchSwarmManager(&m.ServiceManager.DbClient) - if err != nil { - logText += "Failed to find out if there is any swarm manager online\n" - logText += err.Error() + "\n" - return err - } - swarmManagerServer = &r - } - } else { - // Check if there is any manager - r, err := core.FetchSwarmManager(&m.ServiceManager.DbClient) - if err != nil { - logText += "Failed to find out if there is any swarm manager\n" - logText += err.Error() + "\n" - return err - } - swarmManagerServer = &r - } - - if swarmManagerServer == nil && server.SwarmMode == core.SwarmWorker { - logText += "No manager found\n" - logText += "At least one active swarm manager is required in cluster to add a worker\n" - return err - } - - // NOTE: From here, if `swarmManagerServer` is nil, then this new server can be initialized as first swarm manager - if swarmManagerServer == nil { - // Initialize as first swarm manager - err = dockerClient.InitializeAsManager(request.AdvertiseIP) - if err != nil { - logText += "Failed to initialize as first swarm manager\n" - logText += err.Error() + "\n" - return err - } - } else { - // Get docker client of swarm manager - swarmManagerConn, err := ssh_toolkit.NetConnOverSSH("unix", swarmManagerServer.DockerUnixSocketPath, 5, swarmManagerServer.IP, swarmManagerServer.SSHPort, swarmManagerServer.User, m.Config.SystemConfig.SshPrivateKey) - if err != nil { - logText += "Failed to connect to swarm manager\n" - logText += err.Error() + "\n" - return err - } - swarmManagerDockerClient, err := containermanger.New(ctx, swarmManagerConn) - if err != nil { - logText += "Failed to create docker client for swarm manager\n" - logText += err.Error() + "\n" - return err - } - // Fetch cluster join token from swarm manager - var joinToken string - if server.SwarmMode == core.SwarmManager { - token, err := swarmManagerDockerClient.GenerateManagerJoinToken() - if err != nil { - logText += "Failed to generate manager join token\n" - logText += err.Error() + "\n" - return err - } - joinToken = token - } else { - token, err := swarmManagerDockerClient.GenerateWorkerJoinToken() - if err != nil { - logText += "Failed to generate worker join token\n" - logText += err.Error() + "\n" - return err - } - joinToken = token - } - // Add node to swarm cluster - err = dockerClient.JoinSwarm(fmt.Sprintf("%s:2377", swarmManagerServer.IP), joinToken, request.AdvertiseIP) - if err != nil { - logText += "Failed to join swarm cluster\n" - logText += err.Error() + "\n" - return err - } - } - - // create all the volume in the server - pvVolumes, err := core.FindAllPersistentVolumes(ctx, m.ServiceManager.DbClient) - if err != nil { - logText += "Failed to find all persistent volumes\nUser may need to create them manually\n" - logText += err.Error() + "\n" - } - for _, persistentVolume := range pvVolumes { - // remove volume (try) - _ = dockerClient.RemoveVolume(persistentVolume.Name) - // create volume - var err error - if persistentVolume.Type == core.PersistentVolumeTypeLocal { - err = dockerClient.CreateLocalVolume(persistentVolume.Name) - } else if persistentVolume.Type == core.PersistentVolumeTypeNFS { - err = dockerClient.CreateNFSVolume(persistentVolume.Name, persistentVolume.NFSConfig.Host, persistentVolume.NFSConfig.Path, persistentVolume.NFSConfig.Version) - } else if persistentVolume.Type == core.PersistentVolumeTypeCIFS { - err = dockerClient.CreateCIFSVolume(persistentVolume.Name, persistentVolume.CIFSConfig.Host, persistentVolume.CIFSConfig.Share, persistentVolume.CIFSConfig.Username, persistentVolume.CIFSConfig.Password, persistentVolume.CIFSConfig.FileMode, persistentVolume.CIFSConfig.DirMode, persistentVolume.CIFSConfig.Uid, persistentVolume.CIFSConfig.Gid) - } - if err != nil { - logText += "Failed to add persistent volume " + persistentVolume.Name + "\n" - logText += err.Error() + "\n" - } else { - logText += "Persistent volume " + persistentVolume.Name + " added successfully\n" - } - } + //// create all the volume in the server + //pvVolumes, err := core.FindAllPersistentVolumes(ctx, m.ServiceManager.DbClient) + //if err != nil { + // logText += "Failed to find all persistent volumes\nUser may need to create them manually\n" + // logText += err.Error() + "\n" + //} + //for _, persistentVolume := range pvVolumes { + // // remove volume (try) + // _ = dockerClient.RemoveVolume(persistentVolume.Name) + // // create volume + // var err error + // if persistentVolume.Type == core.PersistentVolumeTypeLocal { + // err = dockerClient.CreateLocalVolume(persistentVolume.Name) + // } else if persistentVolume.Type == core.PersistentVolumeTypeNFS { + // err = dockerClient.CreateNFSVolume(persistentVolume.Name, persistentVolume.NFSConfig.Host, persistentVolume.NFSConfig.Path, persistentVolume.NFSConfig.Version) + // } else if persistentVolume.Type == core.PersistentVolumeTypeCIFS { + // err = dockerClient.CreateCIFSVolume(persistentVolume.Name, persistentVolume.CIFSConfig.Host, persistentVolume.CIFSConfig.Share, persistentVolume.CIFSConfig.Username, persistentVolume.CIFSConfig.Password, persistentVolume.CIFSConfig.FileMode, persistentVolume.CIFSConfig.DirMode, persistentVolume.CIFSConfig.Uid, persistentVolume.CIFSConfig.Gid) + // } + // if err != nil { + // logText += "Failed to add persistent volume " + persistentVolume.Name + "\n" + // logText += err.Error() + "\n" + // } else { + // logText += "Persistent volume " + persistentVolume.Name + " added successfully\n" + // } + //} // set log logText += "Server is ready for deployment\n" From d5a44c312e8ec957cf10445fd8d8591edf2b4b09 Mon Sep 17 00:00:00 2001 From: tanmoysrt <57363826+tanmoysrt@users.noreply.github.com> Date: Fri, 14 Mar 2025 14:55:48 +0530 Subject: [PATCH 2/7] feat: add agent token to server --- swiftwave_service/core/models.go | 1 + 1 file changed, 1 insertion(+) diff --git a/swiftwave_service/core/models.go b/swiftwave_service/core/models.go index c4de9bb675..0769f666f3 100644 --- a/swiftwave_service/core/models.go +++ b/swiftwave_service/core/models.go @@ -11,6 +11,7 @@ type Server struct { ID uint `json:"id" gorm:"primaryKey"` Name string `json:"name" gorm:"unique"` PublicIP string `json:"public_ip" gorm:"not null"` + AgentToken string `json:"agent_token" gorm:"unique"` WireguardConfig WireguardConfig `json:"wireguard_config" gorm:"embedded;embeddedPrefix:wireguard_"` ScheduleDeployments bool `json:"schedule_deployments" gorm:"default:true"` ProxyConfig ProxyConfig `json:"proxy_config" gorm:"embedded;embeddedPrefix:proxy_"` From 118e57a553278db2d069d53b9fabd907992d3e19 Mon Sep 17 00:00:00 2001 From: tanmoysrt <57363826+tanmoysrt@users.noreply.github.com> Date: Fri, 14 Mar 2025 15:19:21 +0530 Subject: [PATCH 3/7] chore: get rid of console and analytics token --- .../analytics_service_token.operations.go | 63 --------- .../core/console_token.operations.go | 74 ----------- swiftwave_service/core/models.go | 48 ++----- swiftwave_service/core/types.go | 8 -- swiftwave_service/graphql/generated.go | 120 ------------------ .../graphql/persistent_volume.resolvers.go | 1 + .../graphql/schema/server.graphqls | 1 - swiftwave_service/graphql/server.resolvers.go | 16 --- 8 files changed, 12 insertions(+), 319 deletions(-) delete mode 100644 swiftwave_service/core/analytics_service_token.operations.go delete mode 100644 swiftwave_service/core/console_token.operations.go diff --git a/swiftwave_service/core/analytics_service_token.operations.go b/swiftwave_service/core/analytics_service_token.operations.go deleted file mode 100644 index 8a821c6ac8..0000000000 --- a/swiftwave_service/core/analytics_service_token.operations.go +++ /dev/null @@ -1,63 +0,0 @@ -package core - -import ( - "context" - "errors" - "fmt" - "github.com/google/uuid" - "github.com/labstack/gommon/random" - "gorm.io/gorm" -) - -func FetchAnalyticsServiceToken(ctx context.Context, db gorm.DB, serverId uint) (*AnalyticsServiceToken, error) { - // check if token exists - var tokenData AnalyticsServiceToken - tx := db.Where("server_id = ?", serverId).First(&tokenData) - if tx.Error == nil { - return &tokenData, nil - } - // create a new token - tokenData = AnalyticsServiceToken{ - ID: uuid.NewString(), - Token: random.String(32), - ServerID: serverId, - } - tx = db.Create(&tokenData) - if tx.Error != nil { - return nil, tx.Error - } - return &tokenData, nil -} - -func (token *AnalyticsServiceToken) IDToken() (string, error) { - if token == nil { - return "", errors.New("token is nil") - } - return fmt.Sprintf("%s:%s", token.ID, token.Token), nil -} - -func DeleteAnalyticsServiceToken(ctx context.Context, db gorm.DB, serverId uint) error { - tx := db.Where("server_id = ?", serverId).Delete(&AnalyticsServiceToken{}) - if tx.Error != nil { - // don't return error if token does not exist - if errors.Is(tx.Error, gorm.ErrRecordNotFound) { - return nil - } else { - return tx.Error - } - } - return nil -} - -// RotateAnalyticsServiceToken : delete existing token and create a new token. [Recommended to use transaction] -func RotateAnalyticsServiceToken(ctx context.Context, db gorm.DB, serverId uint) (*AnalyticsServiceToken, error) { - // delete existing token - err := DeleteAnalyticsServiceToken(ctx, db, serverId) - if err != nil { - if !errors.Is(err, gorm.ErrRecordNotFound) { - return nil, err - } - } - // create a new token - return FetchAnalyticsServiceToken(ctx, db, serverId) -} diff --git a/swiftwave_service/core/console_token.operations.go b/swiftwave_service/core/console_token.operations.go deleted file mode 100644 index a3083b3e6d..0000000000 --- a/swiftwave_service/core/console_token.operations.go +++ /dev/null @@ -1,74 +0,0 @@ -package core - -import ( - "context" - "errors" - "github.com/google/uuid" - "github.com/labstack/gommon/random" - "gorm.io/gorm" - "time" -) - -func GenerateConsoleTokenForServer(db gorm.DB, serverId uint) (*ConsoleToken, error) { - // find server - server, err := FetchServerByID(&db, serverId) - if err != nil { - return nil, errors.New("failed to fetch server") - } - // generate token - record := &ConsoleToken{ - ID: uuid.NewString(), - Target: ConsoleTargetTypeServer, - ServerID: &server.ID, - ExpiresAt: time.Now().Add(time.Minute * 1), - Token: random.String(64), - } - // save record - tx := db.Create(record) - if tx.Error != nil { - return nil, tx.Error - } - return record, nil -} - -func GenerateConsoleTokenForApplication(db gorm.DB, applicationId string, targetServerId uint) (*ConsoleToken, error) { - // find application - application := &Application{} - err := application.FindById(context.TODO(), db, applicationId) - if err != nil { - return nil, errors.New("failed to fetch application") - } - // generate token - record := &ConsoleToken{ - ID: uuid.NewString(), - Target: ConsoleTargetTypeApplication, - ApplicationID: &application.ID, - ServerID: &targetServerId, - ExpiresAt: time.Now().Add(time.Minute * 1), - Token: random.String(64), - } - // save record - tx := db.Create(record) - if tx.Error != nil { - return nil, tx.Error - } - return record, nil -} - -func FindConsoleToken(db gorm.DB, id string, token string) (*ConsoleToken, error) { - // read from DB - record := &ConsoleToken{} - tx := db.First(record, "id = ? AND token = ?", id, token) - if tx.Error != nil { - return nil, tx.Error - } - // delete from DB (defer) - defer func() { - _ = db.Delete(record) - }() - // check if expired - if record.ExpiresAt.Before(time.Now()) { - return nil, errors.New("token expired") - } - return record, nil -} diff --git a/swiftwave_service/core/models.go b/swiftwave_service/core/models.go index 0769f666f3..4380f43dca 100644 --- a/swiftwave_service/core/models.go +++ b/swiftwave_service/core/models.go @@ -8,19 +8,17 @@ import ( // Server hold information about server type Server struct { - ID uint `json:"id" gorm:"primaryKey"` - Name string `json:"name" gorm:"unique"` - PublicIP string `json:"public_ip" gorm:"not null"` - AgentToken string `json:"agent_token" gorm:"unique"` - WireguardConfig WireguardConfig `json:"wireguard_config" gorm:"embedded;embeddedPrefix:wireguard_"` - ScheduleDeployments bool `json:"schedule_deployments" gorm:"default:true"` - ProxyConfig ProxyConfig `json:"proxy_config" gorm:"embedded;embeddedPrefix:proxy_"` - Status ServerStatus `json:"status"` - LastPing time.Time `json:"last_ping"` - Logs []ServerLog `json:"logs" gorm:"foreignKey:ServerID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"` - ConsoleTokens []ConsoleToken `json:"console_tokens" gorm:"foreignKey:ServerID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"` - AnalyticsServiceToken *AnalyticsServiceToken `json:"analytics_service_token" gorm:"foreignKey:ServerID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"` - ResourceStats []ServerResourceStat `json:"resource_stats" gorm:"foreignKey:ServerID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"` + ID uint `json:"id" gorm:"primaryKey"` + Name string `json:"name" gorm:"unique"` + PublicIP string `json:"public_ip" gorm:"not null"` + AgentToken string `json:"agent_token" gorm:"unique"` + WireguardConfig WireguardConfig `json:"wireguard_config" gorm:"embedded;embeddedPrefix:wireguard_"` + ScheduleDeployments bool `json:"schedule_deployments" gorm:"default:true"` + ProxyConfig ProxyConfig `json:"proxy_config" gorm:"embedded;embeddedPrefix:proxy_"` + Status ServerStatus `json:"status"` + LastPing time.Time `json:"last_ping"` + Logs []ServerLog `json:"logs" gorm:"foreignKey:ServerID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"` + ResourceStats []ServerResourceStat `json:"resource_stats" gorm:"foreignKey:ServerID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"` } // ServerLog hold logs of server @@ -262,8 +260,6 @@ type Application struct { ResourceLimit ApplicationResourceLimit `json:"resource_limit" gorm:"embedded;embeddedPrefix:resource_limit_"` // Reserved Resource ReservedResource ApplicationReservedResource `json:"reserved_resource" gorm:"embedded;embeddedPrefix:reserved_resource_"` - // ConsoleTokens - ConsoleTokens []ConsoleToken `json:"console_tokens" gorm:"foreignKey:ApplicationID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"` // Is deleted - soft delete - will be deleted from database in background IsDeleted bool `json:"is_deleted" gorm:"default:false"` // Webhook token @@ -321,28 +317,6 @@ type DeploymentLog struct { CreatedAt time.Time `json:"created_at"` } -// ConsoleToken hold information about console auth tokens, used in establishing websocket connection -// Note this -// If Target == ConsoleTargetTypeServer, ServerID denote which server to ssh into -// If Target == ConsoleTargetTypeApplication, ApplicationID denote which application to connect to and ServerID denote which server to connect to. -// In case of ConsoleTargetTypeApplication, we will connect to ServerID and try to ssh into the application container -// If ServerID server has no container for the application, we will return error -type ConsoleToken struct { - ID string `json:"id" gorm:"primaryKey"` - Target ConsoleTarget `json:"target_type"` - ServerID *uint `json:"server_id"` - ApplicationID *string `json:"application_id"` - Token string `json:"token" gorm:"unique"` - ExpiresAt time.Time `json:"expires_at"` -} - -type AnalyticsServiceToken struct { - ID string `json:"id" gorm:"primaryKey"` - Token string `json:"token" gorm:"unique"` - ServerID uint `json:"server_id"` - CreatedAt time.Time `json:"created_at"` -} - // ************************************************************************************* // // Server Related Stats // // ************************************************************************************* // diff --git a/swiftwave_service/core/types.go b/swiftwave_service/core/types.go index c68156aa0b..5792d01e94 100644 --- a/swiftwave_service/core/types.go +++ b/swiftwave_service/core/types.go @@ -283,14 +283,6 @@ var FedoraDependenciesInstallCommands = map[string]string{ "docker": "curl -fsSL get.docker.com | sh -", } -// ConsoleTarget : type of console target -type ConsoleTarget string - -const ( - ConsoleTargetTypeServer ConsoleTarget = "server" - ConsoleTargetTypeApplication ConsoleTarget = "application" -) - // ************************************************************************************* // // Server Related Stats // // ************************************************************************************* // diff --git a/swiftwave_service/graphql/generated.go b/swiftwave_service/graphql/generated.go index 18e82be6c1..25b33f7448 100644 --- a/swiftwave_service/graphql/generated.go +++ b/swiftwave_service/graphql/generated.go @@ -346,7 +346,6 @@ type ComplexityRoot struct { DisableTotp func(childComplexity int) int EnableHTTPSRedirectIngressRule func(childComplexity int, id uint) int EnableTotp func(childComplexity int, totp string) int - FetchAnalyticsServiceToken func(childComplexity int, id uint, rotate bool) int IssueSsl func(childComplexity int, id uint) int Login func(childComplexity int, input model.UserCredential) int Logout func(childComplexity int) int @@ -663,7 +662,6 @@ type MutationResolver interface { DeleteRedirectRule(ctx context.Context, id uint) (bool, error) CreateServer(ctx context.Context, input model.NewServerInput) (*model.Server, error) DeleteServer(ctx context.Context, id uint) (bool, error) - FetchAnalyticsServiceToken(ctx context.Context, id uint, rotate bool) (string, error) ChangeServerIPAddress(ctx context.Context, id uint, ip string) (bool, error) CleanupStack(ctx context.Context, input model.StackInput) (string, error) VerifyStack(ctx context.Context, input model.StackInput) (*model.StackVerifyResult, error) @@ -2439,18 +2437,6 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Mutation.EnableTotp(childComplexity, args["totp"].(string)), true - case "Mutation.fetchAnalyticsServiceToken": - if e.complexity.Mutation.FetchAnalyticsServiceToken == nil { - break - } - - args, err := ec.field_Mutation_fetchAnalyticsServiceToken_args(context.TODO(), rawArgs) - if err != nil { - return 0, false - } - - return e.complexity.Mutation.FetchAnalyticsServiceToken(childComplexity, args["id"].(uint), args["rotate"].(bool)), true - case "Mutation.issueSSL": if e.complexity.Mutation.IssueSsl == nil { break @@ -4579,30 +4565,6 @@ func (ec *executionContext) field_Mutation_enableTotp_args(ctx context.Context, return args, nil } -func (ec *executionContext) field_Mutation_fetchAnalyticsServiceToken_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { - var err error - args := map[string]interface{}{} - var arg0 uint - if tmp, ok := rawArgs["id"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) - arg0, err = ec.unmarshalNUint2uint(ctx, tmp) - if err != nil { - return nil, err - } - } - args["id"] = arg0 - var arg1 bool - if tmp, ok := rawArgs["rotate"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("rotate")) - arg1, err = ec.unmarshalNBoolean2bool(ctx, tmp) - if err != nil { - return nil, err - } - } - args["rotate"] = arg1 - return args, nil -} - func (ec *executionContext) field_Mutation_issueSSL_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -17547,81 +17509,6 @@ func (ec *executionContext) fieldContext_Mutation_deleteServer(ctx context.Conte return fc, nil } -func (ec *executionContext) _Mutation_fetchAnalyticsServiceToken(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Mutation_fetchAnalyticsServiceToken(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - directive0 := func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return ec.resolvers.Mutation().FetchAnalyticsServiceToken(rctx, fc.Args["id"].(uint), fc.Args["rotate"].(bool)) - } - directive1 := func(ctx context.Context) (interface{}, error) { - if ec.directives.IsAuthenticated == nil { - return nil, errors.New("directive isAuthenticated is not implemented") - } - return ec.directives.IsAuthenticated(ctx, nil, directive0) - } - - tmp, err := directive1(rctx) - if err != nil { - return nil, graphql.ErrorOnPath(ctx, err) - } - if tmp == nil { - return nil, nil - } - if data, ok := tmp.(string); ok { - return data, nil - } - return nil, fmt.Errorf(`unexpected type %T from directive, should be string`, tmp) - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(string) - fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_Mutation_fetchAnalyticsServiceToken(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "Mutation", - Field: field, - IsMethod: true, - IsResolver: true, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type String does not have child fields") - }, - } - defer func() { - if r := recover(); r != nil { - err = ec.Recover(ctx, r) - ec.Error(ctx, err) - } - }() - ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Mutation_fetchAnalyticsServiceToken_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { - ec.Error(ctx, err) - return fc, err - } - return fc, nil -} - func (ec *executionContext) _Mutation_changeServerIpAddress(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Mutation_changeServerIpAddress(ctx, field) if err != nil { @@ -32824,13 +32711,6 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) if out.Values[i] == graphql.Null { out.Invalids++ } - case "fetchAnalyticsServiceToken": - out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { - return ec._Mutation_fetchAnalyticsServiceToken(ctx, field) - }) - if out.Values[i] == graphql.Null { - out.Invalids++ - } case "changeServerIpAddress": out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { return ec._Mutation_changeServerIpAddress(ctx, field) diff --git a/swiftwave_service/graphql/persistent_volume.resolvers.go b/swiftwave_service/graphql/persistent_volume.resolvers.go index 09b95bf1c6..5e85fc3bbe 100644 --- a/swiftwave_service/graphql/persistent_volume.resolvers.go +++ b/swiftwave_service/graphql/persistent_volume.resolvers.go @@ -6,6 +6,7 @@ package graphql import ( "context" + "github.com/swiftwave-org/swiftwave/swiftwave_service/core" "github.com/swiftwave-org/swiftwave/swiftwave_service/graphql/model" "github.com/swiftwave-org/swiftwave/swiftwave_service/manager" diff --git a/swiftwave_service/graphql/schema/server.graphqls b/swiftwave_service/graphql/schema/server.graphqls index b81776ad00..68c0ad0d3a 100644 --- a/swiftwave_service/graphql/schema/server.graphqls +++ b/swiftwave_service/graphql/schema/server.graphqls @@ -104,6 +104,5 @@ extend type Query { extend type Mutation { createServer(input: NewServerInput!): Server! @isAuthenticated deleteServer(id: Uint!): Boolean! @isAuthenticated - fetchAnalyticsServiceToken(id: Uint!, rotate:Boolean!): String! @isAuthenticated changeServerIpAddress(id: Uint!, ip: String!): Boolean! @isAuthenticated } \ No newline at end of file diff --git a/swiftwave_service/graphql/server.resolvers.go b/swiftwave_service/graphql/server.resolvers.go index 89fb493129..c031596ec7 100644 --- a/swiftwave_service/graphql/server.resolvers.go +++ b/swiftwave_service/graphql/server.resolvers.go @@ -113,22 +113,6 @@ func (r *mutationResolver) DeleteServer(ctx context.Context, id uint) (bool, err return true, nil } -// FetchAnalyticsServiceToken is the resolver for the fetchAnalyticsServiceToken field. -func (r *mutationResolver) FetchAnalyticsServiceToken(ctx context.Context, id uint, rotate bool) (string, error) { - var tokenRecord *core.AnalyticsServiceToken - var err error - if !rotate { - tokenRecord, err = core.FetchAnalyticsServiceToken(ctx, r.ServiceManager.DbClient, id) - } else { - tokenRecord, err = core.RotateAnalyticsServiceToken(ctx, r.ServiceManager.DbClient, id) - } - if err != nil { - return "", err - } else { - return tokenRecord.IDToken() - } -} - // ChangeServerIPAddress is the resolver for the changeServerIpAddress field. func (r *mutationResolver) ChangeServerIPAddress(ctx context.Context, id uint, ip string) (bool, error) { server, err := core.FetchServerByID(&r.ServiceManager.DbClient, id) From 3609a3271fc322901408fec30594a77fbb8aca79 Mon Sep 17 00:00:00 2001 From: tanmoysrt <57363826+tanmoysrt@users.noreply.github.com> Date: Mon, 17 Mar 2025 00:06:23 +0530 Subject: [PATCH 4/7] refactor: remove console related codes --- swiftwave_service/console/assets/index.html | 107 ---- swiftwave_service/console/assets/main.js | 210 -------- .../console/assets/xterm-addon-fit.js | 8 - swiftwave_service/console/assets/xterm.css | 222 --------- swiftwave_service/console/assets/xterm.js | 3 - swiftwave_service/console/server.go | 455 ------------------ swiftwave_service/console/types.go | 22 - 7 files changed, 1027 deletions(-) delete mode 100644 swiftwave_service/console/assets/index.html delete mode 100644 swiftwave_service/console/assets/main.js delete mode 100644 swiftwave_service/console/assets/xterm-addon-fit.js delete mode 100644 swiftwave_service/console/assets/xterm.css delete mode 100644 swiftwave_service/console/assets/xterm.js delete mode 100644 swiftwave_service/console/server.go delete mode 100644 swiftwave_service/console/types.go diff --git a/swiftwave_service/console/assets/index.html b/swiftwave_service/console/assets/index.html deleted file mode 100644 index 4444be730b..0000000000 --- a/swiftwave_service/console/assets/index.html +++ /dev/null @@ -1,107 +0,0 @@ - - -
- - -