From 3011475ed84f639e37b13a1d03e16670304cd0bb Mon Sep 17 00:00:00 2001 From: Ridai Govinda Pombo Date: Fri, 19 Jun 2020 09:33:09 -0300 Subject: [PATCH] Execution runtimes are more reliable This adds a stable ground to running yb run, exec and build It also does some major clean up. * Narwhal v0.5.1 was used [ch815] [ch1592] [ch1594] [ch1593] --- .yourbase.yml | 1 - cli/run.go | 8 ++++- go.mod | 10 ++++-- go.sum | 24 ++++++++++---- plumbing/util.go | 2 -- runtime/containers.go | 50 +++++++++++++++++------------ runtime/runtime.go | 13 +++++--- workspace/package.go | 37 +++++++++------------ workspace/workspace.go | 73 +++++++++++++++++++++++++++++++++++++++--- 9 files changed, 154 insertions(+), 64 deletions(-) diff --git a/.yourbase.yml b/.yourbase.yml index 2ddb64d6..103356e8 100644 --- a/.yourbase.yml +++ b/.yourbase.yml @@ -5,7 +5,6 @@ dependencies: build_targets: - name: default - host_only: true commands: - go test ./... - go build diff --git a/cli/run.go b/cli/run.go index a23bb2ab..d177ae00 100644 --- a/cli/run.go +++ b/cli/run.go @@ -46,7 +46,13 @@ func (b *RunCmd) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{}) return subcommands.ExitFailure } - runtimeTarget := "default" + pkg, err := ws.TargetPackage() + if err != nil { + log.Errorf("Error loading workspace: %v", err) + return subcommands.ExitFailure + } + + runtimeTarget := pkg.Name argList := f.Args() workDir := "/workspace" diff --git a/go.mod b/go.mod index 52e9c11f..989600cd 100644 --- a/go.mod +++ b/go.mod @@ -32,11 +32,15 @@ require ( github.com/ulikunitz/xz v0.5.7 github.com/waigani/diffparser v0.0.0-20190828052634-7391f219313d // indirect github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect - github.com/yourbase/narwhal v0.3.1 - golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9 + github.com/yourbase/narwhal v0.5.1 + golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 golang.org/x/mod v0.3.0 - golang.org/x/net v0.0.0-20200602114024-627f9648deb9 // indirect + golang.org/x/net v0.0.0-20200625001655-4c5254603344 // indirect golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e // indirect + golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae // indirect + google.golang.org/genproto v0.0.0-20200626011028-ee7919e894b5 // indirect + google.golang.org/grpc v1.30.0 // indirect + google.golang.org/protobuf v1.25.0 // indirect gopkg.in/ini.v1 v1.57.0 gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 // indirect gopkg.in/src-d/go-billy.v4 v4.3.2 diff --git a/go.sum b/go.sum index 4af1d58c..01d9027a 100644 --- a/go.sum +++ b/go.sum @@ -163,6 +163,8 @@ github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.4.1 h1:/exdXoGamhu5ONeUJH0deniYLWYvQwW66yvlfiiKTu0= github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= @@ -355,8 +357,8 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1: github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= -github.com/yourbase/narwhal v0.3.1 h1:V93h26Mu5HlQ99hlBRDjlvoDS9t2e9XCcir5EVHRSas= -github.com/yourbase/narwhal v0.3.1/go.mod h1:C+3zsAn+HhiwMMOAWesrEWFiTWarhn7VT2qZIhGz1Bc= +github.com/yourbase/narwhal v0.5.1 h1:MHQ39AI17HFGoONoHk+p5YaK3t5QH3VNQ/9bE8Rva7c= +github.com/yourbase/narwhal v0.5.1/go.mod h1:TyuDATqB+M33Uskfj+gvpE/6bNe8g3zCAjlz4gwWe14= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= golang.org/x/crypto v0.0.0-20160824173033-351dc6a5bf92/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -370,8 +372,8 @@ golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9 h1:vEg9joUBmeBcK9iSJftGNf3coIG4HqZElCPehJsfAYM= -golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -400,8 +402,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 h1:Ao/3l156eZf2AW5wK8a7/smtodRU+gha3+BeqJ69lRk= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200602114024-627f9648deb9 h1:pNX+40auqi2JqRfOP1akLGtYcn15TUbkhwuCO3foqqM= -golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -433,6 +435,8 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20u golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200610111108-226ff32320da h1:bGb80FudwxpeucJUjPYJXuJ8Hk91vNtfvrymzwiei38= golang.org/x/sys v0.0.0-20200610111108-226ff32320da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae h1:Ih9Yo4hSPImZOpfGuA4bR/ORKTAbhZo2AbWNRCnevdo= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.0.0-20170915090833-1cbadb444a80/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= @@ -473,6 +477,8 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98 google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200610104632-a5b850bcf112 h1:iwoQI4kCHAgRg0oltV6+Jnq5COzoS0NN+QLqHewrf5U= google.golang.org/genproto v0.0.0-20200610104632-a5b850bcf112/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200626011028-ee7919e894b5 h1:a/Sqq5B3dGnmxhuJZIHFsIxhEkqElErr5TaU6IqBAj0= +google.golang.org/genproto v0.0.0-20200626011028-ee7919e894b5/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= @@ -484,6 +490,8 @@ google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0 h1:M5a8xTlYTxwMn5ZFkwhRabsygDY5G8TYLyQDBxJNAxE= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -496,6 +504,8 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.24.0 h1:UhZDfRO8JRQru4/+LlLE0BRKGF8L+PICnvYZmx/fEGA= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20160105164936-4f90aeace3a2/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -540,3 +550,5 @@ mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIa mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4= mvdan.cc/unparam v0.0.0-20190209190245-fbb59629db34/go.mod h1:H6SUd1XjIs+qQCyskXg5OFSrilMRUkD8ePJpHKDPaeY= sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= +zombiezen.com/go/log v1.0.0 h1:4IvZxBeSxdd5GZdqVNxM2j9omoTDvoP7yyxZodSHi5A= +zombiezen.com/go/log v1.0.0/go.mod h1:Eos1rXF8JpgK+h6NYITdTJslqFJJA3SaIJHMU75Sqfg= diff --git a/plumbing/util.go b/plumbing/util.go index 3cfdf634..6a8196c3 100644 --- a/plumbing/util.go +++ b/plumbing/util.go @@ -189,8 +189,6 @@ func FindWorkspaceRoot() (string, error) { // Look upwards to find a manifest file packageDir, err := FindNearestManifestFile() - fmt.Print("WorkspaceRoot considered: ", packageDir) - // If we find a manifest file, check the parent directory for a config.yml if err == nil { parent := filepath.Dir(packageDir) diff --git a/runtime/containers.go b/runtime/containers.go index d53aa35e..30e46e62 100644 --- a/runtime/containers.go +++ b/runtime/containers.go @@ -5,16 +5,22 @@ import ( "bytes" "context" "fmt" - "github.com/yourbase/yb/plumbing/log" "io" "io/ioutil" "net" "os" "strings" + "github.com/yourbase/yb/plumbing/log" + "github.com/yourbase/narwhal" ) +const ( + ContainerDefaultToolsDir = "/opt/yb/tools" + ContainerDefaultCacheDir = "/opt/yb/cache" +) + type ContainerTarget struct { Target Container *narwhal.Container @@ -29,7 +35,6 @@ func (t *ContainerTarget) OS() Os { func (t *ContainerTarget) OSVersion(ctx context.Context) string { var buf bytes.Buffer bufWriter := bufio.NewWriter(&buf) - //err := t.Container.DownloadDirectoryToWriter("/etc/os-release", &buf) err := narwhal.ExecShell(ctx, narwhal.DockerClient(), t.Container.Id, "cat /etc/os-release", &narwhal.ExecShellOptions{ Dir: "/", CombinedOutput: bufWriter, @@ -66,33 +71,27 @@ func (t *ContainerTarget) Architecture() Architecture { return Amd64 } -func (t *ContainerTarget) mkdirInContainer(ctx context.Context, dir string) (created string) { - if t.PathExists(ctx, dir) { - return dir - } - - cmdString := "mkdir -p " + dir - err := narwhal.ExecShell(ctx, narwhal.DockerClient(), t.Container.Id, cmdString, &narwhal.ExecShellOptions{}) - if err == nil { - created = dir - } - - return -} - func (t *ContainerTarget) ToolsDir(ctx context.Context) string { - return t.mkdirInContainer(ctx, "/opt/yb/tools") + err := narwhal.MkdirAll(ctx, narwhal.DockerClient(), t.Container.Id, ContainerDefaultToolsDir) + if err != nil { + return "" + } + return ContainerDefaultToolsDir } func (t *ContainerTarget) PathExists(ctx context.Context, path string) bool { // Assume we can use stat for now statCmd := fmt.Sprintf("stat %s", path) + // Will be ignored, but Docker only succeeds if we pass an output io stream + buff := new(bytes.Buffer) - err := narwhal.ExecShell(ctx, narwhal.DockerClient(), t.Container.Id, statCmd, &narwhal.ExecShellOptions{Dir: "/"}) + err := narwhal.ExecShell(ctx, narwhal.DockerClient(), t.Container.Id, statCmd, &narwhal.ExecShellOptions{CombinedOutput: buff}) if err != nil { - if _, ok := narwhal.IsExitError(err); ok { + if code, _ := narwhal.IsExitError(err); code != 0 { return false } + // Return false anyway, as it errored + return false } return true @@ -103,7 +102,11 @@ func (t *ContainerTarget) String() string { } func (t *ContainerTarget) CacheDir(ctx context.Context) string { - return t.mkdirInContainer(ctx, "/opt/yb/cache") + err := narwhal.MkdirAll(ctx, narwhal.DockerClient(), t.Container.Id, ContainerDefaultCacheDir) + if err != nil { + return "" + } + return ContainerDefaultCacheDir } func (t *ContainerTarget) PrependToPath(ctx context.Context, dir string) { @@ -175,7 +178,10 @@ func (t *ContainerTarget) DownloadFile(ctx context.Context, url string) (string, func (t *ContainerTarget) Unarchive(ctx context.Context, src string, dst string) error { var command string - t.mkdirInContainer(ctx, dst) + err := narwhal.MkdirAll(ctx, narwhal.DockerClient(), t.Container.Id, dst) + if err != nil { + return fmt.Errorf("making dir for unarchiving %s: %v", src, err) + } if strings.HasSuffix(src, "tar.gz") { command = fmt.Sprintf("tar zxf %s -C %s", src, dst) @@ -223,6 +229,8 @@ func (t *ContainerTarget) Run(ctx context.Context, p Process) error { output = p.Output } + t.Container.Definition.Environment = p.Environment + if p.Interactive { return narwhal.ExecShell(ctx, narwhal.DockerClient(), t.Container.Id, p.Command, &narwhal.ExecShellOptions{ Dir: p.Directory, diff --git a/runtime/runtime.go b/runtime/runtime.go index 280f7c67..b35735b7 100644 --- a/runtime/runtime.go +++ b/runtime/runtime.go @@ -3,10 +3,11 @@ package runtime import ( "context" "fmt" - "github.com/yourbase/yb/plumbing/log" "io" "strings" + "github.com/yourbase/yb/plumbing/log" + goruntime "runtime" "github.com/yourbase/narwhal" @@ -76,6 +77,10 @@ func (r *Runtime) SupportsContainers() bool { return r.ContainerServiceContext != nil } +func (r *Runtime) NTargets() int { + return len(r.Targets) +} + func (r *Runtime) AddTarget(targetId string, t Target) error { if _, exists := r.Targets[targetId]; exists { return fmt.Errorf("Unable to add target with id %s - already exists", targetId) @@ -150,15 +155,15 @@ func NewRuntime(ctx context.Context, identifier string, localWorkDir string) *Ru Identifier: identifier, LocalWorkDir: localWorkDir, Targets: make(map[string]Target), - DefaultTarget: &MetalTarget{}, + DefaultTarget: &MetalTarget{workDir: localWorkDir}, ContainerServiceContext: sc, } } -func (r *Runtime) Shutdown() error { +func (r *Runtime) Shutdown(ctx context.Context) error { if r.ContainerServiceContext != nil { - if err := r.ContainerServiceContext.TearDown(); err != nil { + if err := r.ContainerServiceContext.TearDown(ctx); err != nil { return err } } diff --git a/workspace/package.go b/workspace/package.go index da9daa69..523844fe 100644 --- a/workspace/package.go +++ b/workspace/package.go @@ -4,16 +4,15 @@ import ( "context" "errors" "fmt" - "github.com/yourbase/narwhal" - "gopkg.in/yaml.v2" "io" "io/ioutil" "os" - "os/signal" "path/filepath" "strings" - "syscall" + "gopkg.in/yaml.v2" + + "github.com/yourbase/narwhal" . "github.com/yourbase/yb/plumbing" "github.com/yourbase/yb/plumbing/log" "github.com/yourbase/yb/runtime" @@ -103,20 +102,6 @@ func (p Package) ExecuteToWriter(ctx context.Context, runtimeCtx *runtime.Runtim return err } - // TODO Be smarter - c := make(chan os.Signal, 2) - signal.Notify(c, os.Interrupt, syscall.SIGTERM) - go func() { - <-c - fmt.Println("\r- Ctrl+C pressed in Terminal") - if err := runtimeCtx.Shutdown(); err != nil { - // Oops. - os.Exit(1) - } - // Ok! - os.Exit(0) - }() - log.Infof("Executing package '%s'...\n", p.Name) for _, cmdString := range p.Manifest.Exec.Commands { @@ -136,6 +121,15 @@ func (p Package) ExecuteToWriter(ctx context.Context, runtimeCtx *runtime.Runtim return nil } +func (p Package) addMount(cd *narwhal.ContainerDefinition, localPath, remotePath, thing string) { + if thing == "" { + thing = "package" + } + log.Infof("Will mount %s %s at %s in container", thing, localPath, remotePath) + mount := fmt.Sprintf("%s:%s", localPath, remotePath) + cd.Mounts = append(cd.Mounts, mount) +} + func (p Package) checkMounts(cd *narwhal.ContainerDefinition, srcDir string) error { for _, mount := range cd.Mounts { parts := strings.Split(mount, ":") @@ -215,9 +209,10 @@ func (p Package) createExecutionTarget(ctx context.Context, runtimeCtx *runtime. if execContainer.WorkDir != "" { sourceMapDir = execContainer.WorkDir } - log.Infof("Will mount package %s at %s in container", p.Path(), sourceMapDir) - mount := fmt.Sprintf("%s:%s", p.Path(), sourceMapDir) - execContainer.Mounts = append(execContainer.Mounts, mount) + if err := p.checkMounts(&execContainer, p.Path()); err != nil { + return nil, fmt.Errorf("Unable to set host container mount dir: %v", err) + } + p.addMount(&execContainer, p.Path(), sourceMapDir, "package") execTarget, err := runtimeCtx.AddContainer(ctx, execContainer) if err != nil { diff --git a/workspace/workspace.go b/workspace/workspace.go index d747683e..d40a16e4 100644 --- a/workspace/workspace.go +++ b/workspace/workspace.go @@ -4,7 +4,6 @@ import ( "context" "crypto/sha256" "fmt" - "github.com/yourbase/yb/runtime" "io/ioutil" "os" "os/user" @@ -15,6 +14,7 @@ import ( . "github.com/yourbase/yb/plumbing" "github.com/yourbase/yb/plumbing/log" + "github.com/yourbase/yb/runtime" ) type Workspace struct { @@ -27,13 +27,23 @@ func (w Workspace) RunInTarget(ctx context.Context, cmdString string, workDir st log.Infof("Running %s in %s from %s", cmdString, targetName, workDir) - p := runtime.Process{Command: cmdString, Interactive: true, Directory: workDir} + pkg, err := w.TargetPackage() + if err != nil { + return err + } + + p := runtime.Process{Command: cmdString, Interactive: true, Directory: workDir, Environment: pkg.Manifest.Exec.Environment["default"]} runCtx, err := w.execRuntimeContext(ctx) if err != nil { return err } + _, err = pkg.createExecutionTarget(ctx, runCtx) + if err != nil { + return err + + } return runCtx.RunInTarget(ctx, p, targetName) } @@ -216,15 +226,68 @@ func LoadWorkspace() (Workspace, error) { manifestFile := filepath.Join(workspacePath, ".yourbase.yml") configFile := filepath.Join(workspacePath, "config.yml") + var w Workspace + if PathExists(manifestFile) { log.Debugf("Loading workspace from manifest file: %s", manifestFile) - return loadWorkspaceFromPackage(manifestFile, workspacePath) + w, err = loadWorkspaceFromPackage(manifestFile, workspacePath) + } + + if err == nil && validWorkspaceConfig(w) { + return w, nil } if PathExists(configFile) { log.Debugf("Loading workspace from config file: %s", configFile) - return loadWorkspaceFromConfigYaml(configFile, workspacePath) + w, err = loadWorkspaceFromConfigYaml(configFile, workspacePath) + } + + if err == nil && validWorkspaceConfig(w) { + return w, nil + } + + return Workspace{}, fmt.Errorf("Error resolving workspace at path %s", workspacePath) +} + +// validWorkspaceConfig will check if every expected part of whole Configuration Graph is initialized +// as expected +func validWorkspaceConfig(workspace Workspace) (valid bool) { + if valid = len(workspace.packages) > 0; !valid { + return + } + + if valid = filepath.IsAbs(workspace.Path); !valid { + return + } + + if valid = workspace.Target != ""; !valid { + return + } + + for _, pkg := range workspace.packages { + if valid = filepath.IsAbs(pkg.Path()); !valid { + return + } + + if valid = pkg.Name != ""; !valid { + return + } + + if valid = len(pkg.Manifest.Exec.Commands) > 0; !valid { + if pkg.Manifest.Exec.Environment == nil { + pkg.Manifest.Exec.Environment = make(map[string][]string) + } + // No Exec Phase defined, not required, but `yb run should still work` + pkg.Manifest.Exec.Environment["default"] = pkg.Manifest.Build.Environment + if len(pkg.Manifest.Exec.Environment["default"]) == 0 { + if valid = len(pkg.Manifest.BuildTargets) > 0; !valid { + return + } + pkg.Manifest.Exec.Environment["default"] = pkg.Manifest.BuildTargets[0].Environment + } + } + } - return Workspace{}, fmt.Errorf("Error finding workspace at path %s", workspacePath) + return }