-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: hunnywar <[email protected]>
- Loading branch information
Showing
8 changed files
with
197 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
#!/bin/bash | ||
# Copyright 2024 Daytona Platforms Inc. | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
RELEASE_TAG="1.7.7" | ||
RELEASE_ORG="tsl0922" | ||
TTYD_ROOT="$HOME/ttyd" | ||
|
||
# Check if ttyd is already installed | ||
if [ -d "$TTYD_ROOT" ]; then | ||
echo "Terminal Server is already installed. Skipping installation." | ||
exit 0 | ||
fi | ||
|
||
# Ensure the RELEASE_TAG is set | ||
if [ -z "$RELEASE_TAG" ]; then | ||
echo "The RELEASE_TAG build arg must be set." >&2 | ||
exit 1 | ||
fi | ||
|
||
# Determine system architecture | ||
arch=$(uname -m) | ||
if [ "$arch" = "x86_64" ]; then | ||
arch="x86_64" | ||
elif [ "$arch" = "aarch64" ]; then | ||
arch="aarch64" | ||
elif [ "$arch" = "armv7l" ]; then | ||
arch="armhf" | ||
else | ||
echo "Unsupported architecture: $arch" | ||
exit 1 | ||
fi | ||
|
||
# Define the download URL and target file | ||
download_url="https://github.com/$RELEASE_ORG/ttyd/releases/download/$RELEASE_TAG/ttyd.$arch" | ||
target_file="$HOME/ttyd-$arch" | ||
|
||
# Download the file using wget or curl | ||
if command -v wget &>/dev/null; then | ||
wget -O "$target_file" "$download_url" | ||
elif command -v curl &>/dev/null; then | ||
curl -fsSL -o "$target_file" "$download_url" | ||
else | ||
echo "Neither wget nor curl is available. Please install one of them." | ||
exit 1 | ||
fi | ||
|
||
# Make the binary executable | ||
chmod +x "$target_file" | ||
|
||
# Move ttyd to the installation directory | ||
mkdir -p "$TTYD_ROOT/bin" | ||
mv "$target_file" "$TTYD_ROOT/bin/ttyd" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
// Copyright 2024 Daytona Platforms Inc. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package ide | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"io" | ||
"os" | ||
"os/signal" | ||
"os/exec" | ||
"sync" | ||
"syscall" | ||
"time" | ||
|
||
"github.com/daytonaio/daytona/cmd/daytona/config" | ||
"github.com/daytonaio/daytona/internal/cmd/tailscale" | ||
"github.com/daytonaio/daytona/internal/util" | ||
"github.com/daytonaio/daytona/pkg/ports" | ||
"github.com/daytonaio/daytona/pkg/views" | ||
|
||
"github.com/pkg/browser" | ||
log "github.com/sirupsen/logrus" | ||
) | ||
|
||
const startCommand = "$HOME/ttyd/bin/ttyd --port 63777 --writable --cwd" | ||
|
||
// OpenBrowserTerminal starts a browser-based terminal and opens it in the browser | ||
func OpenBrowserTerminal(activeProfile config.Profile, workspaceId string, projectName string, gpgKey string) error { | ||
// Create a cancellation context for graceful shutdown | ||
ctx, cancel := context.WithCancel(context.Background()) | ||
defer cancel() // Ensure the context is canceled on exit | ||
|
||
// Capture OS interrupt signals for graceful exit | ||
signalChan := make(chan os.Signal, 1) | ||
signal.Notify(signalChan, os.Interrupt, syscall.SIGTERM) | ||
|
||
// WaitGroup to wait for all goroutines to finish | ||
var wg sync.WaitGroup | ||
|
||
// Ensure SSH config exists | ||
err := config.EnsureSshConfigEntryAdded(activeProfile.Id, workspaceId, projectName, gpgKey) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
views.RenderInfoMessageBold("Downloading Terminal Server...") | ||
projectHostname := config.GetProjectHostname(activeProfile.Id, workspaceId, projectName) | ||
|
||
// Download and install ttyd | ||
installServerCommand := exec.Command("ssh", projectHostname, "curl -fsSL https://download.daytona.io/daytona/tools/get-ttyd.sh | sh") | ||
installServerCommand.Stdout = io.Writer(&util.DebugLogWriter{}) | ||
installServerCommand.Stderr = io.Writer(&util.DebugLogWriter{}) | ||
|
||
err = installServerCommand.Run() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
projectDir, err := util.GetProjectDir(activeProfile, workspaceId, projectName, gpgKey) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
views.RenderInfoMessageBold("Starting Terminal Server...") | ||
|
||
// Start the terminal server in a goroutine | ||
wg.Add(1) | ||
go func() { | ||
defer wg.Done() | ||
|
||
startServerCommand := exec.CommandContext(ctx, "ssh", projectHostname, fmt.Sprintf("%s %s bash", startCommand, projectDir)) | ||
startServerCommand.Stdout = io.Writer(&util.DebugLogWriter{}) | ||
startServerCommand.Stderr = io.Writer(&util.DebugLogWriter{}) | ||
|
||
err = startServerCommand.Run() | ||
if err != nil && ctx.Err() == nil { // Ignore errors if context was canceled | ||
log.Error(err) | ||
} | ||
}() | ||
|
||
// Forward ttyd (Terminal server) port | ||
browserPort, errChan := tailscale.ForwardPort(workspaceId, projectName, 63777, activeProfile) | ||
if browserPort == nil { | ||
if err := <-errChan; err != nil { | ||
return err | ||
} | ||
} | ||
|
||
ideURL := fmt.Sprintf("http://localhost:%d", *browserPort) | ||
// Wait for the port to be ready | ||
for { | ||
if ports.IsPortReady(*browserPort) { | ||
break | ||
} | ||
time.Sleep(100 * time.Millisecond) | ||
} | ||
|
||
views.RenderInfoMessageBold(fmt.Sprintf("Forwarded %s Terminal port to %s.\nOpening browser...\n", projectName, ideURL)) | ||
|
||
err = browser.OpenURL(ideURL) | ||
if err != nil { | ||
log.Error("Error opening URL: " + err.Error()) | ||
} | ||
|
||
// Handle errors from the port-forwarding goroutine | ||
wg.Add(1) | ||
go func() { | ||
defer wg.Done() | ||
|
||
for { | ||
select { | ||
case <-ctx.Done(): | ||
return | ||
case err := <-errChan: | ||
if err != nil { | ||
// Log errors in debug mode | ||
// Connection errors to the forwarded port should not exit the process | ||
log.Debug(err) | ||
} | ||
} | ||
} | ||
}() | ||
|
||
// Wait for a termination signal | ||
<-signalChan | ||
log.Info("Received termination signal. Shutting down gracefully...") | ||
|
||
// Cancel the context to stop all goroutines | ||
cancel() | ||
|
||
// Wait for all goroutines to complete | ||
wg.Wait() | ||
log.Info("All tasks stopped. Exiting.") | ||
return nil | ||
} |