9a5f4044fa
* Serialize SourceEvents coming from the refresh source The engine requires that a source event coming from a source be "ready to execute" at the moment that it is sent to the engine. Since the refresh source sent all goal states eagerly through its source iterator, the engine assumed that it was legal to execute them all in parallel and did so. This is a problem for the snapshot, since the snapshot expects to be in an order that is a legal topological ordering of the dependency DAG. This PR fixes the issue by sending refresh source events one-at-a-time through the refresh source iterator, only unblocking to send the next step as soon as the previous step completes. * Fix deadlock in refresh test * Fix an issue where the engine "completed" steps too early By signalling that a step is done before committing the step's results to the snapshot, the engine was left with a race where dependent resources could find themselves completely executed and committed before a resource that they depend on has been committed. Fixes pulumi/pulumi#1726 * Fix an issue with Replace steps at the end of a plan If the last step that was executed successfully was a Replace, we could end up in a situation where we unintentionally left the snapshot invalid. * Add a test * CR: pass context.Context as first parameter to Iterate * CR: null->nil
53 lines
1.8 KiB
Go
53 lines
1.8 KiB
Go
// Copyright 2016-2018, 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 deploy
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/pulumi/pulumi/pkg/tokens"
|
|
"github.com/pulumi/pulumi/pkg/util/contract"
|
|
)
|
|
|
|
// NullSource is a singleton source that never returns any resources. This may be used in scenarios where the "new"
|
|
// version of the world is meant to be empty, either for testing purposes, or removal of an existing stack.
|
|
var NullSource Source = &nullSource{}
|
|
|
|
// A nullSource never returns any resources.
|
|
type nullSource struct {
|
|
}
|
|
|
|
func (src *nullSource) Close() error { return nil }
|
|
func (src *nullSource) Project() tokens.PackageName { return "" }
|
|
func (src *nullSource) Info() interface{} { return nil }
|
|
func (src *nullSource) IsRefresh() bool { return false }
|
|
|
|
func (src *nullSource) Iterate(ctx context.Context, opts Options, providers ProviderSource) (SourceIterator, error) {
|
|
contract.Ignore(ctx)
|
|
return &nullSourceIterator{}, nil
|
|
}
|
|
|
|
// nullSourceIterator always returns nil, nil in response to Next, indicating that it is done.
|
|
type nullSourceIterator struct {
|
|
}
|
|
|
|
func (iter *nullSourceIterator) Close() error {
|
|
return nil // nothing to do.
|
|
}
|
|
|
|
func (iter *nullSourceIterator) Next() (SourceEvent, error) {
|
|
return nil, nil // means "done"
|
|
}
|