7b21b5db66
<!--- 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. --> Currently, when we detect that we've created a cycle in the dependency graph, we early-exit. This works well enough for simple cycles, but when early exiting is not sufficient (as when providing a resource output as an argument to another resource's inputs), we will still fail to resolve the full dependency graph. This PR introduces an exception-by-default, as any cycles represent an unsafe/invalid dependency graph and should be resolved manually. We also provide an escape hatch to fall back to current behavior, in case users would prefer to retain the ability to create unsafe dependency graphs (potentially introducing infinite hangs when resolving those graphs). Fixes https://github.com/pulumi/pulumi/issues/13551 ## 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. --> - [x] 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. --> |
||
---|---|---|
.. | ||
aliases | ||
asset | ||
chained_failure | ||
component_dependencies | ||
component_provider_resolution | ||
component_resource_list_of_providers | ||
component_resource_single_provider | ||
config | ||
delete_before_replace | ||
empty | ||
first_class_provider | ||
first_class_provider_invoke | ||
first_class_provider_unknown | ||
future_failure | ||
future_input | ||
ignore_changes | ||
inherit_defaults | ||
inheritance_translation | ||
inheritance_types | ||
input_type_mismatch | ||
input_values_for_outputs | ||
invalid_property_dependency | ||
invoke | ||
invoke_empty_return | ||
invoke_future | ||
invoke_types | ||
large_resource | ||
marshal_failure | ||
one_complex_resource | ||
one_resource | ||
output_all | ||
output_nested | ||
output_property_dependencies | ||
outputs_future | ||
preview | ||
property_dependencies | ||
property_renaming | ||
protect | ||
read | ||
remote_component_dependencies | ||
remote_component_providers | ||
replace_on_changes | ||
resource_op_bad_inputs | ||
resource_op_fail | ||
resource_thens | ||
runtime_settings | ||
source_position | ||
stack_output | ||
ten_resources | ||
types | ||
versions | ||
README.md | ||
__init__.py | ||
util.py |
README.md
Python Language Host Tests
The tests in this directory test the language host directly by posing as the engine and running programs in the same context that they would be run by the CLI. Programs run by these tests can create resources, read resource, invoke data sources, and generally do anything that a Pulumi program can do.
Language host tests provide a program to be run and an implementation
of the LanghostTest
class, which provides implementations for the
four resource monitor endpoints that the language host speaks to:
invoke
, for invoking data sources,read_resource
, for reading existing resources,register_resource
, for creating new resources,register_resource_outputs
, for registering outputs on component resources
Classes deriving from LanghostTest
can override any of these methods
to provide custom test functionality. This is commonly used to perform assertions
or place the language host in unexpected situations.
Adding a new test
To add a new language host test, you can:
- Create a new directory in this directory with the name of your test
- Place an
__init__.py
and__main__.py
in this directory.__init__.py
convinces Python that this directory is a module, while__main__.py
indicates to Python that this module is runnable. - Write your Pulumi program in
__main__.py
. If you want to do assertions, use theassert
keyword to do so. - Add a test file, which can have any name. In this test file you'll want to provide a
subclass of
LanghostTest
that drives your test. An example minimal test would be something like this:
from os import path
from ..util import LanghostTest
class EmptyTests(LanghostTest):
def test_empty(self):
self.run_test(
program=path.join(self.base_path(), "empty"), # If your test is in the empty/ subdirectory
expected_resource_count=0) # Assert there are 0 resource registrations
Your class can have any number of test_*
methods in them. Language host tests are launched by
invoking the run_test
method inherited from LanghostTest
. run_test
accepts the following
keyword arguments:
project
- The name of the project that will be exposed to the running programstack
- The name of the stack that will be exposed to the running programprogram
- A path to the program to be run, relative to the working directory.pwd
- The working directory to use.args
- Command-line arguments to pass to the program.config
- A dict of configuration keys and values to pass to the program.expected_resource_count
- The number of resources this test is expected to register.expected_error
- If non-None, the exact error text that is expected to be received.expected_stderr_contains
- If non-None, asserts that the given substring exists in stderr
If expected_error
is None, the expected error is asserted to be the empty string.
Note that your test method must begin with test_*
, since this is how Python discovers what
tests to run.
One additional thing to note is that this test harness explicitly ignores the registration
of the top-level Stack resource, pulumi:pulumi:Stack
, because it is annoying to write tests around.
All expected resource counts do not count this resource as a registration and overridden resource monitor
methods will never see a registration for pulumi:pulumi:Stack.