Skip to content

Commit

Permalink
Merge pull request #2020 from FabianKramm/master
Browse files Browse the repository at this point in the history
refactor: make ssh port stable if already in .ssh/config
  • Loading branch information
FabianKramm authored Mar 31, 2022
2 parents 2c8c79f + 1ddcce5 commit 45fdf0d
Show file tree
Hide file tree
Showing 15 changed files with 258 additions and 76 deletions.
6 changes: 5 additions & 1 deletion cmd/run_pipeline.go
Original file line number Diff line number Diff line change
Expand Up @@ -374,8 +374,12 @@ func runPipeline(ctx *devspacecontext.Context, f factory.Factory, forceLeader bo
ctx.Log.Debugf("Run pipeline:\n%s\n", string(configPipelineBytes))
}

// create dev context
devCtxCancel, cancelDevCtx := context.WithCancel(ctx.Context)
ctx = ctx.WithContext(values.WithDevContext(ctx.Context, devCtxCancel))

// create a new base dev pod manager
devPodManager := devpod.NewManager(ctx.Context)
devPodManager := devpod.NewManager(cancelDevCtx)
defer devPodManager.Close()

// create dependency registry
Expand Down
6 changes: 3 additions & 3 deletions pkg/devspace/build/builder/restart/restart.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,10 @@ counter=0
while ! [ -f $touchFile ]; do
if [ "$counter" = "0" ]; then
echo "Container started with restart helper."
echo "Waiting for initial sync to complete before starting application..."
echo "Waiting for initial sync to complete or file $touchFile to exist before starting the application..."
else
if [ "$counter" = 10 ]; then
echo "(Still waiting for initial sync to complete)"
echo "(Still waiting...)"
counter=0
fi
fi
Expand All @@ -82,7 +82,7 @@ while ! [ -f $touchFile ]; do
done
if ! [ "$counter" = "0" ]; then
echo "Initial sync completed. Starting application..."
echo "Starting application..."
fi
while $restart; do
Expand Down
4 changes: 2 additions & 2 deletions pkg/devspace/config/versions/latest/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -856,8 +856,8 @@ type RestartHelper struct {
// Path defines the path to the restart helper that might be used if certain config
// options are enabled
Path string `yaml:"path,omitempty" json:"path,omitempty"`
// Disable signals DevSpace to not inject the restart helper
Disable bool `yaml:"disable,omitempty" json:"disable,omitempty"`
// Inject signals DevSpace to inject the restart helper
Inject *bool `yaml:"inject,omitempty" json:"inject,omitempty"`
}

type ProxyCommand struct {
Expand Down
2 changes: 1 addition & 1 deletion pkg/devspace/config/versions/v1beta11/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -774,7 +774,7 @@ func (c *Config) mergeDevConfig(log log.Logger) (map[string]*next.DevPod, error)
if devPods[k].Containers[i].RestartHelper == nil {
devPods[k].Containers[i].RestartHelper = &next.RestartHelper{}
}
devPods[k].Containers[i].RestartHelper.Disable = true
devPods[k].Containers[i].RestartHelper.Inject = ptr.Bool(false)
}
}

Expand Down
12 changes: 12 additions & 0 deletions pkg/devspace/context/values/values.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,20 @@ const (
commandKey
dependencyKey
rootNameKey
devContextKey
)

// WithDevContext creates a new context with the dev context
func WithDevContext(parent context.Context, devCtx context.Context) context.Context {
return WithValue(parent, devContextKey, devCtx)
}

// DevContextFrom returns a context used to start and stop dev configurations
func DevContextFrom(ctx context.Context) (context.Context, bool) {
devCtx, ok := ctx.Value(devContextKey).(context.Context)
return devCtx, ok
}

