Skip to content

Commit cac1c47

Browse files
author
Markus Schwer
committed
add ssh connection and cloud-init check in create command
1 parent 2781c1d commit cac1c47

File tree

2 files changed

+78
-1
lines changed

2 files changed

+78
-1
lines changed

cmd/create.go

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
package cmd
22

33
import (
4+
"bytes"
45
"context"
56
"encoding/base64"
67
"fmt"
8+
"github.com/loft-sh/log"
9+
"github.com/pkg/errors"
10+
"gopkg.in/yaml.v3"
11+
"net"
12+
"time"
713

814
"github.com/loft-sh/devpod/pkg/ssh"
915
"github.com/spf13/cobra"
@@ -12,6 +18,44 @@ import (
1218
"github.com/stackitcloud/devpod-provider-stackit/pkg/stackit"
1319
)
1420

21+
const maxConnectionAttempts = 42
22+
23+
type cloudInit struct {
24+
Status string `json:"status"`
25+
}
26+
27+
func checkConnectionStatus(ctx context.Context, publicIP string, privateKey *[]byte) bool {
28+
// Call external address
29+
sshClient, err := ssh.NewSSHClient(stackit.SSHUserName, net.JoinHostPort(publicIP, stackit.SSHPort), *privateKey)
30+
if err != nil {
31+
log.Default.Debugf("Error creating ssh client: %v", err)
32+
return false
33+
}
34+
defer func() {
35+
if err := sshClient.Close(); err != nil {
36+
log.Default.Debugf("Error closing ssh client: %v", err)
37+
}
38+
}()
39+
40+
buf := new(bytes.Buffer)
41+
if err := ssh.Run(ctx, sshClient, "cloud-init status || true", &bytes.Buffer{}, buf, &bytes.Buffer{}, nil); err != nil {
42+
log.Default.Errorf("Error retrieving cloud-init status, %v", err)
43+
return false
44+
}
45+
46+
var status cloudInit
47+
if err := yaml.Unmarshal(buf.Bytes(), &status); err != nil {
48+
log.Default.Errorf("Unable to parse cloud-init YAML: %v", err)
49+
return false
50+
}
51+
52+
if status.Status != "done" {
53+
return false
54+
}
55+
56+
return true
57+
}
58+
1559
// createCmd represents the create command.
1660
var createCmd = &cobra.Command{
1761
Use: "create",
@@ -35,7 +79,39 @@ var createCmd = &cobra.Command{
3579
return fmt.Errorf("can't b64decode public key: %w", err)
3680
}
3781

38-
return s.Create(ctx, options, publicKey)
82+
if err := s.Create(ctx, options, publicKey); err != nil {
83+
return err
84+
}
85+
86+
privateKey, err := ssh.GetPrivateKeyRawBase(options.MachineFolder)
87+
if err != nil {
88+
return errors.Wrap(err, "load private key")
89+
}
90+
91+
publicIP, err := stackit.New(options.ClientOptions).GetPublicIPOfServer(ctx, options.ProjectID, options.MachineID)
92+
if err != nil {
93+
return errors.Wrap(err, "get public IP")
94+
}
95+
96+
attempt := 0
97+
98+
for {
99+
if attempt >= maxConnectionAttempts {
100+
return errors.New("max connection attempts reached")
101+
}
102+
attempt++
103+
104+
log.Default.Debugf("Attempt %d of %d to connect to server using ssh", attempt, maxConnectionAttempts)
105+
106+
time.Sleep(time.Second)
107+
108+
if checkConnectionStatus(ctx, publicIP, &privateKey) {
109+
log.Default.Info("Successfully connected to server")
110+
break
111+
}
112+
}
113+
114+
return nil
39115
},
40116
}
41117

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ require (
1010
github.com/spf13/cobra v1.9.1
1111
github.com/stackitcloud/stackit-sdk-go/core v0.16.0
1212
github.com/stackitcloud/stackit-sdk-go/services/iaas v0.21.1
13+
gopkg.in/yaml.v3 v3.0.1
1314
)
1415

1516
require (

0 commit comments

Comments
 (0)