Add tokens.StackName (#14487)
<!---
Thanks so much for your contribution! If this is your first time
contributing, please ensure that you have read the
[CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md)
documentation.
-->
# Description
<!--- Please include a summary of the change and which issue is fixed.
Please also include relevant motivation and context. -->
This adds a new type `tokens.StackName` which is a relatively strongly
typed container for a stack name. The only weakly typed aspect of it is
Go will always allow the "zero" value to be created for a struct, which
for a stack name is the empty string which is invalid. To prevent
introducing unexpected empty strings when working with stack names the
`String()` method will panic for zero initialized stack names.
Apart from the zero value, all other instances of `StackName` are via
`ParseStackName` which returns a descriptive error if the string is not
valid.
This PR only updates "pkg/" to use this type. There are a number of
places in "sdk/" which could do with this type as well, but there's no
harm in doing a staggered roll out, and some parts of "sdk/" are user
facing and will probably have to stay on the current `tokens.Name` and
`tokens.QName` types.
There are two places in the system where we panic on invalid stack
names, both in the http backend. This _should_ be fine as we've had long
standing validation that stacks created in the service are valid stack
names.
Just in case people have managed to introduce invalid stack names, there
is the `PULUMI_DISABLE_VALIDATION` environment variable which will turn
off the validation _and_ panicing for stack names. Users can use that to
temporarily disable the validation and continue working, but it should
only be seen as a temporary measure. If they have invalid names they
should rename them, or if they think they should be valid raise an issue
with us to change the validation code.
## Checklist
- [x] I have run `make tidy` to update any new dependencies
- [x] I have run `make lint` to verify my code passes the lint check
- [ ] I have formatted my code using `gofumpt`
<!--- Please provide details if the checkbox below is to be left
unchecked. -->
- [x] I have added tests that prove my fix is effective or that my
feature works
<!---
User-facing changes require a CHANGELOG entry.
-->
- [ ] I have run `make changelog` and committed the
`changelog/pending/<file>` documenting my change
<!--
If the change(s) in this PR is a modification of an existing call to the
Pulumi Cloud,
then the service should honor older versions of the CLI where this
change would not exist.
You must then bump the API version in
/pkg/backend/httpstate/client/api.go, as well as add
it to the service.
-->
- [ ] Yes, there are changes in this PR that warrants bumping the Pulumi
Cloud API version
<!-- @Pulumi employees: If yes, you must submit corresponding changes in
the service repo. -->
2023-11-15 07:44:54 +00:00
|
|
|
// Copyright 2016-2023, Pulumi Corporation.
|
Implement query primitives in the engine
`pulumi query` is designed, essentially, as a souped-up `exec`. We
execute a query program, and add a few convenience constructs (e.g., the
default providers that give you access to things like `getStack`).
Early in the design process, we decided to not re-use the `up`/update
path, both to minimize risk to update operations, and to simplify the
implementation.
This commit will add this "parallel query universe" into the engine
package. In particular, this includes:
* `QuerySource`, which executes the language provider running the query
program, and providing it with some simple constructs, such as the
default provider, which provides access to `getStack`. This is much
like a very simplified `EvalSource`, though notably without any of the
planning/step execution machinery.
* `queryResmon`, which disallows all resource operations, except the
`Invoke` that retrieves the resource outputs of some stack's last
snapshot. This is much like a simplified `resmon`, but without any of
the provider resolution, and without and support for resource
operations generally.
* Various static functions that pull together miscellaneous things
needed to execute a query program. Notably, this includes gathering
language plugins.
2019-04-30 18:07:56 +00:00
|
|
|
//
|
|
|
|
// 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"
|
2023-12-12 12:19:42 +00:00
|
|
|
"errors"
|
Implement query primitives in the engine
`pulumi query` is designed, essentially, as a souped-up `exec`. We
execute a query program, and add a few convenience constructs (e.g., the
default providers that give you access to things like `getStack`).
Early in the design process, we decided to not re-use the `up`/update
path, both to minimize risk to update operations, and to simplify the
implementation.
This commit will add this "parallel query universe" into the engine
package. In particular, this includes:
* `QuerySource`, which executes the language provider running the query
program, and providing it with some simple constructs, such as the
default provider, which provides access to `getStack`. This is much
like a very simplified `EvalSource`, though notably without any of the
planning/step execution machinery.
* `queryResmon`, which disallows all resource operations, except the
`Invoke` that retrieves the resource outputs of some stack's last
snapshot. This is much like a simplified `resmon`, but without any of
the provider resolution, and without and support for resource
operations generally.
* Various static functions that pull together miscellaneous things
needed to execute a query program. Notably, this includes gathering
language plugins.
2019-04-30 18:07:56 +00:00
|
|
|
"fmt"
|
|
|
|
"math"
|
|
|
|
|
2019-09-16 21:16:43 +00:00
|
|
|
opentracing "github.com/opentracing/opentracing-go"
|
2024-01-17 09:35:20 +00:00
|
|
|
"google.golang.org/protobuf/types/known/emptypb"
|
2021-11-13 02:37:17 +00:00
|
|
|
|
Implement query primitives in the engine
`pulumi query` is designed, essentially, as a souped-up `exec`. We
execute a query program, and add a few convenience constructs (e.g., the
default providers that give you access to things like `getStack`).
Early in the design process, we decided to not re-use the `up`/update
path, both to minimize risk to update operations, and to simplify the
implementation.
This commit will add this "parallel query universe" into the engine
package. In particular, this includes:
* `QuerySource`, which executes the language provider running the query
program, and providing it with some simple constructs, such as the
default provider, which provides access to `getStack`. This is much
like a very simplified `EvalSource`, though notably without any of the
planning/step execution machinery.
* `queryResmon`, which disallows all resource operations, except the
`Invoke` that retrieves the resource outputs of some stack's last
snapshot. This is much like a simplified `resmon`, but without any of
the provider resolution, and without and support for resource
operations generally.
* Various static functions that pull together miscellaneous things
needed to execute a query program. Notably, this includes gathering
language plugins.
2019-04-30 18:07:56 +00:00
|
|
|
"google.golang.org/grpc"
|
|
|
|
|
2021-03-17 13:20:05 +00:00
|
|
|
"github.com/pulumi/pulumi/pkg/v3/resource/deploy/providers"
|
|
|
|
"github.com/pulumi/pulumi/sdk/v3/go/common/resource"
|
|
|
|
"github.com/pulumi/pulumi/sdk/v3/go/common/resource/config"
|
|
|
|
"github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin"
|
2023-06-28 16:02:04 +00:00
|
|
|
"github.com/pulumi/pulumi/sdk/v3/go/common/slice"
|
2021-03-17 13:20:05 +00:00
|
|
|
"github.com/pulumi/pulumi/sdk/v3/go/common/tokens"
|
|
|
|
"github.com/pulumi/pulumi/sdk/v3/go/common/util/contract"
|
|
|
|
"github.com/pulumi/pulumi/sdk/v3/go/common/util/logging"
|
|
|
|
"github.com/pulumi/pulumi/sdk/v3/go/common/util/result"
|
|
|
|
"github.com/pulumi/pulumi/sdk/v3/go/common/util/rpcutil"
|
2021-12-17 22:52:01 +00:00
|
|
|
"github.com/pulumi/pulumi/sdk/v3/go/common/workspace"
|
2021-03-17 13:20:05 +00:00
|
|
|
pulumirpc "github.com/pulumi/pulumi/sdk/v3/proto/go"
|
Implement query primitives in the engine
`pulumi query` is designed, essentially, as a souped-up `exec`. We
execute a query program, and add a few convenience constructs (e.g., the
default providers that give you access to things like `getStack`).
Early in the design process, we decided to not re-use the `up`/update
path, both to minimize risk to update operations, and to simplify the
implementation.
This commit will add this "parallel query universe" into the engine
package. In particular, this includes:
* `QuerySource`, which executes the language provider running the query
program, and providing it with some simple constructs, such as the
default provider, which provides access to `getStack`. This is much
like a very simplified `EvalSource`, though notably without any of the
planning/step execution machinery.
* `queryResmon`, which disallows all resource operations, except the
`Invoke` that retrieves the resource outputs of some stack's last
snapshot. This is much like a simplified `resmon`, but without any of
the provider resolution, and without and support for resource
operations generally.
* Various static functions that pull together miscellaneous things
needed to execute a query program. Notably, this includes gathering
language plugins.
2019-04-30 18:07:56 +00:00
|
|
|
)
|
|
|
|
|
2021-01-11 18:07:59 +00:00
|
|
|
// QuerySource is used to synchronously wait for a query result.
|
Implement query primitives in the engine
`pulumi query` is designed, essentially, as a souped-up `exec`. We
execute a query program, and add a few convenience constructs (e.g., the
default providers that give you access to things like `getStack`).
Early in the design process, we decided to not re-use the `up`/update
path, both to minimize risk to update operations, and to simplify the
implementation.
This commit will add this "parallel query universe" into the engine
package. In particular, this includes:
* `QuerySource`, which executes the language provider running the query
program, and providing it with some simple constructs, such as the
default provider, which provides access to `getStack`. This is much
like a very simplified `EvalSource`, though notably without any of the
planning/step execution machinery.
* `queryResmon`, which disallows all resource operations, except the
`Invoke` that retrieves the resource outputs of some stack's last
snapshot. This is much like a simplified `resmon`, but without any of
the provider resolution, and without and support for resource
operations generally.
* Various static functions that pull together miscellaneous things
needed to execute a query program. Notably, this includes gathering
language plugins.
2019-04-30 18:07:56 +00:00
|
|
|
type QuerySource interface {
|
2023-09-20 15:43:46 +00:00
|
|
|
Wait() error
|
Implement query primitives in the engine
`pulumi query` is designed, essentially, as a souped-up `exec`. We
execute a query program, and add a few convenience constructs (e.g., the
default providers that give you access to things like `getStack`).
Early in the design process, we decided to not re-use the `up`/update
path, both to minimize risk to update operations, and to simplify the
implementation.
This commit will add this "parallel query universe" into the engine
package. In particular, this includes:
* `QuerySource`, which executes the language provider running the query
program, and providing it with some simple constructs, such as the
default provider, which provides access to `getStack`. This is much
like a very simplified `EvalSource`, though notably without any of the
planning/step execution machinery.
* `queryResmon`, which disallows all resource operations, except the
`Invoke` that retrieves the resource outputs of some stack's last
snapshot. This is much like a simplified `resmon`, but without any of
the provider resolution, and without and support for resource
operations generally.
* Various static functions that pull together miscellaneous things
needed to execute a query program. Notably, this includes gathering
language plugins.
2019-04-30 18:07:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// NewQuerySource creates a `QuerySource` for some target runtime environment specified by
|
|
|
|
// `runinfo`, and supported by language plugins provided in `plugctx`.
|
2019-08-27 17:10:51 +00:00
|
|
|
func NewQuerySource(cancel context.Context, plugctx *plugin.Context, client BackendClient,
|
2022-08-26 14:51:14 +00:00
|
|
|
runinfo *EvalRunInfo, defaultProviderVersions map[tokens.Package]workspace.PluginSpec,
|
2023-03-03 16:36:39 +00:00
|
|
|
provs ProviderSource,
|
|
|
|
) (QuerySource, error) {
|
Implement query primitives in the engine
`pulumi query` is designed, essentially, as a souped-up `exec`. We
execute a query program, and add a few convenience constructs (e.g., the
default providers that give you access to things like `getStack`).
Early in the design process, we decided to not re-use the `up`/update
path, both to minimize risk to update operations, and to simplify the
implementation.
This commit will add this "parallel query universe" into the engine
package. In particular, this includes:
* `QuerySource`, which executes the language provider running the query
program, and providing it with some simple constructs, such as the
default provider, which provides access to `getStack`. This is much
like a very simplified `EvalSource`, though notably without any of the
planning/step execution machinery.
* `queryResmon`, which disallows all resource operations, except the
`Invoke` that retrieves the resource outputs of some stack's last
snapshot. This is much like a simplified `resmon`, but without any of
the provider resolution, and without and support for resource
operations generally.
* Various static functions that pull together miscellaneous things
needed to execute a query program. Notably, this includes gathering
language plugins.
2019-04-30 18:07:56 +00:00
|
|
|
// Create a new builtin provider. This provider implements features such as `getStack`.
|
2023-12-03 08:46:37 +00:00
|
|
|
builtins := newBuiltinProvider(client, nil, plugctx.Diag)
|
Implement query primitives in the engine
`pulumi query` is designed, essentially, as a souped-up `exec`. We
execute a query program, and add a few convenience constructs (e.g., the
default providers that give you access to things like `getStack`).
Early in the design process, we decided to not re-use the `up`/update
path, both to minimize risk to update operations, and to simplify the
implementation.
This commit will add this "parallel query universe" into the engine
package. In particular, this includes:
* `QuerySource`, which executes the language provider running the query
program, and providing it with some simple constructs, such as the
default provider, which provides access to `getStack`. This is much
like a very simplified `EvalSource`, though notably without any of the
planning/step execution machinery.
* `queryResmon`, which disallows all resource operations, except the
`Invoke` that retrieves the resource outputs of some stack's last
snapshot. This is much like a simplified `resmon`, but without any of
the provider resolution, and without and support for resource
operations generally.
* Various static functions that pull together miscellaneous things
needed to execute a query program. Notably, this includes gathering
language plugins.
2019-04-30 18:07:56 +00:00
|
|
|
|
2023-04-12 09:35:20 +00:00
|
|
|
reg := providers.NewRegistry(plugctx.Host, false, builtins)
|
2019-08-27 17:10:51 +00:00
|
|
|
|
|
|
|
// Allows queryResmon to communicate errors loading providers.
|
2023-10-03 07:21:26 +00:00
|
|
|
providerRegErrChan := make(chan error)
|
2019-08-27 17:10:51 +00:00
|
|
|
|
Implement query primitives in the engine
`pulumi query` is designed, essentially, as a souped-up `exec`. We
execute a query program, and add a few convenience constructs (e.g., the
default providers that give you access to things like `getStack`).
Early in the design process, we decided to not re-use the `up`/update
path, both to minimize risk to update operations, and to simplify the
implementation.
This commit will add this "parallel query universe" into the engine
package. In particular, this includes:
* `QuerySource`, which executes the language provider running the query
program, and providing it with some simple constructs, such as the
default provider, which provides access to `getStack`. This is much
like a very simplified `EvalSource`, though notably without any of the
planning/step execution machinery.
* `queryResmon`, which disallows all resource operations, except the
`Invoke` that retrieves the resource outputs of some stack's last
snapshot. This is much like a simplified `resmon`, but without any of
the provider resolution, and without and support for resource
operations generally.
* Various static functions that pull together miscellaneous things
needed to execute a query program. Notably, this includes gathering
language plugins.
2019-04-30 18:07:56 +00:00
|
|
|
// First, fire up a resource monitor that will disallow all resource operations, as well as
|
|
|
|
// service calls for things like resource ouptuts of state snapshots.
|
2019-05-02 21:22:50 +00:00
|
|
|
//
|
|
|
|
// NOTE: Using the queryResourceMonitor here is *VERY* important, as its job is to disallow
|
|
|
|
// resource operations in query mode!
|
2019-08-27 17:10:51 +00:00
|
|
|
mon, err := newQueryResourceMonitor(builtins, defaultProviderVersions, provs, reg, plugctx,
|
2021-06-30 14:48:56 +00:00
|
|
|
providerRegErrChan, opentracing.SpanFromContext(cancel), runinfo)
|
Implement query primitives in the engine
`pulumi query` is designed, essentially, as a souped-up `exec`. We
execute a query program, and add a few convenience constructs (e.g., the
default providers that give you access to things like `getStack`).
Early in the design process, we decided to not re-use the `up`/update
path, both to minimize risk to update operations, and to simplify the
implementation.
This commit will add this "parallel query universe" into the engine
package. In particular, this includes:
* `QuerySource`, which executes the language provider running the query
program, and providing it with some simple constructs, such as the
default provider, which provides access to `getStack`. This is much
like a very simplified `EvalSource`, though notably without any of the
planning/step execution machinery.
* `queryResmon`, which disallows all resource operations, except the
`Invoke` that retrieves the resource outputs of some stack's last
snapshot. This is much like a simplified `resmon`, but without any of
the provider resolution, and without and support for resource
operations generally.
* Various static functions that pull together miscellaneous things
needed to execute a query program. Notably, this includes gathering
language plugins.
2019-04-30 18:07:56 +00:00
|
|
|
if err != nil {
|
2021-11-13 02:37:17 +00:00
|
|
|
return nil, fmt.Errorf("failed to start resource monitor: %w", err)
|
Implement query primitives in the engine
`pulumi query` is designed, essentially, as a souped-up `exec`. We
execute a query program, and add a few convenience constructs (e.g., the
default providers that give you access to things like `getStack`).
Early in the design process, we decided to not re-use the `up`/update
path, both to minimize risk to update operations, and to simplify the
implementation.
This commit will add this "parallel query universe" into the engine
package. In particular, this includes:
* `QuerySource`, which executes the language provider running the query
program, and providing it with some simple constructs, such as the
default provider, which provides access to `getStack`. This is much
like a very simplified `EvalSource`, though notably without any of the
planning/step execution machinery.
* `queryResmon`, which disallows all resource operations, except the
`Invoke` that retrieves the resource outputs of some stack's last
snapshot. This is much like a simplified `resmon`, but without any of
the provider resolution, and without and support for resource
operations generally.
* Various static functions that pull together miscellaneous things
needed to execute a query program. Notably, this includes gathering
language plugins.
2019-04-30 18:07:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Create a new iterator with appropriate channels, and gear up to go!
|
|
|
|
src := &querySource{
|
2019-08-27 17:10:51 +00:00
|
|
|
mon: mon,
|
|
|
|
plugctx: plugctx,
|
|
|
|
runinfo: runinfo,
|
|
|
|
runLangPlugin: runLangPlugin,
|
2023-09-20 15:43:46 +00:00
|
|
|
langPluginFinChan: make(chan error),
|
|
|
|
providerRegErrChan: make(chan error),
|
2019-08-27 17:10:51 +00:00
|
|
|
cancel: cancel,
|
Implement query primitives in the engine
`pulumi query` is designed, essentially, as a souped-up `exec`. We
execute a query program, and add a few convenience constructs (e.g., the
default providers that give you access to things like `getStack`).
Early in the design process, we decided to not re-use the `up`/update
path, both to minimize risk to update operations, and to simplify the
implementation.
This commit will add this "parallel query universe" into the engine
package. In particular, this includes:
* `QuerySource`, which executes the language provider running the query
program, and providing it with some simple constructs, such as the
default provider, which provides access to `getStack`. This is much
like a very simplified `EvalSource`, though notably without any of the
planning/step execution machinery.
* `queryResmon`, which disallows all resource operations, except the
`Invoke` that retrieves the resource outputs of some stack's last
snapshot. This is much like a simplified `resmon`, but without any of
the provider resolution, and without and support for resource
operations generally.
* Various static functions that pull together miscellaneous things
needed to execute a query program. Notably, this includes gathering
language plugins.
2019-04-30 18:07:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Now invoke Run in a goroutine. All subsequent resource creation events will come in over the gRPC channel,
|
|
|
|
// and we will pump them through the channel. If the Run call ultimately fails, we need to propagate the error.
|
|
|
|
src.forkRun()
|
|
|
|
|
|
|
|
// Finally, return the fresh iterator that the caller can use to take things from here.
|
|
|
|
return src, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type querySource struct {
|
2023-09-20 15:43:46 +00:00
|
|
|
mon SourceResourceMonitor // the resource monitor, per iterator.
|
|
|
|
plugctx *plugin.Context // the plugin context.
|
|
|
|
runinfo *EvalRunInfo // the directives to use when running the program.
|
|
|
|
runLangPlugin func(*querySource) error // runs the language plugin.
|
|
|
|
langPluginFinChan chan error // communicates language plugin completion.
|
|
|
|
providerRegErrChan chan error // communicates errors loading providers
|
|
|
|
done bool // set to true when the evaluation is done.
|
|
|
|
res error // result when the channel is finished.
|
2019-08-27 17:10:51 +00:00
|
|
|
cancel context.Context
|
Implement query primitives in the engine
`pulumi query` is designed, essentially, as a souped-up `exec`. We
execute a query program, and add a few convenience constructs (e.g., the
default providers that give you access to things like `getStack`).
Early in the design process, we decided to not re-use the `up`/update
path, both to minimize risk to update operations, and to simplify the
implementation.
This commit will add this "parallel query universe" into the engine
package. In particular, this includes:
* `QuerySource`, which executes the language provider running the query
program, and providing it with some simple constructs, such as the
default provider, which provides access to `getStack`. This is much
like a very simplified `EvalSource`, though notably without any of the
planning/step execution machinery.
* `queryResmon`, which disallows all resource operations, except the
`Invoke` that retrieves the resource outputs of some stack's last
snapshot. This is much like a simplified `resmon`, but without any of
the provider resolution, and without and support for resource
operations generally.
* Various static functions that pull together miscellaneous things
needed to execute a query program. Notably, this includes gathering
language plugins.
2019-04-30 18:07:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (src *querySource) Close() error {
|
|
|
|
// Cancel the monitor and reclaim any associated resources.
|
|
|
|
src.done = true
|
|
|
|
return src.mon.Cancel()
|
|
|
|
}
|
|
|
|
|
2023-09-20 15:43:46 +00:00
|
|
|
func (src *querySource) Wait() error {
|
Implement query primitives in the engine
`pulumi query` is designed, essentially, as a souped-up `exec`. We
execute a query program, and add a few convenience constructs (e.g., the
default providers that give you access to things like `getStack`).
Early in the design process, we decided to not re-use the `up`/update
path, both to minimize risk to update operations, and to simplify the
implementation.
This commit will add this "parallel query universe" into the engine
package. In particular, this includes:
* `QuerySource`, which executes the language provider running the query
program, and providing it with some simple constructs, such as the
default provider, which provides access to `getStack`. This is much
like a very simplified `EvalSource`, though notably without any of the
planning/step execution machinery.
* `queryResmon`, which disallows all resource operations, except the
`Invoke` that retrieves the resource outputs of some stack's last
snapshot. This is much like a simplified `resmon`, but without any of
the provider resolution, and without and support for resource
operations generally.
* Various static functions that pull together miscellaneous things
needed to execute a query program. Notably, this includes gathering
language plugins.
2019-04-30 18:07:56 +00:00
|
|
|
// If we are done, quit.
|
|
|
|
if src.done {
|
2019-05-02 21:22:50 +00:00
|
|
|
return src.res
|
Implement query primitives in the engine
`pulumi query` is designed, essentially, as a souped-up `exec`. We
execute a query program, and add a few convenience constructs (e.g., the
default providers that give you access to things like `getStack`).
Early in the design process, we decided to not re-use the `up`/update
path, both to minimize risk to update operations, and to simplify the
implementation.
This commit will add this "parallel query universe" into the engine
package. In particular, this includes:
* `QuerySource`, which executes the language provider running the query
program, and providing it with some simple constructs, such as the
default provider, which provides access to `getStack`. This is much
like a very simplified `EvalSource`, though notably without any of the
planning/step execution machinery.
* `queryResmon`, which disallows all resource operations, except the
`Invoke` that retrieves the resource outputs of some stack's last
snapshot. This is much like a simplified `resmon`, but without any of
the provider resolution, and without and support for resource
operations generally.
* Various static functions that pull together miscellaneous things
needed to execute a query program. Notably, this includes gathering
language plugins.
2019-04-30 18:07:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
select {
|
2019-08-27 17:10:51 +00:00
|
|
|
case src.res = <-src.langPluginFinChan:
|
2019-05-02 21:22:50 +00:00
|
|
|
// Language plugin has exited. No need to call `Close`.
|
|
|
|
src.done = true
|
|
|
|
return src.res
|
2019-08-27 17:10:51 +00:00
|
|
|
case src.res = <-src.providerRegErrChan:
|
|
|
|
// Provider registration has failed.
|
|
|
|
src.Close()
|
|
|
|
return src.res
|
Implement query primitives in the engine
`pulumi query` is designed, essentially, as a souped-up `exec`. We
execute a query program, and add a few convenience constructs (e.g., the
default providers that give you access to things like `getStack`).
Early in the design process, we decided to not re-use the `up`/update
path, both to minimize risk to update operations, and to simplify the
implementation.
This commit will add this "parallel query universe" into the engine
package. In particular, this includes:
* `QuerySource`, which executes the language provider running the query
program, and providing it with some simple constructs, such as the
default provider, which provides access to `getStack`. This is much
like a very simplified `EvalSource`, though notably without any of the
planning/step execution machinery.
* `queryResmon`, which disallows all resource operations, except the
`Invoke` that retrieves the resource outputs of some stack's last
snapshot. This is much like a simplified `resmon`, but without any of
the provider resolution, and without and support for resource
operations generally.
* Various static functions that pull together miscellaneous things
needed to execute a query program. Notably, this includes gathering
language plugins.
2019-04-30 18:07:56 +00:00
|
|
|
case <-src.cancel.Done():
|
|
|
|
src.Close()
|
2019-05-02 21:22:50 +00:00
|
|
|
return src.res
|
Implement query primitives in the engine
`pulumi query` is designed, essentially, as a souped-up `exec`. We
execute a query program, and add a few convenience constructs (e.g., the
default providers that give you access to things like `getStack`).
Early in the design process, we decided to not re-use the `up`/update
path, both to minimize risk to update operations, and to simplify the
implementation.
This commit will add this "parallel query universe" into the engine
package. In particular, this includes:
* `QuerySource`, which executes the language provider running the query
program, and providing it with some simple constructs, such as the
default provider, which provides access to `getStack`. This is much
like a very simplified `EvalSource`, though notably without any of the
planning/step execution machinery.
* `queryResmon`, which disallows all resource operations, except the
`Invoke` that retrieves the resource outputs of some stack's last
snapshot. This is much like a simplified `resmon`, but without any of
the provider resolution, and without and support for resource
operations generally.
* Various static functions that pull together miscellaneous things
needed to execute a query program. Notably, this includes gathering
language plugins.
2019-04-30 18:07:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// forkRun evaluate the query program in a separate goroutine. Completion or cancellation will cause
|
|
|
|
// `Wait` to stop blocking and return.
|
|
|
|
func (src *querySource) forkRun() {
|
|
|
|
// Fire up the goroutine to make the RPC invocation against the language runtime. As this executes, calls
|
|
|
|
// to queue things up in the resource channel will occur, and we will serve them concurrently.
|
|
|
|
go func() {
|
2019-05-02 21:22:50 +00:00
|
|
|
// Next, launch the language plugin. Communicate the error, if it exists, or nil if the
|
|
|
|
// program exited cleanly.
|
2019-08-27 17:10:51 +00:00
|
|
|
src.langPluginFinChan <- src.runLangPlugin(src)
|
Implement query primitives in the engine
`pulumi query` is designed, essentially, as a souped-up `exec`. We
execute a query program, and add a few convenience constructs (e.g., the
default providers that give you access to things like `getStack`).
Early in the design process, we decided to not re-use the `up`/update
path, both to minimize risk to update operations, and to simplify the
implementation.
This commit will add this "parallel query universe" into the engine
package. In particular, this includes:
* `QuerySource`, which executes the language provider running the query
program, and providing it with some simple constructs, such as the
default provider, which provides access to `getStack`. This is much
like a very simplified `EvalSource`, though notably without any of the
planning/step execution machinery.
* `queryResmon`, which disallows all resource operations, except the
`Invoke` that retrieves the resource outputs of some stack's last
snapshot. This is much like a simplified `resmon`, but without any of
the provider resolution, and without and support for resource
operations generally.
* Various static functions that pull together miscellaneous things
needed to execute a query program. Notably, this includes gathering
language plugins.
2019-04-30 18:07:56 +00:00
|
|
|
}()
|
|
|
|
}
|
|
|
|
|
2023-09-20 15:43:46 +00:00
|
|
|
func runLangPlugin(src *querySource) error {
|
2019-05-02 21:22:50 +00:00
|
|
|
rt := src.runinfo.Proj.Runtime.Name()
|
2022-10-04 08:58:01 +00:00
|
|
|
rtopts := src.runinfo.Proj.Runtime.Options()
|
2024-01-25 23:28:58 +00:00
|
|
|
programInfo := plugin.NewProgramInfo(
|
|
|
|
/* rootDirectory */ src.runinfo.ProjectRoot,
|
|
|
|
/* programDirectory */ src.runinfo.Pwd,
|
|
|
|
/* entryPoint */ src.runinfo.Program,
|
|
|
|
/* options */ rtopts)
|
|
|
|
langhost, err := src.plugctx.Host.LanguageRuntime(rt, programInfo)
|
2019-05-02 21:22:50 +00:00
|
|
|
if err != nil {
|
2023-09-20 15:43:46 +00:00
|
|
|
return fmt.Errorf("failed to launch language host %s: %w", rt, err)
|
2019-05-02 21:22:50 +00:00
|
|
|
}
|
|
|
|
contract.Assertf(langhost != nil, "expected non-nil language host %s", rt)
|
|
|
|
|
|
|
|
// Decrypt the configuration.
|
2019-08-12 07:22:42 +00:00
|
|
|
var config map[config.Key]string
|
|
|
|
if src.runinfo.Target != nil {
|
|
|
|
config, err = src.runinfo.Target.Config.Decrypt(src.runinfo.Target.Decrypter)
|
|
|
|
if err != nil {
|
2023-09-20 15:43:46 +00:00
|
|
|
return err
|
2019-08-12 07:22:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-31 09:33:29 +00:00
|
|
|
var name, organization string
|
2019-08-12 07:22:42 +00:00
|
|
|
if src.runinfo.Target != nil {
|
Add tokens.StackName (#14487)
<!---
Thanks so much for your contribution! If this is your first time
contributing, please ensure that you have read the
[CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md)
documentation.
-->
# Description
<!--- Please include a summary of the change and which issue is fixed.
Please also include relevant motivation and context. -->
This adds a new type `tokens.StackName` which is a relatively strongly
typed container for a stack name. The only weakly typed aspect of it is
Go will always allow the "zero" value to be created for a struct, which
for a stack name is the empty string which is invalid. To prevent
introducing unexpected empty strings when working with stack names the
`String()` method will panic for zero initialized stack names.
Apart from the zero value, all other instances of `StackName` are via
`ParseStackName` which returns a descriptive error if the string is not
valid.
This PR only updates "pkg/" to use this type. There are a number of
places in "sdk/" which could do with this type as well, but there's no
harm in doing a staggered roll out, and some parts of "sdk/" are user
facing and will probably have to stay on the current `tokens.Name` and
`tokens.QName` types.
There are two places in the system where we panic on invalid stack
names, both in the http backend. This _should_ be fine as we've had long
standing validation that stacks created in the service are valid stack
names.
Just in case people have managed to introduce invalid stack names, there
is the `PULUMI_DISABLE_VALIDATION` environment variable which will turn
off the validation _and_ panicing for stack names. Users can use that to
temporarily disable the validation and continue working, but it should
only be seen as a temporary measure. If they have invalid names they
should rename them, or if they think they should be valid raise an issue
with us to change the validation code.
## Checklist
- [x] I have run `make tidy` to update any new dependencies
- [x] I have run `make lint` to verify my code passes the lint check
- [ ] I have formatted my code using `gofumpt`
<!--- Please provide details if the checkbox below is to be left
unchecked. -->
- [x] I have added tests that prove my fix is effective or that my
feature works
<!---
User-facing changes require a CHANGELOG entry.
-->
- [ ] I have run `make changelog` and committed the
`changelog/pending/<file>` documenting my change
<!--
If the change(s) in this PR is a modification of an existing call to the
Pulumi Cloud,
then the service should honor older versions of the CLI where this
change would not exist.
You must then bump the API version in
/pkg/backend/httpstate/client/api.go, as well as add
it to the service.
-->
- [ ] Yes, there are changes in this PR that warrants bumping the Pulumi
Cloud API version
<!-- @Pulumi employees: If yes, you must submit corresponding changes in
the service repo. -->
2023-11-15 07:44:54 +00:00
|
|
|
name = src.runinfo.Target.Name.String()
|
2022-08-31 09:33:29 +00:00
|
|
|
organization = string(src.runinfo.Target.Organization)
|
2019-05-02 21:22:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Now run the actual program.
|
|
|
|
progerr, bail, err := langhost.Run(plugin.RunInfo{
|
|
|
|
MonitorAddress: src.mon.Address(),
|
2019-08-12 07:22:42 +00:00
|
|
|
Stack: name,
|
2019-05-02 21:22:50 +00:00
|
|
|
Project: string(src.runinfo.Proj.Name),
|
|
|
|
Pwd: src.runinfo.Pwd,
|
|
|
|
Args: src.runinfo.Args,
|
|
|
|
Config: config,
|
|
|
|
DryRun: true,
|
|
|
|
QueryMode: true,
|
|
|
|
Parallel: math.MaxInt32,
|
2022-08-31 09:33:29 +00:00
|
|
|
Organization: organization,
|
2024-01-25 23:28:58 +00:00
|
|
|
Info: programInfo,
|
2019-05-02 21:22:50 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
// Check if we were asked to Bail. This a special random constant used for that
|
|
|
|
// purpose.
|
|
|
|
if err == nil && bail {
|
2023-09-20 15:43:46 +00:00
|
|
|
return result.BailErrorf("run bailed")
|
2019-05-02 21:22:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if err == nil && progerr != "" {
|
|
|
|
// If the program had an unhandled error; propagate it to the caller.
|
2021-11-13 02:37:17 +00:00
|
|
|
err = fmt.Errorf("an unhandled error occurred: %v", progerr)
|
2019-05-02 21:22:50 +00:00
|
|
|
}
|
2023-09-20 15:43:46 +00:00
|
|
|
return err
|
2019-05-02 21:22:50 +00:00
|
|
|
}
|
|
|
|
|
Implement query primitives in the engine
`pulumi query` is designed, essentially, as a souped-up `exec`. We
execute a query program, and add a few convenience constructs (e.g., the
default providers that give you access to things like `getStack`).
Early in the design process, we decided to not re-use the `up`/update
path, both to minimize risk to update operations, and to simplify the
implementation.
This commit will add this "parallel query universe" into the engine
package. In particular, this includes:
* `QuerySource`, which executes the language provider running the query
program, and providing it with some simple constructs, such as the
default provider, which provides access to `getStack`. This is much
like a very simplified `EvalSource`, though notably without any of the
planning/step execution machinery.
* `queryResmon`, which disallows all resource operations, except the
`Invoke` that retrieves the resource outputs of some stack's last
snapshot. This is much like a simplified `resmon`, but without any of
the provider resolution, and without and support for resource
operations generally.
* Various static functions that pull together miscellaneous things
needed to execute a query program. Notably, this includes gathering
language plugins.
2019-04-30 18:07:56 +00:00
|
|
|
// newQueryResourceMonitor creates a new resource monitor RPC server intended to be used in Pulumi's
|
|
|
|
// "query mode".
|
2019-08-27 17:10:51 +00:00
|
|
|
func newQueryResourceMonitor(
|
2022-08-26 14:51:14 +00:00
|
|
|
builtins *builtinProvider, defaultProviderInfo map[tokens.Package]workspace.PluginSpec,
|
2019-08-27 17:10:51 +00:00
|
|
|
provs ProviderSource, reg *providers.Registry, plugctx *plugin.Context,
|
2023-10-03 07:21:26 +00:00
|
|
|
providerRegErrChan chan<- error, tracingSpan opentracing.Span, runinfo *EvalRunInfo,
|
2023-03-03 16:36:39 +00:00
|
|
|
) (*queryResmon, error) {
|
Implement query primitives in the engine
`pulumi query` is designed, essentially, as a souped-up `exec`. We
execute a query program, and add a few convenience constructs (e.g., the
default providers that give you access to things like `getStack`).
Early in the design process, we decided to not re-use the `up`/update
path, both to minimize risk to update operations, and to simplify the
implementation.
This commit will add this "parallel query universe" into the engine
package. In particular, this includes:
* `QuerySource`, which executes the language provider running the query
program, and providing it with some simple constructs, such as the
default provider, which provides access to `getStack`. This is much
like a very simplified `EvalSource`, though notably without any of the
planning/step execution machinery.
* `queryResmon`, which disallows all resource operations, except the
`Invoke` that retrieves the resource outputs of some stack's last
snapshot. This is much like a simplified `resmon`, but without any of
the provider resolution, and without and support for resource
operations generally.
* Various static functions that pull together miscellaneous things
needed to execute a query program. Notably, this includes gathering
language plugins.
2019-04-30 18:07:56 +00:00
|
|
|
// Create our cancellation channel.
|
|
|
|
cancel := make(chan bool)
|
|
|
|
|
2019-08-27 17:10:51 +00:00
|
|
|
// Create channel for handling registrations.
|
|
|
|
providerRegChan := make(chan *registerResourceEvent)
|
|
|
|
|
|
|
|
// Create a new default provider manager.
|
|
|
|
d := &defaultProviders{
|
2021-12-17 22:52:01 +00:00
|
|
|
defaultProviderInfo: defaultProviderInfo,
|
|
|
|
providers: make(map[string]providers.Reference),
|
|
|
|
config: runinfo.Target,
|
|
|
|
requests: make(chan defaultProviderRequest),
|
|
|
|
providerRegChan: providerRegChan,
|
|
|
|
cancel: cancel,
|
2019-08-27 17:10:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
for e := range providerRegChan {
|
|
|
|
urn := syntheticProviderURN(e.goal)
|
|
|
|
|
2022-07-25 11:08:03 +00:00
|
|
|
inputs, _, err := reg.Check(urn, resource.PropertyMap{}, e.goal.Properties, false, nil)
|
2019-08-27 17:10:51 +00:00
|
|
|
if err != nil {
|
2023-10-03 07:21:26 +00:00
|
|
|
providerRegErrChan <- err
|
2019-08-27 17:10:51 +00:00
|
|
|
return
|
|
|
|
}
|
Reuse provider instances where possible (#14127)
<!---
Thanks so much for your contribution! If this is your first time
contributing, please ensure that you have read the
[CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md)
documentation.
-->
# Description
<!--- Please include a summary of the change and which issue is fixed.
Please also include relevant motivation and context. -->
Fixes https://github.com/pulumi/pulumi/issues/13987.
This reworks the registry to better track provider instances such that
we can reuse unconfigured instances between Creates, Updates, and Sames.
When we allocate a provider instance in the registry for a Check call we
save it with the special id "unconfigured". This value should never make
its way back to program SDKs, it's purely an internal value for the
engine.
When we do a Create, Update or Same we look to see if there's an
unconfigured provider to use and if so configures that one, else it
starts up a fresh one. (N.B. Update we can assume there will always be
an unconfigured one from the Check call before).
This has also fixed registry Create to use the ID `UnknownID` rather
than `""`, have added some contract assertions to check that and fixed
up some test fallout because of that (the tests had been getting away
with leaving ID blank before).
## Checklist
- [x] I have run `make tidy` to update any new dependencies
- [x] I have run `make lint` to verify my code passes the lint check
- [ ] I have formatted my code using `gofumpt`
<!--- Please provide details if the checkbox below is to be left
unchecked. -->
- [x] I have added tests that prove my fix is effective or that my
feature works
<!---
User-facing changes require a CHANGELOG entry.
-->
- [ ] I have run `make changelog` and committed the
`changelog/pending/<file>` documenting my change
<!--
If the change(s) in this PR is a modification of an existing call to the
Pulumi Cloud,
then the service should honor older versions of the CLI where this
change would not exist.
You must then bump the API version in
/pkg/backend/httpstate/client/api.go, as well as add
it to the service.
-->
- [ ] Yes, there are changes in this PR that warrants bumping the Pulumi
Cloud API version
<!-- @Pulumi employees: If yes, you must submit corresponding changes in
the service repo. -->
2023-10-12 20:46:01 +00:00
|
|
|
id, _, _, err := reg.Create(urn, inputs, 9999, false)
|
2019-08-27 17:10:51 +00:00
|
|
|
if err != nil {
|
2023-10-03 07:21:26 +00:00
|
|
|
providerRegErrChan <- err
|
2019-08-27 17:10:51 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
Reuse provider instances where possible (#14127)
<!---
Thanks so much for your contribution! If this is your first time
contributing, please ensure that you have read the
[CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md)
documentation.
-->
# Description
<!--- Please include a summary of the change and which issue is fixed.
Please also include relevant motivation and context. -->
Fixes https://github.com/pulumi/pulumi/issues/13987.
This reworks the registry to better track provider instances such that
we can reuse unconfigured instances between Creates, Updates, and Sames.
When we allocate a provider instance in the registry for a Check call we
save it with the special id "unconfigured". This value should never make
its way back to program SDKs, it's purely an internal value for the
engine.
When we do a Create, Update or Same we look to see if there's an
unconfigured provider to use and if so configures that one, else it
starts up a fresh one. (N.B. Update we can assume there will always be
an unconfigured one from the Check call before).
This has also fixed registry Create to use the ID `UnknownID` rather
than `""`, have added some contract assertions to check that and fixed
up some test fallout because of that (the tests had been getting away
with leaving ID blank before).
## Checklist
- [x] I have run `make tidy` to update any new dependencies
- [x] I have run `make lint` to verify my code passes the lint check
- [ ] I have formatted my code using `gofumpt`
<!--- Please provide details if the checkbox below is to be left
unchecked. -->
- [x] I have added tests that prove my fix is effective or that my
feature works
<!---
User-facing changes require a CHANGELOG entry.
-->
- [ ] I have run `make changelog` and committed the
`changelog/pending/<file>` documenting my change
<!--
If the change(s) in this PR is a modification of an existing call to the
Pulumi Cloud,
then the service should honor older versions of the CLI where this
change would not exist.
You must then bump the API version in
/pkg/backend/httpstate/client/api.go, as well as add
it to the service.
-->
- [ ] Yes, there are changes in this PR that warrants bumping the Pulumi
Cloud API version
<!-- @Pulumi employees: If yes, you must submit corresponding changes in
the service repo. -->
2023-10-12 20:46:01 +00:00
|
|
|
contract.Assertf(id != "", "expected non-empty provider ID")
|
|
|
|
contract.Assertf(id != providers.UnknownID, "expected non-unknown provider ID")
|
|
|
|
|
2019-08-27 17:10:51 +00:00
|
|
|
e.done <- &RegisterResult{State: &resource.State{
|
|
|
|
Type: e.goal.Type,
|
|
|
|
URN: urn,
|
Reuse provider instances where possible (#14127)
<!---
Thanks so much for your contribution! If this is your first time
contributing, please ensure that you have read the
[CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md)
documentation.
-->
# Description
<!--- Please include a summary of the change and which issue is fixed.
Please also include relevant motivation and context. -->
Fixes https://github.com/pulumi/pulumi/issues/13987.
This reworks the registry to better track provider instances such that
we can reuse unconfigured instances between Creates, Updates, and Sames.
When we allocate a provider instance in the registry for a Check call we
save it with the special id "unconfigured". This value should never make
its way back to program SDKs, it's purely an internal value for the
engine.
When we do a Create, Update or Same we look to see if there's an
unconfigured provider to use and if so configures that one, else it
starts up a fresh one. (N.B. Update we can assume there will always be
an unconfigured one from the Check call before).
This has also fixed registry Create to use the ID `UnknownID` rather
than `""`, have added some contract assertions to check that and fixed
up some test fallout because of that (the tests had been getting away
with leaving ID blank before).
## Checklist
- [x] I have run `make tidy` to update any new dependencies
- [x] I have run `make lint` to verify my code passes the lint check
- [ ] I have formatted my code using `gofumpt`
<!--- Please provide details if the checkbox below is to be left
unchecked. -->
- [x] I have added tests that prove my fix is effective or that my
feature works
<!---
User-facing changes require a CHANGELOG entry.
-->
- [ ] I have run `make changelog` and committed the
`changelog/pending/<file>` documenting my change
<!--
If the change(s) in this PR is a modification of an existing call to the
Pulumi Cloud,
then the service should honor older versions of the CLI where this
change would not exist.
You must then bump the API version in
/pkg/backend/httpstate/client/api.go, as well as add
it to the service.
-->
- [ ] Yes, there are changes in this PR that warrants bumping the Pulumi
Cloud API version
<!-- @Pulumi employees: If yes, you must submit corresponding changes in
the service repo. -->
2023-10-12 20:46:01 +00:00
|
|
|
ID: id,
|
2019-08-27 17:10:51 +00:00
|
|
|
}}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
Implement query primitives in the engine
`pulumi query` is designed, essentially, as a souped-up `exec`. We
execute a query program, and add a few convenience constructs (e.g., the
default providers that give you access to things like `getStack`).
Early in the design process, we decided to not re-use the `up`/update
path, both to minimize risk to update operations, and to simplify the
implementation.
This commit will add this "parallel query universe" into the engine
package. In particular, this includes:
* `QuerySource`, which executes the language provider running the query
program, and providing it with some simple constructs, such as the
default provider, which provides access to `getStack`. This is much
like a very simplified `EvalSource`, though notably without any of the
planning/step execution machinery.
* `queryResmon`, which disallows all resource operations, except the
`Invoke` that retrieves the resource outputs of some stack's last
snapshot. This is much like a simplified `resmon`, but without any of
the provider resolution, and without and support for resource
operations generally.
* Various static functions that pull together miscellaneous things
needed to execute a query program. Notably, this includes gathering
language plugins.
2019-04-30 18:07:56 +00:00
|
|
|
// New up an engine RPC server.
|
|
|
|
queryResmon := &queryResmon{
|
2019-08-27 17:10:51 +00:00
|
|
|
builtins: builtins,
|
|
|
|
providers: provs,
|
|
|
|
defaultProviders: d,
|
|
|
|
cancel: cancel,
|
|
|
|
reg: reg,
|
Implement query primitives in the engine
`pulumi query` is designed, essentially, as a souped-up `exec`. We
execute a query program, and add a few convenience constructs (e.g., the
default providers that give you access to things like `getStack`).
Early in the design process, we decided to not re-use the `up`/update
path, both to minimize risk to update operations, and to simplify the
implementation.
This commit will add this "parallel query universe" into the engine
package. In particular, this includes:
* `QuerySource`, which executes the language provider running the query
program, and providing it with some simple constructs, such as the
default provider, which provides access to `getStack`. This is much
like a very simplified `EvalSource`, though notably without any of the
planning/step execution machinery.
* `queryResmon`, which disallows all resource operations, except the
`Invoke` that retrieves the resource outputs of some stack's last
snapshot. This is much like a simplified `resmon`, but without any of
the provider resolution, and without and support for resource
operations generally.
* Various static functions that pull together miscellaneous things
needed to execute a query program. Notably, this includes gathering
language plugins.
2019-04-30 18:07:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Fire up a gRPC server and start listening for incomings.
|
2022-11-01 15:15:09 +00:00
|
|
|
handle, err := rpcutil.ServeWithOptions(rpcutil.ServeOptions{
|
|
|
|
Cancel: queryResmon.cancel,
|
|
|
|
Init: func(srv *grpc.Server) error {
|
Implement query primitives in the engine
`pulumi query` is designed, essentially, as a souped-up `exec`. We
execute a query program, and add a few convenience constructs (e.g., the
default providers that give you access to things like `getStack`).
Early in the design process, we decided to not re-use the `up`/update
path, both to minimize risk to update operations, and to simplify the
implementation.
This commit will add this "parallel query universe" into the engine
package. In particular, this includes:
* `QuerySource`, which executes the language provider running the query
program, and providing it with some simple constructs, such as the
default provider, which provides access to `getStack`. This is much
like a very simplified `EvalSource`, though notably without any of the
planning/step execution machinery.
* `queryResmon`, which disallows all resource operations, except the
`Invoke` that retrieves the resource outputs of some stack's last
snapshot. This is much like a simplified `resmon`, but without any of
the provider resolution, and without and support for resource
operations generally.
* Various static functions that pull together miscellaneous things
needed to execute a query program. Notably, this includes gathering
language plugins.
2019-04-30 18:07:56 +00:00
|
|
|
pulumirpc.RegisterResourceMonitorServer(srv, queryResmon)
|
|
|
|
return nil
|
|
|
|
},
|
2022-11-01 15:15:09 +00:00
|
|
|
Options: rpcutil.OpenTracingServerInterceptorOptions(tracingSpan),
|
|
|
|
})
|
Implement query primitives in the engine
`pulumi query` is designed, essentially, as a souped-up `exec`. We
execute a query program, and add a few convenience constructs (e.g., the
default providers that give you access to things like `getStack`).
Early in the design process, we decided to not re-use the `up`/update
path, both to minimize risk to update operations, and to simplify the
implementation.
This commit will add this "parallel query universe" into the engine
package. In particular, this includes:
* `QuerySource`, which executes the language provider running the query
program, and providing it with some simple constructs, such as the
default provider, which provides access to `getStack`. This is much
like a very simplified `EvalSource`, though notably without any of the
planning/step execution machinery.
* `queryResmon`, which disallows all resource operations, except the
`Invoke` that retrieves the resource outputs of some stack's last
snapshot. This is much like a simplified `resmon`, but without any of
the provider resolution, and without and support for resource
operations generally.
* Various static functions that pull together miscellaneous things
needed to execute a query program. Notably, this includes gathering
language plugins.
2019-04-30 18:07:56 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2022-11-01 15:15:09 +00:00
|
|
|
monitorAddress := fmt.Sprintf("127.0.0.1:%d", handle.Port)
|
2021-06-30 14:48:56 +00:00
|
|
|
|
2021-07-09 02:57:47 +00:00
|
|
|
var config map[config.Key]string
|
|
|
|
if runinfo.Target != nil {
|
|
|
|
config, err = runinfo.Target.Config.Decrypt(runinfo.Target.Decrypter)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var name string
|
|
|
|
if runinfo.Target != nil {
|
Add tokens.StackName (#14487)
<!---
Thanks so much for your contribution! If this is your first time
contributing, please ensure that you have read the
[CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md)
documentation.
-->
# Description
<!--- Please include a summary of the change and which issue is fixed.
Please also include relevant motivation and context. -->
This adds a new type `tokens.StackName` which is a relatively strongly
typed container for a stack name. The only weakly typed aspect of it is
Go will always allow the "zero" value to be created for a struct, which
for a stack name is the empty string which is invalid. To prevent
introducing unexpected empty strings when working with stack names the
`String()` method will panic for zero initialized stack names.
Apart from the zero value, all other instances of `StackName` are via
`ParseStackName` which returns a descriptive error if the string is not
valid.
This PR only updates "pkg/" to use this type. There are a number of
places in "sdk/" which could do with this type as well, but there's no
harm in doing a staggered roll out, and some parts of "sdk/" are user
facing and will probably have to stay on the current `tokens.Name` and
`tokens.QName` types.
There are two places in the system where we panic on invalid stack
names, both in the http backend. This _should_ be fine as we've had long
standing validation that stacks created in the service are valid stack
names.
Just in case people have managed to introduce invalid stack names, there
is the `PULUMI_DISABLE_VALIDATION` environment variable which will turn
off the validation _and_ panicing for stack names. Users can use that to
temporarily disable the validation and continue working, but it should
only be seen as a temporary measure. If they have invalid names they
should rename them, or if they think they should be valid raise an issue
with us to change the validation code.
## Checklist
- [x] I have run `make tidy` to update any new dependencies
- [x] I have run `make lint` to verify my code passes the lint check
- [ ] I have formatted my code using `gofumpt`
<!--- Please provide details if the checkbox below is to be left
unchecked. -->
- [x] I have added tests that prove my fix is effective or that my
feature works
<!---
User-facing changes require a CHANGELOG entry.
-->
- [ ] I have run `make changelog` and committed the
`changelog/pending/<file>` documenting my change
<!--
If the change(s) in this PR is a modification of an existing call to the
Pulumi Cloud,
then the service should honor older versions of the CLI where this
change would not exist.
You must then bump the API version in
/pkg/backend/httpstate/client/api.go, as well as add
it to the service.
-->
- [ ] Yes, there are changes in this PR that warrants bumping the Pulumi
Cloud API version
<!-- @Pulumi employees: If yes, you must submit corresponding changes in
the service repo. -->
2023-11-15 07:44:54 +00:00
|
|
|
name = runinfo.Target.Name.String()
|
2021-06-30 14:48:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
queryResmon.callInfo = plugin.CallInfo{
|
|
|
|
Project: string(runinfo.Proj.Name),
|
2021-07-09 02:57:47 +00:00
|
|
|
Stack: name,
|
|
|
|
Config: config,
|
2021-06-30 14:48:56 +00:00
|
|
|
DryRun: true,
|
|
|
|
Parallel: math.MaxInt32,
|
|
|
|
MonitorAddress: monitorAddress,
|
|
|
|
}
|
|
|
|
queryResmon.addr = monitorAddress
|
2022-11-01 15:15:09 +00:00
|
|
|
queryResmon.done = handle.Done
|
Implement query primitives in the engine
`pulumi query` is designed, essentially, as a souped-up `exec`. We
execute a query program, and add a few convenience constructs (e.g., the
default providers that give you access to things like `getStack`).
Early in the design process, we decided to not re-use the `up`/update
path, both to minimize risk to update operations, and to simplify the
implementation.
This commit will add this "parallel query universe" into the engine
package. In particular, this includes:
* `QuerySource`, which executes the language provider running the query
program, and providing it with some simple constructs, such as the
default provider, which provides access to `getStack`. This is much
like a very simplified `EvalSource`, though notably without any of the
planning/step execution machinery.
* `queryResmon`, which disallows all resource operations, except the
`Invoke` that retrieves the resource outputs of some stack's last
snapshot. This is much like a simplified `resmon`, but without any of
the provider resolution, and without and support for resource
operations generally.
* Various static functions that pull together miscellaneous things
needed to execute a query program. Notably, this includes gathering
language plugins.
2019-04-30 18:07:56 +00:00
|
|
|
|
2019-08-27 17:10:51 +00:00
|
|
|
go d.serve()
|
|
|
|
|
Implement query primitives in the engine
`pulumi query` is designed, essentially, as a souped-up `exec`. We
execute a query program, and add a few convenience constructs (e.g., the
default providers that give you access to things like `getStack`).
Early in the design process, we decided to not re-use the `up`/update
path, both to minimize risk to update operations, and to simplify the
implementation.
This commit will add this "parallel query universe" into the engine
package. In particular, this includes:
* `QuerySource`, which executes the language provider running the query
program, and providing it with some simple constructs, such as the
default provider, which provides access to `getStack`. This is much
like a very simplified `EvalSource`, though notably without any of the
planning/step execution machinery.
* `queryResmon`, which disallows all resource operations, except the
`Invoke` that retrieves the resource outputs of some stack's last
snapshot. This is much like a simplified `resmon`, but without any of
the provider resolution, and without and support for resource
operations generally.
* Various static functions that pull together miscellaneous things
needed to execute a query program. Notably, this includes gathering
language plugins.
2019-04-30 18:07:56 +00:00
|
|
|
return queryResmon, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// queryResmon is a pulumirpc.ResourceMonitor that is meant to run in Pulumi's "query mode". It
|
|
|
|
// performs two critical functions:
|
|
|
|
//
|
2022-09-14 02:12:02 +00:00
|
|
|
// 1. Disallows all resource operations. `queryResmon` intercepts all resource operations and
|
|
|
|
// returns an error instead of allowing them to proceed.
|
|
|
|
// 2. Services requests for stack snapshots. This is primarily to allow us to allow queries across
|
|
|
|
// stack snapshots.
|
Implement query primitives in the engine
`pulumi query` is designed, essentially, as a souped-up `exec`. We
execute a query program, and add a few convenience constructs (e.g., the
default providers that give you access to things like `getStack`).
Early in the design process, we decided to not re-use the `up`/update
path, both to minimize risk to update operations, and to simplify the
implementation.
This commit will add this "parallel query universe" into the engine
package. In particular, this includes:
* `QuerySource`, which executes the language provider running the query
program, and providing it with some simple constructs, such as the
default provider, which provides access to `getStack`. This is much
like a very simplified `EvalSource`, though notably without any of the
planning/step execution machinery.
* `queryResmon`, which disallows all resource operations, except the
`Invoke` that retrieves the resource outputs of some stack's last
snapshot. This is much like a simplified `resmon`, but without any of
the provider resolution, and without and support for resource
operations generally.
* Various static functions that pull together miscellaneous things
needed to execute a query program. Notably, this includes gathering
language plugins.
2019-04-30 18:07:56 +00:00
|
|
|
type queryResmon struct {
|
2022-12-14 19:20:26 +00:00
|
|
|
pulumirpc.UnimplementedResourceMonitorServer
|
|
|
|
|
2019-08-27 17:10:51 +00:00
|
|
|
builtins *builtinProvider // provides builtins such as `getStack`.
|
|
|
|
providers ProviderSource // the provider source itself.
|
|
|
|
defaultProviders *defaultProviders // the default provider manager.
|
|
|
|
addr string // the address the host is listening on.
|
|
|
|
cancel chan bool // a channel that can cancel the server.
|
2022-11-01 15:15:09 +00:00
|
|
|
done <-chan error // a channel that resolves when the server completes.
|
2019-08-27 17:10:51 +00:00
|
|
|
reg *providers.Registry // registry for resource providers.
|
2021-06-30 14:48:56 +00:00
|
|
|
callInfo plugin.CallInfo // information for call calls.
|
Implement query primitives in the engine
`pulumi query` is designed, essentially, as a souped-up `exec`. We
execute a query program, and add a few convenience constructs (e.g., the
default providers that give you access to things like `getStack`).
Early in the design process, we decided to not re-use the `up`/update
path, both to minimize risk to update operations, and to simplify the
implementation.
This commit will add this "parallel query universe" into the engine
package. In particular, this includes:
* `QuerySource`, which executes the language provider running the query
program, and providing it with some simple constructs, such as the
default provider, which provides access to `getStack`. This is much
like a very simplified `EvalSource`, though notably without any of the
planning/step execution machinery.
* `queryResmon`, which disallows all resource operations, except the
`Invoke` that retrieves the resource outputs of some stack's last
snapshot. This is much like a simplified `resmon`, but without any of
the provider resolution, and without and support for resource
operations generally.
* Various static functions that pull together miscellaneous things
needed to execute a query program. Notably, this includes gathering
language plugins.
2019-04-30 18:07:56 +00:00
|
|
|
}
|
|
|
|
|
2019-05-02 21:22:50 +00:00
|
|
|
var _ SourceResourceMonitor = (*queryResmon)(nil)
|
|
|
|
|
Implement query primitives in the engine
`pulumi query` is designed, essentially, as a souped-up `exec`. We
execute a query program, and add a few convenience constructs (e.g., the
default providers that give you access to things like `getStack`).
Early in the design process, we decided to not re-use the `up`/update
path, both to minimize risk to update operations, and to simplify the
implementation.
This commit will add this "parallel query universe" into the engine
package. In particular, this includes:
* `QuerySource`, which executes the language provider running the query
program, and providing it with some simple constructs, such as the
default provider, which provides access to `getStack`. This is much
like a very simplified `EvalSource`, though notably without any of the
planning/step execution machinery.
* `queryResmon`, which disallows all resource operations, except the
`Invoke` that retrieves the resource outputs of some stack's last
snapshot. This is much like a simplified `resmon`, but without any of
the provider resolution, and without and support for resource
operations generally.
* Various static functions that pull together miscellaneous things
needed to execute a query program. Notably, this includes gathering
language plugins.
2019-04-30 18:07:56 +00:00
|
|
|
// Address returns the address at which the monitor's RPC server may be reached.
|
|
|
|
func (rm *queryResmon) Address() string {
|
|
|
|
return rm.addr
|
|
|
|
}
|
|
|
|
|
|
|
|
// Cancel signals that the engine should be terminated, awaits its termination, and returns any
|
|
|
|
// errors that result.
|
|
|
|
func (rm *queryResmon) Cancel() error {
|
|
|
|
close(rm.cancel)
|
|
|
|
return <-rm.done
|
|
|
|
}
|
|
|
|
|
|
|
|
// Invoke performs an invocation of a member located in a resource provider.
|
2022-04-14 09:59:46 +00:00
|
|
|
func (rm *queryResmon) Invoke(
|
2023-03-03 16:36:39 +00:00
|
|
|
ctx context.Context, req *pulumirpc.ResourceInvokeRequest,
|
|
|
|
) (*pulumirpc.InvokeResponse, error) {
|
Implement query primitives in the engine
`pulumi query` is designed, essentially, as a souped-up `exec`. We
execute a query program, and add a few convenience constructs (e.g., the
default providers that give you access to things like `getStack`).
Early in the design process, we decided to not re-use the `up`/update
path, both to minimize risk to update operations, and to simplify the
implementation.
This commit will add this "parallel query universe" into the engine
package. In particular, this includes:
* `QuerySource`, which executes the language provider running the query
program, and providing it with some simple constructs, such as the
default provider, which provides access to `getStack`. This is much
like a very simplified `EvalSource`, though notably without any of the
planning/step execution machinery.
* `queryResmon`, which disallows all resource operations, except the
`Invoke` that retrieves the resource outputs of some stack's last
snapshot. This is much like a simplified `resmon`, but without any of
the provider resolution, and without and support for resource
operations generally.
* Various static functions that pull together miscellaneous things
needed to execute a query program. Notably, this includes gathering
language plugins.
2019-04-30 18:07:56 +00:00
|
|
|
tok := tokens.ModuleMember(req.GetTok())
|
|
|
|
label := fmt.Sprintf("QueryResourceMonitor.Invoke(%s)", tok)
|
|
|
|
|
2023-09-11 15:54:07 +00:00
|
|
|
providerReq, err := parseProviderRequest(
|
|
|
|
tok.Package(), req.GetVersion(),
|
|
|
|
req.GetPluginDownloadURL(), req.GetPluginChecksums())
|
2019-08-27 17:10:51 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2022-02-28 23:33:45 +00:00
|
|
|
prov, err := getProviderFromSource(rm.reg, rm.defaultProviders, providerReq, req.GetProvider(), tok)
|
2019-08-27 17:10:51 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
Implement query primitives in the engine
`pulumi query` is designed, essentially, as a souped-up `exec`. We
execute a query program, and add a few convenience constructs (e.g., the
default providers that give you access to things like `getStack`).
Early in the design process, we decided to not re-use the `up`/update
path, both to minimize risk to update operations, and to simplify the
implementation.
This commit will add this "parallel query universe" into the engine
package. In particular, this includes:
* `QuerySource`, which executes the language provider running the query
program, and providing it with some simple constructs, such as the
default provider, which provides access to `getStack`. This is much
like a very simplified `EvalSource`, though notably without any of the
planning/step execution machinery.
* `queryResmon`, which disallows all resource operations, except the
`Invoke` that retrieves the resource outputs of some stack's last
snapshot. This is much like a simplified `resmon`, but without any of
the provider resolution, and without and support for resource
operations generally.
* Various static functions that pull together miscellaneous things
needed to execute a query program. Notably, this includes gathering
language plugins.
2019-04-30 18:07:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
args, err := plugin.UnmarshalProperties(
|
2020-10-27 17:12:12 +00:00
|
|
|
req.GetArgs(), plugin.MarshalOptions{
|
|
|
|
Label: label,
|
|
|
|
KeepUnknowns: true,
|
|
|
|
KeepSecrets: true,
|
|
|
|
KeepResources: true,
|
|
|
|
})
|
Implement query primitives in the engine
`pulumi query` is designed, essentially, as a souped-up `exec`. We
execute a query program, and add a few convenience constructs (e.g., the
default providers that give you access to things like `getStack`).
Early in the design process, we decided to not re-use the `up`/update
path, both to minimize risk to update operations, and to simplify the
implementation.
This commit will add this "parallel query universe" into the engine
package. In particular, this includes:
* `QuerySource`, which executes the language provider running the query
program, and providing it with some simple constructs, such as the
default provider, which provides access to `getStack`. This is much
like a very simplified `EvalSource`, though notably without any of the
planning/step execution machinery.
* `queryResmon`, which disallows all resource operations, except the
`Invoke` that retrieves the resource outputs of some stack's last
snapshot. This is much like a simplified `resmon`, but without any of
the provider resolution, and without and support for resource
operations generally.
* Various static functions that pull together miscellaneous things
needed to execute a query program. Notably, this includes gathering
language plugins.
2019-04-30 18:07:56 +00:00
|
|
|
if err != nil {
|
2021-11-13 02:37:17 +00:00
|
|
|
return nil, fmt.Errorf("failed to unmarshal %v args: %w", tok, err)
|
Implement query primitives in the engine
`pulumi query` is designed, essentially, as a souped-up `exec`. We
execute a query program, and add a few convenience constructs (e.g., the
default providers that give you access to things like `getStack`).
Early in the design process, we decided to not re-use the `up`/update
path, both to minimize risk to update operations, and to simplify the
implementation.
This commit will add this "parallel query universe" into the engine
package. In particular, this includes:
* `QuerySource`, which executes the language provider running the query
program, and providing it with some simple constructs, such as the
default provider, which provides access to `getStack`. This is much
like a very simplified `EvalSource`, though notably without any of the
planning/step execution machinery.
* `queryResmon`, which disallows all resource operations, except the
`Invoke` that retrieves the resource outputs of some stack's last
snapshot. This is much like a simplified `resmon`, but without any of
the provider resolution, and without and support for resource
operations generally.
* Various static functions that pull together miscellaneous things
needed to execute a query program. Notably, this includes gathering
language plugins.
2019-04-30 18:07:56 +00:00
|
|
|
}
|
|
|
|
|
2019-08-27 17:10:51 +00:00
|
|
|
// Do the invoke and then return the arguments.
|
2021-06-30 14:48:56 +00:00
|
|
|
logging.V(5).Infof("QueryResourceMonitor.Invoke received: tok=%v #args=%v", tok, len(args))
|
2019-08-27 17:10:51 +00:00
|
|
|
ret, failures, err := prov.Invoke(tok, args)
|
Implement query primitives in the engine
`pulumi query` is designed, essentially, as a souped-up `exec`. We
execute a query program, and add a few convenience constructs (e.g., the
default providers that give you access to things like `getStack`).
Early in the design process, we decided to not re-use the `up`/update
path, both to minimize risk to update operations, and to simplify the
implementation.
This commit will add this "parallel query universe" into the engine
package. In particular, this includes:
* `QuerySource`, which executes the language provider running the query
program, and providing it with some simple constructs, such as the
default provider, which provides access to `getStack`. This is much
like a very simplified `EvalSource`, though notably without any of the
planning/step execution machinery.
* `queryResmon`, which disallows all resource operations, except the
`Invoke` that retrieves the resource outputs of some stack's last
snapshot. This is much like a simplified `resmon`, but without any of
the provider resolution, and without and support for resource
operations generally.
* Various static functions that pull together miscellaneous things
needed to execute a query program. Notably, this includes gathering
language plugins.
2019-04-30 18:07:56 +00:00
|
|
|
if err != nil {
|
2021-11-13 02:37:17 +00:00
|
|
|
return nil, fmt.Errorf("invocation of %v returned an error: %w", tok, err)
|
Implement query primitives in the engine
`pulumi query` is designed, essentially, as a souped-up `exec`. We
execute a query program, and add a few convenience constructs (e.g., the
default providers that give you access to things like `getStack`).
Early in the design process, we decided to not re-use the `up`/update
path, both to minimize risk to update operations, and to simplify the
implementation.
This commit will add this "parallel query universe" into the engine
package. In particular, this includes:
* `QuerySource`, which executes the language provider running the query
program, and providing it with some simple constructs, such as the
default provider, which provides access to `getStack`. This is much
like a very simplified `EvalSource`, though notably without any of the
planning/step execution machinery.
* `queryResmon`, which disallows all resource operations, except the
`Invoke` that retrieves the resource outputs of some stack's last
snapshot. This is much like a simplified `resmon`, but without any of
the provider resolution, and without and support for resource
operations generally.
* Various static functions that pull together miscellaneous things
needed to execute a query program. Notably, this includes gathering
language plugins.
2019-04-30 18:07:56 +00:00
|
|
|
}
|
2020-10-27 17:12:12 +00:00
|
|
|
mret, err := plugin.MarshalProperties(ret, plugin.MarshalOptions{
|
|
|
|
Label: label,
|
|
|
|
KeepUnknowns: true,
|
|
|
|
KeepResources: req.GetAcceptResources(),
|
|
|
|
})
|
Implement query primitives in the engine
`pulumi query` is designed, essentially, as a souped-up `exec`. We
execute a query program, and add a few convenience constructs (e.g., the
default providers that give you access to things like `getStack`).
Early in the design process, we decided to not re-use the `up`/update
path, both to minimize risk to update operations, and to simplify the
implementation.
This commit will add this "parallel query universe" into the engine
package. In particular, this includes:
* `QuerySource`, which executes the language provider running the query
program, and providing it with some simple constructs, such as the
default provider, which provides access to `getStack`. This is much
like a very simplified `EvalSource`, though notably without any of the
planning/step execution machinery.
* `queryResmon`, which disallows all resource operations, except the
`Invoke` that retrieves the resource outputs of some stack's last
snapshot. This is much like a simplified `resmon`, but without any of
the provider resolution, and without and support for resource
operations generally.
* Various static functions that pull together miscellaneous things
needed to execute a query program. Notably, this includes gathering
language plugins.
2019-04-30 18:07:56 +00:00
|
|
|
if err != nil {
|
2021-11-13 02:37:17 +00:00
|
|
|
return nil, fmt.Errorf("failed to marshal return: %w", err)
|
Implement query primitives in the engine
`pulumi query` is designed, essentially, as a souped-up `exec`. We
execute a query program, and add a few convenience constructs (e.g., the
default providers that give you access to things like `getStack`).
Early in the design process, we decided to not re-use the `up`/update
path, both to minimize risk to update operations, and to simplify the
implementation.
This commit will add this "parallel query universe" into the engine
package. In particular, this includes:
* `QuerySource`, which executes the language provider running the query
program, and providing it with some simple constructs, such as the
default provider, which provides access to `getStack`. This is much
like a very simplified `EvalSource`, though notably without any of the
planning/step execution machinery.
* `queryResmon`, which disallows all resource operations, except the
`Invoke` that retrieves the resource outputs of some stack's last
snapshot. This is much like a simplified `resmon`, but without any of
the provider resolution, and without and support for resource
operations generally.
* Various static functions that pull together miscellaneous things
needed to execute a query program. Notably, this includes gathering
language plugins.
2019-04-30 18:07:56 +00:00
|
|
|
}
|
|
|
|
|
2023-06-28 16:02:04 +00:00
|
|
|
chkfails := slice.Prealloc[*pulumirpc.CheckFailure](len(failures))
|
Implement query primitives in the engine
`pulumi query` is designed, essentially, as a souped-up `exec`. We
execute a query program, and add a few convenience constructs (e.g., the
default providers that give you access to things like `getStack`).
Early in the design process, we decided to not re-use the `up`/update
path, both to minimize risk to update operations, and to simplify the
implementation.
This commit will add this "parallel query universe" into the engine
package. In particular, this includes:
* `QuerySource`, which executes the language provider running the query
program, and providing it with some simple constructs, such as the
default provider, which provides access to `getStack`. This is much
like a very simplified `EvalSource`, though notably without any of the
planning/step execution machinery.
* `queryResmon`, which disallows all resource operations, except the
`Invoke` that retrieves the resource outputs of some stack's last
snapshot. This is much like a simplified `resmon`, but without any of
the provider resolution, and without and support for resource
operations generally.
* Various static functions that pull together miscellaneous things
needed to execute a query program. Notably, this includes gathering
language plugins.
2019-04-30 18:07:56 +00:00
|
|
|
for _, failure := range failures {
|
|
|
|
chkfails = append(chkfails, &pulumirpc.CheckFailure{
|
|
|
|
Property: string(failure.Property),
|
|
|
|
Reason: failure.Reason,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
return &pulumirpc.InvokeResponse{Return: mret, Failures: chkfails}, nil
|
|
|
|
}
|
|
|
|
|
2019-10-22 07:20:26 +00:00
|
|
|
func (rm *queryResmon) StreamInvoke(
|
2023-03-03 16:36:39 +00:00
|
|
|
req *pulumirpc.ResourceInvokeRequest, stream pulumirpc.ResourceMonitor_StreamInvokeServer,
|
|
|
|
) error {
|
2019-10-22 07:20:26 +00:00
|
|
|
tok := tokens.ModuleMember(req.GetTok())
|
|
|
|
label := fmt.Sprintf("QueryResourceMonitor.StreamInvoke(%s)", tok)
|
|
|
|
|
2023-09-11 15:54:07 +00:00
|
|
|
providerReq, err := parseProviderRequest(
|
|
|
|
tok.Package(), req.GetVersion(),
|
|
|
|
req.GetPluginDownloadURL(), req.GetPluginChecksums())
|
2019-10-22 07:20:26 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2022-02-28 23:33:45 +00:00
|
|
|
prov, err := getProviderFromSource(rm.reg, rm.defaultProviders, providerReq, req.GetProvider(), tok)
|
2019-10-22 07:20:26 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
args, err := plugin.UnmarshalProperties(
|
|
|
|
req.GetArgs(), plugin.MarshalOptions{Label: label, KeepUnknowns: true})
|
|
|
|
if err != nil {
|
2021-11-13 02:37:17 +00:00
|
|
|
return fmt.Errorf("failed to unmarshal %v args: %w", tok, err)
|
2019-10-22 07:20:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Synchronously do the StreamInvoke and then return the arguments. This will block until the
|
|
|
|
// streaming operation completes!
|
2021-06-30 14:48:56 +00:00
|
|
|
logging.V(5).Infof("QueryResourceMonitor.StreamInvoke received: tok=%v #args=%v", tok, len(args))
|
2019-10-22 07:20:26 +00:00
|
|
|
failures, err := prov.StreamInvoke(tok, args, func(event resource.PropertyMap) error {
|
2023-03-03 16:36:39 +00:00
|
|
|
mret, err := plugin.MarshalProperties(event, plugin.MarshalOptions{
|
|
|
|
Label: label,
|
2022-04-14 09:59:46 +00:00
|
|
|
KeepUnknowns: true,
|
|
|
|
KeepResources: req.GetAcceptResources(),
|
|
|
|
})
|
2019-10-22 07:20:26 +00:00
|
|
|
if err != nil {
|
2021-11-13 02:37:17 +00:00
|
|
|
return fmt.Errorf("failed to marshal return: %w", err)
|
2019-10-22 07:20:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return stream.Send(&pulumirpc.InvokeResponse{Return: mret})
|
|
|
|
})
|
|
|
|
if err != nil {
|
2021-11-13 02:37:17 +00:00
|
|
|
return fmt.Errorf("streaming invocation of %v returned an error: %w", tok, err)
|
2019-10-22 07:20:26 +00:00
|
|
|
}
|
|
|
|
|
2023-06-28 16:02:04 +00:00
|
|
|
chkfails := slice.Prealloc[*pulumirpc.CheckFailure](len(failures))
|
2019-10-22 07:20:26 +00:00
|
|
|
for _, failure := range failures {
|
|
|
|
chkfails = append(chkfails, &pulumirpc.CheckFailure{
|
|
|
|
Property: string(failure.Property),
|
|
|
|
Reason: failure.Reason,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-11-11 23:00:17 +00:00
|
|
|
if len(chkfails) > 0 {
|
|
|
|
return stream.Send(&pulumirpc.InvokeResponse{Failures: chkfails})
|
|
|
|
}
|
|
|
|
return nil
|
2019-10-22 07:20:26 +00:00
|
|
|
}
|
|
|
|
|
2021-06-30 14:48:56 +00:00
|
|
|
// Call dynamically executes a method in the provider associated with a component resource.
|
2024-02-08 13:16:23 +00:00
|
|
|
func (rm *queryResmon) Call(ctx context.Context, req *pulumirpc.ResourceCallRequest) (*pulumirpc.CallResponse, error) {
|
2021-06-30 14:48:56 +00:00
|
|
|
tok := tokens.ModuleMember(req.GetTok())
|
|
|
|
label := fmt.Sprintf("QueryResourceMonitor.Call(%s)", tok)
|
|
|
|
|
2023-09-11 15:54:07 +00:00
|
|
|
providerReq, err := parseProviderRequest(
|
|
|
|
tok.Package(), req.GetVersion(),
|
|
|
|
req.GetPluginDownloadURL(), req.GetPluginChecksums())
|
2021-06-30 14:48:56 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2022-02-28 23:33:45 +00:00
|
|
|
prov, err := getProviderFromSource(rm.reg, rm.defaultProviders, providerReq, req.GetProvider(), tok)
|
2021-06-30 14:48:56 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
args, err := plugin.UnmarshalProperties(
|
|
|
|
req.GetArgs(), plugin.MarshalOptions{
|
|
|
|
Label: label,
|
|
|
|
KeepUnknowns: true,
|
|
|
|
KeepSecrets: true,
|
|
|
|
KeepResources: true,
|
|
|
|
})
|
|
|
|
if err != nil {
|
2021-11-13 02:37:17 +00:00
|
|
|
return nil, fmt.Errorf("failed to unmarshal %v args: %w", tok, err)
|
2021-06-30 14:48:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
argDependencies := map[resource.PropertyKey][]resource.URN{}
|
|
|
|
for name, deps := range req.GetArgDependencies() {
|
|
|
|
urns := make([]resource.URN, len(deps.Urns))
|
|
|
|
for i, urn := range deps.Urns {
|
|
|
|
urns[i] = resource.URN(urn)
|
|
|
|
}
|
|
|
|
argDependencies[resource.PropertyKey(name)] = urns
|
|
|
|
}
|
|
|
|
options := plugin.CallOptions{
|
|
|
|
ArgDependencies: argDependencies,
|
|
|
|
}
|
|
|
|
|
|
|
|
// Do the call and then return the arguments.
|
|
|
|
logging.V(5).Infof(
|
|
|
|
"QueryResourceMonitor.Call received: tok=%v #args=%v #info=%v #options=%v", tok, len(args), rm.callInfo, options)
|
|
|
|
ret, err := prov.Call(tok, args, rm.callInfo, options)
|
|
|
|
if err != nil {
|
2021-11-13 02:37:17 +00:00
|
|
|
return nil, fmt.Errorf("call of %v returned an error: %w", tok, err)
|
2021-06-30 14:48:56 +00:00
|
|
|
}
|
|
|
|
mret, err := plugin.MarshalProperties(ret.Return, plugin.MarshalOptions{
|
|
|
|
Label: label,
|
|
|
|
KeepUnknowns: true,
|
|
|
|
KeepSecrets: true,
|
|
|
|
KeepResources: true,
|
|
|
|
})
|
|
|
|
if err != nil {
|
2021-11-13 02:37:17 +00:00
|
|
|
return nil, fmt.Errorf("failed to marshal return: %w", err)
|
2021-06-30 14:48:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
returnDependencies := map[string]*pulumirpc.CallResponse_ReturnDependencies{}
|
|
|
|
for name, deps := range ret.ReturnDependencies {
|
|
|
|
urns := make([]string, len(deps))
|
|
|
|
for i, urn := range deps {
|
|
|
|
urns[i] = string(urn)
|
|
|
|
}
|
|
|
|
returnDependencies[string(name)] = &pulumirpc.CallResponse_ReturnDependencies{Urns: urns}
|
|
|
|
}
|
|
|
|
|
2023-06-28 16:02:04 +00:00
|
|
|
chkfails := slice.Prealloc[*pulumirpc.CheckFailure](len(ret.Failures))
|
2021-06-30 14:48:56 +00:00
|
|
|
for _, failure := range ret.Failures {
|
|
|
|
chkfails = append(chkfails, &pulumirpc.CheckFailure{
|
|
|
|
Property: string(failure.Property),
|
|
|
|
Reason: failure.Reason,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
return &pulumirpc.CallResponse{Return: mret, ReturnDependencies: returnDependencies, Failures: chkfails}, nil
|
|
|
|
}
|
|
|
|
|
Implement query primitives in the engine
`pulumi query` is designed, essentially, as a souped-up `exec`. We
execute a query program, and add a few convenience constructs (e.g., the
default providers that give you access to things like `getStack`).
Early in the design process, we decided to not re-use the `up`/update
path, both to minimize risk to update operations, and to simplify the
implementation.
This commit will add this "parallel query universe" into the engine
package. In particular, this includes:
* `QuerySource`, which executes the language provider running the query
program, and providing it with some simple constructs, such as the
default provider, which provides access to `getStack`. This is much
like a very simplified `EvalSource`, though notably without any of the
planning/step execution machinery.
* `queryResmon`, which disallows all resource operations, except the
`Invoke` that retrieves the resource outputs of some stack's last
snapshot. This is much like a simplified `resmon`, but without any of
the provider resolution, and without and support for resource
operations generally.
* Various static functions that pull together miscellaneous things
needed to execute a query program. Notably, this includes gathering
language plugins.
2019-04-30 18:07:56 +00:00
|
|
|
// ReadResource reads the current state associated with a resource from its provider plugin.
|
|
|
|
func (rm *queryResmon) ReadResource(ctx context.Context,
|
2023-03-03 16:36:39 +00:00
|
|
|
req *pulumirpc.ReadResourceRequest,
|
|
|
|
) (*pulumirpc.ReadResourceResponse, error) {
|
2023-12-12 12:19:42 +00:00
|
|
|
return nil, errors.New("Query mode does not support reading resources")
|
Implement query primitives in the engine
`pulumi query` is designed, essentially, as a souped-up `exec`. We
execute a query program, and add a few convenience constructs (e.g., the
default providers that give you access to things like `getStack`).
Early in the design process, we decided to not re-use the `up`/update
path, both to minimize risk to update operations, and to simplify the
implementation.
This commit will add this "parallel query universe" into the engine
package. In particular, this includes:
* `QuerySource`, which executes the language provider running the query
program, and providing it with some simple constructs, such as the
default provider, which provides access to `getStack`. This is much
like a very simplified `EvalSource`, though notably without any of the
planning/step execution machinery.
* `queryResmon`, which disallows all resource operations, except the
`Invoke` that retrieves the resource outputs of some stack's last
snapshot. This is much like a simplified `resmon`, but without any of
the provider resolution, and without and support for resource
operations generally.
* Various static functions that pull together miscellaneous things
needed to execute a query program. Notably, this includes gathering
language plugins.
2019-04-30 18:07:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// RegisterResource is invoked by a language process when a new resource has been allocated.
|
|
|
|
func (rm *queryResmon) RegisterResource(ctx context.Context,
|
2023-03-03 16:36:39 +00:00
|
|
|
req *pulumirpc.RegisterResourceRequest,
|
|
|
|
) (*pulumirpc.RegisterResourceResponse, error) {
|
2023-12-12 12:19:42 +00:00
|
|
|
return nil, errors.New("Query mode does not support creating, updating, or deleting resources")
|
Implement query primitives in the engine
`pulumi query` is designed, essentially, as a souped-up `exec`. We
execute a query program, and add a few convenience constructs (e.g., the
default providers that give you access to things like `getStack`).
Early in the design process, we decided to not re-use the `up`/update
path, both to minimize risk to update operations, and to simplify the
implementation.
This commit will add this "parallel query universe" into the engine
package. In particular, this includes:
* `QuerySource`, which executes the language provider running the query
program, and providing it with some simple constructs, such as the
default provider, which provides access to `getStack`. This is much
like a very simplified `EvalSource`, though notably without any of the
planning/step execution machinery.
* `queryResmon`, which disallows all resource operations, except the
`Invoke` that retrieves the resource outputs of some stack's last
snapshot. This is much like a simplified `resmon`, but without any of
the provider resolution, and without and support for resource
operations generally.
* Various static functions that pull together miscellaneous things
needed to execute a query program. Notably, this includes gathering
language plugins.
2019-04-30 18:07:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// RegisterResourceOutputs records some new output properties for a resource that have arrived after its initial
|
|
|
|
// provisioning. These will make their way into the eventual checkpoint state file for that resource.
|
|
|
|
func (rm *queryResmon) RegisterResourceOutputs(ctx context.Context,
|
2023-03-03 16:36:39 +00:00
|
|
|
req *pulumirpc.RegisterResourceOutputsRequest,
|
2024-01-17 09:35:20 +00:00
|
|
|
) (*emptypb.Empty, error) {
|
2023-12-12 12:19:42 +00:00
|
|
|
return nil, errors.New("Query mode does not support registering resource operations")
|
Implement query primitives in the engine
`pulumi query` is designed, essentially, as a souped-up `exec`. We
execute a query program, and add a few convenience constructs (e.g., the
default providers that give you access to things like `getStack`).
Early in the design process, we decided to not re-use the `up`/update
path, both to minimize risk to update operations, and to simplify the
implementation.
This commit will add this "parallel query universe" into the engine
package. In particular, this includes:
* `QuerySource`, which executes the language provider running the query
program, and providing it with some simple constructs, such as the
default provider, which provides access to `getStack`. This is much
like a very simplified `EvalSource`, though notably without any of the
planning/step execution machinery.
* `queryResmon`, which disallows all resource operations, except the
`Invoke` that retrieves the resource outputs of some stack's last
snapshot. This is much like a simplified `resmon`, but without any of
the provider resolution, and without and support for resource
operations generally.
* Various static functions that pull together miscellaneous things
needed to execute a query program. Notably, this includes gathering
language plugins.
2019-04-30 18:07:56 +00:00
|
|
|
}
|
2019-04-12 21:29:08 +00:00
|
|
|
|
|
|
|
// SupportsFeature the query resmon is able to have secrets passed to it, which may be arguments to invoke calls.
|
|
|
|
func (rm *queryResmon) SupportsFeature(ctx context.Context,
|
2023-03-03 16:36:39 +00:00
|
|
|
req *pulumirpc.SupportsFeatureRequest,
|
|
|
|
) (*pulumirpc.SupportsFeatureResponse, error) {
|
2019-04-12 21:29:08 +00:00
|
|
|
hasSupport := false
|
|
|
|
return &pulumirpc.SupportsFeatureResponse{
|
|
|
|
HasSupport: hasSupport,
|
|
|
|
}, nil
|
|
|
|
}
|
2019-08-27 17:10:51 +00:00
|
|
|
|
|
|
|
// syntheticProviderURN will create a "fake" URN for a resource provider in query mode. Query mode
|
|
|
|
// has no stack, no project, and no parent, so there is otherwise no way to generate a principled
|
|
|
|
// URN.
|
|
|
|
func syntheticProviderURN(goal *resource.Goal) resource.URN {
|
|
|
|
return resource.NewURN(
|
|
|
|
"query-stack", "query-project", "parent-type", goal.Type, goal.Name)
|
|
|
|
}
|