Compare commits
1 Commits
release/v1
...
release/v1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1040b7d8ef |
38
.github/workflows/docker.yaml
vendored
38
.github/workflows/docker.yaml
vendored
@@ -4,9 +4,8 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- develop
|
- develop
|
||||||
release:
|
tags:
|
||||||
types:
|
- "v*"
|
||||||
- published
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-and-push:
|
build-and-push:
|
||||||
@@ -14,26 +13,21 @@ jobs:
|
|||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
# Always run against a tag, even if the commit into the tag has [docker skip] within the commit message.
|
# Always run against a tag, even if the commit into the tag has [docker skip] within the commit message.
|
||||||
if: "!contains(github.ref, 'develop') || (!contains(github.event.head_commit.message, 'skip docker') && !contains(github.event.head_commit.message, 'docker skip'))"
|
if: "!contains(github.ref, 'develop') || (!contains(github.event.head_commit.message, 'skip docker') && !contains(github.event.head_commit.message, 'docker skip'))"
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Code checkout
|
- name: Code Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Docker metadata
|
- name: Docker Meta
|
||||||
id: docker_meta
|
id: docker_meta
|
||||||
uses: docker/metadata-action@v4
|
uses: crazy-max/ghaction-docker-meta@v1
|
||||||
with:
|
with:
|
||||||
images: ghcr.io/pterodactyl/wings
|
images: ghcr.io/pterodactyl/wings
|
||||||
flavor: |
|
|
||||||
latest=false
|
|
||||||
tags: |
|
|
||||||
type=raw,value=latest,enable=${{ github.event_name == 'release' && github.event.action == 'published' && github.event.release.prerelease == false }}
|
|
||||||
type=ref,event=tag
|
|
||||||
type=ref,event=branch
|
|
||||||
|
|
||||||
- name: Setup QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v2
|
uses: docker/setup-qemu-action@v2
|
||||||
|
|
||||||
- name: Setup Docker buildx
|
- name: Install buildx
|
||||||
uses: docker/setup-buildx-action@v2
|
uses: docker/setup-buildx-action@v2
|
||||||
|
|
||||||
- name: Login to GitHub Container Registry
|
- name: Login to GitHub Container Registry
|
||||||
@@ -46,12 +40,12 @@ jobs:
|
|||||||
- name: Get Build Information
|
- name: Get Build Information
|
||||||
id: build_info
|
id: build_info
|
||||||
run: |
|
run: |
|
||||||
echo "version_tag=${GITHUB_REF/refs\/tags\/v/}" >> $GITHUB_OUTPUT
|
echo "::set-output name=version_tag::${GITHUB_REF/refs\/tags\/v/}"
|
||||||
echo "short_sha=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
echo "::set-output name=short_sha::$(git rev-parse --short HEAD)"
|
||||||
|
|
||||||
- name: Build and Push (tag)
|
- name: Build and push (latest)
|
||||||
uses: docker/build-push-action@v3
|
uses: docker/build-push-action@v2
|
||||||
if: "github.event_name == 'release' && github.event.action == 'published'"
|
if: "!contains(github.ref, 'develop')"
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: ./Dockerfile
|
file: ./Dockerfile
|
||||||
@@ -62,9 +56,9 @@ jobs:
|
|||||||
labels: ${{ steps.docker_meta.outputs.labels }}
|
labels: ${{ steps.docker_meta.outputs.labels }}
|
||||||
tags: ${{ steps.docker_meta.outputs.tags }}
|
tags: ${{ steps.docker_meta.outputs.tags }}
|
||||||
|
|
||||||
- name: Build and Push (develop)
|
- name: Build and push (develop)
|
||||||
uses: docker/build-push-action@v3
|
uses: docker/build-push-action@v2
|
||||||
if: "github.event_name == 'push' && contains(github.ref, 'develop')"
|
if: "contains(github.ref, 'develop')"
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: ./Dockerfile
|
file: ./Dockerfile
|
||||||
|
|||||||
6
.github/workflows/push.yaml
vendored
6
.github/workflows/push.yaml
vendored
@@ -16,7 +16,7 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-20.04]
|
os: [ubuntu-20.04]
|
||||||
go: ["1.18.10", "1.19.5"]
|
go: ["1.18.8", "1.19.3"]
|
||||||
goos: [linux]
|
goos: [linux]
|
||||||
goarch: [amd64, arm64]
|
goarch: [amd64, arm64]
|
||||||
|
|
||||||
@@ -86,14 +86,14 @@ jobs:
|
|||||||
go test -race $(go list ./...)
|
go test -race $(go list ./...)
|
||||||
|
|
||||||
- name: Upload Release Artifact
|
- name: Upload Release Artifact
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v2
|
||||||
if: ${{ github.ref == 'refs/heads/develop' || github.event_name == 'pull_request' }}
|
if: ${{ github.ref == 'refs/heads/develop' || github.event_name == 'pull_request' }}
|
||||||
with:
|
with:
|
||||||
name: wings_linux_${{ matrix.goarch }}
|
name: wings_linux_${{ matrix.goarch }}
|
||||||
path: dist/wings
|
path: dist/wings
|
||||||
|
|
||||||
- name: Upload Debug Artifact
|
- name: Upload Debug Artifact
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v2
|
||||||
if: ${{ github.ref == 'refs/heads/develop' || github.event_name == 'pull_request' }}
|
if: ${{ github.ref == 'refs/heads/develop' || github.event_name == 'pull_request' }}
|
||||||
with:
|
with:
|
||||||
name: wings_linux_${{ matrix.goarch }}_debug
|
name: wings_linux_${{ matrix.goarch }}_debug
|
||||||
|
|||||||
11
.github/workflows/release.yaml
vendored
11
.github/workflows/release.yaml
vendored
@@ -17,7 +17,7 @@ jobs:
|
|||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: "1.18.10"
|
go-version: "1.18.8"
|
||||||
|
|
||||||
- name: Build release binaries
|
- name: Build release binaries
|
||||||
env:
|
env:
|
||||||
@@ -34,6 +34,7 @@ jobs:
|
|||||||
REF: ${{ github.ref }}
|
REF: ${{ github.ref }}
|
||||||
run: |
|
run: |
|
||||||
sed -n "/^## ${REF:10}/,/^## /{/^## /b;p}" CHANGELOG.md > ./RELEASE_CHANGELOG
|
sed -n "/^## ${REF:10}/,/^## /{/^## /b;p}" CHANGELOG.md > ./RELEASE_CHANGELOG
|
||||||
|
echo "version_name=`sed -nr "s/^## (${REF:10} .*)$/\1/p" CHANGELOG.md`" > $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Create checksum and add to changelog
|
- name: Create checksum and add to changelog
|
||||||
run: |
|
run: |
|
||||||
@@ -58,13 +59,15 @@ jobs:
|
|||||||
|
|
||||||
- name: Create release
|
- name: Create release
|
||||||
id: create_release
|
id: create_release
|
||||||
uses: softprops/action-gh-release@v1
|
uses: actions/create-release@v1
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
draft: true
|
tag_name: ${{ github.ref }}
|
||||||
prerelease: ${{ contains(github.ref, 'rc') || contains(github.ref, 'beta') || contains(github.ref, 'alpha') }}
|
release_name: ${{ steps.extract_changelog.outputs.version_name }}
|
||||||
body_path: ./RELEASE_CHANGELOG
|
body_path: ./RELEASE_CHANGELOG
|
||||||
|
draft: true
|
||||||
|
prerelease: ${{ contains(github.ref, 'beta') || contains(github.ref, 'alpha') }}
|
||||||
|
|
||||||
- name: Upload amd64 binary
|
- name: Upload amd64 binary
|
||||||
uses: actions/upload-release-asset@v1
|
uses: actions/upload-release-asset@v1
|
||||||
|
|||||||
37
CHANGELOG.md
37
CHANGELOG.md
@@ -1,42 +1,5 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## v1.11.2
|
|
||||||
### Fixed
|
|
||||||
* Backups being restored from remote storage (s3) erroring out due to a closed stream.
|
|
||||||
* Fix IP validation logic for activity logs filtering out valid IPs instead of invalid IPs
|
|
||||||
|
|
||||||
## v1.11.1
|
|
||||||
### Changed
|
|
||||||
* Release binaries are now built with Go 1.18.10
|
|
||||||
* Timeout when stopping a server before a transfer begins has been reduced to 15 seconds from 1 minute
|
|
||||||
* Removed insecure SSH protocols for use with the SFTP server
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
* Unnecessary Docker client connections being left open, causing a slow leak of file descriptors
|
|
||||||
* Files being left open in parts of the server's filesystem, causing a leak of file descriptors
|
|
||||||
* IPv6 addresses being corrupted by flawed port stripping logic for activity logs, old entries with malformed IPs will be deleted from the local SQLite database automatically
|
|
||||||
* A server that times out while being stopped at the beginning of a transfer no longer causes the server to become stuck in a transferring state
|
|
||||||
|
|
||||||
## v1.11.0
|
|
||||||
### Added (since 1.7.2)
|
|
||||||
* More detailed information returned by the `/api/system` endpoint when using the `?v=2` query parameter.
|
|
||||||
|
|
||||||
### Changed (since 1.7.2)
|
|
||||||
* Send re-installation status separately from installation status.
|
|
||||||
* Wings release versions will now follow the major and minor version of the Panel.
|
|
||||||
* Transfers no longer buffer to disk, instead they are fully streamed with only a small amount of memory used for buffering.
|
|
||||||
* Release binaries are no longer compressed with UPX.
|
|
||||||
* Use `POST` instead of `GET` for sending the status of a transfer to the Panel.
|
|
||||||
|
|
||||||
### Fixed (since 1.7.2)
|
|
||||||
* Fixed servers outgoing IP not being updated whenever a server's primary allocation is changed when using the Force Outgoing IP option.
|
|
||||||
* Fixed servers being terminated rather than gracefully stopped when a signal is used to stop the container rather than a command.
|
|
||||||
* Fixed file not found errors being treated as an internal error, they are now treated as a 404.
|
|
||||||
* Wings can be run with Podman instead of Docker, this is still experimental and not recommended for production use.
|
|
||||||
* Archive progress is now reported correctly.
|
|
||||||
* Labels for containers can now be set by the Panel.
|
|
||||||
* Fixed servers becoming deadlocked when the target node of a transfer goes offline.
|
|
||||||
|
|
||||||
## v1.11.0-rc.2
|
## v1.11.0-rc.2
|
||||||
### Added
|
### Added
|
||||||
* More detailed information returned by the `/api/system` endpoint when using the `?v=2` query parameter.
|
* More detailed information returned by the `/api/system` endpoint when using the `?v=2` query parameter.
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ func (e *Environment) Attach(ctx context.Context) error {
|
|||||||
|
|
||||||
// Set the stream again with the container.
|
// Set the stream again with the container.
|
||||||
if st, err := e.client.ContainerAttach(ctx, e.Id, opts); err != nil {
|
if st, err := e.client.ContainerAttach(ctx, e.Id, opts); err != nil {
|
||||||
return errors.WrapIf(err, "environment/docker: error while attaching to container")
|
return err
|
||||||
} else {
|
} else {
|
||||||
e.SetStream(&st)
|
e.SetStream(&st)
|
||||||
}
|
}
|
||||||
@@ -143,7 +143,7 @@ func (e *Environment) Create() error {
|
|||||||
if _, err := e.ContainerInspect(ctx); err == nil {
|
if _, err := e.ContainerInspect(ctx); err == nil {
|
||||||
return nil
|
return nil
|
||||||
} else if !client.IsErrNotFound(err) {
|
} else if !client.IsErrNotFound(err) {
|
||||||
return errors.WrapIf(err, "environment/docker: failed to inspect container")
|
return errors.Wrap(err, "environment/docker: failed to inspect container")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to pull the requested image before creating the container.
|
// Try to pull the requested image before creating the container.
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ func (e *Environment) ExitState() (uint32, bool, error) {
|
|||||||
if client.IsErrNotFound(err) {
|
if client.IsErrNotFound(err) {
|
||||||
return 1, false, nil
|
return 1, false, nil
|
||||||
}
|
}
|
||||||
return 0, false, errors.WrapIf(err, "environment/docker: failed to inspect container")
|
return 0, false, err
|
||||||
}
|
}
|
||||||
return uint32(c.State.ExitCode), c.State.OOMKilled, nil
|
return uint32(c.State.ExitCode), c.State.OOMKilled, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ func (e *Environment) Start(ctx context.Context) error {
|
|||||||
// exists on the system, and rebuild the container if that is required for server booting to
|
// exists on the system, and rebuild the container if that is required for server booting to
|
||||||
// occur.
|
// occur.
|
||||||
if err := e.OnBeforeStart(ctx); err != nil {
|
if err := e.OnBeforeStart(ctx); err != nil {
|
||||||
return errors.WrapIf(err, "environment/docker: failed to run pre-boot process")
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we cannot start & attach to the container in 30 seconds something has gone
|
// If we cannot start & attach to the container in 30 seconds something has gone
|
||||||
@@ -119,7 +119,7 @@ func (e *Environment) Start(ctx context.Context) error {
|
|||||||
// By explicitly attaching to the instance before we start it, we can immediately
|
// By explicitly attaching to the instance before we start it, we can immediately
|
||||||
// react to errors/output stopping/etc. when starting.
|
// react to errors/output stopping/etc. when starting.
|
||||||
if err := e.Attach(actx); err != nil {
|
if err := e.Attach(actx); err != nil {
|
||||||
return errors.WrapIf(err, "environment/docker: failed to attach to container")
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := e.client.ContainerStart(actx, e.Id, types.ContainerStartOptions{}); err != nil {
|
if err := e.client.ContainerStart(actx, e.Id, types.ContainerStartOptions{}); err != nil {
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package cron
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net"
|
|
||||||
|
|
||||||
"emperror.dev/errors"
|
"emperror.dev/errors"
|
||||||
|
|
||||||
@@ -18,9 +17,9 @@ type activityCron struct {
|
|||||||
max int
|
max int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run executes the cronjob and ensures we fetch and send all the stored activity to the
|
// Run executes the cronjob and ensures we fetch and send all of the stored activity to the
|
||||||
// Panel instance. Once activity is sent it is deleted from the local database instance. Any
|
// Panel instance. Once activity is sent it is deleted from the local database instance. Any
|
||||||
// SFTP specific events are not handled in this cron, they're handled separately to account
|
// SFTP specific events are not handled in this cron, they're handled seperately to account
|
||||||
// for de-duplication and event merging.
|
// for de-duplication and event merging.
|
||||||
func (ac *activityCron) Run(ctx context.Context) error {
|
func (ac *activityCron) Run(ctx context.Context) error {
|
||||||
// Don't execute this cron if there is currently one running. Once this task is completed
|
// Don't execute this cron if there is currently one running. Once this task is completed
|
||||||
@@ -35,6 +34,7 @@ func (ac *activityCron) Run(ctx context.Context) error {
|
|||||||
Where("event NOT LIKE ?", "server:sftp.%").
|
Where("event NOT LIKE ?", "server:sftp.%").
|
||||||
Limit(ac.max).
|
Limit(ac.max).
|
||||||
Find(&activity)
|
Find(&activity)
|
||||||
|
|
||||||
if tx.Error != nil {
|
if tx.Error != nil {
|
||||||
return errors.WithStack(tx.Error)
|
return errors.WithStack(tx.Error)
|
||||||
}
|
}
|
||||||
@@ -42,42 +42,15 @@ func (ac *activityCron) Run(ctx context.Context) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ids to delete from the database.
|
if err := ac.manager.Client().SendActivityLogs(ctx, activity); err != nil {
|
||||||
ids := make([]int, 0, len(activity))
|
|
||||||
// activities to send to the panel.
|
|
||||||
activities := make([]models.Activity, 0, len(activity))
|
|
||||||
for _, v := range activity {
|
|
||||||
// Delete any activity that has an invalid IP address. This is a fix for
|
|
||||||
// a bug that truncated the last octet of an IPv6 address in the database.
|
|
||||||
if ip := net.ParseIP(v.IP); ip == nil {
|
|
||||||
ids = append(ids, v.ID)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
activities = append(activities, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(ids) > 0 {
|
|
||||||
tx = database.Instance().WithContext(ctx).Where("id IN ?", ids).Delete(&models.Activity{})
|
|
||||||
if tx.Error != nil {
|
|
||||||
return errors.WithStack(tx.Error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(activities) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := ac.manager.Client().SendActivityLogs(ctx, activities); err != nil {
|
|
||||||
return errors.WrapIf(err, "cron: failed to send activity events to Panel")
|
return errors.WrapIf(err, "cron: failed to send activity events to Panel")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add all the successful activities to the list of IDs to delete.
|
var ids []int
|
||||||
ids = make([]int, len(activities))
|
for _, v := range activity {
|
||||||
for i, v := range activities {
|
ids = append(ids, v.ID)
|
||||||
ids[i] = v.ID
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete all the activities that were sent to the Panel (or that were invalid).
|
|
||||||
tx = database.Instance().WithContext(ctx).Where("id IN ?", ids).Delete(&models.Activity{})
|
tx = database.Instance().WithContext(ctx).Where("id IN ?", ids).Delete(&models.Activity{})
|
||||||
if tx.Error != nil {
|
if tx.Error != nil {
|
||||||
return errors.WithStack(tx.Error)
|
return errors.WithStack(tx.Error)
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
|
"github.com/pterodactyl/wings/system"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Event string
|
type Event string
|
||||||
@@ -57,9 +57,7 @@ func (a Activity) SetUser(u string) *Activity {
|
|||||||
// is trimmed down to remove any extraneous data, and the timestamp is set to the current
|
// is trimmed down to remove any extraneous data, and the timestamp is set to the current
|
||||||
// system time and then stored as UTC.
|
// system time and then stored as UTC.
|
||||||
func (a *Activity) BeforeCreate(_ *gorm.DB) error {
|
func (a *Activity) BeforeCreate(_ *gorm.DB) error {
|
||||||
if ip, _, err := net.SplitHostPort(strings.TrimSpace(a.IP)); err == nil {
|
a.IP = system.TrimIPSuffix(a.IP)
|
||||||
a.IP = ip
|
|
||||||
}
|
|
||||||
if a.Timestamp.IsZero() {
|
if a.Timestamp.IsZero() {
|
||||||
a.Timestamp = time.Now()
|
a.Timestamp = time.Now()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ func (c *client) SetTransferStatus(ctx context.Context, uuid string, successful
|
|||||||
if successful {
|
if successful {
|
||||||
state = "success"
|
state = "success"
|
||||||
}
|
}
|
||||||
resp, err := c.Post(ctx, fmt.Sprintf("/servers/%s/transfer/%s", uuid, state), nil)
|
resp, err := c.Get(ctx, fmt.Sprintf("/servers/%s/transfer/%s", uuid, state), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,7 +95,6 @@ func getDownloadFile(c *gin.Context) {
|
|||||||
middleware.CaptureAndAbort(c, err)
|
middleware.CaptureAndAbort(c, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
c.Header("Content-Length", strconv.Itoa(int(st.Size())))
|
c.Header("Content-Length", strconv.Itoa(int(st.Size())))
|
||||||
c.Header("Content-Disposition", "attachment; filename="+strconv.Quote(st.Name()))
|
c.Header("Content-Disposition", "attachment; filename="+strconv.Quote(st.Name()))
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"emperror.dev/errors"
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
|
||||||
"github.com/pterodactyl/wings/environment"
|
"github.com/pterodactyl/wings/environment"
|
||||||
@@ -64,11 +63,11 @@ func postServerTransfer(c *gin.Context) {
|
|||||||
if s.Environment.State() != environment.ProcessOfflineState {
|
if s.Environment.State() != environment.ProcessOfflineState {
|
||||||
if err := s.Environment.WaitForStop(
|
if err := s.Environment.WaitForStop(
|
||||||
s.Context(),
|
s.Context(),
|
||||||
time.Second*15,
|
time.Minute,
|
||||||
false,
|
false,
|
||||||
); err != nil && !strings.Contains(strings.ToLower(err.Error()), "no such container") {
|
); err != nil && !strings.Contains(strings.ToLower(err.Error()), "no such container") {
|
||||||
s.SetTransferring(false)
|
notifyPanelOfFailure()
|
||||||
middleware.CaptureAndAbort(c, errors.Wrap(err, "failed to stop server for transfer"))
|
s.Log().WithError(err).Error("failed to stop server for transfer")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ func getServerWebsocket(c *gin.Context) {
|
|||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
break
|
break
|
||||||
case <-s.Context().Done():
|
case <-s.Context().Done():
|
||||||
_ = handler.Connection.WriteControl(ws.CloseMessage, ws.FormatCloseMessage(ws.CloseGoingAway, "server deleted"), time.Now().Add(time.Second*5))
|
handler.Connection.WriteControl(ws.CloseMessage, ws.FormatCloseMessage(ws.CloseGoingAway, "server deleted"), time.Now().Add(time.Second*5))
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
@@ -83,7 +83,7 @@ func getServerWebsocket(c *gin.Context) {
|
|||||||
|
|
||||||
go func(msg websocket.Message) {
|
go func(msg websocket.Message) {
|
||||||
if err := handler.HandleInbound(ctx, msg); err != nil {
|
if err := handler.HandleInbound(ctx, msg); err != nil {
|
||||||
_ = handler.SendErrorJson(msg, err)
|
handler.SendErrorJson(msg, err)
|
||||||
}
|
}
|
||||||
}(j)
|
}(j)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,7 +85,6 @@ func (b *LocalBackup) Restore(ctx context.Context, _ io.Reader, callback Restore
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
var reader io.Reader = f
|
var reader io.Reader = f
|
||||||
// Steal the logic we use for making backups which will be applied when restoring
|
// Steal the logic we use for making backups which will be applied when restoring
|
||||||
|
|||||||
@@ -6,8 +6,6 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"emperror.dev/errors"
|
|
||||||
|
|
||||||
"github.com/pterodactyl/wings/config"
|
"github.com/pterodactyl/wings/config"
|
||||||
"github.com/pterodactyl/wings/environment"
|
"github.com/pterodactyl/wings/environment"
|
||||||
)
|
)
|
||||||
@@ -59,7 +57,7 @@ func (s *Server) handleServerCrash() error {
|
|||||||
|
|
||||||
exitCode, oomKilled, err := s.Environment.ExitState()
|
exitCode, oomKilled, err := s.Environment.ExitState()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "failed to get exit state for server process")
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the system is not configured to detect a clean exit code as a crash, and the
|
// If the system is not configured to detect a clean exit code as a crash, and the
|
||||||
@@ -87,5 +85,5 @@ func (s *Server) handleServerCrash() error {
|
|||||||
|
|
||||||
s.crasher.SetLastCrash(time.Now())
|
s.crasher.SetLastCrash(time.Now())
|
||||||
|
|
||||||
return errors.Wrap(s.HandlePowerAction(PowerActionStart), "failed to start server after crash detection")
|
return s.HandlePowerAction(PowerActionStart)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ func (fs *Filesystem) DecompressFileUnsafe(ctx context.Context, dir string, file
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer f.Close()
|
// TODO: defer file close?
|
||||||
|
|
||||||
// Identify the type of archive we are dealing with.
|
// Identify the type of archive we are dealing with.
|
||||||
format, input, err := archiver.Identify(filepath.Base(file), f)
|
format, input, err := archiver.Identify(filepath.Base(file), f)
|
||||||
|
|||||||
@@ -183,7 +183,7 @@ func (fs *Filesystem) DirectorySize(dir string) (int64, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !e.IsDir() {
|
if !e.IsDir() {
|
||||||
_ = syscall.Lstat(p, &st)
|
syscall.Lstat(p, &st)
|
||||||
atomic.AddInt64(&size, st.Size)
|
atomic.AddInt64(&size, st.Size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -92,9 +92,6 @@ func (fs *Filesystem) Touch(p string, flag int) (*os.File, error) {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
return f, nil
|
return f, nil
|
||||||
}
|
}
|
||||||
if f != nil {
|
|
||||||
_ = f.Close()
|
|
||||||
}
|
|
||||||
// If the error is not because it doesn't exist then we just need to bail at this point.
|
// If the error is not because it doesn't exist then we just need to bail at this point.
|
||||||
if !errors.Is(err, os.ErrNotExist) {
|
if !errors.Is(err, os.ErrNotExist) {
|
||||||
return nil, errors.Wrap(err, "server/filesystem: touch: failed to open file handle")
|
return nil, errors.Wrap(err, "server/filesystem: touch: failed to open file handle")
|
||||||
|
|||||||
@@ -147,7 +147,6 @@ func (s *Server) Context() context.Context {
|
|||||||
// server instance.
|
// server instance.
|
||||||
func (s *Server) GetEnvironmentVariables() []string {
|
func (s *Server) GetEnvironmentVariables() []string {
|
||||||
out := []string{
|
out := []string{
|
||||||
// TODO: allow this to be overridden by the user.
|
|
||||||
fmt.Sprintf("TZ=%s", config.Get().System.Timezone),
|
fmt.Sprintf("TZ=%s", config.Get().System.Timezone),
|
||||||
fmt.Sprintf("STARTUP=%s", s.Config().Invocation),
|
fmt.Sprintf("STARTUP=%s", s.Config().Invocation),
|
||||||
fmt.Sprintf("SERVER_MEMORY=%d", s.MemoryLimit()),
|
fmt.Sprintf("SERVER_MEMORY=%d", s.MemoryLimit()),
|
||||||
|
|||||||
@@ -128,13 +128,6 @@ func (t *Transfer) PushArchiveToTarget(url, token string) ([]byte, error) {
|
|||||||
t.Log().Debug("sending archive to destination")
|
t.Log().Debug("sending archive to destination")
|
||||||
client := http.Client{Timeout: 0}
|
client := http.Client{Timeout: 0}
|
||||||
res, err := client.Do(req)
|
res, err := client.Do(req)
|
||||||
if err != nil {
|
|
||||||
t.Log().Debug("error while sending archive to destination")
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if res.StatusCode != http.StatusOK {
|
|
||||||
return nil, fmt.Errorf("unexpected status code from destination: %d", res.StatusCode)
|
|
||||||
}
|
|
||||||
t.Log().Debug("waiting for stream to complete")
|
t.Log().Debug("waiting for stream to complete")
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
|
|||||||
@@ -68,21 +68,6 @@ func (c *SFTPServer) Run() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
conf := &ssh.ServerConfig{
|
conf := &ssh.ServerConfig{
|
||||||
Config: ssh.Config{
|
|
||||||
KeyExchanges: []string{
|
|
||||||
"curve25519-sha256", "curve25519-sha256@libssh.org",
|
|
||||||
"ecdh-sha2-nistp256", "ecdh-sha2-nistp384", "ecdh-sha2-nistp521",
|
|
||||||
"diffie-hellman-group14-sha256",
|
|
||||||
},
|
|
||||||
Ciphers: []string{
|
|
||||||
"aes128-gcm@openssh.com",
|
|
||||||
"chacha20-poly1305@openssh.com",
|
|
||||||
"aes128-ctr", "aes192-ctr", "aes256-ctr",
|
|
||||||
},
|
|
||||||
MACs: []string{
|
|
||||||
"hmac-sha2-256-etm@openssh.com", "hmac-sha2-256",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
NoClientAuth: false,
|
NoClientAuth: false,
|
||||||
MaxAuthTries: 6,
|
MaxAuthTries: 6,
|
||||||
PasswordCallback: func(conn ssh.ConnMetadata, password []byte) (*ssh.Permissions, error) {
|
PasswordCallback: func(conn ssh.ConnMetadata, password []byte) (*ssh.Permissions, error) {
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
package system
|
package system
|
||||||
|
|
||||||
var Version = "1.11.2"
|
var Version = "1.11.0-rc.2"
|
||||||
|
|||||||
29
system/strings.go
Normal file
29
system/strings.go
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package system
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/rand"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ipTrimRegex = regexp.MustCompile(`(:\d*)?$`)
|
||||||
|
|
||||||
|
const characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
|
||||||
|
|
||||||
|
// RandomString generates a random string of alpha-numeric characters using a
|
||||||
|
// pseudo-random number generator. The output of this function IS NOT cryptographically
|
||||||
|
// secure, it is used solely for generating random strings outside a security context.
|
||||||
|
func RandomString(n int) string {
|
||||||
|
var b strings.Builder
|
||||||
|
b.Grow(n)
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
b.WriteByte(characters[rand.Intn(len(characters))])
|
||||||
|
}
|
||||||
|
return b.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// TrimIPSuffix removes the internal port value from an IP address to ensure we're only
|
||||||
|
// ever working directly with the IP address.
|
||||||
|
func TrimIPSuffix(s string) string {
|
||||||
|
return ipTrimRegex.ReplaceAllString(s, "")
|
||||||
|
}
|
||||||
@@ -127,7 +127,6 @@ func GetDockerInfo(ctx context.Context) (types.Version, types.Info, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return types.Version{}, types.Info{}, err
|
return types.Version{}, types.Info{}, err
|
||||||
}
|
}
|
||||||
defer c.Close()
|
|
||||||
|
|
||||||
dockerVersion, err := c.ServerVersion(ctx)
|
dockerVersion, err := c.ServerVersion(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user