115 lines
3 KiB
Go
115 lines
3 KiB
Go
package auto
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"encoding/json"
|
|
"os"
|
|
"os/exec"
|
|
"runtime/debug"
|
|
"strings"
|
|
|
|
"github.com/pkg/errors"
|
|
"github.com/pulumi/pulumi/sdk/v2/go/pulumi"
|
|
)
|
|
|
|
func (s *stack) host(isPreview bool) (string, string, error) {
|
|
var stdout bytes.Buffer
|
|
var errBuff bytes.Buffer
|
|
args := []string{"host"}
|
|
if isPreview {
|
|
args = append(args, "preview")
|
|
}
|
|
cmd := exec.Command("pulumi", args...)
|
|
cmd.Dir = s.SourcePath
|
|
cmd.Stdout = &stdout
|
|
stderr, _ := cmd.StderrPipe()
|
|
cmd.Start()
|
|
scanner := bufio.NewScanner(stderr)
|
|
scanner.Split(bufio.ScanLines)
|
|
|
|
resMonAddrChan := make(chan string)
|
|
engineAddrChan := make(chan string)
|
|
failChan := make(chan bool)
|
|
go func() {
|
|
numAddrs := 0
|
|
for scanner.Scan() {
|
|
m := scanner.Text()
|
|
errBuff.WriteString(m)
|
|
if strings.HasPrefix(m, "resmon: ") {
|
|
numAddrs++
|
|
// resmon: 127.0.0.1:23423
|
|
resMonAddrChan <- strings.Split(m, " ")[1]
|
|
}
|
|
if strings.HasPrefix(m, "engine: ") {
|
|
numAddrs++
|
|
// engine: 127.0.0.1:23423
|
|
engineAddrChan <- strings.Split(m, " ")[1]
|
|
}
|
|
}
|
|
if numAddrs < 2 {
|
|
failChan <- true
|
|
}
|
|
}()
|
|
var monitorAddr string
|
|
var engineAddr string
|
|
for i := 0; i < 2; i++ {
|
|
select {
|
|
case <-failChan:
|
|
return stdout.String(), errBuff.String(), errors.New("failed to launch host")
|
|
case monitorAddr = <-resMonAddrChan:
|
|
case engineAddr = <-engineAddrChan:
|
|
}
|
|
}
|
|
|
|
os.Setenv(pulumi.EnvMonitor, monitorAddr)
|
|
os.Setenv(pulumi.EnvProject, s.ProjectName)
|
|
os.Setenv(pulumi.EnvStack, s.Name)
|
|
os.Setenv(pulumi.EnvEngine, engineAddr)
|
|
|
|
cfg, err := s.rawConfig()
|
|
if err != nil {
|
|
return stdout.String(), errBuff.String(), errors.Wrap(err, "failed to serialize config for inline program")
|
|
}
|
|
cfgStr, err := json.Marshal(cfg)
|
|
if err != nil {
|
|
return stdout.String(), errBuff.String(), errors.Wrap(err, "unable to marshal config")
|
|
}
|
|
os.Setenv(pulumi.EnvConfig, string(cfgStr))
|
|
err = execUserCode(s.InlineSource)
|
|
if err != nil {
|
|
cmd.Process.Signal(os.Interrupt)
|
|
waitErr := cmd.Wait()
|
|
if waitErr != nil {
|
|
return stdout.String(), errBuff.String(), errors.Wrap(err, "failed to run inline program and shutdown gracefully")
|
|
}
|
|
return stdout.String(), errBuff.String(), errors.Wrap(err, "error running inline pulumi program")
|
|
}
|
|
|
|
err = cmd.Process.Signal(os.Interrupt)
|
|
if err != nil {
|
|
return stdout.String(), errBuff.String(), errors.Wrap(err, "failed to shutdown host gracefully")
|
|
}
|
|
cmd.Wait()
|
|
|
|
return stdout.String(), errBuff.String(), nil
|
|
}
|
|
|
|
func execUserCode(fn pulumi.RunFunc) (err error) {
|
|
defer func() {
|
|
if r := recover(); r != nil {
|
|
if pErr, ok := r.(error); ok {
|
|
err = errors.Wrap(pErr, "go inline source runtime error, an unhandled error occurred:")
|
|
} else {
|
|
err = errors.New("go inline source runtime error, an unhandled error occurred: unknown error")
|
|
}
|
|
}
|
|
}()
|
|
stack := string(debug.Stack())
|
|
if strings.Contains(stack, "github.com/pulumi/pulumi/sdk/go/pulumi/run.go") {
|
|
return errors.New("nested stack operations are not supported https://github.com/pulumi/pulumi/issues/5058")
|
|
}
|
|
|
|
err = pulumi.RunErr(fn)
|
|
return err
|
|
}
|