// RootNameFrom returns the root name of the devspace config
func RootNameFrom(ctx context.Context) (string, bool) {
user, ok := ctx.Value(rootNameKey).(string)
Expand Down
5 changes: 4 additions & 1 deletion pkg/devspace/devpod/devpod.go
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,9 @@ func needPodReplaceContainer(devContainer *latest.DevContainer) bool {
if len(devContainer.PersistPaths) > 0 {
return true
}
if devContainer.RestartHelper != nil && devContainer.RestartHelper.Inject != nil && *devContainer.RestartHelper.Inject {
return true
}
if devContainer.Terminal != nil && !devContainer.Terminal.DisableReplace && (devContainer.Terminal.Enabled == nil || *devContainer.Terminal.Enabled) {
return true
}
Expand All @@ -554,7 +557,7 @@ func needPodReplaceContainer(devContainer *latest.DevContainer) bool {
if devContainer.Args != nil {
return true
}
if devContainer.RestartHelper == nil || !devContainer.RestartHelper.Disable {
if devContainer.RestartHelper == nil || devContainer.RestartHelper.Inject == nil || *devContainer.RestartHelper.Inject {
for _, s := range devContainer.Sync {
if s.OnUpload != nil && s.OnUpload.RestartContainer {
return true
Expand Down
33 changes: 13 additions & 20 deletions pkg/devspace/devpod/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"github.com/loft-sh/devspace/pkg/devspace/config/versions/latest"
devspacecontext "github.com/loft-sh/devspace/pkg/devspace/context"
"github.com/loft-sh/devspace/pkg/devspace/context/values"
"github.com/loft-sh/devspace/pkg/devspace/deploy"
"github.com/loft-sh/devspace/pkg/devspace/services/podreplace"
"github.com/loft-sh/devspace/pkg/util/lockfactory"
Expand Down Expand Up @@ -41,9 +42,6 @@ type Manager interface {
// Close will close the manager and wait for all dev pods to stop
Close()

// Context returns the context of the DevManager
Context() context.Context

// Wait will wait until all DevPods are stopped
Wait() error
}
Expand All @@ -52,15 +50,12 @@ type devPodManager struct {
lockFactory lockfactory.LockFactory

m sync.Mutex
ctx context.Context
cancels []context.CancelFunc
devPods map[string]*devPod
}

func NewManager(ctx context.Context) Manager {
ctx, cancel := context.WithCancel(ctx)
func NewManager(cancel context.CancelFunc) Manager {
return &devPodManager{
ctx: ctx,
cancels: []context.CancelFunc{cancel},
lockFactory: lockfactory.NewDefaultLockFactory(),
devPods: map[string]*devPod{},
Expand All @@ -86,21 +81,18 @@ func (d *devPodManager) Close() {
}
d.cancels = []context.CancelFunc{}
d.m.Unlock()
d.Wait()
}

func (d *devPodManager) Context() context.Context {
return d.ctx
_ = d.Wait()
}

func (d *devPodManager) StartMultiple(ctx *devspacecontext.Context, devPods []string, options Options) error {
devCtx, _ := values.DevContextFrom(ctx.Context)
select {
case <-d.ctx.Done():
return d.ctx.Err()
case <-devCtx.Done():
return devCtx.Err()
default:
}

cancelCtx, cancel := context.WithCancel(d.ctx)
cancelCtx, cancel := context.WithCancel(devCtx)
d.m.Lock()
d.cancels = append(d.cancels, cancel)
d.m.Unlock()
Expand Down Expand Up @@ -174,16 +166,17 @@ func (d *devPodManager) Start(originalContext *devspacecontext.Context, devPodCo
var dp *devPod
d.m.Lock()
dp = d.devPods[devPodConfig.Name]
d.m.Unlock()

// check if already running
if dp != nil {
return nil, DevPodAlreadyExists{}
select {
case <-dp.Done():
default:
d.m.Unlock()
return nil, DevPodAlreadyExists{}
}
}

// create a new dev pod
dp = newDevPod()
d.m.Lock()
d.devPods[devPodConfig.Name] = dp
d.m.Unlock()

Expand Down
6 changes: 5 additions & 1 deletion pkg/devspace/pipeline/pipeline.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package pipeline

import (
"context"
"fmt"
"github.com/loft-sh/devspace/pkg/devspace/context/values"
utilerrors "k8s.io/apimachinery/pkg/util/errors"
Expand Down Expand Up @@ -205,7 +206,10 @@ func (p *pipeline) startNewDependency(ctx *devspacecontext.Context, dependency t
pipelineConfig = dependency.Config().Config().Pipelines[executePipeline]
}

dependencyDevPodManager := devpod.NewManager(p.devPodManager.Context())
devCtx, _ := values.DevContextFrom(ctx.Context)
devCtxCancel, cancelDevCtx := context.WithCancel(devCtx)
ctx = ctx.WithContext(values.WithDevContext(ctx.Context, devCtxCancel))
dependencyDevPodManager := devpod.NewManager(cancelDevCtx)
pip := NewPipeline(dependency.Name(), dependencyDevPodManager, p.dependencyRegistry, pipelineConfig, p.options)
pip.(*pipeline).parent = p

Expand Down
6 changes: 3 additions & 3 deletions pkg/devspace/services/podreplace/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,16 +242,16 @@ func replaceWorkingDir(ctx *devspacecontext.Context, devPod *latest.DevPod, devC

func replaceCommand(ctx *devspacecontext.Context, devPod *latest.DevPod, devContainer *latest.DevContainer, podTemplate *corev1.PodTemplateSpec) error {
// replace with DevSpace helper
injectRestartHelper := false
if devContainer.RestartHelper == nil || !devContainer.RestartHelper.Disable {
injectRestartHelper := devContainer.RestartHelper != nil && devContainer.RestartHelper.Inject != nil && *devContainer.RestartHelper.Inject
if devContainer.RestartHelper == nil || devContainer.RestartHelper.Inject == nil || *devContainer.RestartHelper.Inject {
for _, s := range devContainer.Sync {
if s.StartContainer || (s.OnUpload != nil && s.OnUpload.RestartContainer) {
injectRestartHelper = true
}
}
}
if len(devContainer.Command) == 0 && injectRestartHelper {
return fmt.Errorf("dev.%s.sync[*].onUpload.restartContainer is true, please specify the entrypoint that should get restarted in dev.%s.command", devPod.Name, devPod.Name)
return fmt.Errorf("dev.%s.sync[*].onUpload.restartContainer or dev.%s.restartHelper.inject is true, please specify the entrypoint that should get restarted in dev.%s.command", devPod.Name, devPod.Name, devPod.Name)
}
if !injectRestartHelper && len(devContainer.Command) == 0 && devContainer.Args == nil {
return nil
Expand Down
4 changes: 2 additions & 2 deletions pkg/devspace/services/proxycommands/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@ func startProxyCommands(ctx *devspacecontext.Context, devContainer *latest.DevCo
}

// get a local port
port, err := ssh.LockPort()
port, err := ssh.GetInstance(ctx.Log).LockPort()
if err != nil {
return errors.Wrap(err, "find port")
}

defer ssh.ReleasePort(port)
defer ssh.GetInstance(ctx.Log).ReleasePort(port)

// get remote port
defaultRemotePort := DefaultRemotePort
Expand Down
71 changes: 66 additions & 5 deletions pkg/devspace/services/ssh/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,18 @@ import (
"io/ioutil"
"os"
"path/filepath"
"strconv"
"strings"
"sync"
)

var configLock sync.Mutex

var (
MarkerStartPrefix = "# DevSpace Start "
MarkerEndPrefix = "# DevSpace End "
)

func configureSSHConfig(host, port string, log log.Logger) error {
configLock.Lock()
defer configLock.Unlock()
Expand All @@ -25,7 +31,7 @@ func configureSSHConfig(host, port string, log log.Logger) error {
}

sshConfigPath := filepath.Join(homeDir, ".ssh", "config")
newFile, err := replaceHost(sshConfigPath, host, port)
newFile, err := addHost(sshConfigPath, host, port)
if err != nil {
return errors.Wrap(err, "parse ssh config")
}
Expand All @@ -43,7 +49,65 @@ func configureSSHConfig(host, port string, log log.Logger) error {
return nil
}

func replaceHost(path, host, port string) (string, error) {
type DevSpaceSSHEntry struct {
Host string
Hostname string
Port int
}

func ParseDevSpaceHosts(path string) ([]DevSpaceSSHEntry, error) {
var reader io.Reader
f, err := os.Open(path)
if err != nil {
if !os.IsNotExist(err) {
return nil, err
}

reader = strings.NewReader("")
} else {
reader = f
defer f.Close()
}

configScanner := scanner.NewScanner(reader)
inSection := false

entries := []DevSpaceSSHEntry{}
current := &DevSpaceSSHEntry{}
for configScanner.Scan() {
text := strings.TrimSpace(configScanner.Text())
if strings.HasPrefix(text, MarkerStartPrefix) {
inSection = true
} else if strings.HasPrefix(text, MarkerEndPrefix) {
if current.Host != "" && current.Port > 0 && current.Hostname != "" {
entries = append(entries, *current)
}
current = &DevSpaceSSHEntry{}
inSection = false
} else if inSection {
if strings.HasPrefix(text, "Host ") {
current.Host = strings.TrimPrefix(text, "Host ")
}
if strings.HasPrefix(text, "Port ") {
port := strings.TrimPrefix(text, "Port ")
intPort, err := strconv.Atoi(port)
if err == nil {
current.Port = intPort
}
}
if strings.HasPrefix(text, "HostName ") {
current.Hostname = strings.TrimPrefix(text, "HostName ")
}
}
}
if configScanner.Err() != nil {
return nil, errors.Wrap(err, "parse ssh config")
}

return entries, nil
}

func addHost(path, host, port string) (string, error) {
var reader io.Reader
f, err := os.Open(path)
if err != nil {
Expand Down Expand Up @@ -77,7 +141,6 @@ func replaceHost(path, host, port string) (string, error) {
}

// add new section
newLines = append(newLines, "")
newLines = append(newLines, startMarker)
newLines = append(newLines, "Host "+host)
newLines = append(newLines, " HostName localhost")
Expand All @@ -87,7 +150,5 @@ func replaceHost(path, host, port string) (string, error) {
newLines = append(newLines, " UserKnownHostsFile /dev/null")
newLines = append(newLines, " User devspace")
newLines = append(newLines, endMarker)
newLines = append(newLines, "")

return strings.Join(newLines, "\n"), nil
}
Loading

0 comments on commit 45fdf0d

Please sign in to comment.