├── .ci-mgmt.yaml ├── .github └── workflows │ ├── build.yml │ ├── command-dispatch.yml │ ├── prerelease.yml │ ├── pull-request.yml │ ├── release.yml │ ├── run-acceptance-tests.yml │ └── weekly-pulumi-update.yml ├── .gitignore ├── .golangci.yml ├── .goreleaser.prerelease.yml ├── .goreleaser.yml ├── .mise.toml ├── CODE-OF-CONDUCT.md ├── LICENSE ├── Makefile ├── README.md ├── deployment-templates ├── .goreleaser.yml ├── README-DEPLOYMENT.md └── release.yml ├── examples ├── base_test.go ├── dotnet │ ├── .gitignore │ ├── Program.cs │ ├── Pulumi.yaml │ └── provider-provider-boilerplate.csproj ├── dotnet_test.go ├── go │ ├── Pulumi.yaml │ ├── go.mod │ ├── go.sum │ └── main.go ├── go_test.go ├── java_test.go ├── nodejs │ ├── .gitignore │ ├── Pulumi.yaml │ ├── index.ts │ ├── package.json │ └── tsconfig.json ├── nodejs_test.go ├── python │ ├── .gitignore │ ├── Pulumi.yaml │ ├── __main__.py │ └── requirements.txt ├── python_test.go ├── testdata │ └── recorded │ │ └── TestProviderUpgrade │ │ └── yaml │ │ └── 0.0.1 │ │ ├── grpc.json │ │ └── stack.json ├── yaml │ ├── Pulumi.yaml │ └── README.md └── yaml_test.go ├── go.mod ├── go.sum ├── provider ├── cmd │ └── pulumi-resource-provider-boilerplate │ │ ├── main.go │ │ └── schema.json ├── provider.go ├── random_component.go ├── random_resource.go └── random_resource_test.go ├── sdk ├── dotnet │ ├── Config │ │ ├── Config.cs │ │ └── README.md │ ├── Mynamespace.ProviderBoilerplate.csproj │ ├── Provider.cs │ ├── README.md │ ├── Random.cs │ ├── RandomComponent.cs │ ├── Utilities.cs │ ├── logo.png │ ├── pulumi-plugin.json │ └── version.txt ├── go │ └── provider-boilerplate │ │ ├── config │ │ └── config.go │ │ ├── doc.go │ │ ├── init.go │ │ ├── internal │ │ ├── pulumiUtilities.go │ │ └── pulumiVersion.go │ │ ├── provider.go │ │ ├── pulumi-plugin.json │ │ ├── random.go │ │ └── randomComponent.go ├── java │ ├── README.md │ ├── settings.gradle │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── mynamespace │ │ └── providerboilerplate │ │ ├── Config.java │ │ ├── Provider.java │ │ ├── ProviderArgs.java │ │ ├── Random.java │ │ ├── RandomArgs.java │ │ ├── RandomComponent.java │ │ ├── RandomComponentArgs.java │ │ └── Utilities.java ├── nodejs │ ├── README.md │ ├── config │ │ ├── index.ts │ │ └── vars.ts │ ├── index.ts │ ├── package.json │ ├── provider.ts │ ├── random.ts │ ├── randomComponent.ts │ ├── tsconfig.json │ └── utilities.ts └── python │ ├── README.md │ ├── mynamespace_provider_boilerplate │ ├── README.md │ ├── __init__.py │ ├── _utilities.py │ ├── config │ │ ├── __init__.py │ │ ├── __init__.pyi │ │ └── vars.py │ ├── provider.py │ ├── pulumi-plugin.json │ ├── py.typed │ ├── random.py │ └── random_component.py │ └── pyproject.toml └── tests └── provider_test.go /.ci-mgmt.yaml: -------------------------------------------------------------------------------- 1 | template: native 2 | provider: provider-boilerplate 3 | major-version: 0 4 | providerDefaultBranch: main 5 | providerVersion: github.com/pulumi/pulumi-provider-boilerplate/provider.Version 6 | parallel: 3 7 | # For some reason this is required. If it's omitted all of the env keys get duplicated. 8 | envOverride: 9 | FOO: BAR 10 | -------------------------------------------------------------------------------- /.github/workflows/command-dispatch.yml: -------------------------------------------------------------------------------- 1 | # WARNING: This file is autogenerated - changes will be overwritten if not made via https://github.com/pulumi/ci-mgmt 2 | 3 | name: command-dispatch 4 | on: 5 | issue_comment: 6 | types: 7 | - created 8 | - edited 9 | env: 10 | GITHUB_TOKEN: ${{ secrets.PULUMI_BOT_TOKEN }} 11 | PROVIDER: provider-boilerplate 12 | PULUMI_ACCESS_TOKEN: ${{ secrets.PULUMI_ACCESS_TOKEN }} 13 | PULUMI_LOCAL_NUGET: ${{ github.workspace }}/nuget 14 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 15 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 16 | NUGET_PUBLISH_KEY: ${{ secrets.NUGET_PUBLISH_KEY }} 17 | PYPI_USERNAME: __token__ 18 | PYPI_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} 19 | TRAVIS_OS_NAME: linux 20 | SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} 21 | PULUMI_GO_DEP_ROOT: ${{ github.workspace }}/.. 22 | PUBLISH_REPO_USERNAME: ${{ secrets.OSSRH_USERNAME }} 23 | PUBLISH_REPO_PASSWORD: ${{ secrets.OSSRH_PASSWORD }} 24 | SIGNING_KEY_ID: ${{ secrets.JAVA_SIGNING_KEY_ID }} 25 | SIGNING_KEY: ${{ secrets.JAVA_SIGNING_KEY }} 26 | SIGNING_PASSWORD: ${{ secrets.JAVA_SIGNING_PASSWORD }} 27 | GOVERSION: "1.21.x" 28 | NODEVERSION: "20.x" 29 | PYTHONVERSION: "3.11.8" 30 | DOTNETVERSION: "8.0.x" 31 | JAVAVERSION: "11" 32 | FOO: BAR 33 | jobs: 34 | command-dispatch-for-testing: 35 | runs-on: ubuntu-latest 36 | name: command-dispatch-for-testing 37 | steps: 38 | - name: Checkout Repo 39 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 40 | with: 41 | lfs: true 42 | - uses: peter-evans/slash-command-dispatch@13bc09769d122a64f75aa5037256f6f2d78be8c4 # v4.0.0 43 | with: 44 | token: ${{ secrets.PULUMI_BOT_TOKEN }} 45 | reaction-token: ${{ secrets.GITHUB_TOKEN }} 46 | commands: run-acceptance-tests 47 | permission: write 48 | issue-type: pull-request 49 | repository: pulumi/pulumi-provider-boilerplate 50 | if: ${{ github.event.issue.pull_request }} 51 | -------------------------------------------------------------------------------- /.github/workflows/pull-request.yml: -------------------------------------------------------------------------------- 1 | # WARNING: This file is autogenerated - changes will be overwritten if not made via https://github.com/pulumi/ci-mgmt 2 | 3 | name: pull-request 4 | on: 5 | pull_request_target: {} 6 | env: 7 | GITHUB_TOKEN: ${{ secrets.PULUMI_BOT_TOKEN }} 8 | PROVIDER: provider-boilerplate 9 | PULUMI_ACCESS_TOKEN: ${{ secrets.PULUMI_ACCESS_TOKEN }} 10 | PULUMI_LOCAL_NUGET: ${{ github.workspace }}/nuget 11 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 12 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 13 | NUGET_PUBLISH_KEY: ${{ secrets.NUGET_PUBLISH_KEY }} 14 | PYPI_USERNAME: __token__ 15 | PYPI_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} 16 | TRAVIS_OS_NAME: linux 17 | SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} 18 | PULUMI_GO_DEP_ROOT: ${{ github.workspace }}/.. 19 | PUBLISH_REPO_USERNAME: ${{ secrets.OSSRH_USERNAME }} 20 | PUBLISH_REPO_PASSWORD: ${{ secrets.OSSRH_PASSWORD }} 21 | SIGNING_KEY_ID: ${{ secrets.JAVA_SIGNING_KEY_ID }} 22 | SIGNING_KEY: ${{ secrets.JAVA_SIGNING_KEY }} 23 | SIGNING_PASSWORD: ${{ secrets.JAVA_SIGNING_PASSWORD }} 24 | GOVERSION: "1.21.x" 25 | NODEVERSION: "20.x" 26 | PYTHONVERSION: "3.11.8" 27 | DOTNETVERSION: "8.0.x" 28 | JAVAVERSION: "11" 29 | FOO: BAR 30 | jobs: 31 | comment-on-pr: 32 | runs-on: ubuntu-latest 33 | name: comment-on-pr 34 | steps: 35 | - name: Checkout Repo 36 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 37 | with: 38 | lfs: true 39 | - name: Comment PR 40 | uses: thollander/actions-comment-pull-request@24bffb9b452ba05a4f3f77933840a6a841d1b32b # v3.0.1 41 | with: 42 | message: > 43 | PR is now waiting for a maintainer to run the acceptance tests. 44 | 45 | **Note for the maintainer:** To run the acceptance tests, please comment */run-acceptance-tests* on the PR 46 | github-token: ${{ secrets.GITHUB_TOKEN }} 47 | if: github.event.pull_request.head.repo.full_name != github.repository 48 | -------------------------------------------------------------------------------- /.github/workflows/weekly-pulumi-update.yml: -------------------------------------------------------------------------------- 1 | # WARNING: This file is autogenerated - changes will be overwritten if not made via https://github.com/pulumi/ci-mgmt 2 | 3 | name: weekly-pulumi-update 4 | on: 5 | schedule: 6 | - cron: 35 12 * * 4 7 | workflow_dispatch: {} 8 | env: 9 | GITHUB_TOKEN: ${{ secrets.PULUMI_BOT_TOKEN }} 10 | PROVIDER: provider-boilerplate 11 | PULUMI_ACCESS_TOKEN: ${{ secrets.PULUMI_ACCESS_TOKEN }} 12 | PULUMI_LOCAL_NUGET: ${{ github.workspace }}/nuget 13 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 14 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 15 | NUGET_PUBLISH_KEY: ${{ secrets.NUGET_PUBLISH_KEY }} 16 | PYPI_USERNAME: __token__ 17 | PYPI_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} 18 | TRAVIS_OS_NAME: linux 19 | SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} 20 | PULUMI_GO_DEP_ROOT: ${{ github.workspace }}/.. 21 | PUBLISH_REPO_USERNAME: ${{ secrets.OSSRH_USERNAME }} 22 | PUBLISH_REPO_PASSWORD: ${{ secrets.OSSRH_PASSWORD }} 23 | SIGNING_KEY_ID: ${{ secrets.JAVA_SIGNING_KEY_ID }} 24 | SIGNING_KEY: ${{ secrets.JAVA_SIGNING_KEY }} 25 | SIGNING_PASSWORD: ${{ secrets.JAVA_SIGNING_PASSWORD }} 26 | GOVERSION: "1.21.x" 27 | NODEVERSION: "20.x" 28 | PYTHONVERSION: "3.11.8" 29 | DOTNETVERSION: "8.0.x" 30 | JAVAVERSION: "11" 31 | FOO: BAR 32 | jobs: 33 | weekly-pulumi-update: 34 | runs-on: ubuntu-latest 35 | steps: 36 | - name: Checkout Repo 37 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 38 | with: 39 | lfs: true 40 | - name: Install Go 41 | uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 42 | with: 43 | go-version: ${{ env.GOVERSION }} 44 | cache-dependency-path: "**/*.sum" 45 | - name: Install pulumictl 46 | uses: jaxxstorm/action-install-gh-release@6096f2a2bbfee498ced520b6922ac2c06e990ed2 # v2.1.0 47 | with: 48 | repo: pulumi/pulumictl 49 | - name: Install Pulumi CLI 50 | uses: pulumi/actions@df5a93ad715135263c732ba288301bd044c383c0 # v6.3.0 51 | - name: Setup DotNet 52 | uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4.3.1 53 | with: 54 | dotnet-version: ${{ env.DOTNETVERSION }} 55 | - name: Setup Node 56 | uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 57 | with: 58 | node-version: ${{ env.NODEVERSION }} 59 | registry-url: https://registry.npmjs.org 60 | - name: Setup Python 61 | uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 62 | with: 63 | python-version: ${{ env.PYTHONVERSION }} 64 | - name: Update Pulumi/Pulumi 65 | id: gomod 66 | run: >- 67 | git config --local user.email 'bot@pulumi.com' 68 | 69 | git config --local user.name 'pulumi-bot' 70 | 71 | git checkout -b update-pulumi/${{ github.run_id }}-${{ github.run_number }} 72 | 73 | for MODFILE in $(find . -name go.mod); do pushd $(dirname $MODFILE); go get github.com/pulumi/pulumi/pkg/v3 github.com/pulumi/pulumi/sdk/v3; go mod tidy; popd; done 74 | 75 | gh repo view pulumi/pulumi --json latestRelease --jq .latestRelease.tagName | sed 's/^v//' > .pulumi.version 76 | 77 | git update-index -q --refresh 78 | 79 | if ! git diff-files --quiet; then echo changes=1 >> "$GITHUB_OUTPUT"; fi 80 | - name: Provider with Pulumi Upgrade 81 | if: steps.gomod.outputs.changes != 0 82 | run: >- 83 | make codegen && make local_generate 84 | 85 | git add sdk/nodejs 86 | 87 | git commit -m "Regenerating Node.js SDK based on updated modules" || echo "ignore commit failure, may be empty" 88 | 89 | git add sdk/python 90 | 91 | git commit -m "Regenerating Python SDK based on updated modules" || echo "ignore commit failure, may be empty" 92 | 93 | git add sdk/dotnet 94 | 95 | git commit -m "Regenerating .NET SDK based on updated modules" || echo "ignore commit failure, may be empty" 96 | 97 | git add sdk/go* 98 | 99 | git commit -m "Regenerating Go SDK based on updated modules" || echo "ignore commit failure, may be empty" 100 | 101 | git add sdk/java* 102 | 103 | git commit -m "Regenerating Java SDK based on updated modules" || echo "ignore commit failure, may be empty" 104 | 105 | git add . 106 | 107 | git commit -m "Updated modules" || echo "ignore commit failure, may be empty" 108 | 109 | git push origin update-pulumi/${{ github.run_id }}-${{ github.run_number }} 110 | - name: Create PR 111 | id: create-pr 112 | if: steps.gomod.outputs.changes != 0 113 | run: > 114 | ver=$(cat .pulumi.version) 115 | 116 | msg="Automated upgrade: bump pulumi/pulumi to ${ver}" 117 | 118 | # See https://github.com/cli/cli/issues/6485#issuecomment-2560935183 for --head workaround 119 | 120 | gh pr create -t "$msg" -b "$msg" --head $(git branch --show-current) 121 | env: 122 | GITHUB_TOKEN: ${{ secrets.PULUMI_BOT_TOKEN }} 123 | name: weekly-pulumi-update 124 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor/ 2 | **/bin/ 3 | **/obj/ 4 | **/node_modules/ 5 | **/.vs 6 | **/.idea 7 | **/.ionide 8 | .pulumi 9 | Pulumi.*.yaml 10 | yarn.lock 11 | ci-scripts 12 | /nuget/ 13 | provider/**/schema-embed.json 14 | 15 | sdk/dotnet/version.txt 16 | sdk/java/.gradle 17 | sdk/java/build/ 18 | sdk/java/build.gradle 19 | sdk/python/venv 20 | -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | run: 2 | timeout: 10m 3 | 4 | linters: 5 | enable-all: false 6 | enable: 7 | - depguard 8 | - errcheck 9 | - exhaustive 10 | - copyloopvar 11 | - gci 12 | - gocritic 13 | - gofumpt 14 | - goheader 15 | - gosec 16 | - govet 17 | - importas 18 | - ineffassign 19 | - lll 20 | - misspell 21 | - nakedret 22 | - nolintlint 23 | - paralleltest 24 | - perfsprint 25 | - prealloc 26 | - revive 27 | - unconvert 28 | - unused 29 | 30 | linters-settings: 31 | depguard: 32 | rules: 33 | protobuf: 34 | deny: 35 | - pkg: "github.com/golang/protobuf" 36 | desc: Use google.golang.org/protobuf instead 37 | gci: 38 | sections: 39 | - standard # Standard section: captures all standard library packages. 40 | - blank # Blank section: contains all blank imports. 41 | - default # Default section: contains all imports that could not be matched to another section type. 42 | - prefix(github.com/pulumi/) # Custom section: groups all imports with the github.com/pulumi/ prefix. 43 | - prefix(github.com/pulumi/pulumi-dockerbuild/) # Custom section: local imports 44 | custom-order: true 45 | gocritic: 46 | enable-all: true 47 | disabled-checks: 48 | - hugeParam 49 | - importShadow 50 | goheader: 51 | template: |- 52 | Copyright 2025, Pulumi Corporation. 53 | 54 | Licensed under the Apache License, Version 2.0 (the "License"); 55 | you may not use this file except in compliance with the License. 56 | You may obtain a copy of the License at 57 | 58 | http://www.apache.org/licenses/LICENSE-2.0 59 | 60 | Unless required by applicable law or agreed to in writing, software 61 | distributed under the License is distributed on an "AS IS" BASIS, 62 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 63 | See the License for the specific language governing permissions and 64 | limitations under the License. 65 | govet: 66 | enable: 67 | - nilness 68 | # Reject comparisons of reflect.Value with DeepEqual or '=='. 69 | - reflectvaluecompare 70 | # Reject sort.Slice calls with a non-slice argument. 71 | - sortslice 72 | # Detect write to struct/arrays by-value that aren't read again. 73 | - unusedwrite 74 | nakedret: 75 | # Make an issue if func has more lines of code than this setting, and it has naked returns. 76 | # Default: 30 77 | max-func-lines: 60 78 | nolintlint: 79 | # Some linter exclusions are added to generated or templated files 80 | # pre-emptively. 81 | # Don't complain about these. 82 | allow-unused: true 83 | 84 | issues: 85 | exclude-use-default: false 86 | exclude-rules: 87 | # Don't warn on unused parameters. 88 | # Parameter names are useful; replacing them with '_' is undesirable. 89 | - linters: [revive] 90 | text: 'unused-parameter: parameter \S+ seems to be unused, consider removing or renaming it as _' 91 | 92 | # staticcheck already has smarter checks for empty blocks. 93 | # revive's empty-block linter has false positives. 94 | # For example, as of writing this, the following is not allowed. 95 | # for foo() { } 96 | - linters: [revive] 97 | text: "empty-block: this block is empty, you can remove it" 98 | 99 | # We *frequently* use the term 'new' in the context of properties 100 | # (new and old properties), 101 | # and we rarely use the 'new' built-in function. 102 | # It's fine to ignore these cases. 103 | - linters: [revive] 104 | text: "redefines-builtin-id: redefinition of the built-in function new" 105 | -------------------------------------------------------------------------------- /.goreleaser.prerelease.yml: -------------------------------------------------------------------------------- 1 | # WARNING: This file is autogenerated - changes will be overwritten if not made via https://github.com/pulumi/ci-mgmt 2 | 3 | project_name: pulumi-provider-boilerplate 4 | builds: 5 | - id: build-provider 6 | dir: provider 7 | env: 8 | - CGO_ENABLED=0 9 | - GO111MODULE=on 10 | goos: 11 | - darwin 12 | - linux 13 | goarch: 14 | - amd64 15 | - arm64 16 | ignore: &a1 [] 17 | main: ./cmd/pulumi-resource-provider-boilerplate/ 18 | ldflags: &a2 19 | - -s 20 | - -w 21 | - -X 22 | github.com/pulumi/pulumi-provider-boilerplate/provider/pkg/version.Version={{.Tag}} 23 | binary: pulumi-resource-provider-boilerplate 24 | - id: build-provider-sign-windows 25 | dir: provider 26 | env: 27 | - CGO_ENABLED=0 28 | - GO111MODULE=on 29 | goos: 30 | - windows 31 | goarch: 32 | - amd64 33 | - arm64 34 | ignore: *a1 35 | main: ./cmd/pulumi-resource-provider-boilerplate/ 36 | ldflags: *a2 37 | binary: pulumi-resource-provider-boilerplate 38 | hooks: 39 | post: 40 | - make sign-goreleaser-exe-{{ .Arch }} 41 | archives: 42 | - name_template: "{{ .Binary }}-{{ .Tag }}-{{ .Os }}-{{ .Arch }}" 43 | id: archive 44 | snapshot: 45 | name_template: "{{ .Tag }}-SNAPSHOT" 46 | changelog: 47 | skip: true 48 | release: 49 | disable: true 50 | blobs: 51 | - provider: s3 52 | region: us-west-2 53 | bucket: get.pulumi.com 54 | folder: releases/plugins/ 55 | ids: 56 | - archive 57 | -------------------------------------------------------------------------------- /.goreleaser.yml: -------------------------------------------------------------------------------- 1 | # WARNING: This file is autogenerated - changes will be overwritten if not made via https://github.com/pulumi/ci-mgmt 2 | 3 | project_name: pulumi-provider-boilerplate 4 | builds: 5 | - id: build-provider 6 | dir: provider 7 | env: 8 | - CGO_ENABLED=0 9 | - GO111MODULE=on 10 | goos: 11 | - darwin 12 | - linux 13 | goarch: 14 | - amd64 15 | - arm64 16 | ignore: &a1 [] 17 | main: ./cmd/pulumi-resource-provider-boilerplate/ 18 | ldflags: &a2 19 | - -s 20 | - -w 21 | - -X 22 | github.com/pulumi/pulumi-provider-boilerplate/provider/pkg/version.Version={{.Tag}} 23 | binary: pulumi-resource-provider-boilerplate 24 | - id: build-provider-sign-windows 25 | dir: provider 26 | env: 27 | - CGO_ENABLED=0 28 | - GO111MODULE=on 29 | goos: 30 | - windows 31 | goarch: 32 | - amd64 33 | - arm64 34 | ignore: *a1 35 | main: ./cmd/pulumi-resource-provider-boilerplate/ 36 | ldflags: *a2 37 | binary: pulumi-resource-provider-boilerplate 38 | hooks: 39 | post: 40 | - make sign-goreleaser-exe-{{ .Arch }} 41 | archives: 42 | - name_template: "{{ .Binary }}-{{ .Tag }}-{{ .Os }}-{{ .Arch }}" 43 | id: archive 44 | snapshot: 45 | name_template: "{{ .Tag }}-SNAPSHOT" 46 | changelog: 47 | skip: true 48 | release: 49 | disable: false 50 | blobs: 51 | - provider: s3 52 | region: us-west-2 53 | bucket: get.pulumi.com 54 | folder: releases/plugins/ 55 | ids: 56 | - archive 57 | -------------------------------------------------------------------------------- /.mise.toml: -------------------------------------------------------------------------------- 1 | [tools] 2 | golangci-lint = "1.64.8" 3 | -------------------------------------------------------------------------------- /CODE-OF-CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of experience, 9 | education, socio-economic status, nationality, personal appearance, race, 10 | religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | * Contribute in a positive and constructive way 23 | 24 | Examples of unacceptable behavior by participants include: 25 | 26 | * The use of sexualized language or imagery and unwelcome sexual attention or 27 | advances 28 | * Trolling, insulting/derogatory comments, and personal or political attacks 29 | * Public or private harassment 30 | * Publishing others' private information, such as a physical or electronic 31 | address, without explicit permission 32 | * Other conduct which could reasonably be considered inappropriate in a 33 | professional setting 34 | 35 | ## Our Community Guidelines 36 | * Be clear and stay on topic. Communicating with strangers on the Internet can make it hard to convey or read tone, and sarcasm is frequently misunderstood. Try to use clear language, and think about how the other person will receive it. 37 | * Don’t cross-post the same thing in multiple GitHub Discussion topics or multiple Slack channels. This can make it difficult for people answering your questions and creates "scrollback spam". 38 | * Public discussion is preferred to private. Avoid using Slack DMs for questions, and instead share them in public Slack channels or GitHub Discussion threads. This allows a larger audience to both share their knowledge as well as learn from your question or issue. If you're having a problem, chances are someone else is having a similar problem. Learning in public is a community contribution. 39 | * Minimize notifications to other community members. Avoid tagging other community members in Slack messages or Discussion threads, unless you are replying to something specific. Community members are here to help each other, but are not "on call" for support, and we expect everyone to try to minimize "notification fatigue". If your issue is time-sensitive or critical, use methods like support@pulumi.com instead. 40 | 41 | ## Our Responsibilities 42 | 43 | Project maintainers are responsible for clarifying the standards of acceptable 44 | behavior and are expected to take appropriate and fair corrective action in 45 | response to any instances of unacceptable behavior. 46 | 47 | Project maintainers have the right and responsibility to remove, edit, or 48 | reject comments, commits, code, wiki edits, issues, GitHub Discussions posts, 49 | and other contributions that are not aligned to this Code of Conduct, or to ban 50 | temporarily or permanently any contributor for other behaviors that they deem 51 | inappropriate, threatening, offensive, or harmful. 52 | 53 | ## Scope 54 | 55 | This Code of Conduct applies both within project spaces (including the Community Slack 56 | and GitHub Discussions forums) and in public spaces when an individual is representing the 57 | project or its community. Examples of representing a project or community include 58 | using an official project e-mail address, posting via an official social media account, 59 | or acting as an appointed representative at an online or offline event. Representation 60 | of a project may be further defined and clarified by project maintainers. 61 | 62 | ## Enforcement 63 | 64 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 65 | reported by contacting the project team at code-of-conduct@pulumi.com. All 66 | complaints will be reviewed and investigated and will result in a response that 67 | is deemed necessary and appropriate to the circumstances. The project team is 68 | obligated to maintain confidentiality with regard to the reporter of an incident. 69 | Further details of specific enforcement policies may be posted separately. 70 | 71 | Project maintainers who do not follow or enforce the Code of Conduct in good 72 | faith may face temporary or permanent repercussions as determined by other 73 | members of the project's leadership. 74 | 75 | ## Attribution 76 | 77 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 78 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 79 | 80 | [homepage]: https://www.contributor-covenant.org 81 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PROJECT_NAME := Pulumi Provider Boilerplate 2 | 3 | PACK := provider-boilerplate 4 | PACKDIR := sdk 5 | PROJECT := github.com/pulumi/pulumi-provider-boilerplate 6 | NODE_MODULE_NAME := @pulumi/boilerplate 7 | NUGET_PKG_NAME := Pulumi.Boilerplate 8 | 9 | PROVIDER := pulumi-resource-${PACK} 10 | PROVIDER_PATH := provider 11 | VERSION_PATH := ${PROVIDER_PATH}/version.Version 12 | 13 | PULUMI := .pulumi/bin/pulumi 14 | 15 | SCHEMA_FILE := provider/cmd/pulumi-resource-provider-boilerplate/schema.json 16 | export GOPATH := $(shell go env GOPATH) 17 | 18 | WORKING_DIR := $(shell pwd) 19 | TESTPARALLELISM := 4 20 | 21 | # Override during CI using `make [TARGET] PROVIDER_VERSION=""` or by setting a PROVIDER_VERSION environment variable 22 | # Local & branch builds will just used this fixed default version unless specified 23 | PROVIDER_VERSION ?= 1.0.0-alpha.0+dev 24 | # Use this normalised version everywhere rather than the raw input to ensure consistency. 25 | VERSION_GENERIC = $(shell pulumictl convert-version --language generic --version "$(PROVIDER_VERSION)") 26 | 27 | # Need to pick up locally pinned pulumi-langage-* plugins. 28 | export PULUMI_IGNORE_AMBIENT_PLUGINS = true 29 | 30 | ensure:: 31 | go mod tidy 32 | 33 | $(SCHEMA_FILE): provider $(PULUMI) 34 | $(PULUMI) package get-schema $(WORKING_DIR)/bin/${PROVIDER} | \ 35 | jq 'del(.version)' > $(SCHEMA_FILE) 36 | 37 | # Codegen generates the schema file and *generates* all sdks. This is a local process and 38 | # does not require the ability to build all SDKs. 39 | # 40 | # To build the SDKs, use `make build_sdks` 41 | codegen: $(SCHEMA_FILE) sdk/dotnet sdk/go sdk/nodejs sdk/python sdk/java 42 | 43 | .PHONY: sdk/% 44 | sdk/%: $(SCHEMA_FILE) 45 | rm -rf $@ 46 | $(PULUMI) package gen-sdk --language $* $(SCHEMA_FILE) --version "${VERSION_GENERIC}" 47 | 48 | sdk/java: $(SCHEMA_FILE) 49 | rm -rf $@ 50 | $(PULUMI) package gen-sdk --language java $(SCHEMA_FILE) 51 | 52 | sdk/python: $(SCHEMA_FILE) 53 | rm -rf $@ 54 | $(PULUMI) package gen-sdk --language python $(SCHEMA_FILE) --version "${VERSION_GENERIC}" 55 | cp README.md ${PACKDIR}/python/ 56 | 57 | sdk/dotnet: $(SCHEMA_FILE) 58 | rm -rf $@ 59 | $(PULUMI) package gen-sdk --language dotnet $(SCHEMA_FILE) --version "${VERSION_GENERIC}" 60 | 61 | 62 | .PHONY: provider 63 | provider: bin/${PROVIDER} bin/pulumi-gen-${PACK} # Required by CI 64 | 65 | bin/${PROVIDER}: 66 | cd provider && go build -o $(WORKING_DIR)/bin/${PROVIDER} -ldflags "-X ${PROJECT}/${VERSION_PATH}=${VERSION_GENERIC}" $(PROJECT)/${PROVIDER_PATH}/cmd/$(PROVIDER) 67 | 68 | .PHONY: provider_debug 69 | provider_debug: 70 | (cd provider && go build -o $(WORKING_DIR)/bin/${PROVIDER} -gcflags="all=-N -l" -ldflags "-X ${PROJECT}/${VERSION_PATH}=${VERSION_GENERIC}" $(PROJECT)/${PROVIDER_PATH}/cmd/$(PROVIDER)) 71 | 72 | test_provider: 73 | cd provider && go test -short -v -count=1 -cover -timeout 2h -parallel ${TESTPARALLELISM} -coverprofile="coverage.txt" ./... 74 | 75 | dotnet_sdk: sdk/dotnet 76 | cd ${PACKDIR}/dotnet/&& \ 77 | echo "${VERSION_GENERIC}" > version.txt && \ 78 | dotnet build 79 | 80 | go_sdk: sdk/go 81 | 82 | nodejs_sdk: sdk/nodejs 83 | cd ${PACKDIR}/nodejs/ && \ 84 | yarn install && \ 85 | yarn run tsc 86 | cp README.md LICENSE ${PACKDIR}/nodejs/package.json ${PACKDIR}/nodejs/yarn.lock ${PACKDIR}/nodejs/bin/ 87 | 88 | python_sdk: sdk/python 89 | cp README.md ${PACKDIR}/python/ 90 | cd ${PACKDIR}/python/ && \ 91 | rm -rf ./bin/ ../python.bin/ && cp -R . ../python.bin && mv ../python.bin ./bin && \ 92 | python3 -m venv venv && \ 93 | ./venv/bin/python -m pip install build && \ 94 | cd ./bin && \ 95 | ../venv/bin/python -m build . 96 | 97 | bin/pulumi-java-gen:: 98 | echo pulumi-java-gen is no longer necessary 99 | 100 | java_sdk:: PACKAGE_VERSION := $(VERSION_GENERIC) 101 | java_sdk:: sdk/java 102 | cd sdk/java/ && \ 103 | gradle --console=plain build 104 | 105 | .PHONY: build 106 | build:: provider build_sdks 107 | 108 | .PHONY: build_sdks 109 | build_sdks: dotnet_sdk go_sdk nodejs_sdk python_sdk java_sdk 110 | 111 | # Required for the codegen action that runs in pulumi/pulumi 112 | only_build:: build 113 | 114 | lint: 115 | golangci-lint --path-prefix provider --config .golangci.yml run --fix 116 | 117 | 118 | install:: install_nodejs_sdk install_dotnet_sdk 119 | cp $(WORKING_DIR)/bin/${PROVIDER} ${GOPATH}/bin 120 | 121 | 122 | GO_TEST := go test -v -count=1 -cover -timeout 2h -parallel ${TESTPARALLELISM} 123 | 124 | test_all:: test 125 | cd provider/pkg && $(GO_TEST) ./... 126 | cd tests/sdk/nodejs && $(GO_TEST) ./... 127 | cd tests/sdk/python && $(GO_TEST) ./... 128 | cd tests/sdk/dotnet && $(GO_TEST) ./... 129 | cd tests/sdk/go && $(GO_TEST) ./... 130 | 131 | install_dotnet_sdk:: 132 | rm -rf $(WORKING_DIR)/nuget/$(NUGET_PKG_NAME).*.nupkg 133 | mkdir -p $(WORKING_DIR)/nuget 134 | find . -name '*.nupkg' -print -exec cp -p {} ${WORKING_DIR}/nuget \; 135 | 136 | install_python_sdk:: 137 | #target intentionally blank 138 | 139 | install_go_sdk:: 140 | #target intentionally blank 141 | 142 | install_java_sdk:: 143 | #target intentionally blank 144 | 145 | install_nodejs_sdk:: 146 | -yarn unlink --cwd $(WORKING_DIR)/sdk/nodejs/bin 147 | yarn link --cwd $(WORKING_DIR)/sdk/nodejs/bin 148 | 149 | test:: test_provider 150 | cd examples && go test -v -tags=all -timeout 2h 151 | 152 | $(PULUMI): HOME := $(WORKING_DIR) 153 | $(PULUMI): go.mod 154 | @ PULUMI_VERSION="$$(cd provider && go list -m github.com/pulumi/pulumi/pkg/v3 | awk '{print $$2}')"; \ 155 | if [ -x $(PULUMI) ]; then \ 156 | CURRENT_VERSION="$$($(PULUMI) version)"; \ 157 | if [ "$${CURRENT_VERSION}" != "$${PULUMI_VERSION}" ]; then \ 158 | echo "Upgrading $(PULUMI) from $${CURRENT_VERSION} to $${PULUMI_VERSION}"; \ 159 | rm $(PULUMI); \ 160 | fi; \ 161 | fi; \ 162 | if ! [ -x $(PULUMI) ]; then \ 163 | curl -fsSL https://get.pulumi.com | sh -s -- --version "$${PULUMI_VERSION#v}"; \ 164 | fi 165 | 166 | # Set these variables to enable signing of the windows binary 167 | AZURE_SIGNING_CLIENT_ID ?= 168 | AZURE_SIGNING_CLIENT_SECRET ?= 169 | AZURE_SIGNING_TENANT_ID ?= 170 | AZURE_SIGNING_KEY_VAULT_URI ?= 171 | SKIP_SIGNING ?= 172 | 173 | bin/jsign-6.0.jar: 174 | mkdir -p bin 175 | wget https://github.com/ebourg/jsign/releases/download/6.0/jsign-6.0.jar --output-document=bin/jsign-6.0.jar 176 | 177 | sign-goreleaser-exe-amd64: GORELEASER_ARCH := amd64_v1 178 | sign-goreleaser-exe-arm64: GORELEASER_ARCH := arm64 179 | 180 | # Set the shell to bash to allow for the use of bash syntax. 181 | sign-goreleaser-exe-%: SHELL:=/bin/bash 182 | sign-goreleaser-exe-%: bin/jsign-6.0.jar 183 | @# Only sign windows binary if fully configured. 184 | @# Test variables set by joining with | between and looking for || showing at least one variable is empty. 185 | @# Move the binary to a temporary location and sign it there to avoid the target being up-to-date if signing fails. 186 | @set -e; \ 187 | if [[ "${SKIP_SIGNING}" != "true" ]]; then \ 188 | if [[ "|${AZURE_SIGNING_CLIENT_ID}|${AZURE_SIGNING_CLIENT_SECRET}|${AZURE_SIGNING_TENANT_ID}|${AZURE_SIGNING_KEY_VAULT_URI}|" == *"||"* ]]; then \ 189 | echo "Can't sign windows binaries as required configuration not set: AZURE_SIGNING_CLIENT_ID, AZURE_SIGNING_CLIENT_SECRET, AZURE_SIGNING_TENANT_ID, AZURE_SIGNING_KEY_VAULT_URI"; \ 190 | echo "To rebuild with signing delete the unsigned windows exe file and rebuild with the fixed configuration"; \ 191 | if [[ "${CI}" == "true" ]]; then exit 1; fi; \ 192 | else \ 193 | file=dist/build-provider-sign-windows_windows_${GORELEASER_ARCH}/pulumi-resource-provider-boilerplate.exe; \ 194 | mv $${file} $${file}.unsigned; \ 195 | az login --service-principal \ 196 | --username "${AZURE_SIGNING_CLIENT_ID}" \ 197 | --password "${AZURE_SIGNING_CLIENT_SECRET}" \ 198 | --tenant "${AZURE_SIGNING_TENANT_ID}" \ 199 | --output none; \ 200 | ACCESS_TOKEN=$$(az account get-access-token --resource "https://vault.azure.net" | jq -r .accessToken); \ 201 | java -jar bin/jsign-6.0.jar \ 202 | --storetype AZUREKEYVAULT \ 203 | --keystore "PulumiCodeSigning" \ 204 | --url "${AZURE_SIGNING_KEY_VAULT_URI}" \ 205 | --storepass "$${ACCESS_TOKEN}" \ 206 | $${file}.unsigned; \ 207 | mv $${file}.unsigned $${file}; \ 208 | az logout; \ 209 | fi; \ 210 | fi 211 | 212 | # To make an immediately observable change to .ci-mgmt.yaml: 213 | # 214 | # - Edit .ci-mgmt.yaml 215 | # - Run make ci-mgmt to apply the change locally. 216 | # 217 | ci-mgmt: .ci-mgmt.yaml 218 | go run github.com/pulumi/ci-mgmt/provider-ci@master generate 219 | .PHONY: ci-mgmt 220 | 221 | .PHONY: codegen 222 | codegen: # Required by CI 223 | 224 | .PHONY: generate_schema 225 | generate_schema: ${SCHEMA_PATH} # Required by CI 226 | 227 | .PHONY: build_go install_go_sdk 228 | generate_go: sdk/go # Required by CI 229 | build_go: # Required by CI 230 | 231 | .PHONY: build_java install_java_sdk 232 | generate_java: sdk/java # Required by CI 233 | build_java: # Required by CI 234 | 235 | .PHONY: build_python install_python_sdk 236 | generate_python: sdk/python # Required by CI 237 | build_python: # Required by CI 238 | 239 | .PHONY: build_nodejs install_nodejs_sdk 240 | generate_nodejs: sdk/nodejs # Required by CI 241 | build_nodejs: # Required by CI 242 | 243 | .PHONY: build_dotnet install_dotnet_sdk 244 | generate_dotnet: sdk/dotnet # Required by CI 245 | build_dotnet: # Required by CI 246 | 247 | bin/pulumi-gen-${PACK}: # Required by CI 248 | touch bin/pulumi-gen-${PACK} 249 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Pulumi Native Provider Boilerplate 2 | 3 | This repository is a boilerplate showing how to create and locally test a native Pulumi provider (with examples of both CustomResource and ComponentResource [resource types](https://www.pulumi.com/docs/iac/concepts/resources/)). 4 | 5 | ## Authoring a Pulumi Native Provider 6 | 7 | This boilerplate creates a working Pulumi-owned provider named `provider-boilerplate`. 8 | It implements a random number generator that you can [build and test out for yourself](#test-against-the-example) and then replace the Random code with code specific to your provider. 9 | 10 | 11 | ### Prerequisites 12 | 13 | You will need to ensure the following tools are installed and present in your `$PATH`: 14 | 15 | * [`pulumictl`](https://github.com/pulumi/pulumictl#installation) 16 | * [Go 1.21](https://golang.org/dl/) or 1.latest 17 | * [NodeJS](https://nodejs.org/en/) 14.x. We recommend using [nvm](https://github.com/nvm-sh/nvm) to manage NodeJS installations. 18 | * [Yarn](https://yarnpkg.com/) 19 | * [TypeScript](https://www.typescriptlang.org/) 20 | * [Python](https://www.python.org/downloads/) (called as `python3`). For recent versions of MacOS, the system-installed version is fine. 21 | * [.NET](https://dotnet.microsoft.com/download) 22 | 23 | 24 | ### Build & test the boilerplate provider 25 | 26 | 1. Run `make build install` to build and install the provider. 27 | 1. Run `make gen_examples` to generate the example programs in `examples/` off of the source `examples/yaml` example program. 28 | 1. Run `make up` to run the example program in `examples/yaml`. 29 | 1. Run `make down` to tear down the example program. 30 | 31 | ### Creating a new provider repository 32 | 33 | Pulumi offers this repository as a [GitHub template repository](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-repository-from-a-template) for convenience. From this repository: 34 | 35 | 1. Click "Use this template". 36 | 1. Set the following options: 37 | * Owner: pulumi 38 | * Repository name: pulumi-provider-boilerplate (replace "provider-boilerplate" with the name of your provider) 39 | * Description: Pulumi provider for xyz 40 | * Repository type: Public 41 | 1. Clone the generated repository. 42 | 43 | From the templated repository: 44 | 45 | 1. Run the following command to update files to use the name of your provider (third-party: use your GitHub organization/username): 46 | 47 | ```bash 48 | make prepare NAME=foo ORG=myorg REPOSITORY=github.com/myorg/pulumi-foo 49 | ``` 50 | 51 | This will do the following: 52 | - rename folders in `provider/cmd` to `pulumi-resource-{NAME}` 53 | - replace dependencies in `provider/go.mod` to reflect your repository name 54 | - find and replace all instances of `provider-boilerplate` with the `NAME` of your provider. 55 | - find and replace all instances of the boilerplate `abc` with the `ORG` of your provider. 56 | - replace all instances of the `github.com/pulumi/pulumi-provider-boilerplate` repository with the `REPOSITORY` location 57 | 58 | #### Build the provider and install the plugin 59 | 60 | ```bash 61 | $ make build install 62 | ``` 63 | 64 | This will: 65 | 66 | 1. Create the SDK codegen binary and place it in a `./bin` folder (gitignored) 67 | 2. Create the provider binary and place it in the `./bin` folder (gitignored) 68 | 3. Generate the dotnet, Go, Node, and Python SDKs and place them in the `./sdk` folder 69 | 4. Install the provider on your machine. 70 | 71 | #### Test against the example 72 | 73 | ```bash 74 | $ cd examples/simple 75 | $ yarn link @pulumi/provider-boilerplate 76 | $ yarn install 77 | $ pulumi stack init test 78 | $ pulumi up 79 | ``` 80 | 81 | Now that you have completed all of the above steps, you have a working provider that generates a random string for you. 82 | 83 | #### A brief repository overview 84 | 85 | You now have: 86 | 87 | 1. A `provider/` folder containing the building and implementation logic 88 | 1. `cmd/pulumi-resource-provider-boilerplate/main.go` - holds the provider's sample implementation logic. 89 | 2. `deployment-templates` - a set of files to help you around deployment and publication 90 | 3. `sdk` - holds the generated code libraries created by `pulumi gen-sdk` 91 | 4. `examples` a folder of Pulumi programs to try locally and/or use in CI. 92 | 5. A `Makefile` and this `README`. 93 | 94 | #### Additional Details 95 | 96 | This repository depends on the pulumi-go-provider library. For more details on building providers, please check 97 | the [Pulumi Go Provider docs](https://github.com/pulumi/pulumi-go-provider). 98 | 99 | ### Build Examples 100 | 101 | Create an example program using the resources defined in your provider, and place it in the `examples/` folder. 102 | 103 | You can now repeat the steps for [build, install, and test](#test-against-the-example). 104 | 105 | ## Configuring CI and releases 106 | 107 | 1. Follow the instructions laid out in the [deployment templates](./deployment-templates/README-DEPLOYMENT.md). 108 | 109 | ## References 110 | 111 | Other resources/examples for implementing providers: 112 | * [Pulumi Command provider](https://github.com/pulumi/pulumi-command/blob/master/provider/pkg/provider/provider.go) 113 | * [Pulumi Go Provider repository](https://github.com/pulumi/pulumi-go-provider) 114 | -------------------------------------------------------------------------------- /deployment-templates/.goreleaser.yml: -------------------------------------------------------------------------------- 1 | archives: 2 | - id: archive 3 | name_template: '{{ .Binary }}-{{ .Tag }}-{{ .Os }}-{{ .Arch }}' 4 | before: 5 | hooks: 6 | - make gen 7 | builds: 8 | - binary: pulumi-resource-xyz 9 | dir: provider 10 | env: 11 | - CGO_ENABLED=0 12 | goarch: 13 | - amd64 14 | - arm64 15 | goos: 16 | - darwin 17 | - windows 18 | - linux 19 | ldflags: 20 | # The line below MUST align with the module in current provider/go.mod 21 | - -X github.com/your-org-name/pulumi-xyz/provider/Version={{.Tag }} 22 | main: ./cmd/pulumi-resource-xyz/ 23 | changelog: 24 | skip: true 25 | release: 26 | disable: false 27 | prerelease: auto 28 | snapshot: 29 | name_template: '{{ .Tag }}-SNAPSHOT' 30 | -------------------------------------------------------------------------------- /deployment-templates/README-DEPLOYMENT.md: -------------------------------------------------------------------------------- 1 | # Configure 2 | 3 | 1. Create a directory at the root of your repo called .github/workflows 4 | 5 | 1. Place the release.yml from this directory there 6 | 7 | 1. Place the .goreleaser.yml from this directory at the root of your repo 8 | 9 | 1. Obtain needed accounts and tokens from the language specific package managers you will use 10 | 11 | 1. Add any needed tokens to the actions secrets for your repository or organization 12 | 13 | 1. Customize the release.yml with the correct tokens using the format: 14 | 15 | `${{ secrets.MyTokenName }}` 16 | 17 | 1. Customize .goreleaser.yml for your provider, replacing any instances of 'xyz' with your provider's name, and paying special attention that the ldlflags are set to match your provider/go.mod exactly: 18 | 19 | `-X github.com/pulumi/pulumi-aws/provider/v5/pkg/version.Version={{.Tag}}` 20 | 21 | 1. Delete this directory if desired 22 | 23 | 24 | # Deploy 25 | 26 | 1. Push a tag to your repo in the format "v0.0.0" to initiate a release 27 | 28 | 1. IMPORTANT: also add a tag in the format "sdk/v0.0.0" for the Go SDK 29 | -------------------------------------------------------------------------------- /deployment-templates/release.yml: -------------------------------------------------------------------------------- 1 | name: release 2 | on: 3 | push: 4 | tags: 5 | - v*.*.* 6 | - '!v*.*.*-**' 7 | env: 8 | PROVIDER: "YOUR PROVIDER NAME HERE eg: xyz" 9 | # THIS GITHUB_TOKEN IS A REQUIREMENT TO BE ABLE TO WRITE TO GH RELEASES 10 | GITHUB_TOKEN: ${{ YOUR GITHUB TOKEN HERE }} 11 | # IF YOU NEED TO PUBLISH A NPM PACKAGE THEN ENSURE A NPM_TOKEN SECRET IS SET 12 | # AND PUBLISH_NPM: TRUE. IF YOU WANT TO PUBLISH TO A PRIVATE NPM REGISTRY 13 | # THEN ENSURE THE NPM_REGISTRY_URL IS CHANGED 14 | NODE_AUTH_TOKEN: ${{ YOUR NPM TOKEN HERE }} 15 | NPM_TOKEN: ${{ YOUR NPM TOKEN HERE }} 16 | PUBLISH_NPM: true 17 | NPM_REGISTRY_URL: https://registry.npmjs.org 18 | # IF YOU NEED TO PUBLISH A NUGET PACKAGE THEN ENSURE AN NUGET_PUBLISH_KEY 19 | # SECRET IS SET AND PUBLISH_NUGET: TRUE. IF YOU WANT TO PUBLISH TO AN ALTERNATIVE 20 | # NPM REGISTRY THEN ENSURE THE NPM_REGISTRY_URL IS CHANGED 21 | NUGET_PUBLISH_KEY: ${{ YOUR NUGET PUBLISH KEY HERE }} 22 | NUGET_FEED_URL: https://api.nuget.org/v3/index.json 23 | PUBLISH_NUGET: true 24 | # IF YOU NEED TO PUBLISH A PYPI PACKAGE THEN ENSURE AN PYPI_API_TOKEN 25 | # SECRET IS SET AND PUBLISH_PYPI: TRUE. IF YOU WANT TO PUBLISH TO AN ALTERNATIVE 26 | # PYPI REGISTRY THEN ENSURE THE PYPI_REPOSITORY_URL IS SET. IF YOU ARE USING AN API_TOKEN THEN 27 | # YOU DO NOT NEED TO CHANGE THE PYPI_USERNAME (__token__) , IF YOU ARE USING PASSWORD AUTHENTICATION THEN YOU WILL 28 | # NEED TO CHANGE TO USE THE CORRECT PASSWORD 29 | PYPI_PASSWORD: ${{ YOUR PYPI PASSWORD HERE }} 30 | PYPI_USERNAME: "YOUR PYPI USERNAME HERE" 31 | PYPI_REPOSITORY_URL: "" 32 | PUBLISH_PYPI: true 33 | jobs: 34 | publish_binary: 35 | name: publish 36 | runs-on: ubuntu-latest 37 | steps: 38 | - name: Checkout Repo 39 | uses: actions/checkout@v2 40 | - name: Unshallow clone for tags 41 | run: git fetch --prune --unshallow --tags 42 | - name: Install Go 43 | uses: actions/setup-go@v2 44 | with: 45 | go-version: ${{matrix.goversion}} 46 | - name: Install pulumictl 47 | uses: jaxxstorm/action-install-gh-release@v1.5.0 48 | with: 49 | repo: pulumi/pulumictl 50 | - name: Run GoReleaser 51 | uses: goreleaser/goreleaser-action@v2 52 | with: 53 | args: -p 3 release --rm-dist 54 | version: latest 55 | strategy: 56 | fail-fast: true 57 | matrix: 58 | goversion: 59 | - 1.17.x 60 | publish_sdk: 61 | name: Publish SDKs 62 | runs-on: ubuntu-latest 63 | needs: publish_binary 64 | steps: 65 | - name: Checkout Repo 66 | uses: actions/checkout@v2 67 | - name: Unshallow clone for tags 68 | run: git fetch --prune --unshallow --tags 69 | - name: Install Go 70 | uses: actions/setup-go@v2 71 | with: 72 | go-version: ${{ matrix.goversion }} 73 | - name: Install pulumictl 74 | uses: jaxxstorm/action-install-gh-release@v1.5.0 75 | with: 76 | repo: pulumi/pulumictl 77 | - name: Install Pulumi CLI 78 | uses: pulumi/action-install-pulumi-cli@v2.0.0 79 | - name: Setup Node 80 | uses: actions/setup-node@v1 81 | with: 82 | node-version: ${{matrix.nodeversion}} 83 | registry-url: ${{env.NPM_REGISTRY_URL}} 84 | - name: Setup DotNet 85 | uses: actions/setup-dotnet@v1 86 | with: 87 | dotnet-version: ${{matrix.dotnetversion}} 88 | - name: Setup Python 89 | uses: actions/setup-python@v1 90 | with: 91 | python-version: ${{matrix.pythonversion}} 92 | - name: Generate SDK 93 | run: make ${{ matrix.language }}_sdk 94 | - name: Check worktree clean 95 | run: | 96 | git update-index -q --refresh 97 | if ! git diff-files --quiet; then 98 | >&2 echo "error: working tree is not clean, aborting!" 99 | git status 100 | git diff 101 | exit 1 102 | fi 103 | - name: Compress SDK folder 104 | run: tar -zcf sdk/${{ matrix.language }}.tar.gz -C sdk/${{ matrix.language }} . 105 | - name: Upload artifacts 106 | uses: actions/upload-artifact@v2 107 | with: 108 | name: ${{ matrix.language }}-sdk.tar.gz 109 | path: ${{ github.workspace}}/sdk/${{ matrix.language }}.tar.gz 110 | - if: ${{ matrix.language == 'python' && env.PUBLISH_PYPI == 'true' }} 111 | name: Publish package to PyPI 112 | uses: pypa/gh-action-pypi-publish@release/v1 113 | with: 114 | user: ${{ env.PYPI_USERNAME }} 115 | password: ${{ env.PYPI_PASSWORD }} 116 | packages-dir: ${{github.workspace}}/sdk/python/bin/dist 117 | - if: ${{ matrix.language == 'nodejs' && env.PUBLISH_NPM == 'true' }} 118 | uses: JS-DevTools/npm-publish@v1 119 | with: 120 | access: "public" 121 | token: ${{ env.NPM_TOKEN }} 122 | package: ${{github.workspace}}/sdk/nodejs/bin/package.json 123 | - if: ${{ matrix.language == 'dotnet' && env.PUBLISH_NUGET == 'true' }} 124 | name: publish nuget package 125 | run: | 126 | dotnet nuget push ${{github.workspace}}/sdk/dotnet/bin/Debug/*.nupkg -s ${{ env.NUGET_FEED_URL }} -k ${{ env.NUGET_PUBLISH_KEY }} 127 | echo "done publishing packages" 128 | strategy: 129 | fail-fast: true 130 | matrix: 131 | dotnetversion: 132 | - 3.1.301 133 | goversion: 134 | - 1.18.x 135 | language: 136 | - nodejs 137 | - python 138 | - dotnet 139 | - go 140 | nodeversion: 141 | - 14.x 142 | pythonversion: 143 | - "3.9" 144 | -------------------------------------------------------------------------------- /examples/base_test.go: -------------------------------------------------------------------------------- 1 | package examples 2 | 3 | import ( 4 | "github.com/pulumi/providertest/providers" 5 | goprovider "github.com/pulumi/pulumi-go-provider" 6 | "github.com/pulumi/pulumi-provider-boilerplate/provider" 7 | pulumirpc "github.com/pulumi/pulumi/sdk/v3/proto/go" 8 | ) 9 | 10 | var providerFactory = func(_ providers.PulumiTest) (pulumirpc.ResourceProviderServer, error) { 11 | return goprovider.RawServer("provider-boilerplate", "1.0.0", provider.Provider())(nil) 12 | } 13 | -------------------------------------------------------------------------------- /examples/dotnet/.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Aa][Rr][Mm]/ 27 | [Aa][Rr][Mm]64/ 28 | bld/ 29 | [Bb]in/ 30 | [Oo]bj/ 31 | [Ll]og/ 32 | [Ll]ogs/ 33 | 34 | # Visual Studio 2015/2017 cache/options directory 35 | .vs/ 36 | # Uncomment if you have tasks that create the project's static files in wwwroot 37 | #wwwroot/ 38 | 39 | # Visual Studio 2017 auto generated files 40 | Generated\ Files/ 41 | 42 | # MSTest test Results 43 | [Tt]est[Rr]esult*/ 44 | [Bb]uild[Ll]og.* 45 | 46 | # NUnit 47 | *.VisualState.xml 48 | TestResult.xml 49 | nunit-*.xml 50 | 51 | # Build Results of an ATL Project 52 | [Dd]ebugPS/ 53 | [Rr]eleasePS/ 54 | dlldata.c 55 | 56 | # Benchmark Results 57 | BenchmarkDotNet.Artifacts/ 58 | 59 | # .NET Core 60 | project.lock.json 61 | project.fragment.lock.json 62 | artifacts/ 63 | 64 | # StyleCop 65 | StyleCopReport.xml 66 | 67 | # Files built by Visual Studio 68 | *_i.c 69 | *_p.c 70 | *_h.h 71 | *.ilk 72 | *.meta 73 | *.obj 74 | *.iobj 75 | *.pch 76 | *.pdb 77 | *.ipdb 78 | *.pgc 79 | *.pgd 80 | *.rsp 81 | *.sbr 82 | *.tlb 83 | *.tli 84 | *.tlh 85 | *.tmp 86 | *.tmp_proj 87 | *_wpftmp.csproj 88 | *.log 89 | *.vspscc 90 | *.vssscc 91 | .builds 92 | *.pidb 93 | *.svclog 94 | *.scc 95 | 96 | # Chutzpah Test files 97 | _Chutzpah* 98 | 99 | # Visual C++ cache files 100 | ipch/ 101 | *.aps 102 | *.ncb 103 | *.opendb 104 | *.opensdf 105 | *.sdf 106 | *.cachefile 107 | *.VC.db 108 | *.VC.VC.opendb 109 | 110 | # Visual Studio profiler 111 | *.psess 112 | *.vsp 113 | *.vspx 114 | *.sap 115 | 116 | # Visual Studio Trace Files 117 | *.e2e 118 | 119 | # TFS 2012 Local Workspace 120 | $tf/ 121 | 122 | # Guidance Automation Toolkit 123 | *.gpState 124 | 125 | # ReSharper is a .NET coding add-in 126 | _ReSharper*/ 127 | *.[Rr]e[Ss]harper 128 | *.DotSettings.user 129 | 130 | # JustCode is a .NET coding add-in 131 | .JustCode 132 | 133 | # TeamCity is a build add-in 134 | _TeamCity* 135 | 136 | # DotCover is a Code Coverage Tool 137 | *.dotCover 138 | 139 | # AxoCover is a Code Coverage Tool 140 | .axoCover/* 141 | !.axoCover/settings.json 142 | 143 | # Visual Studio code coverage results 144 | *.coverage 145 | *.coveragexml 146 | 147 | # NCrunch 148 | _NCrunch_* 149 | .*crunch*.local.xml 150 | nCrunchTemp_* 151 | 152 | # MightyMoose 153 | *.mm.* 154 | AutoTest.Net/ 155 | 156 | # Web workbench (sass) 157 | .sass-cache/ 158 | 159 | # Installshield output folder 160 | [Ee]xpress/ 161 | 162 | # DocProject is a documentation generator add-in 163 | DocProject/buildhelp/ 164 | DocProject/Help/*.HxT 165 | DocProject/Help/*.HxC 166 | DocProject/Help/*.hhc 167 | DocProject/Help/*.hhk 168 | DocProject/Help/*.hhp 169 | DocProject/Help/Html2 170 | DocProject/Help/html 171 | 172 | # Click-Once directory 173 | publish/ 174 | 175 | # Publish Web Output 176 | *.[Pp]ublish.xml 177 | *.azurePubxml 178 | # Note: Comment the next line if you want to checkin your web deploy settings, 179 | # but database connection strings (with potential passwords) will be unencrypted 180 | *.pubxml 181 | *.publishproj 182 | 183 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 184 | # checkin your Azure Web App publish settings, but sensitive information contained 185 | # in these scripts will be unencrypted 186 | PublishScripts/ 187 | 188 | # NuGet Packages 189 | *.nupkg 190 | # NuGet Symbol Packages 191 | *.snupkg 192 | # The packages folder can be ignored because of Package Restore 193 | **/[Pp]ackages/* 194 | # except build/, which is used as an MSBuild target. 195 | !**/[Pp]ackages/build/ 196 | # Uncomment if necessary however generally it will be regenerated when needed 197 | #!**/[Pp]ackages/repositories.config 198 | # NuGet v3's project.json files produces more ignorable files 199 | *.nuget.props 200 | *.nuget.targets 201 | 202 | # Microsoft Azure Build Output 203 | csx/ 204 | *.build.csdef 205 | 206 | # Microsoft Azure Emulator 207 | ecf/ 208 | rcf/ 209 | 210 | # Windows Store app package directories and files 211 | AppPackages/ 212 | BundleArtifacts/ 213 | Package.StoreAssociation.xml 214 | _pkginfo.txt 215 | *.appx 216 | *.appxbundle 217 | *.appxupload 218 | 219 | # Visual Studio cache files 220 | # files ending in .cache can be ignored 221 | *.[Cc]ache 222 | # but keep track of directories ending in .cache 223 | !?*.[Cc]ache/ 224 | 225 | # Others 226 | ClientBin/ 227 | ~$* 228 | *~ 229 | *.dbmdl 230 | *.dbproj.schemaview 231 | *.jfm 232 | *.pfx 233 | *.publishsettings 234 | orleans.codegen.cs 235 | 236 | # Including strong name files can present a security risk 237 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 238 | #*.snk 239 | 240 | # Since there are multiple workflows, uncomment next line to ignore bower_components 241 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 242 | #bower_components/ 243 | 244 | # RIA/Silverlight projects 245 | Generated_Code/ 246 | 247 | # Backup & report files from converting an old project file 248 | # to a newer Visual Studio version. Backup files are not needed, 249 | # because we have git ;-) 250 | _UpgradeReport_Files/ 251 | Backup*/ 252 | UpgradeLog*.XML 253 | UpgradeLog*.htm 254 | ServiceFabricBackup/ 255 | *.rptproj.bak 256 | 257 | # SQL Server files 258 | *.mdf 259 | *.ldf 260 | *.ndf 261 | 262 | # Business Intelligence projects 263 | *.rdl.data 264 | *.bim.layout 265 | *.bim_*.settings 266 | *.rptproj.rsuser 267 | *- [Bb]ackup.rdl 268 | *- [Bb]ackup ([0-9]).rdl 269 | *- [Bb]ackup ([0-9][0-9]).rdl 270 | 271 | # Microsoft Fakes 272 | FakesAssemblies/ 273 | 274 | # GhostDoc plugin setting file 275 | *.GhostDoc.xml 276 | 277 | # Node.js Tools for Visual Studio 278 | .ntvs_analysis.dat 279 | node_modules/ 280 | 281 | # Visual Studio 6 build log 282 | *.plg 283 | 284 | # Visual Studio 6 workspace options file 285 | *.opt 286 | 287 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 288 | *.vbw 289 | 290 | # Visual Studio LightSwitch build output 291 | **/*.HTMLClient/GeneratedArtifacts 292 | **/*.DesktopClient/GeneratedArtifacts 293 | **/*.DesktopClient/ModelManifest.xml 294 | **/*.Server/GeneratedArtifacts 295 | **/*.Server/ModelManifest.xml 296 | _Pvt_Extensions 297 | 298 | # Paket dependency manager 299 | .paket/paket.exe 300 | paket-files/ 301 | 302 | # FAKE - F# Make 303 | .fake/ 304 | 305 | # CodeRush personal settings 306 | .cr/personal 307 | 308 | # Python Tools for Visual Studio (PTVS) 309 | __pycache__/ 310 | *.pyc 311 | 312 | # Cake - Uncomment if you are using it 313 | # tools/** 314 | # !tools/packages.config 315 | 316 | # Tabs Studio 317 | *.tss 318 | 319 | # Telerik's JustMock configuration file 320 | *.jmconfig 321 | 322 | # BizTalk build output 323 | *.btp.cs 324 | *.btm.cs 325 | *.odx.cs 326 | *.xsd.cs 327 | 328 | # OpenCover UI analysis results 329 | OpenCover/ 330 | 331 | # Azure Stream Analytics local run output 332 | ASALocalRun/ 333 | 334 | # MSBuild Binary and Structured Log 335 | *.binlog 336 | 337 | # NVidia Nsight GPU debugger configuration file 338 | *.nvuser 339 | 340 | # MFractors (Xamarin productivity tool) working folder 341 | .mfractor/ 342 | 343 | # Local History for Visual Studio 344 | .localhistory/ 345 | 346 | # BeatPulse healthcheck temp database 347 | healthchecksdb 348 | 349 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 350 | MigrationBackup/ 351 | 352 | # Ionide (cross platform F# VS Code tools) working folder 353 | .ionide/ 354 | -------------------------------------------------------------------------------- /examples/dotnet/Program.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using Pulumi; 4 | using Boilerplate = Mynamespace.ProviderBoilerplate; 5 | 6 | return await Deployment.RunAsync(() => 7 | { 8 | var myRandomResource = new Boilerplate.Random("myRandomResource", new() 9 | { 10 | Length = 24, 11 | }); 12 | 13 | var myRandomComponent = new Boilerplate.RandomComponent("myRandomComponent", new() 14 | { 15 | Length = 24, 16 | }); 17 | 18 | return new Dictionary 19 | { 20 | ["output"] = 21 | { 22 | { "value", myRandomResource.Result }, 23 | }, 24 | }; 25 | }); 26 | 27 | -------------------------------------------------------------------------------- /examples/dotnet/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: provider-boilerplate 2 | runtime: dotnet 3 | -------------------------------------------------------------------------------- /examples/dotnet/provider-provider-boilerplate.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/dotnet_test.go: -------------------------------------------------------------------------------- 1 | //go:build dotnet || all 2 | // +build dotnet all 3 | 4 | package examples 5 | 6 | import "testing" 7 | 8 | func TestDotnet(t *testing.T) { 9 | // TODO 10 | } 11 | -------------------------------------------------------------------------------- /examples/go/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: provider-boilerplate 2 | runtime: go 3 | -------------------------------------------------------------------------------- /examples/go/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/pulumi/pulumi-provider-boilerplate/examples/go 2 | 3 | go 1.24 4 | 5 | toolchain go1.24.2 6 | 7 | replace github.com/mynamespace/provider-boilerplate => ../../ 8 | 9 | require ( 10 | github.com/mynamespace/provider-boilerplate v0.0.0-00010101000000-000000000000 11 | github.com/pulumi/pulumi/sdk/v3 v3.173.0 12 | ) 13 | 14 | require ( 15 | dario.cat/mergo v1.0.0 // indirect 16 | github.com/BurntSushi/toml v1.2.1 // indirect 17 | github.com/Microsoft/go-winio v0.6.1 // indirect 18 | github.com/ProtonMail/go-crypto v1.1.3 // indirect 19 | github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect 20 | github.com/agext/levenshtein v1.2.3 // indirect 21 | github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect 22 | github.com/atotto/clipboard v0.1.4 // indirect 23 | github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect 24 | github.com/blang/semver v3.5.1+incompatible // indirect 25 | github.com/charmbracelet/bubbles v0.16.1 // indirect 26 | github.com/charmbracelet/bubbletea v0.25.0 // indirect 27 | github.com/charmbracelet/lipgloss v0.7.1 // indirect 28 | github.com/cheggaaa/pb v1.0.29 // indirect 29 | github.com/cloudflare/circl v1.3.7 // indirect 30 | github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 // indirect 31 | github.com/cyphar/filepath-securejoin v0.3.6 // indirect 32 | github.com/djherbis/times v1.5.0 // indirect 33 | github.com/emirpasic/gods v1.18.1 // indirect 34 | github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect 35 | github.com/go-git/go-billy/v5 v5.6.1 // indirect 36 | github.com/go-git/go-git/v5 v5.13.1 // indirect 37 | github.com/gogo/protobuf v1.3.2 // indirect 38 | github.com/golang/glog v1.2.4 // indirect 39 | github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect 40 | github.com/google/uuid v1.6.0 // indirect 41 | github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 // indirect 42 | github.com/hashicorp/errwrap v1.1.0 // indirect 43 | github.com/hashicorp/go-multierror v1.1.1 // indirect 44 | github.com/hashicorp/hcl/v2 v2.22.0 // indirect 45 | github.com/inconshreveable/mousetrap v1.1.0 // indirect 46 | github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect 47 | github.com/kevinburke/ssh_config v1.2.0 // indirect 48 | github.com/lucasb-eyer/go-colorful v1.2.0 // indirect 49 | github.com/mattn/go-isatty v0.0.20 // indirect 50 | github.com/mattn/go-localereader v0.0.1 // indirect 51 | github.com/mattn/go-runewidth v0.0.15 // indirect 52 | github.com/mitchellh/go-ps v1.0.0 // indirect 53 | github.com/mitchellh/go-wordwrap v1.0.1 // indirect 54 | github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect 55 | github.com/muesli/cancelreader v0.2.2 // indirect 56 | github.com/muesli/reflow v0.3.0 // indirect 57 | github.com/muesli/termenv v0.15.2 // indirect 58 | github.com/opentracing/basictracer-go v1.1.0 // indirect 59 | github.com/opentracing/opentracing-go v1.2.0 // indirect 60 | github.com/pgavlin/fx v0.1.6 // indirect 61 | github.com/pjbgf/sha1cd v0.3.0 // indirect 62 | github.com/pkg/errors v0.9.1 // indirect 63 | github.com/pkg/term v1.1.0 // indirect 64 | github.com/pulumi/appdash v0.0.0-20231130102222-75f619a67231 // indirect 65 | github.com/pulumi/esc v0.14.2 // indirect 66 | github.com/rivo/uniseg v0.4.4 // indirect 67 | github.com/rogpeppe/go-internal v1.12.0 // indirect 68 | github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 // indirect 69 | github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 // indirect 70 | github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect 71 | github.com/skeema/knownhosts v1.3.0 // indirect 72 | github.com/spf13/cobra v1.8.0 // indirect 73 | github.com/spf13/pflag v1.0.5 // indirect 74 | github.com/texttheater/golang-levenshtein v1.0.1 // indirect 75 | github.com/uber/jaeger-client-go v2.30.0+incompatible // indirect 76 | github.com/uber/jaeger-lib v2.4.1+incompatible // indirect 77 | github.com/xanzy/ssh-agent v0.3.3 // indirect 78 | github.com/zclconf/go-cty v1.14.0 // indirect 79 | go.uber.org/atomic v1.11.0 // indirect 80 | golang.org/x/crypto v0.37.0 // indirect 81 | golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect 82 | golang.org/x/mod v0.19.0 // indirect 83 | golang.org/x/net v0.39.0 // indirect 84 | golang.org/x/sync v0.13.0 // indirect 85 | golang.org/x/sys v0.32.0 // indirect 86 | golang.org/x/term v0.31.0 // indirect 87 | golang.org/x/text v0.24.0 // indirect 88 | golang.org/x/tools v0.23.0 // indirect 89 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect 90 | google.golang.org/grpc v1.67.1 // indirect 91 | google.golang.org/protobuf v1.36.6 // indirect 92 | gopkg.in/warnings.v0 v0.1.2 // indirect 93 | gopkg.in/yaml.v3 v3.0.1 // indirect 94 | lukechampine.com/frand v1.4.2 // indirect 95 | ) 96 | -------------------------------------------------------------------------------- /examples/go/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | boilerplate "github.com/mynamespace/provider-boilerplate/sdk/go/provider-boilerplate" 5 | "github.com/pulumi/pulumi/sdk/v3/go/pulumi" 6 | ) 7 | 8 | func main() { 9 | pulumi.Run(func(ctx *pulumi.Context) error { 10 | myRandomResource, err := boilerplate.NewRandom(ctx, "myRandomResource", &boilerplate.RandomArgs{ 11 | Length: pulumi.Int(24), 12 | }) 13 | if err != nil { 14 | return err 15 | } 16 | _, err = boilerplate.NewRandomComponent(ctx, "myRandomComponent", &boilerplate.RandomComponentArgs{ 17 | Length: pulumi.Int(24), 18 | }) 19 | if err != nil { 20 | return err 21 | } 22 | ctx.Export("output", pulumi.StringMap{ 23 | "value": myRandomResource.Result, 24 | }) 25 | return nil 26 | }) 27 | } 28 | -------------------------------------------------------------------------------- /examples/go_test.go: -------------------------------------------------------------------------------- 1 | //go:build go || all 2 | // +build go all 3 | 4 | package examples 5 | 6 | import ( 7 | "os" 8 | "path/filepath" 9 | "testing" 10 | 11 | "github.com/pulumi/providertest/pulumitest" 12 | "github.com/pulumi/providertest/pulumitest/opttest" 13 | "github.com/stretchr/testify/require" 14 | ) 15 | 16 | func TestGoExampleLifecycle(t *testing.T) { 17 | cwd, err := os.Getwd() 18 | require.NoError(t, err) 19 | 20 | module := filepath.Join(cwd, "..") 21 | pt := pulumitest.NewPulumiTest(t, "go", 22 | opttest.GoModReplacement("github.com/mynamespace/provider-boilerplate", module), 23 | opttest.AttachProviderServer("provider-boilerplate", providerFactory), 24 | opttest.SkipInstall(), 25 | ) 26 | 27 | pt.Preview(t) 28 | pt.Up(t) 29 | pt.Destroy(t) 30 | } 31 | -------------------------------------------------------------------------------- /examples/java_test.go: -------------------------------------------------------------------------------- 1 | //go:build java || all 2 | // +build java all 3 | 4 | package examples 5 | 6 | import "testing" 7 | 8 | func TestJava(t *testing.T) { 9 | // TODO 10 | } 11 | -------------------------------------------------------------------------------- /examples/nodejs/.gitignore: -------------------------------------------------------------------------------- 1 | /bin/ 2 | /node_modules/ -------------------------------------------------------------------------------- /examples/nodejs/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: provider-boilerplate 2 | runtime: nodejs 3 | -------------------------------------------------------------------------------- /examples/nodejs/index.ts: -------------------------------------------------------------------------------- 1 | import * as pulumi from "@pulumi/pulumi"; 2 | import * as boilerplate from "@mynamespace/provider-boilerplate"; 3 | 4 | const myRandomResource = new boilerplate.Random("myRandomResource", { 5 | length: 24, 6 | }); 7 | const myRandomComponent = new boilerplate.RandomComponent("myRandomComponent", { 8 | length: 24, 9 | }); 10 | export const output = { 11 | value: myRandomResource.result, 12 | }; 13 | -------------------------------------------------------------------------------- /examples/nodejs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "provider-boilerplate", 3 | "devDependencies": { 4 | "@types/node": "^20" 5 | }, 6 | "dependencies": { 7 | "typescript": "^4.0.0", 8 | "@pulumi/pulumi": "3.173.0", 9 | "@mynamespace/provider-boilerplate": "1.0.0-alpha.0+dev" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /examples/nodejs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "strict": true, 4 | "outDir": "bin", 5 | "target": "es2016", 6 | "module": "commonjs", 7 | "moduleResolution": "node", 8 | "sourceMap": true, 9 | "experimentalDecorators": true, 10 | "pretty": true, 11 | "noFallthroughCasesInSwitch": true, 12 | "noImplicitReturns": true, 13 | "forceConsistentCasingInFileNames": true 14 | }, 15 | "files": [ 16 | "index.ts", 17 | ] 18 | } -------------------------------------------------------------------------------- /examples/nodejs_test.go: -------------------------------------------------------------------------------- 1 | //go:build nodejs || all 2 | // +build nodejs all 3 | 4 | package examples 5 | 6 | import ( 7 | "testing" 8 | 9 | "github.com/pulumi/providertest/pulumitest" 10 | "github.com/pulumi/providertest/pulumitest/opttest" 11 | ) 12 | 13 | func TestNodejsExampleLifecycle(t *testing.T) { 14 | t.Skip("linking isn't working correctly") 15 | 16 | pt := pulumitest.NewPulumiTest(t, "nodejs", 17 | opttest.YarnLink("@mynamespace/provider-boilerplate"), 18 | opttest.AttachProviderServer("provider-boilerplate", providerFactory), 19 | ) 20 | 21 | pt.Preview(t) 22 | pt.Up(t) 23 | pt.Destroy(t) 24 | } 25 | -------------------------------------------------------------------------------- /examples/python/.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | venv/ -------------------------------------------------------------------------------- /examples/python/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: provider-boilerplate 2 | runtime: python 3 | -------------------------------------------------------------------------------- /examples/python/__main__.py: -------------------------------------------------------------------------------- 1 | import pulumi 2 | import provider_boilerplate as boilerplate 3 | 4 | my_random_resource = boilerplate.Random("myRandomResource", length=24) 5 | my_random_component = boilerplate.RandomComponent("myRandomComponent", length=24) 6 | pulumi.export("output", { 7 | "value": my_random_resource.result, 8 | }) 9 | -------------------------------------------------------------------------------- /examples/python/requirements.txt: -------------------------------------------------------------------------------- 1 | pulumi-provide-boilerplate==1.0.0 2 | pulumi>=3.0.0,<4.0.0 3 | -------------------------------------------------------------------------------- /examples/python_test.go: -------------------------------------------------------------------------------- 1 | //go:build python || all 2 | // +build python all 3 | 4 | package examples 5 | 6 | import "testing" 7 | 8 | func TestPython(t *testing.T) { 9 | // TODO: https://github.com/pulumi/providertest/issues/39 10 | } 11 | -------------------------------------------------------------------------------- /examples/testdata/recorded/TestProviderUpgrade/yaml/0.0.1/stack.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "deployment": { 4 | "manifest": { 5 | "time": "2025-05-30T14:47:32.241046-07:00", 6 | "magic": "ddbd0ff735ffe7afff6024a5108d8161cc4d85cd0ddbd9ddcc43a35f4b02ead1", 7 | "version": "v3.169.0" 8 | }, 9 | "secrets_providers": { 10 | "type": "passphrase", 11 | "state": { 12 | "salt": "v1:3HkNSDWDx/4=:v1:YyfhcN2mZs7H6q45:tjon1ltzvH7TzYtn7n80R2vNdbKYKA==" 13 | } 14 | }, 15 | "resources": [ 16 | { 17 | "urn": "urn:pulumi:test::provider-boilerplate::pulumi:pulumi:Stack::provider-boilerplate-test", 18 | "custom": false, 19 | "type": "pulumi:pulumi:Stack", 20 | "outputs": { 21 | "output": { 22 | "value": "n31imZ04vLfP2Cbzp9GLnuwq" 23 | } 24 | }, 25 | "created": "2025-05-30T21:47:31.971519Z", 26 | "modified": "2025-05-30T21:47:31.971519Z" 27 | }, 28 | { 29 | "urn": "urn:pulumi:test::provider-boilerplate::pulumi:providers:provider-boilerplate::default", 30 | "custom": true, 31 | "id": "8ebefee5-0c5c-483f-ad91-407e3909b8ee", 32 | "type": "pulumi:providers:provider-boilerplate", 33 | "inputs": { 34 | "__internal": { 35 | "pulumi-go-provider-infer": true, 36 | "pulumi-go-provider-version": "1.0.2" 37 | } 38 | }, 39 | "created": "2025-05-30T21:47:31.979385Z", 40 | "modified": "2025-05-30T21:47:31.979385Z" 41 | }, 42 | { 43 | "urn": "urn:pulumi:test::provider-boilerplate::provider-boilerplate:index:Random::myRandomResource", 44 | "custom": true, 45 | "id": "myRandomResource", 46 | "type": "provider-boilerplate:index:Random", 47 | "inputs": { 48 | "length": 24 49 | }, 50 | "outputs": { 51 | "length": 24, 52 | "result": "n31imZ04vLfP2Cbzp9GLnuwq" 53 | }, 54 | "parent": "urn:pulumi:test::provider-boilerplate::pulumi:pulumi:Stack::provider-boilerplate-test", 55 | "provider": "urn:pulumi:test::provider-boilerplate::pulumi:providers:provider-boilerplate::default::8ebefee5-0c5c-483f-ad91-407e3909b8ee", 56 | "propertyDependencies": { 57 | "length": [] 58 | }, 59 | "created": "2025-05-30T21:47:31.98239Z", 60 | "modified": "2025-05-30T21:47:31.98239Z" 61 | }, 62 | { 63 | "urn": "urn:pulumi:test::provider-boilerplate::provider-boilerplate:index:RandomComponent::myRandomComponent", 64 | "custom": false, 65 | "type": "provider-boilerplate:index:RandomComponent", 66 | "outputs": { 67 | "length": 24, 68 | "password": { 69 | "4dabf18193072939515e22adb298388d": "1b47061264138c4ac30d75fd1eb44270", 70 | "plaintext": "\"REDACTED BY PROVIDERTEST\"" 71 | } 72 | }, 73 | "parent": "urn:pulumi:test::provider-boilerplate::pulumi:pulumi:Stack::provider-boilerplate-test", 74 | "created": "2025-05-30T21:47:31.984582Z", 75 | "modified": "2025-05-30T21:47:31.984582Z" 76 | }, 77 | { 78 | "urn": "urn:pulumi:test::provider-boilerplate::pulumi:providers:random::default_4_18_2", 79 | "custom": true, 80 | "id": "2cf21826-def2-47bb-b564-a49a873c09d0", 81 | "type": "pulumi:providers:random", 82 | "inputs": { 83 | "__internal": {}, 84 | "version": "4.18.2" 85 | }, 86 | "outputs": { 87 | "version": "4.18.2" 88 | }, 89 | "created": "2025-05-30T21:47:32.155789Z", 90 | "modified": "2025-05-30T21:47:32.155789Z" 91 | }, 92 | { 93 | "urn": "urn:pulumi:test::provider-boilerplate::provider-boilerplate:index:RandomComponent$random:index/randomPassword:RandomPassword::myRandomComponent-password", 94 | "custom": true, 95 | "id": "none", 96 | "type": "random:index/randomPassword:RandomPassword", 97 | "inputs": { 98 | "length": 24 99 | }, 100 | "outputs": { 101 | "__meta": "{\"schema_version\":\"3\"}", 102 | "__pulumi_raw_state_delta": { 103 | "obj": { 104 | "ps": { 105 | "keepers": { 106 | "4dabf18193072939515e22adb298388d": "1b47061264138c4ac30d75fd1eb44270", 107 | "plaintext": "{\"replace\":{\"raw\":null}}" 108 | }, 109 | "overrideSpecial": { 110 | "4dabf18193072939515e22adb298388d": "1b47061264138c4ac30d75fd1eb44270", 111 | "plaintext": "{\"replace\":{\"raw\":null}}" 112 | } 113 | } 114 | } 115 | }, 116 | "bcryptHash": { 117 | "4dabf18193072939515e22adb298388d": "1b47061264138c4ac30d75fd1eb44270", 118 | "plaintext": "\"REDACTED BY PROVIDERTEST\"" 119 | }, 120 | "id": "none", 121 | "length": 24, 122 | "lower": true, 123 | "minLower": 0, 124 | "minNumeric": 0, 125 | "minSpecial": 0, 126 | "minUpper": 0, 127 | "number": true, 128 | "numeric": true, 129 | "result": { 130 | "4dabf18193072939515e22adb298388d": "1b47061264138c4ac30d75fd1eb44270", 131 | "plaintext": "\"REDACTED BY PROVIDERTEST\"" 132 | }, 133 | "special": true, 134 | "upper": true 135 | }, 136 | "parent": "urn:pulumi:test::provider-boilerplate::provider-boilerplate:index:RandomComponent::myRandomComponent", 137 | "provider": "urn:pulumi:test::provider-boilerplate::pulumi:providers:random::default_4_18_2::2cf21826-def2-47bb-b564-a49a873c09d0", 138 | "propertyDependencies": { 139 | "length": [] 140 | }, 141 | "additionalSecretOutputs": [ 142 | "bcryptHash", 143 | "result" 144 | ], 145 | "created": "2025-05-30T21:47:32.235864Z", 146 | "modified": "2025-05-30T21:47:32.235864Z" 147 | } 148 | ], 149 | "metadata": {} 150 | } 151 | } -------------------------------------------------------------------------------- /examples/yaml/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: provider-boilerplate 2 | runtime: yaml 3 | 4 | resources: 5 | myRandomResource: 6 | type: provider-boilerplate:Random 7 | properties: 8 | length: 24 9 | myRandomComponent: 10 | type: provider-boilerplate:RandomComponent 11 | properties: 12 | length: 24 13 | 14 | outputs: 15 | output: 16 | value: ${myRandomResource.result} 17 | -------------------------------------------------------------------------------- /examples/yaml/README.md: -------------------------------------------------------------------------------- 1 | # YAML Example Program 2 | 3 | Test Pulumi program written in YAML for testing this provider locally. 4 | 5 | Edit this yaml program to test features of your provider locally. You can run this program using the following command: 6 | 7 | ```bash 8 | pulumi login 9 | pulumi stack init local 10 | pulumi up 11 | ``` 12 | 13 | Note that unlike the rest of the auto-generated examples in the ./examples directory, this example is not automatically generated. It is intended to be a place for you to test your provider locally. 14 | 15 | The remaining examples are language specific examples derived from the `make gen_examples` command supported in this provider's Makefile. These examples are automatically generated and should not be edited directly. To regenerate these examples, run `make gen_examples` in the root of this provider's repository. 16 | -------------------------------------------------------------------------------- /examples/yaml_test.go: -------------------------------------------------------------------------------- 1 | //go:build yaml || all 2 | // +build yaml all 3 | 4 | package examples 5 | 6 | import ( 7 | "testing" 8 | 9 | "github.com/pulumi/providertest" 10 | "github.com/pulumi/providertest/pulumitest" 11 | "github.com/pulumi/providertest/pulumitest/assertpreview" 12 | "github.com/pulumi/providertest/pulumitest/opttest" 13 | ) 14 | 15 | func TestYAMLExampleLifecycle(t *testing.T) { 16 | pt := pulumitest.NewPulumiTest(t, "yaml", 17 | opttest.AttachProviderServer("provider-boilerplate", providerFactory), 18 | opttest.SkipInstall(), 19 | ) 20 | 21 | pt.Preview(t) 22 | pt.Up(t) 23 | pt.Destroy(t) 24 | } 25 | 26 | func TestYAMLExampleUpgrade(t *testing.T) { 27 | pt := pulumitest.NewPulumiTest(t, "yaml", 28 | opttest.AttachProviderServer("provider-boilerplate", providerFactory), 29 | opttest.SkipInstall(), 30 | ) 31 | previewResult := providertest.PreviewProviderUpgrade(t, pt, "provider-boilerplate", "0.0.1") 32 | 33 | assertpreview.HasNoChanges(t, previewResult) 34 | } 35 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/pulumi/pulumi-provider-boilerplate 2 | 3 | go 1.24 4 | 5 | toolchain go1.24.1 6 | 7 | // Play nicely with the generated SDK's fake module path. 8 | replace github.com/mynamespace/provider-boilerplate => . 9 | 10 | require ( 11 | github.com/blang/semver v3.5.1+incompatible 12 | github.com/mynamespace/provider-boilerplate v0.0.0-00010101000000-000000000000 13 | github.com/pulumi/providertest v0.3.1 14 | github.com/pulumi/pulumi-go-provider v1.0.2 15 | github.com/pulumi/pulumi-random/sdk/v4 v4.18.2 16 | github.com/pulumi/pulumi/sdk/v3 v3.173.0 17 | github.com/stretchr/testify v1.10.0 18 | ) 19 | 20 | require ( 21 | dario.cat/mergo v1.0.0 // indirect 22 | github.com/BurntSushi/toml v1.2.1 // indirect 23 | github.com/Microsoft/go-winio v0.6.1 // indirect 24 | github.com/ProtonMail/go-crypto v1.1.3 // indirect 25 | github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect 26 | github.com/agext/levenshtein v1.2.3 // indirect 27 | github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect 28 | github.com/atotto/clipboard v0.1.4 // indirect 29 | github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect 30 | github.com/charmbracelet/bubbles v0.16.1 // indirect 31 | github.com/charmbracelet/bubbletea v0.25.0 // indirect 32 | github.com/charmbracelet/lipgloss v0.7.1 // indirect 33 | github.com/cheggaaa/pb v1.0.29 // indirect 34 | github.com/cloudflare/circl v1.3.7 // indirect 35 | github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 // indirect 36 | github.com/cyphar/filepath-securejoin v0.3.6 // indirect 37 | github.com/davecgh/go-spew v1.1.1 // indirect 38 | github.com/djherbis/times v1.5.0 // indirect 39 | github.com/edsrzf/mmap-go v1.1.0 // indirect 40 | github.com/emirpasic/gods v1.18.1 // indirect 41 | github.com/fsnotify/fsnotify v1.7.0 // indirect 42 | github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect 43 | github.com/go-git/go-billy/v5 v5.6.1 // indirect 44 | github.com/go-git/go-git/v5 v5.13.1 // indirect 45 | github.com/gogo/protobuf v1.3.2 // indirect 46 | github.com/golang/glog v1.2.4 // indirect 47 | github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect 48 | github.com/golang/protobuf v1.5.4 // indirect 49 | github.com/google/uuid v1.6.0 // indirect 50 | github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 // indirect 51 | github.com/hashicorp/errwrap v1.1.0 // indirect 52 | github.com/hashicorp/go-multierror v1.1.1 // indirect 53 | github.com/hashicorp/hcl/v2 v2.22.0 // indirect 54 | github.com/inconshreveable/mousetrap v1.1.0 // indirect 55 | github.com/iwdgo/sigintwindows v0.2.2 // indirect 56 | github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect 57 | github.com/kevinburke/ssh_config v1.2.0 // indirect 58 | github.com/lucasb-eyer/go-colorful v1.2.0 // indirect 59 | github.com/mattn/go-isatty v0.0.20 // indirect 60 | github.com/mattn/go-localereader v0.0.1 // indirect 61 | github.com/mattn/go-runewidth v0.0.15 // indirect 62 | github.com/mitchellh/go-ps v1.0.0 // indirect 63 | github.com/mitchellh/go-wordwrap v1.0.1 // indirect 64 | github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect 65 | github.com/muesli/cancelreader v0.2.2 // indirect 66 | github.com/muesli/reflow v0.3.0 // indirect 67 | github.com/muesli/termenv v0.15.2 // indirect 68 | github.com/natefinch/atomic v1.0.1 // indirect 69 | github.com/nxadm/tail v1.4.11 // indirect 70 | github.com/opentracing/basictracer-go v1.1.0 // indirect 71 | github.com/opentracing/opentracing-go v1.2.0 // indirect 72 | github.com/pgavlin/fx v0.1.6 // indirect 73 | github.com/pgavlin/goldmark v1.1.33-0.20200616210433-b5eb04559386 // indirect 74 | github.com/pjbgf/sha1cd v0.3.0 // indirect 75 | github.com/pkg/errors v0.9.1 // indirect 76 | github.com/pkg/term v1.1.0 // indirect 77 | github.com/pmezard/go-difflib v1.0.0 // indirect 78 | github.com/pulumi/appdash v0.0.0-20231130102222-75f619a67231 // indirect 79 | github.com/pulumi/esc v0.14.2 // indirect 80 | github.com/pulumi/pulumi/pkg/v3 v3.173.0 // indirect 81 | github.com/rivo/uniseg v0.4.4 // indirect 82 | github.com/rogpeppe/go-internal v1.12.0 // indirect 83 | github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 // indirect 84 | github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 // indirect 85 | github.com/segmentio/asm v1.2.0 // indirect 86 | github.com/segmentio/encoding v0.3.6 // indirect 87 | github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect 88 | github.com/skeema/knownhosts v1.3.0 // indirect 89 | github.com/spf13/cast v1.4.1 // indirect 90 | github.com/spf13/cobra v1.8.0 // indirect 91 | github.com/spf13/pflag v1.0.5 // indirect 92 | github.com/texttheater/golang-levenshtein v1.0.1 // indirect 93 | github.com/uber/jaeger-client-go v2.30.0+incompatible // indirect 94 | github.com/uber/jaeger-lib v2.4.1+incompatible // indirect 95 | github.com/xanzy/ssh-agent v0.3.3 // indirect 96 | github.com/zclconf/go-cty v1.14.0 // indirect 97 | go.uber.org/atomic v1.11.0 // indirect 98 | golang.org/x/crypto v0.37.0 // indirect 99 | golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect 100 | golang.org/x/mod v0.19.0 // indirect 101 | golang.org/x/net v0.39.0 // indirect 102 | golang.org/x/sync v0.13.0 // indirect 103 | golang.org/x/sys v0.32.0 // indirect 104 | golang.org/x/term v0.31.0 // indirect 105 | golang.org/x/text v0.24.0 // indirect 106 | golang.org/x/tools v0.23.0 // indirect 107 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect 108 | google.golang.org/grpc v1.67.1 // indirect 109 | google.golang.org/protobuf v1.36.6 // indirect 110 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect 111 | gopkg.in/warnings.v0 v0.1.2 // indirect 112 | gopkg.in/yaml.v3 v3.0.1 // indirect 113 | lukechampine.com/frand v1.4.2 // indirect 114 | ) 115 | -------------------------------------------------------------------------------- /provider/cmd/pulumi-resource-provider-boilerplate/main.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025, Pulumi Corporation. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package main runs the provider's gRPC server. 16 | package main 17 | 18 | import ( 19 | "context" 20 | "fmt" 21 | "os" 22 | 23 | xyz "github.com/pulumi/pulumi-provider-boilerplate/provider" 24 | ) 25 | 26 | // Serve the provider against Pulumi's Provider protocol. 27 | func main() { 28 | err := xyz.Provider().Run(context.Background(), xyz.Name, xyz.Version) 29 | if err != nil { 30 | fmt.Fprintf(os.Stderr, "Error: %s", err.Error()) 31 | os.Exit(1) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /provider/cmd/pulumi-resource-provider-boilerplate/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "provider-boilerplate", 3 | "displayName": "provider-boilerplate", 4 | "namespace": "mynamespace", 5 | "meta": { 6 | "moduleFormat": "(.*)" 7 | }, 8 | "language": { 9 | "csharp": { 10 | "respectSchemaVersion": true 11 | }, 12 | "go": { 13 | "generateResourceContainerTypes": true, 14 | "importBasePath": "github.com/mynamespace/provider-boilerplate/sdk/go/provider-boilerplate", 15 | "respectSchemaVersion": true 16 | }, 17 | "nodejs": { 18 | "respectSchemaVersion": true 19 | }, 20 | "python": { 21 | "pyproject": { 22 | "enabled": true 23 | }, 24 | "respectSchemaVersion": true 25 | } 26 | }, 27 | "config": { 28 | "variables": { 29 | "itsasecret": { 30 | "type": "boolean" 31 | } 32 | } 33 | }, 34 | "provider": { 35 | "type": "object", 36 | "inputProperties": { 37 | "itsasecret": { 38 | "type": "boolean" 39 | } 40 | } 41 | }, 42 | "resources": { 43 | "provider-boilerplate:index:Random": { 44 | "properties": { 45 | "length": { 46 | "type": "integer" 47 | }, 48 | "result": { 49 | "type": "string" 50 | } 51 | }, 52 | "type": "object", 53 | "required": [ 54 | "length", 55 | "result" 56 | ], 57 | "inputProperties": { 58 | "length": { 59 | "type": "integer" 60 | } 61 | }, 62 | "requiredInputs": [ 63 | "length" 64 | ] 65 | }, 66 | "provider-boilerplate:index:RandomComponent": { 67 | "properties": { 68 | "length": { 69 | "type": "integer" 70 | }, 71 | "password": { 72 | "type": "string" 73 | } 74 | }, 75 | "type": "object", 76 | "required": [ 77 | "length", 78 | "password" 79 | ], 80 | "inputProperties": { 81 | "length": { 82 | "type": "integer" 83 | } 84 | }, 85 | "requiredInputs": [ 86 | "length" 87 | ], 88 | "isComponent": true 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /provider/provider.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025, Pulumi Corporation. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package provider implements a simple random resource and component. 16 | package provider 17 | 18 | import ( 19 | "fmt" 20 | 21 | p "github.com/pulumi/pulumi-go-provider" 22 | "github.com/pulumi/pulumi-go-provider/infer" 23 | "github.com/pulumi/pulumi/sdk/v3/go/common/tokens" 24 | ) 25 | 26 | // Version is initialized by the Go linker to contain the semver of this build. 27 | var Version string 28 | 29 | // Name controls how this provider is referenced in package names and elsewhere. 30 | const Name string = "provider-boilerplate" 31 | 32 | // Provider creates a new instance of the provider. 33 | func Provider() p.Provider { 34 | p, err := infer.NewProviderBuilder(). 35 | WithDisplayName("provider-boilerplate"). 36 | WithNamespace("mynamespace"). 37 | WithResources(infer.Resource(Random{})). 38 | WithComponents(infer.ComponentF(NewRandomComponent)). 39 | WithConfig(infer.Config(&Config{})). 40 | WithModuleMap(map[tokens.ModuleName]tokens.ModuleName{ 41 | "provider": "index", 42 | }).Build() 43 | if err != nil { 44 | panic(fmt.Errorf("unable to build provider: %w", err)) 45 | } 46 | return p 47 | } 48 | 49 | // Config defines provider-level configuration 50 | type Config struct { 51 | Scream *bool `pulumi:"itsasecret,optional"` 52 | } 53 | -------------------------------------------------------------------------------- /provider/random_component.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025, Pulumi Corporation. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package provider 16 | 17 | import ( 18 | "github.com/pulumi/pulumi-go-provider/infer" 19 | "github.com/pulumi/pulumi-random/sdk/v4/go/random" 20 | "github.com/pulumi/pulumi/sdk/v3/go/pulumi" 21 | ) 22 | 23 | // RandomComponent represents a Pulumi component resource. 24 | // 25 | // Similar to resources, components have a controlling struct. 26 | // The NewRandomComponent function is responsible for creating 27 | // the component by composing together other resources. 28 | type RandomComponent struct { 29 | pulumi.ResourceState // Component state needs this for tracking nested resource states. 30 | RandomComponentArgs // Include all the input fields in the state. 31 | Password pulumi.StringOutput `pulumi:"password"` 32 | } 33 | 34 | // RandomComponentArgs are inputs to the custom component's constructor. 35 | // 36 | // Similar to resources, components have an input struct, defining what arguments it accepts. 37 | type RandomComponentArgs struct { 38 | Length pulumi.IntInput `pulumi:"length"` 39 | } 40 | 41 | // NewRandomComponent constructs the component. 42 | func NewRandomComponent( 43 | ctx *pulumi.Context, 44 | name string, 45 | args RandomComponentArgs, 46 | opts ...pulumi.ResourceOption, 47 | ) (*RandomComponent, error) { 48 | // Initialize the component state. 49 | comp := &RandomComponent{ 50 | RandomComponentArgs: args, 51 | } 52 | // Register the component resource to which we will attach all other resources. 53 | err := ctx.RegisterComponentResource(Name+":index:RandomComponent", name, comp, opts...) 54 | if err != nil { 55 | return nil, err 56 | } 57 | 58 | // Construct the arguments for the sub-resource. 59 | pArgs := &random.RandomPasswordArgs{ 60 | Length: args.Length, 61 | } 62 | 63 | // We can access provider configuration too if needed. 64 | config := infer.GetConfig[Config](ctx.Context()) 65 | if config.Scream != nil { 66 | pArgs.Lower = pulumi.BoolPtr(*config.Scream) 67 | } 68 | 69 | // Create the sub-resource. Ensure that the sub-resource is parented to the component resource. 70 | password, err := random.NewRandomPassword(ctx, name+"-password", pArgs, pulumi.Parent(comp)) 71 | if err != nil { 72 | return nil, err 73 | } 74 | 75 | // Update the state of the component with output from the sub-resource. 76 | comp.Password = password.Result 77 | return comp, nil 78 | } 79 | -------------------------------------------------------------------------------- /provider/random_resource.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025, Pulumi Corporation. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package provider 16 | 17 | import ( 18 | "context" 19 | "math/rand/v2" 20 | 21 | "github.com/pulumi/pulumi-go-provider/infer" 22 | ) 23 | 24 | // Random is the controller for the resource. 25 | // 26 | // Each resource has a controlling struct. 27 | // Resource behavior is determined by implementing methods on the controlling struct. 28 | // The `Create` method is mandatory, but other methods are optional. 29 | // - Check: Remap inputs before they are typed. 30 | // - Diff: Change how instances of a resource are compared. 31 | // - Update: Mutate a resource in place. 32 | // - Read: Get the state of a resource from the backing provider. 33 | // - Delete: Custom logic when the resource is deleted. 34 | // - Annotate: Describe fields and set defaults for a resource. 35 | // - WireDependencies: Control how outputs and secrets flows through values. 36 | type Random struct{} 37 | 38 | // RandomArgs are the inputs to the random resource's constructor. 39 | // 40 | // Each resource has an input struct, defining what arguments it accepts. 41 | type RandomArgs struct { 42 | // Fields projected into Pulumi must be public and hava a `pulumi:"..."` tag. 43 | // The pulumi tag doesn't need to match the field name, but it's generally a 44 | // good idea. 45 | Length int `pulumi:"length"` 46 | } 47 | 48 | // RandomState is what's persisted in state. 49 | // 50 | // Each resource has a state, describing the fields that exist on the resource. 51 | type RandomState struct { 52 | // It is generally a good idea to embed args in outputs, but it isn't strictly necessary. 53 | RandomArgs 54 | // Here we define a required output called result. 55 | Result string `pulumi:"result"` 56 | } 57 | 58 | // Create creates a new instance of the random resource. 59 | // 60 | // All resources must implement Create at a minimum. 61 | func (Random) Create( 62 | ctx context.Context, 63 | req infer.CreateRequest[RandomArgs], 64 | ) (infer.CreateResponse[RandomState], error) { 65 | name := req.Name 66 | input := req.Inputs 67 | preview := req.DryRun 68 | state := RandomState{RandomArgs: input} 69 | if preview { 70 | return infer.CreateResponse[RandomState]{ID: name, Output: state}, nil 71 | } 72 | state.Result = makeRandom(input.Length) 73 | return infer.CreateResponse[RandomState]{ID: name, Output: state}, nil 74 | } 75 | 76 | func makeRandom(length int) string { 77 | charset := []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") // SED_SKIP 78 | 79 | result := make([]rune, length) 80 | for i := range result { 81 | result[i] = charset[rand.IntN(len(charset))] //nolint:gosec // Intentionally weak random. 82 | } 83 | return string(result) 84 | } 85 | -------------------------------------------------------------------------------- /provider/random_resource_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025, Pulumi Corporation. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package provider 16 | 17 | import ( 18 | "testing" 19 | 20 | "github.com/blang/semver" 21 | "github.com/stretchr/testify/assert" 22 | "github.com/stretchr/testify/require" 23 | 24 | integration "github.com/pulumi/pulumi-go-provider/integration" 25 | presource "github.com/pulumi/pulumi/sdk/v3/go/common/resource" 26 | "github.com/pulumi/pulumi/sdk/v3/go/property" 27 | ) 28 | 29 | func TestRandomResource(t *testing.T) { 30 | t.Parallel() 31 | 32 | server, err := integration.NewServer(t.Context(), 33 | "xyz", 34 | semver.Version{Minor: 1}, 35 | integration.WithProvider(Provider()), 36 | ) 37 | require.NoError(t, err) 38 | 39 | integration.LifeCycleTest{ 40 | Resource: "xyz:index:Random", 41 | Create: integration.Operation{ 42 | Inputs: presource.FromResourcePropertyMap(presource.NewPropertyMapFromMap(map[string]interface{}{ 43 | "length": 24, 44 | })), 45 | 46 | Hook: func(inputs, output property.Map) { 47 | t.Logf("Outputs: %v", output) 48 | result := output.Get("result").AsString() 49 | assert.Len(t, result, 24) 50 | }, 51 | }, 52 | Updates: []integration.Operation{ 53 | { 54 | Inputs: presource.FromResourcePropertyMap(presource.NewPropertyMapFromMap(map[string]interface{}{ 55 | "length": 10, 56 | })), 57 | 58 | Hook: func(inputs, output property.Map) { 59 | result := output.Get("result").AsString() 60 | assert.Len(t, result, 10) 61 | }, 62 | }, 63 | }, 64 | }.Run(t, server) 65 | } 66 | -------------------------------------------------------------------------------- /sdk/dotnet/Config/Config.cs: -------------------------------------------------------------------------------- 1 | // *** WARNING: this file was generated by pulumi-language-dotnet. *** 2 | // *** Do not edit by hand unless you're certain you know what you are doing! *** 3 | 4 | using System; 5 | using System.Collections.Immutable; 6 | 7 | namespace Mynamespace.ProviderBoilerplate 8 | { 9 | public static class Config 10 | { 11 | [global::System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "IDE1006", Justification = 12 | "Double underscore prefix used to avoid conflicts with variable names.")] 13 | private sealed class __Value 14 | { 15 | private readonly Func _getter; 16 | private T _value = default!; 17 | private bool _set; 18 | 19 | public __Value(Func getter) 20 | { 21 | _getter = getter; 22 | } 23 | 24 | public T Get() => _set ? _value : _getter(); 25 | 26 | public void Set(T value) 27 | { 28 | _value = value; 29 | _set = true; 30 | } 31 | } 32 | 33 | private static readonly global::Pulumi.Config __config = new global::Pulumi.Config("provider-boilerplate"); 34 | 35 | private static readonly __Value _itsasecret = new __Value(() => __config.GetBoolean("itsasecret")); 36 | public static bool? Itsasecret 37 | { 38 | get => _itsasecret.Get(); 39 | set => _itsasecret.Set(value); 40 | } 41 | 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /sdk/dotnet/Config/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pulumi/pulumi-provider-boilerplate/a69fee122706ff35eefd524db1773877d0518b56/sdk/dotnet/Config/README.md -------------------------------------------------------------------------------- /sdk/dotnet/Mynamespace.ProviderBoilerplate.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | true 5 | Pulumi Corp. 6 | Pulumi Corp. 7 | 8 | 9 | 10 | 11 | logo.png 12 | 1.0.0-alpha.0+dev 13 | 14 | net6.0 15 | enable 16 | 17 | 18 | 19 | true 20 | 1701;1702;1591 21 | 22 | 23 | 24 | $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb 25 | true 26 | true 27 | 28 | 29 | 30 | true 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | True 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /sdk/dotnet/Provider.cs: -------------------------------------------------------------------------------- 1 | // *** WARNING: this file was generated by pulumi-language-dotnet. *** 2 | // *** Do not edit by hand unless you're certain you know what you are doing! *** 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Collections.Immutable; 7 | using System.Threading.Tasks; 8 | using Pulumi.Serialization; 9 | using Pulumi; 10 | 11 | namespace Mynamespace.ProviderBoilerplate 12 | { 13 | [ProviderBoilerplateResourceType("pulumi:providers:provider-boilerplate")] 14 | public partial class Provider : global::Pulumi.ProviderResource 15 | { 16 | /// 17 | /// Create a Provider resource with the given unique name, arguments, and options. 18 | /// 19 | /// 20 | /// The unique name of the resource 21 | /// The arguments used to populate this resource's properties 22 | /// A bag of options that control this resource's behavior 23 | public Provider(string name, ProviderArgs? args = null, CustomResourceOptions? options = null) 24 | : base("provider-boilerplate", name, args ?? new ProviderArgs(), MakeResourceOptions(options, "")) 25 | { 26 | } 27 | 28 | private static CustomResourceOptions MakeResourceOptions(CustomResourceOptions? options, Input? id) 29 | { 30 | var defaultOptions = new CustomResourceOptions 31 | { 32 | Version = Utilities.Version, 33 | }; 34 | var merged = CustomResourceOptions.Merge(defaultOptions, options); 35 | // Override the ID if one was specified for consistency with other language SDKs. 36 | merged.Id = id ?? merged.Id; 37 | return merged; 38 | } 39 | } 40 | 41 | public sealed class ProviderArgs : global::Pulumi.ResourceArgs 42 | { 43 | [Input("itsasecret", json: true)] 44 | public Input? Itsasecret { get; set; } 45 | 46 | public ProviderArgs() 47 | { 48 | } 49 | public static new ProviderArgs Empty => new ProviderArgs(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /sdk/dotnet/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pulumi/pulumi-provider-boilerplate/a69fee122706ff35eefd524db1773877d0518b56/sdk/dotnet/README.md -------------------------------------------------------------------------------- /sdk/dotnet/Random.cs: -------------------------------------------------------------------------------- 1 | // *** WARNING: this file was generated by pulumi-language-dotnet. *** 2 | // *** Do not edit by hand unless you're certain you know what you are doing! *** 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Collections.Immutable; 7 | using System.Threading.Tasks; 8 | using Pulumi.Serialization; 9 | using Pulumi; 10 | 11 | namespace Mynamespace.ProviderBoilerplate 12 | { 13 | [ProviderBoilerplateResourceType("provider-boilerplate:index:Random")] 14 | public partial class Random : global::Pulumi.CustomResource 15 | { 16 | [Output("length")] 17 | public Output Length { get; private set; } = null!; 18 | 19 | [Output("result")] 20 | public Output Result { get; private set; } = null!; 21 | 22 | 23 | /// 24 | /// Create a Random resource with the given unique name, arguments, and options. 25 | /// 26 | /// 27 | /// The unique name of the resource 28 | /// The arguments used to populate this resource's properties 29 | /// A bag of options that control this resource's behavior 30 | public Random(string name, RandomArgs args, CustomResourceOptions? options = null) 31 | : base("provider-boilerplate:index:Random", name, args ?? new RandomArgs(), MakeResourceOptions(options, "")) 32 | { 33 | } 34 | 35 | private Random(string name, Input id, CustomResourceOptions? options = null) 36 | : base("provider-boilerplate:index:Random", name, null, MakeResourceOptions(options, id)) 37 | { 38 | } 39 | 40 | private static CustomResourceOptions MakeResourceOptions(CustomResourceOptions? options, Input? id) 41 | { 42 | var defaultOptions = new CustomResourceOptions 43 | { 44 | Version = Utilities.Version, 45 | }; 46 | var merged = CustomResourceOptions.Merge(defaultOptions, options); 47 | // Override the ID if one was specified for consistency with other language SDKs. 48 | merged.Id = id ?? merged.Id; 49 | return merged; 50 | } 51 | /// 52 | /// Get an existing Random resource's state with the given name, ID, and optional extra 53 | /// properties used to qualify the lookup. 54 | /// 55 | /// 56 | /// The unique name of the resulting resource. 57 | /// The unique provider ID of the resource to lookup. 58 | /// A bag of options that control this resource's behavior 59 | public static Random Get(string name, Input id, CustomResourceOptions? options = null) 60 | { 61 | return new Random(name, id, options); 62 | } 63 | } 64 | 65 | public sealed class RandomArgs : global::Pulumi.ResourceArgs 66 | { 67 | [Input("length", required: true)] 68 | public Input Length { get; set; } = null!; 69 | 70 | public RandomArgs() 71 | { 72 | } 73 | public static new RandomArgs Empty => new RandomArgs(); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /sdk/dotnet/RandomComponent.cs: -------------------------------------------------------------------------------- 1 | // *** WARNING: this file was generated by pulumi-language-dotnet. *** 2 | // *** Do not edit by hand unless you're certain you know what you are doing! *** 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Collections.Immutable; 7 | using System.Threading.Tasks; 8 | using Pulumi.Serialization; 9 | using Pulumi; 10 | 11 | namespace Mynamespace.ProviderBoilerplate 12 | { 13 | [ProviderBoilerplateResourceType("provider-boilerplate:index:RandomComponent")] 14 | public partial class RandomComponent : global::Pulumi.ComponentResource 15 | { 16 | [Output("length")] 17 | public Output Length { get; private set; } = null!; 18 | 19 | [Output("password")] 20 | public Output Password { get; private set; } = null!; 21 | 22 | 23 | /// 24 | /// Create a RandomComponent resource with the given unique name, arguments, and options. 25 | /// 26 | /// 27 | /// The unique name of the resource 28 | /// The arguments used to populate this resource's properties 29 | /// A bag of options that control this resource's behavior 30 | public RandomComponent(string name, RandomComponentArgs args, ComponentResourceOptions? options = null) 31 | : base("provider-boilerplate:index:RandomComponent", name, args ?? new RandomComponentArgs(), MakeResourceOptions(options, ""), remote: true) 32 | { 33 | } 34 | 35 | private static ComponentResourceOptions MakeResourceOptions(ComponentResourceOptions? options, Input? id) 36 | { 37 | var defaultOptions = new ComponentResourceOptions 38 | { 39 | Version = Utilities.Version, 40 | }; 41 | var merged = ComponentResourceOptions.Merge(defaultOptions, options); 42 | // Override the ID if one was specified for consistency with other language SDKs. 43 | merged.Id = id ?? merged.Id; 44 | return merged; 45 | } 46 | } 47 | 48 | public sealed class RandomComponentArgs : global::Pulumi.ResourceArgs 49 | { 50 | [Input("length", required: true)] 51 | public Input Length { get; set; } = null!; 52 | 53 | public RandomComponentArgs() 54 | { 55 | } 56 | public static new RandomComponentArgs Empty => new RandomComponentArgs(); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /sdk/dotnet/Utilities.cs: -------------------------------------------------------------------------------- 1 | // *** WARNING: this file was generated by pulumi-language-dotnet. *** 2 | // *** Do not edit by hand unless you're certain you know what you are doing! *** 3 | 4 | namespace Mynamespace.ProviderBoilerplate 5 | { 6 | static class Utilities 7 | { 8 | public static string? GetEnv(params string[] names) 9 | { 10 | foreach (var n in names) 11 | { 12 | var value = global::System.Environment.GetEnvironmentVariable(n); 13 | if (value != null) 14 | { 15 | return value; 16 | } 17 | } 18 | return null; 19 | } 20 | 21 | static string[] trueValues = { "1", "t", "T", "true", "TRUE", "True" }; 22 | static string[] falseValues = { "0", "f", "F", "false", "FALSE", "False" }; 23 | public static bool? GetEnvBoolean(params string[] names) 24 | { 25 | var s = GetEnv(names); 26 | if (s != null) 27 | { 28 | if (global::System.Array.IndexOf(trueValues, s) != -1) 29 | { 30 | return true; 31 | } 32 | if (global::System.Array.IndexOf(falseValues, s) != -1) 33 | { 34 | return false; 35 | } 36 | } 37 | return null; 38 | } 39 | 40 | public static int? GetEnvInt32(params string[] names) => int.TryParse(GetEnv(names), out int v) ? (int?)v : null; 41 | 42 | public static double? GetEnvDouble(params string[] names) => double.TryParse(GetEnv(names), out double v) ? (double?)v : null; 43 | 44 | [global::System.Obsolete("Please use WithDefaults instead")] 45 | public static global::Pulumi.InvokeOptions WithVersion(this global::Pulumi.InvokeOptions? options) 46 | { 47 | var dst = options ?? new global::Pulumi.InvokeOptions{}; 48 | dst.Version = options?.Version ?? Version; 49 | return dst; 50 | } 51 | 52 | public static global::Pulumi.InvokeOptions WithDefaults(this global::Pulumi.InvokeOptions? src) 53 | { 54 | var dst = src ?? new global::Pulumi.InvokeOptions{}; 55 | dst.Version = src?.Version ?? Version; 56 | return dst; 57 | } 58 | 59 | public static global::Pulumi.InvokeOutputOptions WithDefaults(this global::Pulumi.InvokeOutputOptions? src) 60 | { 61 | var dst = src ?? new global::Pulumi.InvokeOutputOptions{}; 62 | dst.Version = src?.Version ?? Version; 63 | return dst; 64 | } 65 | 66 | private readonly static string version; 67 | public static string Version => version; 68 | 69 | static Utilities() 70 | { 71 | var assembly = global::System.Reflection.IntrospectionExtensions.GetTypeInfo(typeof(Utilities)).Assembly; 72 | using var stream = assembly.GetManifestResourceStream("Mynamespace.ProviderBoilerplate.version.txt"); 73 | using var reader = new global::System.IO.StreamReader(stream ?? throw new global::System.NotSupportedException("Missing embedded version.txt file")); 74 | version = reader.ReadToEnd().Trim(); 75 | var parts = version.Split("\n"); 76 | if (parts.Length == 2) 77 | { 78 | // The first part is the provider name. 79 | version = parts[1].Trim(); 80 | } 81 | } 82 | } 83 | 84 | internal sealed class ProviderBoilerplateResourceTypeAttribute : global::Pulumi.ResourceTypeAttribute 85 | { 86 | public ProviderBoilerplateResourceTypeAttribute(string type) : base(type, Utilities.Version) 87 | { 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /sdk/dotnet/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pulumi/pulumi-provider-boilerplate/a69fee122706ff35eefd524db1773877d0518b56/sdk/dotnet/logo.png -------------------------------------------------------------------------------- /sdk/dotnet/pulumi-plugin.json: -------------------------------------------------------------------------------- 1 | { 2 | "resource": true, 3 | "name": "provider-boilerplate", 4 | "version": "1.0.0-alpha.0+dev" 5 | } 6 | -------------------------------------------------------------------------------- /sdk/dotnet/version.txt: -------------------------------------------------------------------------------- 1 | 1.0.0-alpha.0+dev -------------------------------------------------------------------------------- /sdk/go/provider-boilerplate/config/config.go: -------------------------------------------------------------------------------- 1 | // Code generated by pulumi-language-go DO NOT EDIT. 2 | // *** WARNING: Do not edit by hand unless you're certain you know what you are doing! *** 3 | 4 | package config 5 | 6 | import ( 7 | "github.com/mynamespace/provider-boilerplate/sdk/go/provider-boilerplate/internal" 8 | "github.com/pulumi/pulumi/sdk/v3/go/pulumi" 9 | "github.com/pulumi/pulumi/sdk/v3/go/pulumi/config" 10 | ) 11 | 12 | var _ = internal.GetEnvOrDefault 13 | 14 | func GetItsasecret(ctx *pulumi.Context) bool { 15 | return config.GetBool(ctx, "provider-boilerplate:itsasecret") 16 | } 17 | -------------------------------------------------------------------------------- /sdk/go/provider-boilerplate/doc.go: -------------------------------------------------------------------------------- 1 | // Package providerboilerplate exports types, functions, subpackages for provisioning providerboilerplate resources. 2 | package providerboilerplate 3 | -------------------------------------------------------------------------------- /sdk/go/provider-boilerplate/init.go: -------------------------------------------------------------------------------- 1 | // Code generated by pulumi-language-go DO NOT EDIT. 2 | // *** WARNING: Do not edit by hand unless you're certain you know what you are doing! *** 3 | 4 | package providerboilerplate 5 | 6 | import ( 7 | "fmt" 8 | 9 | "github.com/blang/semver" 10 | "github.com/mynamespace/provider-boilerplate/sdk/go/provider-boilerplate/internal" 11 | "github.com/pulumi/pulumi/sdk/v3/go/pulumi" 12 | ) 13 | 14 | type module struct { 15 | version semver.Version 16 | } 17 | 18 | func (m *module) Version() semver.Version { 19 | return m.version 20 | } 21 | 22 | func (m *module) Construct(ctx *pulumi.Context, name, typ, urn string) (r pulumi.Resource, err error) { 23 | switch typ { 24 | case "provider-boilerplate:index:Random": 25 | r = &Random{} 26 | case "provider-boilerplate:index:RandomComponent": 27 | r = &RandomComponent{} 28 | default: 29 | return nil, fmt.Errorf("unknown resource type: %s", typ) 30 | } 31 | 32 | err = ctx.RegisterResource(typ, name, nil, r, pulumi.URN_(urn)) 33 | return 34 | } 35 | 36 | type pkg struct { 37 | version semver.Version 38 | } 39 | 40 | func (p *pkg) Version() semver.Version { 41 | return p.version 42 | } 43 | 44 | func (p *pkg) ConstructProvider(ctx *pulumi.Context, name, typ, urn string) (pulumi.ProviderResource, error) { 45 | if typ != "pulumi:providers:provider-boilerplate" { 46 | return nil, fmt.Errorf("unknown provider type: %s", typ) 47 | } 48 | 49 | r := &Provider{} 50 | err := ctx.RegisterResource(typ, name, nil, r, pulumi.URN_(urn)) 51 | return r, err 52 | } 53 | 54 | func init() { 55 | version, err := internal.PkgVersion() 56 | if err != nil { 57 | version = semver.Version{Major: 1} 58 | } 59 | pulumi.RegisterResourceModule( 60 | "provider-boilerplate", 61 | "index", 62 | &module{version}, 63 | ) 64 | pulumi.RegisterResourcePackage( 65 | "provider-boilerplate", 66 | &pkg{version}, 67 | ) 68 | } 69 | -------------------------------------------------------------------------------- /sdk/go/provider-boilerplate/internal/pulumiUtilities.go: -------------------------------------------------------------------------------- 1 | // Code generated by pulumi-language-go DO NOT EDIT. 2 | // *** WARNING: Do not edit by hand unless you're certain you know what you are doing! *** 3 | 4 | package internal 5 | 6 | import ( 7 | "fmt" 8 | "os" 9 | "reflect" 10 | "regexp" 11 | "strconv" 12 | "strings" 13 | 14 | "github.com/blang/semver" 15 | "github.com/pulumi/pulumi/sdk/v3/go/pulumi" 16 | ) 17 | 18 | import ( 19 | "github.com/pulumi/pulumi/sdk/v3/go/pulumi/internals" 20 | ) 21 | 22 | type envParser func(v string) interface{} 23 | 24 | func ParseEnvBool(v string) interface{} { 25 | b, err := strconv.ParseBool(v) 26 | if err != nil { 27 | return nil 28 | } 29 | return b 30 | } 31 | 32 | func ParseEnvInt(v string) interface{} { 33 | i, err := strconv.ParseInt(v, 0, 0) 34 | if err != nil { 35 | return nil 36 | } 37 | return int(i) 38 | } 39 | 40 | func ParseEnvFloat(v string) interface{} { 41 | f, err := strconv.ParseFloat(v, 64) 42 | if err != nil { 43 | return nil 44 | } 45 | return f 46 | } 47 | 48 | func ParseEnvStringArray(v string) interface{} { 49 | var result pulumi.StringArray 50 | for _, item := range strings.Split(v, ";") { 51 | result = append(result, pulumi.String(item)) 52 | } 53 | return result 54 | } 55 | 56 | func GetEnvOrDefault(def interface{}, parser envParser, vars ...string) interface{} { 57 | for _, v := range vars { 58 | if value, ok := os.LookupEnv(v); ok { 59 | if parser != nil { 60 | return parser(value) 61 | } 62 | return value 63 | } 64 | } 65 | return def 66 | } 67 | 68 | // PkgVersion uses reflection to determine the version of the current package. 69 | // If a version cannot be determined, v1 will be assumed. The second return 70 | // value is always nil. 71 | func PkgVersion() (semver.Version, error) { 72 | // emptyVersion defaults to v0.0.0 73 | if !SdkVersion.Equals(semver.Version{}) { 74 | return SdkVersion, nil 75 | } 76 | type sentinal struct{} 77 | pkgPath := reflect.TypeOf(sentinal{}).PkgPath() 78 | re := regexp.MustCompile("^.*/pulumi-provider-boilerplate/sdk(/v\\d+)?") 79 | if match := re.FindStringSubmatch(pkgPath); match != nil { 80 | vStr := match[1] 81 | if len(vStr) == 0 { // If the version capture group was empty, default to v1. 82 | return semver.Version{Major: 1}, nil 83 | } 84 | return semver.MustParse(fmt.Sprintf("%s.0.0", vStr[2:])), nil 85 | } 86 | return semver.Version{Major: 1}, nil 87 | } 88 | 89 | // isZero is a null safe check for if a value is it's types zero value. 90 | func IsZero(v interface{}) bool { 91 | if v == nil { 92 | return true 93 | } 94 | return reflect.ValueOf(v).IsZero() 95 | } 96 | 97 | func CallPlain( 98 | ctx *pulumi.Context, 99 | tok string, 100 | args pulumi.Input, 101 | output pulumi.Output, 102 | self pulumi.Resource, 103 | property string, 104 | resultPtr reflect.Value, 105 | errorPtr *error, 106 | opts ...pulumi.InvokeOption, 107 | ) { 108 | res, err := callPlainInner(ctx, tok, args, output, self, opts...) 109 | if err != nil { 110 | *errorPtr = err 111 | return 112 | } 113 | 114 | v := reflect.ValueOf(res) 115 | 116 | // extract res.property field if asked to do so 117 | if property != "" { 118 | v = v.FieldByName("Res") 119 | } 120 | 121 | // return by setting the result pointer; this style of returns shortens the generated code without generics 122 | resultPtr.Elem().Set(v) 123 | } 124 | 125 | func callPlainInner( 126 | ctx *pulumi.Context, 127 | tok string, 128 | args pulumi.Input, 129 | output pulumi.Output, 130 | self pulumi.Resource, 131 | opts ...pulumi.InvokeOption, 132 | ) (any, error) { 133 | o, err := ctx.Call(tok, args, output, self, opts...) 134 | if err != nil { 135 | return nil, err 136 | } 137 | 138 | outputData, err := internals.UnsafeAwaitOutput(ctx.Context(), o) 139 | if err != nil { 140 | return nil, err 141 | } 142 | 143 | // Ingoring deps silently. They are typically non-empty, r.f() calls include r as a dependency. 144 | known := outputData.Known 145 | value := outputData.Value 146 | secret := outputData.Secret 147 | 148 | problem := "" 149 | if !known { 150 | problem = "an unknown value" 151 | } else if secret { 152 | problem = "a secret value" 153 | } 154 | 155 | if problem != "" { 156 | return nil, fmt.Errorf("Plain resource method %q incorrectly returned %s. "+ 157 | "This is an error in the provider, please report this to the provider developer.", 158 | tok, problem) 159 | } 160 | 161 | return value, nil 162 | } 163 | 164 | // PkgResourceDefaultOpts provides package level defaults to pulumi.OptionResource. 165 | func PkgResourceDefaultOpts(opts []pulumi.ResourceOption) []pulumi.ResourceOption { 166 | defaults := []pulumi.ResourceOption{} 167 | 168 | version := semver.MustParse("1.0.0-alpha.0+dev") 169 | if !version.Equals(semver.Version{}) { 170 | defaults = append(defaults, pulumi.Version(version.String())) 171 | } 172 | return append(defaults, opts...) 173 | } 174 | 175 | // PkgInvokeDefaultOpts provides package level defaults to pulumi.OptionInvoke. 176 | func PkgInvokeDefaultOpts(opts []pulumi.InvokeOption) []pulumi.InvokeOption { 177 | defaults := []pulumi.InvokeOption{} 178 | 179 | version := semver.MustParse("1.0.0-alpha.0+dev") 180 | if !version.Equals(semver.Version{}) { 181 | defaults = append(defaults, pulumi.Version(version.String())) 182 | } 183 | return append(defaults, opts...) 184 | } 185 | -------------------------------------------------------------------------------- /sdk/go/provider-boilerplate/internal/pulumiVersion.go: -------------------------------------------------------------------------------- 1 | // Code generated by pulumi-language-go DO NOT EDIT. 2 | // *** WARNING: Do not edit by hand unless you're certain you know what you are doing! *** 3 | 4 | package internal 5 | 6 | import ( 7 | "github.com/blang/semver" 8 | ) 9 | 10 | var SdkVersion semver.Version = semver.Version{} 11 | var pluginDownloadURL string = "" 12 | -------------------------------------------------------------------------------- /sdk/go/provider-boilerplate/provider.go: -------------------------------------------------------------------------------- 1 | // Code generated by pulumi-language-go DO NOT EDIT. 2 | // *** WARNING: Do not edit by hand unless you're certain you know what you are doing! *** 3 | 4 | package providerboilerplate 5 | 6 | import ( 7 | "context" 8 | "reflect" 9 | 10 | "github.com/mynamespace/provider-boilerplate/sdk/go/provider-boilerplate/internal" 11 | "github.com/pulumi/pulumi/sdk/v3/go/pulumi" 12 | ) 13 | 14 | type Provider struct { 15 | pulumi.ProviderResourceState 16 | } 17 | 18 | // NewProvider registers a new resource with the given unique name, arguments, and options. 19 | func NewProvider(ctx *pulumi.Context, 20 | name string, args *ProviderArgs, opts ...pulumi.ResourceOption) (*Provider, error) { 21 | if args == nil { 22 | args = &ProviderArgs{} 23 | } 24 | 25 | opts = internal.PkgResourceDefaultOpts(opts) 26 | var resource Provider 27 | err := ctx.RegisterResource("pulumi:providers:provider-boilerplate", name, args, &resource, opts...) 28 | if err != nil { 29 | return nil, err 30 | } 31 | return &resource, nil 32 | } 33 | 34 | type providerArgs struct { 35 | Itsasecret *bool `pulumi:"itsasecret"` 36 | } 37 | 38 | // The set of arguments for constructing a Provider resource. 39 | type ProviderArgs struct { 40 | Itsasecret pulumi.BoolPtrInput 41 | } 42 | 43 | func (ProviderArgs) ElementType() reflect.Type { 44 | return reflect.TypeOf((*providerArgs)(nil)).Elem() 45 | } 46 | 47 | type ProviderInput interface { 48 | pulumi.Input 49 | 50 | ToProviderOutput() ProviderOutput 51 | ToProviderOutputWithContext(ctx context.Context) ProviderOutput 52 | } 53 | 54 | func (*Provider) ElementType() reflect.Type { 55 | return reflect.TypeOf((**Provider)(nil)).Elem() 56 | } 57 | 58 | func (i *Provider) ToProviderOutput() ProviderOutput { 59 | return i.ToProviderOutputWithContext(context.Background()) 60 | } 61 | 62 | func (i *Provider) ToProviderOutputWithContext(ctx context.Context) ProviderOutput { 63 | return pulumi.ToOutputWithContext(ctx, i).(ProviderOutput) 64 | } 65 | 66 | type ProviderOutput struct{ *pulumi.OutputState } 67 | 68 | func (ProviderOutput) ElementType() reflect.Type { 69 | return reflect.TypeOf((**Provider)(nil)).Elem() 70 | } 71 | 72 | func (o ProviderOutput) ToProviderOutput() ProviderOutput { 73 | return o 74 | } 75 | 76 | func (o ProviderOutput) ToProviderOutputWithContext(ctx context.Context) ProviderOutput { 77 | return o 78 | } 79 | 80 | func init() { 81 | pulumi.RegisterInputType(reflect.TypeOf((*ProviderInput)(nil)).Elem(), &Provider{}) 82 | pulumi.RegisterOutputType(ProviderOutput{}) 83 | } 84 | -------------------------------------------------------------------------------- /sdk/go/provider-boilerplate/pulumi-plugin.json: -------------------------------------------------------------------------------- 1 | { 2 | "resource": true, 3 | "name": "provider-boilerplate", 4 | "version": "1.0.0-alpha.0+dev" 5 | } 6 | -------------------------------------------------------------------------------- /sdk/go/provider-boilerplate/random.go: -------------------------------------------------------------------------------- 1 | // Code generated by pulumi-language-go DO NOT EDIT. 2 | // *** WARNING: Do not edit by hand unless you're certain you know what you are doing! *** 3 | 4 | package providerboilerplate 5 | 6 | import ( 7 | "context" 8 | "reflect" 9 | 10 | "errors" 11 | "github.com/mynamespace/provider-boilerplate/sdk/go/provider-boilerplate/internal" 12 | "github.com/pulumi/pulumi/sdk/v3/go/pulumi" 13 | ) 14 | 15 | type Random struct { 16 | pulumi.CustomResourceState 17 | 18 | Length pulumi.IntOutput `pulumi:"length"` 19 | Result pulumi.StringOutput `pulumi:"result"` 20 | } 21 | 22 | // NewRandom registers a new resource with the given unique name, arguments, and options. 23 | func NewRandom(ctx *pulumi.Context, 24 | name string, args *RandomArgs, opts ...pulumi.ResourceOption) (*Random, error) { 25 | if args == nil { 26 | return nil, errors.New("missing one or more required arguments") 27 | } 28 | 29 | if args.Length == nil { 30 | return nil, errors.New("invalid value for required argument 'Length'") 31 | } 32 | opts = internal.PkgResourceDefaultOpts(opts) 33 | var resource Random 34 | err := ctx.RegisterResource("provider-boilerplate:index:Random", name, args, &resource, opts...) 35 | if err != nil { 36 | return nil, err 37 | } 38 | return &resource, nil 39 | } 40 | 41 | // GetRandom gets an existing Random resource's state with the given name, ID, and optional 42 | // state properties that are used to uniquely qualify the lookup (nil if not required). 43 | func GetRandom(ctx *pulumi.Context, 44 | name string, id pulumi.IDInput, state *RandomState, opts ...pulumi.ResourceOption) (*Random, error) { 45 | var resource Random 46 | err := ctx.ReadResource("provider-boilerplate:index:Random", name, id, state, &resource, opts...) 47 | if err != nil { 48 | return nil, err 49 | } 50 | return &resource, nil 51 | } 52 | 53 | // Input properties used for looking up and filtering Random resources. 54 | type randomState struct { 55 | } 56 | 57 | type RandomState struct { 58 | } 59 | 60 | func (RandomState) ElementType() reflect.Type { 61 | return reflect.TypeOf((*randomState)(nil)).Elem() 62 | } 63 | 64 | type randomArgs struct { 65 | Length int `pulumi:"length"` 66 | } 67 | 68 | // The set of arguments for constructing a Random resource. 69 | type RandomArgs struct { 70 | Length pulumi.IntInput 71 | } 72 | 73 | func (RandomArgs) ElementType() reflect.Type { 74 | return reflect.TypeOf((*randomArgs)(nil)).Elem() 75 | } 76 | 77 | type RandomInput interface { 78 | pulumi.Input 79 | 80 | ToRandomOutput() RandomOutput 81 | ToRandomOutputWithContext(ctx context.Context) RandomOutput 82 | } 83 | 84 | func (*Random) ElementType() reflect.Type { 85 | return reflect.TypeOf((**Random)(nil)).Elem() 86 | } 87 | 88 | func (i *Random) ToRandomOutput() RandomOutput { 89 | return i.ToRandomOutputWithContext(context.Background()) 90 | } 91 | 92 | func (i *Random) ToRandomOutputWithContext(ctx context.Context) RandomOutput { 93 | return pulumi.ToOutputWithContext(ctx, i).(RandomOutput) 94 | } 95 | 96 | // RandomArrayInput is an input type that accepts RandomArray and RandomArrayOutput values. 97 | // You can construct a concrete instance of `RandomArrayInput` via: 98 | // 99 | // RandomArray{ RandomArgs{...} } 100 | type RandomArrayInput interface { 101 | pulumi.Input 102 | 103 | ToRandomArrayOutput() RandomArrayOutput 104 | ToRandomArrayOutputWithContext(context.Context) RandomArrayOutput 105 | } 106 | 107 | type RandomArray []RandomInput 108 | 109 | func (RandomArray) ElementType() reflect.Type { 110 | return reflect.TypeOf((*[]*Random)(nil)).Elem() 111 | } 112 | 113 | func (i RandomArray) ToRandomArrayOutput() RandomArrayOutput { 114 | return i.ToRandomArrayOutputWithContext(context.Background()) 115 | } 116 | 117 | func (i RandomArray) ToRandomArrayOutputWithContext(ctx context.Context) RandomArrayOutput { 118 | return pulumi.ToOutputWithContext(ctx, i).(RandomArrayOutput) 119 | } 120 | 121 | // RandomMapInput is an input type that accepts RandomMap and RandomMapOutput values. 122 | // You can construct a concrete instance of `RandomMapInput` via: 123 | // 124 | // RandomMap{ "key": RandomArgs{...} } 125 | type RandomMapInput interface { 126 | pulumi.Input 127 | 128 | ToRandomMapOutput() RandomMapOutput 129 | ToRandomMapOutputWithContext(context.Context) RandomMapOutput 130 | } 131 | 132 | type RandomMap map[string]RandomInput 133 | 134 | func (RandomMap) ElementType() reflect.Type { 135 | return reflect.TypeOf((*map[string]*Random)(nil)).Elem() 136 | } 137 | 138 | func (i RandomMap) ToRandomMapOutput() RandomMapOutput { 139 | return i.ToRandomMapOutputWithContext(context.Background()) 140 | } 141 | 142 | func (i RandomMap) ToRandomMapOutputWithContext(ctx context.Context) RandomMapOutput { 143 | return pulumi.ToOutputWithContext(ctx, i).(RandomMapOutput) 144 | } 145 | 146 | type RandomOutput struct{ *pulumi.OutputState } 147 | 148 | func (RandomOutput) ElementType() reflect.Type { 149 | return reflect.TypeOf((**Random)(nil)).Elem() 150 | } 151 | 152 | func (o RandomOutput) ToRandomOutput() RandomOutput { 153 | return o 154 | } 155 | 156 | func (o RandomOutput) ToRandomOutputWithContext(ctx context.Context) RandomOutput { 157 | return o 158 | } 159 | 160 | func (o RandomOutput) Length() pulumi.IntOutput { 161 | return o.ApplyT(func(v *Random) pulumi.IntOutput { return v.Length }).(pulumi.IntOutput) 162 | } 163 | 164 | func (o RandomOutput) Result() pulumi.StringOutput { 165 | return o.ApplyT(func(v *Random) pulumi.StringOutput { return v.Result }).(pulumi.StringOutput) 166 | } 167 | 168 | type RandomArrayOutput struct{ *pulumi.OutputState } 169 | 170 | func (RandomArrayOutput) ElementType() reflect.Type { 171 | return reflect.TypeOf((*[]*Random)(nil)).Elem() 172 | } 173 | 174 | func (o RandomArrayOutput) ToRandomArrayOutput() RandomArrayOutput { 175 | return o 176 | } 177 | 178 | func (o RandomArrayOutput) ToRandomArrayOutputWithContext(ctx context.Context) RandomArrayOutput { 179 | return o 180 | } 181 | 182 | func (o RandomArrayOutput) Index(i pulumi.IntInput) RandomOutput { 183 | return pulumi.All(o, i).ApplyT(func(vs []interface{}) *Random { 184 | return vs[0].([]*Random)[vs[1].(int)] 185 | }).(RandomOutput) 186 | } 187 | 188 | type RandomMapOutput struct{ *pulumi.OutputState } 189 | 190 | func (RandomMapOutput) ElementType() reflect.Type { 191 | return reflect.TypeOf((*map[string]*Random)(nil)).Elem() 192 | } 193 | 194 | func (o RandomMapOutput) ToRandomMapOutput() RandomMapOutput { 195 | return o 196 | } 197 | 198 | func (o RandomMapOutput) ToRandomMapOutputWithContext(ctx context.Context) RandomMapOutput { 199 | return o 200 | } 201 | 202 | func (o RandomMapOutput) MapIndex(k pulumi.StringInput) RandomOutput { 203 | return pulumi.All(o, k).ApplyT(func(vs []interface{}) *Random { 204 | return vs[0].(map[string]*Random)[vs[1].(string)] 205 | }).(RandomOutput) 206 | } 207 | 208 | func init() { 209 | pulumi.RegisterInputType(reflect.TypeOf((*RandomInput)(nil)).Elem(), &Random{}) 210 | pulumi.RegisterInputType(reflect.TypeOf((*RandomArrayInput)(nil)).Elem(), RandomArray{}) 211 | pulumi.RegisterInputType(reflect.TypeOf((*RandomMapInput)(nil)).Elem(), RandomMap{}) 212 | pulumi.RegisterOutputType(RandomOutput{}) 213 | pulumi.RegisterOutputType(RandomArrayOutput{}) 214 | pulumi.RegisterOutputType(RandomMapOutput{}) 215 | } 216 | -------------------------------------------------------------------------------- /sdk/go/provider-boilerplate/randomComponent.go: -------------------------------------------------------------------------------- 1 | // Code generated by pulumi-language-go DO NOT EDIT. 2 | // *** WARNING: Do not edit by hand unless you're certain you know what you are doing! *** 3 | 4 | package providerboilerplate 5 | 6 | import ( 7 | "context" 8 | "reflect" 9 | 10 | "errors" 11 | "github.com/mynamespace/provider-boilerplate/sdk/go/provider-boilerplate/internal" 12 | "github.com/pulumi/pulumi/sdk/v3/go/pulumi" 13 | ) 14 | 15 | type RandomComponent struct { 16 | pulumi.ResourceState 17 | 18 | Length pulumi.IntOutput `pulumi:"length"` 19 | Password pulumi.StringOutput `pulumi:"password"` 20 | } 21 | 22 | // NewRandomComponent registers a new resource with the given unique name, arguments, and options. 23 | func NewRandomComponent(ctx *pulumi.Context, 24 | name string, args *RandomComponentArgs, opts ...pulumi.ResourceOption) (*RandomComponent, error) { 25 | if args == nil { 26 | return nil, errors.New("missing one or more required arguments") 27 | } 28 | 29 | if args.Length == nil { 30 | return nil, errors.New("invalid value for required argument 'Length'") 31 | } 32 | opts = internal.PkgResourceDefaultOpts(opts) 33 | var resource RandomComponent 34 | err := ctx.RegisterRemoteComponentResource("provider-boilerplate:index:RandomComponent", name, args, &resource, opts...) 35 | if err != nil { 36 | return nil, err 37 | } 38 | return &resource, nil 39 | } 40 | 41 | type randomComponentArgs struct { 42 | Length int `pulumi:"length"` 43 | } 44 | 45 | // The set of arguments for constructing a RandomComponent resource. 46 | type RandomComponentArgs struct { 47 | Length pulumi.IntInput 48 | } 49 | 50 | func (RandomComponentArgs) ElementType() reflect.Type { 51 | return reflect.TypeOf((*randomComponentArgs)(nil)).Elem() 52 | } 53 | 54 | type RandomComponentInput interface { 55 | pulumi.Input 56 | 57 | ToRandomComponentOutput() RandomComponentOutput 58 | ToRandomComponentOutputWithContext(ctx context.Context) RandomComponentOutput 59 | } 60 | 61 | func (*RandomComponent) ElementType() reflect.Type { 62 | return reflect.TypeOf((**RandomComponent)(nil)).Elem() 63 | } 64 | 65 | func (i *RandomComponent) ToRandomComponentOutput() RandomComponentOutput { 66 | return i.ToRandomComponentOutputWithContext(context.Background()) 67 | } 68 | 69 | func (i *RandomComponent) ToRandomComponentOutputWithContext(ctx context.Context) RandomComponentOutput { 70 | return pulumi.ToOutputWithContext(ctx, i).(RandomComponentOutput) 71 | } 72 | 73 | // RandomComponentArrayInput is an input type that accepts RandomComponentArray and RandomComponentArrayOutput values. 74 | // You can construct a concrete instance of `RandomComponentArrayInput` via: 75 | // 76 | // RandomComponentArray{ RandomComponentArgs{...} } 77 | type RandomComponentArrayInput interface { 78 | pulumi.Input 79 | 80 | ToRandomComponentArrayOutput() RandomComponentArrayOutput 81 | ToRandomComponentArrayOutputWithContext(context.Context) RandomComponentArrayOutput 82 | } 83 | 84 | type RandomComponentArray []RandomComponentInput 85 | 86 | func (RandomComponentArray) ElementType() reflect.Type { 87 | return reflect.TypeOf((*[]*RandomComponent)(nil)).Elem() 88 | } 89 | 90 | func (i RandomComponentArray) ToRandomComponentArrayOutput() RandomComponentArrayOutput { 91 | return i.ToRandomComponentArrayOutputWithContext(context.Background()) 92 | } 93 | 94 | func (i RandomComponentArray) ToRandomComponentArrayOutputWithContext(ctx context.Context) RandomComponentArrayOutput { 95 | return pulumi.ToOutputWithContext(ctx, i).(RandomComponentArrayOutput) 96 | } 97 | 98 | // RandomComponentMapInput is an input type that accepts RandomComponentMap and RandomComponentMapOutput values. 99 | // You can construct a concrete instance of `RandomComponentMapInput` via: 100 | // 101 | // RandomComponentMap{ "key": RandomComponentArgs{...} } 102 | type RandomComponentMapInput interface { 103 | pulumi.Input 104 | 105 | ToRandomComponentMapOutput() RandomComponentMapOutput 106 | ToRandomComponentMapOutputWithContext(context.Context) RandomComponentMapOutput 107 | } 108 | 109 | type RandomComponentMap map[string]RandomComponentInput 110 | 111 | func (RandomComponentMap) ElementType() reflect.Type { 112 | return reflect.TypeOf((*map[string]*RandomComponent)(nil)).Elem() 113 | } 114 | 115 | func (i RandomComponentMap) ToRandomComponentMapOutput() RandomComponentMapOutput { 116 | return i.ToRandomComponentMapOutputWithContext(context.Background()) 117 | } 118 | 119 | func (i RandomComponentMap) ToRandomComponentMapOutputWithContext(ctx context.Context) RandomComponentMapOutput { 120 | return pulumi.ToOutputWithContext(ctx, i).(RandomComponentMapOutput) 121 | } 122 | 123 | type RandomComponentOutput struct{ *pulumi.OutputState } 124 | 125 | func (RandomComponentOutput) ElementType() reflect.Type { 126 | return reflect.TypeOf((**RandomComponent)(nil)).Elem() 127 | } 128 | 129 | func (o RandomComponentOutput) ToRandomComponentOutput() RandomComponentOutput { 130 | return o 131 | } 132 | 133 | func (o RandomComponentOutput) ToRandomComponentOutputWithContext(ctx context.Context) RandomComponentOutput { 134 | return o 135 | } 136 | 137 | func (o RandomComponentOutput) Length() pulumi.IntOutput { 138 | return o.ApplyT(func(v *RandomComponent) pulumi.IntOutput { return v.Length }).(pulumi.IntOutput) 139 | } 140 | 141 | func (o RandomComponentOutput) Password() pulumi.StringOutput { 142 | return o.ApplyT(func(v *RandomComponent) pulumi.StringOutput { return v.Password }).(pulumi.StringOutput) 143 | } 144 | 145 | type RandomComponentArrayOutput struct{ *pulumi.OutputState } 146 | 147 | func (RandomComponentArrayOutput) ElementType() reflect.Type { 148 | return reflect.TypeOf((*[]*RandomComponent)(nil)).Elem() 149 | } 150 | 151 | func (o RandomComponentArrayOutput) ToRandomComponentArrayOutput() RandomComponentArrayOutput { 152 | return o 153 | } 154 | 155 | func (o RandomComponentArrayOutput) ToRandomComponentArrayOutputWithContext(ctx context.Context) RandomComponentArrayOutput { 156 | return o 157 | } 158 | 159 | func (o RandomComponentArrayOutput) Index(i pulumi.IntInput) RandomComponentOutput { 160 | return pulumi.All(o, i).ApplyT(func(vs []interface{}) *RandomComponent { 161 | return vs[0].([]*RandomComponent)[vs[1].(int)] 162 | }).(RandomComponentOutput) 163 | } 164 | 165 | type RandomComponentMapOutput struct{ *pulumi.OutputState } 166 | 167 | func (RandomComponentMapOutput) ElementType() reflect.Type { 168 | return reflect.TypeOf((*map[string]*RandomComponent)(nil)).Elem() 169 | } 170 | 171 | func (o RandomComponentMapOutput) ToRandomComponentMapOutput() RandomComponentMapOutput { 172 | return o 173 | } 174 | 175 | func (o RandomComponentMapOutput) ToRandomComponentMapOutputWithContext(ctx context.Context) RandomComponentMapOutput { 176 | return o 177 | } 178 | 179 | func (o RandomComponentMapOutput) MapIndex(k pulumi.StringInput) RandomComponentOutput { 180 | return pulumi.All(o, k).ApplyT(func(vs []interface{}) *RandomComponent { 181 | return vs[0].(map[string]*RandomComponent)[vs[1].(string)] 182 | }).(RandomComponentOutput) 183 | } 184 | 185 | func init() { 186 | pulumi.RegisterInputType(reflect.TypeOf((*RandomComponentInput)(nil)).Elem(), &RandomComponent{}) 187 | pulumi.RegisterInputType(reflect.TypeOf((*RandomComponentArrayInput)(nil)).Elem(), RandomComponentArray{}) 188 | pulumi.RegisterInputType(reflect.TypeOf((*RandomComponentMapInput)(nil)).Elem(), RandomComponentMap{}) 189 | pulumi.RegisterOutputType(RandomComponentOutput{}) 190 | pulumi.RegisterOutputType(RandomComponentArrayOutput{}) 191 | pulumi.RegisterOutputType(RandomComponentMapOutput{}) 192 | } 193 | -------------------------------------------------------------------------------- /sdk/java/README.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /sdk/java/settings.gradle: -------------------------------------------------------------------------------- 1 | // *** WARNING: this file was generated by pulumi-java-gen. *** 2 | // *** Do not edit by hand unless you're certain you know what you are doing! *** 3 | 4 | pluginManagement { 5 | repositories { 6 | maven { // The google mirror is less flaky than mavenCentral() 7 | url("https://maven-central.storage-download.googleapis.com/maven2/") 8 | } 9 | gradlePluginPortal() 10 | } 11 | } 12 | 13 | rootProject.name = "com.mynamespace.provider-boilerplate" 14 | include("lib") 15 | -------------------------------------------------------------------------------- /sdk/java/src/main/java/com/mynamespace/providerboilerplate/Config.java: -------------------------------------------------------------------------------- 1 | // *** WARNING: this file was generated by pulumi-language-java. *** 2 | // *** Do not edit by hand unless you're certain you know what you are doing! *** 3 | 4 | package com.mynamespace.providerboilerplate; 5 | 6 | import com.pulumi.core.internal.Codegen; 7 | import java.lang.Boolean; 8 | import java.util.Optional; 9 | 10 | public final class Config { 11 | 12 | private static final com.pulumi.Config config = com.pulumi.Config.of("provider-boilerplate"); 13 | public Optional itsasecret() { 14 | return Codegen.booleanProp("itsasecret").config(config).get(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /sdk/java/src/main/java/com/mynamespace/providerboilerplate/Provider.java: -------------------------------------------------------------------------------- 1 | // *** WARNING: this file was generated by pulumi-language-java. *** 2 | // *** Do not edit by hand unless you're certain you know what you are doing! *** 3 | 4 | package com.mynamespace.providerboilerplate; 5 | 6 | import com.mynamespace.providerboilerplate.ProviderArgs; 7 | import com.mynamespace.providerboilerplate.Utilities; 8 | import com.pulumi.core.Output; 9 | import com.pulumi.core.annotations.ResourceType; 10 | import com.pulumi.core.internal.Codegen; 11 | import javax.annotation.Nullable; 12 | 13 | @ResourceType(type="pulumi:providers:provider-boilerplate") 14 | public class Provider extends com.pulumi.resources.ProviderResource { 15 | /** 16 | * 17 | * @param name The _unique_ name of the resulting resource. 18 | */ 19 | public Provider(java.lang.String name) { 20 | this(name, ProviderArgs.Empty); 21 | } 22 | /** 23 | * 24 | * @param name The _unique_ name of the resulting resource. 25 | * @param args The arguments to use to populate this resource's properties. 26 | */ 27 | public Provider(java.lang.String name, @Nullable ProviderArgs args) { 28 | this(name, args, null); 29 | } 30 | /** 31 | * 32 | * @param name The _unique_ name of the resulting resource. 33 | * @param args The arguments to use to populate this resource's properties. 34 | * @param options A bag of options that control this resource's behavior. 35 | */ 36 | public Provider(java.lang.String name, @Nullable ProviderArgs args, @Nullable com.pulumi.resources.CustomResourceOptions options) { 37 | super("provider-boilerplate", name, makeArgs(args, options), makeResourceOptions(options, Codegen.empty()), false); 38 | } 39 | 40 | private static ProviderArgs makeArgs(@Nullable ProviderArgs args, @Nullable com.pulumi.resources.CustomResourceOptions options) { 41 | if (options != null && options.getUrn().isPresent()) { 42 | return null; 43 | } 44 | return args == null ? ProviderArgs.Empty : args; 45 | } 46 | 47 | private static com.pulumi.resources.CustomResourceOptions makeResourceOptions(@Nullable com.pulumi.resources.CustomResourceOptions options, @Nullable Output id) { 48 | var defaultOptions = com.pulumi.resources.CustomResourceOptions.builder() 49 | .version(Utilities.getVersion()) 50 | .build(); 51 | return com.pulumi.resources.CustomResourceOptions.merge(defaultOptions, options, id); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /sdk/java/src/main/java/com/mynamespace/providerboilerplate/ProviderArgs.java: -------------------------------------------------------------------------------- 1 | // *** WARNING: this file was generated by pulumi-language-java. *** 2 | // *** Do not edit by hand unless you're certain you know what you are doing! *** 3 | 4 | package com.mynamespace.providerboilerplate; 5 | 6 | import com.pulumi.core.Output; 7 | import com.pulumi.core.annotations.Import; 8 | import java.lang.Boolean; 9 | import java.util.Objects; 10 | import java.util.Optional; 11 | import javax.annotation.Nullable; 12 | 13 | 14 | public final class ProviderArgs extends com.pulumi.resources.ResourceArgs { 15 | 16 | public static final ProviderArgs Empty = new ProviderArgs(); 17 | 18 | @Import(name="itsasecret", json=true) 19 | private @Nullable Output itsasecret; 20 | 21 | public Optional> itsasecret() { 22 | return Optional.ofNullable(this.itsasecret); 23 | } 24 | 25 | private ProviderArgs() {} 26 | 27 | private ProviderArgs(ProviderArgs $) { 28 | this.itsasecret = $.itsasecret; 29 | } 30 | 31 | public static Builder builder() { 32 | return new Builder(); 33 | } 34 | public static Builder builder(ProviderArgs defaults) { 35 | return new Builder(defaults); 36 | } 37 | 38 | public static final class Builder { 39 | private ProviderArgs $; 40 | 41 | public Builder() { 42 | $ = new ProviderArgs(); 43 | } 44 | 45 | public Builder(ProviderArgs defaults) { 46 | $ = new ProviderArgs(Objects.requireNonNull(defaults)); 47 | } 48 | 49 | public Builder itsasecret(@Nullable Output itsasecret) { 50 | $.itsasecret = itsasecret; 51 | return this; 52 | } 53 | 54 | public Builder itsasecret(Boolean itsasecret) { 55 | return itsasecret(Output.of(itsasecret)); 56 | } 57 | 58 | public ProviderArgs build() { 59 | return $; 60 | } 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /sdk/java/src/main/java/com/mynamespace/providerboilerplate/Random.java: -------------------------------------------------------------------------------- 1 | // *** WARNING: this file was generated by pulumi-language-java. *** 2 | // *** Do not edit by hand unless you're certain you know what you are doing! *** 3 | 4 | package com.mynamespace.providerboilerplate; 5 | 6 | import com.mynamespace.providerboilerplate.RandomArgs; 7 | import com.mynamespace.providerboilerplate.Utilities; 8 | import com.pulumi.core.Output; 9 | import com.pulumi.core.annotations.Export; 10 | import com.pulumi.core.annotations.ResourceType; 11 | import com.pulumi.core.internal.Codegen; 12 | import java.lang.Integer; 13 | import java.lang.String; 14 | import javax.annotation.Nullable; 15 | 16 | @ResourceType(type="provider-boilerplate:index:Random") 17 | public class Random extends com.pulumi.resources.CustomResource { 18 | @Export(name="length", refs={Integer.class}, tree="[0]") 19 | private Output length; 20 | 21 | public Output length() { 22 | return this.length; 23 | } 24 | @Export(name="result", refs={String.class}, tree="[0]") 25 | private Output result; 26 | 27 | public Output result() { 28 | return this.result; 29 | } 30 | 31 | /** 32 | * 33 | * @param name The _unique_ name of the resulting resource. 34 | */ 35 | public Random(java.lang.String name) { 36 | this(name, RandomArgs.Empty); 37 | } 38 | /** 39 | * 40 | * @param name The _unique_ name of the resulting resource. 41 | * @param args The arguments to use to populate this resource's properties. 42 | */ 43 | public Random(java.lang.String name, RandomArgs args) { 44 | this(name, args, null); 45 | } 46 | /** 47 | * 48 | * @param name The _unique_ name of the resulting resource. 49 | * @param args The arguments to use to populate this resource's properties. 50 | * @param options A bag of options that control this resource's behavior. 51 | */ 52 | public Random(java.lang.String name, RandomArgs args, @Nullable com.pulumi.resources.CustomResourceOptions options) { 53 | super("provider-boilerplate:index:Random", name, makeArgs(args, options), makeResourceOptions(options, Codegen.empty()), false); 54 | } 55 | 56 | private Random(java.lang.String name, Output id, @Nullable com.pulumi.resources.CustomResourceOptions options) { 57 | super("provider-boilerplate:index:Random", name, null, makeResourceOptions(options, id), false); 58 | } 59 | 60 | private static RandomArgs makeArgs(RandomArgs args, @Nullable com.pulumi.resources.CustomResourceOptions options) { 61 | if (options != null && options.getUrn().isPresent()) { 62 | return null; 63 | } 64 | return args == null ? RandomArgs.Empty : args; 65 | } 66 | 67 | private static com.pulumi.resources.CustomResourceOptions makeResourceOptions(@Nullable com.pulumi.resources.CustomResourceOptions options, @Nullable Output id) { 68 | var defaultOptions = com.pulumi.resources.CustomResourceOptions.builder() 69 | .version(Utilities.getVersion()) 70 | .build(); 71 | return com.pulumi.resources.CustomResourceOptions.merge(defaultOptions, options, id); 72 | } 73 | 74 | /** 75 | * Get an existing Host resource's state with the given name, ID, and optional extra 76 | * properties used to qualify the lookup. 77 | * 78 | * @param name The _unique_ name of the resulting resource. 79 | * @param id The _unique_ provider ID of the resource to lookup. 80 | * @param options Optional settings to control the behavior of the CustomResource. 81 | */ 82 | public static Random get(java.lang.String name, Output id, @Nullable com.pulumi.resources.CustomResourceOptions options) { 83 | return new Random(name, id, options); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /sdk/java/src/main/java/com/mynamespace/providerboilerplate/RandomArgs.java: -------------------------------------------------------------------------------- 1 | // *** WARNING: this file was generated by pulumi-language-java. *** 2 | // *** Do not edit by hand unless you're certain you know what you are doing! *** 3 | 4 | package com.mynamespace.providerboilerplate; 5 | 6 | import com.pulumi.core.Output; 7 | import com.pulumi.core.annotations.Import; 8 | import com.pulumi.exceptions.MissingRequiredPropertyException; 9 | import java.lang.Integer; 10 | import java.util.Objects; 11 | 12 | 13 | public final class RandomArgs extends com.pulumi.resources.ResourceArgs { 14 | 15 | public static final RandomArgs Empty = new RandomArgs(); 16 | 17 | @Import(name="length", required=true) 18 | private Output length; 19 | 20 | public Output length() { 21 | return this.length; 22 | } 23 | 24 | private RandomArgs() {} 25 | 26 | private RandomArgs(RandomArgs $) { 27 | this.length = $.length; 28 | } 29 | 30 | public static Builder builder() { 31 | return new Builder(); 32 | } 33 | public static Builder builder(RandomArgs defaults) { 34 | return new Builder(defaults); 35 | } 36 | 37 | public static final class Builder { 38 | private RandomArgs $; 39 | 40 | public Builder() { 41 | $ = new RandomArgs(); 42 | } 43 | 44 | public Builder(RandomArgs defaults) { 45 | $ = new RandomArgs(Objects.requireNonNull(defaults)); 46 | } 47 | 48 | public Builder length(Output length) { 49 | $.length = length; 50 | return this; 51 | } 52 | 53 | public Builder length(Integer length) { 54 | return length(Output.of(length)); 55 | } 56 | 57 | public RandomArgs build() { 58 | if ($.length == null) { 59 | throw new MissingRequiredPropertyException("RandomArgs", "length"); 60 | } 61 | return $; 62 | } 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /sdk/java/src/main/java/com/mynamespace/providerboilerplate/RandomComponent.java: -------------------------------------------------------------------------------- 1 | // *** WARNING: this file was generated by pulumi-language-java. *** 2 | // *** Do not edit by hand unless you're certain you know what you are doing! *** 3 | 4 | package com.mynamespace.providerboilerplate; 5 | 6 | import com.mynamespace.providerboilerplate.RandomComponentArgs; 7 | import com.mynamespace.providerboilerplate.Utilities; 8 | import com.pulumi.core.Output; 9 | import com.pulumi.core.annotations.Export; 10 | import com.pulumi.core.annotations.ResourceType; 11 | import com.pulumi.core.internal.Codegen; 12 | import java.lang.Integer; 13 | import java.lang.String; 14 | import javax.annotation.Nullable; 15 | 16 | @ResourceType(type="provider-boilerplate:index:RandomComponent") 17 | public class RandomComponent extends com.pulumi.resources.ComponentResource { 18 | @Export(name="length", refs={Integer.class}, tree="[0]") 19 | private Output length; 20 | 21 | public Output length() { 22 | return this.length; 23 | } 24 | @Export(name="password", refs={String.class}, tree="[0]") 25 | private Output password; 26 | 27 | public Output password() { 28 | return this.password; 29 | } 30 | 31 | /** 32 | * 33 | * @param name The _unique_ name of the resulting resource. 34 | */ 35 | public RandomComponent(java.lang.String name) { 36 | this(name, RandomComponentArgs.Empty); 37 | } 38 | /** 39 | * 40 | * @param name The _unique_ name of the resulting resource. 41 | * @param args The arguments to use to populate this resource's properties. 42 | */ 43 | public RandomComponent(java.lang.String name, RandomComponentArgs args) { 44 | this(name, args, null); 45 | } 46 | /** 47 | * 48 | * @param name The _unique_ name of the resulting resource. 49 | * @param args The arguments to use to populate this resource's properties. 50 | * @param options A bag of options that control this resource's behavior. 51 | */ 52 | public RandomComponent(java.lang.String name, RandomComponentArgs args, @Nullable com.pulumi.resources.ComponentResourceOptions options) { 53 | super("provider-boilerplate:index:RandomComponent", name, makeArgs(args, options), makeResourceOptions(options, Codegen.empty()), true); 54 | } 55 | 56 | private static RandomComponentArgs makeArgs(RandomComponentArgs args, @Nullable com.pulumi.resources.ComponentResourceOptions options) { 57 | if (options != null && options.getUrn().isPresent()) { 58 | return null; 59 | } 60 | return args == null ? RandomComponentArgs.Empty : args; 61 | } 62 | 63 | private static com.pulumi.resources.ComponentResourceOptions makeResourceOptions(@Nullable com.pulumi.resources.ComponentResourceOptions options, @Nullable Output id) { 64 | var defaultOptions = com.pulumi.resources.ComponentResourceOptions.builder() 65 | .version(Utilities.getVersion()) 66 | .build(); 67 | return com.pulumi.resources.ComponentResourceOptions.merge(defaultOptions, options, id); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /sdk/java/src/main/java/com/mynamespace/providerboilerplate/RandomComponentArgs.java: -------------------------------------------------------------------------------- 1 | // *** WARNING: this file was generated by pulumi-language-java. *** 2 | // *** Do not edit by hand unless you're certain you know what you are doing! *** 3 | 4 | package com.mynamespace.providerboilerplate; 5 | 6 | import com.pulumi.core.Output; 7 | import com.pulumi.core.annotations.Import; 8 | import com.pulumi.exceptions.MissingRequiredPropertyException; 9 | import java.lang.Integer; 10 | import java.util.Objects; 11 | 12 | 13 | public final class RandomComponentArgs extends com.pulumi.resources.ResourceArgs { 14 | 15 | public static final RandomComponentArgs Empty = new RandomComponentArgs(); 16 | 17 | @Import(name="length", required=true) 18 | private Output length; 19 | 20 | public Output length() { 21 | return this.length; 22 | } 23 | 24 | private RandomComponentArgs() {} 25 | 26 | private RandomComponentArgs(RandomComponentArgs $) { 27 | this.length = $.length; 28 | } 29 | 30 | public static Builder builder() { 31 | return new Builder(); 32 | } 33 | public static Builder builder(RandomComponentArgs defaults) { 34 | return new Builder(defaults); 35 | } 36 | 37 | public static final class Builder { 38 | private RandomComponentArgs $; 39 | 40 | public Builder() { 41 | $ = new RandomComponentArgs(); 42 | } 43 | 44 | public Builder(RandomComponentArgs defaults) { 45 | $ = new RandomComponentArgs(Objects.requireNonNull(defaults)); 46 | } 47 | 48 | public Builder length(Output length) { 49 | $.length = length; 50 | return this; 51 | } 52 | 53 | public Builder length(Integer length) { 54 | return length(Output.of(length)); 55 | } 56 | 57 | public RandomComponentArgs build() { 58 | if ($.length == null) { 59 | throw new MissingRequiredPropertyException("RandomComponentArgs", "length"); 60 | } 61 | return $; 62 | } 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /sdk/java/src/main/java/com/mynamespace/providerboilerplate/Utilities.java: -------------------------------------------------------------------------------- 1 | // *** WARNING: this file was generated by pulumi-language-java. *** 2 | // *** Do not edit by hand unless you're certain you know what you are doing! *** 3 | 4 | package com.mynamespace.providerboilerplate; 5 | 6 | 7 | 8 | 9 | 10 | import java.io.BufferedReader; 11 | import java.io.InputStreamReader; 12 | import java.util.Optional; 13 | import java.util.stream.Collectors; 14 | import javax.annotation.Nullable; 15 | import com.pulumi.core.internal.Environment; 16 | import com.pulumi.deployment.InvokeOptions; 17 | import com.pulumi.deployment.InvokeOutputOptions; 18 | 19 | public class Utilities { 20 | 21 | public static Optional getEnv(java.lang.String... names) { 22 | for (var n : names) { 23 | var value = Environment.getEnvironmentVariable(n); 24 | if (value.isValue()) { 25 | return Optional.of(value.value()); 26 | } 27 | } 28 | return Optional.empty(); 29 | } 30 | 31 | public static Optional getEnvBoolean(java.lang.String... names) { 32 | for (var n : names) { 33 | var value = Environment.getBooleanEnvironmentVariable(n); 34 | if (value.isValue()) { 35 | return Optional.of(value.value()); 36 | } 37 | } 38 | return Optional.empty(); 39 | } 40 | 41 | public static Optional getEnvInteger(java.lang.String... names) { 42 | for (var n : names) { 43 | var value = Environment.getIntegerEnvironmentVariable(n); 44 | if (value.isValue()) { 45 | return Optional.of(value.value()); 46 | } 47 | } 48 | return Optional.empty(); 49 | } 50 | 51 | public static Optional getEnvDouble(java.lang.String... names) { 52 | for (var n : names) { 53 | var value = Environment.getDoubleEnvironmentVariable(n); 54 | if (value.isValue()) { 55 | return Optional.of(value.value()); 56 | } 57 | } 58 | return Optional.empty(); 59 | } 60 | 61 | public static InvokeOptions withVersion(@Nullable InvokeOptions options) { 62 | if (options != null && options.getVersion().isPresent()) { 63 | return options; 64 | } 65 | return new InvokeOptions( 66 | options == null ? null : options.getParent().orElse(null), 67 | options == null ? null : options.getProvider().orElse(null), 68 | getVersion() 69 | ); 70 | } 71 | 72 | public static InvokeOutputOptions withVersion(@Nullable InvokeOutputOptions options) { 73 | if (options != null && options.getVersion().isPresent()) { 74 | return options; 75 | } 76 | return new InvokeOutputOptions( 77 | options == null ? null : options.getParent().orElse(null), 78 | options == null ? null : options.getProvider().orElse(null), 79 | getVersion(), 80 | options == null ? null : options.getDependsOn() 81 | ); 82 | } 83 | 84 | private static final java.lang.String version; 85 | public static java.lang.String getVersion() { 86 | return version; 87 | } 88 | 89 | static { 90 | var resourceName = "com/mynamespace/provider-boilerplate/version.txt"; 91 | var versionFile = Utilities.class.getClassLoader().getResourceAsStream(resourceName); 92 | if (versionFile == null) { 93 | throw new IllegalStateException( 94 | java.lang.String.format("expected resource '%s' on Classpath, not found", resourceName) 95 | ); 96 | } 97 | version = new BufferedReader(new InputStreamReader(versionFile)) 98 | .lines() 99 | .collect(Collectors.joining("\n")) 100 | .trim(); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /sdk/nodejs/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pulumi/pulumi-provider-boilerplate/a69fee122706ff35eefd524db1773877d0518b56/sdk/nodejs/README.md -------------------------------------------------------------------------------- /sdk/nodejs/config/index.ts: -------------------------------------------------------------------------------- 1 | // *** WARNING: this file was generated by pulumi-language-nodejs. *** 2 | // *** Do not edit by hand unless you're certain you know what you are doing! *** 3 | 4 | // Export members: 5 | export * from "./vars"; 6 | -------------------------------------------------------------------------------- /sdk/nodejs/config/vars.ts: -------------------------------------------------------------------------------- 1 | // *** WARNING: this file was generated by pulumi-language-nodejs. *** 2 | // *** Do not edit by hand unless you're certain you know what you are doing! *** 3 | 4 | import * as pulumi from "@pulumi/pulumi"; 5 | import * as utilities from "../utilities"; 6 | 7 | declare var exports: any; 8 | const __config = new pulumi.Config("provider-boilerplate"); 9 | 10 | export declare const itsasecret: boolean | undefined; 11 | Object.defineProperty(exports, "itsasecret", { 12 | get() { 13 | return __config.getObject("itsasecret"); 14 | }, 15 | enumerable: true, 16 | }); 17 | 18 | -------------------------------------------------------------------------------- /sdk/nodejs/index.ts: -------------------------------------------------------------------------------- 1 | // *** WARNING: this file was generated by pulumi-language-nodejs. *** 2 | // *** Do not edit by hand unless you're certain you know what you are doing! *** 3 | 4 | import * as pulumi from "@pulumi/pulumi"; 5 | import * as utilities from "./utilities"; 6 | 7 | // Export members: 8 | export { ProviderArgs } from "./provider"; 9 | export type Provider = import("./provider").Provider; 10 | export const Provider: typeof import("./provider").Provider = null as any; 11 | utilities.lazyLoad(exports, ["Provider"], () => require("./provider")); 12 | 13 | export { RandomArgs } from "./random"; 14 | export type Random = import("./random").Random; 15 | export const Random: typeof import("./random").Random = null as any; 16 | utilities.lazyLoad(exports, ["Random"], () => require("./random")); 17 | 18 | export { RandomComponentArgs } from "./randomComponent"; 19 | export type RandomComponent = import("./randomComponent").RandomComponent; 20 | export const RandomComponent: typeof import("./randomComponent").RandomComponent = null as any; 21 | utilities.lazyLoad(exports, ["RandomComponent"], () => require("./randomComponent")); 22 | 23 | 24 | // Export sub-modules: 25 | import * as config from "./config"; 26 | 27 | export { 28 | config, 29 | }; 30 | 31 | const _module = { 32 | version: utilities.getVersion(), 33 | construct: (name: string, type: string, urn: string): pulumi.Resource => { 34 | switch (type) { 35 | case "provider-boilerplate:index:Random": 36 | return new Random(name, undefined, { urn }) 37 | case "provider-boilerplate:index:RandomComponent": 38 | return new RandomComponent(name, undefined, { urn }) 39 | default: 40 | throw new Error(`unknown resource type ${type}`); 41 | } 42 | }, 43 | }; 44 | pulumi.runtime.registerResourceModule("provider-boilerplate", "index", _module) 45 | pulumi.runtime.registerResourcePackage("provider-boilerplate", { 46 | version: utilities.getVersion(), 47 | constructProvider: (name: string, type: string, urn: string): pulumi.ProviderResource => { 48 | if (type !== "pulumi:providers:provider-boilerplate") { 49 | throw new Error(`unknown provider type ${type}`); 50 | } 51 | return new Provider(name, undefined, { urn }); 52 | }, 53 | }); 54 | -------------------------------------------------------------------------------- /sdk/nodejs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@mynamespace/provider-boilerplate", 3 | "version": "1.0.0-alpha.0+dev", 4 | "scripts": { 5 | "build": "tsc" 6 | }, 7 | "dependencies": { 8 | "@pulumi/pulumi": "^3.142.0" 9 | }, 10 | "devDependencies": { 11 | "@types/node": "^18", 12 | "typescript": "^4.3.5" 13 | }, 14 | "pulumi": { 15 | "resource": true, 16 | "name": "provider-boilerplate", 17 | "version": "1.0.0-alpha.0+dev" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /sdk/nodejs/provider.ts: -------------------------------------------------------------------------------- 1 | // *** WARNING: this file was generated by pulumi-language-nodejs. *** 2 | // *** Do not edit by hand unless you're certain you know what you are doing! *** 3 | 4 | import * as pulumi from "@pulumi/pulumi"; 5 | import * as utilities from "./utilities"; 6 | 7 | export class Provider extends pulumi.ProviderResource { 8 | /** @internal */ 9 | public static readonly __pulumiType = 'provider-boilerplate'; 10 | 11 | /** 12 | * Returns true if the given object is an instance of Provider. This is designed to work even 13 | * when multiple copies of the Pulumi SDK have been loaded into the same process. 14 | */ 15 | public static isInstance(obj: any): obj is Provider { 16 | if (obj === undefined || obj === null) { 17 | return false; 18 | } 19 | return obj['__pulumiType'] === "pulumi:providers:" + Provider.__pulumiType; 20 | } 21 | 22 | 23 | /** 24 | * Create a Provider resource with the given unique name, arguments, and options. 25 | * 26 | * @param name The _unique_ name of the resource. 27 | * @param args The arguments to use to populate this resource's properties. 28 | * @param opts A bag of options that control this resource's behavior. 29 | */ 30 | constructor(name: string, args?: ProviderArgs, opts?: pulumi.ResourceOptions) { 31 | let resourceInputs: pulumi.Inputs = {}; 32 | opts = opts || {}; 33 | { 34 | resourceInputs["itsasecret"] = pulumi.output(args ? args.itsasecret : undefined).apply(JSON.stringify); 35 | } 36 | opts = pulumi.mergeOptions(utilities.resourceOptsDefaults(), opts); 37 | super(Provider.__pulumiType, name, resourceInputs, opts); 38 | } 39 | } 40 | 41 | /** 42 | * The set of arguments for constructing a Provider resource. 43 | */ 44 | export interface ProviderArgs { 45 | itsasecret?: pulumi.Input; 46 | } 47 | -------------------------------------------------------------------------------- /sdk/nodejs/random.ts: -------------------------------------------------------------------------------- 1 | // *** WARNING: this file was generated by pulumi-language-nodejs. *** 2 | // *** Do not edit by hand unless you're certain you know what you are doing! *** 3 | 4 | import * as pulumi from "@pulumi/pulumi"; 5 | import * as utilities from "./utilities"; 6 | 7 | export class Random extends pulumi.CustomResource { 8 | /** 9 | * Get an existing Random resource's state with the given name, ID, and optional extra 10 | * properties used to qualify the lookup. 11 | * 12 | * @param name The _unique_ name of the resulting resource. 13 | * @param id The _unique_ provider ID of the resource to lookup. 14 | * @param opts Optional settings to control the behavior of the CustomResource. 15 | */ 16 | public static get(name: string, id: pulumi.Input, opts?: pulumi.CustomResourceOptions): Random { 17 | return new Random(name, undefined as any, { ...opts, id: id }); 18 | } 19 | 20 | /** @internal */ 21 | public static readonly __pulumiType = 'provider-boilerplate:index:Random'; 22 | 23 | /** 24 | * Returns true if the given object is an instance of Random. This is designed to work even 25 | * when multiple copies of the Pulumi SDK have been loaded into the same process. 26 | */ 27 | public static isInstance(obj: any): obj is Random { 28 | if (obj === undefined || obj === null) { 29 | return false; 30 | } 31 | return obj['__pulumiType'] === Random.__pulumiType; 32 | } 33 | 34 | public readonly length!: pulumi.Output; 35 | public /*out*/ readonly result!: pulumi.Output; 36 | 37 | /** 38 | * Create a Random resource with the given unique name, arguments, and options. 39 | * 40 | * @param name The _unique_ name of the resource. 41 | * @param args The arguments to use to populate this resource's properties. 42 | * @param opts A bag of options that control this resource's behavior. 43 | */ 44 | constructor(name: string, args: RandomArgs, opts?: pulumi.CustomResourceOptions) { 45 | let resourceInputs: pulumi.Inputs = {}; 46 | opts = opts || {}; 47 | if (!opts.id) { 48 | if ((!args || args.length === undefined) && !opts.urn) { 49 | throw new Error("Missing required property 'length'"); 50 | } 51 | resourceInputs["length"] = args ? args.length : undefined; 52 | resourceInputs["result"] = undefined /*out*/; 53 | } else { 54 | resourceInputs["length"] = undefined /*out*/; 55 | resourceInputs["result"] = undefined /*out*/; 56 | } 57 | opts = pulumi.mergeOptions(utilities.resourceOptsDefaults(), opts); 58 | super(Random.__pulumiType, name, resourceInputs, opts); 59 | } 60 | } 61 | 62 | /** 63 | * The set of arguments for constructing a Random resource. 64 | */ 65 | export interface RandomArgs { 66 | length: pulumi.Input; 67 | } 68 | -------------------------------------------------------------------------------- /sdk/nodejs/randomComponent.ts: -------------------------------------------------------------------------------- 1 | // *** WARNING: this file was generated by pulumi-language-nodejs. *** 2 | // *** Do not edit by hand unless you're certain you know what you are doing! *** 3 | 4 | import * as pulumi from "@pulumi/pulumi"; 5 | import * as utilities from "./utilities"; 6 | 7 | export class RandomComponent extends pulumi.ComponentResource { 8 | /** @internal */ 9 | public static readonly __pulumiType = 'provider-boilerplate:index:RandomComponent'; 10 | 11 | /** 12 | * Returns true if the given object is an instance of RandomComponent. This is designed to work even 13 | * when multiple copies of the Pulumi SDK have been loaded into the same process. 14 | */ 15 | public static isInstance(obj: any): obj is RandomComponent { 16 | if (obj === undefined || obj === null) { 17 | return false; 18 | } 19 | return obj['__pulumiType'] === RandomComponent.__pulumiType; 20 | } 21 | 22 | public readonly length!: pulumi.Output; 23 | public /*out*/ readonly password!: pulumi.Output; 24 | 25 | /** 26 | * Create a RandomComponent resource with the given unique name, arguments, and options. 27 | * 28 | * @param name The _unique_ name of the resource. 29 | * @param args The arguments to use to populate this resource's properties. 30 | * @param opts A bag of options that control this resource's behavior. 31 | */ 32 | constructor(name: string, args: RandomComponentArgs, opts?: pulumi.ComponentResourceOptions) { 33 | let resourceInputs: pulumi.Inputs = {}; 34 | opts = opts || {}; 35 | if (!opts.id) { 36 | if ((!args || args.length === undefined) && !opts.urn) { 37 | throw new Error("Missing required property 'length'"); 38 | } 39 | resourceInputs["length"] = args ? args.length : undefined; 40 | resourceInputs["password"] = undefined /*out*/; 41 | } else { 42 | resourceInputs["length"] = undefined /*out*/; 43 | resourceInputs["password"] = undefined /*out*/; 44 | } 45 | opts = pulumi.mergeOptions(utilities.resourceOptsDefaults(), opts); 46 | super(RandomComponent.__pulumiType, name, resourceInputs, opts, true /*remote*/); 47 | } 48 | } 49 | 50 | /** 51 | * The set of arguments for constructing a RandomComponent resource. 52 | */ 53 | export interface RandomComponentArgs { 54 | length: pulumi.Input; 55 | } 56 | -------------------------------------------------------------------------------- /sdk/nodejs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "bin", 4 | "target": "es2016", 5 | "module": "commonjs", 6 | "moduleResolution": "node", 7 | "declaration": true, 8 | "sourceMap": true, 9 | "stripInternal": true, 10 | "experimentalDecorators": true, 11 | "noFallthroughCasesInSwitch": true, 12 | "forceConsistentCasingInFileNames": true, 13 | "strict": true 14 | }, 15 | "files": [ 16 | "config/index.ts", 17 | "config/vars.ts", 18 | "index.ts", 19 | "provider.ts", 20 | "random.ts", 21 | "randomComponent.ts", 22 | "utilities.ts" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /sdk/nodejs/utilities.ts: -------------------------------------------------------------------------------- 1 | // *** WARNING: this file was generated by pulumi-language-nodejs. *** 2 | // *** Do not edit by hand unless you're certain you know what you are doing! *** 3 | 4 | 5 | import * as runtime from "@pulumi/pulumi/runtime"; 6 | import * as pulumi from "@pulumi/pulumi"; 7 | 8 | export function getEnv(...vars: string[]): string | undefined { 9 | for (const v of vars) { 10 | const value = process.env[v]; 11 | if (value) { 12 | return value; 13 | } 14 | } 15 | return undefined; 16 | } 17 | 18 | export function getEnvBoolean(...vars: string[]): boolean | undefined { 19 | const s = getEnv(...vars); 20 | if (s !== undefined) { 21 | // NOTE: these values are taken from https://golang.org/src/strconv/atob.go?s=351:391#L1, which is what 22 | // Terraform uses internally when parsing boolean values. 23 | if (["1", "t", "T", "true", "TRUE", "True"].find(v => v === s) !== undefined) { 24 | return true; 25 | } 26 | if (["0", "f", "F", "false", "FALSE", "False"].find(v => v === s) !== undefined) { 27 | return false; 28 | } 29 | } 30 | return undefined; 31 | } 32 | 33 | export function getEnvNumber(...vars: string[]): number | undefined { 34 | const s = getEnv(...vars); 35 | if (s !== undefined) { 36 | const f = parseFloat(s); 37 | if (!isNaN(f)) { 38 | return f; 39 | } 40 | } 41 | return undefined; 42 | } 43 | 44 | export function getVersion(): string { 45 | let version = require('./package.json').version; 46 | // Node allows for the version to be prefixed by a "v", while semver doesn't. 47 | // If there is a v, strip it off. 48 | if (version.indexOf('v') === 0) { 49 | version = version.slice(1); 50 | } 51 | return version; 52 | } 53 | 54 | /** @internal */ 55 | export function resourceOptsDefaults(): any { 56 | return { version: getVersion() }; 57 | } 58 | 59 | /** @internal */ 60 | export function lazyLoad(exports: any, props: string[], loadModule: any) { 61 | for (let property of props) { 62 | Object.defineProperty(exports, property, { 63 | enumerable: true, 64 | get: function() { 65 | return loadModule()[property]; 66 | }, 67 | }); 68 | } 69 | } 70 | 71 | /** @internal */ 72 | export async function callAsync( 73 | tok: string, 74 | props: pulumi.Inputs, 75 | res?: pulumi.Resource, 76 | opts?: {property?: string}, 77 | ): Promise { 78 | const o: any = runtime.call(tok, props, res); 79 | const value = await o.promise(true /*withUnknowns*/); 80 | const isKnown = await o.isKnown; 81 | const isSecret = await o.isSecret; 82 | const problem: string|undefined = 83 | !isKnown ? "an unknown value" 84 | : isSecret ? "a secret value" 85 | : undefined; 86 | // Ingoring o.resources silently. They are typically non-empty, r.f() calls include r as a dependency. 87 | if (problem) { 88 | throw new Error(`Plain resource method "${tok}" incorrectly returned ${problem}. ` + 89 | "This is an error in the provider, please report this to the provider developer."); 90 | } 91 | // Extract a single property if requested. 92 | if (opts && opts.property) { 93 | return value[opts.property]; 94 | } 95 | return value; 96 | } 97 | -------------------------------------------------------------------------------- /sdk/python/README.md: -------------------------------------------------------------------------------- 1 | # Pulumi Native Provider Boilerplate 2 | 3 | This repository is a boilerplate showing how to create and locally test a native Pulumi provider (with examples of both CustomResource and ComponentResource [resource types](https://www.pulumi.com/docs/iac/concepts/resources/)). 4 | 5 | ## Authoring a Pulumi Native Provider 6 | 7 | This boilerplate creates a working Pulumi-owned provider named `provider-boilerplate`. 8 | It implements a random number generator that you can [build and test out for yourself](#test-against-the-example) and then replace the Random code with code specific to your provider. 9 | 10 | 11 | ### Prerequisites 12 | 13 | You will need to ensure the following tools are installed and present in your `$PATH`: 14 | 15 | * [`pulumictl`](https://github.com/pulumi/pulumictl#installation) 16 | * [Go 1.21](https://golang.org/dl/) or 1.latest 17 | * [NodeJS](https://nodejs.org/en/) 14.x. We recommend using [nvm](https://github.com/nvm-sh/nvm) to manage NodeJS installations. 18 | * [Yarn](https://yarnpkg.com/) 19 | * [TypeScript](https://www.typescriptlang.org/) 20 | * [Python](https://www.python.org/downloads/) (called as `python3`). For recent versions of MacOS, the system-installed version is fine. 21 | * [.NET](https://dotnet.microsoft.com/download) 22 | 23 | 24 | ### Build & test the boilerplate provider 25 | 26 | 1. Run `make build install` to build and install the provider. 27 | 1. Run `make gen_examples` to generate the example programs in `examples/` off of the source `examples/yaml` example program. 28 | 1. Run `make up` to run the example program in `examples/yaml`. 29 | 1. Run `make down` to tear down the example program. 30 | 31 | ### Creating a new provider repository 32 | 33 | Pulumi offers this repository as a [GitHub template repository](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-repository-from-a-template) for convenience. From this repository: 34 | 35 | 1. Click "Use this template". 36 | 1. Set the following options: 37 | * Owner: pulumi 38 | * Repository name: pulumi-provider-boilerplate (replace "provider-boilerplate" with the name of your provider) 39 | * Description: Pulumi provider for xyz 40 | * Repository type: Public 41 | 1. Clone the generated repository. 42 | 43 | From the templated repository: 44 | 45 | 1. Run the following command to update files to use the name of your provider (third-party: use your GitHub organization/username): 46 | 47 | ```bash 48 | make prepare NAME=foo ORG=myorg REPOSITORY=github.com/myorg/pulumi-foo 49 | ``` 50 | 51 | This will do the following: 52 | - rename folders in `provider/cmd` to `pulumi-resource-{NAME}` 53 | - replace dependencies in `provider/go.mod` to reflect your repository name 54 | - find and replace all instances of `provider-boilerplate` with the `NAME` of your provider. 55 | - find and replace all instances of the boilerplate `abc` with the `ORG` of your provider. 56 | - replace all instances of the `github.com/pulumi/pulumi-provider-boilerplate` repository with the `REPOSITORY` location 57 | 58 | #### Build the provider and install the plugin 59 | 60 | ```bash 61 | $ make build install 62 | ``` 63 | 64 | This will: 65 | 66 | 1. Create the SDK codegen binary and place it in a `./bin` folder (gitignored) 67 | 2. Create the provider binary and place it in the `./bin` folder (gitignored) 68 | 3. Generate the dotnet, Go, Node, and Python SDKs and place them in the `./sdk` folder 69 | 4. Install the provider on your machine. 70 | 71 | #### Test against the example 72 | 73 | ```bash 74 | $ cd examples/simple 75 | $ yarn link @pulumi/provider-boilerplate 76 | $ yarn install 77 | $ pulumi stack init test 78 | $ pulumi up 79 | ``` 80 | 81 | Now that you have completed all of the above steps, you have a working provider that generates a random string for you. 82 | 83 | #### A brief repository overview 84 | 85 | You now have: 86 | 87 | 1. A `provider/` folder containing the building and implementation logic 88 | 1. `cmd/pulumi-resource-provider-boilerplate/main.go` - holds the provider's sample implementation logic. 89 | 2. `deployment-templates` - a set of files to help you around deployment and publication 90 | 3. `sdk` - holds the generated code libraries created by `pulumi gen-sdk` 91 | 4. `examples` a folder of Pulumi programs to try locally and/or use in CI. 92 | 5. A `Makefile` and this `README`. 93 | 94 | #### Additional Details 95 | 96 | This repository depends on the pulumi-go-provider library. For more details on building providers, please check 97 | the [Pulumi Go Provider docs](https://github.com/pulumi/pulumi-go-provider). 98 | 99 | ### Build Examples 100 | 101 | Create an example program using the resources defined in your provider, and place it in the `examples/` folder. 102 | 103 | You can now repeat the steps for [build, install, and test](#test-against-the-example). 104 | 105 | ## Configuring CI and releases 106 | 107 | 1. Follow the instructions laid out in the [deployment templates](./deployment-templates/README-DEPLOYMENT.md). 108 | 109 | ## References 110 | 111 | Other resources/examples for implementing providers: 112 | * [Pulumi Command provider](https://github.com/pulumi/pulumi-command/blob/master/provider/pkg/provider/provider.go) 113 | * [Pulumi Go Provider repository](https://github.com/pulumi/pulumi-go-provider) 114 | -------------------------------------------------------------------------------- /sdk/python/mynamespace_provider_boilerplate/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pulumi/pulumi-provider-boilerplate/a69fee122706ff35eefd524db1773877d0518b56/sdk/python/mynamespace_provider_boilerplate/README.md -------------------------------------------------------------------------------- /sdk/python/mynamespace_provider_boilerplate/__init__.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # *** WARNING: this file was generated by pulumi-language-python. *** 3 | # *** Do not edit by hand unless you're certain you know what you are doing! *** 4 | 5 | import builtins 6 | from . import _utilities 7 | import typing 8 | # Export this package's modules as members: 9 | from .provider import * 10 | from .random import * 11 | from .random_component import * 12 | 13 | # Make subpackages available: 14 | if typing.TYPE_CHECKING: 15 | import mynamespace_provider_boilerplate.config as __config 16 | config = __config 17 | else: 18 | config = _utilities.lazy_import('mynamespace_provider_boilerplate.config') 19 | 20 | _utilities.register( 21 | resource_modules=""" 22 | [ 23 | { 24 | "pkg": "provider-boilerplate", 25 | "mod": "index", 26 | "fqn": "mynamespace_provider_boilerplate", 27 | "classes": { 28 | "provider-boilerplate:index:Random": "Random", 29 | "provider-boilerplate:index:RandomComponent": "RandomComponent" 30 | } 31 | } 32 | ] 33 | """, 34 | resource_packages=""" 35 | [ 36 | { 37 | "pkg": "provider-boilerplate", 38 | "token": "pulumi:providers:provider-boilerplate", 39 | "fqn": "mynamespace_provider_boilerplate", 40 | "class": "Provider" 41 | } 42 | ] 43 | """ 44 | ) 45 | -------------------------------------------------------------------------------- /sdk/python/mynamespace_provider_boilerplate/_utilities.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # *** WARNING: this file was generated by pulumi-language-python. *** 3 | # *** Do not edit by hand unless you're certain you know what you are doing! *** 4 | 5 | 6 | import asyncio 7 | import functools 8 | import importlib.metadata 9 | import importlib.util 10 | import inspect 11 | import json 12 | import os 13 | import sys 14 | import typing 15 | import warnings 16 | import base64 17 | 18 | import pulumi 19 | import pulumi.runtime 20 | from pulumi.runtime.sync_await import _sync_await 21 | from pulumi.runtime.proto import resource_pb2 22 | 23 | from semver import VersionInfo as SemverVersion 24 | from parver import Version as PEP440Version 25 | 26 | C = typing.TypeVar("C", bound=typing.Callable) 27 | 28 | 29 | def get_env(*args): 30 | for v in args: 31 | value = os.getenv(v) 32 | if value is not None: 33 | return value 34 | return None 35 | 36 | 37 | def get_env_bool(*args): 38 | str = get_env(*args) 39 | if str is not None: 40 | # NOTE: these values are taken from https://golang.org/src/strconv/atob.go?s=351:391#L1, which is what 41 | # Terraform uses internally when parsing boolean values. 42 | if str in ["1", "t", "T", "true", "TRUE", "True"]: 43 | return True 44 | if str in ["0", "f", "F", "false", "FALSE", "False"]: 45 | return False 46 | return None 47 | 48 | 49 | def get_env_int(*args): 50 | str = get_env(*args) 51 | if str is not None: 52 | try: 53 | return int(str) 54 | except: 55 | return None 56 | return None 57 | 58 | 59 | def get_env_float(*args): 60 | str = get_env(*args) 61 | if str is not None: 62 | try: 63 | return float(str) 64 | except: 65 | return None 66 | return None 67 | 68 | 69 | def _get_semver_version(): 70 | # __name__ is set to the fully-qualified name of the current module, In our case, it will be 71 | # ._utilities. is the module we want to query the version for. 72 | root_package, *rest = __name__.split('.') 73 | 74 | # pkg_resources uses setuptools to inspect the set of installed packages. We use it here to ask 75 | # for the currently installed version of the root package (i.e. us) and get its version. 76 | 77 | # Unfortunately, PEP440 and semver differ slightly in incompatible ways. The Pulumi engine expects 78 | # to receive a valid semver string when receiving requests from the language host, so it's our 79 | # responsibility as the library to convert our own PEP440 version into a valid semver string. 80 | 81 | pep440_version_string = importlib.metadata.version(root_package) 82 | pep440_version = PEP440Version.parse(pep440_version_string) 83 | (major, minor, patch) = pep440_version.release 84 | prerelease = None 85 | if pep440_version.pre_tag == 'a': 86 | prerelease = f"alpha.{pep440_version.pre}" 87 | elif pep440_version.pre_tag == 'b': 88 | prerelease = f"beta.{pep440_version.pre}" 89 | elif pep440_version.pre_tag == 'rc': 90 | prerelease = f"rc.{pep440_version.pre}" 91 | elif pep440_version.dev is not None: 92 | # PEP440 has explicit support for dev builds, while semver encodes them as "prerelease" versions. To bridge 93 | # between the two, we convert our dev build version into a prerelease tag. This matches what all of our other 94 | # packages do when constructing their own semver string. 95 | prerelease = f"dev.{pep440_version.dev}" 96 | elif pep440_version.local is not None: 97 | # PEP440 only allows a small set of prerelease tags, so when converting an arbitrary prerelease, 98 | # PypiVersion in /pkg/codegen/python/utilities.go converts it to a local version. Therefore, we need to 99 | # do the reverse conversion here and set the local version as the prerelease tag. 100 | prerelease = pep440_version.local 101 | 102 | return SemverVersion(major=major, minor=minor, patch=patch, prerelease=prerelease) 103 | 104 | 105 | # Determine the version once and cache the value, which measurably improves program performance. 106 | _version = _get_semver_version() 107 | _version_str = str(_version) 108 | 109 | def get_resource_opts_defaults() -> pulumi.ResourceOptions: 110 | return pulumi.ResourceOptions( 111 | version=get_version(), 112 | plugin_download_url=get_plugin_download_url(), 113 | ) 114 | 115 | def get_invoke_opts_defaults() -> pulumi.InvokeOptions: 116 | return pulumi.InvokeOptions( 117 | version=get_version(), 118 | plugin_download_url=get_plugin_download_url(), 119 | ) 120 | 121 | def get_resource_args_opts(resource_args_type, resource_options_type, *args, **kwargs): 122 | """ 123 | Return the resource args and options given the *args and **kwargs of a resource's 124 | __init__ method. 125 | """ 126 | 127 | resource_args, opts = None, None 128 | 129 | # If the first item is the resource args type, save it and remove it from the args list. 130 | if args and isinstance(args[0], resource_args_type): 131 | resource_args, args = args[0], args[1:] 132 | 133 | # Now look at the first item in the args list again. 134 | # If the first item is the resource options class, save it. 135 | if args and isinstance(args[0], resource_options_type): 136 | opts = args[0] 137 | 138 | # If resource_args is None, see if "args" is in kwargs, and, if so, if it's typed as the 139 | # the resource args type. 140 | if resource_args is None: 141 | a = kwargs.get("args") 142 | if isinstance(a, resource_args_type): 143 | resource_args = a 144 | 145 | # If opts is None, look it up in kwargs. 146 | if opts is None: 147 | opts = kwargs.get("opts") 148 | 149 | return resource_args, opts 150 | 151 | 152 | # Temporary: just use pulumi._utils.lazy_import once everyone upgrades. 153 | def lazy_import(fullname): 154 | 155 | import pulumi._utils as u 156 | f = getattr(u, 'lazy_import', None) 157 | if f is None: 158 | f = _lazy_import_temp 159 | 160 | return f(fullname) 161 | 162 | 163 | # Copied from pulumi._utils.lazy_import, see comments there. 164 | def _lazy_import_temp(fullname): 165 | m = sys.modules.get(fullname, None) 166 | if m is not None: 167 | return m 168 | 169 | spec = importlib.util.find_spec(fullname) 170 | 171 | m = sys.modules.get(fullname, None) 172 | if m is not None: 173 | return m 174 | 175 | loader = importlib.util.LazyLoader(spec.loader) 176 | spec.loader = loader 177 | module = importlib.util.module_from_spec(spec) 178 | 179 | m = sys.modules.get(fullname, None) 180 | if m is not None: 181 | return m 182 | 183 | sys.modules[fullname] = module 184 | loader.exec_module(module) 185 | return module 186 | 187 | 188 | class Package(pulumi.runtime.ResourcePackage): 189 | def __init__(self, pkg_info): 190 | super().__init__() 191 | self.pkg_info = pkg_info 192 | 193 | def version(self): 194 | return _version 195 | 196 | def construct_provider(self, name: str, typ: str, urn: str) -> pulumi.ProviderResource: 197 | if typ != self.pkg_info['token']: 198 | raise Exception(f"unknown provider type {typ}") 199 | Provider = getattr(lazy_import(self.pkg_info['fqn']), self.pkg_info['class']) 200 | return Provider(name, pulumi.ResourceOptions(urn=urn)) 201 | 202 | 203 | class Module(pulumi.runtime.ResourceModule): 204 | def __init__(self, mod_info): 205 | super().__init__() 206 | self.mod_info = mod_info 207 | 208 | def version(self): 209 | return _version 210 | 211 | def construct(self, name: str, typ: str, urn: str) -> pulumi.Resource: 212 | class_name = self.mod_info['classes'].get(typ, None) 213 | 214 | if class_name is None: 215 | raise Exception(f"unknown resource type {typ}") 216 | 217 | TheClass = getattr(lazy_import(self.mod_info['fqn']), class_name) 218 | return TheClass(name, pulumi.ResourceOptions(urn=urn)) 219 | 220 | 221 | def register(resource_modules, resource_packages): 222 | resource_modules = json.loads(resource_modules) 223 | resource_packages = json.loads(resource_packages) 224 | 225 | for pkg_info in resource_packages: 226 | pulumi.runtime.register_resource_package(pkg_info['pkg'], Package(pkg_info)) 227 | 228 | for mod_info in resource_modules: 229 | pulumi.runtime.register_resource_module( 230 | mod_info['pkg'], 231 | mod_info['mod'], 232 | Module(mod_info)) 233 | 234 | 235 | _F = typing.TypeVar('_F', bound=typing.Callable[..., typing.Any]) 236 | 237 | 238 | def lift_output_func(func: typing.Any) -> typing.Callable[[_F], _F]: 239 | """Decorator internally used on {fn}_output lifted function versions 240 | to implement them automatically from the un-lifted function.""" 241 | 242 | func_sig = inspect.signature(func) 243 | 244 | def lifted_func(*args, opts=None, **kwargs): 245 | bound_args = func_sig.bind(*args, **kwargs) 246 | # Convert tuple to list, see pulumi/pulumi#8172 247 | args_list = list(bound_args.args) 248 | return pulumi.Output.from_input({ 249 | 'args': args_list, 250 | 'kwargs': bound_args.kwargs 251 | }).apply(lambda resolved_args: func(*resolved_args['args'], 252 | opts=opts, 253 | **resolved_args['kwargs'])) 254 | 255 | return (lambda _: lifted_func) 256 | 257 | 258 | def call_plain( 259 | tok: str, 260 | props: pulumi.Inputs, 261 | res: typing.Optional[pulumi.Resource] = None, 262 | typ: typing.Optional[type] = None, 263 | ) -> typing.Any: 264 | """ 265 | Wraps pulumi.runtime.plain to force the output and return it plainly. 266 | """ 267 | 268 | output = pulumi.runtime.call(tok, props, res, typ) 269 | 270 | # Ingoring deps silently. They are typically non-empty, r.f() calls include r as a dependency. 271 | result, known, secret, _ = _sync_await(asyncio.create_task(_await_output(output))) 272 | 273 | problem = None 274 | if not known: 275 | problem = ' an unknown value' 276 | elif secret: 277 | problem = ' a secret value' 278 | 279 | if problem: 280 | raise AssertionError( 281 | f"Plain resource method '{tok}' incorrectly returned {problem}. " 282 | + "This is an error in the provider, please report this to the provider developer." 283 | ) 284 | 285 | return result 286 | 287 | 288 | async def _await_output(o: pulumi.Output[typing.Any]) -> typing.Tuple[object, bool, bool, set]: 289 | return ( 290 | await o._future, 291 | await o._is_known, 292 | await o._is_secret, 293 | await o._resources, 294 | ) 295 | 296 | 297 | # This is included to provide an upgrade path for users who are using a version 298 | # of the Pulumi SDK (<3.121.0) that does not include the `deprecated` decorator. 299 | def deprecated(message: str) -> typing.Callable[[C], C]: 300 | """ 301 | Decorator to indicate a function is deprecated. 302 | 303 | As well as inserting appropriate statements to indicate that the function is 304 | deprecated, this decorator also tags the function with a special attribute 305 | so that Pulumi code can detect that it is deprecated and react appropriately 306 | in certain situations. 307 | 308 | message is the deprecation message that should be printed if the function is called. 309 | """ 310 | 311 | def decorator(fn: C) -> C: 312 | if not callable(fn): 313 | raise TypeError("Expected fn to be callable") 314 | 315 | @functools.wraps(fn) 316 | def deprecated_fn(*args, **kwargs): 317 | warnings.warn(message) 318 | pulumi.warn(f"{fn.__name__} is deprecated: {message}") 319 | 320 | return fn(*args, **kwargs) 321 | 322 | deprecated_fn.__dict__["_pulumi_deprecated_callable"] = fn 323 | return typing.cast(C, deprecated_fn) 324 | 325 | return decorator 326 | 327 | def get_plugin_download_url(): 328 | return None 329 | 330 | def get_version(): 331 | return _version_str 332 | -------------------------------------------------------------------------------- /sdk/python/mynamespace_provider_boilerplate/config/__init__.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # *** WARNING: this file was generated by pulumi-language-python. *** 3 | # *** Do not edit by hand unless you're certain you know what you are doing! *** 4 | 5 | import builtins 6 | import sys 7 | from .vars import _ExportableConfig 8 | 9 | sys.modules[__name__].__class__ = _ExportableConfig 10 | -------------------------------------------------------------------------------- /sdk/python/mynamespace_provider_boilerplate/config/__init__.pyi: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # *** WARNING: this file was generated by pulumi-language-python. *** 3 | # *** Do not edit by hand unless you're certain you know what you are doing! *** 4 | 5 | import builtins 6 | import copy 7 | import warnings 8 | import sys 9 | import pulumi 10 | import pulumi.runtime 11 | from typing import Any, Mapping, Optional, Sequence, Union, overload 12 | if sys.version_info >= (3, 11): 13 | from typing import NotRequired, TypedDict, TypeAlias 14 | else: 15 | from typing_extensions import NotRequired, TypedDict, TypeAlias 16 | from .. import _utilities 17 | 18 | itsasecret: Optional[bool] 19 | 20 | -------------------------------------------------------------------------------- /sdk/python/mynamespace_provider_boilerplate/config/vars.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # *** WARNING: this file was generated by pulumi-language-python. *** 3 | # *** Do not edit by hand unless you're certain you know what you are doing! *** 4 | 5 | import builtins 6 | import copy 7 | import warnings 8 | import sys 9 | import pulumi 10 | import pulumi.runtime 11 | from typing import Any, Mapping, Optional, Sequence, Union, overload 12 | if sys.version_info >= (3, 11): 13 | from typing import NotRequired, TypedDict, TypeAlias 14 | else: 15 | from typing_extensions import NotRequired, TypedDict, TypeAlias 16 | from .. import _utilities 17 | 18 | import types 19 | 20 | __config__ = pulumi.Config('provider-boilerplate') 21 | 22 | 23 | class _ExportableConfig(types.ModuleType): 24 | @property 25 | def itsasecret(self) -> Optional[bool]: 26 | return __config__.get_bool('itsasecret') 27 | 28 | -------------------------------------------------------------------------------- /sdk/python/mynamespace_provider_boilerplate/provider.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # *** WARNING: this file was generated by pulumi-language-python. *** 3 | # *** Do not edit by hand unless you're certain you know what you are doing! *** 4 | 5 | import builtins 6 | import copy 7 | import warnings 8 | import sys 9 | import pulumi 10 | import pulumi.runtime 11 | from typing import Any, Mapping, Optional, Sequence, Union, overload 12 | if sys.version_info >= (3, 11): 13 | from typing import NotRequired, TypedDict, TypeAlias 14 | else: 15 | from typing_extensions import NotRequired, TypedDict, TypeAlias 16 | from . import _utilities 17 | 18 | __all__ = ['ProviderArgs', 'Provider'] 19 | 20 | @pulumi.input_type 21 | class ProviderArgs: 22 | def __init__(__self__, *, 23 | itsasecret: Optional[pulumi.Input[builtins.bool]] = None): 24 | """ 25 | The set of arguments for constructing a Provider resource. 26 | """ 27 | if itsasecret is not None: 28 | pulumi.set(__self__, "itsasecret", itsasecret) 29 | 30 | @property 31 | @pulumi.getter 32 | def itsasecret(self) -> Optional[pulumi.Input[builtins.bool]]: 33 | return pulumi.get(self, "itsasecret") 34 | 35 | @itsasecret.setter 36 | def itsasecret(self, value: Optional[pulumi.Input[builtins.bool]]): 37 | pulumi.set(self, "itsasecret", value) 38 | 39 | 40 | @pulumi.type_token("pulumi:providers:provider-boilerplate") 41 | class Provider(pulumi.ProviderResource): 42 | @overload 43 | def __init__(__self__, 44 | resource_name: str, 45 | opts: Optional[pulumi.ResourceOptions] = None, 46 | itsasecret: Optional[pulumi.Input[builtins.bool]] = None, 47 | __props__=None): 48 | """ 49 | Create a Provider-boilerplate resource with the given unique name, props, and options. 50 | :param str resource_name: The name of the resource. 51 | :param pulumi.ResourceOptions opts: Options for the resource. 52 | """ 53 | ... 54 | @overload 55 | def __init__(__self__, 56 | resource_name: str, 57 | args: Optional[ProviderArgs] = None, 58 | opts: Optional[pulumi.ResourceOptions] = None): 59 | """ 60 | Create a Provider-boilerplate resource with the given unique name, props, and options. 61 | :param str resource_name: The name of the resource. 62 | :param ProviderArgs args: The arguments to use to populate this resource's properties. 63 | :param pulumi.ResourceOptions opts: Options for the resource. 64 | """ 65 | ... 66 | def __init__(__self__, resource_name: str, *args, **kwargs): 67 | resource_args, opts = _utilities.get_resource_args_opts(ProviderArgs, pulumi.ResourceOptions, *args, **kwargs) 68 | if resource_args is not None: 69 | __self__._internal_init(resource_name, opts, **resource_args.__dict__) 70 | else: 71 | __self__._internal_init(resource_name, *args, **kwargs) 72 | 73 | def _internal_init(__self__, 74 | resource_name: str, 75 | opts: Optional[pulumi.ResourceOptions] = None, 76 | itsasecret: Optional[pulumi.Input[builtins.bool]] = None, 77 | __props__=None): 78 | opts = pulumi.ResourceOptions.merge(_utilities.get_resource_opts_defaults(), opts) 79 | if not isinstance(opts, pulumi.ResourceOptions): 80 | raise TypeError('Expected resource options to be a ResourceOptions instance') 81 | if opts.id is None: 82 | if __props__ is not None: 83 | raise TypeError('__props__ is only valid when passed in combination with a valid opts.id to get an existing resource') 84 | __props__ = ProviderArgs.__new__(ProviderArgs) 85 | 86 | __props__.__dict__["itsasecret"] = pulumi.Output.from_input(itsasecret).apply(pulumi.runtime.to_json) if itsasecret is not None else None 87 | super(Provider, __self__).__init__( 88 | 'provider-boilerplate', 89 | resource_name, 90 | __props__, 91 | opts) 92 | 93 | -------------------------------------------------------------------------------- /sdk/python/mynamespace_provider_boilerplate/pulumi-plugin.json: -------------------------------------------------------------------------------- 1 | { 2 | "resource": true, 3 | "name": "provider-boilerplate", 4 | "version": "1.0.0-alpha.0+dev" 5 | } 6 | -------------------------------------------------------------------------------- /sdk/python/mynamespace_provider_boilerplate/py.typed: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pulumi/pulumi-provider-boilerplate/a69fee122706ff35eefd524db1773877d0518b56/sdk/python/mynamespace_provider_boilerplate/py.typed -------------------------------------------------------------------------------- /sdk/python/mynamespace_provider_boilerplate/random.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # *** WARNING: this file was generated by pulumi-language-python. *** 3 | # *** Do not edit by hand unless you're certain you know what you are doing! *** 4 | 5 | import builtins 6 | import copy 7 | import warnings 8 | import sys 9 | import pulumi 10 | import pulumi.runtime 11 | from typing import Any, Mapping, Optional, Sequence, Union, overload 12 | if sys.version_info >= (3, 11): 13 | from typing import NotRequired, TypedDict, TypeAlias 14 | else: 15 | from typing_extensions import NotRequired, TypedDict, TypeAlias 16 | from . import _utilities 17 | 18 | __all__ = ['RandomArgs', 'Random'] 19 | 20 | @pulumi.input_type 21 | class RandomArgs: 22 | def __init__(__self__, *, 23 | length: pulumi.Input[builtins.int]): 24 | """ 25 | The set of arguments for constructing a Random resource. 26 | """ 27 | pulumi.set(__self__, "length", length) 28 | 29 | @property 30 | @pulumi.getter 31 | def length(self) -> pulumi.Input[builtins.int]: 32 | return pulumi.get(self, "length") 33 | 34 | @length.setter 35 | def length(self, value: pulumi.Input[builtins.int]): 36 | pulumi.set(self, "length", value) 37 | 38 | 39 | @pulumi.type_token("provider-boilerplate:index:Random") 40 | class Random(pulumi.CustomResource): 41 | @overload 42 | def __init__(__self__, 43 | resource_name: str, 44 | opts: Optional[pulumi.ResourceOptions] = None, 45 | length: Optional[pulumi.Input[builtins.int]] = None, 46 | __props__=None): 47 | """ 48 | Create a Random resource with the given unique name, props, and options. 49 | :param str resource_name: The name of the resource. 50 | :param pulumi.ResourceOptions opts: Options for the resource. 51 | """ 52 | ... 53 | @overload 54 | def __init__(__self__, 55 | resource_name: str, 56 | args: RandomArgs, 57 | opts: Optional[pulumi.ResourceOptions] = None): 58 | """ 59 | Create a Random resource with the given unique name, props, and options. 60 | :param str resource_name: The name of the resource. 61 | :param RandomArgs args: The arguments to use to populate this resource's properties. 62 | :param pulumi.ResourceOptions opts: Options for the resource. 63 | """ 64 | ... 65 | def __init__(__self__, resource_name: str, *args, **kwargs): 66 | resource_args, opts = _utilities.get_resource_args_opts(RandomArgs, pulumi.ResourceOptions, *args, **kwargs) 67 | if resource_args is not None: 68 | __self__._internal_init(resource_name, opts, **resource_args.__dict__) 69 | else: 70 | __self__._internal_init(resource_name, *args, **kwargs) 71 | 72 | def _internal_init(__self__, 73 | resource_name: str, 74 | opts: Optional[pulumi.ResourceOptions] = None, 75 | length: Optional[pulumi.Input[builtins.int]] = None, 76 | __props__=None): 77 | opts = pulumi.ResourceOptions.merge(_utilities.get_resource_opts_defaults(), opts) 78 | if not isinstance(opts, pulumi.ResourceOptions): 79 | raise TypeError('Expected resource options to be a ResourceOptions instance') 80 | if opts.id is None: 81 | if __props__ is not None: 82 | raise TypeError('__props__ is only valid when passed in combination with a valid opts.id to get an existing resource') 83 | __props__ = RandomArgs.__new__(RandomArgs) 84 | 85 | if length is None and not opts.urn: 86 | raise TypeError("Missing required property 'length'") 87 | __props__.__dict__["length"] = length 88 | __props__.__dict__["result"] = None 89 | super(Random, __self__).__init__( 90 | 'provider-boilerplate:index:Random', 91 | resource_name, 92 | __props__, 93 | opts) 94 | 95 | @staticmethod 96 | def get(resource_name: str, 97 | id: pulumi.Input[str], 98 | opts: Optional[pulumi.ResourceOptions] = None) -> 'Random': 99 | """ 100 | Get an existing Random resource's state with the given name, id, and optional extra 101 | properties used to qualify the lookup. 102 | 103 | :param str resource_name: The unique name of the resulting resource. 104 | :param pulumi.Input[str] id: The unique provider ID of the resource to lookup. 105 | :param pulumi.ResourceOptions opts: Options for the resource. 106 | """ 107 | opts = pulumi.ResourceOptions.merge(opts, pulumi.ResourceOptions(id=id)) 108 | 109 | __props__ = RandomArgs.__new__(RandomArgs) 110 | 111 | __props__.__dict__["length"] = None 112 | __props__.__dict__["result"] = None 113 | return Random(resource_name, opts=opts, __props__=__props__) 114 | 115 | @property 116 | @pulumi.getter 117 | def length(self) -> pulumi.Output[builtins.int]: 118 | return pulumi.get(self, "length") 119 | 120 | @property 121 | @pulumi.getter 122 | def result(self) -> pulumi.Output[builtins.str]: 123 | return pulumi.get(self, "result") 124 | 125 | -------------------------------------------------------------------------------- /sdk/python/mynamespace_provider_boilerplate/random_component.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # *** WARNING: this file was generated by pulumi-language-python. *** 3 | # *** Do not edit by hand unless you're certain you know what you are doing! *** 4 | 5 | import builtins 6 | import copy 7 | import warnings 8 | import sys 9 | import pulumi 10 | import pulumi.runtime 11 | from typing import Any, Mapping, Optional, Sequence, Union, overload 12 | if sys.version_info >= (3, 11): 13 | from typing import NotRequired, TypedDict, TypeAlias 14 | else: 15 | from typing_extensions import NotRequired, TypedDict, TypeAlias 16 | from . import _utilities 17 | 18 | __all__ = ['RandomComponentArgs', 'RandomComponent'] 19 | 20 | @pulumi.input_type 21 | class RandomComponentArgs: 22 | def __init__(__self__, *, 23 | length: pulumi.Input[builtins.int]): 24 | """ 25 | The set of arguments for constructing a RandomComponent resource. 26 | """ 27 | pulumi.set(__self__, "length", length) 28 | 29 | @property 30 | @pulumi.getter 31 | def length(self) -> pulumi.Input[builtins.int]: 32 | return pulumi.get(self, "length") 33 | 34 | @length.setter 35 | def length(self, value: pulumi.Input[builtins.int]): 36 | pulumi.set(self, "length", value) 37 | 38 | 39 | @pulumi.type_token("provider-boilerplate:index:RandomComponent") 40 | class RandomComponent(pulumi.ComponentResource): 41 | @overload 42 | def __init__(__self__, 43 | resource_name: str, 44 | opts: Optional[pulumi.ResourceOptions] = None, 45 | length: Optional[pulumi.Input[builtins.int]] = None, 46 | __props__=None): 47 | """ 48 | Create a RandomComponent resource with the given unique name, props, and options. 49 | :param str resource_name: The name of the resource. 50 | :param pulumi.ResourceOptions opts: Options for the resource. 51 | """ 52 | ... 53 | @overload 54 | def __init__(__self__, 55 | resource_name: str, 56 | args: RandomComponentArgs, 57 | opts: Optional[pulumi.ResourceOptions] = None): 58 | """ 59 | Create a RandomComponent resource with the given unique name, props, and options. 60 | :param str resource_name: The name of the resource. 61 | :param RandomComponentArgs args: The arguments to use to populate this resource's properties. 62 | :param pulumi.ResourceOptions opts: Options for the resource. 63 | """ 64 | ... 65 | def __init__(__self__, resource_name: str, *args, **kwargs): 66 | resource_args, opts = _utilities.get_resource_args_opts(RandomComponentArgs, pulumi.ResourceOptions, *args, **kwargs) 67 | if resource_args is not None: 68 | __self__._internal_init(resource_name, opts, **resource_args.__dict__) 69 | else: 70 | __self__._internal_init(resource_name, *args, **kwargs) 71 | 72 | def _internal_init(__self__, 73 | resource_name: str, 74 | opts: Optional[pulumi.ResourceOptions] = None, 75 | length: Optional[pulumi.Input[builtins.int]] = None, 76 | __props__=None): 77 | opts = pulumi.ResourceOptions.merge(_utilities.get_resource_opts_defaults(), opts) 78 | if not isinstance(opts, pulumi.ResourceOptions): 79 | raise TypeError('Expected resource options to be a ResourceOptions instance') 80 | if opts.id is not None: 81 | raise ValueError('ComponentResource classes do not support opts.id') 82 | else: 83 | if __props__ is not None: 84 | raise TypeError('__props__ is only valid when passed in combination with a valid opts.id to get an existing resource') 85 | __props__ = RandomComponentArgs.__new__(RandomComponentArgs) 86 | 87 | if length is None and not opts.urn: 88 | raise TypeError("Missing required property 'length'") 89 | __props__.__dict__["length"] = length 90 | __props__.__dict__["password"] = None 91 | super(RandomComponent, __self__).__init__( 92 | 'provider-boilerplate:index:RandomComponent', 93 | resource_name, 94 | __props__, 95 | opts, 96 | remote=True) 97 | 98 | @property 99 | @pulumi.getter 100 | def length(self) -> pulumi.Output[builtins.int]: 101 | return pulumi.get(self, "length") 102 | 103 | @property 104 | @pulumi.getter 105 | def password(self) -> pulumi.Output[builtins.str]: 106 | return pulumi.get(self, "password") 107 | 108 | -------------------------------------------------------------------------------- /sdk/python/pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "mynamespace_provider_boilerplate" 3 | dependencies = ["parver>=0.2.1", "pulumi>=3.165.0,<4.0.0", "semver>=2.8.1", "typing-extensions>=4.11,<5; python_version < \"3.11\""] 4 | readme = "README.md" 5 | requires-python = ">=3.9" 6 | version = "1.0.0a0+dev" 7 | 8 | [build-system] 9 | requires = ["setuptools>=61.0"] 10 | build-backend = "setuptools.build_meta" 11 | 12 | [tool] 13 | [tool.setuptools] 14 | [tool.setuptools.package-data] 15 | mynamespace_provider_boilerplate = ["py.typed", "pulumi-plugin.json"] 16 | -------------------------------------------------------------------------------- /tests/provider_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025, Pulumi Corporation. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package tests 16 | 17 | import ( 18 | "context" 19 | "testing" 20 | 21 | "github.com/blang/semver" 22 | "github.com/stretchr/testify/assert" 23 | "github.com/stretchr/testify/require" 24 | 25 | p "github.com/pulumi/pulumi-go-provider" 26 | "github.com/pulumi/pulumi-go-provider/integration" 27 | xyz "github.com/pulumi/pulumi-provider-boilerplate/provider" 28 | "github.com/pulumi/pulumi/sdk/v3/go/common/resource" 29 | "github.com/pulumi/pulumi/sdk/v3/go/common/tokens" 30 | "github.com/pulumi/pulumi/sdk/v3/go/property" 31 | ) 32 | 33 | func TestRandomCreate(t *testing.T) { 34 | t.Parallel() 35 | 36 | prov := provider(t) 37 | 38 | response, err := prov.Create(p.CreateRequest{ 39 | Urn: urn("Random"), 40 | Properties: property.NewMap(map[string]property.Value{ 41 | "length": property.New(12.0), 42 | }), 43 | 44 | DryRun: false, 45 | }) 46 | 47 | require.NoError(t, err) 48 | result := response.Properties.Get("result").AsString() 49 | assert.Len(t, result, 12) 50 | } 51 | 52 | // urn is a helper function to build an urn for running integration tests. 53 | func urn(typ string) resource.URN { 54 | return resource.NewURN("stack", "proj", "", 55 | tokens.Type("test:index:"+typ), "name") 56 | } 57 | 58 | // Create a test server. 59 | func provider(t *testing.T) integration.Server { 60 | s, err := integration.NewServer( 61 | context.Background(), 62 | xyz.Name, 63 | semver.MustParse("1.0.0"), 64 | integration.WithProvider(xyz.Provider()), 65 | ) 66 | require.NoError(t, err) 67 | return s 68 | } 69 | --------------------------------------------------------------------------------