[automation/go] - Expose structured logging (#6436)
This commit is contained in:
parent
5a8e470176
commit
10d99b8afb
|
@ -19,6 +19,30 @@
|
|||
Please note that `pulumi watch` will not be supported on darwin/arm64 builds.
|
||||
[#6492](https://github.com/pulumi/pulumi/pull/6492)
|
||||
|
||||
- [automation/go] - BREAKING - Expose structured logging for Stack.Up/Preview/Refresh/Destroy.
|
||||
[#6436](https://github.com/pulumi/pulumi/pull/6436)
|
||||
|
||||
This change is marked breaking because it changes the shape of the `PreviewResult` struct.
|
||||
|
||||
**Before**
|
||||
|
||||
```go
|
||||
type PreviewResult struct {
|
||||
Steps []PreviewStep `json:"steps"`
|
||||
ChangeSummary map[string]int `json:"changeSummary"`
|
||||
}
|
||||
```
|
||||
|
||||
**After**
|
||||
|
||||
```go
|
||||
type PreviewResult struct {
|
||||
StdOut string
|
||||
StdErr string
|
||||
ChangeSummary map[apitype.OpType]int
|
||||
}
|
||||
```
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- [sdk/python] Fix mocks issue when passing a resource more than once.
|
||||
|
|
|
@ -87,9 +87,9 @@ func ConvertEngineEvent(e engine.Event) (apitype.EngineEvent, error) {
|
|||
return apiEvent, eventTypePayloadMismatch
|
||||
}
|
||||
// Convert the resource changes.
|
||||
changes := make(map[string]int)
|
||||
changes := make(map[apitype.OpType]int)
|
||||
for op, count := range p.ResourceChanges {
|
||||
changes[string(op)] = count
|
||||
changes[apitype.OpType(op)] = count
|
||||
}
|
||||
apiEvent.SummaryEvent = &apitype.SummaryEvent{
|
||||
MaybeCorrupt: p.MaybeCorrupt,
|
||||
|
@ -174,7 +174,7 @@ func convertStepEventMetadata(md engine.StepEventMetadata) apitype.StepEventMeta
|
|||
}
|
||||
|
||||
return apitype.StepEventMetadata{
|
||||
Op: string(md.Op),
|
||||
Op: apitype.OpType(md.Op),
|
||||
URN: string(md.URN),
|
||||
Type: string(md.Type),
|
||||
|
||||
|
|
|
@ -539,6 +539,7 @@ github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d h1:AREM5mwr4u1
|
|||
github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw=
|
||||
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
|
||||
github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
|
||||
|
@ -1067,6 +1068,7 @@ gopkg.in/src-d/go-git-fixtures.v3 v3.5.0 h1:ivZFOIltbce2Mo8IjzUHAFoq/IylO9WHhNOA
|
|||
gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g=
|
||||
gopkg.in/src-d/go-git.v4 v4.13.1 h1:SRtFyV8Kxc0UP7aCHcijOMQGPxHSmMOPrzulQWolkYE=
|
||||
gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
|
|
|
@ -73,6 +73,7 @@ github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjr
|
|||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
|
||||
|
@ -185,6 +186,7 @@ github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQz
|
|||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223 h1:F9x/1yl3T2AeKLr2AMdilSD8+f9bvMnNN8VS5iDtovc=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
|
||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
github.com/opentracing/basictracer-go v1.0.0 h1:YyUAhaEfjoWXclZVJ9sGoNct7j4TVk7lZWlQw5UXuoo=
|
||||
|
@ -337,6 +339,7 @@ golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5h
|
|||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
@ -406,6 +409,7 @@ gopkg.in/src-d/go-git-fixtures.v3 v3.5.0 h1:ivZFOIltbce2Mo8IjzUHAFoq/IylO9WHhNOA
|
|||
gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g=
|
||||
gopkg.in/src-d/go-git.v4 v4.13.1 h1:SRtFyV8Kxc0UP7aCHcijOMQGPxHSmMOPrzulQWolkYE=
|
||||
gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
|
|
|
@ -22,6 +22,7 @@ require (
|
|||
github.com/mattn/go-colorable v0.1.6 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.8 // indirect
|
||||
github.com/mitchellh/go-ps v1.0.0
|
||||
github.com/nxadm/tail v1.4.8
|
||||
github.com/opentracing/basictracer-go v1.0.0 // indirect
|
||||
github.com/opentracing/opentracing-go v1.1.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
|
|
|
@ -73,6 +73,8 @@ github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjr
|
|||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
|
||||
|
@ -185,6 +187,8 @@ github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQz
|
|||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223 h1:F9x/1yl3T2AeKLr2AMdilSD8+f9bvMnNN8VS5iDtovc=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
|
||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
github.com/opentracing/basictracer-go v1.0.0 h1:YyUAhaEfjoWXclZVJ9sGoNct7j4TVk7lZWlQw5UXuoo=
|
||||
|
@ -337,6 +341,7 @@ golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5h
|
|||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
@ -406,6 +411,8 @@ gopkg.in/src-d/go-git-fixtures.v3 v3.5.0 h1:ivZFOIltbce2Mo8IjzUHAFoq/IylO9WHhNOA
|
|||
gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g=
|
||||
gopkg.in/src-d/go-git.v4 v4.13.1 h1:SRtFyV8Kxc0UP7aCHcijOMQGPxHSmMOPrzulQWolkYE=
|
||||
gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
|
|
|
@ -72,9 +72,8 @@ type SummaryEvent struct {
|
|||
MaybeCorrupt bool `json:"maybeCorrupt"`
|
||||
// Duration is the number of seconds the update was executing.
|
||||
DurationSeconds int `json:"durationSeconds"`
|
||||
// ResourceChanges contains the count for resource change by type. The keys are deploy.StepOp,
|
||||
// which is not exported in this package.
|
||||
ResourceChanges map[string]int `json:"resourceChanges"`
|
||||
// ResourceChanges contains the count for resource change by type.
|
||||
ResourceChanges map[OpType]int `json:"resourceChanges"`
|
||||
// PolicyPacks run during update. Maps PolicyPackName -> version.
|
||||
// Note: When this field was initially added, we forgot to add the JSON tag
|
||||
// and are now locked into to using PascalCase for this field to maintain backwards
|
||||
|
@ -112,8 +111,8 @@ type PropertyDiff struct {
|
|||
// StepEventMetadata describes a "step" within the Pulumi engine, which is any concrete action
|
||||
// to migrate a set of cloud resources from one state to another.
|
||||
type StepEventMetadata struct {
|
||||
// Op is the operation being performed, a deploy.StepOp.
|
||||
Op string `json:"op"`
|
||||
// Op is the operation being performed.
|
||||
Op OpType `json:"op"`
|
||||
URN string `json:"urn"`
|
||||
Type string `json:"type"`
|
||||
|
||||
|
|
|
@ -77,6 +77,22 @@ const (
|
|||
OpCreateReplacement OpType = "create-replacement"
|
||||
// OpDeleteReplaced indicates an existing resource was deleted after replacement.
|
||||
OpDeleteReplaced OpType = "delete-replaced"
|
||||
// OpRead indicates reading an existing resource.
|
||||
OpRead OpType = "read"
|
||||
// OpReadReplacement indicates reading an existing resource for a replacement.
|
||||
OpReadReplacement OpType = "read-replacement"
|
||||
// OpRefresh indicates refreshing an existing resource.
|
||||
OpRefresh OpType = "refresh" // refreshing an existing resource.
|
||||
// OpReadDiscard indicates removing a resource that was read.
|
||||
OpReadDiscard OpType = "discard"
|
||||
// OpDiscardReplaced indicates discarding a read resource that was replaced.
|
||||
OpDiscardReplaced OpType = "discard-replaced"
|
||||
// OpRemovePendingReplace indicates removing a pending replace resource.
|
||||
OpRemovePendingReplace OpType = "remove-pending-replace"
|
||||
// OpImport indicates importing an existing resource.
|
||||
OpImport OpType = "import"
|
||||
// OpImportReplacement indicates replacement of an existing resource with an imported resource.
|
||||
OpImportReplacement OpType = "import-replacement"
|
||||
)
|
||||
|
||||
// UpdateInfo describes a previous update.
|
||||
|
|
8
sdk/go/x/auto/events/events.go
Normal file
8
sdk/go/x/auto/events/events.go
Normal file
|
@ -0,0 +1,8 @@
|
|||
package events
|
||||
|
||||
import "github.com/pulumi/pulumi/sdk/v2/go/common/apitype"
|
||||
|
||||
type EngineEvent struct {
|
||||
apitype.EngineEvent
|
||||
Error error
|
||||
}
|
|
@ -26,11 +26,14 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/pulumi/pulumi/sdk/v2/go/common/apitype"
|
||||
"github.com/pulumi/pulumi/sdk/v2/go/common/tokens"
|
||||
"github.com/pulumi/pulumi/sdk/v2/go/common/workspace"
|
||||
"github.com/pulumi/pulumi/sdk/v2/go/pulumi"
|
||||
"github.com/pulumi/pulumi/sdk/v2/go/pulumi/config"
|
||||
"github.com/pulumi/pulumi/sdk/v2/go/x/auto/events"
|
||||
"github.com/pulumi/pulumi/sdk/v2/go/x/auto/optdestroy"
|
||||
"github.com/pulumi/pulumi/sdk/v2/go/x/auto/optpreview"
|
||||
"github.com/pulumi/pulumi/sdk/v2/go/x/auto/optrefresh"
|
||||
"github.com/pulumi/pulumi/sdk/v2/go/x/auto/optup"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
@ -189,13 +192,17 @@ func TestNewStackLocalSource(t *testing.T) {
|
|||
|
||||
// -- pulumi preview --
|
||||
|
||||
prev, err := s.Preview(ctx)
|
||||
var previewEvents []events.EngineEvent
|
||||
prevCh := make(chan events.EngineEvent)
|
||||
go collectEvents(prevCh, &previewEvents)
|
||||
prev, err := s.Preview(ctx, optpreview.EventStreams(prevCh))
|
||||
if err != nil {
|
||||
t.Errorf("preview failed, err: %v", err)
|
||||
t.FailNow()
|
||||
}
|
||||
assert.Equal(t, 1, prev.ChangeSummary["same"])
|
||||
assert.Equal(t, 1, len(prev.Steps))
|
||||
assert.Equal(t, 1, prev.ChangeSummary[apitype.OpSame])
|
||||
steps := countSteps(previewEvents)
|
||||
assert.Equal(t, 1, steps)
|
||||
|
||||
// -- pulumi refresh --
|
||||
|
||||
|
@ -291,27 +298,30 @@ func TestUpsertStackLocalSource(t *testing.T) {
|
|||
|
||||
// -- pulumi preview --
|
||||
|
||||
prev, err := s.Preview(ctx)
|
||||
var previewEvents []events.EngineEvent
|
||||
prevCh := make(chan events.EngineEvent)
|
||||
go collectEvents(prevCh, &previewEvents)
|
||||
prev, err := s.Preview(ctx, optpreview.EventStreams(prevCh))
|
||||
if err != nil {
|
||||
t.Errorf("preview failed, err: %v", err)
|
||||
t.FailNow()
|
||||
}
|
||||
assert.Equal(t, 1, prev.ChangeSummary["same"])
|
||||
assert.Equal(t, 1, len(prev.Steps))
|
||||
|
||||
assert.Equal(t, 1, prev.ChangeSummary[apitype.OpSame])
|
||||
steps := countSteps(previewEvents)
|
||||
assert.Equal(t, 1, steps)
|
||||
|
||||
// -- pulumi refresh --
|
||||
|
||||
ref, err := s.Refresh(ctx)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("refresh failed, err: %v", err)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
assert.Equal(t, "refresh", ref.Summary.Kind)
|
||||
assert.Equal(t, "succeeded", ref.Summary.Result)
|
||||
|
||||
// -- pulumi destroy --
|
||||
|
||||
dRes, err := s.Destroy(ctx)
|
||||
if err != nil {
|
||||
t.Errorf("destroy failed, err: %v", err)
|
||||
|
@ -384,13 +394,17 @@ func TestNewStackRemoteSource(t *testing.T) {
|
|||
|
||||
// -- pulumi preview --
|
||||
|
||||
prev, err := s.Preview(ctx)
|
||||
var previewEvents []events.EngineEvent
|
||||
prevCh := make(chan events.EngineEvent)
|
||||
go collectEvents(prevCh, &previewEvents)
|
||||
prev, err := s.Preview(ctx, optpreview.EventStreams(prevCh))
|
||||
if err != nil {
|
||||
t.Errorf("preview failed, err: %v", err)
|
||||
t.FailNow()
|
||||
}
|
||||
assert.Equal(t, 1, prev.ChangeSummary["same"])
|
||||
assert.Equal(t, 1, len(prev.Steps))
|
||||
assert.Equal(t, 1, prev.ChangeSummary[apitype.OpSame])
|
||||
steps := countSteps(previewEvents)
|
||||
assert.Equal(t, 1, steps)
|
||||
|
||||
// -- pulumi refresh --
|
||||
|
||||
|
@ -472,13 +486,17 @@ func TestUpsertStackRemoteSource(t *testing.T) {
|
|||
|
||||
// -- pulumi preview --
|
||||
|
||||
prev, err := s.Preview(ctx)
|
||||
var previewEvents []events.EngineEvent
|
||||
prevCh := make(chan events.EngineEvent)
|
||||
go collectEvents(prevCh, &previewEvents)
|
||||
prev, err := s.Preview(ctx, optpreview.EventStreams(prevCh))
|
||||
if err != nil {
|
||||
t.Errorf("preview failed, err: %v", err)
|
||||
t.FailNow()
|
||||
}
|
||||
assert.Equal(t, 1, prev.ChangeSummary["same"])
|
||||
assert.Equal(t, 1, len(prev.Steps))
|
||||
assert.Equal(t, 1, prev.ChangeSummary[apitype.OpSame])
|
||||
steps := countSteps(previewEvents)
|
||||
assert.Equal(t, 1, steps)
|
||||
|
||||
// -- pulumi refresh --
|
||||
|
||||
|
@ -572,13 +590,17 @@ func TestNewStackRemoteSourceWithSetup(t *testing.T) {
|
|||
|
||||
// -- pulumi preview --
|
||||
|
||||
prev, err := s.Preview(ctx)
|
||||
var previewEvents []events.EngineEvent
|
||||
prevCh := make(chan events.EngineEvent)
|
||||
go collectEvents(prevCh, &previewEvents)
|
||||
prev, err := s.Preview(ctx, optpreview.EventStreams(prevCh))
|
||||
if err != nil {
|
||||
t.Errorf("preview failed, err: %v", err)
|
||||
t.FailNow()
|
||||
}
|
||||
assert.Equal(t, 1, prev.ChangeSummary["same"])
|
||||
assert.Equal(t, 1, len(prev.Steps))
|
||||
assert.Equal(t, 1, prev.ChangeSummary[apitype.OpSame])
|
||||
steps := countSteps(previewEvents)
|
||||
assert.Equal(t, 1, steps)
|
||||
|
||||
// -- pulumi refresh --
|
||||
|
||||
|
@ -672,13 +694,17 @@ func TestUpsertStackRemoteSourceWithSetup(t *testing.T) {
|
|||
|
||||
// -- pulumi preview --
|
||||
|
||||
prev, err := s.Preview(ctx)
|
||||
var previewEvents []events.EngineEvent
|
||||
prevCh := make(chan events.EngineEvent)
|
||||
go collectEvents(prevCh, &previewEvents)
|
||||
prev, err := s.Preview(ctx, optpreview.EventStreams(prevCh))
|
||||
if err != nil {
|
||||
t.Errorf("preview failed, err: %v", err)
|
||||
t.FailNow()
|
||||
}
|
||||
assert.Equal(t, 1, prev.ChangeSummary["same"])
|
||||
assert.Equal(t, 1, len(prev.Steps))
|
||||
assert.Equal(t, 1, prev.ChangeSummary[apitype.OpSame])
|
||||
steps := countSteps(previewEvents)
|
||||
assert.Equal(t, 1, steps)
|
||||
|
||||
// -- pulumi refresh --
|
||||
|
||||
|
@ -762,13 +788,17 @@ func TestNewStackInlineSource(t *testing.T) {
|
|||
|
||||
// -- pulumi preview --
|
||||
|
||||
prev, err := s.Preview(ctx)
|
||||
var previewEvents []events.EngineEvent
|
||||
prevCh := make(chan events.EngineEvent)
|
||||
go collectEvents(prevCh, &previewEvents)
|
||||
prev, err := s.Preview(ctx, optpreview.EventStreams(prevCh))
|
||||
if err != nil {
|
||||
t.Errorf("preview failed, err: %v", err)
|
||||
t.FailNow()
|
||||
}
|
||||
assert.Equal(t, 1, prev.ChangeSummary["same"])
|
||||
assert.Equal(t, 1, len(prev.Steps))
|
||||
assert.Equal(t, 1, prev.ChangeSummary[apitype.OpSame])
|
||||
steps := countSteps(previewEvents)
|
||||
assert.Equal(t, 1, steps)
|
||||
|
||||
// -- pulumi refresh --
|
||||
|
||||
|
@ -851,13 +881,17 @@ func TestUpsertStackInlineSource(t *testing.T) {
|
|||
|
||||
// -- pulumi preview --
|
||||
|
||||
prev, err := s.Preview(ctx)
|
||||
var previewEvents []events.EngineEvent
|
||||
prevCh := make(chan events.EngineEvent)
|
||||
go collectEvents(prevCh, &previewEvents)
|
||||
prev, err := s.Preview(ctx, optpreview.EventStreams(prevCh))
|
||||
if err != nil {
|
||||
t.Errorf("preview failed, err: %v", err)
|
||||
t.FailNow()
|
||||
}
|
||||
assert.Equal(t, 1, prev.ChangeSummary["same"])
|
||||
assert.Equal(t, 1, len(prev.Steps))
|
||||
assert.Equal(t, 1, prev.ChangeSummary[apitype.OpSame])
|
||||
steps := countSteps(previewEvents)
|
||||
assert.Equal(t, 1, steps)
|
||||
|
||||
// -- pulumi refresh --
|
||||
|
||||
|
@ -1132,6 +1166,123 @@ func TestNestedConfig(t *testing.T) {
|
|||
assert.JSONEq(t, "[\"one\",\"two\",\"three\"]", list.Value)
|
||||
}
|
||||
|
||||
func TestStructuredOutput(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
sName := fmt.Sprintf("int_test%d", rangeIn(10000000, 99999999))
|
||||
stackName := FullyQualifiedStackName(pulumiOrg, pName, sName)
|
||||
cfg := ConfigMap{
|
||||
"bar": ConfigValue{
|
||||
Value: "abc",
|
||||
},
|
||||
"buzz": ConfigValue{
|
||||
Value: "secret",
|
||||
Secret: true,
|
||||
},
|
||||
}
|
||||
|
||||
// initialize
|
||||
pDir := filepath.Join(".", "test", "testproj")
|
||||
s, err := UpsertStackLocalSource(ctx, stackName, pDir)
|
||||
if err != nil {
|
||||
t.Errorf("failed to initialize stack, err: %v", err)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
defer func() {
|
||||
// -- pulumi stack rm --
|
||||
err = s.Workspace().RemoveStack(ctx, s.Name())
|
||||
assert.Nil(t, err, "failed to remove stack. Resources have leaked.")
|
||||
}()
|
||||
|
||||
err = s.SetAllConfig(ctx, cfg)
|
||||
if err != nil {
|
||||
t.Errorf("failed to set config, err: %v", err)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
// Set environment variables scoped to the workspace.
|
||||
envvars := map[string]string{
|
||||
"foo": "bar",
|
||||
"barfoo": "foobar",
|
||||
}
|
||||
err = s.Workspace().SetEnvVars(envvars)
|
||||
assert.Nil(t, err, "failed to set environment values")
|
||||
envvars = s.Workspace().GetEnvVars()
|
||||
assert.NotNil(t, envvars, "failed to get environment values after setting many")
|
||||
|
||||
s.Workspace().SetEnvVar("bar", "buzz")
|
||||
envvars = s.Workspace().GetEnvVars()
|
||||
assert.NotNil(t, envvars, "failed to get environment value after setting")
|
||||
|
||||
s.Workspace().UnsetEnvVar("bar")
|
||||
envvars = s.Workspace().GetEnvVars()
|
||||
assert.NotNil(t, envvars, "failed to get environment values after unsetting.")
|
||||
|
||||
// -- pulumi up --
|
||||
var upEvents []events.EngineEvent
|
||||
upCh := make(chan events.EngineEvent)
|
||||
go collectEvents(upCh, &upEvents)
|
||||
res, err := s.Up(ctx, optup.EventStreams(upCh))
|
||||
if err != nil {
|
||||
t.Errorf("up failed, err: %v", err)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
assert.Equal(t, 3, len(res.Outputs), "expected two plain outputs")
|
||||
assert.Equal(t, "foo", res.Outputs["exp_static"].Value)
|
||||
assert.False(t, res.Outputs["exp_static"].Secret)
|
||||
assert.Equal(t, "abc", res.Outputs["exp_cfg"].Value)
|
||||
assert.False(t, res.Outputs["exp_cfg"].Secret)
|
||||
assert.Equal(t, "secret", res.Outputs["exp_secret"].Value)
|
||||
assert.True(t, res.Outputs["exp_secret"].Secret)
|
||||
assert.Equal(t, "update", res.Summary.Kind)
|
||||
assert.Equal(t, "succeeded", res.Summary.Result)
|
||||
assert.True(t, containsSummary(upEvents))
|
||||
|
||||
// -- pulumi preview --
|
||||
var previewEvents []events.EngineEvent
|
||||
prevCh := make(chan events.EngineEvent)
|
||||
go collectEvents(prevCh, &previewEvents)
|
||||
prev, err := s.Preview(ctx, optpreview.EventStreams(prevCh))
|
||||
if err != nil {
|
||||
t.Errorf("preview failed, err: %v", err)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
assert.Equal(t, 1, prev.ChangeSummary[apitype.OpSame])
|
||||
steps := countSteps(previewEvents)
|
||||
assert.Equal(t, 1, steps)
|
||||
assert.True(t, containsSummary(previewEvents))
|
||||
|
||||
// -- pulumi refresh --
|
||||
var refreshEvents []events.EngineEvent
|
||||
refCh := make(chan events.EngineEvent)
|
||||
go collectEvents(refCh, &refreshEvents)
|
||||
ref, err := s.Refresh(ctx, optrefresh.EventStreams(refCh))
|
||||
if err != nil {
|
||||
t.Errorf("refresh failed, err: %v", err)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
assert.Equal(t, "refresh", ref.Summary.Kind)
|
||||
assert.Equal(t, "succeeded", ref.Summary.Result)
|
||||
assert.True(t, containsSummary(refreshEvents))
|
||||
|
||||
// -- pulumi destroy --
|
||||
var destroyEvents []events.EngineEvent
|
||||
desCh := make(chan events.EngineEvent)
|
||||
go collectEvents(desCh, &destroyEvents)
|
||||
dRes, err := s.Destroy(ctx, optdestroy.EventStreams(desCh))
|
||||
if err != nil {
|
||||
t.Errorf("destroy failed, err: %v", err)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
assert.Equal(t, "destroy", dRes.Summary.Kind)
|
||||
assert.Equal(t, "succeeded", dRes.Summary.Result)
|
||||
assert.True(t, containsSummary(destroyEvents))
|
||||
}
|
||||
|
||||
func BenchmarkBulkSetConfigMixed(b *testing.B) {
|
||||
ctx := context.Background()
|
||||
stackName := FullyQualifiedStackName(pulumiOrg, "set_config_mixed", "dev")
|
||||
|
@ -1340,3 +1491,33 @@ func getTestOrg() string {
|
|||
}
|
||||
return testOrg
|
||||
}
|
||||
|
||||
func countSteps(log []events.EngineEvent) int {
|
||||
steps := 0
|
||||
for _, e := range log {
|
||||
if e.ResourcePreEvent != nil {
|
||||
steps++
|
||||
}
|
||||
}
|
||||
return steps
|
||||
}
|
||||
|
||||
func containsSummary(log []events.EngineEvent) bool {
|
||||
hasSummary := false
|
||||
for _, e := range log {
|
||||
if e.SummaryEvent != nil {
|
||||
hasSummary = true
|
||||
}
|
||||
}
|
||||
return hasSummary
|
||||
}
|
||||
|
||||
func collectEvents(eventChannel <-chan events.EngineEvent, events *[]events.EngineEvent) {
|
||||
for {
|
||||
event, ok := <-eventChannel
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
*events = append(*events, event)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,8 +17,10 @@
|
|||
package optdestroy
|
||||
|
||||
import (
|
||||
"github.com/pulumi/pulumi/sdk/v2/go/x/auto/debug"
|
||||
"io"
|
||||
|
||||
"github.com/pulumi/pulumi/sdk/v2/go/x/auto/debug"
|
||||
"github.com/pulumi/pulumi/sdk/v2/go/x/auto/events"
|
||||
)
|
||||
|
||||
// Parallel is the number of resource operations to run in parallel at once during the destroy
|
||||
|
@ -57,6 +59,13 @@ func ProgressStreams(writers ...io.Writer) Option {
|
|||
})
|
||||
}
|
||||
|
||||
// EventStreams allows specifying one or more channels to receive the Pulumi event stream
|
||||
func EventStreams(channels ...chan<- events.EngineEvent) Option {
|
||||
return optionFunc(func(opts *Options) {
|
||||
opts.EventStreams = channels
|
||||
})
|
||||
}
|
||||
|
||||
func DebugLogging(debugOpts debug.LoggingOptions) Option {
|
||||
return optionFunc(func(opts *Options) {
|
||||
opts.DebugLogOpts = debugOpts
|
||||
|
@ -83,6 +92,8 @@ type Options struct {
|
|||
TargetDependents bool
|
||||
// ProgressStreams allows specifying one or more io.Writers to redirect incremental destroy output
|
||||
ProgressStreams []io.Writer
|
||||
// EventStreams allows specifying one or more channels to receive the Pulumi event stream
|
||||
EventStreams []chan<- events.EngineEvent
|
||||
// DebugLogOpts specifies additional settings for debug logging
|
||||
DebugLogOpts debug.LoggingOptions
|
||||
}
|
||||
|
|
|
@ -17,7 +17,10 @@
|
|||
package optpreview
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/pulumi/pulumi/sdk/v2/go/x/auto/debug"
|
||||
"github.com/pulumi/pulumi/sdk/v2/go/x/auto/events"
|
||||
)
|
||||
|
||||
// Parallel is the number of resource operations to run in parallel at once during the update
|
||||
|
@ -76,6 +79,20 @@ func DebugLogging(debugOpts debug.LoggingOptions) Option {
|
|||
})
|
||||
}
|
||||
|
||||
// ProgressStreams allows specifying one or more io.Writers to redirect incremental preview output
|
||||
func ProgressStreams(writers ...io.Writer) Option {
|
||||
return optionFunc(func(opts *Options) {
|
||||
opts.ProgressStreams = writers
|
||||
})
|
||||
}
|
||||
|
||||
// EventStreams allows specifying one or more channels to receive the Pulumi event stream
|
||||
func EventStreams(channels ...chan<- events.EngineEvent) Option {
|
||||
return optionFunc(func(opts *Options) {
|
||||
opts.EventStreams = channels
|
||||
})
|
||||
}
|
||||
|
||||
// Option is a parameter to be applied to a Stack.Preview() operation
|
||||
type Option interface {
|
||||
ApplyOption(*Options)
|
||||
|
@ -102,6 +119,10 @@ type Options struct {
|
|||
TargetDependents bool
|
||||
// DebugLogOpts specifies additional settings for debug logging
|
||||
DebugLogOpts debug.LoggingOptions
|
||||
// ProgressStreams allows specifying one or more io.Writers to redirect incremental preview output
|
||||
ProgressStreams []io.Writer
|
||||
// EventStreams allows specifying one or more channels to receive the Pulumi event stream
|
||||
EventStreams []chan<- events.EngineEvent
|
||||
}
|
||||
|
||||
type optionFunc func(*Options)
|
||||
|
|
|
@ -17,8 +17,10 @@
|
|||
package optrefresh
|
||||
|
||||
import (
|
||||
"github.com/pulumi/pulumi/sdk/v2/go/x/auto/debug"
|
||||
"io"
|
||||
|
||||
"github.com/pulumi/pulumi/sdk/v2/go/x/auto/debug"
|
||||
"github.com/pulumi/pulumi/sdk/v2/go/x/auto/events"
|
||||
)
|
||||
|
||||
// Parallel is the number of resource operations to run in parallel at once during the refresh
|
||||
|
@ -57,6 +59,13 @@ func ProgressStreams(writers ...io.Writer) Option {
|
|||
})
|
||||
}
|
||||
|
||||
// EventStreams allows specifying one or more channels to receive the Pulumi event stream
|
||||
func EventStreams(channels ...chan<- events.EngineEvent) Option {
|
||||
return optionFunc(func(opts *Options) {
|
||||
opts.EventStreams = channels
|
||||
})
|
||||
}
|
||||
|
||||
func DebugLogging(debugOpts debug.LoggingOptions) Option {
|
||||
return optionFunc(func(opts *Options) {
|
||||
opts.DebugLogOpts = debugOpts
|
||||
|
@ -83,6 +92,8 @@ type Options struct {
|
|||
Target []string
|
||||
// ProgressStreams allows specifying one or more io.Writers to redirect incremental refresh output
|
||||
ProgressStreams []io.Writer
|
||||
// EventStreams allows specifying one or more channels to receive the Pulumi event stream
|
||||
EventStreams []chan<- events.EngineEvent
|
||||
// DebugLogOpts specifies additional settings for debug logging
|
||||
DebugLogOpts debug.LoggingOptions
|
||||
}
|
||||
|
|
|
@ -17,8 +17,10 @@
|
|||
package optup
|
||||
|
||||
import (
|
||||
"github.com/pulumi/pulumi/sdk/v2/go/x/auto/debug"
|
||||
"io"
|
||||
|
||||
"github.com/pulumi/pulumi/sdk/v2/go/x/auto/debug"
|
||||
"github.com/pulumi/pulumi/sdk/v2/go/x/auto/events"
|
||||
)
|
||||
|
||||
// Parallel is the number of resource operations to run in parallel at once during the update
|
||||
|
@ -84,6 +86,13 @@ func DebugLogging(debugOpts debug.LoggingOptions) Option {
|
|||
})
|
||||
}
|
||||
|
||||
// EventStreams allows specifying one or more channels to receive the Pulumi event stream
|
||||
func EventStreams(channels ...chan<- events.EngineEvent) Option {
|
||||
return optionFunc(func(opts *Options) {
|
||||
opts.EventStreams = channels
|
||||
})
|
||||
}
|
||||
|
||||
// Option is a parameter to be applied to a Stack.Up() operation
|
||||
type Option interface {
|
||||
ApplyOption(*Options)
|
||||
|
@ -108,10 +117,12 @@ type Options struct {
|
|||
Target []string
|
||||
// Allows updating of dependent targets discovered but not specified in the Target list
|
||||
TargetDependents bool
|
||||
// ProgressStreams allows specifying one or more io.Writers to redirect incremental update output
|
||||
ProgressStreams []io.Writer
|
||||
// DebugLogOpts specifies additional settings for debug logging
|
||||
DebugLogOpts debug.LoggingOptions
|
||||
// ProgressStreams allows specifying one or more io.Writers to redirect incremental update output
|
||||
ProgressStreams []io.Writer
|
||||
// EventStreams allows specifying one or more channels to receive the Pulumi event stream
|
||||
EventStreams []chan<- events.EngineEvent
|
||||
}
|
||||
|
||||
type optionFunc func(*Options)
|
||||
|
|
|
@ -92,14 +92,16 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/pulumi/pulumi/sdk/v2/go/x/auto/debug"
|
||||
|
||||
pbempty "github.com/golang/protobuf/ptypes/empty"
|
||||
"github.com/nxadm/tail"
|
||||
"github.com/pkg/errors"
|
||||
"google.golang.org/grpc"
|
||||
|
||||
|
@ -109,6 +111,8 @@ import (
|
|||
"github.com/pulumi/pulumi/sdk/v2/go/common/util/contract"
|
||||
"github.com/pulumi/pulumi/sdk/v2/go/common/util/rpcutil"
|
||||
"github.com/pulumi/pulumi/sdk/v2/go/pulumi"
|
||||
"github.com/pulumi/pulumi/sdk/v2/go/x/auto/debug"
|
||||
"github.com/pulumi/pulumi/sdk/v2/go/x/auto/events"
|
||||
"github.com/pulumi/pulumi/sdk/v2/go/x/auto/optdestroy"
|
||||
"github.com/pulumi/pulumi/sdk/v2/go/x/auto/optpreview"
|
||||
"github.com/pulumi/pulumi/sdk/v2/go/x/auto/optrefresh"
|
||||
|
@ -242,7 +246,7 @@ func (s *Stack) Preview(ctx context.Context, opts ...optpreview.Option) (Preview
|
|||
sharedArgs = append(sharedArgs, fmt.Sprintf("--parallel=%d", preOpts.Parallel))
|
||||
}
|
||||
|
||||
kind, args := constant.ExecKindAutoLocal, []string{"preview", "--json"}
|
||||
kind, args := constant.ExecKindAutoLocal, []string{"preview"}
|
||||
if program := s.Workspace().Program(); program != nil {
|
||||
server, err := startLanguageRuntimeServer(program)
|
||||
if err != nil {
|
||||
|
@ -255,15 +259,46 @@ func (s *Stack) Preview(ctx context.Context, opts ...optpreview.Option) (Preview
|
|||
|
||||
args = append(args, fmt.Sprintf("--exec-kind=%s", kind))
|
||||
args = append(args, sharedArgs...)
|
||||
stdout, stderr, code, err := s.runPulumiCmdSync(ctx, nil /* additionalOutput */, args...)
|
||||
|
||||
var summaryEvents []apitype.SummaryEvent
|
||||
eventChannel := make(chan events.EngineEvent)
|
||||
go func(ch chan events.EngineEvent, events *[]apitype.SummaryEvent) {
|
||||
for {
|
||||
event, ok := <-eventChannel
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if event.SummaryEvent != nil {
|
||||
summaryEvents = append(summaryEvents, *event.SummaryEvent)
|
||||
}
|
||||
}
|
||||
}(eventChannel, &summaryEvents)
|
||||
|
||||
eventChannels := []chan<- events.EngineEvent{eventChannel}
|
||||
eventChannels = append(eventChannels, preOpts.EventStreams...)
|
||||
|
||||
t, err := tailLogs("preview", eventChannels)
|
||||
if err != nil {
|
||||
return res, errors.Wrap(err, "failed to tail logs")
|
||||
}
|
||||
defer cleanup(t, eventChannels)
|
||||
args = append(args, "--event-log", t.Filename)
|
||||
|
||||
stdout, stderr, code, err := s.runPulumiCmdSync(ctx, preOpts.ProgressStreams /* additionalOutput */, args...)
|
||||
if err != nil {
|
||||
return res, newAutoError(errors.Wrap(err, "failed to run preview"), stdout, stderr, code)
|
||||
}
|
||||
|
||||
err = json.Unmarshal([]byte(stdout), &res)
|
||||
if err != nil {
|
||||
return res, newAutoError(errors.Wrap(err, "unable to unmarshal preview result"), stdout, stderr, code)
|
||||
if len(summaryEvents) == 0 {
|
||||
return res, newAutoError(errors.New("failed to get preview summary"), stdout, stderr, code)
|
||||
}
|
||||
if len(summaryEvents) > 1 {
|
||||
return res, newAutoError(errors.New("got multiple preview summaries"), stdout, stderr, code)
|
||||
}
|
||||
|
||||
res.StdOut = stdout
|
||||
res.StdErr = stderr
|
||||
res.ChangeSummary = summaryEvents[0].ResourceChanges
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
@ -317,8 +352,18 @@ func (s *Stack) Up(ctx context.Context, opts ...optup.Option) (UpResult, error)
|
|||
|
||||
kind, args = constant.ExecKindAutoInline, append(args, "--client="+server.address)
|
||||
}
|
||||
|
||||
args = append(args, fmt.Sprintf("--exec-kind=%s", kind))
|
||||
|
||||
if len(upOpts.EventStreams) > 0 {
|
||||
eventChannels := upOpts.EventStreams
|
||||
t, err := tailLogs("up", eventChannels)
|
||||
if err != nil {
|
||||
return res, errors.Wrap(err, "failed to tail logs")
|
||||
}
|
||||
defer cleanup(t, eventChannels)
|
||||
args = append(args, "--event-log", t.Filename)
|
||||
}
|
||||
|
||||
args = append(args, sharedArgs...)
|
||||
stdout, stderr, code, err := s.runPulumiCmdSync(ctx, upOpts.ProgressStreams, args...)
|
||||
if err != nil {
|
||||
|
@ -385,6 +430,16 @@ func (s *Stack) Refresh(ctx context.Context, opts ...optrefresh.Option) (Refresh
|
|||
}
|
||||
args = append(args, fmt.Sprintf("--exec-kind=%s", execKind))
|
||||
|
||||
if len(refreshOpts.EventStreams) > 0 {
|
||||
eventChannels := refreshOpts.EventStreams
|
||||
t, err := tailLogs("refresh", eventChannels)
|
||||
if err != nil {
|
||||
return res, errors.Wrap(err, "failed to tail logs")
|
||||
}
|
||||
defer cleanup(t, eventChannels)
|
||||
args = append(args, "--event-log", t.Filename)
|
||||
}
|
||||
|
||||
stdout, stderr, code, err := s.runPulumiCmdSync(ctx, refreshOpts.ProgressStreams, args...)
|
||||
if err != nil {
|
||||
return res, newAutoError(errors.Wrap(err, "failed to refresh stack"), stdout, stderr, code)
|
||||
|
@ -445,6 +500,16 @@ func (s *Stack) Destroy(ctx context.Context, opts ...optdestroy.Option) (Destroy
|
|||
}
|
||||
args = append(args, fmt.Sprintf("--exec-kind=%s", execKind))
|
||||
|
||||
if len(destroyOpts.EventStreams) > 0 {
|
||||
eventChannels := destroyOpts.EventStreams
|
||||
t, err := tailLogs("destroy", eventChannels)
|
||||
if err != nil {
|
||||
return res, errors.Wrap(err, "failed to tail logs")
|
||||
}
|
||||
defer cleanup(t, eventChannels)
|
||||
args = append(args, "--event-log", t.Filename)
|
||||
}
|
||||
|
||||
stdout, stderr, code, err := s.runPulumiCmdSync(ctx, destroyOpts.ProgressStreams, args...)
|
||||
if err != nil {
|
||||
return res, newAutoError(errors.Wrap(err, "failed to destroy stack"), stdout, stderr, code)
|
||||
|
@ -653,7 +718,6 @@ type OutputValue struct {
|
|||
|
||||
// UpResult contains information about a Stack.Up operation,
|
||||
// including Outputs, and a summary of the deployed changes.
|
||||
// TODO: remote StdOut in favor of structured info https://github.com/pulumi/pulumi/issues/5218
|
||||
type UpResult struct {
|
||||
StdOut string
|
||||
StdErr string
|
||||
|
@ -722,12 +786,12 @@ type PropertyDiff struct {
|
|||
|
||||
// PreviewResult is the output of Stack.Preview() describing the expected set of changes from the next Stack.Up()
|
||||
type PreviewResult struct {
|
||||
Steps []PreviewStep `json:"steps"`
|
||||
ChangeSummary map[string]int `json:"changeSummary"`
|
||||
StdOut string
|
||||
StdErr string
|
||||
ChangeSummary map[apitype.OpType]int
|
||||
}
|
||||
|
||||
// RefreshResult is the output of a successful Stack.Refresh operation
|
||||
// TODO: replace StdOut with structured output https://github.com/pulumi/pulumi/issues/5220
|
||||
type RefreshResult struct {
|
||||
StdOut string
|
||||
StdErr string
|
||||
|
@ -735,7 +799,6 @@ type RefreshResult struct {
|
|||
}
|
||||
|
||||
// DestroyResult is the output of a successful Stack.Destroy operation
|
||||
// TODO: replace StdOut with structured output https://github.com/pulumi/pulumi/issues/5219
|
||||
type DestroyResult struct {
|
||||
StdOut string
|
||||
StdErr string
|
||||
|
@ -751,6 +814,8 @@ func (s *Stack) runPulumiCmdSync(
|
|||
args ...string,
|
||||
) (string, string, int, error) {
|
||||
var env []string
|
||||
debugEnv := fmt.Sprintf("%s=%s", "PULUMI_DEBUG_COMMANDS", "true")
|
||||
env = append(env, debugEnv)
|
||||
if s.Workspace().PulumiHome() != "" {
|
||||
homeEnv := fmt.Sprintf("%s=%s", pulumiHomeEnv, s.Workspace().PulumiHome())
|
||||
env = append(env, homeEnv)
|
||||
|
@ -924,3 +989,27 @@ func (s *languageRuntimeServer) GetPluginInfo(ctx context.Context, req *pbempty.
|
|||
Version: "1.0.0",
|
||||
}, nil
|
||||
}
|
||||
|
||||
func tailLogs(command string, receivers []chan<- events.EngineEvent) (*tail.Tail, error) {
|
||||
logDir, err := ioutil.TempDir("", fmt.Sprintf("automation-logs-%s-", command))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to create logdir")
|
||||
}
|
||||
logFile := filepath.Join(logDir, "eventlog.txt")
|
||||
|
||||
t, err := watchFile(logFile, receivers)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to watch file")
|
||||
}
|
||||
|
||||
return t, nil
|
||||
}
|
||||
|
||||
func cleanup(t *tail.Tail, channels []chan<- events.EngineEvent) {
|
||||
logDir := filepath.Dir(t.Filename)
|
||||
t.Cleanup()
|
||||
os.RemoveAll(logDir)
|
||||
for _, ch := range channels {
|
||||
close(ch)
|
||||
}
|
||||
}
|
||||
|
|
54
sdk/go/x/auto/watcher.go
Normal file
54
sdk/go/x/auto/watcher.go
Normal file
|
@ -0,0 +1,54 @@
|
|||
// Copyright 2016-2021, Pulumi Corporation.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
package auto
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/nxadm/tail"
|
||||
|
||||
"github.com/pulumi/pulumi/sdk/v2/go/common/apitype"
|
||||
"github.com/pulumi/pulumi/sdk/v2/go/x/auto/events"
|
||||
)
|
||||
|
||||
func watchFile(path string, receivers []chan<- events.EngineEvent) (*tail.Tail, error) {
|
||||
t, err := tail.TailFile(path, tail.Config{
|
||||
Follow: true,
|
||||
Logger: tail.DiscardingLogger,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
go func(tailedLog *tail.Tail) {
|
||||
for line := range tailedLog.Lines {
|
||||
if line.Err != nil {
|
||||
for _, r := range receivers {
|
||||
r <- events.EngineEvent{Error: line.Err}
|
||||
}
|
||||
continue
|
||||
}
|
||||
var e apitype.EngineEvent
|
||||
err = json.Unmarshal([]byte(line.Text), &e)
|
||||
if err != nil {
|
||||
for _, r := range receivers {
|
||||
r <- events.EngineEvent{Error: err}
|
||||
}
|
||||
continue
|
||||
}
|
||||
for _, r := range receivers {
|
||||
r <- events.EngineEvent{EngineEvent: e}
|
||||
}
|
||||
}
|
||||
}(t)
|
||||
return t, nil
|
||||
}
|
|
@ -540,6 +540,7 @@ github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d h1:AREM5mwr4u1
|
|||
github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw=
|
||||
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
|
||||
github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
|
||||
|
@ -1070,6 +1071,7 @@ gopkg.in/src-d/go-git-fixtures.v3 v3.5.0 h1:ivZFOIltbce2Mo8IjzUHAFoq/IylO9WHhNOA
|
|||
gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g=
|
||||
gopkg.in/src-d/go-git.v4 v4.13.1 h1:SRtFyV8Kxc0UP7aCHcijOMQGPxHSmMOPrzulQWolkYE=
|
||||
gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
|
|
Loading…
Reference in a new issue