github.com/caos/orbos@v1.5.14-0.20221103111702-e6cd0cea7ad4/internal/operator/orbiter/kinds/providers/gce/gcemachine.go (about)

     1  package gce
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"fmt"
     7  	"io"
     8  	"os"
     9  	"os/exec"
    10  	"strings"
    11  
    12  	"github.com/caos/orbos/internal/operator/orbiter/kinds/providers/ssh"
    13  	"github.com/caos/orbos/mntr"
    14  )
    15  
    16  type gceMachine struct {
    17  	mntr.Monitor
    18  	id      string
    19  	zone    string
    20  	context *context
    21  }
    22  
    23  func newGCEMachine(context *context, monitor mntr.Monitor, id string, zone string) machine {
    24  	return &gceMachine{
    25  		Monitor: monitor,
    26  		id:      id,
    27  		zone:    zone,
    28  		context: context,
    29  	}
    30  }
    31  
    32  func resetBuffer(buffer *bytes.Buffer) {
    33  	if buffer != nil {
    34  		buffer.Reset()
    35  	}
    36  }
    37  
    38  func (c *gceMachine) Zone() string {
    39  	return c.zone
    40  }
    41  
    42  func (c *gceMachine) Execute(stdin io.Reader, command string) ([]byte, error) {
    43  	buf, err := c.execute(stdin, command)
    44  	defer resetBuffer(buf)
    45  	if err != nil {
    46  		return nil, err
    47  	}
    48  	return buf.Bytes(), nil
    49  }
    50  
    51  func (c *gceMachine) execute(stdin io.Reader, command string) (outBuf *bytes.Buffer, err error) {
    52  	outBuf = new(bytes.Buffer)
    53  	errBuf := new(bytes.Buffer)
    54  	defer resetBuffer(errBuf)
    55  
    56  	gcloud, err := exec.LookPath("gcloud")
    57  	if err != nil {
    58  		return nil, err
    59  	}
    60  
    61  	if err := gcloudSession(c.context.desired.JSONKey.Value, gcloud, func(bin string) error {
    62  		cmd := exec.Command(gcloud,
    63  			"compute",
    64  			"ssh",
    65  			"--zone", c.zone,
    66  			fmt.Sprintf("orbiter@%s", c.id),
    67  			"--tunnel-through-iap",
    68  			"--project", c.context.projectID,
    69  			"--command", command,
    70  		)
    71  		cmd.Stdin = stdin
    72  		cmd.Stdout = outBuf
    73  		cmd.Stderr = errBuf
    74  		if runErr := cmd.Run(); runErr != nil {
    75  			return errors.New(errBuf.String())
    76  		}
    77  		return nil
    78  	}); err != nil {
    79  		return nil, err
    80  	}
    81  	return outBuf, nil
    82  }
    83  
    84  func (c *gceMachine) Shell() error {
    85  	errBuf := new(bytes.Buffer)
    86  	defer resetBuffer(errBuf)
    87  
    88  	gcloud, err := exec.LookPath("gcloud")
    89  	if err != nil {
    90  		return err
    91  	}
    92  
    93  	if err := gcloudSession(c.context.desired.JSONKey.Value, gcloud, func(bin string) error {
    94  		cmd := exec.Command(gcloud,
    95  			"compute",
    96  			"ssh",
    97  			"--zone", c.zone,
    98  			fmt.Sprintf("orbiter@%s", c.id),
    99  			"--tunnel-through-iap",
   100  			"--project", c.context.projectID,
   101  		)
   102  		cmd.Stderr = os.Stderr
   103  		cmd.Stdin = os.Stdin
   104  		cmd.Stdout = os.Stdout
   105  		return cmd.Run()
   106  	}); err != nil {
   107  		return err
   108  	}
   109  	return nil
   110  }
   111  
   112  func (c *gceMachine) WriteFile(path string, data io.Reader, permissions uint16) error {
   113  
   114  	user, err := c.Execute(nil, "whoami")
   115  	if err != nil {
   116  		return err
   117  	}
   118  
   119  	mkdir, writeFile := ssh.WriteFileCommands(strings.TrimSpace(string(user)), path, permissions)
   120  	_, err = c.Execute(nil, mkdir)
   121  	if err != nil {
   122  		return err
   123  	}
   124  
   125  	_, err = c.Execute(data, writeFile)
   126  	return err
   127  }
   128  
   129  func (c *gceMachine) ReadFile(path string, data io.Writer) error {
   130  	buf, err := c.execute(nil, fmt.Sprintf("sudo cat %s", path))
   131  	defer resetBuffer(buf)
   132  	if err != nil {
   133  		return err
   134  	}
   135  
   136  	_, err = io.Copy(data, buf)
   137  	return err
   138  }