Merge branch 'master' into iwahbe/2715/add-pulumi-about-command
22
.readthedocs.yaml
Normal file
|
@ -0,0 +1,22 @@
|
|||
# .readthedocs.yaml
|
||||
|
||||
# Read the Docs configuration file
|
||||
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
||||
|
||||
# Required
|
||||
version: 2
|
||||
|
||||
# Build documentation in the developer-docs/ directory with Sphinx
|
||||
sphinx:
|
||||
configuration: developer-docs/conf.py
|
||||
|
||||
formats:
|
||||
- pdf
|
||||
|
||||
# Optionally set the version of Python and requirements required to build your docs
|
||||
python:
|
||||
version: "3.6"
|
||||
install:
|
||||
- requirements: developer-docs/requirements.txt
|
||||
|
||||
|
29
CHANGELOG.md
|
@ -1,6 +1,35 @@
|
|||
CHANGELOG
|
||||
=========
|
||||
|
||||
## 3.11.0 (2021-08-25)
|
||||
|
||||
### Improvements
|
||||
|
||||
- [auto/dotnet] - Add support for `--exact` and `--server` with `pulumi plugin install` via Automation API. BREAKING NOTE: If you are subclassing `Workspace` your `InstallPluginAsync` implementation will need to be updated to reflect the new `PluginInstallOptions` parameter.
|
||||
[#7762](https://github.com/pulumi/pulumi/pull/7796)
|
||||
|
||||
- [codegen/go] - Add helper function forms `$fnOutput` that accept
|
||||
`Input`s, return an `Output`, and wrap the underlying `$fn` call.
|
||||
This change addreses
|
||||
[#5758](https://github.com/pulumi/pulumi/issues/) for Go, making it
|
||||
easier to compose functions/datasources with Pulumi resources.
|
||||
[#7784](https://github.com/pulumi/pulumi/pull/7784)
|
||||
|
||||
- [sdk/python] - Speed up `pulumi up` on Python projects by optimizing
|
||||
`pip` invocations
|
||||
[#7819](https://github.com/pulumi/pulumi/pull/7819)
|
||||
|
||||
- [sdk/dotnet] - Support for calling methods.
|
||||
[#7582](https://github.com/pulumi/pulumi/pull/7582)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- [cli] - Avoid `missing go.sum entry for module` for new Go projects.
|
||||
[#7808](https://github.com/pulumi/pulumi/pull/7808)
|
||||
|
||||
- [codegen/schema] - Allow hyphen in schema path reference.
|
||||
[#7824](https://github.com/pulumi/pulumi/pull/7824)
|
||||
|
||||
## 3.10.3 (2021-08-19)
|
||||
### Improvements
|
||||
|
||||
|
|
|
@ -7,6 +7,3 @@
|
|||
|
||||
- [cli/about] - Add comand for debug information
|
||||
[#7817](https://github.com/pulumi/pulumi/pull/7817)
|
||||
|
||||
- [cli] - Avoid `missing go.sum entry for module` for new Go projects.
|
||||
[#7808](https://github.com/pulumi/pulumi/pull/7808)
|
||||
|
|
3
Makefile
|
@ -36,6 +36,9 @@ build:: generate
|
|||
build_debug:: generate
|
||||
cd pkg && go install -gcflags="all=-N -l" -ldflags "-X github.com/pulumi/pulumi/pkg/v3/version.Version=${VERSION}" ${PROJECT}
|
||||
|
||||
developer_docs::
|
||||
cd developer-docs && make html
|
||||
|
||||
install:: generate
|
||||
cd pkg && GOBIN=$(PULUMI_BIN) go install -ldflags "-X github.com/pulumi/pulumi/pkg/v3/version.Version=${VERSION}" ${PROJECT}
|
||||
|
||||
|
|
1
developer-docs/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
_build
|
28
developer-docs/Makefile
Normal file
|
@ -0,0 +1,28 @@
|
|||
SPHINXOPTS ?=
|
||||
SPHINXBUILD ?= sphinx-build
|
||||
SOURCEDIR = .
|
||||
BUILDDIR = _build
|
||||
|
||||
html: Makefile graphics
|
||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
|
||||
pdf: Makefile graphics
|
||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
|
||||
.PHONY: graphics Makefile
|
||||
|
||||
SVG_FILES = \
|
||||
providers/resource-lifecycle.svg \
|
||||
architecture/construct.svg \
|
||||
architecture/create.svg \
|
||||
architecture/delete-before-replace-graph.svg \
|
||||
architecture/delete-before-replace.svg \
|
||||
architecture/import.svg \
|
||||
architecture/replace.svg \
|
||||
architecture/same.svg \
|
||||
architecture/update.svg
|
||||
|
||||
%.svg: %.uml
|
||||
plantuml -tsvg $<
|
||||
|
||||
graphics: Makefile $(SVG_FILES)
|
23
developer-docs/architecture/construct.svg
Normal file
After Width: | Height: | Size: 6.5 KiB |
13
developer-docs/architecture/construct.uml
Normal file
|
@ -0,0 +1,13 @@
|
|||
@startuml
|
||||
participant "Language SDK" order 10
|
||||
box "Engine"
|
||||
participant "Resource Monitor" order 15
|
||||
end box
|
||||
participant "Resource Provider" order 30
|
||||
|
||||
"Language SDK" -> "Resource Monitor" ++ : RegisterResourceRequest(type, name, inputs, options)
|
||||
"Resource Monitor" -> "Resource Provider" ++ : ConstructRequest(monitor address, type, name, inputs, options)
|
||||
"Resource Provider" <--> "Resource Monitor": Component resource + child resource registrations
|
||||
"Resource Monitor" <- "Resource Provider" -- : ConstructResponse(outputs)
|
||||
"Language SDK" <- "Resource Monitor" -- : RegisterResourceResponse(urn, ID, new state)
|
||||
@enduml
|
33
developer-docs/architecture/create.svg
Normal file
After Width: | Height: | Size: 11 KiB |
23
developer-docs/architecture/create.uml
Normal file
|
@ -0,0 +1,23 @@
|
|||
@startuml
|
||||
participant "Language SDK" order 10
|
||||
box "Engine"
|
||||
participant "Resource Monitor" order 15
|
||||
participant "Step Generator" order 20
|
||||
participant "Step Executor" order 25
|
||||
end box
|
||||
participant "Resource Provider" order 30
|
||||
|
||||
"Language SDK" -> "Resource Monitor" ++ : RegisterResourceRequest(type, name, inputs, options)
|
||||
"Resource Monitor" -> "Step Generator" ++ : RegisterResourceEvent(type, name, inputs, options)
|
||||
"Step Generator" -> "Resource Provider" ++ : CheckRequest(type, inputs)
|
||||
"Step Generator" <- "Resource Provider" -- : CheckResponse(inputs', failures)
|
||||
"Step Generator" -> "Step Executor" --++ : CreateStep(inputs', options)
|
||||
note left
|
||||
This is fire-and-forget on the part of the step generator.
|
||||
The step will run in parallel with steps for other resources.
|
||||
end note
|
||||
"Step Executor" -> "Resource Provider" ++ : CreateRequest(type, inputs')
|
||||
"Step Executor" <- "Resource Provider" -- : CreateResponse(new state)
|
||||
"Resource Monitor" <- "Step Executor" -- : done(new state)
|
||||
"Language SDK" <- "Resource Monitor" -- : RegisterResourceResponse(urn, ID, new state)
|
||||
@enduml
|
35
developer-docs/architecture/delete-before-replace-graph.svg
Normal file
|
@ -0,0 +1,35 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="247px" preserveAspectRatio="none" style="width:175px;height:247px;background:#FFFFFF;" version="1.1" viewBox="0 0 175 247" width="175px" zoomAndPan="magnify"><defs><filter height="300%" id="f1xo3jf5eexdn" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0"/><feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3"/><feBlend in="SourceGraphic" in2="blurOut3" mode="normal"/></filter></defs><g><!--MD5=[770389ab9df153645bc6ef28055eb2b5]
|
||||
entity A--><rect fill="#FEFECE" filter="url(#f1xo3jf5eexdn)" height="36.4883" style="stroke:#A80036;stroke-width:1.5;" width="30" x="39" y="199"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="10" x="49" y="222.5352">A</text><!--MD5=[b2d39259b6aeabc16b394deeb0238426]
|
||||
entity B--><rect fill="#FEFECE" filter="url(#f1xo3jf5eexdn)" height="36.4883" style="stroke:#A80036;stroke-width:1.5;" width="28" x="8" y="103"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="8" x="18" y="126.5352">B</text><!--MD5=[16fab723be418f7eaf2ea4bd895a8e51]
|
||||
entity C--><rect fill="#FEFECE" filter="url(#f1xo3jf5eexdn)" height="36.4883" style="stroke:#A80036;stroke-width:1.5;" width="30" x="71" y="103"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="10" x="81" y="126.5352">C</text><!--MD5=[118f42602524ad482f02b27ef22fc383]
|
||||
entity D--><rect fill="#FEFECE" filter="url(#f1xo3jf5eexdn)" height="36.4883" style="stroke:#A80036;stroke-width:1.5;" width="30" x="7" y="7"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="10" x="17" y="30.5352">D</text><!--MD5=[68f82070d0aec4ff4b64d9b1102926da]
|
||||
entity E--><rect fill="#FEFECE" filter="url(#f1xo3jf5eexdn)" height="36.4883" style="stroke:#A80036;stroke-width:1.5;" width="28" x="72" y="7"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="8" x="82" y="30.5352">E</text><!--MD5=[22029b2902cbfefb11350e8ee6e306b3]
|
||||
entity F--><rect fill="#FEFECE" filter="url(#f1xo3jf5eexdn)" height="36.4883" style="stroke:#A80036;stroke-width:1.5;" width="28" x="135" y="7"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="8" x="145" y="30.5352">F</text><!--MD5=[72912e6cd343fd0b615113a50578b9b8]
|
||||
link E to C--><path d="M86,43.24 C86,58.48 86,80.81 86,97.46 " fill="none" id="E-to-C" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="86,102.87,90,93.87,86,97.87,82,93.87,86,102.87" style="stroke:#A80036;stroke-width:1.0;"/><!--MD5=[63e03b6ea79d913a67ba6fcf5a4ae973]
|
||||
link F to C--><path d="M137.44,43.24 C127.05,58.74 111.75,81.59 100.53,98.32 " fill="none" id="F-to-C" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="97.48,102.87,105.813,97.6201,100.2634,98.7163,99.1672,93.1667,97.48,102.87" style="stroke:#A80036;stroke-width:1.0;"/><!--MD5=[1454d5cde7bc0c276b7bdc83fba84c24]
|
||||
link C to A--><path d="M80.13,139.24 C74.9,154.61 67.21,177.2 61.53,193.89 " fill="none" id="C-to-A" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="59.83,198.87,66.5232,191.645,61.4454,194.1381,58.9522,189.0603,59.83,198.87" style="stroke:#A80036;stroke-width:1.0;"/><!--MD5=[5ebc1f44a7c66b9e925829b6b9c43293]
|
||||
link D to B--><path d="M22,43.24 C22,58.48 22,80.81 22,97.46 " fill="none" id="D-to-B" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="22,102.87,26,93.87,22,97.87,18,93.87,22,102.87" style="stroke:#A80036;stroke-width:1.0;"/><!--MD5=[2c777c0c38089c390787dfc0786ecb92]
|
||||
link B to A--><path d="M27.87,139.24 C33.1,154.61 40.79,177.2 46.47,193.89 " fill="none" id="B-to-A" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="48.17,198.87,49.0478,189.0603,46.5546,194.1381,41.4768,191.645,48.17,198.87" style="stroke:#A80036;stroke-width:1.0;"/><!--MD5=[6f1b4fca46cfefae17b5bfbc8573426e]
|
||||
@startuml
|
||||
agent A
|
||||
agent B
|
||||
agent C
|
||||
agent D
|
||||
agent E
|
||||
agent F
|
||||
|
||||
E - -> C
|
||||
F - -> C
|
||||
C - -> A
|
||||
D - -> B
|
||||
B - -> A
|
||||
@enduml
|
||||
|
||||
PlantUML version 1.2021.9(Sun Jul 25 03:13:56 PDT 2021)
|
||||
(GPL source distribution)
|
||||
Java Runtime: OpenJDK Runtime Environment
|
||||
JVM: OpenJDK 64-Bit Server VM
|
||||
Default Encoding: UTF-8
|
||||
Language: en
|
||||
Country: US
|
||||
--></g></svg>
|
After Width: | Height: | Size: 4.5 KiB |
14
developer-docs/architecture/delete-before-replace-graph.uml
Normal file
|
@ -0,0 +1,14 @@
|
|||
@startuml
|
||||
agent A
|
||||
agent B
|
||||
agent C
|
||||
agent D
|
||||
agent E
|
||||
agent F
|
||||
|
||||
E --> C
|
||||
F --> C
|
||||
C --> A
|
||||
D --> B
|
||||
B --> A
|
||||
@enduml
|
37
developer-docs/architecture/delete-before-replace.svg
Normal file
After Width: | Height: | Size: 14 KiB |
27
developer-docs/architecture/delete-before-replace.uml
Normal file
|
@ -0,0 +1,27 @@
|
|||
@startuml
|
||||
participant "Language SDK" order 10
|
||||
box "Engine"
|
||||
participant "Resource Monitor" order 15
|
||||
participant "Step Generator" order 20
|
||||
participant "Step Executor" order 25
|
||||
end box
|
||||
participant "Resource Provider" order 30
|
||||
|
||||
"Language SDK" -> "Resource Monitor" ++ : RegisterResourceRequest(type, name, inputs, options)
|
||||
"Resource Monitor" -> "Step Generator" ++ : RegisterResourceEvent(type, name, inputs, options)
|
||||
"Step Generator" -> "Resource Provider" ++ : CheckRequest(type, inputs, old inputs)
|
||||
"Step Generator" <- "Resource Provider" -- : CheckResponse(inputs', failures)
|
||||
"Step Generator" -> "Resource Provider" ++ : DiffRequest(type, inputs', old state, options)
|
||||
"Step Generator" <- "Resource Provider" -- : DiffResponse(diffs)
|
||||
"Step Generator" -> "Step Executor" --++ : [DeleteStep(old state), CreateStep(inputs', options)]
|
||||
note left
|
||||
This is fire-and-forget on the part of the step generator.
|
||||
The steps will run in parallel with steps for other resources.
|
||||
end note
|
||||
"Step Executor" -> "Resource Provider" ++ : DeleteRequest(type, old state)
|
||||
"Step Executor" <- "Resource Provider" -- : DeleteResponse()
|
||||
"Step Executor" -> "Resource Provider" ++ : CreateRequest(type, inputs', old state)
|
||||
"Step Executor" <- "Resource Provider" -- : CreateResponse(new state)
|
||||
"Resource Monitor" <- "Step Executor" -- : done(new state)
|
||||
"Language SDK" <- "Resource Monitor" -- : RegisterResourceResponse(urn, ID, new state)
|
||||
@enduml
|
35
developer-docs/architecture/import.svg
Normal file
After Width: | Height: | Size: 12 KiB |
25
developer-docs/architecture/import.uml
Normal file
|
@ -0,0 +1,25 @@
|
|||
@startuml
|
||||
participant "Language SDK" order 10
|
||||
box "Engine"
|
||||
participant "Resource Monitor" order 15
|
||||
participant "Step Generator" order 20
|
||||
participant "Step Executor" order 25
|
||||
end box
|
||||
participant "Resource Provider" order 30
|
||||
|
||||
"Language SDK" -> "Resource Monitor" ++ : RegisterResourceRequest(type, name, inputs, options)
|
||||
"Resource Monitor" -> "Step Generator" ++ : RegisterResourceEvent(type, name, inputs, options)
|
||||
"Step Generator" -> "Step Executor" --++ : ImportStep(inputs, options)
|
||||
note left
|
||||
This is fire-and-forget on the part of the step generator.
|
||||
The step will run in parallel with steps for other resources.
|
||||
end note
|
||||
"Step Executor" -> "Resource Provider" ++ : ReadRequest(type, id)
|
||||
"Step Executor" <- "Resource Provider" -- : ReadResponse(current inputs, current state)
|
||||
"Step Executor" -> "Resource Provider" ++ : CheckRequest(type, inputs, current inputs)
|
||||
"Step Executor" <- "Resource Provider" -- : CheckResponse(inputs', failures)
|
||||
"Step Executor" -> "Resource Provider" ++ : DiffRequest(type, inputs', current state, options)
|
||||
"Step Executor" <- "Resource Provider" -- : DiffResponse(diffs)
|
||||
"Resource Monitor" <- "Step Executor" -- : done(current state)
|
||||
"Language SDK" <- "Resource Monitor" -- : RegisterResourceResponse(urn, ID, current state)
|
||||
@enduml
|
19
developer-docs/architecture/overview.md
Normal file
|
@ -0,0 +1,19 @@
|
|||
# Pulumi Architecture Overview
|
||||
|
||||
Broadly speaking, Pulumi is composed of five components:
|
||||
|
||||
1. The deployment engine
|
||||
2. State storage backends
|
||||
3. Language SDKs
|
||||
4. Resource providers
|
||||
5. Package schemas and code generators
|
||||
|
||||
## The Deployment Engine
|
||||
|
||||
## State Storage Backends
|
||||
|
||||
## Language SDKs
|
||||
|
||||
## Resource Providers
|
||||
|
||||
## Package Schemas and Code Generators
|
40
developer-docs/architecture/replace.svg
Normal file
After Width: | Height: | Size: 16 KiB |
30
developer-docs/architecture/replace.uml
Normal file
|
@ -0,0 +1,30 @@
|
|||
@startuml
|
||||
participant "Language SDK" order 10
|
||||
box "Engine"
|
||||
participant "Resource Monitor" order 15
|
||||
participant "Step Generator" order 20
|
||||
participant "Step Executor" order 25
|
||||
end box
|
||||
participant "Resource Provider" order 30
|
||||
|
||||
"Language SDK" -> "Resource Monitor" ++ : RegisterResourceRequest(type, name, inputs, options)
|
||||
"Resource Monitor" -> "Step Generator" ++ : RegisterResourceEvent(type, name, inputs, options)
|
||||
"Step Generator" -> "Resource Provider" ++ : CheckRequest(type, inputs, old inputs)
|
||||
"Step Generator" <- "Resource Provider" -- : CheckResponse(inputs', failures)
|
||||
"Step Generator" -> "Resource Provider" ++ : DiffRequest(type, inputs', old state, options)
|
||||
"Step Generator" <- "Resource Provider" -- : DiffResponse(diffs)
|
||||
"Step Generator" -> "Step Executor" --++ : CreateStep(inputs', old state, options)
|
||||
note left
|
||||
This is fire-and-forget on the part of the step generator.
|
||||
The step will run in parallel with steps for other resources.
|
||||
end note
|
||||
"Step Executor" -> "Resource Provider" ++ : CreateRequest(type, inputs', old state)
|
||||
"Step Executor" <- "Resource Provider" -- : CreateResponse(new state)
|
||||
"Resource Monitor" <- "Step Executor" -- : done(new state)
|
||||
"Language SDK" <- "Resource Monitor" -- : RegisterResourceResponse(urn, ID, new state)
|
||||
...Pulumi program exits...
|
||||
"Step Generator" -> "Step Generator": Generate delete steps
|
||||
"Step Generator" -> "Step Executor" ++ : DeleteStep(old state)
|
||||
"Step Executor" -> "Resource Provider" ++ : DeleteRequest(type, old state)
|
||||
"Step Executor" <- "Resource Provider" -- : DeleteResponse()
|
||||
@enduml
|
255
developer-docs/architecture/resource-registration.md
Normal file
|
@ -0,0 +1,255 @@
|
|||
# Resource Registration
|
||||
|
||||
A Pulumi program declares the desired states of its stack's resources by sending `RegisterResource` requests to the
|
||||
Pulumi engine. Each `RegisterResource` request contains the type, name, and parent (if any) of the resource, a
|
||||
reference to the provider instance that manages the resource (where an empty reference indicates that the resource
|
||||
uses the default provider instance for its package + version), the values of the resource's input properties, and
|
||||
any options that apply to the resource. The engine decides what step to take in order to drive a resource to its
|
||||
goal state by diffing the resource's current state as present in the statefile with its desired state. If there is
|
||||
no current state, the resource is created. Otherwise, the engine calls the resource's provider's `Diff` method to
|
||||
determine wither the resource is unchanged, updated, or replaced. Once the required action (or actions, in the case
|
||||
of a replacement) has been determined, the engine calls the resource's provider's `Create`, `Update`, or `Delete`
|
||||
methods to perform it. After the action completes, the engine returns the new state of the resource to the Pulumi
|
||||
program.
|
||||
|
||||
Although we typically treat the engine as a single unit, in the case of resource registrations it helps to break it
|
||||
down into a few of its internal components: the resource monitor, the step generator, and the step executor. Each
|
||||
of these components is a participant in the response to a `RegisterResourceRequest`.
|
||||
|
||||
## The Resource Monitor
|
||||
|
||||
The resource monitor provides serves the `ResourceMonitor` gRPC interface, and provides a shim between language SDKs
|
||||
and the rest of the engine. There is a single resource monitor per deployment. As the engine's feature set has grown,
|
||||
the resource monitor has taken on responsibilities beyond its original use as a simple marshaling/unmarshaling layer.
|
||||
It is now responsible for handling default providers (providers for resource registrations that do not reference a
|
||||
provider instance) and for dispatching `RegisterResourceRequest`s for multi-language components into appropriate
|
||||
`Construct` calls.
|
||||
|
||||
When the resource monitor receives a resource registration, it does the following:
|
||||
|
||||
1. Unmarshals data from the gRPC wire format to the engine's internal representation.
|
||||
2. If the registration request does not name a provider instance, handles the resolution of the resource's default
|
||||
provider.
|
||||
3. If the request is for a multi-language component, dispatches a `Construct` call to the component's provider and
|
||||
waits for the result.
|
||||
4. If the request is not for a multi-langauge component, sends a `RegisterResourceEvent` to the step generator and
|
||||
waits for the result.
|
||||
5. Marshals the result of the `Construct` call or `RegisterResourceEvent` from the engine's internal representation
|
||||
to the gRPC wire format and returns from the RPC call.
|
||||
|
||||
### Default Providers
|
||||
|
||||
Default providers demand some amount of special attention. A _default provider_ for a package and version is the
|
||||
provider instance that is used for resources at that package and version that do not otherwise reference a provider
|
||||
instance when they are registered. For example, consider the following program that creates an AWS S3 bucket:
|
||||
|
||||
```typescript
|
||||
import * as aws from "@pulumi/aws";
|
||||
|
||||
new aws.s3.Bucket("myBucket");
|
||||
```
|
||||
|
||||
The constructor call will become a `RegisterResourceRequest` like:
|
||||
|
||||
```
|
||||
RegisterResourceRequest{
|
||||
type: "aws:s3/bucket:Bucket",
|
||||
name: "myBucket",
|
||||
parent: "urn:pulumi:dev::project::pulumi:pulumi:Stack::project",
|
||||
custom: true,
|
||||
object: {},
|
||||
version: "4.16.0",
|
||||
}
|
||||
```
|
||||
|
||||
Becuase this request does not contain a value for the `provider` field, it will use the default provider for the
|
||||
`aws` package at version 4.16.0. The resource monitor ensures that only a single default provider instance exists
|
||||
for each particular package version, and only creates default provider instances if they are needed. Default provider
|
||||
instances are registered by synthesizing an appropriate `RegisterResourceEvent` with input properties sourced from the
|
||||
stack's configuration values for the provider's package. In the example above, the AWS default provider would be
|
||||
configured using any stack configuration values whose keys begin with `aws:` (e.g. `aws:region`).
|
||||
|
||||
If we change the program slightly to create and reference a provider instance, the default provider will no longer
|
||||
be used:
|
||||
|
||||
```typescript
|
||||
import * as aws from "@pulumi/aws";
|
||||
|
||||
const usWest2 = new aws.Provider("us-west-2", {region: "us-west-2"});
|
||||
|
||||
new aws.s3.Bucket("myBucket", {}, {provider: usWest2});
|
||||
```
|
||||
|
||||
The constructor call will become a `RegisterResourceRequest` like:
|
||||
|
||||
```
|
||||
RegisterResourceRequest{
|
||||
type: "aws:s3/bucket:Bucket",
|
||||
name: "myBucket",
|
||||
parent: "urn:pulumi:dev::project::pulumi:pulumi:Stack::project",
|
||||
custom: true,
|
||||
object: {},
|
||||
provider: "urn:pulumi:dev::vpc-2::pulumi:providers:aws::us-west-2::308b79ee-8249-40fb-a203-de190cb8faa8",
|
||||
version: "4.16.0",
|
||||
}
|
||||
```
|
||||
|
||||
Note that this request _does_ contain a value for the `provider` field.
|
||||
|
||||
## The Step Generator
|
||||
|
||||
The step generator is responsible for processing `RegisterResourceEvent`s from the resource monitor. The generator
|
||||
implements the core logic that determines which actions to take in order to drive the actual state of a resource to
|
||||
its desired state as represented by the input properties in its `RegisterResourceEvent`. In order to simplify
|
||||
reasoning about the actual state of a stack's resources, the step generator processes `RegisterResourceEvent`s
|
||||
serially. It is important to note that this approach puts the step generator on a deployment's critical path, so
|
||||
any significant blocking in the step generator may slow down deployments accordingly. In the case of updates, step
|
||||
generator latency is generally insignificant compared to the time spent performing resource operations, but this is
|
||||
not the case for updates where most resources are unchanged or for previews, which spend very little time in resource
|
||||
providers in general.
|
||||
|
||||
When the step generator receives a `RegisterResourceEvent`, it does the following:
|
||||
|
||||
1. Generate a URN for the resource using the resource's type, name, and parent.
|
||||
2. Look up the existing state for the resource, if any. If the event contains aliases for the resource, this includes
|
||||
checking for existing state under those aliases. It is an error if a resource's aliases match multiple existing
|
||||
states.
|
||||
3. Pre-process input properties for ignored changes by setting any properties mentioned in the event's ignore changes
|
||||
list to their old value (if any)
|
||||
4. If the event indicates that the resource should be imported, issue an `ImportStep` to the step executor and return.
|
||||
5. Call the resource's provider's `Check` method with the event's input properties and the resource's existing inputs,
|
||||
if any. The existing inputs may be used by the provider to repopulate default values for input properties that are
|
||||
automatically generated when the resource is created but should not be changed with subsequent updates (e.g.
|
||||
automatically generated names). `Check` returns a pre-processed bag of input values to be used with later calls to
|
||||
`Diff`, `Create`, and `Update`.
|
||||
6. Invoke any analyzers for the stack to perform additional validation of the resource's input properties.
|
||||
7. If the resource has no existing state, it is being created. Issue a `CreateStep` to the step executor and return.
|
||||
8. Diff the resource in order to determine whether it must be updated, replaced, delete-before-replaced, or has no
|
||||
changes. Diffing is covered in detail later on, but typically consists of calling the reosource's provider's
|
||||
`Diff` method with the checked inputs from step 5.
|
||||
9. If the resource has no changes, issue a `SameStep` to the step executor and return.
|
||||
10. If the resource is not being replaced, issue an `UpdateStep` to the step executor and return.
|
||||
11. If the resource is being replaced, call the resource's provider's `Check` method again, but with no existing
|
||||
inputs. This call ensures that the input properties used to create the replacement resource do not reuse
|
||||
generated defaults from the existing resource.
|
||||
12. If the replacement resource is being created before the original is deleted (a normal replacement), issue a
|
||||
`CreateStep` and a `DeleteStep` to the step executor and return.
|
||||
13. At this point, the resource must be deleted before its replacement is created (this is the "delete-before-replace"
|
||||
case). Calculate the set of dependent resources that must be deleted prior to deleting the resource being replaced.
|
||||
The details of this calculation are covered in a later section. Once the set of deletions has been calculated,
|
||||
issue a sequence of `DeleteStep`s followed by a single `CreateStep` to the step executor.
|
||||
|
||||
Note that all steps that are issued to the step generator are fire-and-forget. Once steps have been issues, the step
|
||||
generator moves on to process the next `RegisterResourceEvent`. It is the responsibility of the step executor to
|
||||
communicate the results of each step back to the resource monitor.
|
||||
|
||||
Once the Pulumi program has exited, the step generator determines which existing resources must be deleted by taking
|
||||
the difference between the set of registered resources and the set of existing resources. These resources are scheduled
|
||||
for deletion by first sorting the list of resources to delete using the topological order of their reverse-dependency
|
||||
grapth, then decomposing the list into a list of lists where each list can be executed in parallel but a previous list
|
||||
must be executed to completion before advancing to the next list.
|
||||
|
||||
In lieu of tracking per-step dependencies and orienting the step executor around these dependencies, this approach
|
||||
provides a conservative approximation of what deletions can safely occur in parallel. The insight here is that the
|
||||
resource dependency graph is a partially-ordered set and all partially-ordered sets can be easily decomposed into
|
||||
antichains--subsets of the set that are all not comparable to one another (in this definition, "not comparable"
|
||||
means "do not depend on one another").
|
||||
|
||||
The algorithm for decomposing a poset into antichains is:
|
||||
|
||||
1. While there exist elements in the poset,
|
||||
a. There must exist at least one "maximal" element of the poset. Let `E_max` be those elements.
|
||||
b. Remove all elements E_max from the poset. `E_max` is an antichain.
|
||||
c. Goto 1.
|
||||
|
||||
Translated to a resource dependency graph:
|
||||
|
||||
1. While the set of condemned resources is not empty:
|
||||
a. Remove all resources with no outgoing edges from the graph and add them to the current antichain.
|
||||
b. Goto 1.
|
||||
|
||||
The resulting list of antichains is a list of list of delete steps that can be safely executed in parallel. Since
|
||||
deletes must be processed in reverse order (so that resources are not deleted prior to their dependents), the step
|
||||
generator reverses the list and then issues each sublist to the step executor.
|
||||
|
||||
### Resource Diffing
|
||||
|
||||
Although resource diffing is simple in most cases, there are several possibilities that the step generator must
|
||||
consider as part of performing a diff. The algorithm for diffing a resource is outlined here.
|
||||
|
||||
1. If the resource has been marked for replacement out of band (e.g. by the use of the `--target-replace` command-line
|
||||
option of the Pulumi CLI), the resource must be replaced.
|
||||
2. If the resource's provider has changed, the resource must be replaced. Default providers are allowed to change
|
||||
without requiring replacement if and only if the provider's configuration allows the new default provider to continue
|
||||
to manage existing resources (this is intended to allow default providers to be upgraded without requiring that
|
||||
all the resources they manage are replaced).
|
||||
3. If the engine is configured to use pre-1.0-style diffs, compare the resource's old and new inputs. If the old and
|
||||
new inputs differ, the resource must be updated.
|
||||
4. Otherwise, call the resource's provider's `Diff` method with the resource's new inputs, old state, and ignore changes
|
||||
set to determine whether the resource has changed, and if so, if it must be replaced.
|
||||
|
||||
Once the diff has been calculated, the step generator applies any replace-on-change options specified by the
|
||||
resource. These options force a resource to require that it is replaced if any of a particular set of properties has
|
||||
changed.
|
||||
|
||||
### Dependent Replacements
|
||||
|
||||
When a resource must be deleted before it is replaced--whether this is required by the resource's provider or is forced
|
||||
using the `deleteBeforeReplace` resource option--it may be necessary to first delete dependent resources. The step
|
||||
generator does this by taking the complete set of transitive dependents on the resource under consideration and
|
||||
removing any resources that would not be replaced by changes to their dependencies. It determines whether or not a
|
||||
resource must be replaced by substituting unknowns for any input properties that may change due to deletion of the
|
||||
resources their value depends on and calling the resource's provider's `Diff` method.
|
||||
|
||||
This is perhaps clearer when described by example. Consider the following dependency graph:
|
||||
|
||||
![Delete-before-replace example graph](./delete-before-replace-graph.svg)
|
||||
|
||||
In this graph, all of B, C, D, E, and F transitively depend on A. It may be the case,however, that changes to the
|
||||
specific properties of any of those resources R that would occur if a resource on the path to A were deleted and
|
||||
recreated may not cause R to be replaced. For example, the edge from B to A may be a simple `dependsOn` edge such that
|
||||
a change to B does not actually influence any of B's input properties. More commonly, the edge from B to A may be due
|
||||
to a property from A being used as the input to a property of B that does not require B to be replaced upon a change.
|
||||
In these cases, neither B nor D would need to be deleted before A could be deleted.
|
||||
|
||||
## The Step Executor
|
||||
|
||||
The step executor is responsible for executing sequences of steps (called "chains") that perform the resource actions
|
||||
for a deployment. These chains are issued by the step generator, and most often consist of a single step. While the
|
||||
steps the make up a chain must be performed serially, chains may be executed in parallel. The step executor uses a
|
||||
(potentially infinite) pool of workers to execute steps. Once a step completes, the step executor communicates its
|
||||
results to the resource monitor if necessary. If a step fails, the step executor notes the failure and cancels the
|
||||
deployment. Once the Pulumi program has exited and the step generator has issued all required deletions, the step
|
||||
executor waits for all outstanding steps to complete and then returns.
|
||||
|
||||
## Example Resource Registration Sequences
|
||||
|
||||
### Custom Resources
|
||||
|
||||
Each of the diagrams below demonstrates a sequence of events that occur when a custom resource is registered. Examples
|
||||
are given for each possible action: create, update, replace, delete-before-replace, import, and no change.
|
||||
|
||||
#### Create
|
||||
![Create diagram](./create.svg)
|
||||
|
||||
#### Update
|
||||
![Update diagram](./update.svg)
|
||||
|
||||
#### Replace
|
||||
![Replace diagram](./replace.svg)
|
||||
|
||||
#### Delete-before-replace
|
||||
![Delete-before-replace diagram](./delete-before-replace.svg)
|
||||
|
||||
#### Import
|
||||
![Import diagram](./import.svg)
|
||||
|
||||
#### No change
|
||||
![No change diagram](./same.svg)
|
||||
|
||||
### Multi-language Components
|
||||
|
||||
The diagram below illustrates the sequence of events that occurs when a multi-language component is registered. The
|
||||
registration of the component's children is elided.
|
||||
|
||||
![Multi-language component construction](./construct.svg)
|
33
developer-docs/architecture/same.svg
Normal file
After Width: | Height: | Size: 11 KiB |
23
developer-docs/architecture/same.uml
Normal file
|
@ -0,0 +1,23 @@
|
|||
@startuml
|
||||
participant "Language SDK" order 10
|
||||
box "Engine"
|
||||
participant "Resource Monitor" order 15
|
||||
participant "Step Generator" order 20
|
||||
participant "Step Executor" order 25
|
||||
end box
|
||||
participant "Resource Provider" order 30
|
||||
|
||||
"Language SDK" -> "Resource Monitor" ++ : RegisterResourceRequest(type, name, inputs, options)
|
||||
"Resource Monitor" -> "Step Generator" ++ : RegisterResourceEvent(type, name, inputs, options)
|
||||
"Step Generator" -> "Resource Provider" ++ : CheckRequest(type, inputs, old inputs)
|
||||
"Step Generator" <- "Resource Provider" -- : CheckResponse(inputs', failures)
|
||||
"Step Generator" -> "Resource Provider" ++ : DiffRequest(type, inputs', old state)
|
||||
"Step Generator" <- "Resource Provider" -- : DiffResponse(diffs)
|
||||
"Step Generator" -> "Step Executor" --++ : SameStep(inputs', old state, options)
|
||||
note left
|
||||
This is fire-and-forget on the part of the step generator.
|
||||
The step will run in parallel with steps for other resources.
|
||||
end note
|
||||
"Resource Monitor" <- "Step Executor" -- : done(old state)
|
||||
"Language SDK" <- "Resource Monitor" -- : RegisterResourceResponse(urn, ID, old tate)
|
||||
@enduml
|
35
developer-docs/architecture/update.svg
Normal file
After Width: | Height: | Size: 12 KiB |
25
developer-docs/architecture/update.uml
Normal file
|
@ -0,0 +1,25 @@
|
|||
@startuml
|
||||
participant "Language SDK" order 10
|
||||
box "Engine"
|
||||
participant "Resource Monitor" order 15
|
||||
participant "Step Generator" order 20
|
||||
participant "Step Executor" order 25
|
||||
end box
|
||||
participant "Resource Provider" order 30
|
||||
|
||||
"Language SDK" -> "Resource Monitor" ++ : RegisterResourceRequest(type, name, inputs, options)
|
||||
"Resource Monitor" -> "Step Generator" ++ : RegisterResourceEvent(type, name, inputs, options)
|
||||
"Step Generator" -> "Resource Provider" ++ : CheckRequest(type, inputs, old inputs)
|
||||
"Step Generator" <- "Resource Provider" -- : CheckResponse(inputs', failures)
|
||||
"Step Generator" -> "Resource Provider" ++ : DiffRequest(type, inputs', old state, options)
|
||||
"Step Generator" <- "Resource Provider" -- : DiffResponse(diffs)
|
||||
"Step Generator" -> "Step Executor" --++ : UpdateStep(inputs', old state, options)
|
||||
note left
|
||||
This is fire-and-forget on the part of the step generator.
|
||||
The step will run in parallel with steps for other resources.
|
||||
end note
|
||||
"Step Executor" -> "Resource Provider" ++ : UpdateRequest(type, inputs', old state)
|
||||
"Step Executor" <- "Resource Provider" -- : UpdateResponse(new state)
|
||||
"Resource Monitor" <- "Step Executor" -- : done(new state)
|
||||
"Language SDK" <- "Resource Monitor" -- : RegisterResourceResponse(urn, ID, new state)
|
||||
@enduml
|
19
developer-docs/build.md
Normal file
|
@ -0,0 +1,19 @@
|
|||
# Building the Docs
|
||||
|
||||
In order to build the devloper documentation:
|
||||
|
||||
1. Install [PlantUML](https://plantuml.com). On macOS, this can be done via `brew install plantuml`.
|
||||
2. Install the requirements for Sphinx:
|
||||
|
||||
```bash
|
||||
$ pip install requirements.txt
|
||||
```
|
||||
|
||||
3. Run `make` to build the HTML documentation:
|
||||
|
||||
```bash
|
||||
$ make
|
||||
```
|
||||
|
||||
This will regenerate any out-of-date SVGs and build the a local version of the HTML documentation. The documentation
|
||||
can also be built from the repository root by running `make developer_docs`.
|
55
developer-docs/conf.py
Normal file
|
@ -0,0 +1,55 @@
|
|||
# Configuration file for the Sphinx documentation builder.
|
||||
#
|
||||
# This file only contains a selection of the most common options. For a full
|
||||
# list see the documentation:
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
||||
|
||||
# -- Path setup --------------------------------------------------------------
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#
|
||||
# import os
|
||||
# import sys
|
||||
# sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
project = 'Pulumi'
|
||||
copyright = '2021, Pulumi Corporation'
|
||||
author = 'Pulumi'
|
||||
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
'sphinx.ext.autosectionlabel',
|
||||
'sphinx_tabs.tabs',
|
||||
'myst_parser',
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This pattern also affects html_static_path and html_extra_path.
|
||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
32
developer-docs/index.md
Normal file
|
@ -0,0 +1,32 @@
|
|||
# Pulumi Developer Documentation
|
||||
|
||||
Welcome to the Pulumi developer documentation! This documentation provides details on Pulumi internals, including but
|
||||
not limited to:
|
||||
|
||||
- How to build and test Pulumi
|
||||
- Pulumi architectural details
|
||||
- Specifications
|
||||
|
||||
Use the navigation bar to the left to browse the docs.
|
||||
|
||||
```{toctree}
|
||||
:hidden:
|
||||
:caption: System Architecture
|
||||
|
||||
architecture/overview
|
||||
architecture/resource-registration
|
||||
```
|
||||
|
||||
```{toctree}
|
||||
:hidden:
|
||||
:caption: Resource Providers
|
||||
|
||||
providers/implementers-guide
|
||||
```
|
||||
|
||||
```{toctree}
|
||||
:hidden:
|
||||
:caption: Meta
|
||||
|
||||
build
|
||||
```
|
|
@ -338,7 +338,7 @@ last refereshed state.
|
|||
The diagram below summarizes the custom resource lifecycle. Detailed descriptions of each
|
||||
resource operation follow.
|
||||
|
||||
![Custom Resource Lifeycle Diagram](./resource_lifecycle.svg)
|
||||
![Custom Resource Lifeycle Diagram](./resource-lifecycle.svg)
|
||||
|
||||
### Lifecycle Methods
|
||||
|
82
developer-docs/providers/resource-lifecycle.svg
Normal file
|
@ -0,0 +1,82 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="795px" preserveAspectRatio="none" style="width:1385px;height:795px;background:#FFFFFF;" version="1.1" viewBox="0 0 1385 795" width="1385px" zoomAndPan="magnify"><defs><filter height="300%" id="f1ht2b1gslamyn" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0"/><feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3"/><feBlend in="SourceGraphic" in2="blurOut3" mode="normal"/></filter></defs><g><ellipse cx="453" cy="16" fill="#000000" filter="url(#f1ht2b1gslamyn)" rx="10" ry="10" style="stroke:none;stroke-width:1.0;"/><rect fill="#FEFECE" filter="url(#f1ht2b1gslamyn)" height="150.4883" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="256" x="7" y="368"/><rect fill="#FFFFFF" height="118" rx="12.5" ry="12.5" style="stroke:#FFFFFF;stroke-width:1.0;" width="250" x="10" y="397.4883"/><line style="stroke:#A80036;stroke-width:1.5;" x1="7" x2="263" y1="394.4883" y2="394.4883"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="34" x="118" y="386.5352">Read</text><rect fill="#FEFECE" filter="url(#f1ht2b1gslamyn)" height="40" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="228" x="19" y="406.4883"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="218" x="24" y="431.7793">Read(reg.URN, reg.ID, reg.State)</text><ellipse cx="133" cy="492.4883" filter="url(#f1ht2b1gslamyn)" rx="10" ry="10" style="stroke:#000000;stroke-width:1.0;fill:none;"/><ellipse cx="133.5" cy="492.9883" fill="#000000" rx="6" ry="6" style="stroke:none;stroke-width:1.0;"/><!--MD5=[a9f1eddd24a2a537be099c93a63c087b]
|
||||
link read_read to *end*Read--><path d="M133,446.6883 C133,456.4483 133,468.1083 133,477.0783 " fill="none" id="read_read-to-*end*Read" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="133,482.2883,137,473.2883,133,477.2883,129,473.2883,133,482.2883" style="stroke:#A80036;stroke-width:1.0;"/><rect fill="#FEFECE" filter="url(#f1ht2b1gslamyn)" height="302.4883" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="310" x="298" y="292"/><rect fill="#FFFFFF" height="270" rx="12.5" ry="12.5" style="stroke:#FFFFFF;stroke-width:1.0;" width="304" x="301" y="321.4883"/><line style="stroke:#A80036;stroke-width:1.5;" x1="298" x2="608" y1="318.4883" y2="318.4883"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="46" x="430" y="310.5352">Import</text><rect fill="#FEFECE" filter="url(#f1ht2b1gslamyn)" height="40" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="159" x="371.5" y="330.4883"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="149" x="376.5" y="355.7793">Read(reg.URN, reg.ID)</text><rect fill="#FEFECE" filter="url(#f1ht2b1gslamyn)" height="40" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="282" x="310" y="406.4883"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="272" x="315" y="431.7793">Check(reg.URN, reg.Inputs, read.Inputs)</text><rect fill="#FEFECE" filter="url(#f1ht2b1gslamyn)" height="40" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="271" x="315.5" y="482.4883"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="261" x="320.5" y="507.7793">Diff(reg.URN, check.Inputs, read.State)</text><ellipse cx="451" cy="568.4883" filter="url(#f1ht2b1gslamyn)" rx="10" ry="10" style="stroke:#000000;stroke-width:1.0;fill:none;"/><ellipse cx="451.5" cy="568.9883" fill="#000000" rx="6" ry="6" style="stroke:none;stroke-width:1.0;"/><!--MD5=[ae6d5a98713f46cd29b3aff73c0432aa]
|
||||
link import_read to import_check--><path d="M451,370.5483 C451,379.8783 451,391.2283 451,401.1783 " fill="none" id="import_read-to-import_check" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="451,406.2383,455,397.2383,451,401.2383,447,397.2383,451,406.2383" style="stroke:#A80036;stroke-width:1.0;"/><!--MD5=[430f2e2903cceea4610401c9d1b5b4d3]
|
||||
link import_check to import_diff--><path d="M451,446.5483 C451,455.8783 451,467.2283 451,477.1783 " fill="none" id="import_check-to-import_diff" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="451,482.2383,455,473.2383,451,477.2383,447,473.2383,451,482.2383" style="stroke:#A80036;stroke-width:1.0;"/><!--MD5=[95fe03e3183800fd46e941677e7205f9]
|
||||
link import_diff to *end*Import--><path d="M451,522.6883 C451,532.4483 451,544.1083 451,553.0783 " fill="none" id="import_diff-to-*end*Import" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="451,558.2883,455,549.2883,451,553.2883,447,549.2883,451,558.2883" style="stroke:#A80036;stroke-width:1.0;"/><rect fill="#FEFECE" filter="url(#f1ht2b1gslamyn)" height="680.4883" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="730" x="643" y="103"/><rect fill="#FFFFFF" height="648" rx="12.5" ry="12.5" style="stroke:#FFFFFF;stroke-width:1.0;" width="724" x="646" y="132.4883"/><line style="stroke:#A80036;stroke-width:1.5;" x1="643" x2="1373" y1="129.4883" y2="129.4883"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="54" x="981" y="121.5352">Manage</text><rect fill="#FEFECE" filter="url(#f1ht2b1gslamyn)" height="40" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="281" x="673" y="141.4883"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="271" x="678" y="166.7793">Check(reg.URN, reg.Inputs, last?.Inputs)</text><rect fill="#FEFECE" filter="url(#f1ht2b1gslamyn)" height="40" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="215" x="655" y="292.4883"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="205" x="660" y="317.7793">Create(reg.URN, check.Inputs)</text><rect fill="#FEFECE" filter="url(#f1ht2b1gslamyn)" height="40" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="314" x="790.5" y="234.4883"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="304" x="795.5" y="259.7793">Diff(reg.URN, check.Inputs, last.ID, last.State)</text><rect fill="#FEFECE" filter="url(#f1ht2b1gslamyn)" height="40" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="245" x="778" y="408.4883"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="235" x="783" y="433.7793">Update(reg.URN, last.ID, last.State)</text><rect fill="#FEFECE" filter="url(#f1ht2b1gslamyn)" height="40" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="196" x="948.5" y="350.4883"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="186" x="953.5" y="375.7793">Check(reg.URN, reg.Inputs)</text><rect fill="#FEFECE" filter="url(#f1ht2b1gslamyn)" height="40" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="199" x="932" y="466.4883"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="189" x="937" y="491.7793">Create(reg.URN, reg.Inputs)</text><g id="Manage.manage_replace_delete_after_create"><rect fill="#FEFECE" filter="url(#f1ht2b1gslamyn)" height="50.6211" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="391" x="832" y="601.4883"/><line style="stroke:#A80036;stroke-width:1.5;" x1="832" x2="1223" y1="627.9766" y2="627.9766"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="229" x="913" y="620.0234">Delete(reg.URN, last.ID, last.State)</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="371" x="837" y="644.5781">note that this step happens once the Pulumi program has exited</text></g><rect fill="#FEFECE" filter="url(#f1ht2b1gslamyn)" height="40" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="138" x="1161.5" y="466.4883"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="128" x="1166.5" y="491.7793">Delete dependents</text><rect fill="#FEFECE" filter="url(#f1ht2b1gslamyn)" height="40" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="239" x="1118" y="543.4883"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="229" x="1123" y="568.7793">Delete(reg.URN, last.ID, last.State)</text><rect fill="#FEFECE" filter="url(#f1ht2b1gslamyn)" height="40" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="215" x="1050" y="670.4883"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="205" x="1055" y="695.7793">Create(reg.URN, check.Inputs)</text><ellipse cx="878.5" cy="757.4883" filter="url(#f1ht2b1gslamyn)" rx="10" ry="10" style="stroke:#000000;stroke-width:1.0;fill:none;"/><ellipse cx="879" cy="757.9883" fill="#000000" rx="6" ry="6" style="stroke:none;stroke-width:1.0;"/><!--MD5=[6a24f9d7a6384fcc9dfe0e40779635cd]
|
||||
link manage_check to manage_create--><path d="M795.02,181.6183 C790.65,187.0283 786.42,193.1883 783.5,199.4883 C770.37,227.8683 765.45,263.8883 763.6,287.3083 " fill="none" id="manage_check-to-manage_create" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="763.24,292.3983,767.8976,283.7203,763.6115,287.4121,759.9197,283.126,763.24,292.3983" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="78" x="784.5" y="213.0566">no last state</text><!--MD5=[6c1279eb02b9d63b68e4e867d2945e06]
|
||||
link manage_check to manage_diff--><path d="M841.59,181.5683 C863.03,196.1283 892.61,216.2083 915.06,231.4583 " fill="none" id="manage_check-to-manage_diff" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="919.45,234.4383,914.2332,226.0845,915.3074,231.6385,909.7535,232.7127,919.45,234.4383" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="84" x="893.5" y="213.0566">has last state</text><!--MD5=[75cf380d1867293c2c38d7b5794ac0ca]
|
||||
link manage_diff to manage_update--><path d="M923.37,274.5383 C918.28,279.7883 913.53,285.8783 910.5,292.4883 C894.09,328.2883 894.88,375.0683 897.38,403.1083 " fill="none" id="manage_diff-to-manage_update" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="897.87,408.1183,901.005,398.7817,897.3993,403.1405,893.0405,399.5348,897.87,408.1183" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="96" x="911.5" y="317.5566">can be updated</text><!--MD5=[475bf7a6d5f74542d3094a3e4c006f3f]
|
||||
link manage_diff to manage_replace_check--><path d="M990.26,274.5983 C998.35,279.5883 1006.23,285.5483 1012.5,292.4883 C1026.08,307.5283 1034.92,328.8583 1040.18,345.2583 " fill="none" id="manage_diff-to-manage_replace_check" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="1041.69,350.1783,1042.8602,340.3992,1040.2166,345.4003,1035.2154,342.7567,1041.69,350.1783" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="108" x="1035.5" y="317.5566">must be replaced</text><!--MD5=[0cac4c5aae92b7da67549b590f22b20b]
|
||||
link manage_replace_check to manage_replace_create_before_delete--><path d="M1043.99,390.5683 C1041.44,409.9683 1037.47,440.0983 1034.7,461.1883 " fill="none" id="manage_replace_check-to-manage_replace_create_before_delete" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="1034.02,466.3483,1039.168,457.952,1034.6771,461.3916,1031.2374,456.9007,1034.02,466.3483" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="124" x="1041.5" y="433.5566">create before delete</text><!--MD5=[bb163b3a3cac95fb1660d5b3316a4ec8]
|
||||
link manage_replace_check to manage_replace_delete_dependents--><path d="M1135.31,390.5783 C1147.7,395.3183 1159.83,401.1983 1170.5,408.4883 C1190.45,422.1183 1206.79,444.4583 1217.36,461.5683 " fill="none" id="manage_replace_check-to-manage_replace_delete_dependents" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="1220.18,466.2483,1218.9411,456.4776,1217.5907,461.9709,1212.0974,460.6205,1220.18,466.2483" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="113" x="1209.5" y="433.5566">delete after craete</text><!--MD5=[fd5f046217bb41c91b57f94b75c028e6]
|
||||
link manage_replace_create_before_delete to manage_replace_delete_after_create--><path d="M1030.94,506.7483 C1030.28,529.8783 1029.15,568.9583 1028.36,596.0383 " fill="none" id="manage_replace_create_before_delete-to-manage_replace_delete_after_create" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="1028.21,601.2883,1032.4654,592.4062,1028.3528,596.2903,1024.4687,592.1777,1028.21,601.2883" style="stroke:#A80036;stroke-width:1.0;"/><!--MD5=[d9dd268e8ab66b521b1fbb3d30a1afd6]
|
||||
link manage_replace_delete_dependents to manage_replace_delete_before_create--><path d="M1232.3,506.7983 C1233.19,516.3383 1234.28,527.9483 1235.22,538.0883 " fill="none" id="manage_replace_delete_dependents-to-manage_replace_delete_before_create" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="1235.7,543.2383,1238.8325,533.9009,1235.228,538.2606,1230.8682,534.6561,1235.7,543.2383" style="stroke:#A80036;stroke-width:1.0;"/><!--MD5=[4c01834528a54528affee7556f74f604]
|
||||
link manage_replace_delete_before_create to manage_replace_create_after_delete--><path d="M1239.33,583.7683 C1240.14,602.8883 1238.58,632.1883 1224.5,652.4883 C1220.58,658.1483 1215.5,663.0283 1209.89,667.2183 " fill="none" id="manage_replace_delete_before_create-to-manage_replace_create_after_delete" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="1205.51,670.2883,1215.1765,668.4018,1209.6055,667.42,1210.5873,661.849,1205.51,670.2883" style="stroke:#A80036;stroke-width:1.0;"/><!--MD5=[58bd43061bbf4734b2332235cc2ce9d5]
|
||||
link manage_create to *end*Manage--><path d="M762.5,332.8483 C762.5,355.5283 762.5,394.2383 762.5,427.4883 C762.5,427.4883 762.5,427.4883 762.5,691.4883 C762.5,737.3183 832.25,751.1583 863.58,755.0583 " fill="none" id="manage_create-to-*end*Manage" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="868.61,755.6383,860.1256,750.6367,863.6427,755.0673,859.2121,758.5844,868.61,755.6383" style="stroke:#A80036;stroke-width:1.0;"/><!--MD5=[f306adc3f87ccc87da18b0dfd6870354]
|
||||
link manage_update to *end*Manage--><path d="M868.26,448.5483 C844.58,465.2483 816.5,491.9083 816.5,524.4883 C816.5,524.4883 816.5,524.4883 816.5,691.4883 C816.5,719.2883 846.56,739.8883 864.81,749.8383 " fill="none" id="manage_update-to-*end*Manage" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="869.62,752.3583,863.4961,744.6448,865.1886,750.0425,859.7909,751.735,869.62,752.3583" style="stroke:#A80036;stroke-width:1.0;"/><!--MD5=[dfbdada2b400b3d1f7c1a8b46fc52c5b]
|
||||
link manage_replace_delete_after_create to *end*Manage--><path d="M998.77,652.7683 C965.49,681.4583 912.32,727.3183 889.5,747.0083 " fill="none" id="manage_replace_delete_after_create-to-*end*Manage" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="885.6,750.3683,895.025,747.5102,889.3832,747.0991,889.7943,741.4572,885.6,750.3683" style="stroke:#A80036;stroke-width:1.0;"/><!--MD5=[ecbac8beeac4b28b80eae4b88efdf6ad]
|
||||
link manage_replace_create_after_delete to *end*Manage--><path d="M1075.68,710.5483 C1011.27,725.5583 926.95,745.1983 893.3,753.0383 " fill="none" id="manage_replace_create_after_delete-to-*end*Manage" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="888.35,754.1983,898.0206,756.0638,893.221,753.0698,896.215,748.2702,888.35,754.1983" style="stroke:#A80036;stroke-width:1.0;"/><!--MD5=[a1863298862c1f16686f7212d047fbdc]
|
||||
link *start to Read--><path d="M442.98,16.87 C416.9,17.05 345.92,20.93 303,56 C208.29,133.38 165.62,274.52 147.42,363.01 " fill="none" id="*start-to-Read" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="146.41,367.97,152.1064,359.9356,147.3961,363.0682,144.2635,358.3579,146.41,367.97" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="140" x="304" y="69.5684">read existing resource</text><!--MD5=[4d808eca49b36bf39c9ca2e13f8697a2]
|
||||
link *start to Import--><path d="M453,26.27 C453,60.53 453,183.35 453,286.68 " fill="none" id="*start-to-Import" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="453,291.89,457,282.89,453,286.89,449,282.89,453,291.89" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="155" x="454" y="69.5684">import existing resource</text><!--MD5=[9fa6da595ff909d93bcc26d44388e242]
|
||||
link *start to Manage--><path d="M462.96,17.49 C489.72,19.19 564.71,26.46 618,56 C641.43,68.99 664.42,83.78 686.79,99.83 " fill="none" id="*start-to-Manage" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="690.96,102.84,686.0037,94.3291,686.9059,99.9136,681.3214,100.8158,690.96,102.84" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="107" x="644" y="69.5684">manage resource</text><!--MD5=[318e06d7f4389017c1755234a013d98c]
|
||||
@startuml
|
||||
hide empty description
|
||||
|
||||
[*] - -> Read: read existing resource
|
||||
[*] - -> Import: import existing resource
|
||||
[*] - -> Manage: manage resource
|
||||
|
||||
state Read {
|
||||
state "Read(reg.URN, reg.ID, reg.State)" as read_read
|
||||
|
||||
read_read - -> [*]
|
||||
}
|
||||
|
||||
state Import {
|
||||
state "Read(reg.URN, reg.ID)" as import_read
|
||||
state "Check(reg.URN, reg.Inputs, read.Inputs)" as import_check
|
||||
state "Diff(reg.URN, check.Inputs, read.State)" as import_diff
|
||||
|
||||
import_read - -> import_check
|
||||
import_check - -> import_diff
|
||||
import_diff - -> [*]
|
||||
}
|
||||
|
||||
state Manage {
|
||||
state "Check(reg.URN, reg.Inputs, last?.Inputs)" as manage_check
|
||||
state "Create(reg.URN, check.Inputs)" as manage_create
|
||||
state "Diff(reg.URN, check.Inputs, last.ID, last.State)" as manage_diff
|
||||
state "Update(reg.URN, last.ID, last.State)" as manage_update
|
||||
state "Check(reg.URN, reg.Inputs)" as manage_replace_check
|
||||
state "Create(reg.URN, reg.Inputs)" as manage_replace_create_before_delete
|
||||
state "Delete(reg.URN, last.ID, last.State)" as manage_replace_delete_after_create
|
||||
state "Delete dependents" as manage_replace_delete_dependents
|
||||
state "Delete(reg.URN, last.ID, last.State)" as manage_replace_delete_before_create
|
||||
state "Create(reg.URN, check.Inputs)" as manage_replace_create_after_delete
|
||||
|
||||
manage_replace_delete_after_create: note that this step happens once the Pulumi program has exited
|
||||
|
||||
manage_check - -> manage_create: no last state
|
||||
manage_check - -> manage_diff: has last state
|
||||
manage_diff - -> manage_update: can be updated
|
||||
manage_diff - -> manage_replace_check: must be replaced
|
||||
manage_replace_check - -> manage_replace_create_before_delete: create before delete
|
||||
manage_replace_check - -> manage_replace_delete_dependents: delete after craete
|
||||
manage_replace_create_before_delete - -> manage_replace_delete_after_create
|
||||
manage_replace_delete_dependents - -> manage_replace_delete_before_create
|
||||
manage_replace_delete_before_create - -> manage_replace_create_after_delete
|
||||
manage_create - -> [*]
|
||||
manage_update - -> [*]
|
||||
manage_replace_delete_after_create - -> [*]
|
||||
manage_replace_create_after_delete - -> [*]
|
||||
}
|
||||
@enduml
|
||||
|
||||
PlantUML version 1.2021.9(Sun Jul 25 03:13:56 PDT 2021)
|
||||
(GPL source distribution)
|
||||
Java Runtime: OpenJDK Runtime Environment
|
||||
JVM: OpenJDK 64-Bit Server VM
|
||||
Default Encoding: UTF-8
|
||||
Language: en
|
||||
Country: US
|
||||
--></g></svg>
|
After Width: | Height: | Size: 20 KiB |
52
developer-docs/providers/resource-lifecycle.uml
Normal file
|
@ -0,0 +1,52 @@
|
|||
@startuml
|
||||
hide empty description
|
||||
|
||||
[*] --> Read: read existing resource
|
||||
[*] --> Import: import existing resource
|
||||
[*] --> Manage: manage resource
|
||||
|
||||
state Read {
|
||||
state "Read(reg.URN, reg.ID, reg.State)" as read_read
|
||||
|
||||
read_read --> [*]
|
||||
}
|
||||
|
||||
state Import {
|
||||
state "Read(reg.URN, reg.ID)" as import_read
|
||||
state "Check(reg.URN, reg.Inputs, read.Inputs)" as import_check
|
||||
state "Diff(reg.URN, check.Inputs, read.State)" as import_diff
|
||||
|
||||
import_read --> import_check
|
||||
import_check --> import_diff
|
||||
import_diff --> [*]
|
||||
}
|
||||
|
||||
state Manage {
|
||||
state "Check(reg.URN, reg.Inputs, last?.Inputs)" as manage_check
|
||||
state "Create(reg.URN, check.Inputs)" as manage_create
|
||||
state "Diff(reg.URN, check.Inputs, last.ID, last.State)" as manage_diff
|
||||
state "Update(reg.URN, last.ID, last.State)" as manage_update
|
||||
state "Check(reg.URN, reg.Inputs)" as manage_replace_check
|
||||
state "Create(reg.URN, reg.Inputs)" as manage_replace_create_before_delete
|
||||
state "Delete(reg.URN, last.ID, last.State)" as manage_replace_delete_after_create
|
||||
state "Delete dependents" as manage_replace_delete_dependents
|
||||
state "Delete(reg.URN, last.ID, last.State)" as manage_replace_delete_before_create
|
||||
state "Create(reg.URN, check.Inputs)" as manage_replace_create_after_delete
|
||||
|
||||
manage_replace_delete_after_create: note that this step happens once the Pulumi program has exited
|
||||
|
||||
manage_check --> manage_create: no last state
|
||||
manage_check --> manage_diff: has last state
|
||||
manage_diff --> manage_update: can be updated
|
||||
manage_diff --> manage_replace_check: must be replaced
|
||||
manage_replace_check --> manage_replace_create_before_delete: create before delete
|
||||
manage_replace_check --> manage_replace_delete_dependents: delete after craete
|
||||
manage_replace_create_before_delete --> manage_replace_delete_after_create
|
||||
manage_replace_delete_dependents --> manage_replace_delete_before_create
|
||||
manage_replace_delete_before_create --> manage_replace_create_after_delete
|
||||
manage_create --> [*]
|
||||
manage_update --> [*]
|
||||
manage_replace_delete_after_create --> [*]
|
||||
manage_replace_create_after_delete --> [*]
|
||||
}
|
||||
@enduml
|
4
developer-docs/requirements.txt
Normal file
|
@ -0,0 +1,4 @@
|
|||
sphinx==4.0.2
|
||||
sphinx_rtd_theme==0.5.2
|
||||
sphinx-tabs==3.1.0
|
||||
myst-parser==0.15.1
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2016-2020, Pulumi Corporation.
|
||||
// Copyright 2016-2021, Pulumi Corporation.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
@ -706,7 +706,32 @@ func (pkg *pkgContext) getInputUsage(name string) string {
|
|||
}, "\n")
|
||||
}
|
||||
|
||||
type genInputImplementationArgs struct {
|
||||
name string
|
||||
receiverType string
|
||||
elementType string
|
||||
ptrMethods bool
|
||||
toOutputMethods bool
|
||||
resourceType bool
|
||||
}
|
||||
|
||||
func genInputImplementation(w io.Writer, name, receiverType, elementType string, ptrMethods, resourceType bool) {
|
||||
genInputImplementationWithArgs(w, genInputImplementationArgs{
|
||||
name: name,
|
||||
receiverType: receiverType,
|
||||
elementType: elementType,
|
||||
ptrMethods: ptrMethods,
|
||||
resourceType: resourceType,
|
||||
toOutputMethods: true,
|
||||
})
|
||||
}
|
||||
|
||||
func genInputImplementationWithArgs(w io.Writer, genArgs genInputImplementationArgs) {
|
||||
name := genArgs.name
|
||||
receiverType := genArgs.receiverType
|
||||
elementType := genArgs.elementType
|
||||
resourceType := genArgs.resourceType
|
||||
|
||||
fmt.Fprintf(w, "func (%s) ElementType() reflect.Type {\n", receiverType)
|
||||
if resourceType {
|
||||
fmt.Fprintf(w, "\treturn reflect.TypeOf((*%s)(nil))\n", elementType)
|
||||
|
@ -715,15 +740,17 @@ func genInputImplementation(w io.Writer, name, receiverType, elementType string,
|
|||
}
|
||||
fmt.Fprintf(w, "}\n\n")
|
||||
|
||||
fmt.Fprintf(w, "func (i %s) To%sOutput() %sOutput {\n", receiverType, Title(name), name)
|
||||
fmt.Fprintf(w, "\treturn i.To%sOutputWithContext(context.Background())\n", Title(name))
|
||||
fmt.Fprintf(w, "}\n\n")
|
||||
if genArgs.toOutputMethods {
|
||||
fmt.Fprintf(w, "func (i %s) To%sOutput() %sOutput {\n", receiverType, Title(name), name)
|
||||
fmt.Fprintf(w, "\treturn i.To%sOutputWithContext(context.Background())\n", Title(name))
|
||||
fmt.Fprintf(w, "}\n\n")
|
||||
|
||||
fmt.Fprintf(w, "func (i %s) To%sOutputWithContext(ctx context.Context) %sOutput {\n", receiverType, Title(name), name)
|
||||
fmt.Fprintf(w, "\treturn pulumi.ToOutputWithContext(ctx, i).(%sOutput)\n", name)
|
||||
fmt.Fprintf(w, "}\n\n")
|
||||
fmt.Fprintf(w, "func (i %s) To%sOutputWithContext(ctx context.Context) %sOutput {\n", receiverType, Title(name), name)
|
||||
fmt.Fprintf(w, "\treturn pulumi.ToOutputWithContext(ctx, i).(%sOutput)\n", name)
|
||||
fmt.Fprintf(w, "}\n\n")
|
||||
}
|
||||
|
||||
if ptrMethods {
|
||||
if genArgs.ptrMethods {
|
||||
fmt.Fprintf(w, "func (i %s) To%sPtrOutput() %sPtrOutput {\n", receiverType, Title(name), name)
|
||||
fmt.Fprintf(w, "\treturn i.To%sPtrOutputWithContext(context.Background())\n", Title(name))
|
||||
fmt.Fprintf(w, "}\n\n")
|
||||
|
@ -1054,13 +1081,7 @@ func (pkg *pkgContext) genInputTypes(w io.Writer, t *schema.ObjectType, details
|
|||
// Generate the plain inputs.
|
||||
pkg.genInputInterface(w, name)
|
||||
|
||||
printComment(w, t.Comment, false)
|
||||
fmt.Fprintf(w, "type %sArgs struct {\n", name)
|
||||
for _, p := range t.Properties {
|
||||
printCommentWithDeprecationMessage(w, p.Comment, p.DeprecationMessage, true)
|
||||
fmt.Fprintf(w, "\t%s %s `pulumi:\"%s\"`\n", Title(p.Name), pkg.typeString(p.Type), p.Name)
|
||||
}
|
||||
fmt.Fprintf(w, "}\n\n")
|
||||
pkg.genInputArgsStruct(w, name+"Args", t)
|
||||
|
||||
genInputImplementation(w, name, name+"Args", name, details.ptrElement, false)
|
||||
|
||||
|
@ -1098,14 +1119,43 @@ func (pkg *pkgContext) genInputTypes(w io.Writer, t *schema.ObjectType, details
|
|||
}
|
||||
}
|
||||
|
||||
func (pkg *pkgContext) genOutputTypes(w io.Writer, t *schema.ObjectType, details *typeDetails) {
|
||||
contract.Assert(!t.IsInputShape())
|
||||
|
||||
name := pkg.tokenToType(t.Token)
|
||||
func (pkg *pkgContext) genInputArgsStruct(w io.Writer, typeName string, t *schema.ObjectType) {
|
||||
contract.Assert(t.IsInputShape())
|
||||
|
||||
printComment(w, t.Comment, false)
|
||||
fmt.Fprintf(w, "type %s struct {\n", typeName)
|
||||
for _, p := range t.Properties {
|
||||
printCommentWithDeprecationMessage(w, p.Comment, p.DeprecationMessage, true)
|
||||
fmt.Fprintf(w, "\t%s %s `pulumi:\"%s\"`\n", Title(p.Name), pkg.typeString(p.Type), p.Name)
|
||||
}
|
||||
fmt.Fprintf(w, "}\n\n")
|
||||
}
|
||||
|
||||
genOutputType(w, name, name, details.ptrElement, false)
|
||||
type genOutputTypesArgs struct {
|
||||
t *schema.ObjectType
|
||||
|
||||
// optional type name override
|
||||
name string
|
||||
}
|
||||
|
||||
func (pkg *pkgContext) genOutputTypes(w io.Writer, genArgs genOutputTypesArgs) {
|
||||
t := genArgs.t
|
||||
details := pkg.detailsForType(t)
|
||||
|
||||
contract.Assert(!t.IsInputShape())
|
||||
|
||||
name := genArgs.name
|
||||
if name == "" {
|
||||
name = pkg.tokenToType(t.Token)
|
||||
}
|
||||
|
||||
printComment(w, t.Comment, false)
|
||||
genOutputType(w,
|
||||
name, /* baseName */
|
||||
name, /* elementType */
|
||||
details.ptrElement, /* ptrMethods */
|
||||
false, /* resourceType */
|
||||
)
|
||||
|
||||
for _, p := range t.Properties {
|
||||
printCommentWithDeprecationMessage(w, p.Comment, p.DeprecationMessage, false)
|
||||
|
@ -1117,7 +1167,8 @@ func (pkg *pkgContext) genOutputTypes(w io.Writer, t *schema.ObjectType, details
|
|||
propName = "Get" + propName
|
||||
}
|
||||
fmt.Fprintf(w, "func (o %sOutput) %s() %s {\n", name, propName, outputType)
|
||||
fmt.Fprintf(w, "\treturn o.ApplyT(func (v %s) %s { return v.%s }).(%s)\n", name, applyType, Title(p.Name), outputType)
|
||||
fmt.Fprintf(w, "\treturn o.ApplyT(func (v %s) %s { return v.%s }).(%s)\n",
|
||||
name, applyType, Title(p.Name), outputType)
|
||||
fmt.Fprintf(w, "}\n\n")
|
||||
}
|
||||
|
||||
|
@ -1618,10 +1669,24 @@ func (pkg *pkgContext) genResource(w io.Writer, r *schema.Resource, generateReso
|
|||
return nil
|
||||
}
|
||||
|
||||
func (pkg *pkgContext) genFunction(w io.Writer, f *schema.Function) {
|
||||
// If the function starts with New or Get, it will conflict; so rename them.
|
||||
name := pkg.functionNames[f]
|
||||
func (pkg *pkgContext) genFunctionCodeFile(f *schema.Function) string {
|
||||
importsAndAliases := map[string]string{}
|
||||
pkg.getImports(f, importsAndAliases)
|
||||
buffer := &bytes.Buffer{}
|
||||
|
||||
var imports []string
|
||||
if f.NeedsOutputVersion() {
|
||||
imports = []string{"context", "reflect"}
|
||||
}
|
||||
|
||||
pkg.genHeader(buffer, imports, importsAndAliases)
|
||||
pkg.genFunction(buffer, f)
|
||||
pkg.genFunctionOutputVersion(buffer, f)
|
||||
return buffer.String()
|
||||
}
|
||||
|
||||
func (pkg *pkgContext) genFunction(w io.Writer, f *schema.Function) {
|
||||
name := pkg.functionName(f)
|
||||
printCommentWithDeprecationMessage(w, f.Comment, f.DeprecationMessage, false)
|
||||
|
||||
// Now, emit the function signature.
|
||||
|
@ -1671,20 +1736,91 @@ func (pkg *pkgContext) genFunction(w io.Writer, f *schema.Function) {
|
|||
// If there are argument and/or return types, emit them.
|
||||
if f.Inputs != nil {
|
||||
fmt.Fprintf(w, "\n")
|
||||
pkg.genPlainType(w, fmt.Sprintf("%sArgs", name), f.Inputs.Comment, "", f.Inputs.Properties)
|
||||
pkg.genPlainType(w, pkg.functionArgsTypeName(f), f.Inputs.Comment, "", f.Inputs.Properties)
|
||||
}
|
||||
if f.Outputs != nil {
|
||||
fmt.Fprintf(w, "\n")
|
||||
pkg.genPlainType(w, fmt.Sprintf("%sResult", name), f.Outputs.Comment, "", f.Outputs.Properties)
|
||||
pkg.genPlainType(w, pkg.functionResultTypeName(f), f.Outputs.Comment, "", f.Outputs.Properties)
|
||||
}
|
||||
}
|
||||
|
||||
func (pkg *pkgContext) functionName(f *schema.Function) string {
|
||||
// If the function starts with New or Get, it will conflict; so rename them.
|
||||
name, hasName := pkg.functionNames[f]
|
||||
|
||||
if !hasName {
|
||||
panic(fmt.Sprintf("No function name found for %v", f))
|
||||
}
|
||||
|
||||
return name
|
||||
}
|
||||
|
||||
func (pkg *pkgContext) functionArgsTypeName(f *schema.Function) string {
|
||||
name := pkg.functionName(f)
|
||||
return fmt.Sprintf("%sArgs", name)
|
||||
}
|
||||
|
||||
func (pkg *pkgContext) functionResultTypeName(f *schema.Function) string {
|
||||
name := pkg.functionName(f)
|
||||
return fmt.Sprintf("%sResult", name)
|
||||
}
|
||||
|
||||
func (pkg *pkgContext) genFunctionOutputVersion(w io.Writer, f *schema.Function) {
|
||||
if !f.NeedsOutputVersion() {
|
||||
return
|
||||
}
|
||||
|
||||
originalName := pkg.functionName(f)
|
||||
name := originalName + "Output"
|
||||
originalResultTypeName := pkg.functionResultTypeName(f)
|
||||
resultTypeName := originalResultTypeName + "Output"
|
||||
|
||||
code := `
|
||||
func ${fn}Output(ctx *pulumi.Context, args ${fn}OutputArgs, opts ...pulumi.InvokeOption) ${outputType} {
|
||||
return pulumi.ToOutputWithContext(context.Background(), args).
|
||||
ApplyT(func(v interface{}) (${fn}Result, error) {
|
||||
args := v.(${fn}Args)
|
||||
r, err := ${fn}(ctx, &args, opts...)
|
||||
return *r, err
|
||||
}).(${outputType})
|
||||
}
|
||||
|
||||
`
|
||||
code = strings.ReplaceAll(code, "${fn}", originalName)
|
||||
code = strings.ReplaceAll(code, "${outputType}", resultTypeName)
|
||||
fmt.Fprintf(w, code)
|
||||
|
||||
pkg.genInputArgsStruct(w, name+"Args", f.Inputs.InputShape)
|
||||
|
||||
genInputImplementationWithArgs(w, genInputImplementationArgs{
|
||||
name: name + "Args",
|
||||
receiverType: name + "Args",
|
||||
elementType: pkg.functionArgsTypeName(f),
|
||||
})
|
||||
|
||||
pkg.genOutputTypes(w, genOutputTypesArgs{
|
||||
t: f.Outputs,
|
||||
name: originalResultTypeName,
|
||||
})
|
||||
|
||||
// Assuming the file represented by `w` only has one function,
|
||||
// generate an `init()` for Output type init.
|
||||
initCode := `
|
||||
func init() {
|
||||
pulumi.RegisterOutputType(${outputType}{})
|
||||
}
|
||||
|
||||
`
|
||||
initCode = strings.ReplaceAll(initCode, "${outputType}", resultTypeName)
|
||||
fmt.Fprintf(w, initCode)
|
||||
}
|
||||
|
||||
func (pkg *pkgContext) genType(w io.Writer, obj *schema.ObjectType) {
|
||||
contract.Assert(!obj.IsInputShape())
|
||||
|
||||
pkg.genPlainType(w, pkg.tokenToType(obj.Token), obj.Comment, "", obj.Properties)
|
||||
pkg.genInputTypes(w, obj.InputShape, pkg.detailsForType(obj))
|
||||
pkg.genOutputTypes(w, obj, pkg.detailsForType(obj))
|
||||
pkg.genOutputTypes(w, genOutputTypesArgs{t: obj})
|
||||
}
|
||||
|
||||
func (pkg *pkgContext) addSuffixesToName(typ schema.Type, name string) []string {
|
||||
|
@ -2377,6 +2513,19 @@ func generatePackageContextMap(tool string, pkg *schema.Package, goInfo GoPackag
|
|||
scanResource(r)
|
||||
}
|
||||
|
||||
// For fnApply function versions, we need to register any
|
||||
// input or output property type metadata, in case they have
|
||||
// types used in array or pointer element positions.
|
||||
for _, f := range pkg.Functions {
|
||||
parentOptional := false
|
||||
if f.Inputs != nil {
|
||||
populateDetailsForPropertyTypes(seenMap, f.Inputs.Properties, parentOptional)
|
||||
}
|
||||
if f.Outputs != nil {
|
||||
populateDetailsForPropertyTypes(seenMap, f.Outputs.Properties, parentOptional)
|
||||
}
|
||||
}
|
||||
|
||||
for _, f := range pkg.Functions {
|
||||
if f.IsMethod {
|
||||
continue
|
||||
|
@ -2554,15 +2703,9 @@ func GeneratePackage(tool string, pkg *schema.Package) (map[string][]byte, error
|
|||
|
||||
// Functions
|
||||
for _, f := range pkg.functions {
|
||||
importsAndAliases := map[string]string{}
|
||||
pkg.getImports(f, importsAndAliases)
|
||||
|
||||
buffer := &bytes.Buffer{}
|
||||
pkg.genHeader(buffer, nil, importsAndAliases)
|
||||
|
||||
pkg.genFunction(buffer, f)
|
||||
|
||||
setFile(path.Join(mod, camel(tokenToName(f.Token))+".go"), buffer.String())
|
||||
fileName := path.Join(mod, camel(tokenToName(f.Token))+".go")
|
||||
code := pkg.genFunctionCodeFile(f)
|
||||
setFile(fileName, code)
|
||||
}
|
||||
|
||||
knownTypes := make(map[schema.Type]struct{}, len(pkg.typeDetails))
|
||||
|
|
|
@ -1,6 +1,14 @@
|
|||
package gen
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
|
@ -250,3 +258,88 @@ func TestEnumUsage(t *testing.T) {
|
|||
}, pulumi.WithMocks("project", "stack", mocks(1))))
|
||||
})
|
||||
}
|
||||
|
||||
func TestGenerateOutputFuncs(t *testing.T) {
|
||||
testDir := filepath.Join("..", "internal", "test", "testdata", "output-funcs")
|
||||
|
||||
files, err := ioutil.ReadDir(testDir)
|
||||
if err != nil {
|
||||
assert.NoError(t, err)
|
||||
return
|
||||
}
|
||||
|
||||
var examples []string
|
||||
for _, f := range files {
|
||||
name := f.Name()
|
||||
if strings.HasSuffix(name, ".json") {
|
||||
examples = append(examples, strings.TrimSuffix(name, ".json"))
|
||||
}
|
||||
}
|
||||
|
||||
sort.Slice(examples, func(i, j int) bool { return examples[i] < examples[j] })
|
||||
|
||||
gen := func(reader io.Reader, writer io.Writer) error {
|
||||
var pkgSpec schema.PackageSpec
|
||||
err := json.NewDecoder(reader).Decode(&pkgSpec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pkg, err := schema.ImportSpec(pkgSpec, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tool := "tool"
|
||||
var goPkgInfo GoPackageInfo
|
||||
if goInfo, ok := pkg.Language["go"].(GoPackageInfo); ok {
|
||||
goPkgInfo = goInfo
|
||||
}
|
||||
pkgContexts := generatePackageContextMap(tool, pkg, goPkgInfo)
|
||||
|
||||
var pkgContext *pkgContext
|
||||
|
||||
for _, c := range pkgContexts {
|
||||
if len(c.functionNames) == 1 {
|
||||
pkgContext = c
|
||||
}
|
||||
}
|
||||
|
||||
if pkgContext == nil {
|
||||
return fmt.Errorf("Cannot find a package with 1 function in generatePackageContextMap result")
|
||||
}
|
||||
|
||||
fun := pkg.Functions[0]
|
||||
_, err = writer.Write([]byte(pkgContext.genFunctionCodeFile(fun)))
|
||||
return err
|
||||
|
||||
}
|
||||
|
||||
for _, ex := range examples {
|
||||
t.Run(ex, func(t *testing.T) {
|
||||
inputFile := filepath.Join(testDir, fmt.Sprintf("%s.json", ex))
|
||||
expectedOutputFile := filepath.Join(testDir, "go", fmt.Sprintf("%s.go", ex))
|
||||
test.ValidateFileTransformer(t, inputFile, expectedOutputFile, gen)
|
||||
})
|
||||
}
|
||||
|
||||
goDir := filepath.Join("..", "internal", "test", "testdata", "output-funcs", "go")
|
||||
|
||||
t.Run("compileGeneratedCode", func(t *testing.T) {
|
||||
t.Logf("cd %s && go mod tidy", goDir)
|
||||
cmd := exec.Command("go", "mod", "tidy")
|
||||
cmd.Dir = goDir
|
||||
assert.NoError(t, cmd.Run())
|
||||
|
||||
t.Logf("cd %s && go build .", goDir)
|
||||
cmd = exec.Command("go", "build", ".")
|
||||
cmd.Dir = goDir
|
||||
assert.NoError(t, cmd.Run())
|
||||
})
|
||||
|
||||
t.Run("testGeneratedCode", func(t *testing.T) {
|
||||
t.Logf("cd %s && go test .", goDir)
|
||||
cmd := exec.Command("go", "test", ".")
|
||||
cmd.Dir = goDir
|
||||
assert.NoError(t, cmd.Run())
|
||||
})
|
||||
}
|
||||
|
|
|
@ -15,7 +15,9 @@
|
|||
package test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
@ -185,3 +187,47 @@ func CheckAllFilesGenerated(t *testing.T, actual, expected map[string][]byte) {
|
|||
assert.Fail(t, "No content generated for expected file %s", s)
|
||||
}
|
||||
}
|
||||
|
||||
// Validates a transformer on a single file.
|
||||
func ValidateFileTransformer(
|
||||
t *testing.T,
|
||||
inputFile string,
|
||||
expectedOutputFile string,
|
||||
transformer func(reader io.Reader, writer io.Writer) error) {
|
||||
|
||||
reader, err := os.Open(inputFile)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
|
||||
err = transformer(reader, &buf)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
actualBytes := buf.Bytes()
|
||||
|
||||
if os.Getenv("PULUMI_ACCEPT") != "" {
|
||||
err := ioutil.WriteFile(expectedOutputFile, actualBytes, 0600)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
actual := map[string][]byte{expectedOutputFile: actualBytes}
|
||||
|
||||
expectedBytes, err := ioutil.ReadFile(expectedOutputFile)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
expected := map[string][]byte{expectedOutputFile: expectedBytes}
|
||||
|
||||
ValidateFileEquality(t, actual, expected)
|
||||
}
|
||||
|
|
|
@ -4,6 +4,9 @@
|
|||
package example
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
|
||||
"github.com/pulumi/pulumi-random/sdk/v2/go/random"
|
||||
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
|
||||
)
|
||||
|
@ -24,3 +27,42 @@ type ArgFunctionArgs struct {
|
|||
type ArgFunctionResult struct {
|
||||
Age *int `pulumi:"age"`
|
||||
}
|
||||
|
||||
func ArgFunctionOutput(ctx *pulumi.Context, args ArgFunctionOutputArgs, opts ...pulumi.InvokeOption) ArgFunctionResultOutput {
|
||||
return pulumi.ToOutputWithContext(context.Background(), args).
|
||||
ApplyT(func(v interface{}) (ArgFunctionResult, error) {
|
||||
args := v.(ArgFunctionArgs)
|
||||
r, err := ArgFunction(ctx, &args, opts...)
|
||||
return *r, err
|
||||
}).(ArgFunctionResultOutput)
|
||||
}
|
||||
|
||||
type ArgFunctionOutputArgs struct {
|
||||
Name random.RandomPetInput `pulumi:"name"`
|
||||
}
|
||||
|
||||
func (ArgFunctionOutputArgs) ElementType() reflect.Type {
|
||||
return reflect.TypeOf((*ArgFunctionArgs)(nil)).Elem()
|
||||
}
|
||||
|
||||
type ArgFunctionResultOutput struct{ *pulumi.OutputState }
|
||||
|
||||
func (ArgFunctionResultOutput) ElementType() reflect.Type {
|
||||
return reflect.TypeOf((*ArgFunctionResult)(nil)).Elem()
|
||||
}
|
||||
|
||||
func (o ArgFunctionResultOutput) ToArgFunctionResultOutput() ArgFunctionResultOutput {
|
||||
return o
|
||||
}
|
||||
|
||||
func (o ArgFunctionResultOutput) ToArgFunctionResultOutputWithContext(ctx context.Context) ArgFunctionResultOutput {
|
||||
return o
|
||||
}
|
||||
|
||||
func (o ArgFunctionResultOutput) Age() pulumi.IntPtrOutput {
|
||||
return o.ApplyT(func(v ArgFunctionResult) *int { return v.Age }).(pulumi.IntPtrOutput)
|
||||
}
|
||||
|
||||
func init() {
|
||||
pulumi.RegisterOutputType(ArgFunctionResultOutput{})
|
||||
}
|
||||
|
|
29
pkg/codegen/internal/test/testdata/output-funcs/funcWithAllOptionalInputs.json
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"functions": {
|
||||
"madeup-package:codegentest:funcWithAllOptionalInputs": {
|
||||
"description": "Check codegen of functions with all optional inputs.",
|
||||
"inputs": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"a": {
|
||||
"type": "string"
|
||||
},
|
||||
"b": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"outputs": {
|
||||
"properties": {
|
||||
"r": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"r"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
16
pkg/codegen/internal/test/testdata/output-funcs/funcWithConstInput.json
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"functions": {
|
||||
"madeup-package:codegentest:funcWithConstInput": {
|
||||
"description": "Codegen demo with const inputs",
|
||||
"inputs": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"plainInput": {
|
||||
"type": "string",
|
||||
"const": "fixed"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
33
pkg/codegen/internal/test/testdata/output-funcs/funcWithDefaultValue.json
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"functions": {
|
||||
"madeup-package:codegentest:funcWithDefaultValue": {
|
||||
"description": "Check codegen of functions with default values.",
|
||||
"inputs": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"a"
|
||||
],
|
||||
"properties": {
|
||||
"a": {
|
||||
"type": "string"
|
||||
},
|
||||
"b": {
|
||||
"type": "string",
|
||||
"default": "b-default"
|
||||
}
|
||||
}
|
||||
},
|
||||
"outputs": {
|
||||
"properties": {
|
||||
"r": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"r"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
32
pkg/codegen/internal/test/testdata/output-funcs/funcWithDictParam.json
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
"functions": {
|
||||
"madeup-package:codegentest:funcWithDictParam": {
|
||||
"description": "Check codegen of functions with a Dict<str,str> parameter.",
|
||||
"inputs": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"a": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"b": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"outputs": {
|
||||
"properties": {
|
||||
"r": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"r"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
32
pkg/codegen/internal/test/testdata/output-funcs/funcWithListParam.json
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
"functions": {
|
||||
"madeup-package:codegentest:funcWithListParam": {
|
||||
"description": "Check codegen of functions with a List parameter.",
|
||||
"inputs": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"a": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"b": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"outputs": {
|
||||
"properties": {
|
||||
"r": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"r"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
35
pkg/codegen/internal/test/testdata/output-funcs/getClientConfig.json
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"functions": {
|
||||
"azure-native:codegentest:getClientConfig": {
|
||||
"description": "Use this function to access the current configuration of the native Azure provider.",
|
||||
"outputs": {
|
||||
"description": "Configuration values returned by getClientConfig.",
|
||||
"properties": {
|
||||
"clientId": {
|
||||
"type": "string",
|
||||
"description": "Azure Client ID (Application Object ID)."
|
||||
},
|
||||
"objectId": {
|
||||
"type": "string",
|
||||
"description": "Azure Object ID of the current user or service principal."
|
||||
},
|
||||
"subscriptionId": {
|
||||
"type": "string",
|
||||
"description": "Azure Subscription ID"
|
||||
},
|
||||
"tenantId": {
|
||||
"type": "string",
|
||||
"description": "Azure Tenant ID"
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"clientId",
|
||||
"objectId",
|
||||
"subscriptionId",
|
||||
"tenantId"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
348
pkg/codegen/internal/test/testdata/output-funcs/getIntegrationRuntimeObjectMetadatum.json
vendored
Normal file
|
@ -0,0 +1,348 @@
|
|||
{
|
||||
"functions": {
|
||||
"azure-native:codegentest:getIntegrationRuntimeObjectMetadatum": {
|
||||
"description": "A list of SSIS object metadata.\nAPI Version: 2018-06-01.",
|
||||
"inputs": {
|
||||
"properties": {
|
||||
"factoryName": {
|
||||
"type": "string",
|
||||
"description": "The factory name."
|
||||
},
|
||||
"integrationRuntimeName": {
|
||||
"type": "string",
|
||||
"description": "The integration runtime name."
|
||||
},
|
||||
"metadataPath": {
|
||||
"type": "string",
|
||||
"description": "Metadata path."
|
||||
},
|
||||
"resourceGroupName": {
|
||||
"type": "string",
|
||||
"description": "The resource group name."
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"factoryName",
|
||||
"integrationRuntimeName",
|
||||
"resourceGroupName"
|
||||
]
|
||||
},
|
||||
"outputs": {
|
||||
"description": "A list of SSIS object metadata.",
|
||||
"properties": {
|
||||
"nextLink": {
|
||||
"type": "string",
|
||||
"description": "The link to the next page of results, if any remaining results exist."
|
||||
},
|
||||
"value": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"$ref": "#/types/azure-native:codegentest:SsisEnvironmentResponse"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"$ref": "#/types/azure-native:codegentest:SsisFolderResponse"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"$ref": "#/types/azure-native:codegentest:SsisPackageResponse"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"$ref": "#/types/azure-native:codegentest:SsisProjectResponse"
|
||||
}
|
||||
],
|
||||
"discriminator": {
|
||||
"propertyName": "type",
|
||||
"mapping": {
|
||||
"Environment": "#/types/azure-native:codegentest:SsisEnvironmentResponse",
|
||||
"Folder": "#/types/azure-native:codegentest:SsisFolderResponse",
|
||||
"Package": "#/types/azure-native:codegentest:SsisPackageResponse",
|
||||
"Project": "#/types/azure-native:codegentest:SsisProjectResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "List of SSIS object metadata."
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
},
|
||||
"types": {
|
||||
"azure-native:codegentest:SsisEnvironmentResponse": {
|
||||
"description": "Ssis environment.",
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "string",
|
||||
"description": "Metadata description."
|
||||
},
|
||||
"folderId": {
|
||||
"type": "number",
|
||||
"description": "Folder id which contains environment."
|
||||
},
|
||||
"id": {
|
||||
"type": "number",
|
||||
"description": "Metadata id."
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Metadata name."
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "The type of SSIS object metadata.\nExpected value is 'Environment'.",
|
||||
"const": "Environment"
|
||||
},
|
||||
"variables": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"$ref": "#/types/azure-native:codegentest:SsisVariableResponse"
|
||||
},
|
||||
"description": "Variable in environment"
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"type"
|
||||
]
|
||||
},
|
||||
"azure-native:codegentest:SsisFolderResponse": {
|
||||
"description": "Ssis folder.",
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "string",
|
||||
"description": "Metadata description."
|
||||
},
|
||||
"id": {
|
||||
"type": "number",
|
||||
"description": "Metadata id."
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Metadata name."
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "The type of SSIS object metadata.\nExpected value is 'Folder'.",
|
||||
"const": "Folder"
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"type"
|
||||
]
|
||||
},
|
||||
"azure-native:codegentest:SsisPackageResponse": {
|
||||
"description": "Ssis Package.",
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "string",
|
||||
"description": "Metadata description."
|
||||
},
|
||||
"folderId": {
|
||||
"type": "number",
|
||||
"description": "Folder id which contains package."
|
||||
},
|
||||
"id": {
|
||||
"type": "number",
|
||||
"description": "Metadata id."
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Metadata name."
|
||||
},
|
||||
"parameters": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"$ref": "#/types/azure-native:codegentest:SsisParameterResponse"
|
||||
},
|
||||
"description": "Parameters in package"
|
||||
},
|
||||
"projectId": {
|
||||
"type": "number",
|
||||
"description": "Project id which contains package."
|
||||
},
|
||||
"projectVersion": {
|
||||
"type": "number",
|
||||
"description": "Project version which contains package."
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "The type of SSIS object metadata.\nExpected value is 'Package'.",
|
||||
"const": "Package"
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"type"
|
||||
]
|
||||
},
|
||||
"azure-native:codegentest:SsisProjectResponse": {
|
||||
"description": "Ssis project.",
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "string",
|
||||
"description": "Metadata description."
|
||||
},
|
||||
"environmentRefs": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"$ref": "#/types/azure-native:codegentest:SsisEnvironmentReferenceResponse"
|
||||
},
|
||||
"description": "Environment reference in project"
|
||||
},
|
||||
"folderId": {
|
||||
"type": "number",
|
||||
"description": "Folder id which contains project."
|
||||
},
|
||||
"id": {
|
||||
"type": "number",
|
||||
"description": "Metadata id."
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Metadata name."
|
||||
},
|
||||
"parameters": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"$ref": "#/types/azure-native:codegentest:SsisParameterResponse"
|
||||
},
|
||||
"description": "Parameters in project"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "The type of SSIS object metadata.\nExpected value is 'Project'.",
|
||||
"const": "Project"
|
||||
},
|
||||
"version": {
|
||||
"type": "number",
|
||||
"description": "Project version."
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"type"
|
||||
]
|
||||
},
|
||||
"azure-native:codegentest:SsisEnvironmentReferenceResponse": {
|
||||
"description": "Ssis environment reference.",
|
||||
"properties": {
|
||||
"environmentFolderName": {
|
||||
"type": "string",
|
||||
"description": "Environment folder name."
|
||||
},
|
||||
"environmentName": {
|
||||
"type": "string",
|
||||
"description": "Environment name."
|
||||
},
|
||||
"id": {
|
||||
"type": "number",
|
||||
"description": "Environment reference id."
|
||||
},
|
||||
"referenceType": {
|
||||
"type": "string",
|
||||
"description": "Reference type"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"azure-native:codegentest:SsisParameterResponse": {
|
||||
"description": "Ssis parameter.",
|
||||
"properties": {
|
||||
"dataType": {
|
||||
"type": "string",
|
||||
"description": "Parameter type."
|
||||
},
|
||||
"defaultValue": {
|
||||
"type": "string",
|
||||
"description": "Default value of parameter."
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"description": "Parameter description."
|
||||
},
|
||||
"designDefaultValue": {
|
||||
"type": "string",
|
||||
"description": "Design default value of parameter."
|
||||
},
|
||||
"id": {
|
||||
"type": "number",
|
||||
"description": "Parameter id."
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Parameter name."
|
||||
},
|
||||
"required": {
|
||||
"type": "boolean",
|
||||
"description": "Whether parameter is required."
|
||||
},
|
||||
"sensitive": {
|
||||
"type": "boolean",
|
||||
"description": "Whether parameter is sensitive."
|
||||
},
|
||||
"sensitiveDefaultValue": {
|
||||
"type": "string",
|
||||
"description": "Default sensitive value of parameter."
|
||||
},
|
||||
"valueSet": {
|
||||
"type": "boolean",
|
||||
"description": "Parameter value set."
|
||||
},
|
||||
"valueType": {
|
||||
"type": "string",
|
||||
"description": "Parameter value type."
|
||||
},
|
||||
"variable": {
|
||||
"type": "string",
|
||||
"description": "Parameter reference variable."
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"azure-native:codegentest:SsisVariableResponse": {
|
||||
"description": "Ssis variable.",
|
||||
"properties": {
|
||||
"dataType": {
|
||||
"type": "string",
|
||||
"description": "Variable type."
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"description": "Variable description."
|
||||
},
|
||||
"id": {
|
||||
"type": "number",
|
||||
"description": "Variable id."
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Variable name."
|
||||
},
|
||||
"sensitive": {
|
||||
"type": "boolean",
|
||||
"description": "Whether variable is sensitive."
|
||||
},
|
||||
"sensitiveValue": {
|
||||
"type": "string",
|
||||
"description": "Variable sensitive value."
|
||||
},
|
||||
"value": {
|
||||
"type": "string",
|
||||
"description": "Variable value."
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
255
pkg/codegen/internal/test/testdata/output-funcs/go/codegen_test.go
vendored
Normal file
|
@ -0,0 +1,255 @@
|
|||
// Copyright 2016-2021, Pulumi Corporation.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package codegentest
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/pulumi/pulumi/sdk/v3/go/common/resource"
|
||||
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
|
||||
)
|
||||
|
||||
type mocks int
|
||||
|
||||
// Create the mock.
|
||||
func (mocks) NewResource(args pulumi.MockResourceArgs) (string, resource.PropertyMap, error) {
|
||||
panic("NewResource not supported")
|
||||
}
|
||||
|
||||
func (mocks) Call(args pulumi.MockCallArgs) (resource.PropertyMap, error) {
|
||||
if args.Token == "azure-native:codegentest:listStorageAccountKeys" {
|
||||
|
||||
targs := ListStorageAccountKeysArgs{}
|
||||
for k, v := range args.Args {
|
||||
switch k {
|
||||
case "accountName":
|
||||
targs.AccountName = v.V.(string)
|
||||
case "expand":
|
||||
expand := v.V.(string)
|
||||
targs.Expand = &expand
|
||||
case "resourceGroupName":
|
||||
targs.ResourceGroupName = v.V.(string)
|
||||
}
|
||||
}
|
||||
|
||||
var expand string
|
||||
if targs.Expand != nil {
|
||||
expand = *targs.Expand
|
||||
}
|
||||
|
||||
inputs := []StorageAccountKeyResponse{
|
||||
{
|
||||
KeyName: "key",
|
||||
Permissions: "permissions",
|
||||
Value: fmt.Sprintf("accountName=%v, resourceGroupName=%v, expand=%v",
|
||||
targs.AccountName,
|
||||
targs.ResourceGroupName,
|
||||
expand),
|
||||
},
|
||||
}
|
||||
result := ListStorageAccountKeysResult{
|
||||
Keys: inputs,
|
||||
}
|
||||
outputs := map[string]interface{}{
|
||||
"keys": result.Keys,
|
||||
}
|
||||
return resource.NewPropertyMapFromMap(outputs), nil
|
||||
}
|
||||
|
||||
if args.Token == "madeup-package:codegentest:funcWithDefaultValue" ||
|
||||
args.Token == "madeup-package:codegentest:funcWithAllOptionalInputs" ||
|
||||
args.Token == "madeup-package:codegentest:funcWithListParam" ||
|
||||
args.Token == "madeup-package:codegentest:funcWithDictParam" {
|
||||
result := FuncWithDefaultValueResult{
|
||||
R: fmt.Sprintf("%v", args.Args),
|
||||
}
|
||||
outputs := map[string]interface{}{
|
||||
"r": result.R,
|
||||
}
|
||||
return resource.NewPropertyMapFromMap(outputs), nil
|
||||
}
|
||||
|
||||
if args.Token == "azure-native:codegentest:getIntegrationRuntimeObjectMetadatum" {
|
||||
targs := GetIntegrationRuntimeObjectMetadatumArgs{}
|
||||
for k, v := range args.Args {
|
||||
switch k {
|
||||
case "factoryName":
|
||||
targs.FactoryName = v.V.(string)
|
||||
case "integrationRuntimeName":
|
||||
targs.IntegrationRuntimeName = v.V.(string)
|
||||
case "metadataPath":
|
||||
metadataPath := v.V.(string)
|
||||
targs.MetadataPath = &metadataPath
|
||||
case "resourceGroupName":
|
||||
targs.ResourceGroupName = v.V.(string)
|
||||
}
|
||||
}
|
||||
nextLink := "my-next-link"
|
||||
result := GetIntegrationRuntimeObjectMetadatumResult{
|
||||
NextLink: &nextLink,
|
||||
Value: []interface{}{targs},
|
||||
}
|
||||
outputs := map[string]interface{}{
|
||||
"nextLink": result.NextLink,
|
||||
"value": []interface{}{fmt.Sprintf("factoryName=%s", targs.FactoryName)},
|
||||
}
|
||||
|
||||
return resource.NewPropertyMapFromMap(outputs), nil
|
||||
}
|
||||
|
||||
panic(fmt.Errorf("Unknown token: %s", args.Token))
|
||||
}
|
||||
|
||||
func TestListStorageAccountKeysOutput(t *testing.T) {
|
||||
pulumiTest(t, func(ctx *pulumi.Context) error {
|
||||
output := ListStorageAccountKeysOutput(ctx, ListStorageAccountKeysOutputArgs{
|
||||
AccountName: pulumi.String("my-account-name"),
|
||||
ResourceGroupName: pulumi.String("my-resource-group-name"),
|
||||
})
|
||||
|
||||
keys := waitOut(t, output.Keys()).([]StorageAccountKeyResponse)
|
||||
|
||||
assert.Equal(t, 1, len(keys))
|
||||
assert.Equal(t, "key", keys[0].KeyName)
|
||||
assert.Equal(t, "permissions", keys[0].Permissions)
|
||||
assert.Equal(t, "accountName=my-account-name, resourceGroupName=my-resource-group-name, expand=",
|
||||
keys[0].Value)
|
||||
|
||||
output = ListStorageAccountKeysOutput(ctx, ListStorageAccountKeysOutputArgs{
|
||||
AccountName: pulumi.String("my-account-name"),
|
||||
ResourceGroupName: pulumi.String("my-resource-group-name"),
|
||||
Expand: pulumi.String("my-expand"),
|
||||
})
|
||||
|
||||
keys = waitOut(t, output.Keys()).([]StorageAccountKeyResponse)
|
||||
|
||||
assert.Equal(t, 1, len(keys))
|
||||
assert.Equal(t, "key", keys[0].KeyName)
|
||||
assert.Equal(t, "permissions", keys[0].Permissions)
|
||||
assert.Equal(t, "accountName=my-account-name, resourceGroupName=my-resource-group-name, expand=my-expand",
|
||||
keys[0].Value)
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// TODO[pulumi/pulumi#7811]: it seems that default values are not
|
||||
// supported by Go codegen yet, hence we do not observe "B" populated
|
||||
// to default at all here.
|
||||
func TestFuncWithDefaultValueOutput(t *testing.T) {
|
||||
pulumiTest(t, func(ctx *pulumi.Context) error {
|
||||
output := FuncWithDefaultValueOutput(ctx, FuncWithDefaultValueOutputArgs{
|
||||
A: pulumi.String("my-a"),
|
||||
})
|
||||
r := waitOut(t, output.R())
|
||||
assert.Equal(t, "map[a:{my-a}]", r)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func TestFuncWithAllOptionalInputsOutput(t *testing.T) {
|
||||
pulumiTest(t, func(ctx *pulumi.Context) error {
|
||||
output := FuncWithAllOptionalInputsOutput(ctx, FuncWithAllOptionalInputsOutputArgs{
|
||||
A: pulumi.String("my-a"),
|
||||
})
|
||||
r := waitOut(t, output.R())
|
||||
assert.Equal(t, "map[a:{my-a}]", r)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func TestFuncWithListParamOutput(t *testing.T) {
|
||||
pulumiTest(t, func(ctx *pulumi.Context) error {
|
||||
output := FuncWithListParamOutput(ctx, FuncWithListParamOutputArgs{
|
||||
A: pulumi.StringArray{
|
||||
pulumi.String("my-a1"),
|
||||
pulumi.String("my-a2"),
|
||||
pulumi.String("my-a3"),
|
||||
},
|
||||
})
|
||||
r := waitOut(t, output.R())
|
||||
assert.Equal(t, "map[a:{[{my-a1} {my-a2} {my-a3}]}]", r)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func TestFuncWithDictParamOutput(t *testing.T) {
|
||||
pulumiTest(t, func(ctx *pulumi.Context) error {
|
||||
output := FuncWithDictParamOutput(ctx, FuncWithDictParamOutputArgs{
|
||||
A: pulumi.StringMap{
|
||||
"one": pulumi.String("1"),
|
||||
"two": pulumi.String("2"),
|
||||
},
|
||||
})
|
||||
r := waitOut(t, output.R())
|
||||
assert.Equal(t, "map[a:{map[one:{1} two:{2}]}]", r)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetIntegrationRuntimeObjectMetadatumOutput(t *testing.T) {
|
||||
pulumiTest(t, func(ctx *pulumi.Context) error {
|
||||
output := GetIntegrationRuntimeObjectMetadatumOutput(ctx, GetIntegrationRuntimeObjectMetadatumOutputArgs{
|
||||
FactoryName: pulumi.String("my-factory-name"),
|
||||
IntegrationRuntimeName: pulumi.String("my-integration-runtime-name"),
|
||||
MetadataPath: pulumi.String("my-metadata-path"),
|
||||
ResourceGroupName: pulumi.String("my-resource-group-name"),
|
||||
})
|
||||
nextLink := waitOut(t, output.NextLink())
|
||||
assert.Equal(t, "my-next-link", *(nextLink.(*string)))
|
||||
|
||||
value := waitOut(t, output.Value())
|
||||
assert.Equal(t, []interface{}{"factoryName=my-factory-name"}, value)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func pulumiTest(t *testing.T, testBody func(ctx *pulumi.Context) error) {
|
||||
err := pulumi.RunErr(testBody, pulumi.WithMocks("project", "stack", mocks(0)))
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func waitOut(t *testing.T, output pulumi.Output) interface{} {
|
||||
result, err := waitOutput(output, 1*time.Second)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return nil
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func waitOutput(output pulumi.Output, timeout time.Duration) (interface{}, error) {
|
||||
c := make(chan interface{}, 2)
|
||||
output.ApplyT(func(v interface{}) interface{} {
|
||||
c <- v
|
||||
return v
|
||||
})
|
||||
var timeoutMarker *int = new(int)
|
||||
go func() {
|
||||
time.Sleep(timeout)
|
||||
c <- timeoutMarker
|
||||
}()
|
||||
|
||||
result := <-c
|
||||
if result == timeoutMarker {
|
||||
return nil, fmt.Errorf("Timed out waiting for pulumi.Output after %v", timeout)
|
||||
} else {
|
||||
return result, nil
|
||||
}
|
||||
}
|
74
pkg/codegen/internal/test/testdata/output-funcs/go/funcWithAllOptionalInputs.go
vendored
Normal file
|
@ -0,0 +1,74 @@
|
|||
// *** WARNING: this file was generated by tool. ***
|
||||
// *** Do not edit by hand unless you're certain you know what you are doing! ***
|
||||
|
||||
package codegentest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
|
||||
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
|
||||
)
|
||||
|
||||
// Check codegen of functions with all optional inputs.
|
||||
func FuncWithAllOptionalInputs(ctx *pulumi.Context, args *FuncWithAllOptionalInputsArgs, opts ...pulumi.InvokeOption) (*FuncWithAllOptionalInputsResult, error) {
|
||||
var rv FuncWithAllOptionalInputsResult
|
||||
err := ctx.Invoke("madeup-package:codegentest:funcWithAllOptionalInputs", args, &rv, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &rv, nil
|
||||
}
|
||||
|
||||
type FuncWithAllOptionalInputsArgs struct {
|
||||
A *string `pulumi:"a"`
|
||||
B *string `pulumi:"b"`
|
||||
}
|
||||
|
||||
|
||||
type FuncWithAllOptionalInputsResult struct {
|
||||
R string `pulumi:"r"`
|
||||
}
|
||||
|
||||
|
||||
func FuncWithAllOptionalInputsOutput(ctx *pulumi.Context, args FuncWithAllOptionalInputsOutputArgs, opts ...pulumi.InvokeOption) FuncWithAllOptionalInputsResultOutput {
|
||||
return pulumi.ToOutputWithContext(context.Background(), args).
|
||||
ApplyT(func(v interface{}) (FuncWithAllOptionalInputsResult, error) {
|
||||
args := v.(FuncWithAllOptionalInputsArgs)
|
||||
r, err := FuncWithAllOptionalInputs(ctx, &args, opts...)
|
||||
return *r, err
|
||||
}).(FuncWithAllOptionalInputsResultOutput)
|
||||
}
|
||||
|
||||
type FuncWithAllOptionalInputsOutputArgs struct {
|
||||
A pulumi.StringPtrInput `pulumi:"a"`
|
||||
B pulumi.StringPtrInput `pulumi:"b"`
|
||||
}
|
||||
|
||||
func (FuncWithAllOptionalInputsOutputArgs) ElementType() reflect.Type {
|
||||
return reflect.TypeOf((*FuncWithAllOptionalInputsArgs)(nil)).Elem()
|
||||
}
|
||||
|
||||
type FuncWithAllOptionalInputsResultOutput struct { *pulumi.OutputState }
|
||||
|
||||
func (FuncWithAllOptionalInputsResultOutput) ElementType() reflect.Type {
|
||||
return reflect.TypeOf((*FuncWithAllOptionalInputsResult)(nil)).Elem()
|
||||
}
|
||||
|
||||
func (o FuncWithAllOptionalInputsResultOutput) ToFuncWithAllOptionalInputsResultOutput() FuncWithAllOptionalInputsResultOutput {
|
||||
return o
|
||||
}
|
||||
|
||||
func (o FuncWithAllOptionalInputsResultOutput) ToFuncWithAllOptionalInputsResultOutputWithContext(ctx context.Context) FuncWithAllOptionalInputsResultOutput {
|
||||
return o
|
||||
}
|
||||
|
||||
func (o FuncWithAllOptionalInputsResultOutput) R() pulumi.StringOutput {
|
||||
return o.ApplyT(func (v FuncWithAllOptionalInputsResult) string { return v.R }).(pulumi.StringOutput)
|
||||
}
|
||||
|
||||
|
||||
func init() {
|
||||
pulumi.RegisterOutputType(FuncWithAllOptionalInputsResultOutput{})
|
||||
}
|
||||
|
20
pkg/codegen/internal/test/testdata/output-funcs/go/funcWithConstInput.go
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
// *** WARNING: this file was generated by tool. ***
|
||||
// *** Do not edit by hand unless you're certain you know what you are doing! ***
|
||||
|
||||
package codegentest
|
||||
|
||||
import (
|
||||
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
|
||||
)
|
||||
|
||||
// Codegen demo with const inputs
|
||||
func FuncWithConstInput(ctx *pulumi.Context, args *FuncWithConstInputArgs, opts ...pulumi.InvokeOption) error {
|
||||
var rv struct{}
|
||||
err := ctx.Invoke("madeup-package:codegentest:funcWithConstInput", args, &rv, opts...)
|
||||
return err
|
||||
}
|
||||
|
||||
type FuncWithConstInputArgs struct {
|
||||
PlainInput *string `pulumi:"plainInput"`
|
||||
}
|
||||
|
74
pkg/codegen/internal/test/testdata/output-funcs/go/funcWithDefaultValue.go
vendored
Normal file
|
@ -0,0 +1,74 @@
|
|||
// *** WARNING: this file was generated by tool. ***
|
||||
// *** Do not edit by hand unless you're certain you know what you are doing! ***
|
||||
|
||||
package codegentest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
|
||||
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
|
||||
)
|
||||
|
||||
// Check codegen of functions with default values.
|
||||
func FuncWithDefaultValue(ctx *pulumi.Context, args *FuncWithDefaultValueArgs, opts ...pulumi.InvokeOption) (*FuncWithDefaultValueResult, error) {
|
||||
var rv FuncWithDefaultValueResult
|
||||
err := ctx.Invoke("madeup-package:codegentest:funcWithDefaultValue", args, &rv, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &rv, nil
|
||||
}
|
||||
|
||||
type FuncWithDefaultValueArgs struct {
|
||||
A string `pulumi:"a"`
|
||||
B *string `pulumi:"b"`
|
||||
}
|
||||
|
||||
|
||||
type FuncWithDefaultValueResult struct {
|
||||
R string `pulumi:"r"`
|
||||
}
|
||||
|
||||
|
||||
func FuncWithDefaultValueOutput(ctx *pulumi.Context, args FuncWithDefaultValueOutputArgs, opts ...pulumi.InvokeOption) FuncWithDefaultValueResultOutput {
|
||||
return pulumi.ToOutputWithContext(context.Background(), args).
|
||||
ApplyT(func(v interface{}) (FuncWithDefaultValueResult, error) {
|
||||
args := v.(FuncWithDefaultValueArgs)
|
||||
r, err := FuncWithDefaultValue(ctx, &args, opts...)
|
||||
return *r, err
|
||||
}).(FuncWithDefaultValueResultOutput)
|
||||
}
|
||||
|
||||
type FuncWithDefaultValueOutputArgs struct {
|
||||
A pulumi.StringInput `pulumi:"a"`
|
||||
B pulumi.StringPtrInput `pulumi:"b"`
|
||||
}
|
||||
|
||||
func (FuncWithDefaultValueOutputArgs) ElementType() reflect.Type {
|
||||
return reflect.TypeOf((*FuncWithDefaultValueArgs)(nil)).Elem()
|
||||
}
|
||||
|
||||
type FuncWithDefaultValueResultOutput struct { *pulumi.OutputState }
|
||||
|
||||
func (FuncWithDefaultValueResultOutput) ElementType() reflect.Type {
|
||||
return reflect.TypeOf((*FuncWithDefaultValueResult)(nil)).Elem()
|
||||
}
|
||||
|
||||
func (o FuncWithDefaultValueResultOutput) ToFuncWithDefaultValueResultOutput() FuncWithDefaultValueResultOutput {
|
||||
return o
|
||||
}
|
||||
|
||||
func (o FuncWithDefaultValueResultOutput) ToFuncWithDefaultValueResultOutputWithContext(ctx context.Context) FuncWithDefaultValueResultOutput {
|
||||
return o
|
||||
}
|
||||
|
||||
func (o FuncWithDefaultValueResultOutput) R() pulumi.StringOutput {
|
||||
return o.ApplyT(func (v FuncWithDefaultValueResult) string { return v.R }).(pulumi.StringOutput)
|
||||
}
|
||||
|
||||
|
||||
func init() {
|
||||
pulumi.RegisterOutputType(FuncWithDefaultValueResultOutput{})
|
||||
}
|
||||
|
74
pkg/codegen/internal/test/testdata/output-funcs/go/funcWithDictParam.go
vendored
Normal file
|
@ -0,0 +1,74 @@
|
|||
// *** WARNING: this file was generated by tool. ***
|
||||
// *** Do not edit by hand unless you're certain you know what you are doing! ***
|
||||
|
||||
package codegentest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
|
||||
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
|
||||
)
|
||||
|
||||
// Check codegen of functions with a Dict<str,str> parameter.
|
||||
func FuncWithDictParam(ctx *pulumi.Context, args *FuncWithDictParamArgs, opts ...pulumi.InvokeOption) (*FuncWithDictParamResult, error) {
|
||||
var rv FuncWithDictParamResult
|
||||
err := ctx.Invoke("madeup-package:codegentest:funcWithDictParam", args, &rv, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &rv, nil
|
||||
}
|
||||
|
||||
type FuncWithDictParamArgs struct {
|
||||
A map[string]string `pulumi:"a"`
|
||||
B *string `pulumi:"b"`
|
||||
}
|
||||
|
||||
|
||||
type FuncWithDictParamResult struct {
|
||||
R string `pulumi:"r"`
|
||||
}
|
||||
|
||||
|
||||
func FuncWithDictParamOutput(ctx *pulumi.Context, args FuncWithDictParamOutputArgs, opts ...pulumi.InvokeOption) FuncWithDictParamResultOutput {
|
||||
return pulumi.ToOutputWithContext(context.Background(), args).
|
||||
ApplyT(func(v interface{}) (FuncWithDictParamResult, error) {
|
||||
args := v.(FuncWithDictParamArgs)
|
||||
r, err := FuncWithDictParam(ctx, &args, opts...)
|
||||
return *r, err
|
||||
}).(FuncWithDictParamResultOutput)
|
||||
}
|
||||
|
||||
type FuncWithDictParamOutputArgs struct {
|
||||
A pulumi.StringMapInput `pulumi:"a"`
|
||||
B pulumi.StringPtrInput `pulumi:"b"`
|
||||
}
|
||||
|
||||
func (FuncWithDictParamOutputArgs) ElementType() reflect.Type {
|
||||
return reflect.TypeOf((*FuncWithDictParamArgs)(nil)).Elem()
|
||||
}
|
||||
|
||||
type FuncWithDictParamResultOutput struct { *pulumi.OutputState }
|
||||
|
||||
func (FuncWithDictParamResultOutput) ElementType() reflect.Type {
|
||||
return reflect.TypeOf((*FuncWithDictParamResult)(nil)).Elem()
|
||||
}
|
||||
|
||||
func (o FuncWithDictParamResultOutput) ToFuncWithDictParamResultOutput() FuncWithDictParamResultOutput {
|
||||
return o
|
||||
}
|
||||
|
||||
func (o FuncWithDictParamResultOutput) ToFuncWithDictParamResultOutputWithContext(ctx context.Context) FuncWithDictParamResultOutput {
|
||||
return o
|
||||
}
|
||||
|
||||
func (o FuncWithDictParamResultOutput) R() pulumi.StringOutput {
|
||||
return o.ApplyT(func (v FuncWithDictParamResult) string { return v.R }).(pulumi.StringOutput)
|
||||
}
|
||||
|
||||
|
||||
func init() {
|
||||
pulumi.RegisterOutputType(FuncWithDictParamResultOutput{})
|
||||
}
|
||||
|
74
pkg/codegen/internal/test/testdata/output-funcs/go/funcWithListParam.go
vendored
Normal file
|
@ -0,0 +1,74 @@
|
|||
// *** WARNING: this file was generated by tool. ***
|
||||
// *** Do not edit by hand unless you're certain you know what you are doing! ***
|
||||
|
||||
package codegentest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
|
||||
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
|
||||
)
|
||||
|
||||
// Check codegen of functions with a List parameter.
|
||||
func FuncWithListParam(ctx *pulumi.Context, args *FuncWithListParamArgs, opts ...pulumi.InvokeOption) (*FuncWithListParamResult, error) {
|
||||
var rv FuncWithListParamResult
|
||||
err := ctx.Invoke("madeup-package:codegentest:funcWithListParam", args, &rv, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &rv, nil
|
||||
}
|
||||
|
||||
type FuncWithListParamArgs struct {
|
||||
A []string `pulumi:"a"`
|
||||
B *string `pulumi:"b"`
|
||||
}
|
||||
|
||||
|
||||
type FuncWithListParamResult struct {
|
||||
R string `pulumi:"r"`
|
||||
}
|
||||
|
||||
|
||||
func FuncWithListParamOutput(ctx *pulumi.Context, args FuncWithListParamOutputArgs, opts ...pulumi.InvokeOption) FuncWithListParamResultOutput {
|
||||
return pulumi.ToOutputWithContext(context.Background(), args).
|
||||
ApplyT(func(v interface{}) (FuncWithListParamResult, error) {
|
||||
args := v.(FuncWithListParamArgs)
|
||||
r, err := FuncWithListParam(ctx, &args, opts...)
|
||||
return *r, err
|
||||
}).(FuncWithListParamResultOutput)
|
||||
}
|
||||
|
||||
type FuncWithListParamOutputArgs struct {
|
||||
A pulumi.StringArrayInput `pulumi:"a"`
|
||||
B pulumi.StringPtrInput `pulumi:"b"`
|
||||
}
|
||||
|
||||
func (FuncWithListParamOutputArgs) ElementType() reflect.Type {
|
||||
return reflect.TypeOf((*FuncWithListParamArgs)(nil)).Elem()
|
||||
}
|
||||
|
||||
type FuncWithListParamResultOutput struct { *pulumi.OutputState }
|
||||
|
||||
func (FuncWithListParamResultOutput) ElementType() reflect.Type {
|
||||
return reflect.TypeOf((*FuncWithListParamResult)(nil)).Elem()
|
||||
}
|
||||
|
||||
func (o FuncWithListParamResultOutput) ToFuncWithListParamResultOutput() FuncWithListParamResultOutput {
|
||||
return o
|
||||
}
|
||||
|
||||
func (o FuncWithListParamResultOutput) ToFuncWithListParamResultOutputWithContext(ctx context.Context) FuncWithListParamResultOutput {
|
||||
return o
|
||||
}
|
||||
|
||||
func (o FuncWithListParamResultOutput) R() pulumi.StringOutput {
|
||||
return o.ApplyT(func (v FuncWithListParamResult) string { return v.R }).(pulumi.StringOutput)
|
||||
}
|
||||
|
||||
|
||||
func init() {
|
||||
pulumi.RegisterOutputType(FuncWithListParamResultOutput{})
|
||||
}
|
||||
|
31
pkg/codegen/internal/test/testdata/output-funcs/go/getClientConfig.go
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
// *** WARNING: this file was generated by tool. ***
|
||||
// *** Do not edit by hand unless you're certain you know what you are doing! ***
|
||||
|
||||
package codegentest
|
||||
|
||||
import (
|
||||
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
|
||||
)
|
||||
|
||||
// Use this function to access the current configuration of the native Azure provider.
|
||||
func GetClientConfig(ctx *pulumi.Context, opts ...pulumi.InvokeOption) (*GetClientConfigResult, error) {
|
||||
var rv GetClientConfigResult
|
||||
err := ctx.Invoke("azure-native:codegentest:getClientConfig", nil, &rv, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &rv, nil
|
||||
}
|
||||
|
||||
// Configuration values returned by getClientConfig.
|
||||
type GetClientConfigResult struct {
|
||||
// Azure Client ID (Application Object ID).
|
||||
ClientId string `pulumi:"clientId"`
|
||||
// Azure Object ID of the current user or service principal.
|
||||
ObjectId string `pulumi:"objectId"`
|
||||
// Azure Subscription ID
|
||||
SubscriptionId string `pulumi:"subscriptionId"`
|
||||
// Azure Tenant ID
|
||||
TenantId string `pulumi:"tenantId"`
|
||||
}
|
||||
|
98
pkg/codegen/internal/test/testdata/output-funcs/go/getIntegrationRuntimeObjectMetadatum.go
vendored
Normal file
|
@ -0,0 +1,98 @@
|
|||
// *** WARNING: this file was generated by tool. ***
|
||||
// *** Do not edit by hand unless you're certain you know what you are doing! ***
|
||||
|
||||
package codegentest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
|
||||
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
|
||||
)
|
||||
|
||||
// A list of SSIS object metadata.
|
||||
// API Version: 2018-06-01.
|
||||
func GetIntegrationRuntimeObjectMetadatum(ctx *pulumi.Context, args *GetIntegrationRuntimeObjectMetadatumArgs, opts ...pulumi.InvokeOption) (*GetIntegrationRuntimeObjectMetadatumResult, error) {
|
||||
var rv GetIntegrationRuntimeObjectMetadatumResult
|
||||
err := ctx.Invoke("azure-native:codegentest:getIntegrationRuntimeObjectMetadatum", args, &rv, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &rv, nil
|
||||
}
|
||||
|
||||
type GetIntegrationRuntimeObjectMetadatumArgs struct {
|
||||
// The factory name.
|
||||
FactoryName string `pulumi:"factoryName"`
|
||||
// The integration runtime name.
|
||||
IntegrationRuntimeName string `pulumi:"integrationRuntimeName"`
|
||||
// Metadata path.
|
||||
MetadataPath *string `pulumi:"metadataPath"`
|
||||
// The resource group name.
|
||||
ResourceGroupName string `pulumi:"resourceGroupName"`
|
||||
}
|
||||
|
||||
|
||||
// A list of SSIS object metadata.
|
||||
type GetIntegrationRuntimeObjectMetadatumResult struct {
|
||||
// The link to the next page of results, if any remaining results exist.
|
||||
NextLink *string `pulumi:"nextLink"`
|
||||
// List of SSIS object metadata.
|
||||
Value []interface{} `pulumi:"value"`
|
||||
}
|
||||
|
||||
|
||||
func GetIntegrationRuntimeObjectMetadatumOutput(ctx *pulumi.Context, args GetIntegrationRuntimeObjectMetadatumOutputArgs, opts ...pulumi.InvokeOption) GetIntegrationRuntimeObjectMetadatumResultOutput {
|
||||
return pulumi.ToOutputWithContext(context.Background(), args).
|
||||
ApplyT(func(v interface{}) (GetIntegrationRuntimeObjectMetadatumResult, error) {
|
||||
args := v.(GetIntegrationRuntimeObjectMetadatumArgs)
|
||||
r, err := GetIntegrationRuntimeObjectMetadatum(ctx, &args, opts...)
|
||||
return *r, err
|
||||
}).(GetIntegrationRuntimeObjectMetadatumResultOutput)
|
||||
}
|
||||
|
||||
type GetIntegrationRuntimeObjectMetadatumOutputArgs struct {
|
||||
// The factory name.
|
||||
FactoryName pulumi.StringInput `pulumi:"factoryName"`
|
||||
// The integration runtime name.
|
||||
IntegrationRuntimeName pulumi.StringInput `pulumi:"integrationRuntimeName"`
|
||||
// Metadata path.
|
||||
MetadataPath pulumi.StringPtrInput `pulumi:"metadataPath"`
|
||||
// The resource group name.
|
||||
ResourceGroupName pulumi.StringInput `pulumi:"resourceGroupName"`
|
||||
}
|
||||
|
||||
func (GetIntegrationRuntimeObjectMetadatumOutputArgs) ElementType() reflect.Type {
|
||||
return reflect.TypeOf((*GetIntegrationRuntimeObjectMetadatumArgs)(nil)).Elem()
|
||||
}
|
||||
|
||||
// A list of SSIS object metadata.
|
||||
type GetIntegrationRuntimeObjectMetadatumResultOutput struct { *pulumi.OutputState }
|
||||
|
||||
func (GetIntegrationRuntimeObjectMetadatumResultOutput) ElementType() reflect.Type {
|
||||
return reflect.TypeOf((*GetIntegrationRuntimeObjectMetadatumResult)(nil)).Elem()
|
||||
}
|
||||
|
||||
func (o GetIntegrationRuntimeObjectMetadatumResultOutput) ToGetIntegrationRuntimeObjectMetadatumResultOutput() GetIntegrationRuntimeObjectMetadatumResultOutput {
|
||||
return o
|
||||
}
|
||||
|
||||
func (o GetIntegrationRuntimeObjectMetadatumResultOutput) ToGetIntegrationRuntimeObjectMetadatumResultOutputWithContext(ctx context.Context) GetIntegrationRuntimeObjectMetadatumResultOutput {
|
||||
return o
|
||||
}
|
||||
|
||||
// The link to the next page of results, if any remaining results exist.
|
||||
func (o GetIntegrationRuntimeObjectMetadatumResultOutput) NextLink() pulumi.StringPtrOutput {
|
||||
return o.ApplyT(func (v GetIntegrationRuntimeObjectMetadatumResult) *string { return v.NextLink }).(pulumi.StringPtrOutput)
|
||||
}
|
||||
|
||||
// List of SSIS object metadata.
|
||||
func (o GetIntegrationRuntimeObjectMetadatumResultOutput) Value() pulumi.ArrayOutput {
|
||||
return o.ApplyT(func (v GetIntegrationRuntimeObjectMetadatumResult) []interface{} { return v.Value }).(pulumi.ArrayOutput)
|
||||
}
|
||||
|
||||
|
||||
func init() {
|
||||
pulumi.RegisterOutputType(GetIntegrationRuntimeObjectMetadatumResultOutput{})
|
||||
}
|
||||
|
10
pkg/codegen/internal/test/testdata/output-funcs/go/go.mod
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
module codegentest
|
||||
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/pulumi/pulumi/sdk/v3 v3.2.1
|
||||
github.com/stretchr/testify v1.6.1
|
||||
)
|
||||
|
||||
replace github.com/pulumi/pulumi/sdk/v3 => ../../../../../../../sdk
|
342
pkg/codegen/internal/test/testdata/output-funcs/go/go.sum
vendored
Normal file
|
@ -0,0 +1,342 @@
|
|||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs=
|
||||
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
|
||||
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/cheggaaa/pb v1.0.18 h1:G/DgkKaBP0V5lnBg/vx61nVxxAU+VqU5yMzSc0f2PPE=
|
||||
github.com/cheggaaa/pb v1.0.18/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd h1:qMd81Ts1T2OTKmB4acZcyKaMtRnY5Y44NuXGX2GFJ1w=
|
||||
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
|
||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/djherbis/times v1.2.0 h1:xANXjsC/iBqbO00vkWlYwPWgBgEVU6m6AFYg0Pic+Mc=
|
||||
github.com/djherbis/times v1.2.0/go.mod h1:CGMZlo255K5r4Yw0b9RRfFQpM2y7uOmxg4jm9HsaVf8=
|
||||
github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg=
|
||||
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s=
|
||||
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
|
||||
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/gofrs/flock v0.7.1 h1:DP+LD/t0njgoPBvT5MJLeliUIVQR03hiKR6vezdwHlc=
|
||||
github.com/gofrs/flock v0.7.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
|
||||
github.com/gofrs/uuid v3.3.0+incompatible h1:8K4tyRfvU1CYPgJsveYFQMhpFd/wXNM7iK6rR7UHz84=
|
||||
github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
|
||||
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.4.1 h1:/exdXoGamhu5ONeUJH0deniYLWYvQwW66yvlfiiKTu0=
|
||||
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 h1:MJG/KsmcqMwFAkh8mTnAwhyKoB+sTAnY4CACC110tbU=
|
||||
github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645/go.mod h1:6iZfnjpejD4L/4DwD7NryNaJyCQdzwWwH2MWhCA90Kw=
|
||||
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o=
|
||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd h1:Coekwdh0v2wtGp9Gmz1Ze3eVRAWJMLokvN3QjdzCHLY=
|
||||
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE=
|
||||
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-runewidth v0.0.8 h1:3tS41NlGYSmhhe/8fhGRzc+z3AYCw1Fe1WAyLuujKs0=
|
||||
github.com/mattn/go-runewidth v0.0.8/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc=
|
||||
github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
github.com/opentracing/basictracer-go v1.0.0 h1:YyUAhaEfjoWXclZVJ9sGoNct7j4TVk7lZWlQw5UXuoo=
|
||||
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
|
||||
github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU=
|
||||
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sabhiram/go-gitignore v0.0.0-20180611051255-d3107576ba94 h1:G04eS0JkAIVZfaJLjla9dNxkJCPiKIGZlw9AfOhzOD0=
|
||||
github.com/sabhiram/go-gitignore v0.0.0-20180611051255-d3107576ba94/go.mod h1:b18R55ulyQ/h3RaWyloPyER7fWQVZvimKKhnI5OfrJQ=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8=
|
||||
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
|
||||
github.com/src-d/gcfg v1.4.0 h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4=
|
||||
github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/texttheater/golang-levenshtein v0.0.0-20191208221605-eb6844b05fc6 h1:9VTskZOIRf2vKF3UL8TuWElry5pgUpV1tFSe/e/0m/E=
|
||||
github.com/texttheater/golang-levenshtein v0.0.0-20191208221605-eb6844b05fc6/go.mod h1:XDKHRm5ThF8YJjx001LtgelzsoaEcvnA7lVWz9EeX3g=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/tweekmonster/luser v0.0.0-20161003172636-3fa38070dbd7 h1:X9dsIWPuuEJlPX//UmRKophhOKCGXc46RVIGuttks68=
|
||||
github.com/tweekmonster/luser v0.0.0-20161003172636-3fa38070dbd7/go.mod h1:UxoP3EypF8JfGEjAII8jx1q8rQyDnX8qdTCs/UQBVIE=
|
||||
github.com/uber/jaeger-client-go v2.22.1+incompatible h1:NHcubEkVbahf9t3p75TOCR83gdUHXjRJvjoBh1yACsM=
|
||||
github.com/uber/jaeger-client-go v2.22.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
|
||||
github.com/uber/jaeger-lib v2.2.0+incompatible h1:MxZXOiR2JuoANZ3J6DE/U0kSFv/eJ/GfSYVCjK7dyaw=
|
||||
github.com/uber/jaeger-lib v2.2.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
|
||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||
github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70=
|
||||
github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk=
|
||||
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200317142112-1b76d66859c6 h1:TjszyFsQsyZNHwdVdZ5m7bjmreu0znc2kRYsEml9/Ww=
|
||||
golang.org/x/crypto v0.0.0-20200317142112-1b76d66859c6/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200602114024-627f9648deb9 h1:pNX+40auqi2JqRfOP1akLGtYcn15TUbkhwuCO3foqqM=
|
||||
golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980 h1:OjiUf46hAmXblsZdnoSXsEUSKU8r1UEzcL5RVZ4gO9Y=
|
||||
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
|
||||
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200608174601-1b747fd94509 h1:MI14dOfl3OG6Zd32w3ugsrvcUO810fDZdWakTq39dH4=
|
||||
golang.org/x/tools v0.0.0-20200608174601-1b747fd94509/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20200608115520-7c474a2e3482 h1:i+Aiej6cta/Frzp13/swvwz5O00kYcSe0A/C5Wd7zX8=
|
||||
google.golang.org/genproto v0.0.0-20200608115520-7c474a2e3482/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4=
|
||||
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.24.0 h1:UhZDfRO8JRQru4/+LlLE0BRKGF8L+PICnvYZmx/fEGA=
|
||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/cheggaaa/pb.v1 v1.0.28 h1:n1tBJnnK2r7g9OW2btFH91V92STTUevLXYFb8gy9EMk=
|
||||
gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
|
||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
gopkg.in/src-d/go-billy.v4 v4.3.2 h1:0SQA1pRztfTFx2miS8sA97XvooFeNOmvUenF4o0EcVg=
|
||||
gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98=
|
||||
gopkg.in/src-d/go-git-fixtures.v3 v3.5.0 h1:ivZFOIltbce2Mo8IjzUHAFoq/IylO9WHhNOAJK+LsJg=
|
||||
gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g=
|
||||
gopkg.in/src-d/go-git.v4 v4.13.1 h1:SRtFyV8Kxc0UP7aCHcijOMQGPxHSmMOPrzulQWolkYE=
|
||||
gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0 h1:ucqkfpjg9WzSUubAO62csmucvxl4/JeW3F4I4909XkM=
|
||||
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
|
87
pkg/codegen/internal/test/testdata/output-funcs/go/listStorageAccountKeys.go
vendored
Normal file
|
@ -0,0 +1,87 @@
|
|||
// *** WARNING: this file was generated by tool. ***
|
||||
// *** Do not edit by hand unless you're certain you know what you are doing! ***
|
||||
|
||||
package codegentest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
|
||||
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
|
||||
)
|
||||
|
||||
// The response from the ListKeys operation.
|
||||
// API Version: 2021-02-01.
|
||||
func ListStorageAccountKeys(ctx *pulumi.Context, args *ListStorageAccountKeysArgs, opts ...pulumi.InvokeOption) (*ListStorageAccountKeysResult, error) {
|
||||
var rv ListStorageAccountKeysResult
|
||||
err := ctx.Invoke("azure-native:codegentest:listStorageAccountKeys", args, &rv, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &rv, nil
|
||||
}
|
||||
|
||||
type ListStorageAccountKeysArgs struct {
|
||||
// The name of the storage account within the specified resource group. Storage account names must be between 3 and 24 characters in length and use numbers and lower-case letters only.
|
||||
AccountName string `pulumi:"accountName"`
|
||||
// Specifies type of the key to be listed. Possible value is kerb.
|
||||
Expand *string `pulumi:"expand"`
|
||||
// The name of the resource group within the user's subscription. The name is case insensitive.
|
||||
ResourceGroupName string `pulumi:"resourceGroupName"`
|
||||
}
|
||||
|
||||
|
||||
// The response from the ListKeys operation.
|
||||
type ListStorageAccountKeysResult struct {
|
||||
// Gets the list of storage account keys and their properties for the specified storage account.
|
||||
Keys []StorageAccountKeyResponse `pulumi:"keys"`
|
||||
}
|
||||
|
||||
|
||||
func ListStorageAccountKeysOutput(ctx *pulumi.Context, args ListStorageAccountKeysOutputArgs, opts ...pulumi.InvokeOption) ListStorageAccountKeysResultOutput {
|
||||
return pulumi.ToOutputWithContext(context.Background(), args).
|
||||
ApplyT(func(v interface{}) (ListStorageAccountKeysResult, error) {
|
||||
args := v.(ListStorageAccountKeysArgs)
|
||||
r, err := ListStorageAccountKeys(ctx, &args, opts...)
|
||||
return *r, err
|
||||
}).(ListStorageAccountKeysResultOutput)
|
||||
}
|
||||
|
||||
type ListStorageAccountKeysOutputArgs struct {
|
||||
// The name of the storage account within the specified resource group. Storage account names must be between 3 and 24 characters in length and use numbers and lower-case letters only.
|
||||
AccountName pulumi.StringInput `pulumi:"accountName"`
|
||||
// Specifies type of the key to be listed. Possible value is kerb.
|
||||
Expand pulumi.StringPtrInput `pulumi:"expand"`
|
||||
// The name of the resource group within the user's subscription. The name is case insensitive.
|
||||
ResourceGroupName pulumi.StringInput `pulumi:"resourceGroupName"`
|
||||
}
|
||||
|
||||
func (ListStorageAccountKeysOutputArgs) ElementType() reflect.Type {
|
||||
return reflect.TypeOf((*ListStorageAccountKeysArgs)(nil)).Elem()
|
||||
}
|
||||
|
||||
// The response from the ListKeys operation.
|
||||
type ListStorageAccountKeysResultOutput struct { *pulumi.OutputState }
|
||||
|
||||
func (ListStorageAccountKeysResultOutput) ElementType() reflect.Type {
|
||||
return reflect.TypeOf((*ListStorageAccountKeysResult)(nil)).Elem()
|
||||
}
|
||||
|
||||
func (o ListStorageAccountKeysResultOutput) ToListStorageAccountKeysResultOutput() ListStorageAccountKeysResultOutput {
|
||||
return o
|
||||
}
|
||||
|
||||
func (o ListStorageAccountKeysResultOutput) ToListStorageAccountKeysResultOutputWithContext(ctx context.Context) ListStorageAccountKeysResultOutput {
|
||||
return o
|
||||
}
|
||||
|
||||
// Gets the list of storage account keys and their properties for the specified storage account.
|
||||
func (o ListStorageAccountKeysResultOutput) Keys() StorageAccountKeyResponseArrayOutput {
|
||||
return o.ApplyT(func (v ListStorageAccountKeysResult) []StorageAccountKeyResponse { return v.Keys }).(StorageAccountKeyResponseArrayOutput)
|
||||
}
|
||||
|
||||
|
||||
func init() {
|
||||
pulumi.RegisterOutputType(ListStorageAccountKeysResultOutput{})
|
||||
}
|
||||
|
51
pkg/codegen/internal/test/testdata/output-funcs/go/misc.go
vendored
Normal file
|
@ -0,0 +1,51 @@
|
|||
// Copyright 2016-2021, Pulumi Corporation.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// This code is hand-added to make generated code compile.
|
||||
package codegentest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
|
||||
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
|
||||
)
|
||||
|
||||
// An access key for the storage account.
|
||||
type StorageAccountKeyResponse struct {
|
||||
// Name of the key.
|
||||
KeyName string `pulumi:"keyName"`
|
||||
// Permissions for the key -- read-only or full permissions.
|
||||
Permissions string `pulumi:"permissions"`
|
||||
// Base 64-encoded value of the key.
|
||||
Value string `pulumi:"value"`
|
||||
}
|
||||
|
||||
type StorageAccountKeyResponseArrayOutput struct{ *pulumi.OutputState }
|
||||
|
||||
func (StorageAccountKeyResponseArrayOutput) ElementType() reflect.Type {
|
||||
return reflect.TypeOf((*[]StorageAccountKeyResponse)(nil)).Elem()
|
||||
}
|
||||
|
||||
func (o StorageAccountKeyResponseArrayOutput) ToStorageAccountKeyResponseArrayOutput() StorageAccountKeyResponseArrayOutput {
|
||||
return o
|
||||
}
|
||||
|
||||
func (o StorageAccountKeyResponseArrayOutput) ToStorageAccountKeyResponseArrayOutputWithContext(ctx context.Context) StorageAccountKeyResponseArrayOutput {
|
||||
return o
|
||||
}
|
||||
|
||||
func init() {
|
||||
pulumi.RegisterOutputType(StorageAccountKeyResponseArrayOutput{})
|
||||
}
|
75
pkg/codegen/internal/test/testdata/output-funcs/listStorageAccountKeys.json
vendored
Normal file
|
@ -0,0 +1,75 @@
|
|||
{
|
||||
"functions": {
|
||||
"azure-native:codegentest:listStorageAccountKeys": {
|
||||
"description": "The response from the ListKeys operation.\nAPI Version: 2021-02-01.",
|
||||
"inputs": {
|
||||
"properties": {
|
||||
"accountName": {
|
||||
"type": "string",
|
||||
"description": "The name of the storage account within the specified resource group. Storage account names must be between 3 and 24 characters in length and use numbers and lower-case letters only."
|
||||
},
|
||||
"expand": {
|
||||
"type": "string",
|
||||
"description": "Specifies type of the key to be listed. Possible value is kerb."
|
||||
},
|
||||
"resourceGroupName": {
|
||||
"type": "string",
|
||||
"description": "The name of the resource group within the user's subscription. The name is case insensitive."
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"accountName",
|
||||
"resourceGroupName"
|
||||
]
|
||||
},
|
||||
"outputs": {
|
||||
"description": "The response from the ListKeys operation.",
|
||||
"properties": {
|
||||
"keys": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"$ref": "#/types/azure-native:codegentest:StorageAccountKeyResponse"
|
||||
},
|
||||
"description": "Gets the list of storage account keys and their properties for the specified storage account."
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"keys"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"types": {
|
||||
"azure-native:codegentest:StorageAccountKeyResponse": {
|
||||
"description": "An access key for the storage account.",
|
||||
"properties": {
|
||||
"creationTime": {
|
||||
"type": "string",
|
||||
"description": "Creation time of the key, in round trip date format."
|
||||
},
|
||||
"keyName": {
|
||||
"type": "string",
|
||||
"description": "Name of the key."
|
||||
},
|
||||
"permissions": {
|
||||
"type": "string",
|
||||
"description": "Permissions for the key -- read-only or full permissions."
|
||||
},
|
||||
"value": {
|
||||
"type": "string",
|
||||
"description": "Base 64-encoded value of the key."
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"creationTime",
|
||||
"keyName",
|
||||
"permissions",
|
||||
"value"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -43,6 +43,47 @@ func (i BazArgs) ToBazOutputWithContext(ctx context.Context) BazOutput {
|
|||
return pulumi.ToOutputWithContext(ctx, i).(BazOutput)
|
||||
}
|
||||
|
||||
func (i BazArgs) ToBazPtrOutput() BazPtrOutput {
|
||||
return i.ToBazPtrOutputWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (i BazArgs) ToBazPtrOutputWithContext(ctx context.Context) BazPtrOutput {
|
||||
return pulumi.ToOutputWithContext(ctx, i).(BazOutput).ToBazPtrOutputWithContext(ctx)
|
||||
}
|
||||
|
||||
// BazPtrInput is an input type that accepts BazArgs, BazPtr and BazPtrOutput values.
|
||||
// You can construct a concrete instance of `BazPtrInput` via:
|
||||
//
|
||||
// BazArgs{...}
|
||||
//
|
||||
// or:
|
||||
//
|
||||
// nil
|
||||
type BazPtrInput interface {
|
||||
pulumi.Input
|
||||
|
||||
ToBazPtrOutput() BazPtrOutput
|
||||
ToBazPtrOutputWithContext(context.Context) BazPtrOutput
|
||||
}
|
||||
|
||||
type bazPtrType BazArgs
|
||||
|
||||
func BazPtr(v *BazArgs) BazPtrInput {
|
||||
return (*bazPtrType)(v)
|
||||
}
|
||||
|
||||
func (*bazPtrType) ElementType() reflect.Type {
|
||||
return reflect.TypeOf((**Baz)(nil)).Elem()
|
||||
}
|
||||
|
||||
func (i *bazPtrType) ToBazPtrOutput() BazPtrOutput {
|
||||
return i.ToBazPtrOutputWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (i *bazPtrType) ToBazPtrOutputWithContext(ctx context.Context) BazPtrOutput {
|
||||
return pulumi.ToOutputWithContext(ctx, i).(BazPtrOutput)
|
||||
}
|
||||
|
||||
type BazOutput struct{ *pulumi.OutputState }
|
||||
|
||||
func (BazOutput) ElementType() reflect.Type {
|
||||
|
@ -57,6 +98,16 @@ func (o BazOutput) ToBazOutputWithContext(ctx context.Context) BazOutput {
|
|||
return o
|
||||
}
|
||||
|
||||
func (o BazOutput) ToBazPtrOutput() BazPtrOutput {
|
||||
return o.ToBazPtrOutputWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (o BazOutput) ToBazPtrOutputWithContext(ctx context.Context) BazPtrOutput {
|
||||
return o.ApplyTWithContext(ctx, func(_ context.Context, v Baz) *Baz {
|
||||
return &v
|
||||
}).(BazPtrOutput)
|
||||
}
|
||||
|
||||
func (o BazOutput) Hello() pulumi.StringPtrOutput {
|
||||
return o.ApplyT(func(v Baz) *string { return v.Hello }).(pulumi.StringPtrOutput)
|
||||
}
|
||||
|
@ -65,6 +116,49 @@ func (o BazOutput) World() pulumi.StringPtrOutput {
|
|||
return o.ApplyT(func(v Baz) *string { return v.World }).(pulumi.StringPtrOutput)
|
||||
}
|
||||
|
||||
type BazPtrOutput struct{ *pulumi.OutputState }
|
||||
|
||||
func (BazPtrOutput) ElementType() reflect.Type {
|
||||
return reflect.TypeOf((**Baz)(nil)).Elem()
|
||||
}
|
||||
|
||||
func (o BazPtrOutput) ToBazPtrOutput() BazPtrOutput {
|
||||
return o
|
||||
}
|
||||
|
||||
func (o BazPtrOutput) ToBazPtrOutputWithContext(ctx context.Context) BazPtrOutput {
|
||||
return o
|
||||
}
|
||||
|
||||
func (o BazPtrOutput) Elem() BazOutput {
|
||||
return o.ApplyT(func(v *Baz) Baz {
|
||||
if v != nil {
|
||||
return *v
|
||||
}
|
||||
var ret Baz
|
||||
return ret
|
||||
}).(BazOutput)
|
||||
}
|
||||
|
||||
func (o BazPtrOutput) Hello() pulumi.StringPtrOutput {
|
||||
return o.ApplyT(func(v *Baz) *string {
|
||||
if v == nil {
|
||||
return nil
|
||||
}
|
||||
return v.Hello
|
||||
}).(pulumi.StringPtrOutput)
|
||||
}
|
||||
|
||||
func (o BazPtrOutput) World() pulumi.StringPtrOutput {
|
||||
return o.ApplyT(func(v *Baz) *string {
|
||||
if v == nil {
|
||||
return nil
|
||||
}
|
||||
return v.World
|
||||
}).(pulumi.StringPtrOutput)
|
||||
}
|
||||
|
||||
func init() {
|
||||
pulumi.RegisterOutputType(BazOutput{})
|
||||
pulumi.RegisterOutputType(BazPtrOutput{})
|
||||
}
|
||||
|
|
|
@ -4,6 +4,9 @@
|
|||
package example
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
|
||||
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
|
||||
)
|
||||
|
||||
|
@ -23,3 +26,42 @@ type ArgFunctionArgs struct {
|
|||
type ArgFunctionResult struct {
|
||||
Result *Resource `pulumi:"result"`
|
||||
}
|
||||
|
||||
func ArgFunctionOutput(ctx *pulumi.Context, args ArgFunctionOutputArgs, opts ...pulumi.InvokeOption) ArgFunctionResultOutput {
|
||||
return pulumi.ToOutputWithContext(context.Background(), args).
|
||||
ApplyT(func(v interface{}) (ArgFunctionResult, error) {
|
||||
args := v.(ArgFunctionArgs)
|
||||
r, err := ArgFunction(ctx, &args, opts...)
|
||||
return *r, err
|
||||
}).(ArgFunctionResultOutput)
|
||||
}
|
||||
|
||||
type ArgFunctionOutputArgs struct {
|
||||
Arg1 ResourceInput `pulumi:"arg1"`
|
||||
}
|
||||
|
||||
func (ArgFunctionOutputArgs) ElementType() reflect.Type {
|
||||
return reflect.TypeOf((*ArgFunctionArgs)(nil)).Elem()
|
||||
}
|
||||
|
||||
type ArgFunctionResultOutput struct{ *pulumi.OutputState }
|
||||
|
||||
func (ArgFunctionResultOutput) ElementType() reflect.Type {
|
||||
return reflect.TypeOf((*ArgFunctionResult)(nil)).Elem()
|
||||
}
|
||||
|
||||
func (o ArgFunctionResultOutput) ToArgFunctionResultOutput() ArgFunctionResultOutput {
|
||||
return o
|
||||
}
|
||||
|
||||
func (o ArgFunctionResultOutput) ToArgFunctionResultOutputWithContext(ctx context.Context) ArgFunctionResultOutput {
|
||||
return o
|
||||
}
|
||||
|
||||
func (o ArgFunctionResultOutput) Result() ResourceOutput {
|
||||
return o.ApplyT(func(v ArgFunctionResult) *Resource { return v.Result }).(ResourceOutput)
|
||||
}
|
||||
|
||||
func init() {
|
||||
pulumi.RegisterOutputType(ArgFunctionResultOutput{})
|
||||
}
|
||||
|
|
|
@ -4,6 +4,9 @@
|
|||
package example
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
|
||||
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
|
||||
)
|
||||
|
||||
|
@ -23,3 +26,42 @@ type ArgFunctionArgs struct {
|
|||
type ArgFunctionResult struct {
|
||||
Result *Resource `pulumi:"result"`
|
||||
}
|
||||
|
||||
func ArgFunctionOutput(ctx *pulumi.Context, args ArgFunctionOutputArgs, opts ...pulumi.InvokeOption) ArgFunctionResultOutput {
|
||||
return pulumi.ToOutputWithContext(context.Background(), args).
|
||||
ApplyT(func(v interface{}) (ArgFunctionResult, error) {
|
||||
args := v.(ArgFunctionArgs)
|
||||
r, err := ArgFunction(ctx, &args, opts...)
|
||||
return *r, err
|
||||
}).(ArgFunctionResultOutput)
|
||||
}
|
||||
|
||||
type ArgFunctionOutputArgs struct {
|
||||
Arg1 ResourceInput `pulumi:"arg1"`
|
||||
}
|
||||
|
||||
func (ArgFunctionOutputArgs) ElementType() reflect.Type {
|
||||
return reflect.TypeOf((*ArgFunctionArgs)(nil)).Elem()
|
||||
}
|
||||
|
||||
type ArgFunctionResultOutput struct{ *pulumi.OutputState }
|
||||
|
||||
func (ArgFunctionResultOutput) ElementType() reflect.Type {
|
||||
return reflect.TypeOf((*ArgFunctionResult)(nil)).Elem()
|
||||
}
|
||||
|
||||
func (o ArgFunctionResultOutput) ToArgFunctionResultOutput() ArgFunctionResultOutput {
|
||||
return o
|
||||
}
|
||||
|
||||
func (o ArgFunctionResultOutput) ToArgFunctionResultOutputWithContext(ctx context.Context) ArgFunctionResultOutput {
|
||||
return o
|
||||
}
|
||||
|
||||
func (o ArgFunctionResultOutput) Result() ResourceOutput {
|
||||
return o.ApplyT(func(v ArgFunctionResult) *Resource { return v.Result }).(ResourceOutput)
|
||||
}
|
||||
|
||||
func init() {
|
||||
pulumi.RegisterOutputType(ArgFunctionResultOutput{})
|
||||
}
|
||||
|
|
|
@ -4,6 +4,9 @@
|
|||
package example
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
|
||||
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
|
||||
)
|
||||
|
||||
|
@ -23,3 +26,42 @@ type ArgFunctionArgs struct {
|
|||
type ArgFunctionResult struct {
|
||||
Result *Resource `pulumi:"result"`
|
||||
}
|
||||
|
||||
func ArgFunctionOutput(ctx *pulumi.Context, args ArgFunctionOutputArgs, opts ...pulumi.InvokeOption) ArgFunctionResultOutput {
|
||||
return pulumi.ToOutputWithContext(context.Background(), args).
|
||||
ApplyT(func(v interface{}) (ArgFunctionResult, error) {
|
||||
args := v.(ArgFunctionArgs)
|
||||
r, err := ArgFunction(ctx, &args, opts...)
|
||||
return *r, err
|
||||
}).(ArgFunctionResultOutput)
|
||||
}
|
||||
|
||||
type ArgFunctionOutputArgs struct {
|
||||
Arg1 ResourceInput `pulumi:"arg1"`
|
||||
}
|
||||
|
||||
func (ArgFunctionOutputArgs) ElementType() reflect.Type {
|
||||
return reflect.TypeOf((*ArgFunctionArgs)(nil)).Elem()
|
||||
}
|
||||
|
||||
type ArgFunctionResultOutput struct{ *pulumi.OutputState }
|
||||
|
||||
func (ArgFunctionResultOutput) ElementType() reflect.Type {
|
||||
return reflect.TypeOf((*ArgFunctionResult)(nil)).Elem()
|
||||
}
|
||||
|
||||
func (o ArgFunctionResultOutput) ToArgFunctionResultOutput() ArgFunctionResultOutput {
|
||||
return o
|
||||
}
|
||||
|
||||
func (o ArgFunctionResultOutput) ToArgFunctionResultOutputWithContext(ctx context.Context) ArgFunctionResultOutput {
|
||||
return o
|
||||
}
|
||||
|
||||
func (o ArgFunctionResultOutput) Result() ResourceOutput {
|
||||
return o.ApplyT(func(v ArgFunctionResult) *Resource { return v.Result }).(ResourceOutput)
|
||||
}
|
||||
|
||||
func init() {
|
||||
pulumi.RegisterOutputType(ArgFunctionResultOutput{})
|
||||
}
|
||||
|
|
|
@ -1541,7 +1541,7 @@ const (
|
|||
)
|
||||
|
||||
// Regex used to parse external schema paths. This is declared at the package scope to avoid repeated recompilation.
|
||||
var refPathRegex = regexp.MustCompile(`^/?(?P<package>\w+)/(?P<version>v[^/]*)/schema\.json$`)
|
||||
var refPathRegex = regexp.MustCompile(`^/?(?P<package>[-\w]+)/(?P<version>v[^/]*)/schema\.json$`)
|
||||
|
||||
func (t *types) parseTypeSpecRef(ref string) (typeSpecRef, error) {
|
||||
parsedURL, err := url.Parse(ref)
|
||||
|
@ -2439,3 +2439,29 @@ func jsonMarshal(v interface{}) ([]byte, error) {
|
|||
}
|
||||
return b.Bytes(), nil
|
||||
}
|
||||
|
||||
// Determines if codegen should emit a ${fn}Output version that
|
||||
// automatically accepts Inputs and returns Outputs.
|
||||
func (fun *Function) NeedsOutputVersion() bool {
|
||||
|
||||
// Skip functions that return no value. Arguably we could
|
||||
// support them and return `Task`, but there are no such
|
||||
// functions in `pulumi-azure-native` or `pulumi-aws` so we
|
||||
// omit to simplify.
|
||||
if fun.Outputs == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// Skip functions that have no inputs. The user can simply
|
||||
// lift the `Task` to `Output` manually.
|
||||
if fun.Inputs == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// No properties is kind of like no inputs.
|
||||
if len(fun.Inputs.Properties) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -310,6 +310,17 @@ func Test_parseTypeSpecRef(t *testing.T) {
|
|||
Token: "pulumi:providers:kubernetes",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "hyphenatedUrlPath",
|
||||
ref: "/azure-native/v1.22.0/schema.json#/resources/azure-native:web:WebApp",
|
||||
want: typeSpecRef{
|
||||
URL: toURL("/azure-native/v1.22.0/schema.json#/resources/azure-native:web:WebApp"),
|
||||
Package: "azure-native",
|
||||
Version: toVersionPtr("1.22.0"),
|
||||
Kind: "resources",
|
||||
Token: "azure-native:web:WebApp",
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
|
|
@ -624,8 +624,31 @@ namespace Pulumi.Automation
|
|||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Task InstallPluginAsync(string name, string version, PluginKind kind = PluginKind.Resource, CancellationToken cancellationToken = default)
|
||||
=> this.RunCommandAsync(new[] { "plugin", "install", kind.ToString().ToLower(), name, version }, cancellationToken);
|
||||
public override Task InstallPluginAsync(string name, string version, PluginKind kind = PluginKind.Resource, PluginInstallOptions? options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var args = new List<string>
|
||||
{
|
||||
"plugin",
|
||||
"install",
|
||||
kind.ToString().ToLowerInvariant(),
|
||||
name,
|
||||
version
|
||||
};
|
||||
|
||||
if (options != null)
|
||||
{
|
||||
if (options.ExactVersion)
|
||||
args.Add("--exact");
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(options.ServerUrl))
|
||||
{
|
||||
args.Add("--server");
|
||||
args.Add(options.ServerUrl);
|
||||
}
|
||||
}
|
||||
|
||||
return this.RunCommandAsync(args, cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Task RemovePluginAsync(string? name = null, string? versionRange = null, PluginKind kind = PluginKind.Resource, CancellationToken cancellationToken = default)
|
||||
|
|
17
sdk/dotnet/Pulumi.Automation/PluginInstallOptions.cs
Normal file
|
@ -0,0 +1,17 @@
|
|||
namespace Pulumi.Automation
|
||||
{
|
||||
public class PluginInstallOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// If <c>true</c>, force installation of an exact version match (usually >= is accepted).
|
||||
/// <para/>
|
||||
/// Defaults to <c>false</c>.
|
||||
/// </summary>
|
||||
public bool ExactVersion { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A URL to download plugins from.
|
||||
/// </summary>
|
||||
public string? ServerUrl { get; set; }
|
||||
}
|
||||
}
|
|
@ -158,6 +158,12 @@ Pulumi.Automation.PluginInfo.Path.get -> string
|
|||
Pulumi.Automation.PluginInfo.ServerUrl.get -> string
|
||||
Pulumi.Automation.PluginInfo.Size.get -> long
|
||||
Pulumi.Automation.PluginInfo.Version.get -> string
|
||||
Pulumi.Automation.PluginInstallOptions
|
||||
Pulumi.Automation.PluginInstallOptions.ExactVersion.get -> bool
|
||||
Pulumi.Automation.PluginInstallOptions.ExactVersion.set -> void
|
||||
Pulumi.Automation.PluginInstallOptions.PluginInstallOptions() -> void
|
||||
Pulumi.Automation.PluginInstallOptions.ServerUrl.get -> string
|
||||
Pulumi.Automation.PluginInstallOptions.ServerUrl.set -> void
|
||||
Pulumi.Automation.PluginKind
|
||||
Pulumi.Automation.PluginKind.Analyzer = 0 -> Pulumi.Automation.PluginKind
|
||||
Pulumi.Automation.PluginKind.Language = 1 -> Pulumi.Automation.PluginKind
|
||||
|
@ -332,6 +338,7 @@ Pulumi.Automation.WhoAmIResult.User.get -> string
|
|||
Pulumi.Automation.WhoAmIResult.WhoAmIResult(string user) -> void
|
||||
Pulumi.Automation.Workspace
|
||||
Pulumi.Automation.Workspace.CreateStackAsync(string stackName) -> System.Threading.Tasks.Task
|
||||
Pulumi.Automation.Workspace.InstallPluginAsync(string name, string version, Pulumi.Automation.PluginKind kind, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task
|
||||
Pulumi.Automation.Workspace.SelectStackAsync(string stackName) -> System.Threading.Tasks.Task
|
||||
Pulumi.Automation.WorkspaceStack
|
||||
Pulumi.Automation.WorkspaceStack.DestroyAsync(Pulumi.Automation.DestroyOptions options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task<Pulumi.Automation.UpdateResult>
|
||||
|
@ -359,7 +366,7 @@ abstract Pulumi.Automation.Workspace.GetConfigAsync(string stackName, string key
|
|||
abstract Pulumi.Automation.Workspace.GetProjectSettingsAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task<Pulumi.Automation.ProjectSettings>
|
||||
abstract Pulumi.Automation.Workspace.GetStackOutputsAsync(string stackName, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task<System.Collections.Immutable.ImmutableDictionary<string, Pulumi.Automation.OutputValue>>
|
||||
abstract Pulumi.Automation.Workspace.GetStackSettingsAsync(string stackName, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task<Pulumi.Automation.StackSettings>
|
||||
abstract Pulumi.Automation.Workspace.InstallPluginAsync(string name, string version, Pulumi.Automation.PluginKind kind = Pulumi.Automation.PluginKind.Resource, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task
|
||||
abstract Pulumi.Automation.Workspace.InstallPluginAsync(string name, string version, Pulumi.Automation.PluginKind kind = Pulumi.Automation.PluginKind.Resource, Pulumi.Automation.PluginInstallOptions options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task
|
||||
abstract Pulumi.Automation.Workspace.ListPluginsAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task<System.Collections.Immutable.ImmutableList<Pulumi.Automation.PluginInfo>>
|
||||
abstract Pulumi.Automation.Workspace.ListStacksAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task<System.Collections.Immutable.ImmutableList<Pulumi.Automation.StackSummary>>
|
||||
abstract Pulumi.Automation.Workspace.Logger.get -> Microsoft.Extensions.Logging.ILogger
|
||||
|
@ -392,7 +399,7 @@ override Pulumi.Automation.LocalWorkspace.GetConfigAsync(string stackName, strin
|
|||
override Pulumi.Automation.LocalWorkspace.GetProjectSettingsAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task<Pulumi.Automation.ProjectSettings>
|
||||
override Pulumi.Automation.LocalWorkspace.GetStackOutputsAsync(string stackName, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task<System.Collections.Immutable.ImmutableDictionary<string, Pulumi.Automation.OutputValue>>
|
||||
override Pulumi.Automation.LocalWorkspace.GetStackSettingsAsync(string stackName, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task<Pulumi.Automation.StackSettings>
|
||||
override Pulumi.Automation.LocalWorkspace.InstallPluginAsync(string name, string version, Pulumi.Automation.PluginKind kind = Pulumi.Automation.PluginKind.Resource, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task
|
||||
override Pulumi.Automation.LocalWorkspace.InstallPluginAsync(string name, string version, Pulumi.Automation.PluginKind kind = Pulumi.Automation.PluginKind.Resource, Pulumi.Automation.PluginInstallOptions options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task
|
||||
override Pulumi.Automation.LocalWorkspace.ListPluginsAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task<System.Collections.Immutable.ImmutableList<Pulumi.Automation.PluginInfo>>
|
||||
override Pulumi.Automation.LocalWorkspace.ListStacksAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task<System.Collections.Immutable.ImmutableList<Pulumi.Automation.StackSummary>>
|
||||
override Pulumi.Automation.LocalWorkspace.Logger.get -> Microsoft.Extensions.Logging.ILogger
|
||||
|
|
|
@ -593,7 +593,7 @@
|
|||
<member name="M:Pulumi.Automation.LocalWorkspace.ImportStackAsync(System.String,Pulumi.Automation.StackDeployment,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:Pulumi.Automation.LocalWorkspace.InstallPluginAsync(System.String,System.String,Pulumi.Automation.PluginKind,System.Threading.CancellationToken)">
|
||||
<member name="M:Pulumi.Automation.LocalWorkspace.InstallPluginAsync(System.String,System.String,Pulumi.Automation.PluginKind,Pulumi.Automation.PluginInstallOptions,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:Pulumi.Automation.LocalWorkspace.RemovePluginAsync(System.String,System.String,Pulumi.Automation.PluginKind,System.Threading.CancellationToken)">
|
||||
|
@ -665,6 +665,18 @@
|
|||
<see cref="M:Pulumi.Automation.LocalWorkspace.SaveStackSettingsAsync(System.String,Pulumi.Automation.StackSettings,System.Threading.CancellationToken)"/>.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Pulumi.Automation.PluginInstallOptions.ExactVersion">
|
||||
<summary>
|
||||
If <c>true</c>, force installation of an exact version match (usually >= is accepted).
|
||||
<para/>
|
||||
Defaults to <c>false</c>.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Pulumi.Automation.PluginInstallOptions.ServerUrl">
|
||||
<summary>
|
||||
A URL to download plugins from.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:Pulumi.Automation.PreviewOptions">
|
||||
<summary>
|
||||
Options controlling the behavior of an <see cref="M:Pulumi.Automation.WorkspaceStack.PreviewAsync(Pulumi.Automation.PreviewOptions,System.Threading.CancellationToken)"/> operation.
|
||||
|
@ -1123,13 +1135,14 @@
|
|||
stack's state (such as recovery from failed deployments).
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Pulumi.Automation.Workspace.InstallPluginAsync(System.String,System.String,Pulumi.Automation.PluginKind,System.Threading.CancellationToken)">
|
||||
<member name="M:Pulumi.Automation.Workspace.InstallPluginAsync(System.String,System.String,Pulumi.Automation.PluginKind,Pulumi.Automation.PluginInstallOptions,System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
Installs a plugin in the Workspace, for example to use cloud providers like AWS or GCP.
|
||||
</summary>
|
||||
<param name="name">The name of the plugin.</param>
|
||||
<param name="version">The version of the plugin e.g. "v1.0.0".</param>
|
||||
<param name="kind">The kind of plugin e.g. "resource".</param>
|
||||
<param name="options">Any additional plugin installation options.</param>
|
||||
<param name="cancellationToken">A cancellation token.</param>
|
||||
</member>
|
||||
<member name="M:Pulumi.Automation.Workspace.RemovePluginAsync(System.String,System.String,Pulumi.Automation.PluginKind,System.Threading.CancellationToken)">
|
||||
|
|
|
@ -260,7 +260,18 @@ namespace Pulumi.Automation
|
|||
/// <param name="version">The version of the plugin e.g. "v1.0.0".</param>
|
||||
/// <param name="kind">The kind of plugin e.g. "resource".</param>
|
||||
/// <param name="cancellationToken">A cancellation token.</param>
|
||||
public abstract Task InstallPluginAsync(string name, string version, PluginKind kind = PluginKind.Resource, CancellationToken cancellationToken = default);
|
||||
public Task InstallPluginAsync(string name, string version, PluginKind kind, CancellationToken cancellationToken)
|
||||
=> this.InstallPluginAsync(name, version, kind: kind, options: null, cancellationToken: cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Installs a plugin in the Workspace, for example to use cloud providers like AWS or GCP.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the plugin.</param>
|
||||
/// <param name="version">The version of the plugin e.g. "v1.0.0".</param>
|
||||
/// <param name="kind">The kind of plugin e.g. "resource".</param>
|
||||
/// <param name="options">Any additional plugin installation options.</param>
|
||||
/// <param name="cancellationToken">A cancellation token.</param>
|
||||
public abstract Task InstallPluginAsync(string name, string version, PluginKind kind = PluginKind.Resource, PluginInstallOptions? options = null, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Removes a plugin from the Workspace matching the specified name and version.
|
||||
|
|
28
sdk/dotnet/Pulumi/Deployment/CallOptions.cs
Normal file
|
@ -0,0 +1,28 @@
|
|||
// Copyright 2016-2021, Pulumi Corporation
|
||||
|
||||
namespace Pulumi
|
||||
{
|
||||
/// <summary>
|
||||
/// Options to help control the behavior of <see cref="Deployment.Call{T}"/>.
|
||||
/// </summary>
|
||||
public class CallOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// An optional parent to use for default options for this call (e.g. the default provider
|
||||
/// to use).
|
||||
/// </summary>
|
||||
public Resource? Parent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// An optional provider to use for this call. If no provider is supplied, the default
|
||||
/// provider for the called function's package will be used.
|
||||
/// </summary>
|
||||
public ProviderResource? Provider { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// An optional version, corresponding to the version of the provider plugin that should be
|
||||
/// used when performing this call.
|
||||
/// </summary>
|
||||
public string? Version { get; set; }
|
||||
}
|
||||
}
|
|
@ -8,7 +8,7 @@ namespace Pulumi
|
|||
public sealed class DeploymentInstance : IDeployment
|
||||
{
|
||||
private readonly IDeployment _deployment;
|
||||
|
||||
|
||||
internal DeploymentInstance(IDeployment deployment)
|
||||
{
|
||||
_deployment = deployment;
|
||||
|
@ -49,6 +49,25 @@ namespace Pulumi
|
|||
public Task InvokeAsync(string token, InvokeArgs args, InvokeOptions? options = null)
|
||||
=> _deployment.InvokeAsync(token, args, options);
|
||||
|
||||
/// <summary>
|
||||
/// Dynamically calls the function '<paramref name="token"/>', which is offered by a
|
||||
/// provider plugin.
|
||||
/// <para/>
|
||||
/// The result of <see cref="Call{T}"/> will be a <see cref="Output{T}"/> resolved to the
|
||||
/// result value of the provider plugin.
|
||||
/// <para/>
|
||||
/// The <paramref name="args"/> inputs can be a bag of computed values(including, `T`s,
|
||||
/// <see cref="Task{TResult}"/>s, <see cref="Output{T}"/>s etc.).
|
||||
/// </summary>
|
||||
public Output<T> Call<T>(string token, CallArgs args, Resource? self = null, CallOptions? options = null)
|
||||
=> _deployment.Call<T>(token, args, self, options);
|
||||
|
||||
/// <summary>
|
||||
/// Same as <see cref="Call{T}"/>, however the return value is ignored.
|
||||
/// </summary>
|
||||
public void Call(string token, CallArgs args, Resource? self = null, CallOptions? options = null)
|
||||
=> _deployment.Call(token, args, self, options);
|
||||
|
||||
internal IDeploymentInternal Internal => (IDeploymentInternal)_deployment;
|
||||
}
|
||||
}
|
||||
|
|
138
sdk/dotnet/Pulumi/Deployment/Deployment_Call.cs
Normal file
|
@ -0,0 +1,138 @@
|
|||
// Copyright 2016-2021, Pulumi Corporation
|
||||
|
||||
using System;
|
||||
using System.Collections.Immutable;
|
||||
using System.Threading.Tasks;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
using Pulumi.Serialization;
|
||||
using Pulumirpc;
|
||||
|
||||
namespace Pulumi
|
||||
{
|
||||
public sealed partial class Deployment
|
||||
{
|
||||
void IDeployment.Call(string token, CallArgs args, Resource? self, CallOptions? options)
|
||||
=> Call<object>(token, args, self, options, convertResult: false);
|
||||
|
||||
Output<T> IDeployment.Call<T>(string token, CallArgs args, Resource? self, CallOptions? options)
|
||||
=> Call<T>(token, args, self, options, convertResult: true);
|
||||
|
||||
private Output<T> Call<T>(string token, CallArgs args, Resource? self, CallOptions? options, bool convertResult)
|
||||
=> new Output<T>(CallAsync<T>(token, args, self, options, convertResult));
|
||||
|
||||
private async Task<OutputData<T>> CallAsync<T>(
|
||||
string token, CallArgs args, Resource? self, CallOptions? options, bool convertResult)
|
||||
{
|
||||
var (result, deps) = await CallRawAsync(token, args, self, options).ConfigureAwait(false);
|
||||
if (convertResult)
|
||||
{
|
||||
var converted = Converter.ConvertValue<T>($"{token} result", new Value { StructValue = result });
|
||||
return new OutputData<T>(deps, converted.Value, converted.IsKnown, converted.IsSecret);
|
||||
}
|
||||
|
||||
return new OutputData<T>(ImmutableHashSet<Resource>.Empty, default!, isKnown: true, isSecret: false);
|
||||
}
|
||||
|
||||
private async Task<(Struct Return, ImmutableHashSet<Resource> Dependencies)> CallRawAsync(
|
||||
string token, CallArgs args, Resource? self, CallOptions? options)
|
||||
{
|
||||
var label = $"Calling function: token={token} asynchronously";
|
||||
Log.Debug(label);
|
||||
|
||||
// Be resilient to misbehaving callers.
|
||||
// ReSharper disable once ConstantNullCoalescingCondition
|
||||
args ??= CallArgs.Empty;
|
||||
|
||||
// Wait for all values to be available, and then perform the RPC.
|
||||
var argsDict = await args.ToDictionaryAsync().ConfigureAwait(false);
|
||||
|
||||
// If we have a self arg, include it in the args.
|
||||
if (self != null)
|
||||
{
|
||||
argsDict = argsDict.SetItem("__self__", self);
|
||||
}
|
||||
|
||||
var (serialized, argDependencies) = await SerializeFilteredPropertiesAsync(
|
||||
$"call:{token}",
|
||||
argsDict, _ => true, keepResources: true).ConfigureAwait(false);
|
||||
Log.Debug($"Call RPC prepared: token={token}" +
|
||||
(_excessiveDebugOutput ? $", obj={serialized}" : ""));
|
||||
|
||||
// Determine the provider and version to use.
|
||||
ProviderResource? provider;
|
||||
string? version;
|
||||
if (self != null)
|
||||
{
|
||||
provider = self._provider;
|
||||
version = self._version;
|
||||
}
|
||||
else
|
||||
{
|
||||
provider = GetProvider(token, options);
|
||||
version = options?.Version;
|
||||
}
|
||||
var providerReference = await ProviderResource.RegisterAsync(provider).ConfigureAwait(false);
|
||||
|
||||
// Create the request.
|
||||
var request = new CallRequest
|
||||
{
|
||||
Tok = token,
|
||||
Provider = providerReference ?? "",
|
||||
Version = version ?? "",
|
||||
Args = serialized,
|
||||
};
|
||||
|
||||
// Add arg dependencies to the request.
|
||||
foreach (var (argName, directDependencies) in argDependencies)
|
||||
{
|
||||
var urns = await GetAllTransitivelyReferencedResourceUrnsAsync(directDependencies).ConfigureAwait(false);
|
||||
var deps = new CallRequest.Types.ArgumentDependencies();
|
||||
deps.Urns.AddRange(urns);
|
||||
request.ArgDependencies.Add(argName, deps);
|
||||
}
|
||||
|
||||
// Kick off the call.
|
||||
var result = await Monitor.CallAsync(request).ConfigureAwait(false);
|
||||
|
||||
// Handle failures.
|
||||
if (result.Failures.Count > 0)
|
||||
{
|
||||
var reasons = "";
|
||||
foreach (var reason in result.Failures)
|
||||
{
|
||||
if (reasons != "")
|
||||
{
|
||||
reasons += "; ";
|
||||
}
|
||||
|
||||
reasons += $"{reason.Reason} ({reason.Property})";
|
||||
}
|
||||
|
||||
throw new CallException($"Call of '{token}' failed: {reasons}");
|
||||
}
|
||||
|
||||
// Unmarshal return dependencies.
|
||||
var dependencies = ImmutableHashSet.CreateBuilder<Resource>();
|
||||
foreach (var (_, returnDependencies) in result.ReturnDependencies)
|
||||
{
|
||||
foreach (var urn in returnDependencies.Urns)
|
||||
{
|
||||
dependencies.Add(new DependencyResource(urn));
|
||||
}
|
||||
}
|
||||
|
||||
return (result.Return, dependencies.ToImmutable());
|
||||
}
|
||||
|
||||
private static ProviderResource? GetProvider(string token, CallOptions? options)
|
||||
=> options?.Provider ?? options?.Parent?.GetProvider(token);
|
||||
|
||||
private sealed class CallException : Exception
|
||||
{
|
||||
public CallException(string error)
|
||||
: base(error)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -24,6 +24,9 @@ namespace Pulumi
|
|||
|
||||
public async Task<InvokeResponse> InvokeAsync(InvokeRequest request)
|
||||
=> await this._client.InvokeAsync(request);
|
||||
|
||||
public async Task<CallResponse> CallAsync(CallRequest request)
|
||||
=> await this._client.CallAsync(request);
|
||||
|
||||
public async Task<ReadResourceResponse> ReadResourceAsync(Resource resource, ReadResourceRequest request)
|
||||
=> await this._client.ReadResourceAsync(request);
|
||||
|
|
|
@ -38,5 +38,23 @@ namespace Pulumi
|
|||
/// return value is ignored.
|
||||
/// </summary>
|
||||
Task InvokeAsync(string token, InvokeArgs args, InvokeOptions? options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Dynamically calls the function '<paramref name="token"/>', which is offered by a
|
||||
/// provider plugin. <see cref="Call{T}"/> returns immediately while the operation takes
|
||||
/// place asynchronously in the background, similar to Resource constructors.
|
||||
/// <para/>
|
||||
/// The result of <see cref="Call{T}"/> will be a <see cref="Output{T}"/> resolved to the
|
||||
/// result value of the provider plugin.
|
||||
/// <para/>
|
||||
/// The <paramref name="args"/> inputs can be a bag of computed values(including, `T`s,
|
||||
/// <see cref="Task{TResult}"/>s, <see cref="Output{T}"/>s etc.).
|
||||
/// </summary>
|
||||
Output<T> Call<T>(string token, CallArgs args, Resource? self = null, CallOptions? options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Same as <see cref="Call{T}"/>, however the return value is ignored.
|
||||
/// </summary>
|
||||
void Call(string token, CallArgs args, Resource? self = null, CallOptions? options = null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,8 @@ namespace Pulumi
|
|||
Task<SupportsFeatureResponse> SupportsFeatureAsync(SupportsFeatureRequest request);
|
||||
|
||||
Task<InvokeResponse> InvokeAsync(InvokeRequest request);
|
||||
|
||||
Task<CallResponse> CallAsync(CallRequest request);
|
||||
|
||||
Task<ReadResourceResponse> ReadResourceAsync(Resource resource, ReadResourceRequest request);
|
||||
|
||||
|
|
|
@ -21,6 +21,16 @@ Pulumi.Asset
|
|||
Pulumi.AssetArchive
|
||||
Pulumi.AssetArchive.AssetArchive(System.Collections.Generic.IDictionary<string, Pulumi.AssetOrArchive> assets) -> void
|
||||
Pulumi.AssetOrArchive
|
||||
Pulumi.CallArgs
|
||||
Pulumi.CallArgs.CallArgs() -> void
|
||||
Pulumi.CallOptions
|
||||
Pulumi.CallOptions.CallOptions() -> void
|
||||
Pulumi.CallOptions.Parent.get -> Pulumi.Resource
|
||||
Pulumi.CallOptions.Parent.set -> void
|
||||
Pulumi.CallOptions.Provider.get -> Pulumi.ProviderResource
|
||||
Pulumi.CallOptions.Provider.set -> void
|
||||
Pulumi.CallOptions.Version.get -> string
|
||||
Pulumi.CallOptions.Version.set -> void
|
||||
Pulumi.ComponentResource
|
||||
Pulumi.ComponentResource.ComponentResource(string type, string name, Pulumi.ComponentResourceOptions options = null) -> void
|
||||
Pulumi.ComponentResource.ComponentResource(string type, string name, Pulumi.ResourceArgs args, Pulumi.ComponentResourceOptions options = null, bool remote = false) -> void
|
||||
|
@ -73,6 +83,8 @@ Pulumi.DictionaryResourceArgs
|
|||
Pulumi.DictionaryResourceArgs.DictionaryResourceArgs(System.Collections.Immutable.ImmutableDictionary<string, object> dictionary) -> void
|
||||
Pulumi.Deployment
|
||||
Pulumi.DeploymentInstance
|
||||
Pulumi.DeploymentInstance.Call(string token, Pulumi.CallArgs args, Pulumi.Resource self = null, Pulumi.CallOptions options = null) -> void
|
||||
Pulumi.DeploymentInstance.Call<T>(string token, Pulumi.CallArgs args, Pulumi.Resource self = null, Pulumi.CallOptions options = null) -> Pulumi.Output<T>
|
||||
Pulumi.DeploymentInstance.InvokeAsync(string token, Pulumi.InvokeArgs args, Pulumi.InvokeOptions options = null) -> System.Threading.Tasks.Task
|
||||
Pulumi.DeploymentInstance.InvokeAsync<T>(string token, Pulumi.InvokeArgs args, Pulumi.InvokeOptions options = null) -> System.Threading.Tasks.Task<T>
|
||||
Pulumi.DeploymentInstance.IsDryRun.get -> bool
|
||||
|
@ -357,5 +369,6 @@ static Pulumi.Union<T0, T1>.FromT1(T1 input) -> Pulumi.Union<T0, T1>
|
|||
static Pulumi.Union<T0, T1>.implicit operator Pulumi.Union<T0, T1>(T0 t) -> Pulumi.Union<T0, T1>
|
||||
static Pulumi.Union<T0, T1>.implicit operator Pulumi.Union<T0, T1>(T1 t) -> Pulumi.Union<T0, T1>
|
||||
static Pulumi.Urn.Create(Pulumi.Input<string> name, Pulumi.Input<string> type, Pulumi.Resource parent = null, Pulumi.Input<string> parentUrn = null, Pulumi.Input<string> project = null, Pulumi.Input<string> stack = null) -> Pulumi.Output<string>
|
||||
static readonly Pulumi.CallArgs.Empty -> Pulumi.CallArgs
|
||||
static readonly Pulumi.InvokeArgs.Empty -> Pulumi.InvokeArgs
|
||||
static readonly Pulumi.ResourceArgs.Empty -> Pulumi.ResourceArgs
|
||||
|
|
23
sdk/dotnet/Pulumi/Resources/CallArgs.cs
Normal file
|
@ -0,0 +1,23 @@
|
|||
// Copyright 2016-2021, Pulumi Corporation
|
||||
|
||||
using System;
|
||||
|
||||
namespace Pulumi
|
||||
{
|
||||
/// <summary>
|
||||
/// Base type for all call argument classes.
|
||||
/// </summary>
|
||||
public abstract class CallArgs : InputArgs
|
||||
{
|
||||
public static readonly CallArgs Empty = new EmptyCallArgs();
|
||||
|
||||
private protected override void ValidateMember(Type memberType, string fullName)
|
||||
{
|
||||
// No validation. A member may or may not be IInput.
|
||||
}
|
||||
|
||||
private sealed class EmptyCallArgs : CallArgs
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -93,6 +93,16 @@ namespace Pulumi
|
|||
/// </summary>
|
||||
private readonly ImmutableDictionary<string, ProviderResource> _providers;
|
||||
|
||||
/// <summary>
|
||||
/// The specified provider or provider determined from the parent for custom resources.
|
||||
/// </summary>
|
||||
internal readonly ProviderResource? _provider;
|
||||
|
||||
/// <summary>
|
||||
/// The specified provider version.
|
||||
/// </summary>
|
||||
internal readonly string? _version;
|
||||
|
||||
/// <summary>
|
||||
/// Creates and registers a new resource object. <paramref name="type"/> is the fully
|
||||
/// qualified type token and <paramref name="name"/> is the "name" part to use in creating a
|
||||
|
@ -241,6 +251,8 @@ namespace Pulumi
|
|||
}
|
||||
|
||||
this._protect = options.Protect == true;
|
||||
this._provider = custom ? options.Provider : null;
|
||||
this._version = options.Version;
|
||||
|
||||
// Collapse any 'Alias'es down to URNs. We have to wait until this point to do so
|
||||
// because we do not know the default 'name' and 'type' to apply until we are inside the
|
||||
|
|
|
@ -58,6 +58,21 @@ namespace Pulumi.Testing
|
|||
return new InvokeResponse { Return = await SerializeAsync(result).ConfigureAwait(false) };
|
||||
}
|
||||
|
||||
public async Task<CallResponse> CallAsync(CallRequest request)
|
||||
{
|
||||
// For now, we'll route both Invoke and Call through IMocks.CallAsync.
|
||||
var args = ToDictionary(request.Args);
|
||||
|
||||
var result = await _mocks.CallAsync(new MockCallArgs
|
||||
{
|
||||
Token = request.Tok,
|
||||
Args = args,
|
||||
Provider = request.Provider,
|
||||
})
|
||||
.ConfigureAwait(false);
|
||||
return new CallResponse { Return = await SerializeAsync(result).ConfigureAwait(false) };
|
||||
}
|
||||
|
||||
public async Task<ReadResourceResponse> ReadResourceAsync(Resource resource, ReadResourceRequest request)
|
||||
{
|
||||
var (id, state) = await _mocks.NewResourceAsync(new MockResourceArgs
|
||||
|
|
|
@ -23,6 +23,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
|
||||
"github.com/pulumi/pulumi/sdk/v3/python"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
@ -369,13 +370,30 @@ func TestRuntimeErrorPython(t *testing.T) {
|
|||
stackName := FullyQualifiedStackName(pulumiOrg, runtimeErrProj, sName)
|
||||
|
||||
// initialize
|
||||
pDir := filepath.Join(".", "test", "errors", "runtime_error", "python")
|
||||
|
||||
cmd := exec.Command("python3", "-m", "venv", "venv")
|
||||
cmd.Dir = pDir
|
||||
err := cmd.Run()
|
||||
pDir, err := filepath.Abs(filepath.Join(".", "test", "errors", "runtime_error", "python"))
|
||||
if err != nil {
|
||||
t.Errorf("failed to install project dependencies")
|
||||
t.Error(err)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
err = python.InstallDependencies(pDir, "venv", true /*showOutput*/)
|
||||
if err != nil {
|
||||
t.Errorf("failed to create a venv and install project dependencies: %v", err)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
pySDK, err := filepath.Abs(filepath.Join("..", "..", "..", "sdk", "python", "env", "src"))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
// install Pulumi Python SDK from the current source tree, -e means no-copy, ref directly
|
||||
pyCmd := python.VirtualEnvCommand(filepath.Join(pDir, "venv"), "python", "-m", "pip", "install", "-e", pySDK)
|
||||
pyCmd.Dir = pDir
|
||||
err = pyCmd.Run()
|
||||
if err != nil {
|
||||
t.Errorf("failed to link venv against in-source pulumi: %v", err)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
|
@ -394,6 +412,7 @@ func TestRuntimeErrorPython(t *testing.T) {
|
|||
_, err = s.Up(ctx)
|
||||
assert.NotNil(t, err)
|
||||
assert.True(t, IsRuntimeError(err), "%+v", err)
|
||||
assert.Contains(t, fmt.Sprintf("%v", err), "IndexError: list index out of range")
|
||||
|
||||
// -- pulumi destroy --
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
pulumi>=2.0.0,<3.0.0
|
||||
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
%% regenerate using https://github.com/mermaid-js/mermaid-cli
|
||||
|
||||
flowchart TD
|
||||
start("Resource registration")
|
||||
|
||||
read_read("Read(reg.URN, reg.ID, reg.State)")
|
||||
|
||||
import_read("Read(reg.URN, reg.ID)")
|
||||
import_check("Check(reg.URN, reg.Inputs, read.Inputs)")
|
||||
import_diff("Diff(reg.URN, check.Inputs, read.State)")
|
||||
|
||||
manage_check("Check(reg.URN, reg.Inputs, last?.Inputs)")
|
||||
manage_create("Create(reg.URN, check.Inputs)")
|
||||
manage_diff("Diff(reg.URN, check.Inputs, last.ID, last.State)")
|
||||
manage_update("Update(reg.URN, last.ID, last.State)")
|
||||
manage_replace_check("Check(reg.URN, reg.Inputs)")
|
||||
manage_replace_create_before_delete("Create(reg.URN, reg.Inputs)")
|
||||
manage_replace_delete_after_create("Delete(reg.URN, last.ID, last.State)")
|
||||
manage_replace_delete_dependents("Delete dependents")
|
||||
manage_replace_delete_before_create("Delete(reg.URN, last.ID, last.State)")
|
||||
manage_replace_create_after_delete("Create(reg.URN, check.Inputs)")
|
||||
|
||||
done("Return new inputs and state")
|
||||
|
||||
start-- read -->read_read
|
||||
start-- import -->import_read
|
||||
start-- manage -->manage_check
|
||||
|
||||
read_read-->done
|
||||
|
||||
import_read-->import_check
|
||||
import_check-->import_diff
|
||||
import_diff-->done
|
||||
|
||||
manage_check-- no last state -->manage_create
|
||||
manage_check-- has last state -->manage_diff
|
||||
manage_diff-- can be updated -->manage_update
|
||||
manage_diff-- must be replaced -->manage_replace_check
|
||||
manage_replace_check-- create before delete -->manage_replace_create_before_delete
|
||||
manage_replace_check-- delete after craete -->manage_replace_delete_dependents
|
||||
manage_replace_create_before_delete-->manage_replace_delete_after_create
|
||||
manage_replace_delete_dependents-->manage_replace_delete_before_create
|
||||
manage_replace_delete_before_create-->manage_replace_create_after_delete
|
||||
manage_create-->done
|
||||
manage_update-->done
|
||||
manage_replace_delete_after_create-->done
|
||||
manage_replace_create_after_delete-->done
|
Before Width: | Height: | Size: 29 KiB |
|
@ -24,6 +24,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
|
@ -188,8 +189,7 @@ func (host *pythonLanguageHost) GetRequiredPlugins(ctx context.Context,
|
|||
|
||||
plugins := []*pulumirpc.PluginDependency{}
|
||||
for _, pkg := range pulumiPackages {
|
||||
|
||||
plugin, err := determinePluginDependency(host.virtualenvPath, host.cwd, pkg.Name, pkg.Version)
|
||||
plugin, err := determinePluginDependency(host.virtualenvPath, host.cwd, pkg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -318,23 +318,27 @@ var packagesWithoutPlugins = map[string]struct{}{
|
|||
}
|
||||
|
||||
type pythonPackage struct {
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
Location string `json:"location"`
|
||||
}
|
||||
|
||||
func determinePulumiPackages(virtualenv, cwd string) ([]pythonPackage, error) {
|
||||
logging.V(5).Infof("GetRequiredPlugins: Determining pulumi packages")
|
||||
|
||||
// Run the `python -m pip list --format json` command.
|
||||
args := []string{"-m", "pip", "list", "--format", "json"}
|
||||
// Run the `python -m pip list -v --format json` command.
|
||||
args := []string{"-m", "pip", "list", "-v", "--format", "json"}
|
||||
output, err := runPythonCommand(virtualenv, cwd, args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Parse the JSON output.
|
||||
// Parse the JSON output; on some systems pip -v verbose mode
|
||||
// follows JSON with non-JSON trailer, so we need to be
|
||||
// careful when parsing and ignore the trailer.
|
||||
var packages []pythonPackage
|
||||
if err := json.Unmarshal(output, &packages); err != nil {
|
||||
jsonDecoder := json.NewDecoder(bytes.NewBuffer(output))
|
||||
if err := jsonDecoder.Decode(&packages); err != nil {
|
||||
return nil, errors.Wrapf(err, "parsing `python %s` output", strings.Join(args, " "))
|
||||
}
|
||||
|
||||
|
@ -365,23 +369,17 @@ func determinePulumiPackages(virtualenv, cwd string) ([]pythonPackage, error) {
|
|||
// are derived from the package name and version. If the plugin version cannot be determined from the package version,
|
||||
// nil is returned.
|
||||
func determinePluginDependency(
|
||||
virtualenv, cwd, packageName, packageVersion string) (*pulumirpc.PluginDependency, error) {
|
||||
virtualenv, cwd string, pkg pythonPackage) (*pulumirpc.PluginDependency, error) {
|
||||
|
||||
logging.V(5).Infof("GetRequiredPlugins: Determining plugin dependency: %v, %v", packageName, packageVersion)
|
||||
|
||||
// Determine the location of the installed package.
|
||||
packageLocation, err := determinePackageLocation(virtualenv, cwd, packageName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
logging.V(5).Infof("GetRequiredPlugins: Determining plugin dependency: %v, %v", pkg.Name, pkg.Version)
|
||||
|
||||
// The name of the module inside the package can be different from the package name.
|
||||
// However, our convention is to always use the same name, e.g. a package name of
|
||||
// "pulumi-aws" will have a module named "pulumi_aws", so we can determine the module
|
||||
// by replacing hyphens with underscores.
|
||||
packageModuleName := strings.ReplaceAll(packageName, "-", "_")
|
||||
packageModuleName := strings.ReplaceAll(pkg.Name, "-", "_")
|
||||
|
||||
pulumiPluginFilePath := filepath.Join(packageLocation, packageModuleName, "pulumiplugin.json")
|
||||
pulumiPluginFilePath := filepath.Join(pkg.Location, packageModuleName, "pulumiplugin.json")
|
||||
logging.V(5).Infof("GetRequiredPlugins: pulumiplugin.json file path: %s", pulumiPluginFilePath)
|
||||
|
||||
var name, version, server string
|
||||
|
@ -390,7 +388,7 @@ func determinePluginDependency(
|
|||
// If `resource` is set to false, the Pulumi package has indicated that there is no associated plugin.
|
||||
// Ignore it.
|
||||
if !plugin.Resource {
|
||||
logging.V(5).Infof("GetRequiredPlugins: Ignoring package %s with resource set to false", packageName)
|
||||
logging.V(5).Infof("GetRequiredPlugins: Ignoring package %s with resource set to false", pkg.Name)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
@ -403,7 +401,7 @@ func determinePluginDependency(
|
|||
}
|
||||
|
||||
if name == "" {
|
||||
name = strings.TrimPrefix(packageName, "pulumi-")
|
||||
name = strings.TrimPrefix(pkg.Name, "pulumi-")
|
||||
}
|
||||
|
||||
if version == "" {
|
||||
|
@ -413,11 +411,11 @@ func determinePluginDependency(
|
|||
// "3.31.0a1605189729" will have an associated plugin with a version of "3.31.0-alpha.1605189729+42435656".
|
||||
// The "+42435656" suffix cannot be determined so the plugin version cannot be determined. In such cases,
|
||||
// log the issue and skip the package.
|
||||
version, err = determinePluginVersion(packageVersion)
|
||||
version, err = determinePluginVersion(pkg.Version)
|
||||
if err != nil {
|
||||
logging.V(5).Infof(
|
||||
"GetRequiredPlugins: Could not determine plugin version for package %s with version %s",
|
||||
packageName, packageVersion)
|
||||
pkg.Name, pkg.Version)
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
@ -437,16 +435,6 @@ func determinePluginDependency(
|
|||
return &result, nil
|
||||
}
|
||||
|
||||
// determinePackageLocation determines the location on disk of the package by running `python -m pip show <package>`
|
||||
// and parsing the output.
|
||||
func determinePackageLocation(virtualenv, cwd, packageName string) (string, error) {
|
||||
b, err := runPythonCommand(virtualenv, cwd, "-m", "pip", "show", packageName)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return parseLocation(packageName, string(b))
|
||||
}
|
||||
|
||||
func parseLocation(packageName, pipShowOutput string) (string, error) {
|
||||
// We want the value of Location from the following output of `python -m pip show <packageName>`:
|
||||
// $ python -m pip show pulumi-aws
|
||||
|
|
|
@ -142,3 +142,28 @@ func TestDeterminePluginVersion(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeterminePulumiPackages(t *testing.T) {
|
||||
t.Run("empty", func(t *testing.T) {
|
||||
cwd := t.TempDir()
|
||||
_, err := runPythonCommand("", cwd, "-m", "venv", "venv")
|
||||
assert.NoError(t, err)
|
||||
packages, err := determinePulumiPackages("venv", cwd)
|
||||
assert.NoError(t, err)
|
||||
assert.Empty(t, packages)
|
||||
})
|
||||
t.Run("non-empty", func(t *testing.T) {
|
||||
cwd := t.TempDir()
|
||||
_, err := runPythonCommand("", cwd, "-m", "venv", "venv")
|
||||
assert.NoError(t, err)
|
||||
_, err = runPythonCommand("venv", cwd, "-m", "pip", "install", "pulumi-random")
|
||||
assert.NoError(t, err)
|
||||
packages, err := determinePulumiPackages("venv", cwd)
|
||||
assert.NoError(t, err)
|
||||
assert.NotEmpty(t, packages)
|
||||
assert.Equal(t, 1, len(packages))
|
||||
random := packages[0]
|
||||
assert.Equal(t, "pulumi-random", random.Name)
|
||||
assert.NotEmpty(t, random.Location)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -117,7 +117,7 @@ class LocalWorkspace(Workspace):
|
|||
break
|
||||
path = os.path.join(self.work_dir, f"Pulumi{found_ext}")
|
||||
writable_settings = {key: settings.__dict__[key] for key in settings.__dict__ if settings.__dict__[key] is not None}
|
||||
with open(path, "w") as file:
|
||||
with open(path, "w", encoding="utf-8") as file:
|
||||
if found_ext == ".json":
|
||||
json.dump(writable_settings, file, indent=4)
|
||||
else:
|
||||
|
@ -129,7 +129,7 @@ class LocalWorkspace(Workspace):
|
|||
path = os.path.join(self.work_dir, f"Pulumi.{stack_settings_name}{ext}")
|
||||
if not os.path.exists(path):
|
||||
continue
|
||||
with open(path, "r") as file:
|
||||
with open(path, "r", encoding="utf-8") as file:
|
||||
settings = json.load(file) if ext == ".json" else yaml.safe_load(file)
|
||||
return StackSettings._deserialize(settings)
|
||||
raise FileNotFoundError(f"failed to find stack settings file in workdir: {self.work_dir}")
|
||||
|
@ -143,7 +143,7 @@ class LocalWorkspace(Workspace):
|
|||
found_ext = ext
|
||||
break
|
||||
path = os.path.join(self.work_dir, f"Pulumi.{stack_settings_name}{found_ext}")
|
||||
with open(path, "w") as file:
|
||||
with open(path, "w", encoding="utf-8") as file:
|
||||
if found_ext == ".json":
|
||||
json.dump(settings._serialize(), file, indent=4)
|
||||
else:
|
||||
|
@ -490,7 +490,7 @@ def _load_project_settings(work_dir: str) -> ProjectSettings:
|
|||
project_path = os.path.join(work_dir, f"Pulumi{ext}")
|
||||
if not os.path.exists(project_path):
|
||||
continue
|
||||
with open(project_path, "r") as file:
|
||||
with open(project_path, "r", encoding="utf-8") as file:
|
||||
settings = json.load(file) if ext == ".json" else yaml.safe_load(file)
|
||||
return ProjectSettings(**settings)
|
||||
raise FileNotFoundError(f"failed to find project settings file in workdir: {work_dir}")
|
||||
|
|
23
sdk/python/lib/pulumi/automation/_representable.py
Normal file
|
@ -0,0 +1,23 @@
|
|||
# Copyright 2016-2021, Pulumi Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
|
||||
class _Representable:
|
||||
"""This mix-in improves the default `__repr__` to be more readable."""
|
||||
|
||||
def __repr__(self):
|
||||
inputs = self.__dict__
|
||||
fields = [f"{key}={inputs[key]!r}" for key in inputs] # pylint: disable=consider-using-dict-items
|
||||
fields = ", ".join(fields)
|
||||
return f"{self.__class__.__name__}({fields})"
|
|
@ -32,6 +32,7 @@ from ._server import LanguageServer
|
|||
from ._workspace import Workspace, PulumiFn, Deployment
|
||||
from ..runtime.settings import _GRPC_CHANNEL_OPTIONS
|
||||
from ..runtime.proto import language_pb2_grpc
|
||||
from ._representable import _Representable
|
||||
|
||||
_DATETIME_FORMAT = '%Y-%m-%dT%H:%M:%S.%fZ'
|
||||
|
||||
|
@ -84,17 +85,11 @@ class UpdateSummary:
|
|||
f"resource_changes={self.resource_changes!r}, config={self.config!r}, Deployment={self.Deployment!r})"
|
||||
|
||||
|
||||
class BaseResult:
|
||||
class BaseResult(_Representable):
|
||||
def __init__(self, stdout: str, stderr: str):
|
||||
self.stdout = stdout
|
||||
self.stderr = stderr
|
||||
|
||||
def __repr__(self):
|
||||
inputs = self.__dict__
|
||||
fields = [f"{key}={inputs[key]!r}" for key in inputs] # pylint: disable=consider-using-dict-items
|
||||
fields = ", ".join(fields)
|
||||
return f"{self.__class__.__name__}({fields})"
|
||||
|
||||
|
||||
class PreviewResult(BaseResult):
|
||||
def __init__(self, stdout: str, stderr: str, change_summary: OpMap):
|
||||
|
@ -647,13 +642,13 @@ def _create_log_file(command: str) -> Tuple[str, tempfile.TemporaryDirectory]:
|
|||
filepath = os.path.join(log_dir.name, "eventlog.txt")
|
||||
|
||||
# Open and close the file to ensure it exists before we start polling for logs
|
||||
with open(filepath, "w+"):
|
||||
with open(filepath, "w+", encoding="utf-8"):
|
||||
pass
|
||||
return filepath, log_dir
|
||||
|
||||
|
||||
def _watch_logs(filename: str, callback: OnEvent):
|
||||
with open(filename) as f:
|
||||
with open(filename, encoding="utf-8") as f:
|
||||
while True:
|
||||
line = f.readline()
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
from enum import Enum
|
||||
from typing import Optional, List, Mapping, Any, MutableMapping
|
||||
from ._representable import _Representable
|
||||
|
||||
|
||||
class OpType(str, Enum):
|
||||
|
@ -43,13 +44,8 @@ class OpType(str, Enum):
|
|||
OpMap = MutableMapping[OpType, int]
|
||||
|
||||
|
||||
class BaseEvent:
|
||||
def __repr__(self):
|
||||
# pylint: disable=duplicate-code
|
||||
inputs = self.__dict__
|
||||
fields = [f"{key}={inputs[key]!r}" for key in inputs] # pylint: disable=consider-using-dict-items
|
||||
fields = ", ".join(fields)
|
||||
return f"{self.__class__.__name__}({fields})"
|
||||
class BaseEvent(_Representable):
|
||||
pass
|
||||
|
||||
|
||||
class CancelEvent(BaseEvent):
|
||||
|
|
|
@ -337,15 +337,10 @@ def _create_provider_resource(ref: str) -> ProviderResource:
|
|||
otherwise return an instance of DependencyProviderResource.
|
||||
"""
|
||||
urn, _ = _parse_resource_reference(ref)
|
||||
urn_parts = urn.split("::")
|
||||
urn_name = urn_parts[3]
|
||||
qualified_type = urn_parts[2]
|
||||
typ = qualified_type.split("$")[-1]
|
||||
typ_parts = typ.split(":")
|
||||
typ_name = typ_parts[2] if len(typ_parts) > 2 else ""
|
||||
|
||||
resource_package = rpc.get_resource_package(typ_name, version="")
|
||||
urn_parts = pulumi.urn._parse_urn(urn)
|
||||
resource_package = rpc.get_resource_package(urn_parts.typ_name, version="")
|
||||
if resource_package is not None:
|
||||
return cast(ProviderResource, resource_package.construct_provider(urn_name, typ, urn))
|
||||
return cast(ProviderResource, resource_package.construct_provider(
|
||||
urn_parts.urn_name, urn_parts.typ, urn))
|
||||
|
||||
return DependencyProviderResource(ref)
|
||||
|
|
|
@ -24,6 +24,7 @@ from .runtime.resource import get_resource, register_resource, register_resource
|
|||
convert_providers
|
||||
from .runtime.settings import get_root_resource
|
||||
from .output import _is_prompt, _map_input, _map2_input, T, Output
|
||||
from . import urn as urn_util
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .output import Input, Inputs
|
||||
|
@ -985,12 +986,11 @@ class DependencyProviderResource(ProviderResource):
|
|||
|
||||
def __init__(self, ref: str) -> None:
|
||||
ref_urn, ref_id = _parse_resource_reference(ref)
|
||||
urn_parts = ref_urn.split("::")
|
||||
qualified_type = urn_parts[2]
|
||||
typ = qualified_type.split("$")[-1]
|
||||
typ_parts = typ.split(":")
|
||||
# typ will be "pulumi:providers:<package>" and we want the last part.
|
||||
pkg = typ_parts[2] if len(typ_parts) > 2 else ""
|
||||
urn_parts = urn_util._parse_urn(ref_urn)
|
||||
|
||||
# `typ` will be `pulumi:providers:<package>` and we want the
|
||||
# last part, which normally parses as `typ_name`.
|
||||
pkg = urn_parts.typ_name
|
||||
|
||||
super().__init__(pkg=pkg, name="", props={}, opts=None, dependency=True)
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ import json
|
|||
import os
|
||||
|
||||
# default to an empty map for config.
|
||||
CONFIG: Dict[str, Any] = dict()
|
||||
CONFIG: Dict[str, Any] = {}
|
||||
|
||||
# default to an empty set for config secret keys.
|
||||
_SECRET_KEYS: Set[str] = set()
|
||||
|
@ -56,7 +56,7 @@ def get_config_env() -> Dict[str, Any]:
|
|||
if 'PULUMI_CONFIG' in os.environ:
|
||||
env_config = os.environ['PULUMI_CONFIG']
|
||||
return json.loads(env_config)
|
||||
return dict()
|
||||
return {}
|
||||
|
||||
|
||||
def get_config_env_key(k: str) -> str:
|
||||
|
|
|
@ -139,7 +139,7 @@ class MockMonitor:
|
|||
|
||||
def __init__(self, mocks: Mocks):
|
||||
self.mocks = mocks
|
||||
self.resources = dict()
|
||||
self.resources = {}
|
||||
|
||||
def make_urn(self, parent: str, type_: str, name: str) -> str:
|
||||
if parent != "":
|
||||
|
|
|
@ -26,6 +26,7 @@ from .rpc_manager import RPC_MANAGER
|
|||
from .settings import handle_grpc_error
|
||||
from ..output import Output
|
||||
from .. import _types
|
||||
from .. import urn as urn_util
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
@ -194,9 +195,8 @@ def get_resource(res: 'Resource',
|
|||
transform_using_type_metadata = typ is not None
|
||||
|
||||
# Extract the resource type from the URN.
|
||||
urn_parts = urn.split("::")
|
||||
qualified_type = urn_parts[2]
|
||||
ty = qualified_type.split("$")[-1]
|
||||
urn_parts = urn_util._parse_urn(urn)
|
||||
ty = urn_parts.typ
|
||||
|
||||
# Initialize the URN property on the resource.
|
||||
(resolve_urn, res.__dict__["urn"]) = resource_output(res)
|
||||
|
|
|
@ -29,6 +29,7 @@ import six
|
|||
from . import known_types, settings
|
||||
from .. import log
|
||||
from .. import _types
|
||||
from .. import urn as urn_util
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..output import Inputs, Input, Output
|
||||
|
@ -399,15 +400,12 @@ def deserialize_resource(ref_struct: struct_pb2.Struct, keep_unknowns: Optional[
|
|||
urn = ref_struct["urn"]
|
||||
version = ref_struct["packageVersion"] if "packageVersion" in ref_struct else ""
|
||||
|
||||
urn_parts = urn.split("::")
|
||||
urn_name = urn_parts[3]
|
||||
qualified_type = urn_parts[2]
|
||||
typ = qualified_type.split("$")[-1]
|
||||
|
||||
typ_parts = typ.split(":")
|
||||
pkg_name = typ_parts[0]
|
||||
mod_name = typ_parts[1] if len(typ_parts) > 1 else ""
|
||||
typ_name = typ_parts[2] if len(typ_parts) > 2 else ""
|
||||
urn_parts = urn_util._parse_urn(urn)
|
||||
urn_name = urn_parts.urn_name
|
||||
typ = urn_parts.typ
|
||||
pkg_name = urn_parts.pkg_name
|
||||
mod_name = urn_parts.mod_name
|
||||
typ_name = urn_parts.typ_name
|
||||
|
||||
is_provider = pkg_name == "pulumi" and mod_name == "providers"
|
||||
if is_provider:
|
||||
|
@ -881,7 +879,7 @@ class ResourcePackage(ABC):
|
|||
pass
|
||||
|
||||
|
||||
_RESOURCE_PACKAGES: Dict[str, List[ResourcePackage]] = dict()
|
||||
_RESOURCE_PACKAGES: Dict[str, List[ResourcePackage]] = {}
|
||||
|
||||
|
||||
def register_resource_package(pkg: str, package: ResourcePackage):
|
||||
|
@ -922,7 +920,7 @@ class ResourceModule(ABC):
|
|||
pass
|
||||
|
||||
|
||||
_RESOURCE_MODULES: Dict[str, List[ResourceModule]] = dict()
|
||||
_RESOURCE_MODULES: Dict[str, List[ResourceModule]] = {}
|
||||
|
||||
|
||||
def _module_key(pkg: str, mod: str) -> str:
|
||||
|
|
|
@ -127,7 +127,7 @@ class Stack(ComponentResource):
|
|||
super().__init__('pulumi:pulumi:Stack', name, None, None)
|
||||
|
||||
# Invoke the function while this stack is active and then register its outputs.
|
||||
self.outputs = dict()
|
||||
self.outputs = {}
|
||||
set_root_resource(self)
|
||||
try:
|
||||
func()
|
||||
|
|
41
sdk/python/lib/pulumi/urn.py
Normal file
|
@ -0,0 +1,41 @@
|
|||
# Copyright 2016-2021, Pulumi Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
|
||||
_UrnParts = namedtuple('_UrnParts', ['urn_name',
|
||||
'typ',
|
||||
'pkg_name',
|
||||
'mod_name',
|
||||
'typ_name'])
|
||||
|
||||
|
||||
def _parse_urn(urn: str) -> _UrnParts:
|
||||
try:
|
||||
urn_parts = urn.split('::')
|
||||
urn_name = urn_parts[3] if len(urn_parts) >= 4 else ""
|
||||
qualified_type = urn_parts[2]
|
||||
typ = qualified_type.split("$")[-1]
|
||||
typ_parts = typ.split(":")
|
||||
pkg_name = typ_parts[0]
|
||||
mod_name = typ_parts[1] if len(typ_parts) > 1 else ""
|
||||
typ_name = typ_parts[2] if len(typ_parts) > 2 else ""
|
||||
return _UrnParts(urn_name=urn_name,
|
||||
typ=typ,
|
||||
pkg_name=pkg_name,
|
||||
mod_name=mod_name,
|
||||
typ_name=typ_name)
|
||||
except Exception as e:
|
||||
raise ValueError(f'Cannot parse URN: {urn}') from e
|
34
sdk/python/lib/test/test_urn.py
Normal file
|
@ -0,0 +1,34 @@
|
|||
# Copyright 2016-2021, Pulumi Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
|
||||
from pulumi import urn as urn_util
|
||||
|
||||
|
||||
def test_parse_urn_with_name():
|
||||
res = urn_util._parse_urn('urn:pulumi:stack::project::pulumi:providers:aws::default_4_13_0')
|
||||
assert res.urn_name == 'default_4_13_0'
|
||||
assert res.typ == 'pulumi:providers:aws'
|
||||
assert res.pkg_name == 'pulumi'
|
||||
assert res.mod_name == 'providers'
|
||||
assert res.typ_name == 'aws'
|
||||
|
||||
|
||||
def test_parse_urn_without_name():
|
||||
res = urn_util._parse_urn('urn:pulumi:stack::project::pulumi:providers:aws')
|
||||
assert res.urn_name == ''
|
||||
assert res.typ == 'pulumi:providers:aws'
|
||||
assert res.pkg_name == 'pulumi'
|
||||
assert res.mod_name == 'providers'
|
||||
assert res.typ_name == 'aws'
|
353
tests/integration/construct_component_methods/dotnet/.gitignore
vendored
Normal file
|
@ -0,0 +1,353 @@
|
|||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
##
|
||||
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||
|
||||
# User-specific files
|
||||
*.rsuser
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Mono auto generated files
|
||||
mono_crash.*
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
[Aa][Rr][Mm]/
|
||||
[Aa][Rr][Mm]64/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
[Ll]ogs/
|
||||
|
||||
# Visual Studio 2015/2017 cache/options directory
|
||||
.vs/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
# Visual Studio 2017 auto generated files
|
||||
Generated\ Files/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# NUnit
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
nunit-*.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
# Benchmark Results
|
||||
BenchmarkDotNet.Artifacts/
|
||||
|
||||
# .NET Core
|
||||
project.lock.json
|
||||
project.fragment.lock.json
|
||||
artifacts/
|
||||
|
||||
# StyleCop
|
||||
StyleCopReport.xml
|
||||
|
||||
# Files built by Visual Studio
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_h.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.iobj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.ipdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*_wpftmp.csproj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# Visual Studio Trace Files
|
||||
*.e2e
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# JustCode is a .NET coding add-in
|
||||
.JustCode
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# AxoCover is a Code Coverage Tool
|
||||
.axoCover/*
|
||||
!.axoCover/settings.json
|
||||
|
||||
# Visual Studio code coverage results
|
||||
*.coverage
|
||||
*.coveragexml
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
nCrunchTemp_*
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||
# in these scripts will be unencrypted
|
||||
PublishScripts/
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# NuGet Symbol Packages
|
||||
*.snupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/[Pp]ackages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/[Pp]ackages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/[Pp]ackages/repositories.config
|
||||
# NuGet v3's project.json files produces more ignorable files
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
|
||||
# Microsoft Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Microsoft Azure Emulator
|
||||
ecf/
|
||||
rcf/
|
||||
|
||||
# Windows Store app package directories and files
|
||||
AppPackages/
|
||||
BundleArtifacts/
|
||||
Package.StoreAssociation.xml
|
||||
_pkginfo.txt
|
||||
*.appx
|
||||
*.appxbundle
|
||||
*.appxupload
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!?*.[Cc]ache/
|
||||
|
||||
# Others
|
||||
ClientBin/
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.jfm
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
orleans.codegen.cs
|
||||
|
||||
# Including strong name files can present a security risk
|
||||
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||
#*.snk
|
||||
|
||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||
#bower_components/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
ServiceFabricBackup/
|
||||
*.rptproj.bak
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
*.ndf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
*.rptproj.rsuser
|
||||
*- [Bb]ackup.rdl
|
||||
*- [Bb]ackup ([0-9]).rdl
|
||||
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# GhostDoc plugin setting file
|
||||
*.GhostDoc.xml
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
node_modules/
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||
*.vbw
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/ModelManifest.xml
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
|
||||
# Paket dependency manager
|
||||
.paket/paket.exe
|
||||
paket-files/
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
||||
|
||||
# CodeRush personal settings
|
||||
.cr/personal
|
||||
|
||||
# Python Tools for Visual Studio (PTVS)
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Cake - Uncomment if you are using it
|
||||
# tools/**
|
||||
# !tools/packages.config
|
||||
|
||||
# Tabs Studio
|
||||
*.tss
|
||||
|
||||
# Telerik's JustMock configuration file
|
||||
*.jmconfig
|
||||
|
||||
# BizTalk build output
|
||||
*.btp.cs
|
||||
*.btm.cs
|
||||
*.odx.cs
|
||||
*.xsd.cs
|
||||
|
||||
# OpenCover UI analysis results
|
||||
OpenCover/
|
||||
|
||||
# Azure Stream Analytics local run output
|
||||
ASALocalRun/
|
||||
|
||||
# MSBuild Binary and Structured Log
|
||||
*.binlog
|
||||
|
||||
# NVidia Nsight GPU debugger configuration file
|
||||
*.nvuser
|
||||
|
||||
# MFractors (Xamarin productivity tool) working folder
|
||||
.mfractor/
|
||||
|
||||
# Local History for Visual Studio
|
||||
.localhistory/
|
||||
|
||||
# BeatPulse healthcheck temp database
|
||||
healthchecksdb
|
||||
|
||||
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||
MigrationBackup/
|
||||
|
||||
# Ionide (cross platform F# VS Code tools) working folder
|
||||
.ionide/
|
|
@ -0,0 +1,41 @@
|
|||
// Copyright 2016-2021, Pulumi Corporation. All rights reserved.
|
||||
|
||||
using Pulumi;
|
||||
|
||||
class ComponentArgs : ResourceArgs
|
||||
{
|
||||
[Input("first")]
|
||||
public Input<string> First { get; set; } = null!;
|
||||
|
||||
[Input("second")]
|
||||
public Input<string> Second { get; set; } = null!;
|
||||
}
|
||||
|
||||
class Component : ComponentResource
|
||||
{
|
||||
public Component(string name, ComponentArgs args, ComponentResourceOptions? opts = null)
|
||||
: base("testcomponent:index:Component", name, args, opts, remote: true)
|
||||
{
|
||||
}
|
||||
|
||||
public Output<GetMessageResult> GetMessage(GetMessageArgs args)
|
||||
=> Deployment.Instance.Call<GetMessageResult>("testcomponent:index:Component/getMessage", args, this);
|
||||
}
|
||||
|
||||
public class GetMessageArgs : CallArgs
|
||||
{
|
||||
[Input("name")]
|
||||
public Input<string> Name { get; set; } = null!;
|
||||
}
|
||||
|
||||
[OutputType]
|
||||
public sealed class GetMessageResult
|
||||
{
|
||||
public readonly string Message;
|
||||
|
||||
[OutputConstructor]
|
||||
private GetMessageResult(string message)
|
||||
{
|
||||
Message = message;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,16 @@
|
|||
// Copyright 2016-2021, Pulumi Corporation. All rights reserved.
|
||||
|
||||
using Pulumi;
|
||||
|
||||
class MyStack : Stack
|
||||
{
|
||||
[Output("message")]
|
||||
public Output<string> Message { get; set; }
|
||||
|
||||
public MyStack()
|
||||
{
|
||||
var component = new Component("component", new ComponentArgs { First = "Hello", Second = "World" });
|
||||
var result = component.GetMessage(new GetMessageArgs { Name = "Alice" });
|
||||
Message = result.Apply(v => v.Message);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
// Copyright 2016-2021, Pulumi Corporation. All rights reserved.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Pulumi;
|
||||
|
||||
class Program
|
||||
{
|
||||
static Task<int> Main() => Deployment.RunAsync<MyStack>();
|
||||
}
|