0
0
mirror of https://github.com/bpg/terraform-provider-proxmox.git synced 2025-06-30 02:31:10 +00:00

fix(provider): EOF error when closing SSH session (#1113)

Signed-off-by: Pavel Boldyrev <627562+bpg@users.noreply.github.com>
This commit is contained in:
Pavel Boldyrev 2024-03-11 20:05:11 -04:00 committed by GitHub
parent fed87bad3c
commit b63f1b7889
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 70 additions and 17 deletions

View File

@ -65,6 +65,10 @@ func main() {
serveOpts = append(serveOpts, tf6server.WithManagedDebug())
}
// Remove any date and time prefix in log package function output to
// prevent duplicate timestamp and incorrect log level setting
log.SetFlags(log.Flags() &^ (log.Ldate | log.Ltime))
err = tf6server.Serve(
"registry.terraform.io/bpg/proxmox",
muxServer.ProviderServer,

View File

@ -10,6 +10,7 @@ import (
"context"
"errors"
"fmt"
"io"
"net"
"os"
"path"
@ -122,21 +123,42 @@ func (c *client) ExecuteNodeCommands(ctx context.Context, nodeName string, comma
"commands": commands,
})
closeOrLogError := utils.CloseOrLogError(ctx)
sshClient, err := c.openNodeShell(ctx, node)
if err != nil {
return nil, err
}
defer closeOrLogError(sshClient)
defer func(sshClient *ssh.Client) {
e := sshClient.Close()
if e != nil {
tflog.Warn(ctx, "failed to close SSH client", map[string]interface{}{
"error": e,
})
}
}(sshClient)
output, err := c.executeCommands(ctx, sshClient, commands)
if err != nil {
return nil, err
}
return output, nil
}
func (c *client) executeCommands(ctx context.Context, sshClient *ssh.Client, commands []string) ([]byte, error) {
sshSession, err := sshClient.NewSession()
if err != nil {
return nil, fmt.Errorf("failed to create SSH session: %w", err)
}
defer closeOrLogError(sshSession)
defer func(session *ssh.Session) {
e := session.Close()
if e != nil && !errors.Is(e, io.EOF) {
tflog.Warn(ctx, "failed to close SSH session", map[string]interface{}{
"error": e,
})
}
}(sshSession)
script := strings.Join(commands, "; ")
@ -188,7 +210,7 @@ func (c *client) NodeUpload(
defer func(sshClient *ssh.Client) {
e := sshClient.Close()
if e != nil {
tflog.Error(ctx, "failed to close SSH client", map[string]interface{}{
tflog.Warn(ctx, "failed to close SSH client", map[string]interface{}{
"error": e,
})
}
@ -208,7 +230,7 @@ func (c *client) NodeUpload(
defer func(sftpClient *sftp.Client) {
e := sftpClient.Close()
if e != nil {
tflog.Error(ctx, "failed to close SFTP client", map[string]interface{}{
tflog.Warn(ctx, "failed to close SFTP client", map[string]interface{}{
"error": e,
})
}
@ -227,7 +249,7 @@ func (c *client) NodeUpload(
defer func(remoteFile *sftp.File) {
e := remoteFile.Close()
if e != nil {
tflog.Error(ctx, "failed to close remote file", map[string]interface{}{
tflog.Warn(ctx, "failed to close remote file", map[string]interface{}{
"error": e,
})
}
@ -284,7 +306,7 @@ func (c *client) NodeStreamUpload(
defer func(sshClient *ssh.Client) {
e := sshClient.Close()
if e != nil {
tflog.Error(ctx, "failed to close SSH client", map[string]interface{}{
tflog.Warn(ctx, "failed to close SSH client", map[string]interface{}{
"error": e,
})
}
@ -296,6 +318,29 @@ func (c *client) NodeStreamUpload(
remoteFilePath := strings.ReplaceAll(filepath.Join(remoteFileDir, d.FileName), `\`, "/")
err = c.uploadFile(ctx, sshClient, d, remoteFilePath)
if err != nil {
return err
}
err = c.checkUploadedFile(ctx, sshClient, remoteFilePath, fileSize)
if err != nil {
return err
}
tflog.Debug(ctx, "uploaded file to datastore", map[string]interface{}{
"remote_file_path": remoteFilePath,
})
return nil
}
func (c *client) uploadFile(
ctx context.Context,
sshClient *ssh.Client,
req *api.FileUploadRequest,
remoteFilePath string,
) error {
sshSession, err := sshClient.NewSession()
if err != nil {
return fmt.Errorf("failed to create SSH session: %w", err)
@ -303,14 +348,14 @@ func (c *client) NodeStreamUpload(
defer func(session *ssh.Session) {
e := session.Close()
if e != nil {
tflog.Error(ctx, "failed to close SSH session", map[string]interface{}{
if e != nil && !errors.Is(e, io.EOF) {
tflog.Warn(ctx, "failed to close SSH session", map[string]interface{}{
"error": e,
})
}
}(sshSession)
sshSession.Stdin = d.File
sshSession.Stdin = req.File
output, err := sshSession.CombinedOutput(
fmt.Sprintf(`%s; try_sudo "/usr/bin/tee %s"`, TrySudo, remoteFilePath),
@ -319,6 +364,15 @@ func (c *client) NodeStreamUpload(
return fmt.Errorf("error transferring file: %s", string(output))
}
return nil
}
func (c *client) checkUploadedFile(
ctx context.Context,
sshClient *ssh.Client,
remoteFilePath string,
fileSize int64,
) error {
sftpClient, err := sftp.NewClient(sshClient)
if err != nil {
return fmt.Errorf("failed to create SFTP client: %w", err)
@ -327,7 +381,7 @@ func (c *client) NodeStreamUpload(
defer func(sftpClient *sftp.Client) {
e := sftpClient.Close()
if e != nil {
tflog.Error(ctx, "failed to close SFTP client", map[string]interface{}{
tflog.Warn(ctx, "failed to close SFTP client", map[string]interface{}{
"error": e,
})
}
@ -349,11 +403,6 @@ func (c *client) NodeStreamUpload(
remoteFilePath, bytesUploaded, fileSize)
}
tflog.Debug(ctx, "uploaded file to datastore", map[string]interface{}{
"remote_file_path": remoteFilePath,
"size": bytesUploaded,
})
return nil
}