// Copyright (c) 2020 Gitpod GmbH. All rights reserved. // Licensed under the GNU Affero General Public License (AGPL). // See License-AGPL.txt in the project root for license information. package cmd import ( "encoding/base64" "io" "log" "os" "syscall" "github.com/spf13/cobra" ) // This command takes a base64 stream, saves it to disk and executes it. We use this in // agent-smith to upload/run the sentinel. // We don't want this explanation to end up in the binary. const delimiter = "@" // gitpodRunCmd represents the gitpodRun command var gitpodRunCmd = &cobra.Command{ Use: "__gitpod_run []", Short: "Used by Gitpod to ensure smooth operation", Hidden: true, Args: cobra.MaximumNArgs(1), Run: func(cmd *cobra.Command, args []string) { var tmpfile *os.File var err error if len(args) == 1 { tmpfile, err = os.OpenFile(args[0], os.O_WRONLY|os.O_CREATE, 0700) } else { tmpfile, err = os.CreateTemp("", "gp") } if err != nil { _ = os.Remove(tmpfile.Name()) log.Fatal(err) } decoder := base64.NewDecoder(base64.RawStdEncoding, &delimitingReader{os.Stdin, false}) _, err = io.Copy(tmpfile, decoder) if err != nil { _ = os.Remove(tmpfile.Name()) log.Fatal(err) } tmpfile.Close() err = os.Chmod(tmpfile.Name(), 0700) if err != nil { _ = os.Remove(tmpfile.Name()) log.Fatal(err) } err = syscall.Exec(tmpfile.Name(), []string{"gpr", "serve"}, []string{}) if err != nil { _ = os.Remove(tmpfile.Name()) log.Fatal(err) } }, } type delimitingReader struct { io.Reader EOF bool } func (p *delimitingReader) Read(buf []byte) (int, error) { if p.EOF { return 0, io.EOF } n, err := p.Reader.Read(buf) if err != nil { return n, err } for i := 0; i < n; i++ { if buf[i] == delimiter[0] { p.EOF = true return i, io.EOF } } return n, err } func init() { rootCmd.AddCommand(gitpodRunCmd) }