Compare commits
55 commits
Author | SHA1 | Date | |
---|---|---|---|
4d4ff9f1d6 | |||
2d26cdd9ed | |||
b14bc09b1c | |||
09b7aa9186 | |||
c39343fa3d | |||
4b7985384c | |||
6cb801cf17 | |||
52d01bb915 | |||
c1c82b8317 | |||
e77d780370 | |||
72a4e1fc3f | |||
c6cefcd3f4 | |||
4029a1c89b | |||
d9dd88c740 | |||
574a6a104d | |||
87d8c7f074 | |||
7222e5570a | |||
dbc8ab9ad6 | |||
2c25c3fbd0 | |||
f98d39b84b | |||
e60d6bf248 | |||
e846b3201f | |||
1cedb29193 | |||
3e2f36548e | |||
013fcdec9d | |||
b0dfad44c5 | |||
50308812c4 | |||
06a19b53ed | |||
b9f57bc6b9 | |||
3329d81c1a | |||
a1339277f0 | |||
ed769377dc | |||
ba39ed9ad4 | |||
a7783f26de | |||
f6cc3d375c | |||
372ddc7e5c | |||
554660b23a | |||
10ceee406e | |||
c4c1f3d449 | |||
d3b2dedd1d | |||
a5f72ddbeb | |||
272c4643b2 | |||
164a2ec818 | |||
5dd7851293 | |||
74ba28ad55 | |||
0a38bc295c | |||
0d4fb3e340 | |||
fbeac6fc10 | |||
c6b8168423 | |||
c6240cf38d | |||
0343a6de76 | |||
d7ec7ce06c | |||
aa9bed5508 | |||
d401912902 | |||
6057dc3362 |
|
@ -28,8 +28,8 @@ RUN groupadd --gid $USER_GID $USER_NAME \
|
|||
|
||||
RUN mkdir -p /go/bin \
|
||||
&& chown -R $USER_NAME: /go \
|
||||
&& mkdir -p /opt/pulumi/bin \
|
||||
&& chown -R $USER_NAME: /opt/pulumi
|
||||
&& mkdir -p $HOME/.pulumi/bin \
|
||||
&& chown -R $USER_NAME: $HOME/.pulumi
|
||||
|
||||
USER $USER_NAME
|
||||
|
||||
|
@ -38,7 +38,7 @@ USER $USER_NAME
|
|||
ENV XDG_CONFIG_HOME=/home/$USER_NAME/.config
|
||||
ENV XDG_CACHE_HOME=/home/$USER_NAME/.cache
|
||||
|
||||
RUN echo "export PATH=/opt/pulumi:/opt/pulumi/bin:$GOPATH/bin:/usr/local/go/bin:$PATH" >> ~/.bashrc \
|
||||
RUN echo "export PATH=$HOME/.pulumi:$HOME/.pulumi/bin:$GOPATH/bin:/usr/local/go/bin:$PATH" >> ~/.bashrc \
|
||||
&& echo "alias l='ls -aF'" >> ~/.bash_aliases \
|
||||
&& echo "alias ll='ls -ahlF'" >> ~/.bash_aliases \
|
||||
&& echo "alias ls='ls --color=auto --group-directories-first'" >> ~/.bash_aliases
|
||||
|
|
|
@ -16,10 +16,9 @@
|
|||
|
||||
"remoteUser": "user",
|
||||
|
||||
"extensions": ["golang.go", "ms-dotnettools.csharp", "ms-python.python"],
|
||||
"extensions": ["golang.go", "ms-dotnettools.csharp", "ms-python.python", "formulahendry.dotnet-test-explorer"],
|
||||
|
||||
// We want to dotnet restore all projects on startup so that omnisharp doesn't complain about lots of missing types on startup.
|
||||
"postCreateCommand": "find -name \"*.??proj\" | xargs -L1 dotnet restore",
|
||||
"postCreateCommand": "make ensure",
|
||||
|
||||
"settings": {
|
||||
"extensions.ignoreRecommendations": true
|
||||
|
|
5
.github/workflows/master.yml
vendored
5
.github/workflows/master.yml
vendored
|
@ -160,6 +160,7 @@ jobs:
|
|||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: ${{ matrix.dotnet-version }}
|
||||
- run: mkdir -p ${{ runner.temp }}/opt/pulumi/nuget
|
||||
- run: dotnet nuget add source ${{ runner.temp }}/opt/pulumi/nuget
|
||||
- name: Set up Node ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
|
@ -229,6 +230,7 @@ jobs:
|
|||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: ${{ matrix.dotnet-version }}
|
||||
- run: mkdir -p ${{ runner.temp }}/opt/pulumi/nuget
|
||||
- run: dotnet nuget add source ${{ runner.temp }}/opt/pulumi/nuget
|
||||
- name: Set up Node ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
|
@ -303,6 +305,9 @@ jobs:
|
|||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: ${{ matrix.dotnet }}
|
||||
- name: Create Local Nuget
|
||||
run: mkdir -p "${{ env.PULUMI_LOCAL_NUGET }}"
|
||||
shell: bash
|
||||
- run: dotnet nuget add source ${{ env.PULUMI_LOCAL_NUGET }}
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
|
|
8
.github/workflows/prerelease.yml
vendored
8
.github/workflows/prerelease.yml
vendored
|
@ -143,6 +143,7 @@ jobs:
|
|||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: ${{ matrix.dotnet-version }}
|
||||
- run: mkdir -p ${{ runner.temp }}/opt/pulumi/nuget
|
||||
- run: dotnet nuget add source ${{ runner.temp }}/opt/pulumi/nuget
|
||||
- name: Set up Node ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
|
@ -206,6 +207,7 @@ jobs:
|
|||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: ${{ matrix.dotnet-version }}
|
||||
- run: mkdir -p ${{ runner.temp }}/opt/pulumi/nuget
|
||||
- run: dotnet nuget add source ${{ runner.temp }}/opt/pulumi/nuget
|
||||
- name: Set up Node ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
|
@ -280,6 +282,9 @@ jobs:
|
|||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: ${{ matrix.dotnet }}
|
||||
- name: Create Local Nuget
|
||||
run: mkdir -p "${{ env.PULUMI_LOCAL_NUGET }}"
|
||||
shell: bash
|
||||
- run: dotnet nuget add source ${{ env.PULUMI_LOCAL_NUGET }}
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
|
@ -295,9 +300,6 @@ jobs:
|
|||
python-version: ${{ matrix.python-version }}
|
||||
- name: Clean
|
||||
run: dotnet nuget locals all --clear
|
||||
- name: Create Local Nuget
|
||||
run: mkdir -p "D:\\Pulumi\\nuget"
|
||||
shell: bash
|
||||
- name: Install Python Deps
|
||||
run: |
|
||||
pip3 install pyenv-win
|
||||
|
|
5
.github/workflows/release.yml
vendored
5
.github/workflows/release.yml
vendored
|
@ -236,6 +236,7 @@ jobs:
|
|||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: ${{ matrix.dotnet-version }}
|
||||
- run: mkdir -p ${{ runner.temp }}/opt/pulumi/nuget
|
||||
- run: dotnet nuget add source ${{ runner.temp }}/opt/pulumi/nuget
|
||||
- name: Set up Node ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
|
@ -305,6 +306,7 @@ jobs:
|
|||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: ${{ matrix.dotnet-version }}
|
||||
- run: mkdir -p ${{ runner.temp }}/opt/pulumi/nuget
|
||||
- run: dotnet nuget add source ${{ runner.temp }}/opt/pulumi/nuget
|
||||
- name: Set up Node ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
|
@ -386,6 +388,9 @@ jobs:
|
|||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: ${{ matrix.dotnet }}
|
||||
- name: Create Local Nuget
|
||||
run: mkdir -p "${{ env.PULUMI_LOCAL_NUGET }}"
|
||||
shell: bash
|
||||
- run: dotnet nuget add source ${{ env.PULUMI_LOCAL_NUGET }}
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
|
|
|
@ -82,6 +82,7 @@ jobs:
|
|||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: ${{ matrix.dotnet-version }}
|
||||
- run: mkdir -p ${{ runner.temp }}/opt/pulumi/nuget
|
||||
- run: dotnet nuget add source ${{ runner.temp }}/opt/pulumi/nuget
|
||||
- name: Set up Node ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
|
@ -170,6 +171,7 @@ jobs:
|
|||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: ${{ matrix.dotnet-version }}
|
||||
- run: mkdir -p ${{ runner.temp }}/opt/pulumi/nuget
|
||||
- run: dotnet nuget add source ${{ runner.temp }}/opt/pulumi/nuget
|
||||
- name: Set up Node ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
|
@ -279,6 +281,9 @@ jobs:
|
|||
run: |
|
||||
pip3 install pyenv-win
|
||||
pip3 install pipenv
|
||||
- name: Create Local Nuget
|
||||
run: mkdir -p "${{ env.PULUMI_LOCAL_NUGET }}"
|
||||
shell: bash
|
||||
- run: dotnet nuget add source ${{ env.PULUMI_LOCAL_NUGET }}
|
||||
- name: Set Build Env Vars
|
||||
shell: bash
|
||||
|
|
13
.github/workflows/run-docs-generation.yml
vendored
13
.github/workflows/run-docs-generation.yml
vendored
|
@ -93,8 +93,21 @@ jobs:
|
|||
# If generating docs for more providers here, be sure to update
|
||||
# the description of the draft PR that is opened in the next step.
|
||||
pushd docs
|
||||
|
||||
pushd tools/resourcedocsgen
|
||||
go mod edit -replace github.com/pulumi/pulumi/pkg/v3=../../../pulumi/pkg
|
||||
go mod edit -replace github.com/pulumi/pulumi/sdk/v3=../../../pulumi/sdk
|
||||
popd
|
||||
|
||||
./scripts/gen_resource_docs.sh aws true
|
||||
./scripts/gen_resource_docs.sh kubernetes true
|
||||
|
||||
# Undo the changes to the go.mod and go.sum files since we don't want the PR
|
||||
# to contain local overrides or the PR build in docs repo would fail.
|
||||
pushd tools/resourcedocsgen
|
||||
git checkout .
|
||||
popd
|
||||
|
||||
popd
|
||||
|
||||
echo "::set-output name=branchName::${BRANCH_NAME}"
|
||||
|
|
|
@ -5,7 +5,7 @@ image:
|
|||
tasks:
|
||||
- before: >
|
||||
mkdir -p /workspace/opt-pulumi &&
|
||||
sudo ln -s /workspace/opt-pulumi /opt/pulumi
|
||||
sudo ln -s /workspace/opt-pulumi $HOME/.pulumi
|
||||
init: >
|
||||
make ensure &&
|
||||
make install
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
FROM gitpod/workspace-full
|
||||
USER gitpod
|
||||
|
||||
ENV PATH="/opt/pulumi:/opt/pulumi/bin:$PATH"
|
||||
ENV PATH="$HOME/.pulumi:$HOME/.pulumi/bin:$PATH"
|
||||
|
||||
# Install .NET Core 3.1 SDK binaries on Ubuntu 20.04
|
||||
# Source: https://dev.to/carlos487/installing-dotnet-core-in-ubuntu-20-04-6jh
|
||||
|
|
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
|
@ -11,4 +11,7 @@
|
|||
// Experimental but seems to work and means we don't need a vscode instance per go.mod file.
|
||||
"experimentalWorkspaceModule": true,
|
||||
},
|
||||
|
||||
"omnisharp.defaultLaunchSolution": "sdk/dotnet/dotnet.sln",
|
||||
"dotnet-test-explorer.testProjectPath": "sdk/dotnet",
|
||||
}
|
84
CHANGELOG.md
84
CHANGELOG.md
|
@ -1,6 +1,90 @@
|
|||
CHANGELOG
|
||||
=========
|
||||
|
||||
## 3.18.1 (2021-11-22)
|
||||
|
||||
### Improvements
|
||||
|
||||
- [cli] - When running `pulumi new https://github.com/name/repo`, check
|
||||
for branch `main` if branch `master` doesn't exist.
|
||||
[#8463](https://github.com/pulumi/pulumi/pull/8463)
|
||||
|
||||
- [codegen/python] - Program generator now uses `fn_output` forms where
|
||||
appropriate, simplifying auto-generated examples.
|
||||
[#8433](https://github.com/pulumi/pulumi/pull/8433)
|
||||
|
||||
- [codegen/go] - Program generator now uses fnOutput forms where
|
||||
appropriate, simplifying auto-generated examples.
|
||||
[#8431](https://github.com/pulumi/pulumi/pull/8431)
|
||||
|
||||
- [codegen/dotnet] - Program generator now uses `Invoke` forms where
|
||||
appropriate, simplifying auto-generated examples.
|
||||
[#8432](https://github.com/pulumi/pulumi/pull/8432)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- [cli/nodejs] - Allow specifying the tsconfig file used in Pulumi.yaml.
|
||||
[#8452](https://github.com/pulumi/pulumi/pull/8452)
|
||||
|
||||
- [codegen/nodejs] - Respect default values in Pulumi object types.
|
||||
[#8400](https://github.com/pulumi/pulumi/pull/8400)
|
||||
|
||||
- [sdk/python] - Correctly handle version checking python virtual environments.
|
||||
[#8465](https://github.com/pulumi/pulumi/pull/8465)
|
||||
|
||||
- [cli] - Catch expected errors in stacks with filestate backends.
|
||||
[#8455](https://github.com/pulumi/pulumi/pull/8455)
|
||||
|
||||
- [sdk/dotnet] - Do not attempt to serialize unknown values.
|
||||
[#8475](https://github.com/pulumi/pulumi/pull/8475)
|
||||
|
||||
## 3.18.0 (2021-11-17)
|
||||
|
||||
### Improvements
|
||||
- [ci] - Adds CI detector for Buildkite
|
||||
[#7933](https://github.com/pulumi/pulumi/pull/7933)
|
||||
|
||||
- [cli] - Add `--exclude-protected` flag to `pulumi destroy`.
|
||||
[#8359](https://github.com/pulumi/pulumi/pull/8359)
|
||||
|
||||
- [cli] Add the ability to use `pulumi org set [name]` to set a default org
|
||||
to use when creating a stacks in the Pulumi Service backend or self-hosted Service.
|
||||
[#8352](https://github.com/pulumi/pulumi/pull/8352)
|
||||
|
||||
- [schema] Add IsOverlay option to disable codegen for particular types.
|
||||
[#8338](https://github.com/pulumi/pulumi/pull/8338)
|
||||
[#8425](https://github.com/pulumi/pulumi/pull/8425)
|
||||
|
||||
- [sdk/dotnet] - Marshal output values.
|
||||
[#8316](https://github.com/pulumi/pulumi/pull/8316)
|
||||
|
||||
- [sdk/python] - Unmarshal output values in component provider.
|
||||
[#8212](https://github.com/pulumi/pulumi/pull/8212)
|
||||
|
||||
- [sdk/nodejs] - Unmarshal output values in component provider.
|
||||
[#8205](https://github.com/pulumi/pulumi/pull/8205)
|
||||
|
||||
- [sdk/nodejs] - Allow returning failures from Call in the provider without setting result outputs.
|
||||
[#8424](https://github.com/pulumi/pulumi/pull/8424)
|
||||
|
||||
- [sdk/go] - Allow specifying Call failures from the provider.
|
||||
[#8424](https://github.com/pulumi/pulumi/pull/8424)
|
||||
|
||||
- [codegen/nodejs] - Program generator now uses `fnOutput` forms where
|
||||
appropriate, simplifying auto-generated examples.
|
||||
[#8434](https://github.com/pulumi/pulumi/pull/8434)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- [engine] - Compute dependents correctly during targeted deletes.
|
||||
[#8360](https://github.com/pulumi/pulumi/pull/8360)
|
||||
|
||||
- [cli/engine] - Update command respects `--target-dependents`.
|
||||
[#8395](https://github.com/pulumi/pulumi/pull/8395)
|
||||
|
||||
- [docs] - Fix broken lists in dotnet docs.
|
||||
[docs#6558](https://github.com/pulumi/docs/issues/6558)
|
||||
|
||||
## 3.17.1 (2021-11-09)
|
||||
|
||||
### Improvements
|
||||
|
|
|
@ -1,18 +1,12 @@
|
|||
### Improvements
|
||||
|
||||
- [codegen/docs] Edit docs codegen to document `$fnOutput` function
|
||||
invoke forms in API documentation.
|
||||
[#8287](https://github.com/pulumi/pulumi/pull/8287)
|
||||
|
||||
- [codegen/go] - Remove `ResourcePtr` types from generated SDKs. Besides being
|
||||
unnecessary--`Resource` types already accommodate `nil` to indicate the lack of
|
||||
a value--the implementation of `Ptr` types for resources was incorrect, making
|
||||
these types virtually unusable in practice.
|
||||
[#8449](https://github.com/pulumi/pulumi/pull/8449)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- [automation/python] - Fix deserialization of events.
|
||||
[#8375](https://github.com/pulumi/pulumi/pull/8375)
|
||||
|
||||
- [sdk/dotnet] - Fixes failing preview for programs that call data
|
||||
sources (`F.Invoke`) with unknown outputs
|
||||
[#8339](https://github.com/pulumi/pulumi/pull/8339)
|
||||
|
||||
- [programgen/go] - Don't change imported resource names.
|
||||
[#8353](https://github.com/pulumi/pulumi/pull/8353)
|
||||
- [codegen/go] - Respect default values in Pulumi object types.
|
||||
[#8411](https://github.com/pulumi/pulumi/pull/8400)
|
||||
|
|
|
@ -22,7 +22,7 @@ To hack on Pulumi, you'll need to get a development environment set up. You'll w
|
|||
You can easily get all required dependencies with brew and npm
|
||||
|
||||
```bash
|
||||
brew install node pipenv python@3 typescript yarn go@1.17 golangci/tap/golangci-lint pulumi/tap/pulumictl
|
||||
brew install node pipenv python@3 typescript yarn go@1.17 golangci/tap/golangci-lint pulumi/tap/pulumictl coreutils
|
||||
curl https://raw.githubusercontent.com/Homebrew/homebrew-cask/0272f0d33f/Casks/dotnet-sdk.rb > dotnet-sdk.rb # v3.1.0
|
||||
brew install --HEAD -s dotnet-sdk.rb
|
||||
rm dotnet-sdk.rb
|
||||
|
@ -38,12 +38,10 @@ If you have a web browser, you can get a fully pre-configured Pulumi development
|
|||
|
||||
We use `make` as our build system, so you'll want to install that as well, if you don't have it already. We have extremely limited support for doing development on Windows (the bare minimum for us to get Windows validation of `pulumi`) so if you're on windows, we recommend that you use the [Windows Subsystem for Linux](https://docs.microsoft.com/en-us/windows/wsl/install-win10). We'd like to [make this better](https://github.com/pulumi/pulumi/issues/208) so feel free to pitch in if you can.
|
||||
|
||||
For historical reasons (which we'd [like to address](https://github.com/pulumi/pulumi/issues/1515)) our build system requires that the folder `/opt/pulumi` exists and is writable by the current user. If you'd like, you can override this location by setting `PULUMI_ROOT` in your environment. The build is known to fail if this doesn't exist, so you'll need to create it first.
|
||||
We build Pulumi in `$PULUMI_ROOT`, which defaults to `$HOME/.pulumi`. If you would like to build Pulumi in another location, you do so by setting `$PULUMI_ROOT`.
|
||||
|
||||
```bash
|
||||
mkdir /opt/pulumi
|
||||
sudo chown <your_user_name>: /opt/pulumi
|
||||
export PATH=/opt/pulumi:/opt/pulumi/bin:$PATH
|
||||
export PATH=$HOME/.pulumi/bin:$PATH
|
||||
```
|
||||
|
||||
You'll also need to make sure your maximum open file descriptor limit is set to 5000 at a minimum.
|
||||
|
@ -55,9 +53,10 @@ ulimit -n 5000
|
|||
|
||||
Across our projects, we try to use a regular set of make targets. The ones you'll care most about are:
|
||||
|
||||
0. `make ensure`, which restores/installs any build dependencies
|
||||
1. `make ensure`, which restores/installs any build dependencies
|
||||
1. `make dist`, which just builds and installs the Pulumi CLI
|
||||
1. `make`, which builds Pulumi and runs a quick set of tests
|
||||
2. `make all` which builds Pulumi and runs the quick tests and a larger set of tests.
|
||||
1. `make all` which builds Pulumi and runs the quick tests and a larger set of tests.
|
||||
|
||||
We make heavy use of integration level testing where we invoke `pulumi` to create and then delete cloud resources. This requires you to have a Pulumi account (so [sign up for free](https://pulumi.com) today if you haven't already) and login with `pulumi login`.
|
||||
|
||||
|
|
15
Makefile
15
Makefile
|
@ -29,19 +29,18 @@ build-proto::
|
|||
.PHONY: generate
|
||||
generate::
|
||||
$(call STEP_MESSAGE)
|
||||
echo "Generate static assets bundle for docs generator"
|
||||
cd pkg && go generate ./codegen/docs/gen.go
|
||||
echo "This command does not do anything anymore. It will be removed in a future version."
|
||||
|
||||
build:: generate
|
||||
build::
|
||||
cd pkg && go install -ldflags "-X github.com/pulumi/pulumi/pkg/v3/version.Version=${VERSION}" ${PROJECT}
|
||||
|
||||
build_debug:: generate
|
||||
build_debug::
|
||||
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
|
||||
install::
|
||||
cd pkg && GOBIN=$(PULUMI_BIN) go install -ldflags "-X github.com/pulumi/pulumi/pkg/v3/version.Version=${VERSION}" ${PROJECT}
|
||||
|
||||
install_all:: install
|
||||
|
@ -66,6 +65,8 @@ test_build:: $(TEST_ALL_DEPS)
|
|||
cd tests/testprovider && go build -o pulumi-resource-testprovider
|
||||
cd tests/integration/construct_component/testcomponent && yarn install && yarn link @pulumi/pulumi && yarn run tsc
|
||||
cd tests/integration/construct_component/testcomponent-go && go build -o pulumi-resource-testcomponent
|
||||
cd tests/integration/construct_component_output_values/testcomponent && yarn install && yarn link @pulumi/pulumi && yarn run tsc
|
||||
cd tests/integration/construct_component_output_values/testcomponent-go && go build -o pulumi-resource-testcomponent
|
||||
cd tests/integration/construct_component_slow/testcomponent && yarn install && yarn link @pulumi/pulumi && yarn run tsc
|
||||
cd tests/integration/construct_component_plain/testcomponent && yarn install && yarn link @pulumi/pulumi && yarn run tsc
|
||||
cd tests/integration/construct_component_plain/testcomponent-go && go build -o pulumi-resource-testcomponent
|
||||
|
@ -80,6 +81,10 @@ test_build:: $(TEST_ALL_DEPS)
|
|||
cd tests/integration/construct_component_provider/testcomponent-go && go build -o pulumi-resource-testcomponent
|
||||
cd tests/integration/construct_component_methods_unknown/testcomponent && yarn install && yarn link @pulumi/pulumi && yarn run tsc
|
||||
cd tests/integration/construct_component_methods_unknown/testcomponent-go && go build -o pulumi-resource-testcomponent
|
||||
cd tests/integration/construct_component_methods_resources/testcomponent && yarn install && yarn link @pulumi/pulumi && yarn run tsc
|
||||
cd tests/integration/construct_component_methods_resources/testcomponent-go && go build -o pulumi-resource-testcomponent
|
||||
cd tests/integration/construct_component_methods_errors/testcomponent && yarn install && yarn link @pulumi/pulumi && yarn run tsc
|
||||
cd tests/integration/construct_component_methods_errors/testcomponent-go && go build -o pulumi-resource-testcomponent
|
||||
|
||||
test_all:: test_build
|
||||
cd pkg && $(GO_TEST) ${PROJECT_PKGS}
|
||||
|
|
|
@ -173,8 +173,8 @@ details of the core Pulumi CLI and [programming model concepts](https://www.pulu
|
|||
|
||||
| Architecture | Build Status |
|
||||
| ------------ | ------------ |
|
||||
| Linux/macOS x64 | [![Linux x64 Build Status](https://travis-ci.com/pulumi/pulumi.svg?token=cTUUEgrxaTEGyecqJpDn&branch=master)](https://travis-ci.com/pulumi/pulumi) |
|
||||
| Windows x64 | [![Windows x64 Build Status](https://ci.appveyor.com/api/projects/status/uqrduw6qnoss7g4i?svg=true&branch=master)](https://ci.appveyor.com/project/pulumi/pulumi) |
|
||||
| Linux/macOS x64 | [![Linux x64 Build Status](https://github.com/pulumi/pulumi/actions/workflows/master.yml/badge.svg)](https://github.com/pulumi/pulumi/actions/workflows/master.yml) |
|
||||
| Windows x64 | [![Windows x64 Build Status](https://ci.appveyor.com/api/projects/status/uqrduw6qnoss7g4i?svg=true&branch=master)](https://ci.appveyor.com/project/pulumi/pulumi) |
|
||||
|
||||
### Languages
|
||||
|
||||
|
|
18
build.proj
18
build.proj
|
@ -271,6 +271,10 @@
|
|||
WorkingDirectory="$(TestsDirectory)\integration\construct_component\testcomponent" />
|
||||
<Exec Command="yarn link @pulumi/pulumi"
|
||||
WorkingDirectory="$(TestsDirectory)\integration\construct_component\testcomponent" />
|
||||
<Exec Command="yarn install"
|
||||
WorkingDirectory="$(TestsDirectory)\integration\construct_component_output_values\testcomponent" />
|
||||
<Exec Command="yarn link @pulumi/pulumi"
|
||||
WorkingDirectory="$(TestsDirectory)\integration\construct_component_output_values\testcomponent" />
|
||||
<Exec Command="yarn install"
|
||||
WorkingDirectory="$(TestsDirectory)\integration\construct_component_slow\testcomponent" />
|
||||
<Exec Command="yarn link @pulumi/pulumi"
|
||||
|
@ -299,6 +303,14 @@
|
|||
WorkingDirectory="$(TestsDirectory)\integration\construct_component_methods_unknown\testcomponent" />
|
||||
<Exec Command="yarn link @pulumi/pulumi"
|
||||
WorkingDirectory="$(TestsDirectory)\integration\construct_component_methods_unknown\testcomponent" />
|
||||
<Exec Command="yarn install"
|
||||
WorkingDirectory="$(TestsDirectory)\integration\construct_component_methods_resources\testcomponent" />
|
||||
<Exec Command="yarn link @pulumi/pulumi"
|
||||
WorkingDirectory="$(TestsDirectory)\integration\construct_component_methods_resources\testcomponent" />
|
||||
<Exec Command="yarn install"
|
||||
WorkingDirectory="$(TestsDirectory)\integration\construct_component_methods_errors\testcomponent" />
|
||||
<Exec Command="yarn link @pulumi/pulumi"
|
||||
WorkingDirectory="$(TestsDirectory)\integration\construct_component_methods_errors\testcomponent" />
|
||||
<Exec Command="yarn install"
|
||||
WorkingDirectory="$(TestsDirectory)\integration\construct_component_provider\testcomponent" />
|
||||
<Exec Command="yarn link @pulumi/pulumi"
|
||||
|
@ -309,6 +321,8 @@
|
|||
<Exec Command="go build -o pulumi-resource-testprovider.exe" WorkingDirectory="$(TestsDirectory)\testprovider" />
|
||||
<Exec Command="yarn run tsc" WorkingDirectory="$(TestsDirectory)\integration\construct_component\testcomponent" />
|
||||
<Exec Command="go build -o pulumi-resource-testcomponent.exe" WorkingDirectory="$(TestsDirectory)\integration\construct_component\testcomponent-go" />
|
||||
<Exec Command="yarn run tsc" WorkingDirectory="$(TestsDirectory)\integration\construct_component_output_values\testcomponent" />
|
||||
<Exec Command="go build -o pulumi-resource-testcomponent.exe" WorkingDirectory="$(TestsDirectory)\integration\construct_component_output_values\testcomponent-go" />
|
||||
<Exec Command="yarn run tsc" WorkingDirectory="$(TestsDirectory)\integration\construct_component_slow\testcomponent" />
|
||||
<Exec Command="yarn run tsc" WorkingDirectory="$(TestsDirectory)\integration\construct_component_plain\testcomponent" />
|
||||
<Exec Command="go build -o pulumi-resource-testcomponent.exe" WorkingDirectory="$(TestsDirectory)\integration\construct_component_plain\testcomponent-go" />
|
||||
|
@ -321,6 +335,10 @@
|
|||
<Exec Command="go build -o pulumi-resource-testcomponent.exe" WorkingDirectory="$(TestsDirectory)\integration\construct_component_methods\testcomponent-go" />
|
||||
<Exec Command="yarn run tsc" WorkingDirectory="$(TestsDirectory)\integration\construct_component_methods_unknown\testcomponent" />
|
||||
<Exec Command="go build -o pulumi-resource-testcomponent.exe" WorkingDirectory="$(TestsDirectory)\integration\construct_component_methods_unknown\testcomponent-go" />
|
||||
<Exec Command="yarn run tsc" WorkingDirectory="$(TestsDirectory)\integration\construct_component_methods_resources\testcomponent" />
|
||||
<Exec Command="go build -o pulumi-resource-testcomponent.exe" WorkingDirectory="$(TestsDirectory)\integration\construct_component_methods_resources\testcomponent-go" />
|
||||
<Exec Command="yarn run tsc" WorkingDirectory="$(TestsDirectory)\integration\construct_component_methods_errors\testcomponent" />
|
||||
<Exec Command="go build -o pulumi-resource-testcomponent.exe" WorkingDirectory="$(TestsDirectory)\integration\construct_component_methods_errors\testcomponent-go" />
|
||||
<Exec Command="yarn run tsc" WorkingDirectory="$(TestsDirectory)\integration\construct_component_provider\testcomponent" />
|
||||
<Exec Command="go build -o pulumi-resource-testcomponent.exe" WorkingDirectory="$(TestsDirectory)\integration\construct_component_provider\testcomponent-go" />
|
||||
|
||||
|
|
|
@ -96,9 +96,9 @@ SHELL := /bin/bash
|
|||
STEP_MESSAGE = @echo -e "\033[0;32m$(shell echo '$@' | tr a-z A-Z | tr '_' ' '):\033[0m"
|
||||
|
||||
# Our install targets place items item into $PULUMI_ROOT, if it's
|
||||
# unset, default to /opt/pulumi.
|
||||
# unset, default to `$HOME/.pulumi`.
|
||||
ifeq ($(PULUMI_ROOT),)
|
||||
PULUMI_ROOT:=/opt/pulumi
|
||||
PULUMI_ROOT:=$(shell realpath "$$HOME/.pulumi")
|
||||
endif
|
||||
|
||||
# Use Python 3 explicitly vs expecting that `python` will resolve to a python 3
|
||||
|
@ -168,6 +168,7 @@ test_fast::
|
|||
|
||||
install::
|
||||
$(call STEP_MESSAGE)
|
||||
# Implicitly creates PULUMI_ROOT.
|
||||
@mkdir -p $(PULUMI_BIN)
|
||||
@mkdir -p $(PULUMI_NODE_MODULES)
|
||||
@mkdir -p $(PULUMI_NUGET)
|
||||
|
|
|
@ -57,6 +57,14 @@ The description of the package. Descriptions are interpreted as Markdown.
|
|||
|
||||
---
|
||||
|
||||
### `displayName`
|
||||
|
||||
The human-friendly name of the package.
|
||||
|
||||
`string`
|
||||
|
||||
---
|
||||
|
||||
### `functions`
|
||||
|
||||
A map from token to functionSpec that describes the set of functions defined by this package.
|
||||
|
@ -159,6 +167,14 @@ The provider type for this package.
|
|||
|
||||
---
|
||||
|
||||
### `publisher`
|
||||
|
||||
The name of the person or organization that authored and published the package.
|
||||
|
||||
`string`
|
||||
|
||||
---
|
||||
|
||||
### `repository`
|
||||
|
||||
The URL at which the package's sources can be found.
|
||||
|
@ -297,7 +313,7 @@ Enum: `"boolean"` | `"integer"` | `"number"` | `"string"`
|
|||
|
||||
#### `deprecationMessage`
|
||||
|
||||
Indicates whether or not the value is deprecated.
|
||||
Indicates whether the value is deprecated.
|
||||
|
||||
`string`
|
||||
|
||||
|
@ -339,7 +355,7 @@ Describes a function.
|
|||
|
||||
#### `deprecationMessage`
|
||||
|
||||
Indicates whether or not the function is deprecated
|
||||
Indicates whether the function is deprecated
|
||||
|
||||
`string`
|
||||
|
||||
|
@ -361,6 +377,14 @@ The bag of input values for the function, if any.
|
|||
|
||||
---
|
||||
|
||||
#### `isOverlay`
|
||||
|
||||
Indicates that the implementation of the function should not be generated from the schema, and is instead provided out-of-band by the package author
|
||||
|
||||
`boolean`
|
||||
|
||||
---
|
||||
|
||||
#### `language`
|
||||
|
||||
Additional language-specific data about the function.
|
||||
|
@ -564,7 +588,7 @@ Additional language-specific data about the default value.
|
|||
|
||||
#### `deprecationMessage`
|
||||
|
||||
Indicates whether or not the property is deprecated
|
||||
Indicates whether the property is deprecated
|
||||
|
||||
`string`
|
||||
|
||||
|
@ -627,7 +651,7 @@ Items: [Alias Definition](#alias-definition)
|
|||
|
||||
#### `deprecationMessage`
|
||||
|
||||
Indicates whether or not the resource is deprecated
|
||||
Indicates whether the resource is deprecated
|
||||
|
||||
`string`
|
||||
|
||||
|
@ -653,7 +677,15 @@ Additional properties: [Property Definition](#property-definition)
|
|||
|
||||
#### `isComponent`
|
||||
|
||||
Indicates whether or not the resource is a component.
|
||||
Indicates whether the resource is a component.
|
||||
|
||||
`boolean`
|
||||
|
||||
---
|
||||
|
||||
#### `isOverlay`
|
||||
|
||||
Indicates that the implementation of the resource should not be generated from the schema, and is instead provided out-of-band by the package author
|
||||
|
||||
`boolean`
|
||||
|
||||
|
@ -691,7 +723,7 @@ An optional objectTypeSpec that describes additional inputs that mau be necessar
|
|||
|
||||
`string`
|
||||
|
||||
Pattern: `^[a-zA-Z][-a-zA-Z0-9_]*:([^0-9][a-zA-Z0-9._/]*)?:[^0-9][a-zA-Z0-9._/]*$`
|
||||
Pattern: `^[a-zA-Z][-a-zA-Z0-9_]*:([^0-9][a-zA-Z0-9._/-]*)?:[^0-9][a-zA-Z0-9._/]*$`
|
||||
|
||||
## Type Definition
|
||||
|
||||
|
@ -713,6 +745,14 @@ The description of the type, if any. Interpreted as Markdown.
|
|||
|
||||
---
|
||||
|
||||
#### `isOverlay`
|
||||
|
||||
Indicates that the implementation of the type should not be generated from the schema, and is instead provided out-of-band by the package author
|
||||
|
||||
`boolean`
|
||||
|
||||
---
|
||||
|
||||
#### `language`
|
||||
|
||||
Additional language-specific data about the type.
|
||||
|
|
|
@ -21,7 +21,6 @@ import (
|
|||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
survey "gopkg.in/AlecAivazis/survey.v1"
|
||||
surveycore "gopkg.in/AlecAivazis/survey.v1/core"
|
||||
|
||||
|
@ -171,7 +170,7 @@ func confirmBeforeUpdating(kind apitype.UpdateKind, stack Stack,
|
|||
Options: choices,
|
||||
Default: string(no),
|
||||
}, &response, nil); err != nil {
|
||||
return result.FromError(errors.Wrapf(err, "confirmation cancelled, not proceeding with the %s", kind))
|
||||
return result.FromError(fmt.Errorf("confirmation cancelled, not proceeding with the %s: %w", kind, err))
|
||||
}
|
||||
|
||||
if response == string(no) {
|
||||
|
|
|
@ -16,12 +16,11 @@ package backend
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend/display"
|
||||
"github.com/pulumi/pulumi/pkg/v3/engine"
|
||||
"github.com/pulumi/pulumi/pkg/v3/operations"
|
||||
|
@ -298,7 +297,7 @@ func (c *backendClient) GetStackOutputs(ctx context.Context, name string) (resou
|
|||
return nil, err
|
||||
}
|
||||
if s == nil {
|
||||
return nil, errors.Errorf("unknown stack %q", name)
|
||||
return nil, fmt.Errorf("unknown stack %q", name)
|
||||
}
|
||||
snap, err := s.Snapshot(ctx)
|
||||
if err != nil {
|
||||
|
@ -306,7 +305,7 @@ func (c *backendClient) GetStackOutputs(ctx context.Context, name string) (resou
|
|||
}
|
||||
res, err := stack.GetRootStackResource(snap)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "getting root stack resources")
|
||||
return nil, fmt.Errorf("getting root stack resources: %w", err)
|
||||
}
|
||||
if res == nil {
|
||||
return resource.PropertyMap{}, nil
|
||||
|
@ -325,7 +324,7 @@ func (c *backendClient) GetStackResourceOutputs(
|
|||
return nil, err
|
||||
}
|
||||
if s == nil {
|
||||
return nil, errors.Errorf("unknown stack %q", name)
|
||||
return nil, fmt.Errorf("unknown stack %q", name)
|
||||
}
|
||||
snap, err := s.Snapshot(ctx)
|
||||
if err != nil {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package display
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/v3/engine"
|
||||
"github.com/pulumi/pulumi/pkg/v3/resource/stack"
|
||||
|
@ -21,7 +21,7 @@ func ConvertEngineEvent(e engine.Event) (apitype.EngineEvent, error) {
|
|||
var apiEvent apitype.EngineEvent
|
||||
|
||||
// Error to return if the payload doesn't match expected.
|
||||
eventTypePayloadMismatch := errors.Errorf("unexpected payload for event type %v", e.Type)
|
||||
eventTypePayloadMismatch := fmt.Errorf("unexpected payload for event type %v", e.Type)
|
||||
|
||||
switch e.Type {
|
||||
case engine.CancelEvent:
|
||||
|
@ -130,7 +130,7 @@ func ConvertEngineEvent(e engine.Event) (apitype.EngineEvent, error) {
|
|||
}
|
||||
|
||||
default:
|
||||
return apiEvent, errors.Errorf("unknown event type %q", e.Type)
|
||||
return apiEvent, fmt.Errorf("unknown event type %q", e.Type)
|
||||
}
|
||||
|
||||
return apiEvent, nil
|
||||
|
|
|
@ -17,6 +17,7 @@ package filestate
|
|||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
|
@ -28,7 +29,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/gofrs/uuid"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
user "github.com/tweekmonster/luser"
|
||||
"gocloud.dev/blob"
|
||||
_ "gocloud.dev/blob/azureblob" // driver for azblob://
|
||||
|
@ -103,7 +104,7 @@ const FilePathPrefix = "file://"
|
|||
|
||||
func New(d diag.Sink, originalURL string) (Backend, error) {
|
||||
if !IsFileStateBackendURL(originalURL) {
|
||||
return nil, errors.Errorf("local URL %s has an illegal prefix; expected one of: %s",
|
||||
return nil, fmt.Errorf("local URL %s has an illegal prefix; expected one of: %s",
|
||||
originalURL, strings.Join(blob.DefaultURLMux().BucketSchemes(), ", "))
|
||||
}
|
||||
|
||||
|
@ -130,7 +131,7 @@ func New(d diag.Sink, originalURL string) (Backend, error) {
|
|||
|
||||
bucket, err := blobmux.OpenBucket(context.TODO(), u)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "unable to open bucket %s", u)
|
||||
return nil, fmt.Errorf("unable to open bucket %s: %w", u, err)
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(u, FilePathPrefix) {
|
||||
|
@ -178,7 +179,7 @@ func massageBlobPath(path string) (string, error) {
|
|||
if strings.HasPrefix(path, "~") {
|
||||
usr, err := user.Current()
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "Could not determine current user to resolve `file://~` path.")
|
||||
return "", fmt.Errorf("Could not determine current user to resolve `file://~` path.: %w", err)
|
||||
}
|
||||
|
||||
if path == "~" {
|
||||
|
@ -191,7 +192,7 @@ func massageBlobPath(path string) (string, error) {
|
|||
// For file:// backend, ensure a relative path is resolved. fileblob only supports absolute paths.
|
||||
path, err := filepath.Abs(path)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "An IO error occurred while building the absolute path")
|
||||
return "", fmt.Errorf("An IO error occurred while building the absolute path: %w", err)
|
||||
}
|
||||
|
||||
// Using example from https://godoc.org/gocloud.dev/blob/fileblob#example-package--OpenBucket
|
||||
|
@ -300,10 +301,10 @@ func (b *localBackend) CreateStack(ctx context.Context, stackRef backend.StackRe
|
|||
|
||||
tags, err := backend.GetEnvironmentTagsForCurrentStack()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "getting stack tags")
|
||||
return nil, fmt.Errorf("getting stack tags: %w", err)
|
||||
}
|
||||
if err = validation.ValidateStackProperties(string(stackName), tags); err != nil {
|
||||
return nil, errors.Wrap(err, "validating stack properties")
|
||||
return nil, fmt.Errorf("validating stack properties: %w", err)
|
||||
}
|
||||
|
||||
file, err := b.saveStack(stackName, nil, nil)
|
||||
|
@ -320,8 +321,9 @@ func (b *localBackend) CreateStack(ctx context.Context, stackRef backend.StackRe
|
|||
func (b *localBackend) GetStack(ctx context.Context, stackRef backend.StackReference) (backend.Stack, error) {
|
||||
stackName := stackRef.Name()
|
||||
snapshot, path, err := b.getStack(stackName)
|
||||
|
||||
switch {
|
||||
case gcerrors.Code(errors.Cause(err)) == gcerrors.NotFound:
|
||||
case gcerrors.Code(err) == gcerrors.NotFound:
|
||||
return nil, nil
|
||||
case err != nil:
|
||||
return nil, err
|
||||
|
@ -410,7 +412,7 @@ func (b *localBackend) RenameStack(ctx context.Context, stack backend.Stack,
|
|||
return nil, err
|
||||
}
|
||||
if hasExisting {
|
||||
return nil, errors.Errorf("a stack named %s already exists", newName)
|
||||
return nil, fmt.Errorf("a stack named %s already exists", newName)
|
||||
}
|
||||
|
||||
// If we have a snapshot, we need to rename the URNs inside it to use the new stack name.
|
||||
|
@ -663,11 +665,11 @@ func (b *localBackend) apply(
|
|||
|
||||
if saveErr != nil {
|
||||
// We swallow backupErr as it is less important than the saveErr.
|
||||
return changes, result.FromError(errors.Wrap(saveErr, "saving update info"))
|
||||
return changes, result.FromError(fmt.Errorf("saving update info: %w", saveErr))
|
||||
}
|
||||
|
||||
if backupErr != nil {
|
||||
return changes, result.FromError(errors.Wrap(backupErr, "saving backup"))
|
||||
return changes, result.FromError(fmt.Errorf("saving backup: %w", backupErr))
|
||||
}
|
||||
|
||||
// Make sure to print a link to the stack's checkpoint before exiting.
|
||||
|
@ -776,7 +778,7 @@ func (b *localBackend) ExportDeployment(ctx context.Context,
|
|||
|
||||
sdep, err := stack.SerializeDeployment(snap, snap.SecretsManager /* showSecrsts */, false)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "serializing deployment")
|
||||
return nil, fmt.Errorf("serializing deployment: %w", err)
|
||||
}
|
||||
|
||||
data, err := json.Marshal(sdep)
|
||||
|
@ -840,7 +842,7 @@ func (b *localBackend) getLocalStacks() ([]tokens.QName, error) {
|
|||
|
||||
files, err := listBucket(b.bucket, path)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error listing stacks")
|
||||
return nil, fmt.Errorf("error listing stacks: %w", err)
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
|
|
|
@ -187,3 +187,20 @@ func TestListStacksWithMultiplePassphrases(t *testing.T) {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
func TestDrillError(t *testing.T) {
|
||||
// Login to a temp dir filestate backend
|
||||
tmpDir, err := ioutil.TempDir("", "filestatebackend")
|
||||
assert.NoError(t, err)
|
||||
b, err := New(cmdutil.Diag(), "file://"+filepath.ToSlash(tmpDir))
|
||||
assert.NoError(t, err)
|
||||
ctx := context.Background()
|
||||
|
||||
// Get a non-existent stack and expect a nil error because it won't be found.
|
||||
stackRef, err := b.ParseStackReference("dev")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error %v when parsing stack reference", err)
|
||||
}
|
||||
_, err = b.GetStack(ctx, stackRef)
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
|
|
@ -2,11 +2,11 @@ package filestate
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"path"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/pulumi/pulumi/sdk/v3/go/common/util/logging"
|
||||
"gocloud.dev/blob"
|
||||
)
|
||||
|
@ -77,7 +77,7 @@ func listBucket(bucket Bucket, dir string) ([]*blob.ListObject, error) {
|
|||
break
|
||||
}
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not list bucket")
|
||||
return nil, fmt.Errorf("could not list bucket: %w", err)
|
||||
}
|
||||
files = append(files, file)
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ func objectName(obj *blob.ListObject) string {
|
|||
func removeAllByPrefix(bucket Bucket, dir string) error {
|
||||
files, err := listBucket(bucket, dir)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to list bucket objects for removal")
|
||||
return fmt.Errorf("unable to list bucket objects for removal: %w", err)
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
|
@ -113,7 +113,7 @@ func removeAllByPrefix(bucket Bucket, dir string) error {
|
|||
func renameObject(bucket Bucket, source string, dest string) error {
|
||||
err := bucket.Copy(context.TODO(), dest, source, nil)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "copying %s to %s", source, dest)
|
||||
return fmt.Errorf("copying %s to %s: %w", source, dest, err)
|
||||
}
|
||||
|
||||
err = bucket.Delete(context.TODO(), source)
|
||||
|
|
|
@ -3,6 +3,8 @@ package filestate
|
|||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"golang.org/x/oauth2/google"
|
||||
|
@ -11,7 +13,6 @@ import (
|
|||
|
||||
"cloud.google.com/go/storage"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"gocloud.dev/blob"
|
||||
"gocloud.dev/gcp"
|
||||
)
|
||||
|
@ -33,7 +34,7 @@ func googleCredentials(ctx context.Context) (*google.Credentials, error) {
|
|||
// so that users can override the default creds
|
||||
credentials, err := google.CredentialsFromJSON(ctx, []byte(creds), storage.ScopeReadWrite)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to parse credentials from $GOOGLE_CREDENTIALS")
|
||||
return nil, fmt.Errorf("unable to parse credentials from $GOOGLE_CREDENTIALS: %w", err)
|
||||
}
|
||||
return credentials, nil
|
||||
}
|
||||
|
@ -43,7 +44,7 @@ func googleCredentials(ctx context.Context) (*google.Credentials, error) {
|
|||
// 2. application_default_credentials.json file in ~/.config/gcloud or $APPDATA\gcloud
|
||||
credentials, err := gcp.DefaultCredentials(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to find gcp credentials")
|
||||
return nil, fmt.Errorf("unable to find gcp credentials: %w", err)
|
||||
}
|
||||
return credentials, nil
|
||||
}
|
||||
|
|
|
@ -17,14 +17,13 @@ package filestate
|
|||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/user"
|
||||
"path"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend"
|
||||
"github.com/pulumi/pulumi/sdk/v3/go/common/diag"
|
||||
"github.com/pulumi/pulumi/sdk/v3/go/common/tokens"
|
||||
|
|
|
@ -17,6 +17,7 @@ package filestate
|
|||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
|
@ -28,7 +29,6 @@ import (
|
|||
|
||||
"github.com/pulumi/pulumi/pkg/v3/engine"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"gocloud.dev/blob"
|
||||
"gocloud.dev/gcerrors"
|
||||
|
||||
|
@ -133,7 +133,7 @@ func (b *localBackend) getStack(name tokens.QName) (*deploy.Snapshot, string, er
|
|||
|
||||
chk, err := b.getCheckpoint(name)
|
||||
if err != nil {
|
||||
return nil, file, errors.Wrap(err, "failed to load checkpoint")
|
||||
return nil, file, fmt.Errorf("failed to load checkpoint: %w", err)
|
||||
}
|
||||
|
||||
// Materialize an actual snapshot object.
|
||||
|
@ -145,8 +145,7 @@ func (b *localBackend) getStack(name tokens.QName) (*deploy.Snapshot, string, er
|
|||
// Ensure the snapshot passes verification before returning it, to catch bugs early.
|
||||
if !DisableIntegrityChecking {
|
||||
if verifyerr := snapshot.VerifyIntegrity(); verifyerr != nil {
|
||||
return nil, file,
|
||||
errors.Wrapf(verifyerr, "%s: snapshot integrity failure; refusing to use it", file)
|
||||
return nil, file, fmt.Errorf("%s: snapshot integrity failure; refusing to use it: %w", file, verifyerr)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -169,18 +168,18 @@ func (b *localBackend) saveStack(name tokens.QName, snap *deploy.Snapshot, sm se
|
|||
file := b.stackPath(name)
|
||||
m, ext := encoding.Detect(file)
|
||||
if m == nil {
|
||||
return "", errors.Errorf("resource serialization failed; illegal markup extension: '%v'", ext)
|
||||
return "", fmt.Errorf("resource serialization failed; illegal markup extension: '%v'", ext)
|
||||
}
|
||||
if filepath.Ext(file) == "" {
|
||||
file = file + ext
|
||||
}
|
||||
chk, err := stack.SerializeCheckpoint(name, snap, sm, false /* showSecrets */)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "serializaing checkpoint")
|
||||
return "", fmt.Errorf("serializaing checkpoint: %w", err)
|
||||
}
|
||||
byts, err := m.Marshal(chk)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "An IO error occurred while marshalling the checkpoint")
|
||||
return "", fmt.Errorf("An IO error occurred while marshalling the checkpoint: %w", err)
|
||||
}
|
||||
|
||||
// Back up the existing file if it already exists.
|
||||
|
@ -208,7 +207,7 @@ func (b *localBackend) saveStack(name tokens.QName, snap *deploy.Snapshot, sm se
|
|||
if err != nil {
|
||||
logging.V(7).Infof("Error while writing snapshot to: %s (attempt=%d, error=%s)", file, try, err)
|
||||
if try > 10 {
|
||||
return false, nil, errors.Wrap(err, "An IO error occurred while writing the new snapshot file")
|
||||
return false, nil, fmt.Errorf("An IO error occurred while writing the new snapshot file: %w", err)
|
||||
}
|
||||
return false, nil, nil
|
||||
}
|
||||
|
@ -225,7 +224,7 @@ func (b *localBackend) saveStack(name tokens.QName, snap *deploy.Snapshot, sm se
|
|||
// And if we are retaining historical checkpoint information, write it out again
|
||||
if cmdutil.IsTruthy(os.Getenv("PULUMI_RETAIN_CHECKPOINTS")) {
|
||||
if err = b.bucket.WriteAll(context.TODO(), fmt.Sprintf("%v.%v", file, time.Now().UnixNano()), byts, nil); err != nil {
|
||||
return "", errors.Wrap(err, "An IO error occurred while writing the new snapshot file")
|
||||
return "", fmt.Errorf("An IO error occurred while writing the new snapshot file: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -234,9 +233,10 @@ func (b *localBackend) saveStack(name tokens.QName, snap *deploy.Snapshot, sm se
|
|||
// out the checkpoint file since it may contain resource state updates. But we will warn the user that the
|
||||
// file is already written and might be bad.
|
||||
if verifyerr := snap.VerifyIntegrity(); verifyerr != nil {
|
||||
return "", errors.Wrapf(verifyerr,
|
||||
"%s: snapshot integrity failure; it was already written, but is invalid (backup available at %s)",
|
||||
file, bck)
|
||||
return "", fmt.Errorf(
|
||||
"%s: snapshot integrity failure; it was already written, but is invalid (backup available at %s): %w",
|
||||
file, bck, verifyerr)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -323,7 +323,7 @@ func (b *localBackend) getHistory(name tokens.QName, pageSize int, page int) ([]
|
|||
allFiles, err := listBucket(b.bucket, dir)
|
||||
if err != nil {
|
||||
// History doesn't exist until a stack has been updated.
|
||||
if gcerrors.Code(errors.Cause(err)) == gcerrors.NotFound {
|
||||
if gcerrors.Code(err) == gcerrors.NotFound {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, err
|
||||
|
@ -368,11 +368,11 @@ func (b *localBackend) getHistory(name tokens.QName, pageSize int, page int) ([]
|
|||
var update backend.UpdateInfo
|
||||
b, err := b.bucket.ReadAll(context.TODO(), filepath)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "reading history file %s", filepath)
|
||||
return nil, fmt.Errorf("reading history file %s: %w", filepath, err)
|
||||
}
|
||||
err = json.Unmarshal(b, &update)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "reading history file %s", filepath)
|
||||
return nil, fmt.Errorf("reading history file %s: %w", filepath, err)
|
||||
}
|
||||
|
||||
updates = append(updates, update)
|
||||
|
@ -391,7 +391,7 @@ func (b *localBackend) renameHistory(oldName tokens.QName, newName tokens.QName)
|
|||
allFiles, err := listBucket(b.bucket, oldHistory)
|
||||
if err != nil {
|
||||
// if there's nothing there, we don't really need to do a rename.
|
||||
if gcerrors.Code(errors.Cause(err)) == gcerrors.NotFound {
|
||||
if gcerrors.Code(err) == gcerrors.NotFound {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
|
@ -407,10 +407,10 @@ func (b *localBackend) renameHistory(oldName tokens.QName, newName tokens.QName)
|
|||
newBlob := path.Join(newHistory, newFileName)
|
||||
|
||||
if err := b.bucket.Copy(context.TODO(), newBlob, oldBlob, nil); err != nil {
|
||||
return errors.Wrap(err, "copying history file")
|
||||
return fmt.Errorf("copying history file: %w", err)
|
||||
}
|
||||
if err := b.bucket.Delete(context.TODO(), oldBlob); err != nil {
|
||||
return errors.Wrap(err, "deleting existing history file")
|
||||
return fmt.Errorf("deleting existing history file: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ import (
|
|||
"context"
|
||||
cryptorand "crypto/rand"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
|
@ -31,7 +32,7 @@ import (
|
|||
"time"
|
||||
|
||||
opentracing "github.com/opentracing/opentracing-go"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/skratchdot/open-golang/open"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend"
|
||||
|
@ -126,7 +127,7 @@ func New(d diag.Sink, cloudURL string) (Backend, error) {
|
|||
cloudURL = ValueOrDefaultURL(cloudURL)
|
||||
account, err := workspace.GetAccount(cloudURL)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "getting stored credentials")
|
||||
return nil, fmt.Errorf("getting stored credentials: %w", err)
|
||||
}
|
||||
apiToken := account.AccessToken
|
||||
|
||||
|
@ -163,13 +164,13 @@ func loginWithBrowser(ctx context.Context, d diag.Sink, cloudURL string, opts di
|
|||
c := make(chan string)
|
||||
l, err := net.Listen("tcp", "127.0.0.1:")
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not start listener")
|
||||
return nil, fmt.Errorf("could not start listener: %w", err)
|
||||
}
|
||||
|
||||
// Extract the port
|
||||
_, port, err := net.SplitHostPort(l.Addr().String())
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not determine port")
|
||||
return nil, fmt.Errorf("could not determine port: %w", err)
|
||||
}
|
||||
|
||||
// Generate a nonce we'll send with the request.
|
||||
|
@ -229,6 +230,10 @@ func loginWithBrowser(ctx context.Context, d diag.Sink, cloudURL string, opts di
|
|||
return New(d, cloudURL)
|
||||
}
|
||||
|
||||
func SetDefaultOrg(url string, orgName string) error {
|
||||
return workspace.SetBackendConfigDefaultOrg(url, orgName)
|
||||
}
|
||||
|
||||
// Login logs into the target cloud URL and returns the cloud backend for it.
|
||||
func Login(ctx context.Context, d diag.Sink, cloudURL string, opts display.Options) (Backend, error) {
|
||||
cloudURL = ValueOrDefaultURL(cloudURL)
|
||||
|
@ -269,8 +274,7 @@ func Login(ctx context.Context, d diag.Sink, cloudURL string, opts display.Optio
|
|||
} else if !cmdutil.Interactive() {
|
||||
// If interactive mode isn't enabled, the only way to specify a token is through the environment variable.
|
||||
// Fail the attempt to login.
|
||||
return nil, errors.Errorf(
|
||||
"%s must be set for login during non-interactive CLI sessions", AccessTokenEnvVar)
|
||||
return nil, fmt.Errorf("%s must be set for login during non-interactive CLI sessions", AccessTokenEnvVar)
|
||||
} else {
|
||||
// If no access token is available from the environment, and we are interactive, prompt and offer to
|
||||
// open a browser to make it easy to generate and use a fresh token.
|
||||
|
@ -333,7 +337,7 @@ func Login(ctx context.Context, d diag.Sink, cloudURL string, opts display.Optio
|
|||
if err != nil {
|
||||
return nil, err
|
||||
} else if !valid {
|
||||
return nil, errors.Errorf("invalid access token")
|
||||
return nil, fmt.Errorf("invalid access token")
|
||||
}
|
||||
|
||||
// Save them.
|
||||
|
@ -426,7 +430,7 @@ func (b *cloudBackend) parsePolicyPackReference(s string) (backend.PolicyPackRef
|
|||
orgName = split[0]
|
||||
policyPackName = split[1]
|
||||
default:
|
||||
return nil, errors.Errorf("could not parse policy pack name '%s'; must be of the form "+
|
||||
return nil, fmt.Errorf("could not parse policy pack name '%s'; must be of the form "+
|
||||
"<org-name>/<policy-pack-name>", s)
|
||||
}
|
||||
|
||||
|
@ -507,7 +511,7 @@ func (b *cloudBackend) parseStackName(s string) (qualifiedStackReference, error)
|
|||
q.Project = split[1]
|
||||
q.Name = split[2]
|
||||
default:
|
||||
return qualifiedStackReference{}, errors.Errorf("could not parse stack name '%s'", s)
|
||||
return qualifiedStackReference{}, fmt.Errorf("could not parse stack name '%s'", s)
|
||||
}
|
||||
|
||||
return q, nil
|
||||
|
@ -692,14 +696,14 @@ func (b *cloudBackend) CreateStack(
|
|||
|
||||
tags, err := backend.GetEnvironmentTagsForCurrentStack()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error determining initial tags")
|
||||
return nil, fmt.Errorf("error determining initial tags: %w", err)
|
||||
}
|
||||
|
||||
// Confirm the stack identity matches the environment. e.g. stack init foo/bar/baz shouldn't work
|
||||
// if the project name in Pulumi.yaml is anything other than "bar".
|
||||
projNameTag, ok := tags[apitype.ProjectNameTag]
|
||||
if ok && stackID.Project != projNameTag {
|
||||
return nil, errors.Errorf("provided project name %q doesn't match Pulumi.yaml", stackID.Project)
|
||||
return nil, fmt.Errorf("provided project name %q doesn't match Pulumi.yaml", stackID.Project)
|
||||
}
|
||||
|
||||
apistack, err := b.client.CreateStack(ctx, stackID, tags)
|
||||
|
@ -905,7 +909,7 @@ func (b *cloudBackend) createAndStartUpdate(
|
|||
// metadata changes.
|
||||
tags, err := backend.GetMergedStackTags(ctx, stack)
|
||||
if err != nil {
|
||||
return client.UpdateIdentifier{}, 0, "", errors.Wrap(err, "getting stack tags")
|
||||
return client.UpdateIdentifier{}, 0, "", fmt.Errorf("getting stack tags: %w", err)
|
||||
}
|
||||
version, token, err := b.client.StartUpdate(ctx, update, tags)
|
||||
if err != nil {
|
||||
|
@ -1070,7 +1074,7 @@ func (b *cloudBackend) runEngineAction(
|
|||
}
|
||||
completeErr := u.Complete(status)
|
||||
if completeErr != nil {
|
||||
res = result.Merge(res, result.FromError(errors.Wrap(completeErr, "failed to complete update")))
|
||||
res = result.Merge(res, result.FromError(fmt.Errorf("failed to complete update: %w", completeErr)))
|
||||
}
|
||||
|
||||
return changes, res
|
||||
|
@ -1087,7 +1091,7 @@ func (b *cloudBackend) CancelCurrentUpdate(ctx context.Context, stackRef backend
|
|||
}
|
||||
|
||||
if stack.ActiveUpdate == "" {
|
||||
return errors.Errorf("stack %v has never been updated", stackRef)
|
||||
return fmt.Errorf("stack %v has never been updated", stackRef)
|
||||
}
|
||||
|
||||
// Compute the update identifier and attempt to cancel the update.
|
||||
|
@ -1122,7 +1126,7 @@ func (b *cloudBackend) GetHistory(
|
|||
// Convert types from the apitype package into their internal counterparts.
|
||||
cfg, err := convertConfig(update.Config)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "converting configuration")
|
||||
return nil, fmt.Errorf("converting configuration: %w", err)
|
||||
}
|
||||
|
||||
beUpdates = append(beUpdates, backend.UpdateInfo{
|
||||
|
@ -1217,7 +1221,9 @@ func (b *cloudBackend) ExportDeploymentForVersion(
|
|||
// The first stack update version is 1, and monotonically increasing from there.
|
||||
versionNumber, err := strconv.Atoi(version)
|
||||
if err != nil || versionNumber <= 0 {
|
||||
return nil, errors.Errorf("%q is not a valid stack version. It should be a positive integer.", version)
|
||||
return nil, fmt.Errorf(
|
||||
"%q is not a valid stack version. It should be a positive integer",
|
||||
version)
|
||||
}
|
||||
|
||||
return b.exportDeployment(ctx, stack.Ref(), &versionNumber)
|
||||
|
@ -1257,9 +1263,9 @@ func (b *cloudBackend) ImportDeployment(ctx context.Context, stack backend.Stack
|
|||
ctx, backend.ActionLabel(apitype.StackImportUpdate, false /*dryRun*/), update,
|
||||
display.Options{Color: colors.Always})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "waiting for import")
|
||||
return fmt.Errorf("waiting for import: %w", err)
|
||||
} else if status != apitype.StatusSucceeded {
|
||||
return errors.Errorf("import unsuccessful: status %v", status)
|
||||
return fmt.Errorf("import unsuccessful: status %v", status)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -1448,7 +1454,7 @@ func IsValidAccessToken(ctx context.Context, cloudURL, accessToken string) (bool
|
|||
if errResp, ok := err.(*apitype.ErrorResponse); ok && errResp.Code == 401 {
|
||||
return false, "", nil
|
||||
}
|
||||
return false, "", errors.Wrapf(err, "getting user info from %v", cloudURL)
|
||||
return false, "", fmt.Errorf("getting user info from %v: %w", cloudURL, err)
|
||||
}
|
||||
|
||||
return true, username, nil
|
||||
|
@ -1480,7 +1486,7 @@ func (c httpstateBackendClient) GetStackOutputs(ctx context.Context, name string
|
|||
// When using the cloud backend, require that stack references are fully qualified so they
|
||||
// look like "<org>/<project>/<stack>"
|
||||
if strings.Count(name, "/") != 2 {
|
||||
return nil, errors.Errorf("a stack reference's name should be of the form " +
|
||||
return nil, fmt.Errorf("a stack reference's name should be of the form " +
|
||||
"'<organization>/<project>/<stack>'. See https://pulumi.io/help/stack-reference for more information.")
|
||||
}
|
||||
|
||||
|
|
|
@ -14,9 +14,10 @@
|
|||
package httpstate
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestValueOrDefaultURL(t *testing.T) {
|
||||
|
|
|
@ -19,6 +19,7 @@ import (
|
|||
"compress/gzip"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
|
@ -31,7 +32,6 @@ import (
|
|||
|
||||
"github.com/google/go-querystring/query"
|
||||
"github.com/opentracing/opentracing-go"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/v3/util/tracing"
|
||||
"github.com/pulumi/pulumi/pkg/v3/version"
|
||||
|
@ -134,14 +134,14 @@ func pulumiAPICall(ctx context.Context, d diag.Sink, cloudAPI, method, path stri
|
|||
writer := gzip.NewWriter(&buf)
|
||||
defer contract.IgnoreClose(writer)
|
||||
if _, err := writer.Write(body); err != nil {
|
||||
return "", nil, errors.Wrapf(err, "compressing payload")
|
||||
return "", nil, fmt.Errorf("compressing payload: %w", err)
|
||||
}
|
||||
|
||||
// gzip.Writer will not actually write anything unless it is flushed,
|
||||
// and it will not actually write the GZip footer unless it is closed. (Close also flushes)
|
||||
// Without this, the compressed bytes do not decompress properly e.g. in python.
|
||||
if err := writer.Close(); err != nil {
|
||||
return "", nil, errors.Wrapf(err, "closing compressed payload")
|
||||
return "", nil, fmt.Errorf("closing compressed payload: %w", err)
|
||||
}
|
||||
|
||||
logging.V(apiRequestDetailLogLevel).Infof("gzip compression ratio: %f, original size: %d bytes",
|
||||
|
@ -153,7 +153,7 @@ func pulumiAPICall(ctx context.Context, d diag.Sink, cloudAPI, method, path stri
|
|||
|
||||
req, err := http.NewRequest(method, url, bodyReader)
|
||||
if err != nil {
|
||||
return "", nil, errors.Wrapf(err, "creating new HTTP request")
|
||||
return "", nil, fmt.Errorf("creating new HTTP request: %w", err)
|
||||
}
|
||||
|
||||
requestSpan, requestContext := opentracing.StartSpanFromContext(ctx, getEndpointName(method, path),
|
||||
|
@ -210,7 +210,7 @@ func pulumiAPICall(ctx context.Context, d diag.Sink, cloudAPI, method, path stri
|
|||
}
|
||||
|
||||
if err != nil {
|
||||
return "", nil, errors.Wrapf(err, "performing HTTP request")
|
||||
return "", nil, fmt.Errorf("performing HTTP request: %w", err)
|
||||
}
|
||||
logging.V(apiRequestLogLevel).Infof("Pulumi API call response code (%s): %v", url, resp.Status)
|
||||
|
||||
|
@ -228,8 +228,7 @@ func pulumiAPICall(ctx context.Context, d diag.Sink, cloudAPI, method, path stri
|
|||
// type, and if not just return the raw response text.
|
||||
respBody, err := readBody(resp)
|
||||
if err != nil {
|
||||
return "", nil, errors.Wrapf(
|
||||
err, "API call failed (%s), could not read response", resp.Status)
|
||||
return "", nil, fmt.Errorf("API call failed (%s), could not read response: %w", resp.Status, err)
|
||||
}
|
||||
|
||||
// Provide a better error if using an authenticated call without having logged in first.
|
||||
|
@ -260,7 +259,7 @@ func pulumiRESTCall(ctx context.Context, diag diag.Sink, cloudAPI, method, path
|
|||
if queryObj != nil {
|
||||
queryValues, err := query.Values(queryObj)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "marshalling query object as JSON")
|
||||
return fmt.Errorf("marshalling query object as JSON: %w", err)
|
||||
}
|
||||
query := queryValues.Encode()
|
||||
if len(query) > 0 {
|
||||
|
@ -274,7 +273,7 @@ func pulumiRESTCall(ctx context.Context, diag diag.Sink, cloudAPI, method, path
|
|||
if reqObj != nil {
|
||||
reqBody, err = json.Marshal(reqObj)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "marshalling request object as JSON")
|
||||
return fmt.Errorf("marshalling request object as JSON: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -287,7 +286,7 @@ func pulumiRESTCall(ctx context.Context, diag diag.Sink, cloudAPI, method, path
|
|||
// Read API response
|
||||
respBody, err := readBody(resp)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "reading response from API")
|
||||
return fmt.Errorf("reading response from API: %w", err)
|
||||
}
|
||||
if logging.V(apiRequestDetailLogLevel) {
|
||||
logging.V(apiRequestDetailLogLevel).Infof("Pulumi API call response body (%s): %v", url, string(respBody))
|
||||
|
@ -303,7 +302,7 @@ func pulumiRESTCall(ctx context.Context, diag diag.Sink, cloudAPI, method, path
|
|||
} else {
|
||||
// Else, unmarshal as JSON.
|
||||
if err = json.Unmarshal(respBody, respObj); err != nil {
|
||||
return errors.Wrapf(err, "unmarshalling response object")
|
||||
return fmt.Errorf("unmarshalling response object: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -323,7 +322,7 @@ func readBody(resp *http.Response) ([]byte, error) {
|
|||
|
||||
if len(contentEncoding) > 1 {
|
||||
// We only know how to deal with gzip. We can't handle additional encodings layered on top of it.
|
||||
return nil, errors.Errorf("can't handle content encodings %v", contentEncoding)
|
||||
return nil, fmt.Errorf("can't handle content encodings %v", contentEncoding)
|
||||
}
|
||||
|
||||
switch contentEncoding[0] {
|
||||
|
@ -337,11 +336,11 @@ func readBody(resp *http.Response) ([]byte, error) {
|
|||
defer contract.IgnoreClose(reader)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "reading gzip-compressed body")
|
||||
return nil, fmt.Errorf("reading gzip-compressed body: %w", err)
|
||||
}
|
||||
|
||||
return ioutil.ReadAll(reader)
|
||||
default:
|
||||
return nil, errors.Errorf("unrecognized encoding %s", contentEncoding[0])
|
||||
return nil, fmt.Errorf("unrecognized encoding %s", contentEncoding[0])
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ package client
|
|||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
@ -28,7 +29,6 @@ import (
|
|||
"github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin"
|
||||
|
||||
"github.com/blang/semver"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/v3/engine"
|
||||
"github.com/pulumi/pulumi/pkg/v3/util/validation"
|
||||
|
@ -303,7 +303,7 @@ func (pc *Client) CreateStack(
|
|||
ctx context.Context, stackID StackIdentifier, tags map[apitype.StackTagName]string) (apitype.Stack, error) {
|
||||
// Validate names and tags.
|
||||
if err := validation.ValidateStackProperties(stackID.Stack, tags); err != nil {
|
||||
return apitype.Stack{}, errors.Wrap(err, "validating stack properties")
|
||||
return apitype.Stack{}, fmt.Errorf("validating stack properties: %w", err)
|
||||
}
|
||||
|
||||
stack := apitype.Stack{
|
||||
|
@ -521,7 +521,7 @@ func (pc *Client) StartUpdate(ctx context.Context, update UpdateIdentifier,
|
|||
|
||||
// Validate names and tags.
|
||||
if err := validation.ValidateStackProperties(update.StackIdentifier.Stack, tags); err != nil {
|
||||
return 0, "", errors.Wrap(err, "validating stack properties")
|
||||
return 0, "", fmt.Errorf("validating stack properties: %w", err)
|
||||
}
|
||||
|
||||
req := apitype.StartUpdateRequest{
|
||||
|
@ -543,7 +543,7 @@ func (pc *Client) ListPolicyGroups(ctx context.Context, orgName string, inContTo
|
|||
var resp apitype.ListPolicyGroupsResponse
|
||||
err := pc.restCall(ctx, "GET", listPolicyGroupsPath(orgName), nil, nil, &resp)
|
||||
if err != nil {
|
||||
return resp, nil, errors.Wrapf(err, "List Policy Groups failed")
|
||||
return resp, nil, fmt.Errorf("List Policy Groups failed: %w", err)
|
||||
}
|
||||
return resp, nil, nil
|
||||
}
|
||||
|
@ -555,7 +555,7 @@ func (pc *Client) ListPolicyPacks(ctx context.Context, orgName string, inContTok
|
|||
var resp apitype.ListPolicyPacksResponse
|
||||
err := pc.restCall(ctx, "GET", listPolicyPacksPath(orgName), nil, nil, &resp)
|
||||
if err != nil {
|
||||
return resp, nil, errors.Wrapf(err, "List Policy Packs failed")
|
||||
return resp, nil, fmt.Errorf("List Policy Packs failed: %w", err)
|
||||
}
|
||||
return resp, nil, nil
|
||||
}
|
||||
|
@ -609,7 +609,7 @@ func (pc *Client) PublishPolicyPack(ctx context.Context, orgName string,
|
|||
var resp apitype.CreatePolicyPackResponse
|
||||
err := pc.restCall(ctx, "POST", publishPolicyPackPath(orgName), nil, req, &resp)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "Publish policy pack failed")
|
||||
return "", fmt.Errorf("Publish policy pack failed: %w", err)
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -619,7 +619,7 @@ func (pc *Client) PublishPolicyPack(ctx context.Context, orgName string,
|
|||
|
||||
putReq, err := http.NewRequest(http.MethodPut, resp.UploadURI, dirArchive)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "Failed to upload compressed PolicyPack")
|
||||
return "", fmt.Errorf("Failed to upload compressed PolicyPack: %w", err)
|
||||
}
|
||||
|
||||
for k, v := range resp.RequiredHeaders {
|
||||
|
@ -628,7 +628,7 @@ func (pc *Client) PublishPolicyPack(ctx context.Context, orgName string,
|
|||
|
||||
_, err = http.DefaultClient.Do(putReq)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "Failed to upload compressed PolicyPack")
|
||||
return "", fmt.Errorf("Failed to upload compressed PolicyPack: %w", err)
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -645,7 +645,7 @@ func (pc *Client) PublishPolicyPack(ctx context.Context, orgName string,
|
|||
err = pc.restCall(ctx, "POST",
|
||||
publishPolicyPackPublishComplete(orgName, analyzerInfo.Name, version), nil, nil, nil)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "Request to signal completion of the publish operation failed")
|
||||
return "", fmt.Errorf("Request to signal completion of the publish operation failed: %w", err)
|
||||
}
|
||||
|
||||
return version, nil
|
||||
|
@ -708,7 +708,7 @@ func (pc *Client) ApplyPolicyPack(ctx context.Context, orgName, policyGroup,
|
|||
|
||||
err := pc.restCall(ctx, http.MethodPatch, updatePolicyGroupPath(orgName, policyGroup), nil, req, nil)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "Enable policy pack failed")
|
||||
return fmt.Errorf("Enable policy pack failed: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -720,7 +720,7 @@ func (pc *Client) GetPolicyPackSchema(ctx context.Context, orgName,
|
|||
err := pc.restCall(ctx, http.MethodGet,
|
||||
getPolicyPackConfigSchemaPath(orgName, policyPackName, versionTag), nil, nil, &resp)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Retrieving policy pack config schema failed")
|
||||
return nil, fmt.Errorf("Retrieving policy pack config schema failed: %w", err)
|
||||
}
|
||||
return &resp, nil
|
||||
}
|
||||
|
@ -744,7 +744,7 @@ func (pc *Client) DisablePolicyPack(ctx context.Context, orgName string, policyG
|
|||
|
||||
err := pc.restCall(ctx, http.MethodPatch, updatePolicyGroupPath(orgName, policyGroup), nil, req, nil)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "Request to disable policy pack failed")
|
||||
return fmt.Errorf("Request to disable policy pack failed: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -754,7 +754,7 @@ func (pc *Client) RemovePolicyPack(ctx context.Context, orgName string, policyPa
|
|||
path := deletePolicyPackPath(orgName, policyPackName)
|
||||
err := pc.restCall(ctx, http.MethodDelete, path, nil, nil, nil)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "Request to remove policy pack failed")
|
||||
return fmt.Errorf("Request to remove policy pack failed: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -767,7 +767,7 @@ func (pc *Client) RemovePolicyPackByVersion(ctx context.Context, orgName string,
|
|||
path := deletePolicyPackVersionPath(orgName, policyPackName, versionTag)
|
||||
err := pc.restCall(ctx, http.MethodDelete, path, nil, nil, nil)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "Request to remove policy pack failed")
|
||||
return fmt.Errorf("Request to remove policy pack failed: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -776,12 +776,12 @@ func (pc *Client) RemovePolicyPackByVersion(ctx context.Context, orgName string,
|
|||
func (pc *Client) DownloadPolicyPack(ctx context.Context, url string) (io.ReadCloser, error) {
|
||||
getS3Req, err := http.NewRequest(http.MethodGet, url, nil)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Failed to download compressed PolicyPack")
|
||||
return nil, fmt.Errorf("Failed to download compressed PolicyPack: %w", err)
|
||||
}
|
||||
|
||||
resp, err := http.DefaultClient.Do(getS3Req)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Failed to download compressed PolicyPack")
|
||||
return nil, fmt.Errorf("Failed to download compressed PolicyPack: %w", err)
|
||||
}
|
||||
|
||||
return resp.Body, nil
|
||||
|
|
|
@ -12,7 +12,6 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend"
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend/httpstate/client"
|
||||
"github.com/pulumi/pulumi/pkg/v3/engine"
|
||||
|
@ -183,8 +182,7 @@ func (pack *cloudPolicyPack) Publish(
|
|||
if strings.EqualFold(runtime, "nodejs") {
|
||||
packTarball, err = npm.Pack(op.PlugCtx.Pwd, os.Stderr)
|
||||
if err != nil {
|
||||
return result.FromError(
|
||||
errors.Wrap(err, "could not publish policies because of error running npm pack"))
|
||||
return result.FromError(fmt.Errorf("could not publish policies because of error running npm pack: %w", err))
|
||||
}
|
||||
} else {
|
||||
// npm pack puts all the files in a "package" subdirectory inside the .tgz it produces, so we'll do
|
||||
|
@ -192,8 +190,7 @@ func (pack *cloudPolicyPack) Publish(
|
|||
// package directory to determine the runtime of the policy pack.
|
||||
packTarball, err = archive.TGZ(op.PlugCtx.Pwd, "package", true /*useDefaultExcludes*/)
|
||||
if err != nil {
|
||||
return result.FromError(
|
||||
errors.Wrap(err, "could not publish policies because of error creating the .tgz"))
|
||||
return result.FromError(fmt.Errorf("could not publish policies because of error creating the .tgz: %w", err))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -253,18 +250,18 @@ func installRequiredPolicy(finalDir string, tgz io.ReadCloser) error {
|
|||
// If part of the directory tree is missing, ioutil.TempDir will return an error, so make sure
|
||||
// the path we're going to create the temporary folder in actually exists.
|
||||
if err := os.MkdirAll(filepath.Dir(finalDir), 0700); err != nil {
|
||||
return errors.Wrap(err, "creating plugin root")
|
||||
return fmt.Errorf("creating plugin root: %w", err)
|
||||
}
|
||||
|
||||
tempDir, err := ioutil.TempDir(filepath.Dir(finalDir), fmt.Sprintf("%s.tmp", filepath.Base(finalDir)))
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "creating plugin directory %s", tempDir)
|
||||
return fmt.Errorf("creating plugin directory %s: %w", tempDir, err)
|
||||
}
|
||||
|
||||
// The policy pack files are actually in a directory called `package`.
|
||||
tempPackageDir := filepath.Join(tempDir, packageDir)
|
||||
if err := os.MkdirAll(tempPackageDir, 0700); err != nil {
|
||||
return errors.Wrap(err, "creating plugin root")
|
||||
return fmt.Errorf("creating plugin root: %w", err)
|
||||
}
|
||||
|
||||
// If we early out of this function, try to remove the temp folder we created.
|
||||
|
@ -284,13 +281,13 @@ func installRequiredPolicy(finalDir string, tgz io.ReadCloser) error {
|
|||
// unable to rename the directory. That's OK, just ignore the error. The temp directory created
|
||||
// as part of the install will be cleaned up when we exit by the defer above.
|
||||
if err := os.Rename(tempPackageDir, finalDir); err != nil && !os.IsExist(err) {
|
||||
return errors.Wrap(err, "moving plugin")
|
||||
return fmt.Errorf("moving plugin: %w", err)
|
||||
}
|
||||
|
||||
projPath := filepath.Join(finalDir, "PulumiPolicy.yaml")
|
||||
proj, err := workspace.LoadPolicyPack(projPath)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to load policy project at %s", finalDir)
|
||||
return fmt.Errorf("failed to load policy project at %s: %w", finalDir, err)
|
||||
}
|
||||
|
||||
// TODO[pulumi/pulumi#1334]: move to the language plugins so we don't have to hard code here.
|
||||
|
@ -312,10 +309,9 @@ func installRequiredPolicy(finalDir string, tgz io.ReadCloser) error {
|
|||
|
||||
func completeNodeJSInstall(finalDir string) error {
|
||||
if bin, err := npm.Install(finalDir, false /*production*/, nil, os.Stderr); err != nil {
|
||||
return errors.Wrapf(
|
||||
err,
|
||||
"failed to install dependencies of policy pack; you may need to re-run `%s install` "+
|
||||
"in %q before this policy pack works", bin, finalDir)
|
||||
return fmt.Errorf("failed to install dependencies of policy pack; you may need to re-run `%s install` "+
|
||||
"in %q before this policy pack works"+": %w", bin, finalDir, err)
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -330,7 +326,7 @@ func completePythonInstall(finalDir, projPath string, proj *workspace.PolicyPack
|
|||
// Save project with venv info.
|
||||
proj.Runtime.SetOption("virtualenv", venvDir)
|
||||
if err := proj.Save(projPath); err != nil {
|
||||
return errors.Wrapf(err, "saving project at %s", projPath)
|
||||
return fmt.Errorf("saving project at %s: %w", projPath, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -16,8 +16,8 @@ package httpstate
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend"
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend/httpstate/client"
|
||||
"github.com/pulumi/pulumi/pkg/v3/resource/deploy"
|
||||
|
@ -45,7 +45,7 @@ func (persister *cloudSnapshotPersister) Save(snapshot *deploy.Snapshot) error {
|
|||
}
|
||||
deployment, err := stack.SerializeDeployment(snapshot, persister.sm, false /* showSecrets */)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "serializing deployment")
|
||||
return fmt.Errorf("serializing deployment: %w", err)
|
||||
}
|
||||
return persister.backend.client.PatchUpdateCheckpoint(persister.context, persister.update, deployment, token)
|
||||
}
|
||||
|
|
|
@ -24,7 +24,6 @@ import (
|
|||
"github.com/pulumi/pulumi/sdk/v3/go/common/util/contract"
|
||||
"github.com/pulumi/pulumi/sdk/v3/go/common/util/logging"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend"
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend/display"
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend/httpstate/client"
|
||||
|
@ -171,7 +170,7 @@ func (u *cloudUpdate) recordEngineEvents(startingSeqNumber int, events []engine.
|
|||
for idx, event := range events {
|
||||
apiEvent, convErr := display.ConvertEngineEvent(event)
|
||||
if convErr != nil {
|
||||
return errors.Wrap(convErr, "converting engine event")
|
||||
return fmt.Errorf("converting engine event: %w", convErr)
|
||||
}
|
||||
|
||||
// Each event within an update must have a unique sequence number. Any request to
|
||||
|
@ -294,7 +293,7 @@ func (b *cloudBackend) getTarget(ctx context.Context, stackRef backend.StackRefe
|
|||
return nil, fmt.Errorf("the stack '%s' is newer than what this version of the Pulumi CLI understands. "+
|
||||
"Please update your version of the Pulumi CLI", stackRef.Name())
|
||||
default:
|
||||
return nil, errors.Wrap(err, "could not deserialize deployment")
|
||||
return nil, fmt.Errorf("could not deserialize deployment: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,12 +15,12 @@
|
|||
package backend
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/v3/engine"
|
||||
"github.com/pulumi/pulumi/pkg/v3/resource/deploy"
|
||||
"github.com/pulumi/pulumi/pkg/v3/secrets"
|
||||
|
@ -603,14 +603,14 @@ func (sm *SnapshotManager) snap() *deploy.Snapshot {
|
|||
func (sm *SnapshotManager) saveSnapshot() error {
|
||||
snap := sm.snap()
|
||||
if err := snap.NormalizeURNReferences(); err != nil {
|
||||
return errors.Wrap(err, "failed to normalize URN references")
|
||||
return fmt.Errorf("failed to normalize URN references: %w", err)
|
||||
}
|
||||
if err := sm.persister.Save(snap); err != nil {
|
||||
return errors.Wrap(err, "failed to save snapshot")
|
||||
return fmt.Errorf("failed to save snapshot: %w", err)
|
||||
}
|
||||
if sm.doVerify {
|
||||
if err := snap.VerifyIntegrity(); err != nil {
|
||||
return errors.Wrapf(err, "failed to verify snapshot")
|
||||
return fmt.Errorf("failed to verify snapshot: %w", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
|
|
@ -19,8 +19,6 @@ import (
|
|||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/v3/engine"
|
||||
"github.com/pulumi/pulumi/pkg/v3/operations"
|
||||
"github.com/pulumi/pulumi/pkg/v3/resource/deploy"
|
||||
|
@ -178,7 +176,7 @@ func GetEnvironmentTagsForCurrentStack() (map[apitype.StackTagName]string, error
|
|||
if projPath != "" {
|
||||
proj, err := workspace.LoadProject(projPath)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error loading project %q", projPath)
|
||||
return nil, fmt.Errorf("error loading project %q: %w", projPath, err)
|
||||
}
|
||||
tags[apitype.ProjectNameTag] = proj.Name.String()
|
||||
tags[apitype.ProjectRuntimeTag] = proj.Runtime.Name()
|
||||
|
@ -219,7 +217,7 @@ func addGitMetadataToStackTags(tags map[apitype.StackTagName]string, projPath st
|
|||
tags[apitype.VCSRepositoryNameTag] = vcsInfo.Repo
|
||||
tags[apitype.VCSRepositoryKindTag] = vcsInfo.Kind
|
||||
} else {
|
||||
return errors.Wrapf(err, "detecting VCS info for stack tags for remote %v", remoteURL)
|
||||
return fmt.Errorf("detecting VCS info for stack tags for remote %v: %w", remoteURL, err)
|
||||
}
|
||||
// Set the old stack tags keys as GitHub so that the UI will continue to work,
|
||||
// regardless of whether the remote URL is a GitHub URL or not.
|
||||
|
|
|
@ -17,6 +17,7 @@ package main
|
|||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
|
@ -29,7 +30,6 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/blang/semver"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/shirou/gopsutil/host"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
|
@ -117,7 +117,7 @@ func getSummaryAbout(transitiveDependencies bool) summaryAbout {
|
|||
}
|
||||
var plugins []pluginAbout
|
||||
addError := func(err error, message string) {
|
||||
err = errors.Wrap(err, message)
|
||||
err = fmt.Errorf("%s: %w", message, err)
|
||||
result.ErrorMessages = append(result.ErrorMessages, err.Error())
|
||||
result.Errors = append(result.Errors, err)
|
||||
}
|
||||
|
@ -439,7 +439,7 @@ func getGoProgramDependencies(transitive bool) ([]programDependencieAbout, error
|
|||
cmd := exec.Command(ex, cmdArgs...)
|
||||
var out []byte
|
||||
if out, err = cmd.Output(); err != nil {
|
||||
return nil, errors.Wrap(err, "Failed to get modules")
|
||||
return nil, fmt.Errorf("Failed to get modules: %w", err)
|
||||
}
|
||||
|
||||
dec := json.NewDecoder(bytes.NewReader(out))
|
||||
|
@ -450,7 +450,7 @@ func getGoProgramDependencies(transitive bool) ([]programDependencieAbout, error
|
|||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
return nil, errors.Wrapf(err, "Failed to parse \"%s %s\" output", ex, strings.Join(cmdArgs, " "))
|
||||
return nil, fmt.Errorf("Failed to parse \"%s %s\" output: %w", ex, strings.Join(cmdArgs, " "), err)
|
||||
}
|
||||
parsed = append(parsed, m)
|
||||
|
||||
|
@ -525,7 +525,7 @@ func getPythonProgramDependencies(proj *workspace.Project, rootDir string,
|
|||
var result []programDependencieAbout
|
||||
err = json.Unmarshal([]byte(out), &result)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Failed to parse \"python %s\" result", strings.Join(cmdArgs, " "))
|
||||
return nil, fmt.Errorf("Failed to parse \"python %s\" result: %w", strings.Join(cmdArgs, " "), err)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
|
@ -553,7 +553,7 @@ func getDotNetProgramDependencies(proj *workspace.Project, transitive bool) ([]p
|
|||
}
|
||||
cmd := exec.Command(ex, cmdArgs...)
|
||||
if out, err = cmd.Output(); err != nil {
|
||||
return nil, errors.Wrapf(err, "Failed to call \"%s\"", ex)
|
||||
return nil, fmt.Errorf("Failed to call \"%s\": %w", ex, err)
|
||||
}
|
||||
lines := strings.Split(strings.ReplaceAll(string(out), "\r\n", "\n"), "\n")
|
||||
var packages []programDependencieAbout
|
||||
|
@ -577,7 +577,7 @@ func getDotNetProgramDependencies(proj *workspace.Project, transitive bool) ([]p
|
|||
// Transitive package => name version
|
||||
version = 1
|
||||
} else {
|
||||
return nil, errors.Errorf("Failed to parse \"%s\"", p)
|
||||
return nil, fmt.Errorf("Failed to parse \"%s\"", p)
|
||||
}
|
||||
packages = append(packages, programDependencieAbout{
|
||||
Name: nameRequiredVersion[0],
|
||||
|
@ -607,18 +607,18 @@ type yarnLockTree struct {
|
|||
func parseYarnLockFile(path string) ([]programDependencieAbout, error) {
|
||||
ex, err := executable.FindExecutable("yarn")
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Found %s but no yarn executable", path)
|
||||
return nil, fmt.Errorf("Found %s but no yarn executable: %w", path, err)
|
||||
}
|
||||
cmdArgs := []string{"list", "--json"}
|
||||
cmd := exec.Command(ex, cmdArgs...)
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Failed to run \"%s %s\"", ex, strings.Join(cmdArgs, " "))
|
||||
return nil, fmt.Errorf("Failed to run \"%s %s\": %w", ex, strings.Join(cmdArgs, " "), err)
|
||||
}
|
||||
|
||||
var lock yarnLock
|
||||
if err = json.Unmarshal(out, &lock); err != nil {
|
||||
return nil, errors.Wrapf(err, "Failed to parse\"%s %s\"", ex, strings.Join(cmdArgs, " "))
|
||||
return nil, fmt.Errorf("Failed to parse\"%s %s\": %w", ex, strings.Join(cmdArgs, " "), err)
|
||||
}
|
||||
leafs := lock.Data.Trees
|
||||
|
||||
|
@ -627,11 +627,11 @@ func parseYarnLockFile(path string) ([]programDependencieAbout, error) {
|
|||
// Has the form name@version
|
||||
splitName := func(index int, nameVersion string) (string, string, error) {
|
||||
if nameVersion == "" {
|
||||
return "", "", errors.Errorf("Expected \"name\" in dependency %d", index)
|
||||
return "", "", fmt.Errorf("Expected \"name\" in dependency %d", index)
|
||||
}
|
||||
split := strings.LastIndex(nameVersion, "@")
|
||||
if split == -1 {
|
||||
return "", "", errors.Errorf("Failed to parse name and version from %s", nameVersion)
|
||||
return "", "", fmt.Errorf("Failed to parse name and version from %s", nameVersion)
|
||||
}
|
||||
return nameVersion[:split], nameVersion[split+1:], nil
|
||||
}
|
||||
|
@ -667,17 +667,17 @@ type npmPackage struct {
|
|||
func parseNpmLockFile(path string) ([]programDependencieAbout, error) {
|
||||
ex, err := executable.FindExecutable("npm")
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Found %s but not npm", path)
|
||||
return nil, fmt.Errorf("Found %s but not npm: %w", path, err)
|
||||
}
|
||||
cmdArgs := []string{"ls", "--json", "--depth=0"}
|
||||
cmd := exec.Command(ex, cmdArgs...)
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, `Failed to run "%s %s"`, ex, strings.Join(cmdArgs, " "))
|
||||
return nil, fmt.Errorf(`Failed to run "%s %s": %w`, ex, strings.Join(cmdArgs, " "), err)
|
||||
}
|
||||
file := npmFile{}
|
||||
if err = json.Unmarshal(out, &file); err != nil {
|
||||
return nil, errors.Wrapf(err, `Failed to parse \"%s %s"`, ex, strings.Join(cmdArgs, " "))
|
||||
return nil, fmt.Errorf(`Failed to parse \"%s %s": %w`, ex, strings.Join(cmdArgs, " "), err)
|
||||
}
|
||||
result := make([]programDependencieAbout, len(file.Dependencies))
|
||||
var i int
|
||||
|
@ -704,7 +704,7 @@ func crossCheckPackageJSONFile(path string, file []byte,
|
|||
|
||||
var body packageJSON
|
||||
if err := json.Unmarshal(file, &body); err != nil {
|
||||
return nil, errors.Wrapf(err, "Could not parse %s", path)
|
||||
return nil, fmt.Errorf("Could not parse %s: %w", path, err)
|
||||
}
|
||||
dependencies := make(map[string]string)
|
||||
for k, v := range body.Dependencies {
|
||||
|
@ -761,19 +761,19 @@ func getNodeProgramDependencies(rootDir string, transitive bool) ([]programDepen
|
|||
return nil, err
|
||||
}
|
||||
} else if os.IsNotExist(err) {
|
||||
return nil, errors.Errorf("Could not find either %s or %s", yarnFile, npmFile)
|
||||
return nil, fmt.Errorf("Could not find either %s or %s", yarnFile, npmFile)
|
||||
} else {
|
||||
return nil, errors.Wrap(err, "Could not get node dependency data")
|
||||
return nil, fmt.Errorf("Could not get node dependency data: %w", err)
|
||||
}
|
||||
if !transitive {
|
||||
file, err := ioutil.ReadFile(packageFile)
|
||||
if os.IsNotExist(err) {
|
||||
return nil, errors.Errorf("Could not find %s. "+
|
||||
return nil, fmt.Errorf("Could not find %s. "+
|
||||
"Please include this in your report and run "+
|
||||
`pulumi about --transitive" to get a list of used packages`,
|
||||
packageFile)
|
||||
} else if err != nil {
|
||||
return nil, errors.Wrapf(err, "Could not read %s", packageFile)
|
||||
return nil, fmt.Errorf("Could not read %s: %w", packageFile, err)
|
||||
}
|
||||
return crossCheckPackageJSONFile(packageFile, file, result)
|
||||
}
|
||||
|
@ -793,7 +793,7 @@ func getProgramDependenciesAbout(proj *workspace.Project, root string,
|
|||
case langDotnet:
|
||||
return getDotNetProgramDependencies(proj, transitive)
|
||||
default:
|
||||
return nil, errors.Errorf("Unknown Language: %s", language)
|
||||
return nil, fmt.Errorf("Unknown Language: %s", language)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -872,11 +872,11 @@ func getProjectRuntimeAbout(proj *workspace.Project) (projectRuntimeAbout, error
|
|||
case langNodejs:
|
||||
ex, err = executable.FindExecutable("node")
|
||||
if err != nil {
|
||||
return projectRuntimeAbout{}, errors.Wrap(err, "Could not find node executable")
|
||||
return projectRuntimeAbout{}, fmt.Errorf("Could not find node executable: %w", err)
|
||||
}
|
||||
cmd := exec.Command(ex, "--version")
|
||||
if out, err = cmd.Output(); err != nil {
|
||||
return projectRuntimeAbout{}, errors.Wrap(err, "Failed to get node version")
|
||||
return projectRuntimeAbout{}, fmt.Errorf("Failed to get node version: %w", err)
|
||||
}
|
||||
version = string(out)
|
||||
case langPython:
|
||||
|
@ -889,31 +889,31 @@ func getProjectRuntimeAbout(proj *workspace.Project) (projectRuntimeAbout, error
|
|||
return projectRuntimeAbout{}, err
|
||||
}
|
||||
if out, err = cmd.Output(); err != nil {
|
||||
return projectRuntimeAbout{}, errors.Wrap(err, "Failed to get python version")
|
||||
return projectRuntimeAbout{}, fmt.Errorf("Failed to get python version: %w", err)
|
||||
}
|
||||
version = "v" + strings.TrimPrefix(string(out), "Python ")
|
||||
case langGo:
|
||||
ex, err = executable.FindExecutable("go")
|
||||
if err != nil {
|
||||
return projectRuntimeAbout{}, errors.Wrap(err, "Could not find python executable")
|
||||
return projectRuntimeAbout{}, fmt.Errorf("Could not find python executable: %w", err)
|
||||
}
|
||||
cmd := exec.Command(ex, "version")
|
||||
if out, err = cmd.Output(); err != nil {
|
||||
return projectRuntimeAbout{}, errors.Wrap(err, "Failed to get go version")
|
||||
return projectRuntimeAbout{}, fmt.Errorf("Failed to get go version: %w", err)
|
||||
}
|
||||
version = "v" + strings.TrimPrefix(string(out), "go version go")
|
||||
case langDotnet:
|
||||
ex, err = executable.FindExecutable("dotnet")
|
||||
if err != nil {
|
||||
return projectRuntimeAbout{}, errors.Wrap(err, "Could not find dotnet executable")
|
||||
return projectRuntimeAbout{}, fmt.Errorf("Could not find dotnet executable: %w", err)
|
||||
}
|
||||
cmd := exec.Command(ex, "--version")
|
||||
if out, err = cmd.Output(); err != nil {
|
||||
return projectRuntimeAbout{}, errors.Wrap(err, "Failed to get dotnet version")
|
||||
return projectRuntimeAbout{}, fmt.Errorf("Failed to get dotnet version: %w", err)
|
||||
}
|
||||
version = "v" + string(out)
|
||||
default:
|
||||
return projectRuntimeAbout{}, errors.Errorf("Unknown Language: %s", language)
|
||||
return projectRuntimeAbout{}, fmt.Errorf("Unknown Language: %s: %w", language, err)
|
||||
}
|
||||
version = strings.TrimSpace(version)
|
||||
return projectRuntimeAbout{
|
||||
|
|
|
@ -16,6 +16,7 @@ package main
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
@ -24,7 +25,7 @@ import (
|
|||
"strings"
|
||||
|
||||
zxcvbn "github.com/nbutton23/zxcvbn-go"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"golang.org/x/crypto/ssh/terminal"
|
||||
|
||||
|
@ -152,7 +153,7 @@ func copySingleConfigKey(configKey string, path bool, currentStack backend.Stack
|
|||
var decrypter config.Decrypter
|
||||
key, err := parseConfigKey(configKey)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "invalid configuration key")
|
||||
return fmt.Errorf("invalid configuration key: %w", err)
|
||||
}
|
||||
|
||||
v, ok, err := currentProjectStack.Config.Get(key, path)
|
||||
|
@ -163,7 +164,7 @@ func copySingleConfigKey(configKey string, path bool, currentStack backend.Stack
|
|||
if v.Secure() {
|
||||
var err error
|
||||
if decrypter, err = getStackDecrypter(currentStack); err != nil {
|
||||
return errors.Wrap(err, "could not create a decrypter")
|
||||
return fmt.Errorf("could not create a decrypter: %w", err)
|
||||
}
|
||||
} else {
|
||||
decrypter = config.NewPanicCrypter()
|
||||
|
@ -187,8 +188,7 @@ func copySingleConfigKey(configKey string, path bool, currentStack backend.Stack
|
|||
return saveProjectStack(destinationStack, destinationProjectStack)
|
||||
}
|
||||
|
||||
return errors.Errorf(
|
||||
"configuration key '%s' not found for stack '%s'", prettyKey(key), currentStack.Ref())
|
||||
return fmt.Errorf("configuration key '%s' not found for stack '%s'", prettyKey(key), currentStack.Ref())
|
||||
}
|
||||
|
||||
func copyEntireConfigMap(currentStack backend.Stack,
|
||||
|
@ -264,7 +264,7 @@ func newConfigGetCmd(stack *string) *cobra.Command {
|
|||
|
||||
key, err := parseConfigKey(args[0])
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "invalid configuration key")
|
||||
return fmt.Errorf("invalid configuration key: %w", err)
|
||||
}
|
||||
|
||||
return getConfig(s, key, path, jsonOut)
|
||||
|
@ -305,7 +305,7 @@ func newConfigRmCmd(stack *string) *cobra.Command {
|
|||
|
||||
key, err := parseConfigKey(args[0])
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "invalid configuration key")
|
||||
return fmt.Errorf("invalid configuration key: %w", err)
|
||||
}
|
||||
|
||||
ps, err := loadProjectStack(s)
|
||||
|
@ -359,7 +359,7 @@ func newConfigRmAllCmd(stack *string) *cobra.Command {
|
|||
for _, arg := range args {
|
||||
key, err := parseConfigKey(arg)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "invalid configuration key")
|
||||
return fmt.Errorf("invalid configuration key: %w", err)
|
||||
}
|
||||
|
||||
err = ps.Config.Remove(key, path)
|
||||
|
@ -424,13 +424,13 @@ func newConfigRefreshCmd(stack *string) *cobra.Command {
|
|||
_, err = os.Stat(backupFile)
|
||||
if os.IsNotExist(err) {
|
||||
if err = os.Rename(configPath, backupFile); err != nil {
|
||||
return errors.Wrap(err, "backing up existing configuration file")
|
||||
return fmt.Errorf("backing up existing configuration file: %w", err)
|
||||
}
|
||||
|
||||
fmt.Printf("backed up existing configuration file to %s\n", backupFile)
|
||||
break
|
||||
} else if err != nil {
|
||||
return errors.Wrap(err, "backing up existing configuration file")
|
||||
return fmt.Errorf("backing up existing configuration file: %w", err)
|
||||
}
|
||||
|
||||
backupFile = backupFile + ".bak"
|
||||
|
@ -481,7 +481,7 @@ func newConfigSetCmd(stack *string) *cobra.Command {
|
|||
|
||||
key, err := parseConfigKey(args[0])
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "invalid configuration key")
|
||||
return fmt.Errorf("invalid configuration key: %w", err)
|
||||
}
|
||||
|
||||
var value string
|
||||
|
@ -525,9 +525,8 @@ func newConfigSetCmd(stack *string) *cobra.Command {
|
|||
|
||||
// If we saved a plaintext configuration value, and --plaintext was not passed, warn the user.
|
||||
if !plaintext && looksLikeSecret(key, value) {
|
||||
return errors.Errorf(
|
||||
"config value for '%s' looks like a secret; "+
|
||||
"rerun with --secret to encrypt it, or --plaintext if you meant to store in plaintext",
|
||||
return fmt.Errorf("config value for '%s' looks like a secret; "+
|
||||
"rerun with --secret to encrypt it, or --plaintext if you meant to store in plaintext",
|
||||
key)
|
||||
}
|
||||
}
|
||||
|
@ -662,7 +661,7 @@ func parseKeyValuePair(pair string) (config.Key, string, error) {
|
|||
}
|
||||
key, err := parseConfigKey(splitArg[0])
|
||||
if err != nil {
|
||||
return config.Key{}, "", errors.Wrap(err, "invalid configuration key")
|
||||
return config.Key{}, "", fmt.Errorf("invalid configuration key: %w", err)
|
||||
}
|
||||
|
||||
value := splitArg[1]
|
||||
|
@ -769,7 +768,7 @@ func listConfig(stack backend.Stack, showSecrets bool, jsonOut bool) error {
|
|||
|
||||
decrypted, err := cfg[key].Value(decrypter)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not decrypt configuration value")
|
||||
return fmt.Errorf("could not decrypt configuration value: %w", err)
|
||||
}
|
||||
entry.Value = &decrypted
|
||||
|
||||
|
@ -800,7 +799,7 @@ func listConfig(stack backend.Stack, showSecrets bool, jsonOut bool) error {
|
|||
for _, key := range keys {
|
||||
decrypted, err := cfg[key].Value(decrypter)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not decrypt configuration value")
|
||||
return fmt.Errorf("could not decrypt configuration value: %w", err)
|
||||
}
|
||||
|
||||
rows = append(rows, cmdutil.TableRow{Columns: []string{prettyKey(key), decrypted}})
|
||||
|
@ -832,14 +831,14 @@ func getConfig(stack backend.Stack, key config.Key, path, jsonOut bool) error {
|
|||
if v.Secure() {
|
||||
var err error
|
||||
if d, err = getStackDecrypter(stack); err != nil {
|
||||
return errors.Wrap(err, "could not create a decrypter")
|
||||
return fmt.Errorf("could not create a decrypter: %w", err)
|
||||
}
|
||||
} else {
|
||||
d = config.NewPanicCrypter()
|
||||
}
|
||||
raw, err := v.Value(d)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not decrypt configuration value")
|
||||
return fmt.Errorf("could not decrypt configuration value: %w", err)
|
||||
}
|
||||
|
||||
if jsonOut {
|
||||
|
@ -868,8 +867,7 @@ func getConfig(stack backend.Stack, key config.Key, path, jsonOut bool) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
return errors.Errorf(
|
||||
"configuration key '%s' not found for stack '%s'", prettyKey(key), stack.Ref())
|
||||
return fmt.Errorf("configuration key '%s' not found for stack '%s'", prettyKey(key), stack.Ref())
|
||||
}
|
||||
|
||||
var (
|
||||
|
@ -911,7 +909,7 @@ func looksLikeSecret(k config.Key, v string) bool {
|
|||
func getStackConfiguration(stack backend.Stack, sm secrets.Manager) (backend.StackConfiguration, error) {
|
||||
workspaceStack, err := loadProjectStack(stack)
|
||||
if err != nil {
|
||||
return backend.StackConfiguration{}, errors.Wrap(err, "loading stack configuration")
|
||||
return backend.StackConfiguration{}, fmt.Errorf("loading stack configuration: %w", err)
|
||||
}
|
||||
|
||||
// If there are no secrets in the configuration, we should never use the decrypter, so it is safe to return
|
||||
|
@ -926,7 +924,7 @@ func getStackConfiguration(stack backend.Stack, sm secrets.Manager) (backend.Sta
|
|||
|
||||
crypter, err := sm.Decrypter()
|
||||
if err != nil {
|
||||
return backend.StackConfiguration{}, errors.Wrap(err, "getting configuration decrypter")
|
||||
return backend.StackConfiguration{}, fmt.Errorf("getting configuration decrypter: %w", err)
|
||||
}
|
||||
|
||||
return backend.StackConfiguration{
|
||||
|
|
|
@ -15,10 +15,10 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend"
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend/filestate"
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend/httpstate"
|
||||
|
@ -70,7 +70,7 @@ func getStackSecretsManager(s backend.Stack) (secrets.Manager, error) {
|
|||
return newServiceSecretsManager(s.(httpstate.Stack), s.Ref().Name(), stackConfigFile)
|
||||
}
|
||||
|
||||
return nil, errors.Errorf("unknown stack type %s", reflect.TypeOf(s))
|
||||
return nil, fmt.Errorf("unknown stack type %s", reflect.TypeOf(s))
|
||||
}()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -86,9 +86,8 @@ func validateSecretsProvider(typ string) error {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
return errors.Errorf(
|
||||
"unknown secrets provider type '%s' (supported values: %s)",
|
||||
return fmt.Errorf("unknown secrets provider type '%s' (supported values: %s)",
|
||||
kind,
|
||||
strings.Join(supportedKinds, ","),
|
||||
)
|
||||
strings.Join(supportedKinds, ","))
|
||||
|
||||
}
|
||||
|
|
|
@ -17,13 +17,13 @@ package main
|
|||
import (
|
||||
cryptorand "crypto/rand"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/pulumi/pulumi/pkg/v3/secrets"
|
||||
"github.com/pulumi/pulumi/pkg/v3/secrets/passphrase"
|
||||
"github.com/pulumi/pulumi/sdk/v3/go/common/diag"
|
||||
|
@ -42,11 +42,11 @@ func readPassphraseImpl(prompt string, useEnv bool) (phrase string, interactive
|
|||
if phraseFile, ok := os.LookupEnv("PULUMI_CONFIG_PASSPHRASE_FILE"); ok {
|
||||
phraseFilePath, err := filepath.Abs(phraseFile)
|
||||
if err != nil {
|
||||
return "", false, errors.Wrap(err, "unable to construct a path the PULUMI_CONFIG_PASSPHRASE_FILE")
|
||||
return "", false, fmt.Errorf("unable to construct a path the PULUMI_CONFIG_PASSPHRASE_FILE: %w", err)
|
||||
}
|
||||
phraseDetails, err := ioutil.ReadFile(phraseFilePath)
|
||||
if err != nil {
|
||||
return "", false, errors.Wrap(err, "unable to read PULUMI_CONFIG_PASSPHRASE_FILE")
|
||||
return "", false, fmt.Errorf("unable to read PULUMI_CONFIG_PASSPHRASE_FILE: %w", err)
|
||||
}
|
||||
return strings.TrimSpace(string(phraseDetails)), false, nil
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2016-2018, 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.
|
||||
|
@ -16,16 +16,18 @@ package main
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend"
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend/display"
|
||||
"github.com/pulumi/pulumi/pkg/v3/engine"
|
||||
"github.com/pulumi/pulumi/pkg/v3/resource/graph"
|
||||
"github.com/pulumi/pulumi/sdk/v3/go/common/resource"
|
||||
"github.com/pulumi/pulumi/sdk/v3/go/common/util/cmdutil"
|
||||
"github.com/pulumi/pulumi/sdk/v3/go/common/util/contract"
|
||||
"github.com/pulumi/pulumi/sdk/v3/go/common/util/result"
|
||||
)
|
||||
|
||||
|
@ -52,6 +54,7 @@ func newDestroyCmd() *cobra.Command {
|
|||
var yes bool
|
||||
var targets *[]string
|
||||
var targetDependents bool
|
||||
var excludeProtected bool
|
||||
|
||||
var cmd = &cobra.Command{
|
||||
Use: "destroy",
|
||||
|
@ -127,17 +130,17 @@ func newDestroyCmd() *cobra.Command {
|
|||
|
||||
m, err := getUpdateMetadata(message, root, execKind, execAgent)
|
||||
if err != nil {
|
||||
return result.FromError(errors.Wrap(err, "gathering environment metadata"))
|
||||
return result.FromError(fmt.Errorf("gathering environment metadata: %w", err))
|
||||
}
|
||||
|
||||
sm, err := getStackSecretsManager(s)
|
||||
if err != nil {
|
||||
return result.FromError(errors.Wrap(err, "getting secrets manager"))
|
||||
return result.FromError(fmt.Errorf("getting secrets manager: %w", err))
|
||||
}
|
||||
|
||||
cfg, err := getStackConfiguration(s, sm)
|
||||
if err != nil {
|
||||
return result.FromError(errors.Wrap(err, "getting stack configuration"))
|
||||
return result.FromError(fmt.Errorf("getting stack configuration: %w", err))
|
||||
}
|
||||
|
||||
targetUrns := []resource.URN{}
|
||||
|
@ -149,6 +152,29 @@ func newDestroyCmd() *cobra.Command {
|
|||
if err != nil {
|
||||
return result.FromError(err)
|
||||
}
|
||||
|
||||
if targets != nil && len(*targets) > 0 && excludeProtected {
|
||||
return result.FromError(errors.New("You cannot specify --target and --exclude-protected"))
|
||||
}
|
||||
|
||||
var protectedCount int
|
||||
if excludeProtected {
|
||||
contract.Assert(len(targetUrns) == 0)
|
||||
targetUrns, protectedCount, err = handleExcludeProtected(s)
|
||||
if err != nil {
|
||||
return result.FromError(err)
|
||||
} else if protectedCount > 0 && len(targetUrns) == 0 {
|
||||
if !jsonDisplay {
|
||||
fmt.Printf("There were no unprotected resources to destroy. There are still %d"+
|
||||
" protected resources associated with this stack.\n", protectedCount)
|
||||
}
|
||||
// We need to return now. Otherwise the update will conclude
|
||||
// we tried to destroy everything and error for trying to
|
||||
// destroy a protected resource.
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
opts.Engine = engine.UpdateOptions{
|
||||
Parallel: parallel,
|
||||
Debug: debug,
|
||||
|
@ -170,8 +196,10 @@ func newDestroyCmd() *cobra.Command {
|
|||
SecretsManager: sm,
|
||||
Scopes: cancellationScopes,
|
||||
})
|
||||
|
||||
if res == nil && len(*targets) == 0 && !jsonDisplay {
|
||||
if res == nil && protectedCount > 0 && !jsonDisplay {
|
||||
fmt.Printf("All unprotected resources were destroyed. There are still %d protected resources"+
|
||||
" associated with this stack.\n", protectedCount)
|
||||
} else if res == nil && len(*targets) == 0 && !jsonDisplay {
|
||||
fmt.Printf("The resources in the stack have been deleted, but the history and configuration "+
|
||||
"associated with the stack are still maintained. \nIf you want to remove the stack "+
|
||||
"completely, run 'pulumi stack rm %s'.\n", s.Ref())
|
||||
|
@ -202,6 +230,8 @@ func newDestroyCmd() *cobra.Command {
|
|||
cmd.PersistentFlags().BoolVar(
|
||||
&targetDependents, "target-dependents", false,
|
||||
"Allows destroying of dependent targets discovered but not specified in --target list")
|
||||
cmd.PersistentFlags().BoolVar(&excludeProtected, "exclude-protected", false, "Do not destroy protected resources."+
|
||||
" Destroy all other resources.")
|
||||
|
||||
// Flags for engine.UpdateOptions.
|
||||
cmd.PersistentFlags().BoolVar(
|
||||
|
@ -257,3 +287,52 @@ func newDestroyCmd() *cobra.Command {
|
|||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// seperateProtected returns a list or unprotected and protected resources respectively. This allows
|
||||
// us to safely destroy all resources in the unprotected list without invalidating any resource in
|
||||
// the protected list. Protection is contravarient: A < B where A: Protected => B: Protected, A < B
|
||||
// where B: Protected !=> A: Protected.
|
||||
//
|
||||
// A
|
||||
// B: Parent = A
|
||||
// C: Parent = A, Protect = True
|
||||
// D: Parent = C
|
||||
//
|
||||
// -->
|
||||
//
|
||||
// Unprotected: B, D
|
||||
// Protected: A, C
|
||||
//
|
||||
// We rely on the fact that `resources` is topologically sorted with respect to its dependencies.
|
||||
// This function understands that providers live outside this topological sort.
|
||||
func seperateProtected(resources []*resource.State) (
|
||||
/*unprotected*/ []*resource.State /*protected*/, []*resource.State) {
|
||||
dg := graph.NewDependencyGraph(resources)
|
||||
transitiveProtected := graph.ResourceSet{}
|
||||
for _, r := range resources {
|
||||
if r.Protect {
|
||||
rProtected := dg.TransitiveDependenciesOf(r)
|
||||
rProtected[r] = true
|
||||
transitiveProtected.UnionWith(rProtected)
|
||||
}
|
||||
}
|
||||
allResources := graph.NewResourceSetFromArray(resources)
|
||||
return allResources.SetMinus(transitiveProtected).ToArray(), transitiveProtected.ToArray()
|
||||
}
|
||||
|
||||
// Returns the number of protected resources that remain. Appends all unprotected resources to `targetUrns`.
|
||||
func handleExcludeProtected(s backend.Stack) ([]resource.URN, int, error) {
|
||||
// Get snapshot
|
||||
snapshot, err := s.Snapshot(commandContext())
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
} else if snapshot == nil {
|
||||
return nil, 0, errors.New("Failed to find the stack snapshot. Are you in a stack?")
|
||||
}
|
||||
unprotected, protected := seperateProtected(snapshot.Resources)
|
||||
targetUrns := []resource.URN{}
|
||||
for _, r := range unprotected {
|
||||
targetUrns = append(targetUrns, r.URN)
|
||||
}
|
||||
return targetUrns, len(protected), nil
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import (
|
|||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
@ -25,7 +26,7 @@ import (
|
|||
|
||||
"github.com/blang/semver"
|
||||
"github.com/hashicorp/hcl/v2"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend"
|
||||
|
@ -187,7 +188,7 @@ func getCurrentDeploymentForStack(s backend.Stack) (*deploy.Snapshot, error) {
|
|||
return nil, fmt.Errorf("the stack '%s' is newer than what this version of the Pulumi CLI understands. "+
|
||||
"Please update your version of the Pulumi CLI", s.Ref().Name())
|
||||
}
|
||||
return nil, errors.Wrap(err, "could not deserialize deployment")
|
||||
return nil, fmt.Errorf("could not deserialize deployment: %w", err)
|
||||
}
|
||||
return snap, err
|
||||
}
|
||||
|
@ -351,7 +352,7 @@ func newImportCmd() *cobra.Command {
|
|||
}
|
||||
f, err := readImportFile(importFilePath)
|
||||
if err != nil {
|
||||
return result.FromError(errors.Wrap(err, "could not read import file"))
|
||||
return result.FromError(fmt.Errorf("could not read import file: %w", err))
|
||||
}
|
||||
importFile = f
|
||||
} else {
|
||||
|
@ -454,17 +455,17 @@ func newImportCmd() *cobra.Command {
|
|||
|
||||
m, err := getUpdateMetadata(message, root, execKind, execAgent)
|
||||
if err != nil {
|
||||
return result.FromError(errors.Wrap(err, "gathering environment metadata"))
|
||||
return result.FromError(fmt.Errorf("gathering environment metadata: %w", err))
|
||||
}
|
||||
|
||||
sm, err := getStackSecretsManager(s)
|
||||
if err != nil {
|
||||
return result.FromError(errors.Wrap(err, "getting secrets manager"))
|
||||
return result.FromError(fmt.Errorf("getting secrets manager: %w", err))
|
||||
}
|
||||
|
||||
cfg, err := getStackConfiguration(s, sm)
|
||||
if err != nil {
|
||||
return result.FromError(errors.Wrap(err, "getting stack configuration"))
|
||||
return result.FromError(fmt.Errorf("getting stack configuration: %w", err))
|
||||
}
|
||||
|
||||
opts.Engine = engine.UpdateOptions{
|
||||
|
@ -493,7 +494,7 @@ func newImportCmd() *cobra.Command {
|
|||
protectResources)
|
||||
if err != nil {
|
||||
if _, ok := err.(*importer.DiagnosticsError); ok {
|
||||
err = errors.Wrap(err, "internal error")
|
||||
err = fmt.Errorf("internal error: %w", err)
|
||||
}
|
||||
return result.FromError(err)
|
||||
}
|
||||
|
|
|
@ -15,12 +15,12 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend"
|
||||
|
@ -33,6 +33,7 @@ import (
|
|||
|
||||
func newLoginCmd() *cobra.Command {
|
||||
var cloudURL string
|
||||
var defaultOrg string
|
||||
var localMode bool
|
||||
|
||||
cmd := &cobra.Command{
|
||||
|
@ -55,6 +56,9 @@ func newLoginCmd() *cobra.Command {
|
|||
"to log in to a self-hosted Pulumi service running at the api.pulumi.acmecorp.com domain.\n" +
|
||||
"\n" +
|
||||
"For `https://` URLs, the CLI will speak REST to a service that manages state and concurrency control.\n" +
|
||||
"You can specify a default org to use when logging into the Pulumi service backend or a " +
|
||||
"self-hosted Pulumi service.\n" +
|
||||
"\n" +
|
||||
"[PREVIEW] If you prefer to operate Pulumi independently of a service, and entirely local to your computer,\n" +
|
||||
"pass `file://<path>`, where `<path>` will be where state checkpoints will be stored. For instance,\n" +
|
||||
"\n" +
|
||||
|
@ -114,7 +118,7 @@ func newLoginCmd() *cobra.Command {
|
|||
var err error
|
||||
cloudURL, err = workspace.GetCurrentCloudURL()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not determine current cloud")
|
||||
return fmt.Errorf("could not determine current cloud: %w", err)
|
||||
}
|
||||
} else {
|
||||
// Ensure we have the correct cloudurl type before logging in
|
||||
|
@ -127,11 +131,24 @@ func newLoginCmd() *cobra.Command {
|
|||
var err error
|
||||
if filestate.IsFileStateBackendURL(cloudURL) {
|
||||
be, err = filestate.Login(cmdutil.Diag(), cloudURL)
|
||||
if defaultOrg != "" {
|
||||
return fmt.Errorf("unable to set default org for this type of backend")
|
||||
}
|
||||
} else {
|
||||
be, err = httpstate.Login(commandContext(), cmdutil.Diag(), cloudURL, displayOptions)
|
||||
// if the user has specified a default org to associate with the backend
|
||||
if defaultOrg != "" {
|
||||
cloudURL, err := workspace.GetCurrentCloudURL()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := httpstate.SetDefaultOrg(cloudURL, defaultOrg); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "problem logging in")
|
||||
return fmt.Errorf("problem logging in: %w", err)
|
||||
}
|
||||
|
||||
if currentUser, err := be.CurrentUser(); err == nil {
|
||||
|
@ -145,6 +162,8 @@ func newLoginCmd() *cobra.Command {
|
|||
}
|
||||
|
||||
cmd.PersistentFlags().StringVarP(&cloudURL, "cloud-url", "c", "", "A cloud URL to log in to")
|
||||
cmd.PersistentFlags().StringVar(&defaultOrg, "default-org", "", "A default org to associate with the login. "+
|
||||
"Please note, currently, only the managed and self-hosted backends support organizations")
|
||||
cmd.PersistentFlags().BoolVarP(&localMode, "local", "l", false, "Use Pulumi in local-only mode")
|
||||
|
||||
return cmd
|
||||
|
@ -158,9 +177,8 @@ func validateCloudBackendType(typ string) error {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
return errors.Errorf(
|
||||
"unknown backend cloudUrl format '%s' (supported Url formats are: "+
|
||||
"azblob://, gs://, s3://, file://, https:// and http://)",
|
||||
kind,
|
||||
)
|
||||
return fmt.Errorf("unknown backend cloudUrl format '%s' (supported Url formats are: "+
|
||||
"azblob://, gs://, s3://, file://, https:// and http://)",
|
||||
kind)
|
||||
|
||||
}
|
||||
|
|
|
@ -15,7 +15,9 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend"
|
||||
|
@ -65,7 +67,7 @@ func newLogoutCmd() *cobra.Command {
|
|||
var err error
|
||||
cloudURL, err = workspace.GetCurrentCloudURL()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not determine current cloud")
|
||||
return fmt.Errorf("could not determine current cloud: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ import (
|
|||
"time"
|
||||
|
||||
mobytime "github.com/docker/docker/api/types/time"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend/display"
|
||||
|
@ -63,17 +63,17 @@ func newLogsCmd() *cobra.Command {
|
|||
|
||||
sm, err := getStackSecretsManager(s)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "getting secrets manager")
|
||||
return fmt.Errorf("getting secrets manager: %w", err)
|
||||
}
|
||||
|
||||
cfg, err := getStackConfiguration(s, sm)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "getting stack configuration")
|
||||
return fmt.Errorf("getting stack configuration: %w", err)
|
||||
}
|
||||
|
||||
startTime, err := parseSince(since, time.Now())
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to parse argument to '--since' as duration or timestamp")
|
||||
return fmt.Errorf("failed to parse argument to '--since' as duration or timestamp: %w", err)
|
||||
}
|
||||
var resourceFilter *operations.ResourceFilter
|
||||
if resource != "" {
|
||||
|
@ -102,7 +102,7 @@ func newLogsCmd() *cobra.Command {
|
|||
ResourceFilter: resourceFilter,
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to get logs")
|
||||
return fmt.Errorf("failed to get logs: %w", err)
|
||||
}
|
||||
|
||||
// When we are emitting a fixed number of log entries, and outputing JSON, wrap them in an array.
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
@ -26,7 +27,6 @@ import (
|
|||
"strings"
|
||||
"unicode"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
survey "gopkg.in/AlecAivazis/survey.v1"
|
||||
surveycore "gopkg.in/AlecAivazis/survey.v1/core"
|
||||
|
@ -83,7 +83,7 @@ func runNew(args newArgs) error {
|
|||
|
||||
// Validate name (if specified) before further prompts/operations.
|
||||
if args.name != "" && workspace.ValidateProjectName(args.name) != nil {
|
||||
return errors.Errorf("'%s' is not a valid project name. %s.", args.name, workspace.ValidateProjectName(args.name))
|
||||
return fmt.Errorf("'%s' is not a valid project name. %s", args.name, workspace.ValidateProjectName(args.name))
|
||||
}
|
||||
|
||||
// Validate secrets provider type
|
||||
|
@ -94,7 +94,7 @@ func runNew(args newArgs) error {
|
|||
// Get the current working directory.
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "getting the working directory")
|
||||
return fmt.Errorf("getting the working directory: %w", err)
|
||||
}
|
||||
originalCwd := cwd
|
||||
|
||||
|
@ -159,7 +159,7 @@ func runNew(args newArgs) error {
|
|||
if !args.force {
|
||||
if err = workspace.CopyTemplateFilesDryRun(template.Dir, cwd, args.name); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return errors.Wrapf(err, "template '%s' not found", args.templateNameOrURL)
|
||||
return fmt.Errorf("template '%s' not found: %w", args.templateNameOrURL, err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
@ -172,7 +172,11 @@ func runNew(args newArgs) error {
|
|||
// created via the web app.
|
||||
var s backend.Stack
|
||||
if args.stack != "" && strings.Count(args.stack, "/") == 2 {
|
||||
existingStack, existingName, existingDesc, err := getStack(args.stack, opts)
|
||||
stackName, err := buildStackName(args.stack)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
existingStack, existingName, existingDesc, err := getStack(stackName, opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -228,7 +232,7 @@ func runNew(args newArgs) error {
|
|||
// Actually copy the files.
|
||||
if err = workspace.CopyTemplateFiles(template.Dir, cwd, args.force, args.name, args.description); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return errors.Wrapf(err, "template '%s' not found", args.templateNameOrURL)
|
||||
return fmt.Errorf("template '%s' not found: %w", args.templateNameOrURL, err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
@ -245,7 +249,7 @@ func runNew(args newArgs) error {
|
|||
proj.Description = &args.description
|
||||
proj.Template = nil
|
||||
if err = workspace.SaveProject(proj); err != nil {
|
||||
return errors.Wrap(err, "saving project")
|
||||
return fmt.Errorf("saving project: %w", err)
|
||||
}
|
||||
|
||||
// Create the stack, if needed.
|
||||
|
@ -299,19 +303,19 @@ func runNew(args newArgs) error {
|
|||
func useSpecifiedDir(dir string) (string, error) {
|
||||
// Ensure the directory exists.
|
||||
if err := os.MkdirAll(dir, os.ModePerm); err != nil {
|
||||
return "", errors.Wrap(err, "creating the directory")
|
||||
return "", fmt.Errorf("creating the directory: %w", err)
|
||||
}
|
||||
|
||||
// Change the working directory to the specified directory.
|
||||
if err := os.Chdir(dir); err != nil {
|
||||
return "", errors.Wrap(err, "changing the working directory")
|
||||
return "", fmt.Errorf("changing the working directory: %w", err)
|
||||
}
|
||||
|
||||
// Get the new working directory.
|
||||
var cwd string
|
||||
var err error
|
||||
if cwd, err = os.Getwd(); err != nil {
|
||||
return "", errors.Wrap(err, "getting the working directory")
|
||||
return "", fmt.Errorf("getting the working directory: %w", err)
|
||||
}
|
||||
return cwd, nil
|
||||
}
|
||||
|
@ -445,7 +449,7 @@ func errorIfNotEmptyDirectory(path string) error {
|
|||
}
|
||||
|
||||
if len(infos) > 0 {
|
||||
return errors.Errorf("%s is not empty; "+
|
||||
return fmt.Errorf("%s is not empty; "+
|
||||
"rerun in an empty directory, pass the path to an empty directory to --dir, or use --force", path)
|
||||
}
|
||||
|
||||
|
@ -518,7 +522,11 @@ func promptAndCreateStack(prompt promptForValueFunc,
|
|||
}
|
||||
|
||||
if stack != "" {
|
||||
s, err := stackInit(b, stack, setCurrent, secretsProvider)
|
||||
stackName, err := buildStackName(stack)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s, err := stackInit(b, stackName, setCurrent, secretsProvider)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -536,7 +544,14 @@ func promptAndCreateStack(prompt promptForValueFunc,
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s, err := stackInit(b, stackName, setCurrent, secretsProvider)
|
||||
formattedStackName, err := buildStackName(stackName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s, err := stackInit(b, formattedStackName, setCurrent, secretsProvider)
|
||||
if err != nil {
|
||||
if !yes {
|
||||
// Let the user know about the error and loop around to try again.
|
||||
|
@ -577,8 +592,9 @@ func installDependencies(proj *workspace.Project, root string) error {
|
|||
// TODO[pulumi/pulumi#1334]: move to the language plugins so we don't have to hard code here.
|
||||
if strings.EqualFold(proj.Runtime.Name(), "nodejs") {
|
||||
if bin, err := nodeInstallDependencies(); err != nil {
|
||||
return errors.Wrapf(err, "%s install failed; rerun manually to try again, "+
|
||||
"then run 'pulumi up' to perform an initial deployment", bin)
|
||||
return fmt.Errorf("%s install failed; rerun manually to try again, "+
|
||||
"then run 'pulumi up' to perform an initial deployment"+": %w", bin, err)
|
||||
|
||||
}
|
||||
} else if strings.EqualFold(proj.Runtime.Name(), "python") {
|
||||
return pythonInstallDependencies(proj, root)
|
||||
|
@ -620,7 +636,7 @@ func pythonInstallDependencies(proj *workspace.Project, root string) error {
|
|||
// Save project with venv info.
|
||||
proj.Runtime.SetOption("virtualenv", venvDir)
|
||||
if err := workspace.SaveProject(proj); err != nil {
|
||||
return errors.Wrap(err, "saving project")
|
||||
return fmt.Errorf("saving project: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -671,8 +687,9 @@ func goInstallDependencies() error {
|
|||
cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return errors.Wrapf(err, "`go mod tidy` failed to install dependencies; rerun manually to try again, "+
|
||||
"then run 'pulumi up' to perform an initial deployment")
|
||||
return fmt.Errorf("`go mod tidy` failed to install dependencies; rerun manually to try again, "+
|
||||
"then run 'pulumi up' to perform an initial deployment"+": %w", err)
|
||||
|
||||
}
|
||||
|
||||
fmt.Println("Finished installing dependencies")
|
||||
|
|
|
@ -16,13 +16,14 @@ package main
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/stretchr/testify/require"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend"
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend/display"
|
||||
"github.com/pulumi/pulumi/sdk/v3/go/common/resource/config"
|
||||
|
|
153
pkg/cmd/pulumi/org.go
Normal file
153
pkg/cmd/pulumi/org.go
Normal file
|
@ -0,0 +1,153 @@
|
|||
// 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 main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend/display"
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend/httpstate"
|
||||
"github.com/pulumi/pulumi/sdk/v3/go/common/util/cmdutil"
|
||||
"github.com/pulumi/pulumi/sdk/v3/go/common/workspace"
|
||||
)
|
||||
|
||||
func newOrgCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "org",
|
||||
Short: "Manage Organization configuration",
|
||||
Long: "Manage Organization configuration.\n" +
|
||||
"\n" +
|
||||
"Use this command to manage organization configuration, " +
|
||||
"e.g. setting the default organization for a backend",
|
||||
Args: cmdutil.NoArgs,
|
||||
Run: cmdutil.RunFunc(func(cmd *cobra.Command, args []string) error {
|
||||
cloudURL, err := workspace.GetCurrentCloudURL()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defaultOrg, err := workspace.GetBackendConfigDefaultOrg()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("Current Backend: %s\n", cloudURL)
|
||||
if defaultOrg != "" {
|
||||
fmt.Printf("Default Org: %s", defaultOrg)
|
||||
} else {
|
||||
fmt.Println("No Default Org Specified")
|
||||
}
|
||||
|
||||
return nil
|
||||
}),
|
||||
}
|
||||
|
||||
cmd.AddCommand(newOrgSetDefaultCmd())
|
||||
cmd.AddCommand(newOrgGetDefaultCmd())
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func newOrgSetDefaultCmd() *cobra.Command {
|
||||
var orgName string
|
||||
|
||||
var cmd = &cobra.Command{
|
||||
Use: "set-default [NAME]",
|
||||
Args: cmdutil.ExactArgs(1),
|
||||
Short: "Set the default organization for the current backend",
|
||||
Long: "Set the default organization for the current backend.\n" +
|
||||
"\n" +
|
||||
"This command is used to set the default organization in which to create \n" +
|
||||
"projects and stacks for the current backend.\n" +
|
||||
"\n" +
|
||||
"Currently, only the managed and self-hosted backends support organizations. " +
|
||||
"If you try and set a default organization for a backend that does not \n" +
|
||||
"support create organizations, then an error will be returned by the CLI",
|
||||
Run: cmdutil.RunFunc(func(cmd *cobra.Command, args []string) error {
|
||||
displayOpts := display.Options{
|
||||
Color: cmdutil.GetGlobalColorization(),
|
||||
}
|
||||
|
||||
orgName = args[0]
|
||||
|
||||
currentBe, err := currentBackend(displayOpts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !currentBe.SupportsOrganizations() {
|
||||
return fmt.Errorf("unable to set a default organization for backend type: %s",
|
||||
currentBe.Name())
|
||||
}
|
||||
|
||||
if _, ok := currentBe.(httpstate.Backend); ok {
|
||||
cloudURL, err := workspace.GetCurrentCloudURL()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := httpstate.SetDefaultOrg(cloudURL, orgName); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}),
|
||||
}
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func newOrgGetDefaultCmd() *cobra.Command {
|
||||
var cmd = &cobra.Command{
|
||||
Use: "get-default",
|
||||
Short: "Get the default org for the current backend",
|
||||
Long: "Get the default org for the current backend.\n" +
|
||||
"\n" +
|
||||
"This command is used to get the default organization for which and stacks are created in " +
|
||||
"the current backend.\n" +
|
||||
"\n" +
|
||||
"Currently, only the managed and self-hosted backends support organizations.",
|
||||
Run: cmdutil.RunFunc(func(cmd *cobra.Command, args []string) error {
|
||||
displayOpts := display.Options{
|
||||
Color: cmdutil.GetGlobalColorization(),
|
||||
}
|
||||
|
||||
currentBe, err := currentBackend(displayOpts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !currentBe.SupportsOrganizations() {
|
||||
return fmt.Errorf("backends of this type %q do not support organizations",
|
||||
currentBe.Name())
|
||||
}
|
||||
|
||||
defaultOrg, err := workspace.GetBackendConfigDefaultOrg()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if defaultOrg != "" {
|
||||
fmt.Println(defaultOrg)
|
||||
} else {
|
||||
fmt.Println("No Default Org Specified")
|
||||
}
|
||||
|
||||
return nil
|
||||
}),
|
||||
}
|
||||
|
||||
return cmd
|
||||
}
|
|
@ -15,6 +15,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
@ -22,7 +23,7 @@ import (
|
|||
"github.com/pulumi/pulumi/sdk/v3/go/common/util/logging"
|
||||
|
||||
"github.com/blang/semver"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend/display"
|
||||
|
@ -59,7 +60,7 @@ func newPluginInstallCmd() *cobra.Command {
|
|||
var installs []workspace.PluginInfo
|
||||
if len(args) > 0 {
|
||||
if !workspace.IsPluginKind(args[0]) {
|
||||
return errors.Errorf("unrecognized plugin kind: %s", args[0])
|
||||
return fmt.Errorf("unrecognized plugin kind: %s", args[0])
|
||||
} else if len(args) < 2 {
|
||||
return errors.New("missing plugin name argument")
|
||||
} else if len(args) < 3 {
|
||||
|
@ -67,7 +68,7 @@ func newPluginInstallCmd() *cobra.Command {
|
|||
}
|
||||
version, err := semver.ParseTolerant(args[2])
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "invalid plugin semver")
|
||||
return fmt.Errorf("invalid plugin semver: %w", err)
|
||||
}
|
||||
installs = append(installs, workspace.PluginInfo{
|
||||
Kind: workspace.PluginKind(args[0]),
|
||||
|
@ -124,19 +125,19 @@ func newPluginInstallCmd() *cobra.Command {
|
|||
if file == "" {
|
||||
var size int64
|
||||
if tarball, size, err = install.Download(); err != nil {
|
||||
return errors.Wrapf(err, "%s downloading from %s", label, install.ServerURL)
|
||||
return fmt.Errorf("%s downloading from %s: %w", label, install.ServerURL, err)
|
||||
}
|
||||
tarball = workspace.ReadCloserProgressBar(tarball, size, "Downloading plugin", displayOpts.Color)
|
||||
} else {
|
||||
source = file
|
||||
logging.V(1).Infof("%s opening tarball from %s", label, file)
|
||||
if tarball, err = os.Open(file); err != nil {
|
||||
return errors.Wrapf(err, "opening file %s", source)
|
||||
return fmt.Errorf("opening file %s: %w", source, err)
|
||||
}
|
||||
}
|
||||
logging.V(1).Infof("%s installing tarball ...", label)
|
||||
if err = install.Install(tarball); err != nil {
|
||||
return errors.Wrapf(err, "installing %s from %s", label, source)
|
||||
return fmt.Errorf("installing %s from %s: %w", label, source, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ import (
|
|||
"sort"
|
||||
|
||||
"github.com/dustin/go-humanize"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/pulumi/pulumi/sdk/v3/go/common/util/cmdutil"
|
||||
|
@ -39,11 +39,11 @@ func newPluginLsCmd() *cobra.Command {
|
|||
var err error
|
||||
if projectOnly {
|
||||
if plugins, err = getProjectPlugins(); err != nil {
|
||||
return errors.Wrapf(err, "loading project plugins")
|
||||
return fmt.Errorf("loading project plugins: %w", err)
|
||||
}
|
||||
} else {
|
||||
if plugins, err = workspace.GetPluginsWithMetadata(); err != nil {
|
||||
return errors.Wrapf(err, "loading plugins")
|
||||
return fmt.Errorf("loading plugins: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,11 +16,12 @@ package main
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pulumi/pulumi/sdk/v3/go/common/diag"
|
||||
|
||||
"github.com/blang/semver"
|
||||
"github.com/hashicorp/go-multierror"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend/display"
|
||||
|
@ -58,11 +59,11 @@ func newPluginRmCmd() *cobra.Command {
|
|||
var version *semver.Range
|
||||
if len(args) > 0 {
|
||||
if !workspace.IsPluginKind(args[0]) {
|
||||
return errors.Errorf("unrecognized plugin kind: %s", kind)
|
||||
return fmt.Errorf("unrecognized plugin kind: %s", kind)
|
||||
}
|
||||
kind = workspace.PluginKind(args[0])
|
||||
} else if !all {
|
||||
return errors.Errorf("please pass --all if you'd like to remove all plugins")
|
||||
return fmt.Errorf("please pass --all if you'd like to remove all plugins")
|
||||
}
|
||||
if len(args) > 1 {
|
||||
name = args[1]
|
||||
|
@ -70,7 +71,7 @@ func newPluginRmCmd() *cobra.Command {
|
|||
if len(args) > 2 {
|
||||
r, err := semver.ParseRange(args[2])
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "invalid plugin semver")
|
||||
return fmt.Errorf("invalid plugin semver: %w", err)
|
||||
}
|
||||
version = &r
|
||||
}
|
||||
|
@ -79,7 +80,7 @@ func newPluginRmCmd() *cobra.Command {
|
|||
var deletes []workspace.PluginInfo
|
||||
plugins, err := workspace.GetPlugins()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "loading plugins")
|
||||
return fmt.Errorf("loading plugins: %w", err)
|
||||
}
|
||||
for _, plugin := range plugins {
|
||||
if (kind == "" || plugin.Kind == kind) &&
|
||||
|
@ -112,7 +113,7 @@ func newPluginRmCmd() *cobra.Command {
|
|||
for _, plugin := range deletes {
|
||||
if err := plugin.Delete(); err != nil {
|
||||
result = multierror.Append(
|
||||
result, errors.Wrapf(err, "failed to delete %s plugin %s", plugin.Kind, plugin))
|
||||
result, fmt.Errorf("failed to delete %s plugin %s: %w", plugin.Kind, plugin, err))
|
||||
}
|
||||
}
|
||||
if result != nil {
|
||||
|
|
|
@ -15,12 +15,12 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend/display"
|
||||
"github.com/pulumi/pulumi/sdk/v3/go/common/diag/colors"
|
||||
"github.com/pulumi/pulumi/sdk/v3/go/common/util/cmdutil"
|
||||
|
@ -98,7 +98,7 @@ func runNewPolicyPack(args newPolicyArgs) error {
|
|||
// Get the current working directory.
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "getting the working directory")
|
||||
return fmt.Errorf("getting the working directory: %w", err)
|
||||
}
|
||||
|
||||
// If dir was specified, ensure it exists and use it as the
|
||||
|
@ -147,7 +147,7 @@ func runNewPolicyPack(args newPolicyArgs) error {
|
|||
if !args.force {
|
||||
if err = workspace.CopyTemplateFilesDryRun(template.Dir, cwd, ""); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return errors.Wrapf(err, "template '%s' not found", args.templateNameOrURL)
|
||||
return fmt.Errorf("template '%s' not found: %w", args.templateNameOrURL, err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
@ -156,7 +156,7 @@ func runNewPolicyPack(args newPolicyArgs) error {
|
|||
// Actually copy the files.
|
||||
if err = workspace.CopyTemplateFiles(template.Dir, cwd, args.force, "", ""); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return errors.Wrapf(err, "template '%s' not found", args.templateNameOrURL)
|
||||
return fmt.Errorf("template '%s' not found: %w", args.templateNameOrURL, err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
@ -190,7 +190,7 @@ func installPolicyPackDependencies(proj *workspace.PolicyPackProject, projPath,
|
|||
// TODO[pulumi/pulumi#1334]: move to the language plugins so we don't have to hard code here.
|
||||
if strings.EqualFold(proj.Runtime.Name(), "nodejs") {
|
||||
if bin, err := nodeInstallDependencies(); err != nil {
|
||||
return errors.Wrapf(err, "`%s install` failed; rerun manually to try again.", bin)
|
||||
return fmt.Errorf("`%s install` failed; rerun manually to try again.: %w", bin, err)
|
||||
}
|
||||
} else if strings.EqualFold(proj.Runtime.Name(), "python") {
|
||||
const venvDir = "venv"
|
||||
|
@ -201,7 +201,7 @@ func installPolicyPackDependencies(proj *workspace.PolicyPackProject, projPath,
|
|||
// Save project with venv info.
|
||||
proj.Runtime.SetOption("virtualenv", venvDir)
|
||||
if err := proj.Save(projPath); err != nil {
|
||||
return errors.Wrapf(err, "saving project at %s", projPath)
|
||||
return fmt.Errorf("saving project at %s: %w", projPath, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
|
|
@ -15,10 +15,10 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend"
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend/display"
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend/httpstate"
|
||||
|
@ -110,8 +110,8 @@ func requirePolicyPack(policyPack string) (backend.PolicyPack, error) {
|
|||
|
||||
cloudURL, err := workspace.GetCurrentCloudURL()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err,
|
||||
"`pulumi policy` command requires the user to be logged into the Pulumi service")
|
||||
return nil, fmt.Errorf("`pulumi policy` command requires the user to be logged into the Pulumi service: %w", err)
|
||||
|
||||
}
|
||||
|
||||
displayOptions := display.Options{
|
||||
|
|
|
@ -16,6 +16,7 @@ package main
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend"
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend/display"
|
||||
"github.com/pulumi/pulumi/sdk/v3/go/common/util/cmdutil"
|
||||
|
|
|
@ -15,7 +15,9 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend"
|
||||
|
@ -132,17 +134,17 @@ func newPreviewCmd() *cobra.Command {
|
|||
|
||||
m, err := getUpdateMetadata(message, root, execKind, execAgent)
|
||||
if err != nil {
|
||||
return result.FromError(errors.Wrap(err, "gathering environment metadata"))
|
||||
return result.FromError(fmt.Errorf("gathering environment metadata: %w", err))
|
||||
}
|
||||
|
||||
sm, err := getStackSecretsManager(s)
|
||||
if err != nil {
|
||||
return result.FromError(errors.Wrap(err, "getting secrets manager"))
|
||||
return result.FromError(fmt.Errorf("getting secrets manager: %w", err))
|
||||
}
|
||||
|
||||
cfg, err := getStackConfiguration(s, sm)
|
||||
if err != nil {
|
||||
return result.FromError(errors.Wrap(err, "getting stack configuration"))
|
||||
return result.FromError(fmt.Errorf("getting stack configuration: %w", err))
|
||||
}
|
||||
|
||||
targetURNs := []resource.URN{}
|
||||
|
|
|
@ -18,8 +18,8 @@ import (
|
|||
"bufio"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
user "github.com/tweekmonster/luser"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
|
@ -30,10 +30,12 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
user "github.com/tweekmonster/luser"
|
||||
|
||||
"github.com/blang/semver"
|
||||
"github.com/djherbis/times"
|
||||
"github.com/docker/docker/pkg/term"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend/display"
|
||||
|
@ -210,6 +212,7 @@ func NewPulumiCmd() *cobra.Command {
|
|||
cmd.AddCommand(newConsoleCmd())
|
||||
cmd.AddCommand(newAboutCmd())
|
||||
cmd.AddCommand(newSchemaCmd())
|
||||
cmd.AddCommand(newOrgCmd())
|
||||
|
||||
// Less common, and thus hidden, commands:
|
||||
cmd.AddCommand(newGenCompletionCmd(cmd))
|
||||
|
@ -435,7 +438,7 @@ func isBrewInstall(exe string) (bool, error) {
|
|||
if ee, ok := err.(*exec.ExitError); ok {
|
||||
ee.Stderr = stderr.Bytes()
|
||||
}
|
||||
return false, errors.Wrapf(err, "'brew --prefix pulumi' failed")
|
||||
return false, fmt.Errorf("'brew --prefix pulumi' failed: %w", err)
|
||||
}
|
||||
|
||||
brewPrefixCmdOutput := strings.TrimSpace(stdout.String())
|
||||
|
|
|
@ -16,8 +16,9 @@ package main
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend"
|
||||
|
@ -124,17 +125,17 @@ func newRefreshCmd() *cobra.Command {
|
|||
|
||||
m, err := getUpdateMetadata(message, root, execKind, execAgent)
|
||||
if err != nil {
|
||||
return result.FromError(errors.Wrap(err, "gathering environment metadata"))
|
||||
return result.FromError(fmt.Errorf("gathering environment metadata: %w", err))
|
||||
}
|
||||
|
||||
sm, err := getStackSecretsManager(s)
|
||||
if err != nil {
|
||||
return result.FromError(errors.Wrap(err, "getting secrets manager"))
|
||||
return result.FromError(fmt.Errorf("getting secrets manager: %w", err))
|
||||
}
|
||||
|
||||
cfg, err := getStackConfiguration(s, sm)
|
||||
if err != nil {
|
||||
return result.FromError(errors.Wrap(err, "getting stack configuration"))
|
||||
return result.FromError(fmt.Errorf("getting stack configuration: %w", err))
|
||||
}
|
||||
|
||||
targetUrns := []resource.URN{}
|
||||
|
|
|
@ -16,13 +16,14 @@ package main
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/hashicorp/hcl/v2"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"gopkg.in/yaml.v3"
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ import (
|
|||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend"
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend/display"
|
||||
"github.com/pulumi/pulumi/pkg/v3/resource/stack"
|
||||
|
|
|
@ -16,9 +16,9 @@ package main
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/pulumi/pulumi/pkg/v3/resource/stack"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
|
@ -69,8 +69,7 @@ func newStackExportCmd() *cobra.Command {
|
|||
be := s.Backend()
|
||||
specificExpBE, ok := be.(backend.SpecificDeploymentExporter)
|
||||
if !ok {
|
||||
return errors.Errorf(
|
||||
"the current backend (%s) does not provide the ability to export previous deployments",
|
||||
return fmt.Errorf("the current backend (%s) does not provide the ability to export previous deployments",
|
||||
be.Name())
|
||||
}
|
||||
|
||||
|
@ -85,7 +84,7 @@ func newStackExportCmd() *cobra.Command {
|
|||
if file != "" {
|
||||
writer, err = os.Create(file)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not open file")
|
||||
return fmt.Errorf("could not open file: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,7 +115,7 @@ func newStackExportCmd() *cobra.Command {
|
|||
enc.SetIndent("", " ")
|
||||
|
||||
if err = enc.Encode(deployment); err != nil {
|
||||
return errors.Wrap(err, "could not export deployment")
|
||||
return fmt.Errorf("could not export deployment: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
|
@ -68,7 +68,7 @@ func newStackGraphCmd() *cobra.Command {
|
|||
|
||||
// This will prevent a panic when trying to assemble a dependencyGraph when no snapshot is found
|
||||
if snap == nil {
|
||||
return errors.Errorf("unable to find snapshot for stack %q", stackName)
|
||||
return fmt.Errorf("unable to find snapshot for stack %q", stackName)
|
||||
}
|
||||
|
||||
dg := makeDependencyGraph(snap)
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/dustin/go-humanize"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend"
|
||||
|
@ -47,13 +47,13 @@ This command displays data about previous updates for a stack.`,
|
|||
b := s.Backend()
|
||||
updates, err := b.GetHistory(commandContext(), s.Ref(), pageSize, page)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "getting history")
|
||||
return fmt.Errorf("getting history: %w", err)
|
||||
}
|
||||
var decrypter config.Decrypter
|
||||
if showSecrets {
|
||||
crypter, err := getStackDecrypter(s)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "decrypting secrets")
|
||||
return fmt.Errorf("decrypting secrets: %w", err)
|
||||
}
|
||||
decrypter = crypter
|
||||
}
|
||||
|
|
|
@ -16,11 +16,12 @@ package main
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/hashicorp/go-multierror"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend/display"
|
||||
|
@ -61,7 +62,7 @@ func newStackImportCmd() *cobra.Command {
|
|||
if file != "" {
|
||||
reader, err = os.Open(file)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not open file")
|
||||
return fmt.Errorf("could not open file: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -122,7 +123,7 @@ func newStackImportCmd() *cobra.Command {
|
|||
}
|
||||
sdp, err := stack.SerializeDeployment(snapshot, snapshot.SecretsManager, false /* showSecrets */)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "constructing deployment for upload")
|
||||
return fmt.Errorf("constructing deployment for upload: %w", err)
|
||||
}
|
||||
|
||||
bytes, err := json.Marshal(sdp)
|
||||
|
@ -137,7 +138,7 @@ func newStackImportCmd() *cobra.Command {
|
|||
|
||||
// Now perform the deployment.
|
||||
if err = s.ImportDeployment(commandContext(), &dep); err != nil {
|
||||
return errors.Wrap(err, "could not import deployment")
|
||||
return fmt.Errorf("could not import deployment: %w", err)
|
||||
}
|
||||
fmt.Printf("Import successful.\n")
|
||||
return nil
|
||||
|
|
|
@ -15,9 +15,9 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend/display"
|
||||
|
@ -107,11 +107,15 @@ func newStackInitCmd() *cobra.Command {
|
|||
return errors.New("missing stack name")
|
||||
}
|
||||
|
||||
if err := b.ValidateStackName(stackName); err != nil {
|
||||
formattedStackName, err := buildStackName(stackName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := b.ValidateStackName(formattedStackName); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
stackRef, err := b.ParseStackReference(stackName)
|
||||
stackRef, err := b.ParseStackReference(formattedStackName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -15,12 +15,14 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/dustin/go-humanize"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend"
|
||||
|
@ -110,14 +112,14 @@ func runStackLS(args stackLSArgs) error {
|
|||
// Ensure we are in a project; if not, we will fail.
|
||||
projPath, err := workspace.DetectProjectPath()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not detect current project")
|
||||
return fmt.Errorf("could not detect current project: %w", err)
|
||||
} else if projPath == "" {
|
||||
return errors.New("no Pulumi.yaml found; please run this command in a project directory")
|
||||
}
|
||||
|
||||
proj, err := workspace.LoadProject(projPath)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not load current project")
|
||||
return fmt.Errorf("could not load current project: %w", err)
|
||||
}
|
||||
projName := string(proj.Name)
|
||||
filter.Project = &projName
|
||||
|
|
|
@ -17,7 +17,6 @@ package main
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend/display"
|
||||
|
@ -57,7 +56,7 @@ func newStackOutputCmd() *cobra.Command {
|
|||
|
||||
outputs, err := getStackOutputs(snap, showSecrets)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "getting outputs")
|
||||
return fmt.Errorf("getting outputs: %w", err)
|
||||
}
|
||||
if outputs == nil {
|
||||
outputs = make(map[string]interface{})
|
||||
|
@ -76,7 +75,7 @@ func newStackOutputCmd() *cobra.Command {
|
|||
fmt.Printf("%v\n", stringifyOutput(v))
|
||||
}
|
||||
} else {
|
||||
return errors.Errorf("current stack does not have output property '%v'", name)
|
||||
return fmt.Errorf("current stack does not have output property '%v'", name)
|
||||
}
|
||||
} else if jsonOut {
|
||||
if err := printJSON(outputs); err != nil {
|
||||
|
|
|
@ -21,7 +21,6 @@ import (
|
|||
|
||||
"github.com/pulumi/pulumi/sdk/v3/go/common/tokens"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend/display"
|
||||
|
@ -79,15 +78,15 @@ func newStackRenameCmd() *cobra.Command {
|
|||
// Stack doesn't have any configuration, ignore.
|
||||
case configStatErr == nil:
|
||||
if err := os.Rename(oldConfigPath, newConfigPath); err != nil {
|
||||
return errors.Wrapf(err, "renaming configuration file to %s", filepath.Base(newConfigPath))
|
||||
return fmt.Errorf("renaming configuration file to %s: %w", filepath.Base(newConfigPath), err)
|
||||
}
|
||||
default:
|
||||
return errors.Wrapf(err, "checking current configuration file %v", oldConfigPath)
|
||||
return fmt.Errorf("checking current configuration file %v: %w", oldConfigPath, err)
|
||||
}
|
||||
|
||||
// Update the current workspace state to have selected the new stack.
|
||||
if err := state.SetCurrentStack(newStackName); err != nil {
|
||||
return errors.Wrap(err, "setting current stack")
|
||||
return fmt.Errorf("setting current stack: %w", err)
|
||||
}
|
||||
|
||||
fmt.Printf("Renamed %s to %s\n", s.Ref().String(), newStackRef.String())
|
||||
|
|
|
@ -15,7 +15,9 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend/display"
|
||||
|
@ -80,7 +82,7 @@ func newStackSelectCmd() *cobra.Command {
|
|||
return state.SetCurrentStack(s.Ref().String())
|
||||
}
|
||||
|
||||
return errors.Errorf("no stack named '%s' found", stackRef)
|
||||
return fmt.Errorf("no stack named '%s' found", stackRef)
|
||||
}
|
||||
|
||||
// If no stack was given, prompt the user to select a name from the available ones.
|
||||
|
|
|
@ -18,7 +18,6 @@ import (
|
|||
"fmt"
|
||||
"sort"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend"
|
||||
|
@ -79,8 +78,7 @@ func newStackTagGetCmd(stack *string) *cobra.Command {
|
|||
return nil
|
||||
}
|
||||
|
||||
return errors.Errorf(
|
||||
"stack tag '%s' not found for stack '%s'", name, s.Ref())
|
||||
return fmt.Errorf("stack tag '%s' not found for stack '%s'", name, s.Ref())
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,9 +16,9 @@ package main
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend/display"
|
||||
"github.com/pulumi/pulumi/pkg/v3/resource/deploy"
|
||||
"github.com/pulumi/pulumi/pkg/v3/resource/edit"
|
||||
|
@ -57,7 +57,7 @@ func locateStackResource(opts display.Options, snap *deploy.Snapshot, urn resour
|
|||
candidateResources := edit.LocateResource(snap, urn)
|
||||
switch {
|
||||
case len(candidateResources) == 0: // resource was not found
|
||||
return nil, errors.Errorf("No such resource %q exists in the current state", urn)
|
||||
return nil, fmt.Errorf("No such resource %q exists in the current state", urn)
|
||||
case len(candidateResources) == 1: // resource was unambiguously found
|
||||
return candidateResources[0], nil
|
||||
}
|
||||
|
@ -170,7 +170,7 @@ func runTotalStateEdit(
|
|||
|
||||
sdep, err := stack.SerializeDeployment(snap, snap.SecretsManager, false /* showSecrets */)
|
||||
if err != nil {
|
||||
return result.FromError(errors.Wrap(err, "serializing deployment"))
|
||||
return result.FromError(fmt.Errorf("serializing deployment: %w", err))
|
||||
}
|
||||
|
||||
// Once we've mutated the snapshot, import it back into the backend so that it can be persisted.
|
||||
|
|
|
@ -16,12 +16,12 @@ package main
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"os"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend"
|
||||
|
@ -96,17 +96,17 @@ func newUpCmd() *cobra.Command {
|
|||
|
||||
m, err := getUpdateMetadata(message, root, execKind, execAgent)
|
||||
if err != nil {
|
||||
return result.FromError(errors.Wrap(err, "gathering environment metadata"))
|
||||
return result.FromError(fmt.Errorf("gathering environment metadata: %w", err))
|
||||
}
|
||||
|
||||
sm, err := getStackSecretsManager(s)
|
||||
if err != nil {
|
||||
return result.FromError(errors.Wrap(err, "getting secrets manager"))
|
||||
return result.FromError(fmt.Errorf("getting secrets manager: %w", err))
|
||||
}
|
||||
|
||||
cfg, err := getStackConfiguration(s, sm)
|
||||
if err != nil {
|
||||
return result.FromError(errors.Wrap(err, "getting stack configuration"))
|
||||
return result.FromError(fmt.Errorf("getting stack configuration: %w", err))
|
||||
}
|
||||
|
||||
targetURNs := []resource.URN{}
|
||||
|
@ -208,7 +208,7 @@ func newUpCmd() *cobra.Command {
|
|||
|
||||
// Change the working directory to the "virtual workspace" directory.
|
||||
if err = os.Chdir(temp); err != nil {
|
||||
return result.FromError(errors.Wrap(err, "changing the working directory"))
|
||||
return result.FromError(fmt.Errorf("changing the working directory: %w", err))
|
||||
}
|
||||
|
||||
// If a stack was specified via --stack, see if it already exists.
|
||||
|
@ -256,7 +256,7 @@ func newUpCmd() *cobra.Command {
|
|||
proj.Description = &description
|
||||
proj.Template = nil
|
||||
if err = workspace.SaveProject(proj); err != nil {
|
||||
return result.FromError(errors.Wrap(err, "saving project"))
|
||||
return result.FromError(fmt.Errorf("saving project: %w", err))
|
||||
}
|
||||
|
||||
// Create the stack, if needed.
|
||||
|
@ -280,17 +280,17 @@ func newUpCmd() *cobra.Command {
|
|||
|
||||
m, err := getUpdateMetadata(message, root, execKind, execAgent)
|
||||
if err != nil {
|
||||
return result.FromError(errors.Wrap(err, "gathering environment metadata"))
|
||||
return result.FromError(fmt.Errorf("gathering environment metadata: %w", err))
|
||||
}
|
||||
|
||||
sm, err := getStackSecretsManager(s)
|
||||
if err != nil {
|
||||
return result.FromError(errors.Wrap(err, "getting secrets manager"))
|
||||
return result.FromError(fmt.Errorf("getting secrets manager: %w", err))
|
||||
}
|
||||
|
||||
cfg, err := getStackConfiguration(s, sm)
|
||||
if err != nil {
|
||||
return result.FromError(errors.Wrap(err, "getting stack configuration"))
|
||||
return result.FromError(fmt.Errorf("getting stack configuration: %w", err))
|
||||
}
|
||||
|
||||
refreshOption, err := getRefreshOption(proj, refresh)
|
||||
|
@ -588,7 +588,7 @@ func handleConfig(
|
|||
// Save the config.
|
||||
if len(c) > 0 {
|
||||
if err = saveConfig(s, c); err != nil {
|
||||
return errors.Wrap(err, "saving config")
|
||||
return fmt.Errorf("saving config: %w", err)
|
||||
}
|
||||
|
||||
fmt.Println("Saved config")
|
||||
|
|
|
@ -18,6 +18,7 @@ import (
|
|||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
|
@ -30,7 +31,7 @@ import (
|
|||
|
||||
multierror "github.com/hashicorp/go-multierror"
|
||||
opentracing "github.com/opentracing/opentracing-go"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
survey "gopkg.in/AlecAivazis/survey.v1"
|
||||
surveycore "gopkg.in/AlecAivazis/survey.v1/core"
|
||||
git "gopkg.in/src-d/go-git.v4"
|
||||
|
@ -99,7 +100,7 @@ func isFilestateBackend(opts display.Options) (bool, error) {
|
|||
|
||||
url, err := workspace.GetCurrentCloudURL()
|
||||
if err != nil {
|
||||
return false, errors.Wrapf(err, "could not get cloud url")
|
||||
return false, fmt.Errorf("could not get cloud url: %w", err)
|
||||
}
|
||||
|
||||
return filestate.IsFileStateBackendURL(url), nil
|
||||
|
@ -112,7 +113,7 @@ func currentBackend(opts display.Options) (backend.Backend, error) {
|
|||
|
||||
url, err := workspace.GetCurrentCloudURL()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get cloud url")
|
||||
return nil, fmt.Errorf("could not get cloud url: %w", err)
|
||||
}
|
||||
|
||||
if filestate.IsFileStateBackendURL(url) {
|
||||
|
@ -184,7 +185,7 @@ func createSecretsManager(b backend.Backend, stackRef backend.StackReference, se
|
|||
if strings.HasPrefix(secretsProvider, "azurekeyvault://") {
|
||||
parsed, err := url.Parse(secretsProvider)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to parse secrets provider URL")
|
||||
return fmt.Errorf("failed to parse secrets provider URL: %w", err)
|
||||
}
|
||||
|
||||
if parsed.Query().Get("algorithm") == "" {
|
||||
|
@ -215,7 +216,7 @@ func createStack(
|
|||
if _, ok := err.(*backend.OverStackLimitError); ok {
|
||||
return nil, err
|
||||
}
|
||||
return nil, errors.Wrapf(err, "could not create stack")
|
||||
return nil, fmt.Errorf("could not create stack: %w", err)
|
||||
}
|
||||
|
||||
if err := createSecretsManager(b, stackRef, secretsProvider,
|
||||
|
@ -272,7 +273,7 @@ func requireStack(
|
|||
return createStack(b, stackRef, nil, setCurrent, "")
|
||||
}
|
||||
|
||||
return nil, errors.Errorf("no stack named '%s' found", stackName)
|
||||
return nil, fmt.Errorf("no stack named '%s' found", stackName)
|
||||
}
|
||||
|
||||
func requireCurrentStack(offerNew bool, opts display.Options, setCurrent bool) (backend.Stack, error) {
|
||||
|
@ -324,7 +325,7 @@ func chooseStack(
|
|||
for {
|
||||
summaries, outContToken, err := b.ListStacks(ctx, backend.ListStacksFilter{Project: &project}, inContToken)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not query backend for stacks")
|
||||
return nil, fmt.Errorf("could not query backend for stacks: %w", err)
|
||||
}
|
||||
|
||||
allSummaries = append(allSummaries, summaries...)
|
||||
|
@ -404,15 +405,15 @@ func chooseStack(
|
|||
// With the stack name selected, look it up from the backend.
|
||||
stackRef, err := b.ParseStackReference(option)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "parsing selected stack")
|
||||
return nil, fmt.Errorf("parsing selected stack: %w", err)
|
||||
}
|
||||
// GetStack may return (nil, nil) if the stack isn't found.
|
||||
stack, err := b.GetStack(ctx, stackRef)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "getting selected stack")
|
||||
return nil, fmt.Errorf("getting selected stack: %w", err)
|
||||
}
|
||||
if stack == nil {
|
||||
return nil, errors.Errorf("no stack named '%s' found", stackRef)
|
||||
return nil, fmt.Errorf("no stack named '%s' found", stackRef)
|
||||
}
|
||||
|
||||
// If setCurrent is true, we'll persist this choice so it'll be used for future CLI operations.
|
||||
|
@ -437,7 +438,7 @@ func parseAndSaveConfigArray(s backend.Stack, configArray []string, path bool) e
|
|||
}
|
||||
|
||||
if err = saveConfig(s, commandLineConfig); err != nil {
|
||||
return errors.Wrap(err, "saving config")
|
||||
return fmt.Errorf("saving config: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -472,8 +473,9 @@ func readProject() (*workspace.Project, string, error) {
|
|||
// Now that we got here, we have a path, so we will try to load it.
|
||||
path, err := workspace.DetectProjectPathFrom(pwd)
|
||||
if err != nil {
|
||||
return nil, "", errors.Wrapf(err, "failed to find current Pulumi project because of "+
|
||||
"an error when searching for the Pulumi.yaml file (searching upwards from %s)", pwd)
|
||||
return nil, "", fmt.Errorf("failed to find current Pulumi project because of "+
|
||||
"an error when searching for the Pulumi.yaml file (searching upwards from %s)"+": %w", pwd, err)
|
||||
|
||||
} else if path == "" {
|
||||
return nil, "", fmt.Errorf(
|
||||
"no Pulumi.yaml project file found (searching upwards from %s). If you have not "+
|
||||
|
@ -481,7 +483,7 @@ func readProject() (*workspace.Project, string, error) {
|
|||
}
|
||||
proj, err := workspace.LoadProject(path)
|
||||
if err != nil {
|
||||
return nil, "", errors.Wrapf(err, "failed to load Pulumi project located at %q", path)
|
||||
return nil, "", fmt.Errorf("failed to load Pulumi project located at %q: %w", path, err)
|
||||
}
|
||||
|
||||
return proj, filepath.Dir(path), nil
|
||||
|
@ -499,14 +501,15 @@ func readPolicyProject() (*workspace.PolicyPackProject, string, string, error) {
|
|||
// Now that we got here, we have a path, so we will try to load it.
|
||||
path, err := workspace.DetectPolicyPackPathFrom(pwd)
|
||||
if err != nil {
|
||||
return nil, "", "", errors.Wrapf(err, "failed to find current Pulumi project because of "+
|
||||
"an error when searching for the PulumiPolicy.yaml file (searching upwards from %s)", pwd)
|
||||
return nil, "", "", fmt.Errorf("failed to find current Pulumi project because of "+
|
||||
"an error when searching for the PulumiPolicy.yaml file (searching upwards from %s)"+": %w", pwd, err)
|
||||
|
||||
} else if path == "" {
|
||||
return nil, "", "", fmt.Errorf("no PulumiPolicy.yaml project file found (searching upwards from %s)", pwd)
|
||||
}
|
||||
proj, err := workspace.LoadPolicyPack(path)
|
||||
if err != nil {
|
||||
return nil, "", "", errors.Wrapf(err, "failed to load Pulumi policy project located at %q", path)
|
||||
return nil, "", "", fmt.Errorf("failed to load Pulumi policy project located at %q: %w", path, err)
|
||||
}
|
||||
|
||||
return proj, path, filepath.Dir(path), nil
|
||||
|
@ -540,7 +543,7 @@ func isGitWorkTreeDirty(repoRoot string) (bool, error) {
|
|||
if ee, ok := err.(*exec.ExitError); ok {
|
||||
ee.Stderr = stderr.Bytes()
|
||||
}
|
||||
return false, errors.Wrapf(err, "'git status' failed")
|
||||
return false, fmt.Errorf("'git status' failed: %w", err)
|
||||
}
|
||||
|
||||
return bool(anyOutput), nil
|
||||
|
@ -572,7 +575,7 @@ func addGitMetadata(repoRoot string, m *backend.UpdateMetadata) error {
|
|||
// Gather git-related data as appropriate. (Returns nil, nil if no repo found.)
|
||||
repo, err := gitutil.GetGitRepository(repoRoot)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "detecting Git repository")
|
||||
return fmt.Errorf("detecting Git repository: %w", err)
|
||||
}
|
||||
if repo == nil {
|
||||
return nil
|
||||
|
@ -596,7 +599,7 @@ func AddGitRemoteMetadataToMap(repo *git.Repository, env map[string]string) erro
|
|||
// Get the remote URL for this repo.
|
||||
remoteURL, err := gitutil.GetGitRemoteURL(repo, "origin")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "detecting Git remote URL")
|
||||
return fmt.Errorf("detecting Git remote URL: %w", err)
|
||||
}
|
||||
if remoteURL == "" {
|
||||
return nil
|
||||
|
@ -615,7 +618,7 @@ func addVCSMetadataToEnvironment(remoteURL string, env map[string]string) error
|
|||
// We don't require a cloud-hosted VCS, so swallow errors.
|
||||
vcsInfo, err := gitutil.TryGetVCSInfo(remoteURL)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "detecting VCS project information")
|
||||
return fmt.Errorf("detecting VCS project information: %w", err)
|
||||
}
|
||||
env[backend.VCSRepoOwner] = vcsInfo.Owner
|
||||
env[backend.VCSRepoName] = vcsInfo.Repo
|
||||
|
@ -633,14 +636,14 @@ func addGitCommitMetadata(repo *git.Repository, repoRoot string, m *backend.Upda
|
|||
// Commit at HEAD
|
||||
head, err := repo.Head()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "getting repository HEAD")
|
||||
return fmt.Errorf("getting repository HEAD: %w", err)
|
||||
}
|
||||
|
||||
hash := head.Hash()
|
||||
m.Environment[backend.GitHead] = hash.String()
|
||||
commit, commitErr := repo.CommitObject(hash)
|
||||
if commitErr != nil {
|
||||
return errors.Wrap(commitErr, "getting HEAD commit info")
|
||||
return fmt.Errorf("getting HEAD commit info: %w", commitErr)
|
||||
}
|
||||
|
||||
// If in detached head, will be "HEAD", and fallback to use value from CI/CD system if possible.
|
||||
|
@ -671,7 +674,7 @@ func addGitCommitMetadata(repo *git.Repository, repoRoot string, m *backend.Upda
|
|||
// If the worktree is dirty, set a bit, as this could be a mistake.
|
||||
isDirty, err := isGitWorkTreeDirty(repoRoot)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "checking git worktree dirty state")
|
||||
return fmt.Errorf("checking git worktree dirty state: %w", err)
|
||||
}
|
||||
m.Environment[backend.GitDirty] = strconv.FormatBool(isDirty)
|
||||
|
||||
|
@ -837,7 +840,7 @@ func checkDeploymentVersionError(err error, stackName string) error {
|
|||
return fmt.Errorf("the stack '%s' is newer than what this version of the Pulumi CLI understands. "+
|
||||
"Please update your version of the Pulumi CLI", stackName)
|
||||
}
|
||||
return errors.Wrap(err, "could not deserialize deployment")
|
||||
return fmt.Errorf("could not deserialize deployment: %w", err)
|
||||
}
|
||||
|
||||
func getRefreshOption(proj *workspace.Project, refresh string) (bool, error) {
|
||||
|
@ -862,3 +865,20 @@ func getRefreshOption(proj *workspace.Project, refresh string) (bool, error) {
|
|||
// the default functionality right now is to always skip a refresh
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func buildStackName(stackName string) (string, error) {
|
||||
if strings.Count(stackName, "/") == 2 {
|
||||
return stackName, nil
|
||||
}
|
||||
|
||||
defaultOrg, err := workspace.GetBackendConfigDefaultOrg()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if defaultOrg != "" {
|
||||
return fmt.Sprintf("%s/%s", defaultOrg, stackName), nil
|
||||
}
|
||||
|
||||
return stackName, nil
|
||||
}
|
||||
|
|
|
@ -16,8 +16,9 @@ package main
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/v3/backend"
|
||||
|
@ -101,17 +102,17 @@ func newWatchCmd() *cobra.Command {
|
|||
|
||||
m, err := getUpdateMetadata(message, root, execKind, "" /* execAgent */)
|
||||
if err != nil {
|
||||
return result.FromError(errors.Wrap(err, "gathering environment metadata"))
|
||||
return result.FromError(fmt.Errorf("gathering environment metadata: %w", err))
|
||||
}
|
||||
|
||||
sm, err := getStackSecretsManager(s)
|
||||
if err != nil {
|
||||
return result.FromError(errors.Wrap(err, "getting secrets manager"))
|
||||
return result.FromError(fmt.Errorf("getting secrets manager: %w", err))
|
||||
}
|
||||
|
||||
cfg, err := getStackConfiguration(s, sm)
|
||||
if err != nil {
|
||||
return result.FromError(errors.Wrap(err, "getting stack configuration"))
|
||||
return result.FromError(fmt.Errorf("getting stack configuration: %w", err))
|
||||
}
|
||||
|
||||
opts.Engine = engine.UpdateOptions{
|
||||
|
|
|
@ -32,19 +32,3 @@ For minor diffs, you can just update the test files manually and include those u
|
|||
```
|
||||
PULUMI_ACCEPT=true pushd pkg/codegen/docs && go test . && popd
|
||||
```
|
||||
|
||||
## `bundler.go`
|
||||
|
||||
This file contains a `main` function and is part of the `main` package. We run it using the `go generate` command (see the `Makefile` and the starting comment in `pkg/codegen/gen.go`).
|
||||
|
||||
> This file is ignored using a `+build ignore` comment at the top of the file, so it is not ignored during a `go build ...`.
|
||||
|
||||
## `packaged.go`
|
||||
|
||||
A file generated by `bundler.go` that contains formatted byte strings, that represent the string templates from the `./templates/` folder. This file is also git-ignored as it is intended to only be generated by the `docs` repo and is not used during runtime of the main Pulumi CLI. In fact, this whole package is not used during the runtime of the CLI itself.
|
||||
|
||||
## `go:generate`
|
||||
|
||||
> Read more [here](https://blog.golang.org/generate).
|
||||
|
||||
`go:generate` is a special code comment that can be used to run custom commands by simply running `go generate <package>`, which then scans for `go:generate` comments in all sources in the package `<package>`. It also serves as a way to document, that a certain file relies on a command to have been executed before it can be used.
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
//go:build ignore
|
||||
// +build ignore
|
||||
|
||||
// Copyright 2016-2020, 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.
|
||||
|
||||
// Pulling out some of the repeated strings tokens into constants would harm readability, so we just ignore the
|
||||
// goconst linter's warning.
|
||||
//
|
||||
// nolint: lll, goconst
|
||||
package main
|
||||
|
||||
import "github.com/pulumi/pulumi/pkg/v3/codegen/docs/bundler"
|
||||
|
||||
// main reads files under the templates directory, and builds a map of filename to byte slice.
|
||||
// Each file's contents are then written to a generated file.
|
||||
//
|
||||
// NOTE: Sub-directories are currently not supported.
|
||||
func main() {
|
||||
if err := bundler.GenerateTemplatesBundleFile(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
|
@ -1,127 +0,0 @@
|
|||
// 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 bundler
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/format"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
basePath = "."
|
||||
docsTemplatesPath = basePath + "/templates"
|
||||
generatedFileName = basePath + "/packaged.go"
|
||||
)
|
||||
|
||||
var conv = map[string]interface{}{"conv": fmtByteSlice}
|
||||
var tmpl = template.Must(template.New("").Funcs(conv).Parse(`
|
||||
// AUTO-GENERATED FILE! DO NOT EDIT THIS FILE MANUALLY.
|
||||
|
||||
// Copyright 2016-2020, 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.
|
||||
|
||||
// Pulling out some of the repeated strings tokens into constants would harm readability, so we just ignore the
|
||||
// goconst linter's warning.
|
||||
//
|
||||
// nolint: lll, goconst
|
||||
package docs
|
||||
|
||||
func init() {
|
||||
packagedTemplates = make(map[string][]byte)
|
||||
{{ range $key, $value := . }}
|
||||
packagedTemplates["{{ $key }}"] = []byte{ {{ conv $value }} }
|
||||
{{ println }}
|
||||
{{- end }}
|
||||
}
|
||||
`))
|
||||
|
||||
// fmtByteSlice returns a formatted byte string for a given slice of bytes.
|
||||
// We embed the raw bytes to avoid any formatting errors that can occur due to saving
|
||||
// raw strings in a file.
|
||||
func fmtByteSlice(s []byte) string {
|
||||
builder := strings.Builder{}
|
||||
|
||||
for _, v := range s {
|
||||
builder.WriteString(fmt.Sprintf("%d,", int(v)))
|
||||
}
|
||||
|
||||
return builder.String()
|
||||
}
|
||||
|
||||
// GenerateTemplatesBundleFile reads the templates from `../templates/` and writes a git-ignored
|
||||
// packaged.go file containing byte-slices of the templates.
|
||||
func GenerateTemplatesBundleFile() error {
|
||||
files, err := ioutil.ReadDir(docsTemplatesPath)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "reading the templates dir")
|
||||
}
|
||||
|
||||
contents := make(map[string][]byte)
|
||||
for _, f := range files {
|
||||
if f.IsDir() {
|
||||
fmt.Printf("%q is a dir. Skipping...\n", f.Name())
|
||||
}
|
||||
b, err := ioutil.ReadFile(docsTemplatesPath + "/" + f.Name())
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "reading file %s", f.Name())
|
||||
}
|
||||
if len(b) == 0 {
|
||||
fmt.Printf("%q is empty. Skipping...\n", f.Name())
|
||||
continue
|
||||
}
|
||||
contents[f.Name()] = b
|
||||
}
|
||||
|
||||
// We overwrite the file every time the `go generate ...` command is run.
|
||||
f, err := os.Create(generatedFileName)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "creating blob file")
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
builder := &bytes.Buffer{}
|
||||
if err = tmpl.Execute(builder, contents); err != nil {
|
||||
return errors.Wrap(err, "executing template")
|
||||
}
|
||||
|
||||
data, err := format.Source(builder.Bytes())
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "formatting generated code")
|
||||
}
|
||||
|
||||
if err = ioutil.WriteFile(generatedFileName, data, os.ModePerm); err != nil {
|
||||
return errors.Wrap(err, "writing file")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -22,6 +22,8 @@ package docs
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"embed"
|
||||
"errors"
|
||||
"fmt"
|
||||
"html"
|
||||
"html/template"
|
||||
|
@ -30,7 +32,6 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/v3/codegen"
|
||||
"github.com/pulumi/pulumi/pkg/v3/codegen/dotnet"
|
||||
|
@ -41,18 +42,13 @@ import (
|
|||
"github.com/pulumi/pulumi/sdk/v3/go/common/util/contract"
|
||||
)
|
||||
|
||||
// Populated in auto-generated `packaged.go`
|
||||
var packagedTemplates map[string][]byte
|
||||
//go:embed templates/*.tmpl
|
||||
var packagedTemplates embed.FS
|
||||
|
||||
func init() {
|
||||
packagedTemplates = map[string][]byte{}
|
||||
}
|
||||
|
||||
// TODO[pulumi/pulumi#7813]: Remove this lookup once display name is available in
|
||||
// the Pulumi schema.
|
||||
//
|
||||
// NOTE: For the time being this lookup map and the one used by the resourcedocsgen
|
||||
// tool in `pulumi/docs` must be kept up-to-date.
|
||||
// NOTE: This lookup map can be removed when all Pulumi-managed packages
|
||||
// have a DisplayName in their schema. See pulumi/pulumi#7813.
|
||||
// This lookup table no longer needs to be updated for new providers
|
||||
// and is considered stale.
|
||||
//
|
||||
// titleLookup is a map of package name to the desired display name.
|
||||
func titleLookup(shortName string) (string, bool) {
|
||||
|
@ -435,7 +431,7 @@ func (dctx *docGenContext) getLanguageDocHelper(lang string) codegen.DocLanguage
|
|||
if h, ok := dctx.docHelpers[lang]; ok {
|
||||
return h
|
||||
}
|
||||
panic(errors.Errorf("could not find a doc lang helper for %s", lang))
|
||||
panic(fmt.Errorf("could not find a doc lang helper for %s", lang))
|
||||
}
|
||||
|
||||
type propertyCharacteristics struct {
|
||||
|
@ -906,8 +902,14 @@ func (mod *modContext) genNestedTypes(member interface{}, resourceType bool) []d
|
|||
// and if it appears in an input object and/or output object.
|
||||
mod.getTypes(member, tokens)
|
||||
|
||||
var typs []docNestedType
|
||||
var sortedTokens []string
|
||||
for token := range tokens {
|
||||
sortedTokens = append(sortedTokens, token)
|
||||
}
|
||||
sort.Strings(sortedTokens)
|
||||
|
||||
var typs []docNestedType
|
||||
for _, token := range sortedTokens {
|
||||
for _, t := range mod.pkg.Types {
|
||||
switch typ := t.(type) {
|
||||
case *schema.ObjectType:
|
||||
|
@ -1178,7 +1180,7 @@ func (mod *modContext) getConstructorResourceInfo(resourceTypeName string) map[s
|
|||
|
||||
resourceTypeName = fmt.Sprintf("Pulumi.%s.%s.%s", namespace, modName, resourceTypeName)
|
||||
default:
|
||||
panic(errors.Errorf("cannot generate constructor info for unhandled language %q", lang))
|
||||
panic(fmt.Errorf("cannot generate constructor info for unhandled language %q", lang))
|
||||
}
|
||||
|
||||
parts := strings.Split(resourceTypeName, ".")
|
||||
|
@ -1706,8 +1708,13 @@ func (mod *modContext) genIndex() indexData {
|
|||
modName := mod.getModuleFileName()
|
||||
title := modName
|
||||
|
||||
// An empty string indicates that this is the root module.
|
||||
if title == "" {
|
||||
title = formatTitleText(mod.pkg.Name)
|
||||
if mod.pkg.DisplayName != "" {
|
||||
title = mod.pkg.DisplayName
|
||||
} else {
|
||||
title = getPackageDisplayName(mod.pkg.Name)
|
||||
}
|
||||
}
|
||||
|
||||
// If there are submodules, list them.
|
||||
|
@ -1759,7 +1766,7 @@ func (mod *modContext) genIndex() indexData {
|
|||
// assume top level package index page when formatting title tags otherwise, if contains modules, assume modules
|
||||
// top level page when generating title tags.
|
||||
if len(modules) > 0 {
|
||||
titleTag = fmt.Sprintf("%s Package", formatTitleText(title))
|
||||
titleTag = fmt.Sprintf("%s Package", getPackageDisplayName(title))
|
||||
} else {
|
||||
titleTag = fmt.Sprintf("%s.%s", mod.pkg.Name, title)
|
||||
packageDescription = fmt.Sprintf("Explore the resources and functions of the %s.%s module.", mod.pkg.Name, title)
|
||||
|
@ -1784,7 +1791,9 @@ func (mod *modContext) genIndex() indexData {
|
|||
return data
|
||||
}
|
||||
|
||||
func formatTitleText(title string) string {
|
||||
// getPackageDisplayName uses the title lookup map to look for a
|
||||
// display name for the given title.
|
||||
func getPackageDisplayName(title string) string {
|
||||
// If title not found in titleLookup map, default back to title given.
|
||||
if val, ok := titleLookup(title); ok {
|
||||
return val
|
||||
|
@ -1936,12 +1945,8 @@ func (dctx *docGenContext) initialize(tool string, pkg *schema.Package) {
|
|||
|
||||
defer glog.Flush()
|
||||
|
||||
if len(packagedTemplates) == 0 {
|
||||
glog.Fatal(`packagedTemplates is empty. Did you run "make generate" first?`)
|
||||
}
|
||||
|
||||
for name, b := range packagedTemplates {
|
||||
template.Must(dctx.templates.New(name).Parse(string(b)))
|
||||
if _, err := dctx.templates.ParseFS(packagedTemplates, "templates/*.tmpl"); err != nil {
|
||||
glog.Fatalf("initializing templates: %v", err)
|
||||
}
|
||||
|
||||
// Generate the modules from the schema, and for every module
|
||||
|
@ -1958,8 +1963,14 @@ func (dctx *docGenContext) generatePackage(tool string, pkg *schema.Package) (ma
|
|||
|
||||
glog.V(3).Infoln("generating package docs now...")
|
||||
files := fs{}
|
||||
for _, mod := range dctx.modules() {
|
||||
if err := mod.gen(files); err != nil {
|
||||
modules := []string{}
|
||||
modMap := dctx.modules()
|
||||
for k := range modMap {
|
||||
modules = append(modules, k)
|
||||
}
|
||||
sort.Strings(modules)
|
||||
for _, mod := range modules {
|
||||
if err := modMap[mod].gen(files); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@ import (
|
|||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/pulumi/pulumi/pkg/v3/codegen"
|
||||
go_gen "github.com/pulumi/pulumi/pkg/v3/codegen/go"
|
||||
"github.com/pulumi/pulumi/pkg/v3/codegen/python"
|
||||
|
@ -113,7 +112,7 @@ func (mod *modContext) getFunctionResourceInfo(f *schema.Function, outputVersion
|
|||
case "python":
|
||||
resultTypeName = docLangHelper.GetResourceFunctionResultName(mod.mod, f)
|
||||
default:
|
||||
panic(errors.Errorf("cannot generate function resource info for unhandled language %q", lang))
|
||||
panic(fmt.Errorf("cannot generate function resource info for unhandled language %q", lang))
|
||||
}
|
||||
|
||||
parts := strings.Split(resultTypeName, ".")
|
||||
|
|
|
@ -20,10 +20,11 @@ package docs
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/v3/codegen/internal/test"
|
||||
"github.com/pulumi/pulumi/pkg/v3/codegen/schema"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package docs
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
)
|
||||
|
||||
|
@ -36,7 +36,7 @@ func generatePackageTree(rootMod modContext) ([]PackageTreeItem, error) {
|
|||
|
||||
children, err := generatePackageTree(*m)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "generating children for module %s (mod token: %s)", displayName, m.mod)
|
||||
return nil, fmt.Errorf("generating children for module %s (mod token: %s): %w", displayName, m.mod, err)
|
||||
}
|
||||
|
||||
ti := PackageTreeItem{
|
||||
|
|
|
@ -32,7 +32,6 @@ import (
|
|||
"strings"
|
||||
"unicode"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/pulumi/pulumi/pkg/v3/codegen"
|
||||
"github.com/pulumi/pulumi/pkg/v3/codegen/schema"
|
||||
"github.com/pulumi/pulumi/sdk/v3/go/common/diag"
|
||||
|
@ -767,7 +766,7 @@ func primitiveValue(value interface{}) (string, error) {
|
|||
case reflect.String:
|
||||
return fmt.Sprintf("%q", v.String()), nil
|
||||
default:
|
||||
return "", errors.Errorf("unsupported default value of type %T", value)
|
||||
return "", fmt.Errorf("unsupported default value of type %T", value)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -796,7 +795,7 @@ func (mod *modContext) getDefaultValue(dv *schema.DefaultValue, t schema.Type) (
|
|||
break
|
||||
}
|
||||
if val == "" {
|
||||
return "", errors.Errorf("default value '%v' not found in enum '%s'", dv.Value, enumName)
|
||||
return "", fmt.Errorf("default value '%v' not found in enum '%s'", dv.Value, enumName)
|
||||
}
|
||||
default:
|
||||
v, err := primitiveValue(dv.Value)
|
||||
|
@ -1995,6 +1994,11 @@ func (mod *modContext) gen(fs fs) error {
|
|||
|
||||
// Resources
|
||||
for _, r := range mod.resources {
|
||||
if r.IsOverlay {
|
||||
// This resource code is generated by the provider, so no further action is required.
|
||||
continue
|
||||
}
|
||||
|
||||
imports := map[string]codegen.StringSet{}
|
||||
mod.getImportsForResource(r, imports, r)
|
||||
|
||||
|
@ -2017,6 +2021,11 @@ func (mod *modContext) gen(fs fs) error {
|
|||
|
||||
// Functions
|
||||
for _, f := range mod.functions {
|
||||
if f.IsOverlay {
|
||||
// This function code is generated by the provider, so no further action is required.
|
||||
continue
|
||||
}
|
||||
|
||||
code, err := mod.genFunctionFileCode(f)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -2026,6 +2035,11 @@ func (mod *modContext) gen(fs fs) error {
|
|||
|
||||
// Nested types
|
||||
for _, t := range mod.types {
|
||||
if t.IsOverlay {
|
||||
// This type is generated by the provider, so no further action is required.
|
||||
continue
|
||||
}
|
||||
|
||||
if mod.details(t).inputType {
|
||||
buffer := &bytes.Buffer{}
|
||||
mod.genHeader(buffer, pulumiImports)
|
||||
|
@ -2186,6 +2200,11 @@ func generateModuleContextMap(tool string, pkg *schema.Package) (map[string]*mod
|
|||
computePropertyNames(pkg.Config, propertyNames)
|
||||
computePropertyNames(pkg.Provider.InputProperties, propertyNames)
|
||||
for _, r := range pkg.Resources {
|
||||
if r.IsOverlay {
|
||||
// This resource code is generated by the provider, so no further action is required.
|
||||
continue
|
||||
}
|
||||
|
||||
computePropertyNames(r.Properties, propertyNames)
|
||||
computePropertyNames(r.InputProperties, propertyNames)
|
||||
if r.StateInputs != nil {
|
||||
|
@ -2193,6 +2212,11 @@ func generateModuleContextMap(tool string, pkg *schema.Package) (map[string]*mod
|
|||
}
|
||||
}
|
||||
for _, f := range pkg.Functions {
|
||||
if f.IsOverlay {
|
||||
// This function code is generated by the provider, so no further action is required.
|
||||
continue
|
||||
}
|
||||
|
||||
if f.Inputs != nil {
|
||||
computePropertyNames(f.Inputs.Properties, propertyNames)
|
||||
}
|
||||
|
@ -2289,6 +2313,11 @@ func generateModuleContextMap(tool string, pkg *schema.Package) (map[string]*mod
|
|||
|
||||
// Find input and output types referenced by functions.
|
||||
for _, f := range pkg.Functions {
|
||||
if f.IsOverlay {
|
||||
// This function code is generated by the provider, so no further action is required.
|
||||
continue
|
||||
}
|
||||
|
||||
mod := getModFromToken(f.Token, pkg)
|
||||
if !f.IsMethod {
|
||||
mod.functions = append(mod.functions, f)
|
||||
|
@ -2323,8 +2352,10 @@ func generateModuleContextMap(tool string, pkg *schema.Package) (map[string]*mod
|
|||
mod := getModFromToken(typ.Token, pkg)
|
||||
mod.types = append(mod.types, typ)
|
||||
case *schema.EnumType:
|
||||
mod := getModFromToken(typ.Token, pkg)
|
||||
mod.enums = append(mod.enums, typ)
|
||||
if !typ.IsOverlay {
|
||||
mod := getModFromToken(typ.Token, pkg)
|
||||
mod.enums = append(mod.enums, typ)
|
||||
}
|
||||
default:
|
||||
continue
|
||||
}
|
||||
|
@ -2347,6 +2378,11 @@ func LanguageResources(tool string, pkg *schema.Package) (map[string]LanguageRes
|
|||
continue
|
||||
}
|
||||
for _, r := range mod.resources {
|
||||
if r.IsOverlay {
|
||||
// This resource code is generated by the provider, so no further action is required.
|
||||
continue
|
||||
}
|
||||
|
||||
lr := LanguageResource{
|
||||
Resource: r,
|
||||
Package: namespaceName(info.Namespaces, modName),
|
||||
|
|
|
@ -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.
|
||||
|
@ -46,6 +46,9 @@ type generator struct {
|
|||
asyncInit bool
|
||||
configCreated bool
|
||||
diagnostics hcl.Diagnostics
|
||||
// Helper map to emit custom type name suffixes that match
|
||||
// those emitted by codegen.
|
||||
usedInFunctionOutputVersionInputs map[schema.Type]bool
|
||||
}
|
||||
|
||||
const pulumiPackage = "pulumi"
|
||||
|
@ -343,14 +346,32 @@ func (g *generator) functionName(tokenArg model.Expression) (string, string) {
|
|||
return rootNamespace, fmt.Sprintf("%s%s.%s", rootNamespace, namespace, Title(member))
|
||||
}
|
||||
|
||||
func (g *generator) toSchemaType(destType model.Type) (schema.Type, bool) {
|
||||
schemaType, ok := pcl.GetSchemaForType(destType.(model.Type))
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
return codegen.UnwrapType(schemaType), true
|
||||
}
|
||||
|
||||
// argumentTypeName computes the C# argument class name for the given expression and model type.
|
||||
func (g *generator) argumentTypeName(expr model.Expression, destType model.Type) string {
|
||||
schemaType, ok := pcl.GetSchemaForType(destType.(model.Type))
|
||||
schemaType, ok := g.toSchemaType(destType)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
suffix := "Args"
|
||||
if g.usedInFunctionOutputVersionInputs[schemaType] {
|
||||
suffix = "InputArgs"
|
||||
}
|
||||
return g.argumentTypeNameWithSuffix(expr, destType, suffix)
|
||||
}
|
||||
|
||||
schemaType = codegen.UnwrapType(schemaType)
|
||||
func (g *generator) argumentTypeNameWithSuffix(expr model.Expression, destType model.Type, suffix string) string {
|
||||
schemaType, ok := g.toSchemaType(destType)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
|
||||
objType, ok := schemaType.(*schema.ObjectType)
|
||||
if !ok {
|
||||
|
@ -382,7 +403,7 @@ func (g *generator) argumentTypeName(expr model.Expression, destType model.Type)
|
|||
} else if qualifier != "" {
|
||||
namespace = namespace + "." + qualifier
|
||||
}
|
||||
member = member + "Args"
|
||||
member = member + suffix
|
||||
|
||||
return fmt.Sprintf("%s%s.%s", rootNamespace, namespace, Title(member))
|
||||
}
|
||||
|
|
|
@ -255,6 +255,28 @@ func (g *generator) genFunctionUsings(x *model.FunctionCallExpression) []string
|
|||
return []string{fmt.Sprintf("%s = Pulumi.%[1]s", pkg)}
|
||||
}
|
||||
|
||||
func (g *generator) markTypeAsUsedInFunctionOutputVersionInputs(t model.Type) {
|
||||
if g.usedInFunctionOutputVersionInputs == nil {
|
||||
g.usedInFunctionOutputVersionInputs = make(map[schema.Type]bool)
|
||||
}
|
||||
schemaType, ok := g.toSchemaType(t)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
g.usedInFunctionOutputVersionInputs[schemaType] = true
|
||||
}
|
||||
|
||||
func (g *generator) visitToMarkTypesUsedInFunctionOutputVersionInputs(expr model.Expression) {
|
||||
visitor := func(expr model.Expression) (model.Expression, hcl.Diagnostics) {
|
||||
isCons, _, t := pcl.RecognizeTypedObjectCons(expr)
|
||||
if isCons {
|
||||
g.markTypeAsUsedInFunctionOutputVersionInputs(t)
|
||||
}
|
||||
return expr, nil
|
||||
}
|
||||
model.VisitExpression(expr, nil, visitor) // nolint:errcheck
|
||||
}
|
||||
|
||||
func (g *generator) GenFunctionCallExpression(w io.Writer, expr *model.FunctionCallExpression) {
|
||||
switch expr.Name {
|
||||
case pcl.IntrinsicConvert:
|
||||
|
@ -294,10 +316,19 @@ func (g *generator) GenFunctionCallExpression(w io.Writer, expr *model.FunctionC
|
|||
case pcl.Invoke:
|
||||
_, name := g.functionName(expr.Args[0])
|
||||
|
||||
g.Fprintf(w, "%s.InvokeAsync(", name)
|
||||
if len(expr.Args) >= 2 {
|
||||
g.Fgenf(w, "%.v", expr.Args[1])
|
||||
isOut, outArgs, outArgsTy := pcl.RecognizeOutputVersionedInvoke(expr)
|
||||
if isOut {
|
||||
g.visitToMarkTypesUsedInFunctionOutputVersionInputs(outArgs)
|
||||
g.Fprintf(w, "%s.Invoke(", name)
|
||||
typeName := g.argumentTypeNameWithSuffix(expr, outArgsTy, "InvokeArgs")
|
||||
g.genObjectConsExpressionWithTypeName(w, outArgs, typeName)
|
||||
} else {
|
||||
g.Fprintf(w, "%s.InvokeAsync(", name)
|
||||
if len(expr.Args) >= 2 {
|
||||
g.Fgenf(w, "%.v", expr.Args[1])
|
||||
}
|
||||
}
|
||||
|
||||
if len(expr.Args) == 3 {
|
||||
g.Fgenf(w, ", %.v", expr.Args[2])
|
||||
}
|
||||
|
@ -446,7 +477,18 @@ func (g *generator) genObjectConsExpression(w io.Writer, expr *model.ObjectConsE
|
|||
return
|
||||
}
|
||||
|
||||
typeName := g.argumentTypeName(expr, destType)
|
||||
destTypeName := g.argumentTypeName(expr, destType)
|
||||
g.genObjectConsExpressionWithTypeName(w, expr, destTypeName)
|
||||
}
|
||||
|
||||
func (g *generator) genObjectConsExpressionWithTypeName(
|
||||
w io.Writer, expr *model.ObjectConsExpression, destTypeName string) {
|
||||
|
||||
if len(expr.Items) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
typeName := destTypeName
|
||||
if typeName != "" {
|
||||
g.Fgenf(w, "new %s", typeName)
|
||||
g.Fgenf(w, "\n%s{\n", g.Indent)
|
||||
|
|
|
@ -15,13 +15,12 @@
|
|||
package dotnet
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/v3/codegen"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// isReservedWord returns true if s is a C# reserved word as per
|
||||
|
@ -97,7 +96,7 @@ func makeSafeEnumName(name, typeName string) (string, error) {
|
|||
|
||||
// If the name is one illegal character, return an error.
|
||||
if len(safeName) == 1 && !isLegalIdentifierStart(rune(safeName[0])) {
|
||||
return "", errors.Errorf("enum name %s is not a valid identifier", safeName)
|
||||
return "", fmt.Errorf("enum name %s is not a valid identifier", safeName)
|
||||
}
|
||||
|
||||
// Capitalize and make a valid identifier.
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package dotnet
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMakeSafeEnumName(t *testing.T) {
|
||||
tests := []struct {
|
||||
|
|
|
@ -31,8 +31,6 @@ import (
|
|||
"strings"
|
||||
"unicode"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/v3/codegen"
|
||||
"github.com/pulumi/pulumi/pkg/v3/codegen/schema"
|
||||
"github.com/pulumi/pulumi/sdk/v3/go/common/diag"
|
||||
|
@ -116,6 +114,9 @@ type pkgContext struct {
|
|||
|
||||
// Determines if we should emit type registration code
|
||||
disableInputTypeRegistrations bool
|
||||
|
||||
// Determines if we should emit object defaults code
|
||||
disableObjectDefaults bool
|
||||
}
|
||||
|
||||
func (pkg *pkgContext) detailsForType(t schema.Type) *typeDetails {
|
||||
|
@ -271,6 +272,7 @@ func rawResourceName(r *schema.Resource) string {
|
|||
return tokenToName(r.Token)
|
||||
}
|
||||
|
||||
// If `nil` is a valid value of type `t`.
|
||||
func isNilType(t schema.Type) bool {
|
||||
switch t := t.(type) {
|
||||
case *schema.OptionalType, *schema.ArrayType, *schema.MapType, *schema.ResourceType, *schema.InputType:
|
||||
|
@ -297,23 +299,6 @@ func isNilType(t schema.Type) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// The default value for a Pulumi primitive type.
|
||||
func primitiveNilValue(t schema.Type) string {
|
||||
contract.Assert(schema.IsPrimitiveType(t))
|
||||
switch t {
|
||||
case schema.BoolType:
|
||||
return "false"
|
||||
case schema.IntType:
|
||||
return "0"
|
||||
case schema.NumberType:
|
||||
return "0.0"
|
||||
case schema.StringType:
|
||||
return "\"\""
|
||||
default:
|
||||
return "nil"
|
||||
}
|
||||
}
|
||||
|
||||
func (pkg *pkgContext) inputType(t schema.Type) (result string) {
|
||||
switch t := codegen.SimplifyInputUnion(t).(type) {
|
||||
case *schema.OptionalType:
|
||||
|
@ -515,7 +500,12 @@ func (pkg *pkgContext) typeStringImpl(t schema.Type, argsType bool) string {
|
|||
}
|
||||
|
||||
func (pkg *pkgContext) typeString(t schema.Type) string {
|
||||
return pkg.typeStringImpl(t, false)
|
||||
s := pkg.typeStringImpl(t, false)
|
||||
if s == "pulumi." {
|
||||
return "pulumi.Any"
|
||||
}
|
||||
return s
|
||||
|
||||
}
|
||||
|
||||
func (pkg *pkgContext) isExternalReference(t schema.Type) bool {
|
||||
|
@ -573,6 +563,10 @@ func (pkg *pkgContext) resolveObjectType(t *schema.ObjectType) string {
|
|||
}
|
||||
return name
|
||||
}
|
||||
return pkg.contextForExternalReferenceType(t).typeString(t)
|
||||
}
|
||||
|
||||
func (pkg *pkgContext) contextForExternalReferenceType(t *schema.ObjectType) *pkgContext {
|
||||
extPkg := t.Package
|
||||
var goInfo GoPackageInfo
|
||||
|
||||
|
@ -586,7 +580,7 @@ func (pkg *pkgContext) resolveObjectType(t *schema.ObjectType) string {
|
|||
pkgImportAliases: goInfo.PackageImportAliases,
|
||||
modToPkg: goInfo.ModuleToPackage,
|
||||
}
|
||||
return extPkgCtx.typeString(t)
|
||||
return extPkgCtx
|
||||
}
|
||||
|
||||
func (pkg *pkgContext) outputType(t schema.Type) string {
|
||||
|
@ -631,6 +625,9 @@ func (pkg *pkgContext) outputType(t schema.Type) string {
|
|||
}
|
||||
// TODO(pdg): union types
|
||||
return "pulumi.AnyOutput"
|
||||
case *schema.InputType:
|
||||
// We can't make output types for input types. We instead strip the input and try again.
|
||||
return pkg.outputType(t.ElementType)
|
||||
default:
|
||||
switch t {
|
||||
case schema.BoolType:
|
||||
|
@ -782,16 +779,14 @@ type genInputImplementationArgs struct {
|
|||
elementType string
|
||||
ptrMethods bool
|
||||
toOutputMethods bool
|
||||
resourceType bool
|
||||
}
|
||||
|
||||
func genInputImplementation(w io.Writer, name, receiverType, elementType string, ptrMethods, resourceType bool) {
|
||||
func genInputImplementation(w io.Writer, name, receiverType, elementType string, ptrMethods bool) {
|
||||
genInputImplementationWithArgs(w, genInputImplementationArgs{
|
||||
name: name,
|
||||
receiverType: receiverType,
|
||||
elementType: elementType,
|
||||
ptrMethods: ptrMethods,
|
||||
resourceType: resourceType,
|
||||
toOutputMethods: true,
|
||||
})
|
||||
}
|
||||
|
@ -800,14 +795,9 @@ func genInputImplementationWithArgs(w io.Writer, genArgs genInputImplementationA
|
|||
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)
|
||||
} else {
|
||||
fmt.Fprintf(w, "\treturn reflect.TypeOf((*%s)(nil)).Elem()\n", elementType)
|
||||
}
|
||||
fmt.Fprintf(w, "\treturn reflect.TypeOf((*%s)(nil)).Elem()\n", elementType)
|
||||
fmt.Fprintf(w, "}\n\n")
|
||||
|
||||
if genArgs.toOutputMethods {
|
||||
|
@ -835,15 +825,11 @@ func genInputImplementationWithArgs(w io.Writer, genArgs genInputImplementationA
|
|||
}
|
||||
}
|
||||
|
||||
func genOutputType(w io.Writer, baseName, elementType string, ptrMethods, resourceType bool) {
|
||||
func genOutputType(w io.Writer, baseName, elementType string, ptrMethods bool) {
|
||||
fmt.Fprintf(w, "type %sOutput struct { *pulumi.OutputState }\n\n", baseName)
|
||||
|
||||
fmt.Fprintf(w, "func (%sOutput) ElementType() reflect.Type {\n", baseName)
|
||||
if resourceType {
|
||||
fmt.Fprintf(w, "\treturn reflect.TypeOf((*%s)(nil))\n", elementType)
|
||||
} else {
|
||||
fmt.Fprintf(w, "\treturn reflect.TypeOf((*%s)(nil)).Elem()\n", elementType)
|
||||
}
|
||||
fmt.Fprintf(w, "\treturn reflect.TypeOf((*%s)(nil)).Elem()\n", elementType)
|
||||
fmt.Fprintf(w, "}\n\n")
|
||||
|
||||
fmt.Fprintf(w, "func (o %[1]sOutput) To%[2]sOutput() %[1]sOutput {\n", baseName, Title(baseName))
|
||||
|
@ -867,8 +853,8 @@ func genOutputType(w io.Writer, baseName, elementType string, ptrMethods, resour
|
|||
}
|
||||
}
|
||||
|
||||
func genArrayOutput(w io.Writer, baseName, elementType string, resourceType bool) {
|
||||
genOutputType(w, baseName+"Array", "[]"+elementType, false, resourceType)
|
||||
func genArrayOutput(w io.Writer, baseName, elementType string) {
|
||||
genOutputType(w, baseName+"Array", "[]"+elementType, false)
|
||||
|
||||
fmt.Fprintf(w, "func (o %[1]sArrayOutput) Index(i pulumi.IntInput) %[1]sOutput {\n", baseName)
|
||||
fmt.Fprintf(w, "\treturn pulumi.All(o, i).ApplyT(func (vs []interface{}) %s {\n", elementType)
|
||||
|
@ -877,8 +863,8 @@ func genArrayOutput(w io.Writer, baseName, elementType string, resourceType bool
|
|||
fmt.Fprintf(w, "}\n\n")
|
||||
}
|
||||
|
||||
func genMapOutput(w io.Writer, baseName, elementType string, resourceType bool) {
|
||||
genOutputType(w, baseName+"Map", "map[string]"+elementType, false, resourceType)
|
||||
func genMapOutput(w io.Writer, baseName, elementType string) {
|
||||
genOutputType(w, baseName+"Map", "map[string]"+elementType, false)
|
||||
|
||||
fmt.Fprintf(w, "func (o %[1]sMapOutput) MapIndex(k pulumi.StringInput) %[1]sOutput {\n", baseName)
|
||||
fmt.Fprintf(w, "\treturn pulumi.All(o, k).ApplyT(func (vs []interface{}) %s{\n", elementType)
|
||||
|
@ -887,8 +873,8 @@ func genMapOutput(w io.Writer, baseName, elementType string, resourceType bool)
|
|||
fmt.Fprintf(w, "}\n\n")
|
||||
}
|
||||
|
||||
func genPtrOutput(w io.Writer, baseName, elementType string, resourceType bool) {
|
||||
genOutputType(w, baseName+"Ptr", "*"+elementType, false, resourceType)
|
||||
func genPtrOutput(w io.Writer, baseName, elementType string) {
|
||||
genOutputType(w, baseName+"Ptr", "*"+elementType, false)
|
||||
|
||||
fmt.Fprintf(w, "func (o %[1]sPtrOutput) Elem() %[1]sOutput {\n", baseName)
|
||||
fmt.Fprintf(w, "\treturn o.ApplyT(func(v *%[1]s) %[1]s {\n", baseName)
|
||||
|
@ -954,7 +940,7 @@ func (pkg *pkgContext) genEnum(w io.Writer, enumType *schema.EnumType) error {
|
|||
|
||||
fmt.Fprintf(w, "type %[1]sArray []%[1]s\n\n", name)
|
||||
|
||||
genInputImplementation(w, name+"Array", name+"Array", "[]"+name, false, false)
|
||||
genInputImplementation(w, name+"Array", name+"Array", "[]"+name, false)
|
||||
}
|
||||
|
||||
// Generate the map input.
|
||||
|
@ -963,24 +949,24 @@ func (pkg *pkgContext) genEnum(w io.Writer, enumType *schema.EnumType) error {
|
|||
|
||||
fmt.Fprintf(w, "type %[1]sMap map[string]%[1]s\n\n", name)
|
||||
|
||||
genInputImplementation(w, name+"Map", name+"Map", "map[string]"+name, false, false)
|
||||
genInputImplementation(w, name+"Map", name+"Map", "map[string]"+name, false)
|
||||
}
|
||||
|
||||
// Generate the array output
|
||||
if details.arrayElement {
|
||||
genArrayOutput(w, name, name, false)
|
||||
genArrayOutput(w, name, name)
|
||||
}
|
||||
|
||||
// Generate the map output.
|
||||
if details.mapElement {
|
||||
genMapOutput(w, name, name, false)
|
||||
genMapOutput(w, name, name)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pkg *pkgContext) genEnumOutputTypes(w io.Writer, name, elementArgsType, elementGoType, asFuncName string) {
|
||||
genOutputType(w, name, name, true, false)
|
||||
genOutputType(w, name, name, true)
|
||||
|
||||
fmt.Fprintf(w, "func (o %[1]sOutput) To%[2]sOutput() %[3]sOutput {\n", name, asFuncName, elementArgsType)
|
||||
fmt.Fprintf(w, "return o.To%sOutputWithContext(context.Background())\n", asFuncName)
|
||||
|
@ -1003,7 +989,7 @@ func (pkg *pkgContext) genEnumOutputTypes(w io.Writer, name, elementArgsType, el
|
|||
fmt.Fprintf(w, "}).(%sPtrOutput)\n", elementArgsType)
|
||||
fmt.Fprint(w, "}\n\n")
|
||||
|
||||
genPtrOutput(w, name, name, false)
|
||||
genPtrOutput(w, name, name)
|
||||
|
||||
fmt.Fprintf(w, "func (o %[1]sPtrOutput) To%[2]sPtrOutput() %[3]sPtrOutput {\n", name, asFuncName, elementArgsType)
|
||||
fmt.Fprintf(w, "return o.To%sPtrOutputWithContext(context.Background())\n", asFuncName)
|
||||
|
@ -1105,6 +1091,27 @@ func (pkg *pkgContext) genEnumInputFuncs(w io.Writer, typeName string, enum *sch
|
|||
fmt.Fprintln(w)
|
||||
}
|
||||
|
||||
func (pkg *pkgContext) assignProperty(w io.Writer, p *schema.Property, object, value string, indirectAssign bool) {
|
||||
t := strings.TrimSuffix(pkg.typeString(p.Type), "Input")
|
||||
switch codegen.UnwrapType(p.Type).(type) {
|
||||
case *schema.EnumType:
|
||||
t = ""
|
||||
}
|
||||
|
||||
if codegen.IsNOptionalInput(p.Type) {
|
||||
if t != "" {
|
||||
value = fmt.Sprintf("%s(%s)", t, value)
|
||||
}
|
||||
fmt.Fprintf(w, "\targs.%s = %s\n", Title(p.Name), value)
|
||||
} else if indirectAssign {
|
||||
tmpName := camel(p.Name) + "_"
|
||||
fmt.Fprintf(w, "%s := %s\n", tmpName, value)
|
||||
fmt.Fprintf(w, "%s.%s = &%s\n", object, Title(p.Name), tmpName)
|
||||
} else {
|
||||
fmt.Fprintf(w, "%s.%s = %s\n", object, Title(p.Name), value)
|
||||
}
|
||||
}
|
||||
|
||||
func (pkg *pkgContext) genPlainType(w io.Writer, name, comment, deprecationMessage string,
|
||||
properties []*schema.Property) {
|
||||
|
||||
|
@ -1117,6 +1124,66 @@ func (pkg *pkgContext) genPlainType(w io.Writer, name, comment, deprecationMessa
|
|||
fmt.Fprintf(w, "}\n\n")
|
||||
}
|
||||
|
||||
func (pkg *pkgContext) genPlainObjectDefaultFunc(w io.Writer, name string,
|
||||
properties []*schema.Property) error {
|
||||
defaults := []*schema.Property{}
|
||||
for _, p := range properties {
|
||||
if p.DefaultValue != nil || codegen.IsProvideDefaultsFuncRequired(p.Type) {
|
||||
defaults = append(defaults, p)
|
||||
}
|
||||
}
|
||||
|
||||
// There are no defaults, so we don't need to generate a defaults function.
|
||||
if len(defaults) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
printComment(w, fmt.Sprintf("%s sets the appropriate defaults for %s", ProvideDefaultsMethodName, name), false)
|
||||
fmt.Fprintf(w, "func (val *%[1]s) %[2]s() *%[1]s {\n", name, ProvideDefaultsMethodName)
|
||||
fmt.Fprint(w, "if val == nil {\n return nil\n}\n")
|
||||
fmt.Fprint(w, "tmp := *val\n")
|
||||
for _, p := range defaults {
|
||||
if p.DefaultValue != nil {
|
||||
dv, err := pkg.getDefaultValue(p.DefaultValue, codegen.UnwrapType(p.Type))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pkg.needsUtils = true
|
||||
fmt.Fprintf(w, "if isZero(tmp.%s) {\n", Title(p.Name))
|
||||
pkg.assignProperty(w, p, "tmp", dv, !p.IsRequired())
|
||||
fmt.Fprintf(w, "}\n")
|
||||
} else if funcName := pkg.provideDefaultsFuncName(p.Type); funcName != "" {
|
||||
var member string
|
||||
if codegen.IsNOptionalInput(p.Type) {
|
||||
f := fmt.Sprintf("func(v %[1]s) %[1]s { return v.%[2]s*() }", name, funcName)
|
||||
member = fmt.Sprintf("tmp.%[1]s.ApplyT(%[2]s)\n", Title(p.Name), f)
|
||||
} else {
|
||||
member = fmt.Sprintf("tmp.%[1]s.%[2]s()\n", Title(p.Name), funcName)
|
||||
}
|
||||
sigil := ""
|
||||
if p.IsRequired() {
|
||||
sigil = "*"
|
||||
}
|
||||
pkg.assignProperty(w, p, "tmp", sigil+member, false)
|
||||
} else {
|
||||
panic(fmt.Sprintf("Property %s[%s] should not be in the default list", p.Name, p.Type.String()))
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, "return &tmp\n}\n")
|
||||
return nil
|
||||
}
|
||||
|
||||
// The name of the method used to instantiate defaults.
|
||||
const ProvideDefaultsMethodName = "Defaults"
|
||||
|
||||
func (pkg *pkgContext) provideDefaultsFuncName(typ schema.Type) string {
|
||||
if !codegen.IsProvideDefaultsFuncRequired(typ) {
|
||||
return ""
|
||||
}
|
||||
return ProvideDefaultsMethodName
|
||||
}
|
||||
|
||||
func (pkg *pkgContext) genInputTypes(w io.Writer, t *schema.ObjectType, details *typeDetails) {
|
||||
contract.Assert(t.IsInputShape())
|
||||
|
||||
|
@ -1127,7 +1194,7 @@ func (pkg *pkgContext) genInputTypes(w io.Writer, t *schema.ObjectType, details
|
|||
|
||||
pkg.genInputArgsStruct(w, name+"Args", t)
|
||||
|
||||
genInputImplementation(w, name, name+"Args", name, details.ptrElement, false)
|
||||
genInputImplementation(w, name, name+"Args", name, details.ptrElement)
|
||||
|
||||
// Generate the pointer input.
|
||||
if details.ptrElement {
|
||||
|
@ -1141,7 +1208,7 @@ func (pkg *pkgContext) genInputTypes(w io.Writer, t *schema.ObjectType, details
|
|||
fmt.Fprintf(w, "\treturn (*%s)(v)\n", ptrTypeName)
|
||||
fmt.Fprintf(w, "}\n\n")
|
||||
|
||||
genInputImplementation(w, name+"Ptr", "*"+ptrTypeName, "*"+name, false, false)
|
||||
genInputImplementation(w, name+"Ptr", "*"+ptrTypeName, "*"+name, false)
|
||||
}
|
||||
|
||||
// Generate the array input.
|
||||
|
@ -1150,7 +1217,7 @@ func (pkg *pkgContext) genInputTypes(w io.Writer, t *schema.ObjectType, details
|
|||
|
||||
fmt.Fprintf(w, "type %[1]sArray []%[1]sInput\n\n", name)
|
||||
|
||||
genInputImplementation(w, name+"Array", name+"Array", "[]"+name, false, false)
|
||||
genInputImplementation(w, name+"Array", name+"Array", "[]"+name, false)
|
||||
}
|
||||
|
||||
// Generate the map input.
|
||||
|
@ -1159,7 +1226,7 @@ func (pkg *pkgContext) genInputTypes(w io.Writer, t *schema.ObjectType, details
|
|||
|
||||
fmt.Fprintf(w, "type %[1]sMap map[string]%[1]sInput\n\n", name)
|
||||
|
||||
genInputImplementation(w, name+"Map", name+"Map", "map[string]"+name, false, false)
|
||||
genInputImplementation(w, name+"Map", name+"Map", "map[string]"+name, false)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1198,7 +1265,6 @@ func (pkg *pkgContext) genOutputTypes(w io.Writer, genArgs genOutputTypesArgs) {
|
|||
name, /* baseName */
|
||||
name, /* elementType */
|
||||
details.ptrElement, /* ptrMethods */
|
||||
false, /* resourceType */
|
||||
)
|
||||
|
||||
for _, p := range t.Properties {
|
||||
|
@ -1217,7 +1283,7 @@ func (pkg *pkgContext) genOutputTypes(w io.Writer, genArgs genOutputTypesArgs) {
|
|||
}
|
||||
|
||||
if details.ptrElement {
|
||||
genPtrOutput(w, name, name, false)
|
||||
genPtrOutput(w, name, name)
|
||||
|
||||
for _, p := range t.Properties {
|
||||
printCommentWithDeprecationMessage(w, p.Comment, p.DeprecationMessage, false)
|
||||
|
@ -1250,11 +1316,11 @@ func (pkg *pkgContext) genOutputTypes(w io.Writer, genArgs genOutputTypesArgs) {
|
|||
}
|
||||
|
||||
if details.arrayElement {
|
||||
genArrayOutput(w, name, name, false)
|
||||
genArrayOutput(w, name, name)
|
||||
}
|
||||
|
||||
if details.mapElement {
|
||||
genMapOutput(w, name, name, false)
|
||||
genMapOutput(w, name, name)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1283,7 +1349,7 @@ func goPrimitiveValue(value interface{}) (string, error) {
|
|||
case reflect.String:
|
||||
return fmt.Sprintf("%q", v.String()), nil
|
||||
default:
|
||||
return "", errors.Errorf("unsupported default value of type %T", value)
|
||||
return "", fmt.Errorf("unsupported default value of type %T", value)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1308,6 +1374,11 @@ func (pkg *pkgContext) getDefaultValue(dv *schema.DefaultValue, t schema.Type) (
|
|||
return "", err
|
||||
}
|
||||
val = v
|
||||
switch t.(type) {
|
||||
case *schema.EnumType:
|
||||
typeName := strings.TrimSuffix(pkg.typeString(codegen.UnwrapType(t)), "Input")
|
||||
val = fmt.Sprintf("%s(%s)", typeName, val)
|
||||
}
|
||||
}
|
||||
|
||||
if len(dv.Environment) > 0 {
|
||||
|
@ -1391,6 +1462,8 @@ func (pkg *pkgContext) genResource(w io.Writer, r *schema.Resource, generateReso
|
|||
fmt.Fprintf(w, "\t}\n\n")
|
||||
|
||||
// Produce the inputs.
|
||||
|
||||
// Check all required inputs are present
|
||||
for _, p := range r.InputProperties {
|
||||
if p.IsRequired() && isNilType(p.Type) && p.DefaultValue == nil {
|
||||
fmt.Fprintf(w, "\tif args.%s == nil {\n", Title(p.Name))
|
||||
|
@ -1399,26 +1472,8 @@ func (pkg *pkgContext) genResource(w io.Writer, r *schema.Resource, generateReso
|
|||
}
|
||||
}
|
||||
|
||||
assign := func(p *schema.Property, value string, indentation int) {
|
||||
ind := strings.Repeat("\t", indentation)
|
||||
t := strings.TrimSuffix(pkg.typeString(p.Type), "Input")
|
||||
switch codegen.UnwrapType(p.Type).(type) {
|
||||
case *schema.EnumType:
|
||||
t = strings.TrimSuffix(t, "Ptr")
|
||||
}
|
||||
if t == "pulumi." {
|
||||
t = "pulumi.Any"
|
||||
}
|
||||
|
||||
if codegen.IsNOptionalInput(p.Type) {
|
||||
fmt.Fprintf(w, "\targs.%s = %s(%s)\n", Title(p.Name), t, value)
|
||||
} else if isNilType(p.Type) {
|
||||
tmpName := camel(p.Name) + "_"
|
||||
fmt.Fprintf(w, "%s%s := %s\n", ind, tmpName, value)
|
||||
fmt.Fprintf(w, "%sargs.%s = &%s\n", ind, Title(p.Name), tmpName)
|
||||
} else {
|
||||
fmt.Fprintf(w, "%sargs.%s = %s\n", ind, Title(p.Name), value)
|
||||
}
|
||||
assign := func(p *schema.Property, value string) {
|
||||
pkg.assignProperty(w, p, "args", value, isNilType(p.Type))
|
||||
}
|
||||
|
||||
for _, p := range r.InputProperties {
|
||||
|
@ -1427,19 +1482,51 @@ func (pkg *pkgContext) genResource(w io.Writer, r *schema.Resource, generateReso
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
assign(p, v, 1)
|
||||
assign(p, v)
|
||||
} else if p.DefaultValue != nil {
|
||||
v, err := pkg.getDefaultValue(p.DefaultValue, codegen.UnwrapType(p.Type))
|
||||
dv, err := pkg.getDefaultValue(p.DefaultValue, codegen.UnwrapType(p.Type))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defaultComp := "nil"
|
||||
if !codegen.IsNOptionalInput(p.Type) && !isNilType(p.Type) {
|
||||
defaultComp = primitiveNilValue(p.Type)
|
||||
}
|
||||
fmt.Fprintf(w, "\tif args.%s == %s {\n", Title(p.Name), defaultComp)
|
||||
assign(p, v, 2)
|
||||
pkg.needsUtils = true
|
||||
fmt.Fprintf(w, "\tif isZero(args.%s) {\n", Title(p.Name))
|
||||
assign(p, dv)
|
||||
fmt.Fprintf(w, "\t}\n")
|
||||
} else if name := pkg.provideDefaultsFuncName(p.Type); name != "" && !pkg.disableObjectDefaults {
|
||||
var value string
|
||||
var needsNilCheck bool
|
||||
if codegen.IsNOptionalInput(p.Type) {
|
||||
innerFuncType := strings.TrimSuffix(pkg.typeString(codegen.UnwrapType(p.Type)), "Args")
|
||||
applyName := fmt.Sprintf("%sApplier", camel(p.Name))
|
||||
fmt.Fprintf(w, "%[3]s := func(v %[1]s) *%[1]s { return v.%[2]s() }\n", innerFuncType, name, applyName)
|
||||
|
||||
outputValue := pkg.convertToOutput(fmt.Sprintf("args.%s", Title(p.Name)), p.Type)
|
||||
outputType := pkg.typeString(p.Type)
|
||||
if strings.HasSuffix(outputType, "Input") {
|
||||
outputType = strings.TrimSuffix(outputType, "Input") + "Output"
|
||||
}
|
||||
|
||||
// Because applies return pointers, we need to convert to PtrOutput and then call .Elem().
|
||||
var tail string
|
||||
if !strings.HasSuffix(outputType, "PtrOutput") {
|
||||
outputType = strings.TrimSuffix(outputType, "Output") + "PtrOutput"
|
||||
tail = ".Elem()"
|
||||
}
|
||||
needsNilCheck = !p.IsRequired()
|
||||
value = fmt.Sprintf("%s.ApplyT(%s).(%s)%s", outputValue, applyName, outputType, tail)
|
||||
} else {
|
||||
value = fmt.Sprintf("args.%[1]s.%[2]s()", Title(p.Name), name)
|
||||
}
|
||||
v := func() {
|
||||
fmt.Fprintf(w, "args.%[1]s = %s\n", Title(p.Name), value)
|
||||
}
|
||||
if needsNilCheck {
|
||||
fmt.Fprintf(w, "if args.%s != nil {\n", Title(p.Name))
|
||||
v()
|
||||
fmt.Fprint(w, "}\n")
|
||||
} else {
|
||||
v()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1706,42 +1793,26 @@ func (pkg *pkgContext) genResource(w io.Writer, r *schema.Resource, generateReso
|
|||
fmt.Fprintf(w, "\tTo%[1]sOutputWithContext(ctx context.Context) %[1]sOutput\n", name)
|
||||
fmt.Fprintf(w, "}\n\n")
|
||||
|
||||
genInputImplementation(w, name, "*"+name, name, generateResourceContainerTypes, true)
|
||||
genInputImplementation(w, name, "*"+name, "*"+name, false)
|
||||
|
||||
if generateResourceContainerTypes {
|
||||
// Emit the resource pointer input type.
|
||||
fmt.Fprintf(w, "type %sPtrInput interface {\n", name)
|
||||
fmt.Fprintf(w, "\tpulumi.Input\n\n")
|
||||
fmt.Fprintf(w, "\tTo%[1]sPtrOutput() %[1]sPtrOutput\n", name)
|
||||
fmt.Fprintf(w, "\tTo%[1]sPtrOutputWithContext(ctx context.Context) %[1]sPtrOutput\n", name)
|
||||
fmt.Fprintf(w, "}\n\n")
|
||||
ptrTypeName := camel(name) + "PtrType"
|
||||
fmt.Fprintf(w, "type %s %sArgs\n\n", ptrTypeName, name)
|
||||
genInputImplementation(w, name+"Ptr", "*"+ptrTypeName, "*"+name, false, true)
|
||||
if generateResourceContainerTypes && !r.IsProvider {
|
||||
// Generate the resource array input.
|
||||
pkg.genInputInterface(w, name+"Array")
|
||||
fmt.Fprintf(w, "type %[1]sArray []%[1]sInput\n\n", name)
|
||||
genInputImplementation(w, name+"Array", name+"Array", "[]*"+name, false)
|
||||
|
||||
if !r.IsProvider {
|
||||
// Generate the resource array input.
|
||||
pkg.genInputInterface(w, name+"Array")
|
||||
fmt.Fprintf(w, "type %[1]sArray []%[1]sInput\n\n", name)
|
||||
genInputImplementation(w, name+"Array", name+"Array", "[]*"+name, false, false)
|
||||
|
||||
// Generate the resource map input.
|
||||
pkg.genInputInterface(w, name+"Map")
|
||||
fmt.Fprintf(w, "type %[1]sMap map[string]%[1]sInput\n\n", name)
|
||||
genInputImplementation(w, name+"Map", name+"Map", "map[string]*"+name, false, false)
|
||||
}
|
||||
// Generate the resource map input.
|
||||
pkg.genInputInterface(w, name+"Map")
|
||||
fmt.Fprintf(w, "type %[1]sMap map[string]%[1]sInput\n\n", name)
|
||||
genInputImplementation(w, name+"Map", name+"Map", "map[string]*"+name, false)
|
||||
}
|
||||
|
||||
// Emit the resource output type.
|
||||
genOutputType(w, name, name, generateResourceContainerTypes, true)
|
||||
genOutputType(w, name, "*"+name, false)
|
||||
|
||||
if generateResourceContainerTypes {
|
||||
genPtrOutput(w, name, name, true)
|
||||
|
||||
if !r.IsProvider {
|
||||
genArrayOutput(w, name, name, true)
|
||||
genMapOutput(w, name, name, true)
|
||||
}
|
||||
if generateResourceContainerTypes && !r.IsProvider {
|
||||
genArrayOutput(w, name, "*"+name)
|
||||
genMapOutput(w, name, "*"+name)
|
||||
}
|
||||
|
||||
pkg.genResourceRegistrations(w, r, generateResourceContainerTypes)
|
||||
|
@ -1749,6 +1820,30 @@ func (pkg *pkgContext) genResource(w io.Writer, r *schema.Resource, generateReso
|
|||
return nil
|
||||
}
|
||||
|
||||
// Takes an expression and type, and returns a string that converts that expression to an Output type.
|
||||
//
|
||||
// Examples:
|
||||
// ("bar", Foo of ObjectType) => "bar.ToFooOutput()"
|
||||
// ("id", FooOutput) => "id"
|
||||
// ("ptr", FooInput of ObjectType) => "ptr.ToFooPtrOutput().Elem()"
|
||||
func (pkg *pkgContext) convertToOutput(expr string, typ schema.Type) string {
|
||||
elemConversion := ""
|
||||
switch typ.(type) {
|
||||
case *schema.OptionalType:
|
||||
elemConversion = ".Elem()"
|
||||
}
|
||||
outputType := pkg.outputType(typ)
|
||||
// Remove any element before the last .
|
||||
outputType = outputType[strings.LastIndex(outputType, ".")+1:]
|
||||
if strings.HasSuffix(outputType, "ArgsOutput") {
|
||||
outputType = strings.TrimSuffix(outputType, "ArgsOutput") + "Output"
|
||||
}
|
||||
if elemConversion != "" {
|
||||
outputType = strings.TrimSuffix(outputType, "Output") + "PtrOutput"
|
||||
}
|
||||
return fmt.Sprintf("%s.To%s()%s", expr, outputType, elemConversion)
|
||||
}
|
||||
|
||||
func NeedsGoOutputVersion(f *schema.Function) bool {
|
||||
fPkg := f.Package
|
||||
|
||||
|
@ -1766,7 +1861,7 @@ func NeedsGoOutputVersion(f *schema.Function) bool {
|
|||
return f.NeedsOutputVersion()
|
||||
}
|
||||
|
||||
func (pkg *pkgContext) genFunctionCodeFile(f *schema.Function) string {
|
||||
func (pkg *pkgContext) genFunctionCodeFile(f *schema.Function) (string, error) {
|
||||
importsAndAliases := map[string]string{}
|
||||
pkg.getImports(f, importsAndAliases)
|
||||
buffer := &bytes.Buffer{}
|
||||
|
@ -1777,12 +1872,14 @@ func (pkg *pkgContext) genFunctionCodeFile(f *schema.Function) string {
|
|||
}
|
||||
|
||||
pkg.genHeader(buffer, imports, importsAndAliases)
|
||||
pkg.genFunction(buffer, f)
|
||||
if err := pkg.genFunction(buffer, f); err != nil {
|
||||
return "", err
|
||||
}
|
||||
pkg.genFunctionOutputVersion(buffer, f)
|
||||
return buffer.String()
|
||||
return buffer.String(), nil
|
||||
}
|
||||
|
||||
func (pkg *pkgContext) genFunction(w io.Writer, f *schema.Function) {
|
||||
func (pkg *pkgContext) genFunction(w io.Writer, f *schema.Function) error {
|
||||
name := pkg.functionName(f)
|
||||
printCommentWithDeprecationMessage(w, f.Comment, f.DeprecationMessage, false)
|
||||
|
||||
|
@ -1803,6 +1900,8 @@ func (pkg *pkgContext) genFunction(w io.Writer, f *schema.Function) {
|
|||
var inputsVar string
|
||||
if f.Inputs == nil {
|
||||
inputsVar = "nil"
|
||||
} else if codegen.IsProvideDefaultsFuncRequired(f.Inputs) && !pkg.disableObjectDefaults {
|
||||
inputsVar = "args.Defaults()"
|
||||
} else {
|
||||
inputsVar = "args"
|
||||
}
|
||||
|
@ -1826,19 +1925,38 @@ func (pkg *pkgContext) genFunction(w io.Writer, f *schema.Function) {
|
|||
fmt.Fprintf(w, "\t}\n")
|
||||
|
||||
// Return the result.
|
||||
fmt.Fprintf(w, "\treturn &rv, nil\n")
|
||||
var retValue string
|
||||
if codegen.IsProvideDefaultsFuncRequired(f.Outputs) && !pkg.disableObjectDefaults {
|
||||
retValue = "rv.Defaults()"
|
||||
} else {
|
||||
retValue = "&rv"
|
||||
}
|
||||
fmt.Fprintf(w, "\treturn %s, nil\n", retValue)
|
||||
}
|
||||
fmt.Fprintf(w, "}\n")
|
||||
|
||||
// If there are argument and/or return types, emit them.
|
||||
if f.Inputs != nil {
|
||||
fmt.Fprintf(w, "\n")
|
||||
pkg.genPlainType(w, pkg.functionArgsTypeName(f), f.Inputs.Comment, "", f.Inputs.Properties)
|
||||
fnInputsName := pkg.functionArgsTypeName(f)
|
||||
pkg.genPlainType(w, fnInputsName, f.Inputs.Comment, "", f.Inputs.Properties)
|
||||
if codegen.IsProvideDefaultsFuncRequired(f.Inputs) && !pkg.disableObjectDefaults {
|
||||
if err := pkg.genPlainObjectDefaultFunc(w, fnInputsName, f.Inputs.Properties); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
if f.Outputs != nil {
|
||||
fmt.Fprintf(w, "\n")
|
||||
pkg.genPlainType(w, pkg.functionResultTypeName(f), f.Outputs.Comment, "", f.Outputs.Properties)
|
||||
fnOutputsName := pkg.functionResultTypeName(f)
|
||||
pkg.genPlainType(w, fnOutputsName, f.Outputs.Comment, "", f.Outputs.Properties)
|
||||
if codegen.IsProvideDefaultsFuncRequired(f.Outputs) && !pkg.disableObjectDefaults {
|
||||
if err := pkg.genPlainObjectDefaultFunc(w, fnOutputsName, f.Outputs.Properties); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pkg *pkgContext) functionName(f *schema.Function) string {
|
||||
|
@ -2017,12 +2135,24 @@ func rewriteCyclicObjectFields(pkg *schema.Package) {
|
|||
}
|
||||
}
|
||||
|
||||
func (pkg *pkgContext) genType(w io.Writer, obj *schema.ObjectType) {
|
||||
func (pkg *pkgContext) genType(w io.Writer, obj *schema.ObjectType) error {
|
||||
contract.Assert(!obj.IsInputShape())
|
||||
if obj.IsOverlay {
|
||||
// This type is generated by the provider, so no further action is required.
|
||||
return nil
|
||||
}
|
||||
|
||||
plainName := pkg.tokenToType(obj.Token)
|
||||
pkg.genPlainType(w, plainName, obj.Comment, "", obj.Properties)
|
||||
if !pkg.disableObjectDefaults {
|
||||
if err := pkg.genPlainObjectDefaultFunc(w, plainName, obj.Properties); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
pkg.genPlainType(w, pkg.tokenToType(obj.Token), obj.Comment, "", obj.Properties)
|
||||
pkg.genInputTypes(w, obj.InputShape, pkg.detailsForType(obj))
|
||||
pkg.genOutputTypes(w, genOutputTypesArgs{t: obj})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pkg *pkgContext) addSuffixesToName(typ schema.Type, name string) []string {
|
||||
|
@ -2094,16 +2224,16 @@ func (pkg *pkgContext) genNestedCollectionTypes(w io.Writer, types map[string]ma
|
|||
names = append(names, name)
|
||||
if strings.HasSuffix(name, "Array") {
|
||||
fmt.Fprintf(w, "type %s []%sInput\n\n", name, elementTypeName)
|
||||
genInputImplementation(w, name, name, elementTypeName, false, false)
|
||||
genInputImplementation(w, name, name, elementTypeName, false)
|
||||
|
||||
genArrayOutput(w, strings.TrimSuffix(name, "Array"), elementTypeName, false)
|
||||
genArrayOutput(w, strings.TrimSuffix(name, "Array"), elementTypeName)
|
||||
}
|
||||
|
||||
if strings.HasSuffix(name, "Map") {
|
||||
fmt.Fprintf(w, "type %s map[string]%sInput\n\n", name, elementTypeName)
|
||||
genInputImplementation(w, name, name, elementTypeName, false, false)
|
||||
genInputImplementation(w, name, name, elementTypeName, false)
|
||||
|
||||
genMapOutput(w, strings.TrimSuffix(name, "Map"), elementTypeName, false)
|
||||
genMapOutput(w, strings.TrimSuffix(name, "Map"), elementTypeName)
|
||||
}
|
||||
pkg.genInputInterface(w, name)
|
||||
}
|
||||
|
@ -2130,6 +2260,10 @@ func (pkg *pkgContext) genTypeRegistrations(w io.Writer, objTypes []*schema.Obje
|
|||
// Input types.
|
||||
if !pkg.disableInputTypeRegistrations {
|
||||
for _, obj := range objTypes {
|
||||
if obj.IsOverlay {
|
||||
// This type is generated by the provider, so no further action is required.
|
||||
continue
|
||||
}
|
||||
name, details := pkg.tokenToType(obj.Token), pkg.detailsForType(obj)
|
||||
fmt.Fprintf(w, "\tpulumi.RegisterInputType(reflect.TypeOf((*%[1]sInput)(nil)).Elem(), %[1]sArgs{})\n", name)
|
||||
if details.ptrElement {
|
||||
|
@ -2152,6 +2286,10 @@ func (pkg *pkgContext) genTypeRegistrations(w io.Writer, objTypes []*schema.Obje
|
|||
|
||||
// Output types.
|
||||
for _, obj := range objTypes {
|
||||
if obj.IsOverlay {
|
||||
// This type is generated by the provider, so no further action is required.
|
||||
continue
|
||||
}
|
||||
name, details := pkg.tokenToType(obj.Token), pkg.detailsForType(obj)
|
||||
fmt.Fprintf(w, "\tpulumi.RegisterOutputType(%sOutput{})\n", name)
|
||||
if details.ptrElement {
|
||||
|
@ -2222,18 +2360,13 @@ func (pkg *pkgContext) genResourceRegistrations(w io.Writer, r *schema.Resource,
|
|||
fmt.Fprintf(w,
|
||||
"\tpulumi.RegisterInputType(reflect.TypeOf((*%[1]sInput)(nil)).Elem(), &%[1]s{})\n",
|
||||
name)
|
||||
if generateResourceContainerTypes {
|
||||
if generateResourceContainerTypes && !r.IsProvider {
|
||||
fmt.Fprintf(w,
|
||||
"\tpulumi.RegisterInputType(reflect.TypeOf((*%[1]sPtrInput)(nil)).Elem(), &%[1]s{})\n",
|
||||
"\tpulumi.RegisterInputType(reflect.TypeOf((*%[1]sArrayInput)(nil)).Elem(), %[1]sArray{})\n",
|
||||
name)
|
||||
fmt.Fprintf(w,
|
||||
"\tpulumi.RegisterInputType(reflect.TypeOf((*%[1]sMapInput)(nil)).Elem(), %[1]sMap{})\n",
|
||||
name)
|
||||
if !r.IsProvider {
|
||||
fmt.Fprintf(w,
|
||||
"\tpulumi.RegisterInputType(reflect.TypeOf((*%[1]sArrayInput)(nil)).Elem(), %[1]sArray{})\n",
|
||||
name)
|
||||
fmt.Fprintf(w,
|
||||
"\tpulumi.RegisterInputType(reflect.TypeOf((*%[1]sMapInput)(nil)).Elem(), %[1]sMap{})\n",
|
||||
name)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Register all output types
|
||||
|
@ -2248,12 +2381,9 @@ func (pkg *pkgContext) genResourceRegistrations(w io.Writer, r *schema.Resource,
|
|||
}
|
||||
}
|
||||
|
||||
if generateResourceContainerTypes {
|
||||
fmt.Fprintf(w, "\tpulumi.RegisterOutputType(%sPtrOutput{})\n", name)
|
||||
if !r.IsProvider {
|
||||
fmt.Fprintf(w, "\tpulumi.RegisterOutputType(%sArrayOutput{})\n", name)
|
||||
fmt.Fprintf(w, "\tpulumi.RegisterOutputType(%sMapOutput{})\n", name)
|
||||
}
|
||||
if generateResourceContainerTypes && !r.IsProvider {
|
||||
fmt.Fprintf(w, "\tpulumi.RegisterOutputType(%sArrayOutput{})\n", name)
|
||||
fmt.Fprintf(w, "\tpulumi.RegisterOutputType(%sMapOutput{})\n", name)
|
||||
}
|
||||
fmt.Fprintf(w, "}\n\n")
|
||||
}
|
||||
|
@ -2510,6 +2640,17 @@ func (pkg *pkgContext) genConfig(w io.Writer, variables []*schema.Property) erro
|
|||
// definition and its registration to support rehydrating providers.
|
||||
func (pkg *pkgContext) genResourceModule(w io.Writer) {
|
||||
contract.Assert(len(pkg.resources) != 0)
|
||||
allResourcesAreOverlays := true
|
||||
for _, r := range pkg.resources {
|
||||
if !r.IsOverlay {
|
||||
allResourcesAreOverlays = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if allResourcesAreOverlays {
|
||||
// If all resources in this module are overlays, skip further code generation.
|
||||
return
|
||||
}
|
||||
|
||||
basePath := pkg.importBasePath
|
||||
|
||||
|
@ -2545,6 +2686,10 @@ func (pkg *pkgContext) genResourceModule(w io.Writer) {
|
|||
fmt.Fprintf(w, "func (m *module) Construct(ctx *pulumi.Context, name, typ, urn string) (r pulumi.Resource, err error) {\n")
|
||||
fmt.Fprintf(w, "\tswitch typ {\n")
|
||||
for _, r := range pkg.resources {
|
||||
if r.IsOverlay {
|
||||
// This resource code is generated by the provider, so no further action is required.
|
||||
continue
|
||||
}
|
||||
if r.IsProvider {
|
||||
contract.Assert(provider == nil)
|
||||
provider = r
|
||||
|
@ -2641,6 +2786,7 @@ func generatePackageContextMap(tool string, pkg *schema.Package, goInfo GoPackag
|
|||
packages: packages,
|
||||
liftSingleValueMethodReturns: goInfo.LiftSingleValueMethodReturns,
|
||||
disableInputTypeRegistrations: goInfo.DisableInputTypeRegistrations,
|
||||
disableObjectDefaults: goInfo.DisableObjectDefaults,
|
||||
}
|
||||
packages[mod] = pack
|
||||
}
|
||||
|
@ -2744,8 +2890,10 @@ func generatePackageContextMap(tool string, pkg *schema.Package, goInfo GoPackag
|
|||
}
|
||||
populateDetailsForPropertyTypes(seenMap, typ.Properties, false)
|
||||
case *schema.EnumType:
|
||||
pkg := getPkgFromToken(typ.Token)
|
||||
pkg.enums = append(pkg.enums, typ)
|
||||
if !typ.IsOverlay {
|
||||
pkg := getPkgFromToken(typ.Token)
|
||||
pkg.enums = append(pkg.enums, typ)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2962,8 +3110,10 @@ func generatePackageContextMap(tool string, pkg *schema.Package, goInfo GoPackag
|
|||
pkg.functions = append(pkg.functions, f)
|
||||
|
||||
name := tokenToName(f.Token)
|
||||
originalName := name
|
||||
if pkg.names.Has(name) {
|
||||
|
||||
if pkg.names.Has(name) ||
|
||||
pkg.names.Has(name+"Args") ||
|
||||
pkg.names.Has(name+"Result") {
|
||||
switch {
|
||||
case strings.HasPrefix(name, "New"):
|
||||
name = "Create" + name[3:]
|
||||
|
@ -2976,15 +3126,9 @@ func generatePackageContextMap(tool string, pkg *schema.Package, goInfo GoPackag
|
|||
|
||||
if f.Inputs != nil {
|
||||
pkg.names.Add(name + "Args")
|
||||
if originalName != name {
|
||||
pkg.renamed[originalName+"Args"] = name + "Args"
|
||||
}
|
||||
}
|
||||
if f.Outputs != nil {
|
||||
pkg.names.Add(name + "Result")
|
||||
if originalName != name {
|
||||
pkg.renamed[originalName+"Result"] = name + "Result"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3029,6 +3173,11 @@ func LanguageResources(tool string, pkg *schema.Package) (map[string]LanguageRes
|
|||
pkg := packages[mod]
|
||||
|
||||
for _, r := range pkg.resources {
|
||||
if r.IsOverlay {
|
||||
// This resource code is generated by the provider, so no further action is required.
|
||||
continue
|
||||
}
|
||||
|
||||
packagePath := path.Join(goPkgInfo.ImportBasePath, pkg.mod)
|
||||
resources[r.Token] = LanguageResource{
|
||||
Resource: r,
|
||||
|
@ -3098,14 +3247,14 @@ func GeneratePackage(tool string, pkg *schema.Package) (map[string][]byte, error
|
|||
setFile := func(relPath, contents string) {
|
||||
relPath = path.Join(pathPrefix, relPath)
|
||||
if _, ok := files[relPath]; ok {
|
||||
panic(errors.Errorf("duplicate file: %s", relPath))
|
||||
panic(fmt.Errorf("duplicate file: %s", relPath))
|
||||
}
|
||||
|
||||
// Run Go formatter on the code before saving to disk
|
||||
formattedSource, err := format.Source([]byte(contents))
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Invalid content:\n%s\n%s\n", relPath, contents)
|
||||
panic(errors.Wrapf(err, "invalid Go source code:\n\n%s\n", relPath))
|
||||
panic(fmt.Errorf("invalid Go source code:\n\n%s\n: %w", relPath, err))
|
||||
}
|
||||
|
||||
files[relPath] = formattedSource
|
||||
|
@ -3142,6 +3291,11 @@ func GeneratePackage(tool string, pkg *schema.Package) (map[string][]byte, error
|
|||
|
||||
// Resources
|
||||
for _, r := range pkg.resources {
|
||||
if r.IsOverlay {
|
||||
// This resource code is generated by the provider, so no further action is required.
|
||||
continue
|
||||
}
|
||||
|
||||
importsAndAliases := map[string]string{}
|
||||
pkg.getImports(r, importsAndAliases)
|
||||
|
||||
|
@ -3157,8 +3311,16 @@ func GeneratePackage(tool string, pkg *schema.Package) (map[string][]byte, error
|
|||
|
||||
// Functions
|
||||
for _, f := range pkg.functions {
|
||||
if f.IsOverlay {
|
||||
// This function code is generated by the provider, so no further action is required.
|
||||
continue
|
||||
}
|
||||
|
||||
fileName := path.Join(mod, camel(tokenToName(f.Token))+".go")
|
||||
code := pkg.genFunctionCodeFile(f)
|
||||
code, err := pkg.genFunctionCodeFile(f)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
setFile(fileName, code)
|
||||
}
|
||||
|
||||
|
@ -3198,7 +3360,9 @@ func GeneratePackage(tool string, pkg *schema.Package) (map[string][]byte, error
|
|||
pkg.genHeader(buffer, []string{"context", "reflect"}, importsAndAliases)
|
||||
|
||||
for _, t := range pkg.types {
|
||||
pkg.genType(buffer, t)
|
||||
if err := pkg.genType(buffer, t); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
delete(knownTypes, t)
|
||||
}
|
||||
|
||||
|
@ -3248,7 +3412,7 @@ func GeneratePackage(tool string, pkg *schema.Package) (map[string][]byte, error
|
|||
}
|
||||
|
||||
// If there are resources in this module, register the module with the runtime.
|
||||
if len(pkg.resources) != 0 {
|
||||
if len(pkg.resources) != 0 && !allResourcesAreOverlays(pkg.resources) {
|
||||
buffer := &bytes.Buffer{}
|
||||
pkg.genResourceModule(buffer)
|
||||
|
||||
|
@ -3259,6 +3423,15 @@ func GeneratePackage(tool string, pkg *schema.Package) (map[string][]byte, error
|
|||
return files, nil
|
||||
}
|
||||
|
||||
func allResourcesAreOverlays(resources []*schema.Resource) bool {
|
||||
for _, r := range resources {
|
||||
if !r.IsOverlay {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// goPackage returns the suggested package name for the given string.
|
||||
func goPackage(name string) string {
|
||||
return strings.ReplaceAll(name, "-", "")
|
||||
|
@ -3325,4 +3498,12 @@ func PkgVersion() (semver.Version, error) {
|
|||
}
|
||||
return semver.Version{}, fmt.Errorf("failed to determine the package version from %%s", pkgPath)
|
||||
}
|
||||
|
||||
// isZero is a null safe check for if a value is it's types zero value.
|
||||
func isZero(v interface{}) bool {
|
||||
if v == nil {
|
||||
return true
|
||||
}
|
||||
return reflect.ValueOf(v).IsZero()
|
||||
}
|
||||
`
|
||||
|
|
|
@ -2,8 +2,8 @@ package gen
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/pulumi/pulumi/pkg/v3/codegen/schema"
|
||||
)
|
||||
|
||||
|
@ -37,13 +37,15 @@ func CRDTypes(tool string, pkg *schema.Package) (map[string]*bytes.Buffer, error
|
|||
pkg.genHeader(buffer, []string{"context", "reflect"}, importsAndAliases)
|
||||
|
||||
if err := pkg.genResource(buffer, r, goPkgInfo.GenerateResourceContainerTypes); err != nil {
|
||||
return nil, errors.Wrapf(err, "generating resource %s", mod)
|
||||
return nil, fmt.Errorf("generating resource %s: %w", mod, err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(pkg.types) > 0 {
|
||||
for _, t := range pkg.types {
|
||||
pkg.genType(buffer, t)
|
||||
if err := pkg.genType(buffer, t); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
pkg.genTypeRegistrations(buffer, pkg.types)
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
"sync"
|
||||
|
||||
"github.com/hashicorp/hcl/v2"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/v3/codegen"
|
||||
"github.com/pulumi/pulumi/pkg/v3/codegen/hcl2/model"
|
||||
"github.com/pulumi/pulumi/pkg/v3/codegen/hcl2/model/format"
|
||||
|
@ -93,7 +93,7 @@ func GenerateProgram(program *pcl.Program) (map[string][]byte, hcl.Diagnostics,
|
|||
// Run Go formatter on the code before saving to disk
|
||||
formattedSource, err := gofmt.Source(index.Bytes())
|
||||
if err != nil {
|
||||
panic(errors.Errorf("invalid Go source code:\n\n%s", index.String()))
|
||||
panic(fmt.Errorf("invalid Go source code:\n\n%s", index.String()))
|
||||
}
|
||||
|
||||
files := map[string][]byte{
|
||||
|
@ -244,9 +244,7 @@ func (g *generator) collectImports(
|
|||
}
|
||||
pulumiImports.Add(g.getPulumiImport(pkg, vPath, mod))
|
||||
} else if call.Name == pcl.IntrinsicConvert {
|
||||
if schemaType, ok := pcl.GetSchemaForType(call.Type()); ok {
|
||||
g.collectTypeImports(program, schemaType, pulumiImports)
|
||||
}
|
||||
g.collectConvertImports(program, call, pulumiImports)
|
||||
}
|
||||
|
||||
// Checking to see if this function call deserves its own dedicated helper method in the preamble
|
||||
|
@ -277,6 +275,30 @@ func (g *generator) collectImports(
|
|||
return stdImports, pulumiImports, preambleHelperMethods
|
||||
}
|
||||
|
||||
func (g *generator) collectConvertImports(
|
||||
program *pcl.Program,
|
||||
call *model.FunctionCallExpression,
|
||||
pulumiImports codegen.StringSet) {
|
||||
if schemaType, ok := pcl.GetSchemaForType(call.Type()); ok {
|
||||
// Sometimes code for a `__convert` call does not
|
||||
// really use the import of the result type. In such
|
||||
// cases it is important not to generate a
|
||||
// non-compiling unused import. Detect some of these
|
||||
// cases here.
|
||||
//
|
||||
// Fully solving this is deferred for later:
|
||||
// TODO[pulumi/pulumi#8324].
|
||||
if expr, ok := call.Args[0].(*model.TemplateExpression); ok {
|
||||
if lit, ok := expr.Parts[0].(*model.LiteralValueExpression); ok &&
|
||||
model.StringType.AssignableFrom(lit.Type()) &&
|
||||
call.Type().AssignableFrom(lit.Type()) {
|
||||
return
|
||||
}
|
||||
}
|
||||
g.collectTypeImports(program, schemaType, pulumiImports)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *generator) getVersionPath(program *pcl.Program, pkg string) (string, error) {
|
||||
for _, p := range program.Packages() {
|
||||
if p.Name == pkg {
|
||||
|
@ -287,7 +309,7 @@ func (g *generator) getVersionPath(program *pcl.Program, pkg string) (string, er
|
|||
}
|
||||
}
|
||||
|
||||
return "", errors.Errorf("could not find package version information for pkg: %s", pkg)
|
||||
return "", fmt.Errorf("could not find package version information for pkg: %s", pkg)
|
||||
|
||||
}
|
||||
|
||||
|
@ -614,11 +636,17 @@ func (g *generator) genLocalVariable(w io.Writer, v *pcl.LocalVariable) {
|
|||
case *model.FunctionCallExpression:
|
||||
switch expr.Name {
|
||||
case pcl.Invoke:
|
||||
g.Fgenf(w, "%s, err %s %.3v;\n", name, assignment, expr)
|
||||
g.isErrAssigned = true
|
||||
g.Fgenf(w, "if err != nil {\n")
|
||||
g.Fgenf(w, "return err\n")
|
||||
g.Fgenf(w, "}\n")
|
||||
// OutputVersionedInvoke does not return an error
|
||||
noError, _, _ := pcl.RecognizeOutputVersionedInvoke(expr)
|
||||
if noError {
|
||||
g.Fgenf(w, "%s %s %.3v;\n", name, assignment, expr)
|
||||
} else {
|
||||
g.Fgenf(w, "%s, err %s %.3v;\n", name, assignment, expr)
|
||||
g.isErrAssigned = true
|
||||
g.Fgenf(w, "if err != nil {\n")
|
||||
g.Fgenf(w, "return err\n")
|
||||
g.Fgenf(w, "}\n")
|
||||
}
|
||||
case "join", "toBase64", "mimeType", "fileAsset":
|
||||
g.Fgenf(w, "%s := %.3v;\n", name, expr)
|
||||
}
|
||||
|
|
|
@ -195,7 +195,18 @@ func (g *generator) GenFunctionCallExpression(w io.Writer, expr *model.FunctionC
|
|||
if module == "" {
|
||||
module = pkg
|
||||
}
|
||||
name := fmt.Sprintf("%s.%s", module, fn)
|
||||
isOut, outArgs, outArgsType := pcl.RecognizeOutputVersionedInvoke(expr)
|
||||
if isOut {
|
||||
outTypeName, err := outputVersionFunctionArgTypeName(outArgsType)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("Error when generating an output-versioned Invoke: %w", err))
|
||||
}
|
||||
g.Fgenf(w, "%s.%sOutput(ctx, ", module, fn)
|
||||
g.genObjectConsExpressionWithTypeName(w, outArgs, outArgsType, outTypeName)
|
||||
} else {
|
||||
g.Fgenf(w, "%s.%s(ctx, ", module, fn)
|
||||
g.Fgenf(w, "%.v", expr.Args[1])
|
||||
}
|
||||
|
||||
optionsBag := ""
|
||||
var buf bytes.Buffer
|
||||
|
@ -205,9 +216,6 @@ func (g *generator) GenFunctionCallExpression(w io.Writer, expr *model.FunctionC
|
|||
g.Fgenf(&buf, ", nil")
|
||||
}
|
||||
optionsBag = buf.String()
|
||||
|
||||
g.Fgenf(w, "%s(ctx, ", name)
|
||||
g.Fgenf(w, "%.v", expr.Args[1])
|
||||
g.Fgenf(w, "%v)", optionsBag)
|
||||
case "join":
|
||||
g.Fgenf(w, "strings.Join(%v, %v)", expr.Args[1], expr.Args[0])
|
||||
|
@ -246,6 +254,32 @@ func (g *generator) GenFunctionCallExpression(w io.Writer, expr *model.FunctionC
|
|||
}
|
||||
}
|
||||
|
||||
// Currently args type for output-versioned invokes are named
|
||||
// `FOutputArgs`, but this is not yet understood by `tokenToType`. Use
|
||||
// this function to compensate.
|
||||
func outputVersionFunctionArgTypeName(t model.Type) (string, error) {
|
||||
schemaType, ok := pcl.GetSchemaForType(t)
|
||||
if !ok {
|
||||
return "", fmt.Errorf("No schema.Type type found for the given model.Type")
|
||||
}
|
||||
|
||||
objType, ok := schemaType.(*schema.ObjectType)
|
||||
if !ok {
|
||||
return "", fmt.Errorf("Expected a schema.ObjectType, got %s", schemaType.String())
|
||||
}
|
||||
|
||||
pkg := &pkgContext{pkg: &schema.Package{Name: "main"}}
|
||||
|
||||
var ty string
|
||||
if pkg.isExternalReference(objType) {
|
||||
ty = pkg.contextForExternalReferenceType(objType).tokenToType(objType.Token)
|
||||
} else {
|
||||
ty = pkg.tokenToType(objType.Token)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%sOutputArgs", strings.TrimSuffix(ty, "Args")), nil
|
||||
}
|
||||
|
||||
func (g *generator) GenIndexExpression(w io.Writer, expr *model.IndexExpression) {
|
||||
g.Fgenf(w, "%.20v[%.v]", expr.Collection, expr.Key)
|
||||
}
|
||||
|
@ -316,15 +350,10 @@ func (g *generator) genObjectConsExpression(
|
|||
w io.Writer,
|
||||
expr *model.ObjectConsExpression,
|
||||
destType model.Type,
|
||||
isInput bool,
|
||||
) {
|
||||
if len(expr.Items) == 0 {
|
||||
g.Fgenf(w, "nil")
|
||||
return
|
||||
}
|
||||
isInput bool) {
|
||||
|
||||
var temps []interface{}
|
||||
isInput = isInput || isInputty(destType)
|
||||
|
||||
typeName := g.argumentTypeName(expr, destType, isInput)
|
||||
if schemaType, ok := pcl.GetSchemaForType(destType); ok {
|
||||
if obj, ok := codegen.UnwrapType(schemaType).(*schema.ObjectType); ok {
|
||||
|
@ -334,6 +363,21 @@ func (g *generator) genObjectConsExpression(
|
|||
}
|
||||
}
|
||||
|
||||
g.genObjectConsExpressionWithTypeName(w, expr, destType, typeName)
|
||||
}
|
||||
|
||||
func (g *generator) genObjectConsExpressionWithTypeName(
|
||||
w io.Writer,
|
||||
expr *model.ObjectConsExpression,
|
||||
destType model.Type,
|
||||
typeName string) {
|
||||
|
||||
if len(expr.Items) == 0 {
|
||||
g.Fgenf(w, "nil")
|
||||
return
|
||||
}
|
||||
|
||||
var temps []interface{}
|
||||
// TODO: @pgavlin --- ineffectual assignment, was there some work in flight here?
|
||||
// if strings.HasSuffix(typeName, "Args") {
|
||||
// isInput = true
|
||||
|
@ -360,7 +404,7 @@ func (g *generator) genObjectConsExpression(
|
|||
}
|
||||
g.genTemps(w, temps)
|
||||
|
||||
if isMap || !strings.HasSuffix(typeName, "Args") {
|
||||
if isMap || !strings.HasSuffix(typeName, "Args") || strings.HasSuffix(typeName, "OutputArgs") {
|
||||
g.Fgenf(w, "%s", typeName)
|
||||
} else {
|
||||
g.Fgenf(w, "&%s", typeName)
|
||||
|
@ -814,9 +858,15 @@ func (g *generator) genApply(w io.Writer, expr *model.FunctionCallExpression) {
|
|||
isInput := false
|
||||
retType := g.argumentTypeName(nil, then.Signature.ReturnType, isInput)
|
||||
// TODO account for outputs in other namespaces like aws
|
||||
typeAssertion := fmt.Sprintf(".(%sOutput)", retType)
|
||||
if !strings.HasPrefix(retType, "pulumi.") {
|
||||
typeAssertion = fmt.Sprintf(".(pulumi.%sOutput)", Title(retType))
|
||||
// TODO[pulumi/pulumi#8453] incomplete pattern code below.
|
||||
var typeAssertion string
|
||||
if retType == "[]string" {
|
||||
typeAssertion = ".(pulumi.StringArrayOutput)"
|
||||
} else {
|
||||
typeAssertion = fmt.Sprintf(".(%sOutput)", retType)
|
||||
if !strings.HasPrefix(retType, "pulumi.") {
|
||||
typeAssertion = fmt.Sprintf(".(pulumi.%sOutput)", Title(retType))
|
||||
}
|
||||
}
|
||||
|
||||
if len(applyArgs) == 1 {
|
||||
|
|
|
@ -44,7 +44,9 @@ func (os *optionalSpiller) spillExpressionHelper(
|
|||
case *model.FunctionCallExpression:
|
||||
if x.Name == "invoke" {
|
||||
// recurse into invoke args
|
||||
isInvoke = true
|
||||
isOutputInvoke, _, _ := pcl.RecognizeOutputVersionedInvoke(x)
|
||||
// ignore output-versioned invokes as they do not need converting
|
||||
isInvoke = !isOutputInvoke
|
||||
_, diags := os.spillExpressionHelper(x.Args[1], x.Args[1].Type(), isInvoke)
|
||||
return x, diags
|
||||
}
|
||||
|
|
|
@ -60,6 +60,10 @@ type GoPackageInfo struct {
|
|||
// Feature flag to disable generating input type registration. This is a
|
||||
// space saving measure.
|
||||
DisableInputTypeRegistrations bool `json:"disableInputTypeRegistrations,omitempty"`
|
||||
|
||||
// Feature flag to disable generating Pulumi object default functions. This is a
|
||||
// space saving measure.
|
||||
DisableObjectDefaults bool `json:"disableObjectDefaults,omitempty"`
|
||||
}
|
||||
|
||||
// Importer implements schema.Language for Go.
|
||||
|
|
|
@ -20,7 +20,6 @@ import (
|
|||
"strings"
|
||||
"unicode"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/pulumi/pulumi/pkg/v3/codegen"
|
||||
)
|
||||
|
||||
|
@ -84,7 +83,7 @@ func makeSafeEnumName(name, typeName string) (string, error) {
|
|||
|
||||
// If the name is one illegal character, return an error.
|
||||
if len(safeName) == 1 && !isLegalIdentifierStart(rune(safeName[0])) {
|
||||
return "", errors.Errorf("enum name %s is not a valid identifier", safeName)
|
||||
return "", fmt.Errorf("enum name %s is not a valid identifier", safeName)
|
||||
}
|
||||
|
||||
// Capitalize and make a valid identifier.
|
||||
|
|
|
@ -1034,7 +1034,13 @@ func (x *FunctionCallExpression) Typecheck(typecheckOperands bool) hcl.Diagnosti
|
|||
typecheckDiags := typecheckArgs(rng, x.Signature, x.Args...)
|
||||
diagnostics = append(diagnostics, typecheckDiags...)
|
||||
|
||||
x.Signature.ReturnType = liftOperationType(x.Signature.ReturnType, x.Args...)
|
||||
// Unless the function is already automatically using an
|
||||
// Output-returning version, modify the signature to account
|
||||
// for automatic lifting to Promise or Output.
|
||||
_, isOutput := x.Signature.ReturnType.(*OutputType)
|
||||
if !isOutput {
|
||||
x.Signature.ReturnType = liftOperationType(x.Signature.ReturnType, x.Args...)
|
||||
}
|
||||
return diagnostics
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,9 @@
|
|||
|
||||
package format
|
||||
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Func is a function type that implements the fmt.Formatter interface. This can be used to conveniently
|
||||
// implement this interface for types defined in other packages.
|
||||
|
|
|
@ -14,7 +14,9 @@
|
|||
|
||||
package model
|
||||
|
||||
import "github.com/hashicorp/hcl/v2"
|
||||
import (
|
||||
"github.com/hashicorp/hcl/v2"
|
||||
)
|
||||
|
||||
// unwrapIterableSourceType removes any eventual types that wrap a type intended for iteration.
|
||||
func unwrapIterableSourceType(t Type) Type {
|
||||
|
|
|
@ -19,7 +19,7 @@ import (
|
|||
|
||||
"github.com/hashicorp/hcl/v2"
|
||||
"github.com/hashicorp/hcl/v2/hclsyntax"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/v3/codegen/hcl2/syntax"
|
||||
"github.com/pulumi/pulumi/sdk/v3/go/common/util/contract"
|
||||
)
|
||||
|
@ -55,7 +55,7 @@ func MustNewOpaqueType(name string, annotations ...interface{}) *OpaqueType {
|
|||
// NewOpaqueType creates a new opaque type with the given name.
|
||||
func NewOpaqueType(name string, annotations ...interface{}) (*OpaqueType, error) {
|
||||
if _, ok := opaqueTypes[name]; ok {
|
||||
return nil, errors.Errorf("opaque type %s is already defined", name)
|
||||
return nil, fmt.Errorf("opaque type %s is already defined", name)
|
||||
}
|
||||
|
||||
t := &OpaqueType{Name: name, Annotations: annotations}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package syntax
|
||||
|
||||
import "github.com/hashicorp/hcl/v2/hclsyntax"
|
||||
import (
|
||||
"github.com/hashicorp/hcl/v2/hclsyntax"
|
||||
)
|
||||
|
||||
// None is an HCL syntax node that can be used when a syntax node is required but none is appropriate.
|
||||
var None hclsyntax.Node = &hclsyntax.Body{}
|
||||
|
|
|
@ -17,6 +17,7 @@ package test
|
|||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
|
@ -26,7 +27,6 @@ import (
|
|||
"sort"
|
||||
"testing"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gopkg.in/yaml.v3"
|
||||
|
@ -363,7 +363,7 @@ func RunCommandWithOptions(
|
|||
type SchemaVersion = string
|
||||
|
||||
const (
|
||||
AwsSchema SchemaVersion = "4.21.1"
|
||||
AwsSchema SchemaVersion = "4.26.0"
|
||||
AzureNativeSchema SchemaVersion = "1.29.0"
|
||||
AzureSchema SchemaVersion = "4.18.0"
|
||||
KubernetesSchema SchemaVersion = "3.7.2"
|
||||
|
@ -442,7 +442,7 @@ func currentVersion(path string) (string, error) {
|
|||
}
|
||||
json, ok := data.(map[string]interface{})
|
||||
if !ok {
|
||||
return "", errors.Errorf("%s could not be read", path)
|
||||
return "", fmt.Errorf("%s could not be read", path)
|
||||
}
|
||||
version, ok := json["version"]
|
||||
if !ok {
|
||||
|
@ -468,7 +468,7 @@ func replaceSchema(c chan error, path, version, url string) {
|
|||
|
||||
err = os.Remove(path)
|
||||
if !os.IsNotExist(err) && err != nil {
|
||||
c <- errors.Wrap(err, "failed to replace schema")
|
||||
c <- fmt.Errorf("failed to replace schema: %w", err)
|
||||
return
|
||||
}
|
||||
schemaFile, err := os.Create(path)
|
||||
|
|
|
@ -49,14 +49,17 @@ var programTests = []programTest{
|
|||
{
|
||||
Name: "aws-fargate",
|
||||
Description: "AWS Fargate",
|
||||
|
||||
// TODO[pulumi/pulumi#8440]
|
||||
SkipCompile: codegen.NewStringSet("go"),
|
||||
},
|
||||
{
|
||||
Name: "aws-s3-logging",
|
||||
Description: "AWS S3 with logging",
|
||||
SkipCompile: codegen.NewStringSet("dotnet", "nodejs"),
|
||||
SkipCompile: codegen.NewStringSet("dotnet", "nodejs", "go"),
|
||||
// Blocked on dotnet: TODO[pulumi/pulumi#8069]
|
||||
// Blocked on nodejs: TODO[pulumi/pulumi#8068]
|
||||
// Flaky in go: TODO[pulumi/pulumi#8123]
|
||||
},
|
||||
{
|
||||
Name: "aws-webserver",
|
||||
|
@ -122,6 +125,10 @@ var programTests = []programTest{
|
|||
// TODO[pulumi/pulumi#8078]
|
||||
// TODO[pulumi/pulumi#8079]
|
||||
},
|
||||
{
|
||||
Name: "output-funcs-aws",
|
||||
Description: "Output Versioned Functions",
|
||||
},
|
||||
}
|
||||
|
||||
// Checks that a generated program is correct
|
||||
|
|
|
@ -191,6 +191,23 @@ var sdkTests = []sdkTest{
|
|||
Skip: codegen.NewStringSet("python/test", "nodejs/test"),
|
||||
SkipCompileCheck: codegen.NewStringSet(nodejs),
|
||||
},
|
||||
{
|
||||
Directory: "plain-object-defaults",
|
||||
Description: "Ensure that object defaults are generated (repro #8132)",
|
||||
Skip: codegen.NewStringSet("python/test", "nodejs/test"),
|
||||
SkipCompileCheck: codegen.NewStringSet(dotnet),
|
||||
},
|
||||
{
|
||||
Directory: "plain-object-disable-defaults",
|
||||
Description: "Ensure that we can still compile safely when defaults are disabled",
|
||||
Skip: codegen.NewStringSet("python/test", "nodejs/test"),
|
||||
SkipCompileCheck: codegen.NewStringSet(dotnet),
|
||||
},
|
||||
{
|
||||
Directory: "regress-8403",
|
||||
Description: "Regress pulumi/pulumi#8403",
|
||||
SkipCompileCheck: codegen.NewStringSet(dotnet, python, nodejs),
|
||||
},
|
||||
}
|
||||
|
||||
var genSDKOnly bool
|
||||
|
@ -217,11 +234,11 @@ type SDKCodegenOptions struct {
|
|||
Checks map[string]CodegenCheck
|
||||
}
|
||||
|
||||
// `TestSDKCodegen` runs the complete set of SDK code generation tests
|
||||
// TestSDKCodegen runs the complete set of SDK code generation tests
|
||||
// against a particular language's code generator. It also verifies
|
||||
// that the generated code is structurally sound.
|
||||
//
|
||||
// The tests files live in `pkg/codegen/internal/test/testdata` and
|
||||
// The test files live in `pkg/codegen/internal/test/testdata` and
|
||||
// are registered in `var sdkTests` in `sdk_driver.go`.
|
||||
//
|
||||
// An SDK code generation test files consists of a schema and a set of
|
||||
|
@ -245,7 +262,7 @@ type SDKCodegenOptions struct {
|
|||
// PULUMI_ACCEPT=true go test ./...
|
||||
//
|
||||
// This will rebuild subfolders such as `go/` from scratch and store
|
||||
// the set of code-generated file names in `go/codegen-manfiest.json`.
|
||||
// the set of code-generated file names in `go/codegen-manifest.json`.
|
||||
// If these outputs look correct, they need to be checked into git and
|
||||
// will then serve as the expected values for the normal test runs:
|
||||
//
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue