Compare commits
205 Commits
v0.2.0-rc.
...
main
Author | SHA1 | Date |
---|---|---|
|
e1a38586f6 | |
|
4f7180476a | |
|
586f0d6b54 | |
|
8b411168d2 | |
|
74fa699b0d | |
|
26b1f2568f | |
|
a6c03955eb | |
|
8fbf07e1f4 | |
|
a7e859fac4 | |
|
8721ed90ef | |
|
83a5175821 | |
|
571c4de02c | |
|
d4dff7946e | |
|
40c36448af | |
|
835e05e66e | |
|
71c493bcb6 | |
|
de0dda93f2 | |
|
f07156c2af | |
|
9e27dd0eea | |
|
fee19e2923 | |
|
5812b1ff92 | |
|
78fb25a522 | |
|
3a547b7798 | |
|
54e0c4f181 | |
|
af4059f614 | |
|
1f1746c744 | |
|
dd9ce79c78 | |
|
9dfa270307 | |
|
a3172106bc | |
|
adcb5d1bd5 | |
|
a0af7ce2d3 | |
|
e05743d1ca | |
|
5232857570 | |
|
7c0ad5ca0d | |
|
1080e16a58 | |
|
4f304f8880 | |
|
d2d3c99f6a | |
|
643b04c154 | |
|
062a798612 | |
|
48d1d7122b | |
|
89c8a767f4 | |
|
dba741619e | |
|
379e387823 | |
|
bee1366370 | |
|
9746d24b28 | |
|
5d5b5ac7b2 | |
|
e754b6ae12 | |
|
25f3661217 | |
|
1dcaec2745 | |
|
afd99e0cac | |
|
04129ebff4 | |
|
fa9a1f7bef | |
|
a5b90fda43 | |
|
0778ebe6c2 | |
|
7f4b7bb02b | |
|
5f6b58ad6f | |
|
ffcc783470 | |
|
bb239e7414 | |
|
4f584b36c3 | |
|
62525fee4e | |
|
ba610c4046 | |
|
4e20b88589 | |
|
3a77b050fd | |
|
0c1d3f789d | |
|
718e949afc | |
|
8b561e6be9 | |
|
de2b81e1bf | |
|
51848c4954 | |
|
dd665ee0c5 | |
|
cacf5b0fc2 | |
|
025b0ed343 | |
|
bb5f0bf8e7 | |
|
b97d0d1ac8 | |
|
1f3ee551a0 | |
|
d926c4b1e3 | |
|
2da86c5eb7 | |
|
b93d62732e | |
|
b873ec6d39 | |
|
10a1673c55 | |
|
9dba1d6a8f | |
|
edc2ea5d94 | |
|
9dd860359b | |
|
f185cd50b0 | |
|
2fd1c1c08a | |
|
fca1a855bd | |
|
f6e46792b9 | |
|
29ea8ddbfa | |
|
e17bf50037 | |
|
e8472fd066 | |
|
bc16c87562 | |
|
9de531150e | |
|
54fac4d87a | |
|
c2fac0f7b2 | |
|
f3cde1bfc8 | |
|
18b5431c81 | |
|
3a3a3c9dfb | |
|
12c319db27 | |
|
0115992df2 | |
|
7617361f7c | |
|
f0438379ac | |
|
9ac517a330 | |
|
1eae883a6b | |
|
291859c053 | |
|
509422c9a8 | |
|
11b59ad469 | |
|
53155a2d18 | |
|
434972f741 | |
|
8ff4cae190 | |
|
aa077cf3b3 | |
|
909e6bdf70 | |
|
cd6ab94cf0 | |
|
4cc6150686 | |
|
33e7e0e0b5 | |
|
6a7cde65c1 | |
|
aab701c336 | |
|
0c09a205d2 | |
|
9c1dc0461c | |
|
29b53adcf3 | |
|
5d3a93965d | |
|
b53051e32d | |
|
e20ca684ad | |
|
0b5c83094b | |
|
97d0983aae | |
|
94f0334709 | |
|
c987192d28 | |
|
0068bd690f | |
|
9a5beef34b | |
|
f1c048d91f | |
|
1335c4bd9c | |
|
48e682947c | |
|
6dd74ecd93 | |
|
f466e52426 | |
|
f545dc2255 | |
|
d88396bf99 | |
|
d73e859f84 | |
|
9e73fdc8bf | |
|
bb797d14d3 | |
|
4d63c40df2 | |
|
757fdde079 | |
|
f160cb9635 | |
|
d63b09298f | |
|
20f09623ba | |
|
49253219f1 | |
|
c1d7d6dee1 | |
|
696c484e4d | |
|
41f7fef3a6 | |
|
f94e04b173 | |
|
e6d65267f6 | |
|
8927bb315f | |
|
e5e9384760 | |
|
49844f1037 | |
|
1c7fbb2b08 | |
|
3d7c2df08d | |
|
3eb944e994 | |
|
30996ac06d | |
|
b173b8ed8d | |
|
c9b5e1f164 | |
|
cbe6104357 | |
|
d0c5daebd0 | |
|
b8e69e80cc | |
|
2edc403676 | |
|
b5a6d8e196 | |
|
174f1494d7 | |
|
41ade7af31 | |
|
636de21142 | |
|
ea84f80fa9 | |
|
a98c2aaa9b | |
|
05d6daded6 | |
|
c3bf80d4b7 | |
|
29b7710c9e | |
|
fe9b3ca546 | |
|
6a3e69c846 | |
|
b722787a88 | |
|
4985e4bd75 | |
|
40d347df45 | |
|
170f02d47d | |
|
3ea079dc1c | |
|
552e9d0ffa | |
|
b873679e6b | |
|
5c50472ef3 | |
|
22b59a3330 | |
|
52ecaee8b8 | |
|
d7cb09d48a | |
|
093b84421f | |
|
247513f15e | |
|
5810cc03af | |
|
b307d0686b | |
|
cf8475bb06 | |
|
f5d4ad954b | |
|
419df59b88 | |
|
d9d3e432e3 | |
|
8525644969 | |
|
b1fb133c84 | |
|
e1d2e3015a | |
|
74c80baece | |
|
ab9baab1ea | |
|
14ef860742 | |
|
18b681d196 | |
|
56e6e4a503 | |
|
1757c1ca88 | |
|
4724d84157 | |
|
4c1750c14e | |
|
4a06f2deab | |
|
86c5e02850 | |
|
cecf53130b |
|
@ -18,16 +18,16 @@ jobs:
|
|||
# The main gotchas with this action are that it _only_ supports merge commits,
|
||||
# and that PRs _must_ be labelled before they're merged to trigger a backport.
|
||||
open-pr:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
if: github.event.pull_request.merged
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Open Backport PR
|
||||
uses: zeebe-io/backport-action@408fae11ed190c2f91bf15d15af01b8f8b45709b # v2.0.0
|
||||
uses: zeebe-io/backport-action@be567af183754f6a5d831ae90f648954763f17f5 # v3.1.0
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
github_workspace: ${{ github.workspace }}
|
||||
|
|
|
@ -10,21 +10,21 @@ on:
|
|||
|
||||
env:
|
||||
# Common versions
|
||||
GO_VERSION: '1.21.3'
|
||||
GOLANGCI_VERSION: 'v1.55.1'
|
||||
GO_VERSION: '1.23.4'
|
||||
GOLANGCI_VERSION: 'v1.61.0'
|
||||
|
||||
jobs:
|
||||
check-diff:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4
|
||||
uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
|
||||
|
@ -33,27 +33,27 @@ jobs:
|
|||
run: echo "::set-output name=cache::$(make go.cachedir)"
|
||||
|
||||
- name: Cache the Go Build Cache
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3
|
||||
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4
|
||||
with:
|
||||
path: ${{ steps.go.outputs.cache }}
|
||||
key: ${{ runner.os }}-build-check-diff-${{ hashFiles('**/go.sum') }}
|
||||
restore-keys: ${{ runner.os }}-build-check-diff-
|
||||
|
||||
- name: Cache Go Dependencies
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3
|
||||
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4
|
||||
with:
|
||||
path: .work/pkg
|
||||
key: ${{ runner.os }}-pkg-${{ hashFiles('**/go.sum') }}
|
||||
restore-keys: ${{ runner.os }}-pkg-
|
||||
|
||||
- name: Vendor Dependencies
|
||||
run: make vendor vendor.check
|
||||
- name: Download Go Modules
|
||||
run: make modules.download modules.check
|
||||
|
||||
- name: Check Diff
|
||||
run: make check-diff
|
||||
|
||||
detect-noop:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
outputs:
|
||||
noop: ${{ steps.noop.outputs.should_skip }}
|
||||
steps:
|
||||
|
@ -67,18 +67,18 @@ jobs:
|
|||
concurrent_skipping: false
|
||||
|
||||
lint:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
needs: detect-noop
|
||||
if: needs.detect-noop.outputs.noop != 'true'
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4
|
||||
uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
|
||||
|
@ -87,44 +87,44 @@ jobs:
|
|||
run: echo "::set-output name=cache::$(make go.cachedir)"
|
||||
|
||||
- name: Cache the Go Build Cache
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3
|
||||
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4
|
||||
with:
|
||||
path: ${{ steps.go.outputs.cache }}
|
||||
key: ${{ runner.os }}-build-lint-${{ hashFiles('**/go.sum') }}
|
||||
restore-keys: ${{ runner.os }}-build-lint-
|
||||
|
||||
- name: Cache Go Dependencies
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3
|
||||
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4
|
||||
with:
|
||||
path: .work/pkg
|
||||
key: ${{ runner.os }}-pkg-${{ hashFiles('**/go.sum') }}
|
||||
restore-keys: ${{ runner.os }}-pkg-
|
||||
|
||||
- name: Vendor Dependencies
|
||||
run: make vendor vendor.check
|
||||
- name: Download Go Modules
|
||||
run: make modules.download modules.check
|
||||
|
||||
# We could run 'make lint' to ensure our desired Go version, but we prefer
|
||||
# this action because it leaves 'annotations' (i.e. it comments on PRs to
|
||||
# point out linter violations).
|
||||
- name: Lint
|
||||
uses: golangci/golangci-lint-action@3a919529898de77ec3da873e3063ca4b10e7f5cc # v3
|
||||
uses: golangci/golangci-lint-action@aaa42aa0628b4ae2578232a66b541047968fac86 # v6
|
||||
with:
|
||||
version: ${{ env.GOLANGCI_VERSION }}
|
||||
skip-cache: true # We do our own caching.
|
||||
|
||||
codeql:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
needs: detect-noop
|
||||
if: needs.detect-noop.outputs.noop != 'true'
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4
|
||||
uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
|
||||
|
@ -133,42 +133,42 @@ jobs:
|
|||
run: echo "::set-output name=cache::$(make go.cachedir)"
|
||||
|
||||
- name: Cache the Go Build Cache
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3
|
||||
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4
|
||||
with:
|
||||
path: ${{ steps.go.outputs.cache }}
|
||||
key: ${{ runner.os }}-build-check-diff-${{ hashFiles('**/go.sum') }}
|
||||
restore-keys: ${{ runner.os }}-build-check-diff-
|
||||
|
||||
- name: Cache Go Dependencies
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3
|
||||
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4
|
||||
with:
|
||||
path: .work/pkg
|
||||
key: ${{ runner.os }}-pkg-${{ hashFiles('**/go.sum') }}
|
||||
restore-keys: ${{ runner.os }}-pkg-
|
||||
|
||||
- name: Vendor Dependencies
|
||||
run: make vendor vendor.check
|
||||
- name: Download Go Modules
|
||||
run: make modules.download modules.check
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@74483a38d39275f33fcff5f35b679b5ca4a26a99 # v2
|
||||
uses: github/codeql-action/init@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3
|
||||
with:
|
||||
languages: go
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@74483a38d39275f33fcff5f35b679b5ca4a26a99 # v2
|
||||
uses: github/codeql-action/analyze@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3
|
||||
|
||||
trivy-scan-fs:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
needs: detect-noop
|
||||
if: needs.detect-noop.outputs.noop != 'true'
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Run Trivy vulnerability scanner in fs mode
|
||||
uses: aquasecurity/trivy-action@f78e9ecf42a1271402d4f484518b9313235990e1 # 0.13.1
|
||||
uses: aquasecurity/trivy-action@6e7b7d1fd3e4fef0c5fa8cce1229c54b2c9bd0d8 # 0.24.0
|
||||
with:
|
||||
scan-type: 'fs'
|
||||
ignore-unfixed: true
|
||||
|
@ -178,13 +178,13 @@ jobs:
|
|||
severity: 'CRITICAL,HIGH'
|
||||
|
||||
unit-tests:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
needs: detect-noop
|
||||
if: needs.detect-noop.outputs.noop != 'true'
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
|
@ -192,7 +192,7 @@ jobs:
|
|||
run: git fetch --prune --unshallow
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4
|
||||
uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
|
||||
|
@ -201,27 +201,27 @@ jobs:
|
|||
run: echo "::set-output name=cache::$(make go.cachedir)"
|
||||
|
||||
- name: Cache the Go Build Cache
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3
|
||||
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4
|
||||
with:
|
||||
path: ${{ steps.go.outputs.cache }}
|
||||
key: ${{ runner.os }}-build-unit-tests-${{ hashFiles('**/go.sum') }}
|
||||
restore-keys: ${{ runner.os }}-build-unit-tests-
|
||||
|
||||
- name: Cache Go Dependencies
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3
|
||||
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4
|
||||
with:
|
||||
path: .work/pkg
|
||||
key: ${{ runner.os }}-pkg-${{ hashFiles('**/go.sum') }}
|
||||
restore-keys: ${{ runner.os }}-pkg-
|
||||
|
||||
- name: Vendor Dependencies
|
||||
run: make vendor vendor.check
|
||||
- name: Download Go Modules
|
||||
run: make modules.download modules.check
|
||||
|
||||
- name: Run Unit Tests
|
||||
run: make -j2 test
|
||||
|
||||
- name: Publish Unit Test Coverage
|
||||
uses: codecov/codecov-action@c4cf8a4f03f0ac8585acb7c1b7ce3460ec15782f # v4
|
||||
uses: codecov/codecov-action@b9fd7d16f6d7d1b5d2bec1a2887e65ceed900238 # v4
|
||||
with:
|
||||
flags: unittests
|
||||
file: _output/tests/linux_amd64/coverage.txt
|
||||
|
|
|
@ -4,7 +4,7 @@ on: issue_comment
|
|||
|
||||
jobs:
|
||||
points:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
if: startsWith(github.event.comment.body, '/points')
|
||||
|
||||
steps:
|
||||
|
@ -19,7 +19,7 @@ jobs:
|
|||
allow-edits: "false"
|
||||
permission-level: write
|
||||
- name: Handle Command
|
||||
uses: actions/github-script@d7906e4ad0b1822421a7e6a35d5ca353c962f410 # v6
|
||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7
|
||||
env:
|
||||
POINTS: ${{ steps.command.outputs.command-arguments }}
|
||||
with:
|
||||
|
@ -65,7 +65,7 @@ jobs:
|
|||
# NOTE(negz): See also backport.yml, which is the variant that triggers on PR
|
||||
# merge rather than on comment.
|
||||
backport:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
if: github.event.issue.pull_request && startsWith(github.event.comment.body, '/backport')
|
||||
steps:
|
||||
- name: Extract Command
|
||||
|
@ -80,12 +80,12 @@ jobs:
|
|||
permission-level: write
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Open Backport PR
|
||||
uses: zeebe-io/backport-action@408fae11ed190c2f91bf15d15af01b8f8b45709b # v2.0.0
|
||||
uses: zeebe-io/backport-action@be567af183754f6a5d831ae90f648954763f17f5 # v3.1.0
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
github_workspace: ${{ github.workspace }}
|
||||
|
|
|
@ -20,11 +20,11 @@ env:
|
|||
|
||||
jobs:
|
||||
promote-artifacts:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
|
@ -32,7 +32,7 @@ jobs:
|
|||
run: git fetch --prune --unshallow
|
||||
|
||||
- name: Login to Docker
|
||||
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3
|
||||
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3
|
||||
if: env.DOCKER_USR != ''
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USR }}
|
||||
|
|
|
@ -12,11 +12,11 @@ on:
|
|||
|
||||
jobs:
|
||||
create-tag:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
|
||||
- name: Create Tag
|
||||
uses: negz/create-tag@39bae1e0932567a58c20dea5a1a0d18358503320 # v1
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
[submodule "build"]
|
||||
path = build
|
||||
url = https://github.com/upbound/build
|
||||
url = https://github.com/crossplane/build
|
||||
|
|
4
Makefile
4
Makefile
|
@ -24,9 +24,9 @@ NPROCS ?= 1
|
|||
GO_TEST_PARALLEL := $(shell echo $$(( $(NPROCS) / 2 )))
|
||||
|
||||
GO_LDFLAGS += -X $(GO_PROJECT)/pkg/version.Version=$(VERSION)
|
||||
GO_SUBDIRS += proto
|
||||
GO_SUBDIRS += errors proto resource response request
|
||||
GO111MODULE = on
|
||||
GOLANGCILINT_VERSION = 1.55.1
|
||||
GOLANGCILINT_VERSION = 1.61.0
|
||||
GO_LINT_ARGS ?= "--fix"
|
||||
-include build/makelib/golang.mk
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# function-sdk-go
|
||||
[](https://github.com/crossplane/function-sdk-go/actions/workflows/ci.yml)  [](https://pkg.go.dev/github.com/crossplane/function-sdk-go)
|
||||
[](https://github.com/crossplane/function-sdk-go/actions/workflows/ci.yml)  [](https://pkg.go.dev/github.com/crossplane/function-sdk-go)
|
||||
|
||||
The [Go][go] SDK for writing [composition functions][functions].
|
||||
|
||||
|
|
2
build
2
build
|
@ -1 +1 @@
|
|||
Subproject commit a6e25afa0d43da62b11af96a5d29627a52f32cd9
|
||||
Subproject commit 231258db281237379d8ec0c6e4af9d7c1ae5cc4a
|
|
@ -117,7 +117,6 @@ func Cause(err error) error {
|
|||
}
|
||||
|
||||
for err != nil {
|
||||
//nolint:errorlint // We actually do want to check the outermost error.
|
||||
w, ok := err.(wrapped)
|
||||
if !ok {
|
||||
return err
|
||||
|
|
228
go.mod
228
go.mod
|
@ -1,155 +1,201 @@
|
|||
module github.com/crossplane/function-sdk-go
|
||||
|
||||
go 1.21
|
||||
go 1.23.0
|
||||
|
||||
toolchain go1.23.2
|
||||
|
||||
require (
|
||||
github.com/bufbuild/buf v1.27.2
|
||||
github.com/crossplane/crossplane-runtime v1.14.0
|
||||
github.com/go-json-experiment/json v0.0.0-20231013223334-54c864be5b8d
|
||||
github.com/go-logr/logr v1.3.0
|
||||
github.com/go-logr/zapr v1.2.4
|
||||
github.com/bufbuild/buf v1.42.0
|
||||
github.com/crossplane/crossplane-runtime v1.18.0
|
||||
github.com/go-json-experiment/json v0.0.0-20240815175050-ebd3a8989ca1
|
||||
github.com/go-logr/logr v1.4.2
|
||||
github.com/go-logr/zapr v1.3.0
|
||||
github.com/google/go-cmp v0.6.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/upbound/provider-aws v0.43.0
|
||||
go.uber.org/zap v1.26.0
|
||||
google.golang.org/grpc v1.59.0
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0
|
||||
google.golang.org/protobuf v1.31.0
|
||||
k8s.io/api v0.28.3
|
||||
k8s.io/apimachinery v0.28.3
|
||||
k8s.io/utils v0.0.0-20230726121419-3b25d923346b
|
||||
github.com/upbound/provider-aws v1.14.0
|
||||
go.uber.org/zap v1.27.0
|
||||
google.golang.org/grpc v1.67.0
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1
|
||||
google.golang.org/protobuf v1.34.3-0.20240816073751-94ecbc261689
|
||||
k8s.io/api v0.31.0
|
||||
k8s.io/apimachinery v0.31.0
|
||||
k8s.io/utils v0.0.0-20240902221715-702e33fdd3c3
|
||||
sigs.k8s.io/yaml v1.4.0
|
||||
)
|
||||
|
||||
require (
|
||||
connectrpc.com/connect v1.11.1 // indirect
|
||||
connectrpc.com/otelconnect v0.6.0 // indirect
|
||||
dario.cat/mergo v1.0.0 // indirect
|
||||
buf.build/gen/go/bufbuild/bufplugin/protocolbuffers/go v1.34.2-20240904181154-a0be11449112.2 // indirect
|
||||
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.34.2-20240717164558-a6c49f84cc0f.2 // indirect
|
||||
buf.build/gen/go/bufbuild/registry/connectrpc/go v1.16.2-20240821192916-45ba72cdd479.1 // indirect
|
||||
buf.build/gen/go/bufbuild/registry/protocolbuffers/go v1.34.2-20240821192916-45ba72cdd479.2 // indirect
|
||||
buf.build/gen/go/pluginrpc/pluginrpc/protocolbuffers/go v1.34.2-20240828222655-5345c0a56177.2 // indirect
|
||||
buf.build/go/bufplugin v0.2.0 // indirect
|
||||
buf.build/go/protoyaml v0.2.0 // indirect
|
||||
connectrpc.com/connect v1.16.2 // indirect
|
||||
connectrpc.com/otelconnect v0.7.1 // indirect
|
||||
dario.cat/mergo v1.0.1 // indirect
|
||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.1 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||
github.com/Microsoft/hcsshim v0.12.6 // indirect
|
||||
github.com/agext/levenshtein v1.2.3 // indirect
|
||||
github.com/antchfx/htmlquery v1.2.4 // indirect
|
||||
github.com/antchfx/xpath v1.2.0 // indirect
|
||||
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
|
||||
github.com/antlr4-go/antlr/v4 v4.13.1 // indirect
|
||||
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bufbuild/protocompile v0.6.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect
|
||||
github.com/crossplane/upjet v0.11.0-rc.0.0.20231012093706-c4a76d2a7505 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/distribution/reference v0.5.0 // indirect
|
||||
github.com/docker/cli v24.0.6+incompatible // indirect
|
||||
github.com/blang/semver/v4 v4.0.0 // indirect
|
||||
github.com/bufbuild/protocompile v0.14.1 // indirect
|
||||
github.com/bufbuild/protoplugin v0.0.0-20240911180120-7bb73e41a54a // indirect
|
||||
github.com/bufbuild/protovalidate-go v0.6.5 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/containerd/cgroups/v3 v3.0.3 // indirect
|
||||
github.com/containerd/containerd v1.7.22 // indirect
|
||||
github.com/containerd/continuity v0.4.3 // indirect
|
||||
github.com/containerd/errdefs v0.2.0 // indirect
|
||||
github.com/containerd/log v0.1.0 // indirect
|
||||
github.com/containerd/platforms v0.2.1 // indirect
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.15.1 // indirect
|
||||
github.com/containerd/ttrpc v1.2.5 // indirect
|
||||
github.com/containerd/typeurl/v2 v2.2.0 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
|
||||
github.com/crossplane/upjet v1.4.1-0.20240911184956-3afbb7796d46 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/distribution/reference v0.6.0 // indirect
|
||||
github.com/docker/cli v27.2.1+incompatible // indirect
|
||||
github.com/docker/distribution v2.8.3+incompatible // indirect
|
||||
github.com/docker/docker v24.0.7+incompatible // indirect
|
||||
github.com/docker/docker-credential-helpers v0.8.0 // indirect
|
||||
github.com/docker/go-connections v0.4.0 // indirect
|
||||
github.com/docker/docker v27.2.1+incompatible // indirect
|
||||
github.com/docker/docker-credential-helpers v0.8.2 // indirect
|
||||
github.com/docker/go-connections v0.5.0 // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
|
||||
github.com/evanphx/json-patch/v5 v5.6.0 // indirect
|
||||
github.com/evanphx/json-patch v5.9.0+incompatible // indirect
|
||||
github.com/evanphx/json-patch/v5 v5.9.0 // indirect
|
||||
github.com/fatih/camelcase v1.0.0 // indirect
|
||||
github.com/fatih/color v1.15.0 // indirect
|
||||
github.com/felixge/fgprof v0.9.3 // indirect
|
||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||
github.com/go-chi/chi/v5 v5.0.10 // indirect
|
||||
github.com/fatih/color v1.17.0 // indirect
|
||||
github.com/felixge/fgprof v0.9.5 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
|
||||
github.com/go-chi/chi/v5 v5.1.0 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.6 // indirect
|
||||
github.com/go-openapi/jsonreference v0.20.2 // indirect
|
||||
github.com/go-openapi/swag v0.22.3 // indirect
|
||||
github.com/gofrs/uuid/v5 v5.0.0 // indirect
|
||||
github.com/go-openapi/swag v0.22.4 // indirect
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
|
||||
github.com/gobuffalo/flect v1.0.2 // indirect
|
||||
github.com/gofrs/flock v0.12.1 // indirect
|
||||
github.com/gofrs/uuid/v5 v5.3.0 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/google/cel-go v0.21.0 // indirect
|
||||
github.com/google/gnostic-models v0.6.8 // indirect
|
||||
github.com/google/go-containerregistry v0.16.1 // indirect
|
||||
github.com/google/go-containerregistry v0.20.2 // indirect
|
||||
github.com/google/gofuzz v1.2.0 // indirect
|
||||
github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98 // indirect
|
||||
github.com/google/uuid v1.3.1 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 // indirect
|
||||
github.com/hashicorp/go-hclog v1.2.1 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/google/pprof v0.0.0-20240910150728-a0b0bb1d4134 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/hashicorp/go-cty v1.4.1-0.20200723130312-85980079f637 // indirect
|
||||
github.com/hashicorp/go-hclog v1.6.3 // indirect
|
||||
github.com/hashicorp/go-uuid v1.0.3 // indirect
|
||||
github.com/hashicorp/go-version v1.6.0 // indirect
|
||||
github.com/hashicorp/hcl/v2 v2.14.1 // indirect
|
||||
github.com/hashicorp/go-version v1.7.0 // indirect
|
||||
github.com/hashicorp/hcl/v2 v2.21.0 // indirect
|
||||
github.com/hashicorp/logutils v1.0.0 // indirect
|
||||
github.com/hashicorp/terraform-json v0.14.0 // indirect
|
||||
github.com/hashicorp/terraform-plugin-go v0.14.0 // indirect
|
||||
github.com/hashicorp/terraform-plugin-log v0.7.0 // indirect
|
||||
github.com/hashicorp/terraform-plugin-sdk/v2 v2.24.0 // indirect
|
||||
github.com/hashicorp/terraform-json v0.22.1 // indirect
|
||||
github.com/hashicorp/terraform-plugin-framework v1.10.0 // indirect
|
||||
github.com/hashicorp/terraform-plugin-go v0.23.0 // indirect
|
||||
github.com/hashicorp/terraform-plugin-log v0.9.0 // indirect
|
||||
github.com/hashicorp/terraform-plugin-sdk/v2 v2.34.0 // indirect
|
||||
github.com/iancoleman/strcase v0.2.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jdx/go-netrc v1.0.0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/compress v1.17.2 // indirect
|
||||
github.com/klauspost/compress v1.17.9 // indirect
|
||||
github.com/klauspost/pgzip v1.2.6 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.17 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
|
||||
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/moby/docker-image-spec v1.3.1 // indirect
|
||||
github.com/moby/locker v1.0.1 // indirect
|
||||
github.com/moby/patternmatcher v0.6.0 // indirect
|
||||
github.com/moby/sys/mount v0.3.4 // indirect
|
||||
github.com/moby/sys/mountinfo v0.7.2 // indirect
|
||||
github.com/moby/sys/sequential v0.6.0 // indirect
|
||||
github.com/moby/sys/user v0.3.0 // indirect
|
||||
github.com/moby/sys/userns v0.1.0 // indirect
|
||||
github.com/moby/term v0.5.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/morikuni/aec v1.0.0 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.20.2 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.0-rc5 // indirect
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.0 // indirect
|
||||
github.com/opencontainers/runtime-spec v1.2.0 // indirect
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
|
||||
github.com/pkg/profile v1.7.0 // indirect
|
||||
github.com/prometheus/client_golang v1.16.0 // indirect
|
||||
github.com/prometheus/client_model v0.4.0 // indirect
|
||||
github.com/prometheus/common v0.44.0 // indirect
|
||||
github.com/prometheus/procfs v0.10.1 // indirect
|
||||
github.com/rogpeppe/go-internal v1.11.0 // indirect
|
||||
github.com/rs/cors v1.10.1 // indirect
|
||||
github.com/prometheus/client_golang v1.19.1 // indirect
|
||||
github.com/prometheus/client_model v0.6.1 // indirect
|
||||
github.com/prometheus/common v0.55.0 // indirect
|
||||
github.com/prometheus/procfs v0.15.1 // indirect
|
||||
github.com/quic-go/qpack v0.5.1 // indirect
|
||||
github.com/quic-go/quic-go v0.48.2 // indirect
|
||||
github.com/rs/cors v1.11.1 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/spf13/afero v1.10.0 // indirect
|
||||
github.com/spf13/cobra v1.7.0 // indirect
|
||||
github.com/spf13/afero v1.11.0 // indirect
|
||||
github.com/spf13/cobra v1.8.1 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/tetratelabs/wazero v1.5.0 // indirect
|
||||
github.com/stoewer/go-strcase v1.3.0 // indirect
|
||||
github.com/tmccombs/hcl2json v0.3.3 // indirect
|
||||
github.com/vbatts/tar-split v0.11.5 // indirect
|
||||
github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect
|
||||
github.com/vmihailenco/msgpack/v4 v4.3.12 // indirect
|
||||
github.com/vmihailenco/tagparser v0.1.1 // indirect
|
||||
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
github.com/yuin/goldmark v1.4.13 // indirect
|
||||
github.com/zclconf/go-cty v1.11.0 // indirect
|
||||
go.opentelemetry.io/otel v1.19.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.19.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.19.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.19.0 // indirect
|
||||
github.com/zclconf/go-cty v1.14.4 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0 // indirect
|
||||
go.opentelemetry.io/otel v1.30.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.30.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.30.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.30.0 // indirect
|
||||
go.uber.org/atomic v1.11.0 // indirect
|
||||
go.uber.org/mock v0.4.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/crypto v0.14.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
|
||||
golang.org/x/mod v0.13.0 // indirect
|
||||
golang.org/x/net v0.17.0 // indirect
|
||||
golang.org/x/oauth2 v0.11.0 // indirect
|
||||
golang.org/x/sync v0.4.0 // indirect
|
||||
golang.org/x/sys v0.13.0 // indirect
|
||||
golang.org/x/term v0.13.0 // indirect
|
||||
golang.org/x/text v0.13.0 // indirect
|
||||
golang.org/x/time v0.3.0 // indirect
|
||||
golang.org/x/tools v0.14.0 // indirect
|
||||
golang.org/x/crypto v0.35.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect
|
||||
golang.org/x/mod v0.21.0 // indirect
|
||||
golang.org/x/net v0.33.0 // indirect
|
||||
golang.org/x/oauth2 v0.22.0 // indirect
|
||||
golang.org/x/sync v0.11.0 // indirect
|
||||
golang.org/x/sys v0.30.0 // indirect
|
||||
golang.org/x/term v0.29.0 // indirect
|
||||
golang.org/x/text v0.22.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
golang.org/x/tools v0.25.0 // indirect
|
||||
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect
|
||||
google.golang.org/appengine v1.6.8 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
k8s.io/client-go v0.28.3 // indirect
|
||||
k8s.io/component-base v0.28.3 // indirect
|
||||
k8s.io/klog/v2 v2.100.1 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect
|
||||
sigs.k8s.io/controller-runtime v0.16.3 // indirect
|
||||
k8s.io/apiextensions-apiserver v0.31.0 // indirect
|
||||
k8s.io/client-go v0.31.0 // indirect
|
||||
k8s.io/component-base v0.31.0 // indirect
|
||||
k8s.io/klog/v2 v2.130.1 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect
|
||||
pluginrpc.com/pluginrpc v0.3.0 // indirect
|
||||
sigs.k8s.io/controller-runtime v0.19.0 // indirect
|
||||
sigs.k8s.io/controller-tools v0.16.0 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
|
||||
)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,335 @@
|
|||
/*
|
||||
Copyright 2022 The Crossplane Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
//buf:lint:ignore PACKAGE_DIRECTORY_MATCH // Too late to fix this now.
|
||||
package apiextensions.fn.proto.v1;
|
||||
|
||||
import "google/protobuf/duration.proto";
|
||||
import "google/protobuf/struct.proto";
|
||||
|
||||
option go_package = "github.com/crossplane/crossplane/apis/apiextensions/fn/proto/v1";
|
||||
|
||||
// A FunctionRunnerService is a Composition Function.
|
||||
service FunctionRunnerService {
|
||||
// RunFunction runs the Composition Function.
|
||||
rpc RunFunction(RunFunctionRequest) returns (RunFunctionResponse) {}
|
||||
}
|
||||
|
||||
// A RunFunctionRequest requests that the Composition Function be run.
|
||||
message RunFunctionRequest {
|
||||
// Metadata pertaining to this request.
|
||||
RequestMeta meta = 1;
|
||||
|
||||
// The observed state prior to invocation of a Function pipeline. State passed
|
||||
// to each Function is fresh as of the time the pipeline was invoked, not as
|
||||
// of the time each Function was invoked.
|
||||
State observed = 2;
|
||||
|
||||
// Desired state according to a Function pipeline. The state passed to a
|
||||
// particular Function may have been accumulated by previous Functions in the
|
||||
// pipeline.
|
||||
//
|
||||
// Note that the desired state must be a partial object with only the fields
|
||||
// that this function (and its predecessors in the pipeline) wants to have
|
||||
// set in the object. Copying a non-partial observed state to desired is most
|
||||
// likely not what you want to do. Leaving out fields that had been returned
|
||||
// as desired before will result in them being deleted from the objects in the
|
||||
// cluster.
|
||||
State desired = 3;
|
||||
|
||||
// Optional input specific to this Function invocation. A JSON representation
|
||||
// of the 'input' block of the relevant entry in a Composition's pipeline.
|
||||
optional google.protobuf.Struct input = 4;
|
||||
|
||||
// Optional context. Crossplane may pass arbitrary contextual information to a
|
||||
// Function. A Function may also return context in its RunFunctionResponse,
|
||||
// and that context will be passed to subsequent Functions. Crossplane
|
||||
// discards all context returned by the last Function in the pipeline.
|
||||
optional google.protobuf.Struct context = 5;
|
||||
|
||||
// Optional extra resources that the Function required.
|
||||
// Note that extra resources is a map to Resources, plural.
|
||||
// The map key corresponds to the key in a RunFunctionResponse's
|
||||
// extra_resources field. If a Function requested extra resources that
|
||||
// did not exist, Crossplane sets the map key to an empty Resources message to
|
||||
// indicate that it attempted to satisfy the request.
|
||||
map<string, Resources> extra_resources = 6;
|
||||
|
||||
// Optional credentials that this Function may use to communicate with an
|
||||
// external system.
|
||||
map<string, Credentials> credentials = 7;
|
||||
}
|
||||
|
||||
// Credentials that a Function may use to communicate with an external system.
|
||||
message Credentials {
|
||||
// Source of the credentials.
|
||||
oneof source {
|
||||
// Credential data loaded by Crossplane, for example from a Secret.
|
||||
CredentialData credential_data = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// CredentialData loaded by Crossplane, for example from a Secret.
|
||||
message CredentialData {
|
||||
map<string, bytes> data = 1;
|
||||
}
|
||||
|
||||
// Resources represents the state of several Crossplane resources.
|
||||
message Resources {
|
||||
repeated Resource items = 1;
|
||||
}
|
||||
|
||||
// A RunFunctionResponse contains the result of a Composition Function run.
|
||||
message RunFunctionResponse {
|
||||
// Metadata pertaining to this response.
|
||||
ResponseMeta meta = 1;
|
||||
|
||||
// Desired state according to a Function pipeline. Functions may add desired
|
||||
// state, and may mutate or delete any part of the desired state they are
|
||||
// concerned with. A Function must pass through any part of the desired state
|
||||
// that it is not concerned with.
|
||||
//
|
||||
//
|
||||
// Note that the desired state must be a partial object with only the fields
|
||||
// that this function (and its predecessors in the pipeline) wants to have
|
||||
// set in the object. Copying a non-partial observed state to desired is most
|
||||
// likely not what you want to do. Leaving out fields that had been returned
|
||||
// as desired before will result in them being deleted from the objects in the
|
||||
// cluster.
|
||||
State desired = 2;
|
||||
|
||||
// Results of the Function run. Results are used for observability purposes.
|
||||
repeated Result results = 3;
|
||||
|
||||
// Optional context to be passed to the next Function in the pipeline as part
|
||||
// of the RunFunctionRequest. Dropped on the last function in the pipeline.
|
||||
optional google.protobuf.Struct context = 4;
|
||||
|
||||
// Requirements that must be satisfied for this Function to run successfully.
|
||||
Requirements requirements = 5;
|
||||
|
||||
// Status conditions to be applied to the composite resource. Conditions may also
|
||||
// optionally be applied to the composite resource's associated claim.
|
||||
repeated Condition conditions = 6;
|
||||
}
|
||||
|
||||
// RequestMeta contains metadata pertaining to a RunFunctionRequest.
|
||||
message RequestMeta {
|
||||
// An opaque string identifying a request. Requests with identical tags will
|
||||
// be otherwise identical.
|
||||
string tag = 1;
|
||||
}
|
||||
|
||||
// Requirements that must be satisfied for a Function to run successfully.
|
||||
message Requirements {
|
||||
// Extra resources that this Function requires.
|
||||
// The map key uniquely identifies the group of resources.
|
||||
map<string, ResourceSelector> extra_resources = 1;
|
||||
}
|
||||
|
||||
// ResourceSelector selects a group of resources, either by name or by label.
|
||||
message ResourceSelector {
|
||||
// API version of resources to select.
|
||||
string api_version = 1;
|
||||
|
||||
// Kind of resources to select.
|
||||
string kind = 2;
|
||||
|
||||
// Resources to match.
|
||||
oneof match {
|
||||
// Match the resource with this name.
|
||||
string match_name = 3;
|
||||
|
||||
// Match all resources with these labels.
|
||||
MatchLabels match_labels = 4;
|
||||
}
|
||||
|
||||
// Match resources in this namespace.
|
||||
// Omit namespace to match cluster scoped resources, or to match namespaced
|
||||
// resources by labels across all namespaces.
|
||||
optional string namespace = 5;
|
||||
}
|
||||
|
||||
// MatchLabels defines a set of labels to match resources against.
|
||||
message MatchLabels {
|
||||
map<string, string> labels = 1;
|
||||
}
|
||||
|
||||
// ResponseMeta contains metadata pertaining to a RunFunctionResponse.
|
||||
message ResponseMeta {
|
||||
// An opaque string identifying the content of the request. Must match the
|
||||
// meta.tag of the corresponding RunFunctionRequest.
|
||||
string tag = 1;
|
||||
|
||||
// Time-to-live of this response. Crossplane will call the function again when
|
||||
// the TTL expires. Crossplane may cache the response to avoid calling the
|
||||
// function again until the TTL expires.
|
||||
optional google.protobuf.Duration ttl = 2;
|
||||
}
|
||||
|
||||
// State of the composite resource (XR) and any composed resources.
|
||||
message State {
|
||||
// The state of the composite resource (XR).
|
||||
Resource composite = 1;
|
||||
|
||||
// The state of any composed resources.
|
||||
map<string, Resource> resources = 2;
|
||||
}
|
||||
|
||||
// A Resource represents the state of a composite or composed resource.
|
||||
message Resource {
|
||||
// The JSON representation of the resource.
|
||||
//
|
||||
// * Crossplane will set this field in a RunFunctionRequest to the entire
|
||||
// observed state of a resource - including its metadata, spec, and status.
|
||||
//
|
||||
// * A Function should set this field in a RunFunctionRequest to communicate
|
||||
// the desired state of a composite or composed resource.
|
||||
//
|
||||
// * A Function may only specify the desired status of a composite resource -
|
||||
// not its metadata or spec. A Function should not return desired metadata
|
||||
// or spec for a composite resource. This will be ignored.
|
||||
//
|
||||
// * A Function may not specify the desired status of a composed resource -
|
||||
// only its metadata and spec. A Function should not return desired status
|
||||
// for a composed resource. This will be ignored.
|
||||
google.protobuf.Struct resource = 1;
|
||||
|
||||
// The resource's connection details.
|
||||
//
|
||||
// * Crossplane will set this field in a RunFunctionRequest to communicate the
|
||||
// the observed connection details of a composite or composed resource.
|
||||
//
|
||||
// * A Function should set this field in a RunFunctionResponse to indicate the
|
||||
// desired connection details of the composite resource.
|
||||
//
|
||||
// * A Function should not set this field in a RunFunctionResponse to indicate
|
||||
// the desired connection details of a composed resource. This will be
|
||||
// ignored.
|
||||
map<string, bytes> connection_details = 2;
|
||||
|
||||
// Ready indicates whether the resource should be considered ready.
|
||||
//
|
||||
// * Crossplane will never set this field in a RunFunctionRequest.
|
||||
//
|
||||
// * A Function should set this field to READY_TRUE in a RunFunctionResponse
|
||||
// to indicate that a desired composed resource is ready.
|
||||
//
|
||||
// * A Function should set this field to READY_TRUE in a RunFunctionResponse
|
||||
// to indicate that a desired composite resource is ready.
|
||||
// This overwrites the standard readiness detection that determines the
|
||||
// ready state of the composite by the ready state of the the
|
||||
// composed resources.
|
||||
Ready ready = 3;
|
||||
}
|
||||
|
||||
// Ready indicates whether a composed resource should be considered ready.
|
||||
enum Ready {
|
||||
READY_UNSPECIFIED = 0;
|
||||
|
||||
// True means the composed resource has been observed to be ready.
|
||||
READY_TRUE = 1;
|
||||
|
||||
// False means the composed resource has not been observed to be ready.
|
||||
READY_FALSE = 2;
|
||||
}
|
||||
|
||||
// A Result of running a Function.
|
||||
message Result {
|
||||
// Severity of this result.
|
||||
Severity severity = 1;
|
||||
|
||||
// Human-readable details about the result.
|
||||
string message = 2;
|
||||
|
||||
// Optional PascalCase, machine-readable reason for this result. If omitted,
|
||||
// the value will be ComposeResources.
|
||||
optional string reason = 3;
|
||||
|
||||
// The resources this result targets.
|
||||
optional Target target = 4;
|
||||
}
|
||||
|
||||
// Severity of Function results.
|
||||
enum Severity {
|
||||
SEVERITY_UNSPECIFIED = 0;
|
||||
|
||||
// Fatal results are fatal; subsequent Composition Functions may run, but
|
||||
// the Composition Function pipeline run will be considered a failure and
|
||||
// the first fatal result will be returned as an error.
|
||||
SEVERITY_FATAL = 1;
|
||||
|
||||
// Warning results are non-fatal; the entire Composition will run to
|
||||
// completion but warning events and debug logs associated with the
|
||||
// composite resource will be emitted.
|
||||
SEVERITY_WARNING = 2;
|
||||
|
||||
// Normal results are emitted as normal events and debug logs associated
|
||||
// with the composite resource.
|
||||
SEVERITY_NORMAL = 3;
|
||||
}
|
||||
|
||||
// Target of Function results and conditions.
|
||||
enum Target {
|
||||
// If the target is unspecified, the result targets the composite resource.
|
||||
TARGET_UNSPECIFIED = 0;
|
||||
|
||||
// Target the composite resource. Results that target the composite resource
|
||||
// should include detailed, advanced information.
|
||||
TARGET_COMPOSITE = 1;
|
||||
|
||||
// Target the composite and the claim. Results that target the composite and
|
||||
// the claim should include only end-user friendly information.
|
||||
TARGET_COMPOSITE_AND_CLAIM = 2;
|
||||
}
|
||||
|
||||
// Status condition to be applied to the composite resource. Condition may also
|
||||
// optionally be applied to the composite resource's associated claim. For
|
||||
// detailed information on proper usage of status conditions, please see
|
||||
// https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties.
|
||||
message Condition {
|
||||
// Type of condition in PascalCase.
|
||||
string type = 1;
|
||||
|
||||
// Status of the condition.
|
||||
Status status = 2;
|
||||
|
||||
// Reason contains a programmatic identifier indicating the reason for the
|
||||
// condition's last transition. Producers of specific condition types may
|
||||
// define expected values and meanings for this field, and whether the values
|
||||
// are considered a guaranteed API. The value should be a PascalCase string.
|
||||
// This field may not be empty.
|
||||
string reason = 3;
|
||||
|
||||
// Message is a human readable message indicating details about the
|
||||
// transition. This may be an empty string.
|
||||
optional string message = 4;
|
||||
|
||||
// The resources this condition targets.
|
||||
optional Target target = 5;
|
||||
}
|
||||
|
||||
enum Status {
|
||||
STATUS_CONDITION_UNSPECIFIED = 0;
|
||||
|
||||
STATUS_CONDITION_UNKNOWN = 1;
|
||||
|
||||
STATUS_CONDITION_TRUE = 2;
|
||||
|
||||
STATUS_CONDITION_FALSE = 3;
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
//
|
||||
//Copyright 2022 The Crossplane Authors.
|
||||
//
|
||||
//Licensed under the Apache License, Version 2.0 (the "License");
|
||||
//you may not use this file except in compliance with the License.
|
||||
//You may obtain a copy of the License at
|
||||
//
|
||||
//http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
//Unless required by applicable law or agreed to in writing, software
|
||||
//distributed under the License is distributed on an "AS IS" BASIS,
|
||||
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//See the License for the specific language governing permissions and
|
||||
//limitations under the License.
|
||||
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.5.1
|
||||
// - protoc (unknown)
|
||||
// source: v1/run_function.proto
|
||||
|
||||
//buf:lint:ignore PACKAGE_DIRECTORY_MATCH // Too late to fix this now.
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
context "context"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.64.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion9
|
||||
|
||||
const (
|
||||
FunctionRunnerService_RunFunction_FullMethodName = "/apiextensions.fn.proto.v1.FunctionRunnerService/RunFunction"
|
||||
)
|
||||
|
||||
// FunctionRunnerServiceClient is the client API for FunctionRunnerService service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
//
|
||||
// A FunctionRunnerService is a Composition Function.
|
||||
type FunctionRunnerServiceClient interface {
|
||||
// RunFunction runs the Composition Function.
|
||||
RunFunction(ctx context.Context, in *RunFunctionRequest, opts ...grpc.CallOption) (*RunFunctionResponse, error)
|
||||
}
|
||||
|
||||
type functionRunnerServiceClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewFunctionRunnerServiceClient(cc grpc.ClientConnInterface) FunctionRunnerServiceClient {
|
||||
return &functionRunnerServiceClient{cc}
|
||||
}
|
||||
|
||||
func (c *functionRunnerServiceClient) RunFunction(ctx context.Context, in *RunFunctionRequest, opts ...grpc.CallOption) (*RunFunctionResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(RunFunctionResponse)
|
||||
err := c.cc.Invoke(ctx, FunctionRunnerService_RunFunction_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// FunctionRunnerServiceServer is the server API for FunctionRunnerService service.
|
||||
// All implementations must embed UnimplementedFunctionRunnerServiceServer
|
||||
// for forward compatibility.
|
||||
//
|
||||
// A FunctionRunnerService is a Composition Function.
|
||||
type FunctionRunnerServiceServer interface {
|
||||
// RunFunction runs the Composition Function.
|
||||
RunFunction(context.Context, *RunFunctionRequest) (*RunFunctionResponse, error)
|
||||
mustEmbedUnimplementedFunctionRunnerServiceServer()
|
||||
}
|
||||
|
||||
// UnimplementedFunctionRunnerServiceServer must be embedded to have
|
||||
// forward compatible implementations.
|
||||
//
|
||||
// NOTE: this should be embedded by value instead of pointer to avoid a nil
|
||||
// pointer dereference when methods are called.
|
||||
type UnimplementedFunctionRunnerServiceServer struct{}
|
||||
|
||||
func (UnimplementedFunctionRunnerServiceServer) RunFunction(context.Context, *RunFunctionRequest) (*RunFunctionResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method RunFunction not implemented")
|
||||
}
|
||||
func (UnimplementedFunctionRunnerServiceServer) mustEmbedUnimplementedFunctionRunnerServiceServer() {}
|
||||
func (UnimplementedFunctionRunnerServiceServer) testEmbeddedByValue() {}
|
||||
|
||||
// UnsafeFunctionRunnerServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to FunctionRunnerServiceServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeFunctionRunnerServiceServer interface {
|
||||
mustEmbedUnimplementedFunctionRunnerServiceServer()
|
||||
}
|
||||
|
||||
func RegisterFunctionRunnerServiceServer(s grpc.ServiceRegistrar, srv FunctionRunnerServiceServer) {
|
||||
// If the following call pancis, it indicates UnimplementedFunctionRunnerServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
|
||||
t.testEmbeddedByValue()
|
||||
}
|
||||
s.RegisterService(&FunctionRunnerService_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _FunctionRunnerService_RunFunction_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(RunFunctionRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(FunctionRunnerServiceServer).RunFunction(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: FunctionRunnerService_RunFunction_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(FunctionRunnerServiceServer).RunFunction(ctx, req.(*RunFunctionRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// FunctionRunnerService_ServiceDesc is the grpc.ServiceDesc for FunctionRunnerService service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var FunctionRunnerService_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "apiextensions.fn.proto.v1.FunctionRunnerService",
|
||||
HandlerType: (*FunctionRunnerServiceServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "RunFunction",
|
||||
Handler: _FunctionRunnerService_RunFunction_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "v1/run_function.proto",
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -19,12 +19,11 @@ syntax = "proto3";
|
|||
import "google/protobuf/struct.proto";
|
||||
import "google/protobuf/duration.proto";
|
||||
|
||||
// Note that the authoritative Composition Functions protobuf definition lives
|
||||
// at the below URL. Each SDK maintains and manually syncs its own copy.
|
||||
// https://github.com/crossplane/crossplane/tree/master/apis/apiextensions/fn/proto
|
||||
// Generated from apiextensions/fn/proto/v1/run_function.proto by ../hack/duplicate_proto_type.sh. DO NOT EDIT.
|
||||
|
||||
package apiextensions.fn.proto.v1beta1;
|
||||
|
||||
option go_package = "github.com/crossplane/function-sdk-go/proto/v1beta1";
|
||||
option go_package = "github.com/crossplane/crossplane/apis/apiextensions/fn/proto/v1beta1";
|
||||
|
||||
// A FunctionRunnerService is a Composition Function.
|
||||
service FunctionRunnerService {
|
||||
|
@ -63,6 +62,37 @@ message RunFunctionRequest {
|
|||
// and that context will be passed to subsequent Functions. Crossplane
|
||||
// discards all context returned by the last Function in the pipeline.
|
||||
optional google.protobuf.Struct context = 5;
|
||||
|
||||
// Optional extra resources that the Function required.
|
||||
// Note that extra resources is a map to Resources, plural.
|
||||
// The map key corresponds to the key in a RunFunctionResponse's
|
||||
// extra_resources field. If a Function requested extra resources that
|
||||
// did not exist, Crossplane sets the map key to an empty Resources message to
|
||||
// indicate that it attempted to satisfy the request.
|
||||
map<string, Resources> extra_resources = 6;
|
||||
|
||||
// Optional credentials that this Function may use to communicate with an
|
||||
// external system.
|
||||
map <string, Credentials> credentials = 7;
|
||||
}
|
||||
|
||||
// Credentials that a Function may use to communicate with an external system.
|
||||
message Credentials {
|
||||
// Source of the credentials.
|
||||
oneof source {
|
||||
// Credential data loaded by Crossplane, for example from a Secret.
|
||||
CredentialData credential_data = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// CredentialData loaded by Crossplane, for example from a Secret.
|
||||
message CredentialData {
|
||||
map<string, bytes> data = 1;
|
||||
}
|
||||
|
||||
// Resources represents the state of several Crossplane resources.
|
||||
message Resources {
|
||||
repeated Resource items = 1;
|
||||
}
|
||||
|
||||
// A RunFunctionResponse contains the result of a Composition Function run.
|
||||
|
@ -90,6 +120,13 @@ message RunFunctionResponse {
|
|||
// Optional context to be passed to the next Function in the pipeline as part
|
||||
// of the RunFunctionRequest. Dropped on the last function in the pipeline.
|
||||
optional google.protobuf.Struct context = 4;
|
||||
|
||||
// Requirements that must be satisfied for this Function to run successfully.
|
||||
Requirements requirements = 5;
|
||||
|
||||
// Status conditions to be applied to the composite resource. Conditions may also
|
||||
// optionally be applied to the composite resource's associated claim.
|
||||
repeated Condition conditions = 6;
|
||||
}
|
||||
|
||||
// RequestMeta contains metadata pertaining to a RunFunctionRequest.
|
||||
|
@ -99,6 +136,36 @@ message RequestMeta {
|
|||
string tag = 1;
|
||||
}
|
||||
|
||||
// Requirements that must be satisfied for a Function to run successfully.
|
||||
message Requirements {
|
||||
// Extra resources that this Function requires.
|
||||
// The map key uniquely identifies the group of resources.
|
||||
map<string, ResourceSelector> extra_resources = 1;
|
||||
}
|
||||
|
||||
// ResourceSelector selects a group of resources, either by name or by label.
|
||||
message ResourceSelector {
|
||||
// API version of resources to select.
|
||||
string api_version = 1;
|
||||
|
||||
// Kind of resources to select.
|
||||
string kind = 2;
|
||||
|
||||
// Resources to match.
|
||||
oneof match {
|
||||
// Match the resource with this name.
|
||||
string match_name = 3;
|
||||
|
||||
// Match all resources with these labels.
|
||||
MatchLabels match_labels = 4;
|
||||
}
|
||||
}
|
||||
|
||||
// MatchLabels defines a set of labels to match resources against.
|
||||
message MatchLabels {
|
||||
map<string, string> labels = 1;
|
||||
}
|
||||
|
||||
// ResponseMeta contains metadata pertaining to a RunFunctionResponse.
|
||||
message ResponseMeta {
|
||||
// An opaque string identifying the content of the request. Must match the
|
||||
|
@ -182,6 +249,13 @@ message Result {
|
|||
|
||||
// Human-readable details about the result.
|
||||
string message = 2;
|
||||
|
||||
// Optional PascalCase, machine-readable reason for this result. If omitted,
|
||||
// the value will be ComposeResources.
|
||||
optional string reason = 3;
|
||||
|
||||
// The resources this result targets.
|
||||
optional Target target = 4;
|
||||
}
|
||||
|
||||
// Severity of Function results.
|
||||
|
@ -201,4 +275,54 @@ enum Severity {
|
|||
// Normal results are emitted as normal events and debug logs associated
|
||||
// with the composite resource.
|
||||
SEVERITY_NORMAL = 3;
|
||||
}
|
||||
}
|
||||
|
||||
// Target of Function results and conditions.
|
||||
enum Target {
|
||||
// If the target is unspecified, the result targets the composite resource.
|
||||
TARGET_UNSPECIFIED = 0;
|
||||
|
||||
// Target the composite resource. Results that target the composite resource
|
||||
// should include detailed, advanced information.
|
||||
TARGET_COMPOSITE = 1;
|
||||
|
||||
// Target the composite and the claim. Results that target the composite and
|
||||
// the claim should include only end-user friendly information.
|
||||
TARGET_COMPOSITE_AND_CLAIM = 2;
|
||||
}
|
||||
|
||||
// Status condition to be applied to the composite resource. Condition may also
|
||||
// optionally be applied to the composite resource's associated claim. For
|
||||
// detailed information on proper usage of status conditions, please see
|
||||
// https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties.
|
||||
message Condition {
|
||||
// Type of condition in PascalCase.
|
||||
string type = 1;
|
||||
|
||||
// Status of the condition.
|
||||
Status status = 2;
|
||||
|
||||
// Reason contains a programmatic identifier indicating the reason for the
|
||||
// condition's last transition. Producers of specific condition types may
|
||||
// define expected values and meanings for this field, and whether the values
|
||||
// are considered a guaranteed API. The value should be a PascalCase string.
|
||||
// This field may not be empty.
|
||||
string reason = 3;
|
||||
|
||||
// Message is a human readable message indicating details about the
|
||||
// transition. This may be an empty string.
|
||||
optional string message = 4;
|
||||
|
||||
// The resources this condition targets.
|
||||
optional Target target = 5;
|
||||
}
|
||||
|
||||
enum Status {
|
||||
STATUS_CONDITION_UNSPECIFIED = 0;
|
||||
|
||||
STATUS_CONDITION_UNKNOWN = 1;
|
||||
|
||||
STATUS_CONDITION_TRUE = 2;
|
||||
|
||||
STATUS_CONDITION_FALSE = 3;
|
||||
}
|
||||
|
|
|
@ -15,13 +15,11 @@
|
|||
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.3.0
|
||||
// - protoc-gen-go-grpc v1.5.1
|
||||
// - protoc (unknown)
|
||||
// source: v1beta1/run_function.proto
|
||||
|
||||
// Note that the authoritative Composition Functions protobuf definition lives
|
||||
// at the below URL. Each SDK maintains and manually syncs its own copy.
|
||||
// https://github.com/crossplane/crossplane/tree/master/apis/apiextensions/fn/proto
|
||||
// Generated from apiextensions/fn/proto/v1/run_function.proto by ../hack/duplicate_proto_type.sh. DO NOT EDIT.
|
||||
|
||||
package v1beta1
|
||||
|
||||
|
@ -34,8 +32,8 @@ import (
|
|||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.32.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion7
|
||||
// Requires gRPC-Go v1.64.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion9
|
||||
|
||||
const (
|
||||
FunctionRunnerService_RunFunction_FullMethodName = "/apiextensions.fn.proto.v1beta1.FunctionRunnerService/RunFunction"
|
||||
|
@ -44,6 +42,8 @@ const (
|
|||
// FunctionRunnerServiceClient is the client API for FunctionRunnerService service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
//
|
||||
// A FunctionRunnerService is a Composition Function.
|
||||
type FunctionRunnerServiceClient interface {
|
||||
// RunFunction runs the Composition Function.
|
||||
RunFunction(ctx context.Context, in *RunFunctionRequest, opts ...grpc.CallOption) (*RunFunctionResponse, error)
|
||||
|
@ -58,8 +58,9 @@ func NewFunctionRunnerServiceClient(cc grpc.ClientConnInterface) FunctionRunnerS
|
|||
}
|
||||
|
||||
func (c *functionRunnerServiceClient) RunFunction(ctx context.Context, in *RunFunctionRequest, opts ...grpc.CallOption) (*RunFunctionResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(RunFunctionResponse)
|
||||
err := c.cc.Invoke(ctx, FunctionRunnerService_RunFunction_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, FunctionRunnerService_RunFunction_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -68,21 +69,27 @@ func (c *functionRunnerServiceClient) RunFunction(ctx context.Context, in *RunFu
|
|||
|
||||
// FunctionRunnerServiceServer is the server API for FunctionRunnerService service.
|
||||
// All implementations must embed UnimplementedFunctionRunnerServiceServer
|
||||
// for forward compatibility
|
||||
// for forward compatibility.
|
||||
//
|
||||
// A FunctionRunnerService is a Composition Function.
|
||||
type FunctionRunnerServiceServer interface {
|
||||
// RunFunction runs the Composition Function.
|
||||
RunFunction(context.Context, *RunFunctionRequest) (*RunFunctionResponse, error)
|
||||
mustEmbedUnimplementedFunctionRunnerServiceServer()
|
||||
}
|
||||
|
||||
// UnimplementedFunctionRunnerServiceServer must be embedded to have forward compatible implementations.
|
||||
type UnimplementedFunctionRunnerServiceServer struct {
|
||||
}
|
||||
// UnimplementedFunctionRunnerServiceServer must be embedded to have
|
||||
// forward compatible implementations.
|
||||
//
|
||||
// NOTE: this should be embedded by value instead of pointer to avoid a nil
|
||||
// pointer dereference when methods are called.
|
||||
type UnimplementedFunctionRunnerServiceServer struct{}
|
||||
|
||||
func (UnimplementedFunctionRunnerServiceServer) RunFunction(context.Context, *RunFunctionRequest) (*RunFunctionResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method RunFunction not implemented")
|
||||
}
|
||||
func (UnimplementedFunctionRunnerServiceServer) mustEmbedUnimplementedFunctionRunnerServiceServer() {}
|
||||
func (UnimplementedFunctionRunnerServiceServer) testEmbeddedByValue() {}
|
||||
|
||||
// UnsafeFunctionRunnerServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to FunctionRunnerServiceServer will
|
||||
|
@ -92,6 +99,13 @@ type UnsafeFunctionRunnerServiceServer interface {
|
|||
}
|
||||
|
||||
func RegisterFunctionRunnerServiceServer(s grpc.ServiceRegistrar, srv FunctionRunnerServiceServer) {
|
||||
// If the following call pancis, it indicates UnimplementedFunctionRunnerServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
|
||||
t.testEmbeddedByValue()
|
||||
}
|
||||
s.RegisterService(&FunctionRunnerService_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
|
|
|
@ -19,22 +19,23 @@ package request
|
|||
|
||||
import (
|
||||
"google.golang.org/protobuf/types/known/structpb"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
"github.com/crossplane/function-sdk-go/errors"
|
||||
"github.com/crossplane/function-sdk-go/proto/v1beta1"
|
||||
v1 "github.com/crossplane/function-sdk-go/proto/v1"
|
||||
"github.com/crossplane/function-sdk-go/resource"
|
||||
"github.com/crossplane/function-sdk-go/resource/composed"
|
||||
"github.com/crossplane/function-sdk-go/resource/composite"
|
||||
)
|
||||
|
||||
// GetInput from the supplied request. Input is loaded into the supplied object.
|
||||
func GetInput(req *v1beta1.RunFunctionRequest, into runtime.Object) error {
|
||||
return errors.Wrap(resource.AsObject(req.GetInput(), into), "cannot get Function input %T from %T, into, req")
|
||||
func GetInput(req *v1.RunFunctionRequest, into runtime.Object) error {
|
||||
return errors.Wrapf(resource.AsObject(req.GetInput(), into), "cannot get function input %T from %T", into, req)
|
||||
}
|
||||
|
||||
// GetContextKey gets context from the supplied key.
|
||||
func GetContextKey(req *v1beta1.RunFunctionRequest, key string) (*structpb.Value, bool) {
|
||||
func GetContextKey(req *v1.RunFunctionRequest, key string) (*structpb.Value, bool) {
|
||||
f := req.GetContext().GetFields()
|
||||
if f == nil {
|
||||
return nil, false
|
||||
|
@ -44,7 +45,7 @@ func GetContextKey(req *v1beta1.RunFunctionRequest, key string) (*structpb.Value
|
|||
}
|
||||
|
||||
// GetObservedCompositeResource from the supplied request.
|
||||
func GetObservedCompositeResource(req *v1beta1.RunFunctionRequest) (*resource.Composite, error) {
|
||||
func GetObservedCompositeResource(req *v1.RunFunctionRequest) (*resource.Composite, error) {
|
||||
xr := &resource.Composite{
|
||||
Resource: composite.New(),
|
||||
ConnectionDetails: req.GetObserved().GetComposite().GetConnectionDetails(),
|
||||
|
@ -59,7 +60,7 @@ func GetObservedCompositeResource(req *v1beta1.RunFunctionRequest) (*resource.Co
|
|||
}
|
||||
|
||||
// GetObservedComposedResources from the supplied request.
|
||||
func GetObservedComposedResources(req *v1beta1.RunFunctionRequest) (map[resource.Name]resource.ObservedComposed, error) {
|
||||
func GetObservedComposedResources(req *v1.RunFunctionRequest) (map[resource.Name]resource.ObservedComposed, error) {
|
||||
ocds := map[resource.Name]resource.ObservedComposed{}
|
||||
for name, r := range req.GetObserved().GetResources() {
|
||||
ocd := resource.ObservedComposed{Resource: composed.New(), ConnectionDetails: r.GetConnectionDetails()}
|
||||
|
@ -77,7 +78,7 @@ func GetObservedComposedResources(req *v1beta1.RunFunctionRequest) (map[resource
|
|||
}
|
||||
|
||||
// GetDesiredCompositeResource from the supplied request.
|
||||
func GetDesiredCompositeResource(req *v1beta1.RunFunctionRequest) (*resource.Composite, error) {
|
||||
func GetDesiredCompositeResource(req *v1.RunFunctionRequest) (*resource.Composite, error) {
|
||||
xr := &resource.Composite{
|
||||
Resource: composite.New(),
|
||||
ConnectionDetails: req.GetDesired().GetComposite().GetConnectionDetails(),
|
||||
|
@ -92,7 +93,7 @@ func GetDesiredCompositeResource(req *v1beta1.RunFunctionRequest) (*resource.Com
|
|||
}
|
||||
|
||||
// GetDesiredComposedResources from the supplied request.
|
||||
func GetDesiredComposedResources(req *v1beta1.RunFunctionRequest) (map[resource.Name]*resource.DesiredComposed, error) {
|
||||
func GetDesiredComposedResources(req *v1.RunFunctionRequest) (map[resource.Name]*resource.DesiredComposed, error) {
|
||||
dcds := map[resource.Name]*resource.DesiredComposed{}
|
||||
for name, r := range req.GetDesired().GetResources() {
|
||||
dcd := &resource.DesiredComposed{Resource: composed.New()}
|
||||
|
@ -100,14 +101,45 @@ func GetDesiredComposedResources(req *v1beta1.RunFunctionRequest) (map[resource.
|
|||
return nil, err
|
||||
}
|
||||
switch r.GetReady() {
|
||||
case v1beta1.Ready_READY_UNSPECIFIED:
|
||||
case v1.Ready_READY_UNSPECIFIED:
|
||||
dcd.Ready = resource.ReadyUnspecified
|
||||
case v1beta1.Ready_READY_TRUE:
|
||||
case v1.Ready_READY_TRUE:
|
||||
dcd.Ready = resource.ReadyTrue
|
||||
case v1beta1.Ready_READY_FALSE:
|
||||
case v1.Ready_READY_FALSE:
|
||||
dcd.Ready = resource.ReadyFalse
|
||||
}
|
||||
dcds[resource.Name(name)] = dcd
|
||||
}
|
||||
return dcds, nil
|
||||
}
|
||||
|
||||
// GetExtraResources from the supplied request.
|
||||
func GetExtraResources(req *v1.RunFunctionRequest) (map[string][]resource.Extra, error) {
|
||||
out := make(map[string][]resource.Extra, len(req.GetExtraResources()))
|
||||
for name, ers := range req.GetExtraResources() {
|
||||
out[name] = []resource.Extra{}
|
||||
for _, i := range ers.GetItems() {
|
||||
r := &resource.Extra{Resource: &unstructured.Unstructured{}}
|
||||
if err := resource.AsObject(i.GetResource(), r.Resource); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out[name] = append(out[name], *r)
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// GetCredentials from the supplied request.
|
||||
func GetCredentials(req *v1.RunFunctionRequest, name string) (resource.Credentials, error) {
|
||||
cred, exists := req.GetCredentials()[name]
|
||||
if !exists {
|
||||
return resource.Credentials{}, errors.Errorf("%s: credential not found", name)
|
||||
}
|
||||
|
||||
switch t := cred.GetSource().(type) {
|
||||
case *v1.Credentials_CredentialData:
|
||||
return resource.Credentials{Type: resource.CredentialsTypeData, Data: cred.GetCredentialData().GetData()}, nil
|
||||
default:
|
||||
return resource.Credentials{}, errors.Errorf("%s: not a supported credential source", t)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ import (
|
|||
"github.com/google/go-cmp/cmp"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
|
||||
"github.com/crossplane/function-sdk-go/proto/v1beta1"
|
||||
v1 "github.com/crossplane/function-sdk-go/proto/v1"
|
||||
"github.com/crossplane/function-sdk-go/resource"
|
||||
"github.com/crossplane/function-sdk-go/resource/composed"
|
||||
"github.com/crossplane/function-sdk-go/resource/composite"
|
||||
|
@ -37,12 +37,12 @@ func TestGetObservedCompositeResource(t *testing.T) {
|
|||
|
||||
cases := map[string]struct {
|
||||
reason string
|
||||
req *v1beta1.RunFunctionRequest
|
||||
req *v1.RunFunctionRequest
|
||||
want want
|
||||
}{
|
||||
"NoObservedXR": {
|
||||
reason: "In the unlikely event the request has no observed XR we should return a usable, empty Composite.",
|
||||
req: &v1beta1.RunFunctionRequest{},
|
||||
req: &v1.RunFunctionRequest{},
|
||||
want: want{
|
||||
oxr: &resource.Composite{
|
||||
Resource: composite.New(),
|
||||
|
@ -52,9 +52,9 @@ func TestGetObservedCompositeResource(t *testing.T) {
|
|||
},
|
||||
"ObservedXR": {
|
||||
reason: "We should return the XR read from the request.",
|
||||
req: &v1beta1.RunFunctionRequest{
|
||||
Observed: &v1beta1.State{
|
||||
Composite: &v1beta1.Resource{
|
||||
req: &v1.RunFunctionRequest{
|
||||
Observed: &v1.State{
|
||||
Composite: &v1.Resource{
|
||||
Resource: resource.MustStructJSON(`{
|
||||
"apiVersion": "test.crossplane.io/v1",
|
||||
"kind": "XR"
|
||||
|
@ -103,12 +103,12 @@ func TestGetDesiredCompositeResource(t *testing.T) {
|
|||
|
||||
cases := map[string]struct {
|
||||
reason string
|
||||
req *v1beta1.RunFunctionRequest
|
||||
req *v1.RunFunctionRequest
|
||||
want want
|
||||
}{
|
||||
"NoDesiredXR": {
|
||||
reason: "If the request has no desired XR we should return a usable, empty Composite.",
|
||||
req: &v1beta1.RunFunctionRequest{},
|
||||
req: &v1.RunFunctionRequest{},
|
||||
want: want{
|
||||
oxr: &resource.Composite{
|
||||
Resource: composite.New(),
|
||||
|
@ -118,9 +118,9 @@ func TestGetDesiredCompositeResource(t *testing.T) {
|
|||
},
|
||||
"DesiredXR": {
|
||||
reason: "We should return the XR read from the request.",
|
||||
req: &v1beta1.RunFunctionRequest{
|
||||
Desired: &v1beta1.State{
|
||||
Composite: &v1beta1.Resource{
|
||||
req: &v1.RunFunctionRequest{
|
||||
Desired: &v1.State{
|
||||
Composite: &v1.Resource{
|
||||
Resource: resource.MustStructJSON(`{
|
||||
"apiVersion": "test.crossplane.io/v1",
|
||||
"kind": "XR"
|
||||
|
@ -169,21 +169,21 @@ func TestGetObservedComposedResources(t *testing.T) {
|
|||
|
||||
cases := map[string]struct {
|
||||
reason string
|
||||
req *v1beta1.RunFunctionRequest
|
||||
req *v1.RunFunctionRequest
|
||||
want want
|
||||
}{
|
||||
"NoObservedComposedResources": {
|
||||
reason: "If the request has no observed composed resources we should return an empty, non-nil map.",
|
||||
req: &v1beta1.RunFunctionRequest{},
|
||||
req: &v1.RunFunctionRequest{},
|
||||
want: want{
|
||||
ocds: map[resource.Name]resource.ObservedComposed{},
|
||||
},
|
||||
},
|
||||
"ObservedComposedResources": {
|
||||
reason: "If the request has observed composed resources we should return them.",
|
||||
req: &v1beta1.RunFunctionRequest{
|
||||
Observed: &v1beta1.State{
|
||||
Resources: map[string]*v1beta1.Resource{
|
||||
req: &v1.RunFunctionRequest{
|
||||
Observed: &v1.State{
|
||||
Resources: map[string]*v1.Resource{
|
||||
"observed-composed-resource": {
|
||||
Resource: resource.MustStructJSON(`{
|
||||
"apiVersion": "test.crossplane.io/v1",
|
||||
|
@ -236,27 +236,27 @@ func TestGetDesiredComposedResources(t *testing.T) {
|
|||
|
||||
cases := map[string]struct {
|
||||
reason string
|
||||
req *v1beta1.RunFunctionRequest
|
||||
req *v1.RunFunctionRequest
|
||||
want want
|
||||
}{
|
||||
"NoDesiredComposedResources": {
|
||||
reason: "If the request has no desired composed resources we should return an empty, non-nil map.",
|
||||
req: &v1beta1.RunFunctionRequest{},
|
||||
req: &v1.RunFunctionRequest{},
|
||||
want: want{
|
||||
dcds: map[resource.Name]*resource.DesiredComposed{},
|
||||
},
|
||||
},
|
||||
"DesiredComposedResources": {
|
||||
reason: "If the request has desired composed resources we should return them.",
|
||||
req: &v1beta1.RunFunctionRequest{
|
||||
Desired: &v1beta1.State{
|
||||
Resources: map[string]*v1beta1.Resource{
|
||||
req: &v1.RunFunctionRequest{
|
||||
Desired: &v1.State{
|
||||
Resources: map[string]*v1.Resource{
|
||||
"desired-composed-resource": {
|
||||
Resource: resource.MustStructJSON(`{
|
||||
"apiVersion": "test.crossplane.io/v1",
|
||||
"kind": "Composed"
|
||||
}`),
|
||||
Ready: v1beta1.Ready_READY_TRUE,
|
||||
Ready: v1.Ready_READY_TRUE,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -284,3 +284,18 @@ func (cd *Unstructured) SetBool(path string, value bool) error {
|
|||
func (cd *Unstructured) SetInteger(path string, value int64) error {
|
||||
return cd.SetValue(path, value)
|
||||
}
|
||||
|
||||
// SetObservedGeneration of this Composed resource.
|
||||
func (cd *Unstructured) SetObservedGeneration(generation int64) {
|
||||
status := &xpv1.ObservedStatus{}
|
||||
_ = fieldpath.Pave(cd.Object).GetValueInto("status", status)
|
||||
status.SetObservedGeneration(generation)
|
||||
_ = fieldpath.Pave(cd.Object).SetValue("status.observedGeneration", status.ObservedGeneration)
|
||||
}
|
||||
|
||||
// GetObservedGeneration of this Composed resource.
|
||||
func (cd *Unstructured) GetObservedGeneration() int64 {
|
||||
status := &xpv1.ObservedStatus{}
|
||||
_ = fieldpath.Pave(cd.Object).GetValueInto("status", status)
|
||||
return status.GetObservedGeneration()
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ import (
|
|||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
"github.com/upbound/provider-aws/apis/s3/v1beta1"
|
||||
"github.com/upbound/provider-aws/apis/s3/v1beta2"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
@ -62,25 +62,25 @@ func Example() {
|
|||
}
|
||||
|
||||
func ExampleScheme() {
|
||||
// Add all v1beta1 types to the scheme so that From can automatically
|
||||
// Add all v1beta2 types to the scheme so that From can automatically
|
||||
// determine their apiVersion and kind.
|
||||
v1beta1.AddToScheme(Scheme)
|
||||
v1beta2.AddToScheme(Scheme)
|
||||
}
|
||||
|
||||
func ExampleFrom() {
|
||||
// Add all v1beta1 types to the scheme so that From can automatically
|
||||
// Add all v1beta2 types to the scheme so that From can automatically
|
||||
// determine their apiVersion and kind.
|
||||
v1beta1.AddToScheme(Scheme)
|
||||
v1beta2.AddToScheme(Scheme)
|
||||
|
||||
// Create a strongly typed runtime.Object, imported from a provider.
|
||||
b := &v1beta1.Bucket{
|
||||
b := &v1beta2.Bucket{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Labels: map[string]string{
|
||||
"coolness": "high",
|
||||
},
|
||||
},
|
||||
Spec: v1beta1.BucketSpec{
|
||||
ForProvider: v1beta1.BucketParameters{
|
||||
Spec: v1beta2.BucketSpec{
|
||||
ForProvider: v1beta2.BucketParameters{
|
||||
Region: ptr.To[string]("us-east-2"),
|
||||
},
|
||||
},
|
||||
|
@ -100,7 +100,7 @@ func ExampleFrom() {
|
|||
fmt.Println(string(y))
|
||||
|
||||
// Output:
|
||||
// apiVersion: s3.aws.upbound.io/v1beta1
|
||||
// apiVersion: s3.aws.upbound.io/v1beta2
|
||||
// kind: Bucket
|
||||
// metadata:
|
||||
// labels:
|
||||
|
@ -108,10 +108,12 @@ func ExampleFrom() {
|
|||
// spec:
|
||||
// forProvider:
|
||||
// region: us-east-2
|
||||
// status:
|
||||
// observedGeneration: 0
|
||||
}
|
||||
|
||||
func TestFrom(t *testing.T) {
|
||||
v1beta1.AddToScheme(Scheme)
|
||||
v1beta2.AddToScheme(Scheme)
|
||||
|
||||
type args struct {
|
||||
o runtime.Object
|
||||
|
@ -128,12 +130,12 @@ func TestFrom(t *testing.T) {
|
|||
"WithMetadata": {
|
||||
reason: "A resource with metadata should not grow any extra metadata fields during conversion",
|
||||
args: args{
|
||||
o: &v1beta1.Bucket{
|
||||
o: &v1beta2.Bucket{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "cool-bucket",
|
||||
},
|
||||
Spec: v1beta1.BucketSpec{
|
||||
ForProvider: v1beta1.BucketParameters{
|
||||
Spec: v1beta2.BucketSpec{
|
||||
ForProvider: v1beta2.BucketParameters{
|
||||
Region: ptr.To[string]("us-east-2"),
|
||||
},
|
||||
},
|
||||
|
@ -141,8 +143,8 @@ func TestFrom(t *testing.T) {
|
|||
},
|
||||
want: want{
|
||||
cd: &Unstructured{Unstructured: unstructured.Unstructured{Object: map[string]any{
|
||||
"apiVersion": v1beta1.CRDGroupVersion.String(),
|
||||
"kind": v1beta1.Bucket_Kind,
|
||||
"apiVersion": v1beta2.CRDGroupVersion.String(),
|
||||
"kind": v1beta2.Bucket_Kind,
|
||||
"metadata": map[string]any{
|
||||
"name": "cool-bucket",
|
||||
},
|
||||
|
@ -151,15 +153,18 @@ func TestFrom(t *testing.T) {
|
|||
"region": "us-east-2",
|
||||
},
|
||||
},
|
||||
"status": map[string]any{
|
||||
"observedGeneration": float64(0),
|
||||
},
|
||||
}}},
|
||||
},
|
||||
},
|
||||
"WithoutMetadata": {
|
||||
reason: "A resource with no metadata should not grow a metadata object during conversion",
|
||||
args: args{
|
||||
o: &v1beta1.Bucket{
|
||||
Spec: v1beta1.BucketSpec{
|
||||
ForProvider: v1beta1.BucketParameters{
|
||||
o: &v1beta2.Bucket{
|
||||
Spec: v1beta2.BucketSpec{
|
||||
ForProvider: v1beta2.BucketParameters{
|
||||
Region: ptr.To[string]("us-east-2"),
|
||||
},
|
||||
},
|
||||
|
@ -167,13 +172,16 @@ func TestFrom(t *testing.T) {
|
|||
},
|
||||
want: want{
|
||||
cd: &Unstructured{Unstructured: unstructured.Unstructured{Object: map[string]any{
|
||||
"apiVersion": v1beta1.CRDGroupVersion.String(),
|
||||
"kind": v1beta1.Bucket_Kind,
|
||||
"apiVersion": v1beta2.CRDGroupVersion.String(),
|
||||
"kind": v1beta2.Bucket_Kind,
|
||||
"spec": map[string]any{
|
||||
"forProvider": map[string]any{
|
||||
"region": "us-east-2",
|
||||
},
|
||||
},
|
||||
"status": map[string]any{
|
||||
"observedGeneration": float64(0),
|
||||
},
|
||||
}}},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -30,7 +30,7 @@ import (
|
|||
xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1"
|
||||
"github.com/crossplane/crossplane-runtime/pkg/fieldpath"
|
||||
"github.com/crossplane/crossplane-runtime/pkg/resource"
|
||||
"github.com/crossplane/crossplane-runtime/pkg/resource/unstructured/claim"
|
||||
"github.com/crossplane/crossplane-runtime/pkg/resource/unstructured/reference"
|
||||
)
|
||||
|
||||
// New returns a new unstructured composite resource (XR).
|
||||
|
@ -104,8 +104,8 @@ func (xr *Unstructured) SetCompositionReference(ref *corev1.ObjectReference) {
|
|||
}
|
||||
|
||||
// GetCompositionRevisionReference of this composite resource.
|
||||
func (xr *Unstructured) GetCompositionRevisionReference() *corev1.ObjectReference {
|
||||
out := &corev1.ObjectReference{}
|
||||
func (xr *Unstructured) GetCompositionRevisionReference() *corev1.LocalObjectReference {
|
||||
out := &corev1.LocalObjectReference{}
|
||||
if err := fieldpath.Pave(xr.Object).GetValueInto("spec.compositionRevisionRef", out); err != nil {
|
||||
return nil
|
||||
}
|
||||
|
@ -113,7 +113,7 @@ func (xr *Unstructured) GetCompositionRevisionReference() *corev1.ObjectReferenc
|
|||
}
|
||||
|
||||
// SetCompositionRevisionReference of this composite resource.
|
||||
func (xr *Unstructured) SetCompositionRevisionReference(ref *corev1.ObjectReference) {
|
||||
func (xr *Unstructured) SetCompositionRevisionReference(ref *corev1.LocalObjectReference) {
|
||||
_ = fieldpath.Pave(xr.Object).SetValue("spec.compositionRevisionRef", ref)
|
||||
}
|
||||
|
||||
|
@ -147,8 +147,8 @@ func (xr *Unstructured) GetCompositionUpdatePolicy() *xpv1.UpdatePolicy {
|
|||
}
|
||||
|
||||
// GetClaimReference of this composite resource.
|
||||
func (xr *Unstructured) GetClaimReference() *claim.Reference {
|
||||
out := &claim.Reference{}
|
||||
func (xr *Unstructured) GetClaimReference() *reference.Claim {
|
||||
out := &reference.Claim{}
|
||||
if err := fieldpath.Pave(xr.Object).GetValueInto("spec.claimRef", out); err != nil {
|
||||
return nil
|
||||
}
|
||||
|
@ -156,7 +156,7 @@ func (xr *Unstructured) GetClaimReference() *claim.Reference {
|
|||
}
|
||||
|
||||
// SetClaimReference of this composite resource.
|
||||
func (xr *Unstructured) SetClaimReference(ref *claim.Reference) {
|
||||
func (xr *Unstructured) SetClaimReference(ref *reference.Claim) {
|
||||
_ = fieldpath.Pave(xr.Object).SetValue("spec.claimRef", ref)
|
||||
}
|
||||
|
||||
|
@ -350,3 +350,18 @@ func (xr *Unstructured) SetBool(path string, value bool) error {
|
|||
func (xr *Unstructured) SetInteger(path string, value int64) error {
|
||||
return xr.SetValue(path, value)
|
||||
}
|
||||
|
||||
// SetObservedGeneration of this Composite resource.
|
||||
func (xr *Unstructured) SetObservedGeneration(generation int64) {
|
||||
status := &xpv1.ObservedStatus{}
|
||||
_ = fieldpath.Pave(xr.Object).GetValueInto("status", status)
|
||||
status.SetObservedGeneration(generation)
|
||||
_ = fieldpath.Pave(xr.Object).SetValue("status.observedGeneration", status.ObservedGeneration)
|
||||
}
|
||||
|
||||
// GetObservedGeneration of this Composite resource.
|
||||
func (xr *Unstructured) GetObservedGeneration() int64 {
|
||||
status := &xpv1.ObservedStatus{}
|
||||
_ = fieldpath.Pave(xr.Object).GetValueInto("status", status)
|
||||
return status.GetObservedGeneration()
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import (
|
|||
"github.com/go-json-experiment/json"
|
||||
"google.golang.org/protobuf/encoding/protojson"
|
||||
"google.golang.org/protobuf/types/known/structpb"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
"github.com/crossplane/function-sdk-go/errors"
|
||||
|
@ -51,6 +52,29 @@ type DesiredComposed struct {
|
|||
Ready Ready
|
||||
}
|
||||
|
||||
// Extra is a resource requested by a Function.
|
||||
type Extra struct {
|
||||
Resource *unstructured.Unstructured
|
||||
}
|
||||
|
||||
// CredentialsType is the type of credentials.
|
||||
type CredentialsType string
|
||||
|
||||
const (
|
||||
// CredentialsTypeData is a Credential of type Data.
|
||||
CredentialsTypeData = "Data"
|
||||
)
|
||||
|
||||
// Credentials is a secret requested by a Function.
|
||||
type Credentials struct {
|
||||
// Type represents the type of credentials.
|
||||
Type CredentialsType
|
||||
|
||||
// Data is a map of key-value pairs where the keys are strings, and the values are byte slices
|
||||
// containing sensitive data.
|
||||
Data map[string][]byte
|
||||
}
|
||||
|
||||
// Ready indicates whether a composed resource should be considered ready.
|
||||
type Ready string
|
||||
|
||||
|
@ -85,7 +109,7 @@ func AsObject(s *structpb.Struct, o runtime.Object) error {
|
|||
if err != nil {
|
||||
return errors.Wrapf(err, "cannot marshal %T to JSON", s)
|
||||
}
|
||||
return errors.Wrapf(json.Unmarshal(b, o), "cannot unmarshal JSON from %T into %T", s, o)
|
||||
return errors.Wrapf(json.Unmarshal(b, o, json.RejectUnknownMembers(true)), "cannot unmarshal JSON from %T into %T", s, o)
|
||||
}
|
||||
|
||||
// AsStruct gets the supplied struct from the supplied Kubernetes object.
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
Copyright 2024 The Crossplane Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package response
|
||||
|
||||
import (
|
||||
v1 "github.com/crossplane/function-sdk-go/proto/v1"
|
||||
)
|
||||
|
||||
// ConditionOption allows further customization of the condition.
|
||||
type ConditionOption struct {
|
||||
condition *v1.Condition
|
||||
}
|
||||
|
||||
// ConditionTrue will create a condition with the status of true and add the
|
||||
// condition to the supplied RunFunctionResponse.
|
||||
func ConditionTrue(rsp *v1.RunFunctionResponse, typ, reason string) *ConditionOption {
|
||||
return newCondition(rsp, typ, reason, v1.Status_STATUS_CONDITION_TRUE)
|
||||
}
|
||||
|
||||
// ConditionFalse will create a condition with the status of false and add the
|
||||
// condition to the supplied RunFunctionResponse.
|
||||
func ConditionFalse(rsp *v1.RunFunctionResponse, typ, reason string) *ConditionOption {
|
||||
return newCondition(rsp, typ, reason, v1.Status_STATUS_CONDITION_FALSE)
|
||||
}
|
||||
|
||||
// ConditionUnknown will create a condition with the status of unknown and add
|
||||
// the condition to the supplied RunFunctionResponse.
|
||||
func ConditionUnknown(rsp *v1.RunFunctionResponse, typ, reason string) *ConditionOption {
|
||||
return newCondition(rsp, typ, reason, v1.Status_STATUS_CONDITION_UNKNOWN)
|
||||
}
|
||||
|
||||
func newCondition(rsp *v1.RunFunctionResponse, typ, reason string, s v1.Status) *ConditionOption {
|
||||
if rsp.GetConditions() == nil {
|
||||
rsp.Conditions = make([]*v1.Condition, 0, 1)
|
||||
}
|
||||
c := &v1.Condition{
|
||||
Type: typ,
|
||||
Status: s,
|
||||
Reason: reason,
|
||||
Target: v1.Target_TARGET_COMPOSITE.Enum(),
|
||||
}
|
||||
rsp.Conditions = append(rsp.GetConditions(), c)
|
||||
return &ConditionOption{condition: c}
|
||||
}
|
||||
|
||||
// TargetComposite updates the condition to target the composite resource.
|
||||
func (c *ConditionOption) TargetComposite() *ConditionOption {
|
||||
c.condition.Target = v1.Target_TARGET_COMPOSITE.Enum()
|
||||
return c
|
||||
}
|
||||
|
||||
// TargetCompositeAndClaim updates the condition to target both the composite
|
||||
// resource and claim.
|
||||
func (c *ConditionOption) TargetCompositeAndClaim() *ConditionOption {
|
||||
c.condition.Target = v1.Target_TARGET_COMPOSITE_AND_CLAIM.Enum()
|
||||
return c
|
||||
}
|
||||
|
||||
// WithMessage adds the message to the condition.
|
||||
func (c *ConditionOption) WithMessage(message string) *ConditionOption {
|
||||
c.condition.Message = &message
|
||||
return c
|
||||
}
|
|
@ -0,0 +1,193 @@
|
|||
/*
|
||||
Copyright 2024 The Crossplane Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package response_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"google.golang.org/protobuf/testing/protocmp"
|
||||
"k8s.io/utils/ptr"
|
||||
|
||||
v1 "github.com/crossplane/function-sdk-go/proto/v1"
|
||||
"github.com/crossplane/function-sdk-go/response"
|
||||
)
|
||||
|
||||
// Condition types.
|
||||
const (
|
||||
typeDatabaseReady = "DatabaseReady"
|
||||
)
|
||||
|
||||
// Condition reasons.
|
||||
const (
|
||||
reasonAvailable = "ReasonAvailable"
|
||||
reasonCreating = "ReasonCreating"
|
||||
reasonPriorFailure = "ReasonPriorFailure"
|
||||
reasonUnauthorized = "ReasonUnauthorized"
|
||||
)
|
||||
|
||||
func TestCondition(t *testing.T) {
|
||||
type testFn func(*v1.RunFunctionResponse)
|
||||
type args struct {
|
||||
fns []testFn
|
||||
}
|
||||
type want struct {
|
||||
conditions []*v1.Condition
|
||||
}
|
||||
cases := map[string]struct {
|
||||
reason string
|
||||
args args
|
||||
want want
|
||||
}{
|
||||
"CreateBasicRecords": {
|
||||
reason: "Correctly adds conditions to the response.",
|
||||
args: args{
|
||||
fns: []testFn{
|
||||
func(rsp *v1.RunFunctionResponse) {
|
||||
response.ConditionTrue(rsp, typeDatabaseReady, reasonAvailable)
|
||||
},
|
||||
func(rsp *v1.RunFunctionResponse) {
|
||||
response.ConditionFalse(rsp, typeDatabaseReady, reasonCreating)
|
||||
},
|
||||
func(rsp *v1.RunFunctionResponse) {
|
||||
response.ConditionUnknown(rsp, typeDatabaseReady, reasonPriorFailure)
|
||||
},
|
||||
},
|
||||
},
|
||||
want: want{
|
||||
conditions: []*v1.Condition{
|
||||
{
|
||||
Type: typeDatabaseReady,
|
||||
Status: v1.Status_STATUS_CONDITION_TRUE,
|
||||
Reason: reasonAvailable,
|
||||
Target: v1.Target_TARGET_COMPOSITE.Enum(),
|
||||
},
|
||||
{
|
||||
Type: typeDatabaseReady,
|
||||
Status: v1.Status_STATUS_CONDITION_FALSE,
|
||||
Reason: reasonCreating,
|
||||
Target: v1.Target_TARGET_COMPOSITE.Enum(),
|
||||
},
|
||||
{
|
||||
Type: typeDatabaseReady,
|
||||
Status: v1.Status_STATUS_CONDITION_UNKNOWN,
|
||||
Reason: reasonPriorFailure,
|
||||
Target: v1.Target_TARGET_COMPOSITE.Enum(),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"SetTargets": {
|
||||
reason: "Correctly sets targets on condition and adds it to the response.",
|
||||
args: args{
|
||||
fns: []testFn{
|
||||
func(rsp *v1.RunFunctionResponse) {
|
||||
response.ConditionTrue(rsp, typeDatabaseReady, reasonAvailable).TargetComposite()
|
||||
},
|
||||
func(rsp *v1.RunFunctionResponse) {
|
||||
response.ConditionTrue(rsp, typeDatabaseReady, reasonAvailable).TargetCompositeAndClaim()
|
||||
},
|
||||
},
|
||||
},
|
||||
want: want{
|
||||
conditions: []*v1.Condition{
|
||||
{
|
||||
Type: typeDatabaseReady,
|
||||
Status: v1.Status_STATUS_CONDITION_TRUE,
|
||||
Reason: reasonAvailable,
|
||||
Target: v1.Target_TARGET_COMPOSITE.Enum(),
|
||||
},
|
||||
{
|
||||
Type: typeDatabaseReady,
|
||||
Status: v1.Status_STATUS_CONDITION_TRUE,
|
||||
Reason: reasonAvailable,
|
||||
Target: v1.Target_TARGET_COMPOSITE_AND_CLAIM.Enum(),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"SetMessage": {
|
||||
reason: "Correctly sets message on condition and adds it to the response.",
|
||||
args: args{
|
||||
fns: []testFn{
|
||||
func(rsp *v1.RunFunctionResponse) {
|
||||
response.ConditionTrue(rsp, typeDatabaseReady, reasonAvailable).WithMessage("a test message")
|
||||
},
|
||||
},
|
||||
},
|
||||
want: want{
|
||||
conditions: []*v1.Condition{
|
||||
{
|
||||
Type: typeDatabaseReady,
|
||||
Status: v1.Status_STATUS_CONDITION_TRUE,
|
||||
Reason: reasonAvailable,
|
||||
Target: v1.Target_TARGET_COMPOSITE.Enum(),
|
||||
Message: ptr.To("a test message"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"ChainOptions": {
|
||||
reason: "Can chain condition options together.",
|
||||
args: args{
|
||||
fns: []testFn{
|
||||
func(rsp *v1.RunFunctionResponse) {
|
||||
response.ConditionTrue(rsp, typeDatabaseReady, reasonAvailable).
|
||||
WithMessage("a test message").
|
||||
TargetCompositeAndClaim()
|
||||
},
|
||||
func(rsp *v1.RunFunctionResponse) {
|
||||
response.ConditionTrue(rsp, typeDatabaseReady, reasonAvailable).
|
||||
TargetCompositeAndClaim().
|
||||
WithMessage("a test message")
|
||||
},
|
||||
},
|
||||
},
|
||||
want: want{
|
||||
conditions: []*v1.Condition{
|
||||
{
|
||||
Type: typeDatabaseReady,
|
||||
Status: v1.Status_STATUS_CONDITION_TRUE,
|
||||
Reason: reasonAvailable,
|
||||
Target: v1.Target_TARGET_COMPOSITE_AND_CLAIM.Enum(),
|
||||
Message: ptr.To("a test message"),
|
||||
},
|
||||
{
|
||||
Type: typeDatabaseReady,
|
||||
Status: v1.Status_STATUS_CONDITION_TRUE,
|
||||
Reason: reasonAvailable,
|
||||
Target: v1.Target_TARGET_COMPOSITE_AND_CLAIM.Enum(),
|
||||
Message: ptr.To("a test message"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for name, tc := range cases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
rsp := &v1.RunFunctionResponse{}
|
||||
for _, f := range tc.args.fns {
|
||||
f(rsp)
|
||||
}
|
||||
|
||||
if diff := cmp.Diff(tc.want.conditions, rsp.GetConditions(), protocmp.Transform()); diff != "" {
|
||||
t.Errorf("\n%s\nFrom(...): -want, +got:\n%s", tc.reason, diff)
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
}
|
|
@ -18,14 +18,13 @@ limitations under the License.
|
|||
package response
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"google.golang.org/protobuf/types/known/durationpb"
|
||||
"google.golang.org/protobuf/types/known/structpb"
|
||||
|
||||
"github.com/crossplane/function-sdk-go/errors"
|
||||
"github.com/crossplane/function-sdk-go/proto/v1beta1"
|
||||
v1 "github.com/crossplane/function-sdk-go/proto/v1"
|
||||
"github.com/crossplane/function-sdk-go/resource"
|
||||
)
|
||||
|
||||
|
@ -34,9 +33,9 @@ const DefaultTTL = 1 * time.Minute
|
|||
|
||||
// To bootstraps a response to the supplied request. It automatically copies the
|
||||
// desired state from the request.
|
||||
func To(req *v1beta1.RunFunctionRequest, ttl time.Duration) *v1beta1.RunFunctionResponse {
|
||||
return &v1beta1.RunFunctionResponse{
|
||||
Meta: &v1beta1.ResponseMeta{
|
||||
func To(req *v1.RunFunctionRequest, ttl time.Duration) *v1.RunFunctionResponse {
|
||||
return &v1.RunFunctionResponse{
|
||||
Meta: &v1.ResponseMeta{
|
||||
Tag: req.GetMeta().GetTag(),
|
||||
Ttl: durationpb.New(ttl),
|
||||
},
|
||||
|
@ -46,7 +45,7 @@ func To(req *v1beta1.RunFunctionRequest, ttl time.Duration) *v1beta1.RunFunction
|
|||
}
|
||||
|
||||
// SetContextKey sets context to the supplied key.
|
||||
func SetContextKey(rsp *v1beta1.RunFunctionResponse, key string, v *structpb.Value) {
|
||||
func SetContextKey(rsp *v1.RunFunctionResponse, key string, v *structpb.Value) {
|
||||
if rsp.GetContext().GetFields() == nil {
|
||||
rsp.Context = &structpb.Struct{Fields: make(map[string]*structpb.Value)}
|
||||
}
|
||||
|
@ -57,12 +56,12 @@ func SetContextKey(rsp *v1beta1.RunFunctionResponse, key string, v *structpb.Val
|
|||
// supplied response. The caller must be sure to avoid overwriting the desired
|
||||
// state that may have been accumulated by previous Functions in the pipeline,
|
||||
// unless they intend to.
|
||||
func SetDesiredCompositeResource(rsp *v1beta1.RunFunctionResponse, xr *resource.Composite) error {
|
||||
func SetDesiredCompositeResource(rsp *v1.RunFunctionResponse, xr *resource.Composite) error {
|
||||
if rsp.GetDesired() == nil {
|
||||
rsp.Desired = &v1beta1.State{}
|
||||
rsp.Desired = &v1.State{}
|
||||
}
|
||||
s, err := resource.AsStruct(xr.Resource)
|
||||
rsp.Desired.Composite = &v1beta1.Resource{Resource: s, ConnectionDetails: xr.ConnectionDetails}
|
||||
rsp.Desired.Composite = &v1.Resource{Resource: s, ConnectionDetails: xr.ConnectionDetails}
|
||||
return errors.Wrapf(err, "cannot convert %T to desired composite resource", xr.Resource)
|
||||
}
|
||||
|
||||
|
@ -70,66 +69,28 @@ func SetDesiredCompositeResource(rsp *v1beta1.RunFunctionResponse, xr *resource.
|
|||
// supplied response. The caller must be sure to avoid overwriting the desired
|
||||
// state that may have been accumulated by previous Functions in the pipeline,
|
||||
// unless they intend to.
|
||||
func SetDesiredComposedResources(rsp *v1beta1.RunFunctionResponse, dcds map[resource.Name]*resource.DesiredComposed) error {
|
||||
func SetDesiredComposedResources(rsp *v1.RunFunctionResponse, dcds map[resource.Name]*resource.DesiredComposed) error {
|
||||
if rsp.GetDesired() == nil {
|
||||
rsp.Desired = &v1beta1.State{}
|
||||
rsp.Desired = &v1.State{}
|
||||
}
|
||||
if rsp.GetDesired().GetResources() == nil {
|
||||
rsp.Desired.Resources = map[string]*v1beta1.Resource{}
|
||||
rsp.Desired.Resources = map[string]*v1.Resource{}
|
||||
}
|
||||
for name, dcd := range dcds {
|
||||
s, err := resource.AsStruct(dcd.Resource)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r := &v1beta1.Resource{Resource: s}
|
||||
r := &v1.Resource{Resource: s}
|
||||
switch dcd.Ready {
|
||||
case resource.ReadyUnspecified:
|
||||
r.Ready = v1beta1.Ready_READY_UNSPECIFIED
|
||||
r.Ready = v1.Ready_READY_UNSPECIFIED
|
||||
case resource.ReadyFalse:
|
||||
r.Ready = v1beta1.Ready_READY_FALSE
|
||||
r.Ready = v1.Ready_READY_FALSE
|
||||
case resource.ReadyTrue:
|
||||
r.Ready = v1beta1.Ready_READY_TRUE
|
||||
r.Ready = v1.Ready_READY_TRUE
|
||||
}
|
||||
rsp.Desired.Resources[string(name)] = r
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Fatal adds a fatal result to the supplied RunFunctionResponse.
|
||||
func Fatal(rsp *v1beta1.RunFunctionResponse, err error) {
|
||||
if rsp.GetResults() == nil {
|
||||
rsp.Results = make([]*v1beta1.Result, 0, 1)
|
||||
}
|
||||
rsp.Results = append(rsp.GetResults(), &v1beta1.Result{
|
||||
Severity: v1beta1.Severity_SEVERITY_FATAL,
|
||||
Message: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
// Warning adds a warning result to the supplied RunFunctionResponse.
|
||||
func Warning(rsp *v1beta1.RunFunctionResponse, err error) {
|
||||
if rsp.GetResults() == nil {
|
||||
rsp.Results = make([]*v1beta1.Result, 0, 1)
|
||||
}
|
||||
rsp.Results = append(rsp.GetResults(), &v1beta1.Result{
|
||||
Severity: v1beta1.Severity_SEVERITY_WARNING,
|
||||
Message: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
// Normal adds a normal result to the supplied RunFunctionResponse.
|
||||
func Normal(rsp *v1beta1.RunFunctionResponse, message string) {
|
||||
if rsp.GetResults() == nil {
|
||||
rsp.Results = make([]*v1beta1.Result, 0, 1)
|
||||
}
|
||||
rsp.Results = append(rsp.GetResults(), &v1beta1.Result{
|
||||
Severity: v1beta1.Severity_SEVERITY_NORMAL,
|
||||
Message: message,
|
||||
})
|
||||
}
|
||||
|
||||
// Normalf adds a normal result to the supplied RunFunctionResponse.
|
||||
func Normalf(rsp *v1beta1.RunFunctionResponse, format string, a ...any) {
|
||||
Normal(rsp, fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
Copyright 2024 The Crossplane Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package response contains utilities for working with RunFunctionResponses.
|
||||
package response
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
v1 "github.com/crossplane/function-sdk-go/proto/v1"
|
||||
)
|
||||
|
||||
// ResultOption allows further customization of the result.
|
||||
type ResultOption struct {
|
||||
result *v1.Result
|
||||
}
|
||||
|
||||
// Fatal adds a fatal result to the supplied RunFunctionResponse.
|
||||
// An event will be created for the Composite Resource.
|
||||
// A fatal result cannot target the claim.
|
||||
func Fatal(rsp *v1.RunFunctionResponse, err error) {
|
||||
newResult(rsp, v1.Severity_SEVERITY_FATAL, err.Error())
|
||||
}
|
||||
|
||||
// Warning adds a warning result to the supplied RunFunctionResponse.
|
||||
// An event will be created for the Composite Resource.
|
||||
func Warning(rsp *v1.RunFunctionResponse, err error) *ResultOption {
|
||||
return newResult(rsp, v1.Severity_SEVERITY_WARNING, err.Error())
|
||||
}
|
||||
|
||||
// Normal adds a normal result to the supplied RunFunctionResponse.
|
||||
// An event will be created for the Composite Resource.
|
||||
func Normal(rsp *v1.RunFunctionResponse, message string) *ResultOption {
|
||||
return newResult(rsp, v1.Severity_SEVERITY_NORMAL, message)
|
||||
}
|
||||
|
||||
// Normalf adds a normal result to the supplied RunFunctionResponse.
|
||||
// An event will be created for the Composite Resource.
|
||||
func Normalf(rsp *v1.RunFunctionResponse, format string, a ...any) *ResultOption {
|
||||
return Normal(rsp, fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
func newResult(rsp *v1.RunFunctionResponse, s v1.Severity, message string) *ResultOption {
|
||||
if rsp.GetResults() == nil {
|
||||
rsp.Results = make([]*v1.Result, 0, 1)
|
||||
}
|
||||
|
||||
r := &v1.Result{
|
||||
Severity: s,
|
||||
Message: message,
|
||||
Target: v1.Target_TARGET_COMPOSITE.Enum(),
|
||||
}
|
||||
rsp.Results = append(rsp.GetResults(), r)
|
||||
|
||||
return &ResultOption{result: r}
|
||||
}
|
||||
|
||||
// TargetComposite updates the result and its event to target the composite
|
||||
// resource.
|
||||
func (o *ResultOption) TargetComposite() *ResultOption {
|
||||
o.result.Target = v1.Target_TARGET_COMPOSITE.Enum()
|
||||
return o
|
||||
}
|
||||
|
||||
// TargetCompositeAndClaim updates the result and its event to target both the
|
||||
// composite resource and claim.
|
||||
func (o *ResultOption) TargetCompositeAndClaim() *ResultOption {
|
||||
o.result.Target = v1.Target_TARGET_COMPOSITE_AND_CLAIM.Enum()
|
||||
return o
|
||||
}
|
||||
|
||||
// WithReason sets the reason field on the result and its event.
|
||||
func (o *ResultOption) WithReason(reason string) *ResultOption {
|
||||
o.result.Reason = &reason
|
||||
return o
|
||||
}
|
|
@ -0,0 +1,190 @@
|
|||
/*
|
||||
Copyright 2023 The Crossplane Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package response_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"google.golang.org/protobuf/testing/protocmp"
|
||||
"k8s.io/utils/ptr"
|
||||
|
||||
v1 "github.com/crossplane/function-sdk-go/proto/v1"
|
||||
"github.com/crossplane/function-sdk-go/response"
|
||||
)
|
||||
|
||||
func TestResult(t *testing.T) {
|
||||
type testFn func(*v1.RunFunctionResponse)
|
||||
type args struct {
|
||||
fns []testFn
|
||||
}
|
||||
type want struct {
|
||||
results []*v1.Result
|
||||
}
|
||||
cases := map[string]struct {
|
||||
reason string
|
||||
args args
|
||||
want want
|
||||
}{
|
||||
"CreateBasicRecords": {
|
||||
reason: "Correctly adds results to the response.",
|
||||
args: args{
|
||||
fns: []testFn{
|
||||
func(rsp *v1.RunFunctionResponse) {
|
||||
response.Normal(rsp, "this is a test normal result")
|
||||
},
|
||||
func(rsp *v1.RunFunctionResponse) {
|
||||
response.Normalf(rsp, "this is a test normal %s result", "formatted")
|
||||
},
|
||||
func(rsp *v1.RunFunctionResponse) {
|
||||
response.Warning(rsp, errors.New("this is a test warning result"))
|
||||
},
|
||||
func(rsp *v1.RunFunctionResponse) {
|
||||
response.Fatal(rsp, errors.New("this is a test fatal result"))
|
||||
},
|
||||
},
|
||||
},
|
||||
want: want{
|
||||
results: []*v1.Result{
|
||||
{
|
||||
Severity: v1.Severity_SEVERITY_NORMAL,
|
||||
Message: "this is a test normal result",
|
||||
Target: v1.Target_TARGET_COMPOSITE.Enum(),
|
||||
},
|
||||
{
|
||||
Severity: v1.Severity_SEVERITY_NORMAL,
|
||||
Message: "this is a test normal formatted result",
|
||||
Target: v1.Target_TARGET_COMPOSITE.Enum(),
|
||||
},
|
||||
{
|
||||
Severity: v1.Severity_SEVERITY_WARNING,
|
||||
Message: "this is a test warning result",
|
||||
Target: v1.Target_TARGET_COMPOSITE.Enum(),
|
||||
},
|
||||
{
|
||||
Severity: v1.Severity_SEVERITY_FATAL,
|
||||
Message: "this is a test fatal result",
|
||||
Target: v1.Target_TARGET_COMPOSITE.Enum(),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"SetTargets": {
|
||||
reason: "Correctly sets targets on result and adds it to the response.",
|
||||
args: args{
|
||||
fns: []testFn{
|
||||
func(rsp *v1.RunFunctionResponse) {
|
||||
response.Warning(rsp, errors.New("this is a test warning result targeting the composite")).TargetComposite()
|
||||
},
|
||||
func(rsp *v1.RunFunctionResponse) {
|
||||
response.Warning(rsp, errors.New("this is a test fatal result targeting both")).TargetCompositeAndClaim()
|
||||
},
|
||||
},
|
||||
},
|
||||
want: want{
|
||||
results: []*v1.Result{
|
||||
{
|
||||
Severity: v1.Severity_SEVERITY_WARNING,
|
||||
Message: "this is a test warning result targeting the composite",
|
||||
Target: v1.Target_TARGET_COMPOSITE.Enum(),
|
||||
},
|
||||
{
|
||||
Severity: v1.Severity_SEVERITY_WARNING,
|
||||
Message: "this is a test fatal result targeting both",
|
||||
Target: v1.Target_TARGET_COMPOSITE_AND_CLAIM.Enum(),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"SetReason": {
|
||||
reason: "Correctly sets reason on result and adds it to the response.",
|
||||
args: args{
|
||||
fns: []testFn{
|
||||
func(rsp *v1.RunFunctionResponse) {
|
||||
response.Normal(rsp, "this is a test normal result targeting the composite").WithReason("TestReason")
|
||||
},
|
||||
func(rsp *v1.RunFunctionResponse) {
|
||||
response.Warning(rsp, errors.New("this is a test warning result targeting the composite")).WithReason("TestReason")
|
||||
},
|
||||
},
|
||||
},
|
||||
want: want{
|
||||
results: []*v1.Result{
|
||||
{
|
||||
Severity: v1.Severity_SEVERITY_NORMAL,
|
||||
Message: "this is a test normal result targeting the composite",
|
||||
Target: v1.Target_TARGET_COMPOSITE.Enum(),
|
||||
Reason: ptr.To("TestReason"),
|
||||
},
|
||||
{
|
||||
Severity: v1.Severity_SEVERITY_WARNING,
|
||||
Message: "this is a test warning result targeting the composite",
|
||||
Target: v1.Target_TARGET_COMPOSITE.Enum(),
|
||||
Reason: ptr.To("TestReason"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"ChainOptions": {
|
||||
reason: "Can chain result options together.",
|
||||
args: args{
|
||||
fns: []testFn{
|
||||
func(rsp *v1.RunFunctionResponse) {
|
||||
response.Normal(rsp, "this is a test normal result targeting the composite and claim").
|
||||
WithReason("TestReason").
|
||||
TargetCompositeAndClaim()
|
||||
},
|
||||
func(rsp *v1.RunFunctionResponse) {
|
||||
response.Warning(rsp, errors.New("this is a test warning result targeting the composite and claim")).
|
||||
TargetCompositeAndClaim().
|
||||
WithReason("TestReason")
|
||||
},
|
||||
},
|
||||
},
|
||||
want: want{
|
||||
results: []*v1.Result{
|
||||
{
|
||||
Severity: v1.Severity_SEVERITY_NORMAL,
|
||||
Message: "this is a test normal result targeting the composite and claim",
|
||||
Target: v1.Target_TARGET_COMPOSITE_AND_CLAIM.Enum(),
|
||||
Reason: ptr.To("TestReason"),
|
||||
},
|
||||
{
|
||||
Severity: v1.Severity_SEVERITY_WARNING,
|
||||
Message: "this is a test warning result targeting the composite and claim",
|
||||
Target: v1.Target_TARGET_COMPOSITE_AND_CLAIM.Enum(),
|
||||
Reason: ptr.To("TestReason"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for name, tc := range cases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
rsp := &v1.RunFunctionResponse{}
|
||||
for _, f := range tc.args.fns {
|
||||
f(rsp)
|
||||
}
|
||||
|
||||
if diff := cmp.Diff(tc.want.results, rsp.GetResults(), protocmp.Transform()); diff != "" {
|
||||
t.Errorf("\n%s\nFrom(...): -want, +got:\n%s", tc.reason, diff)
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
}
|
90
sdk.go
90
sdk.go
|
@ -18,6 +18,7 @@ limitations under the License.
|
|||
package function
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"net"
|
||||
|
@ -29,28 +30,32 @@ import (
|
|||
"google.golang.org/grpc/credentials"
|
||||
ginsecure "google.golang.org/grpc/credentials/insecure"
|
||||
"google.golang.org/grpc/reflection"
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
"github.com/crossplane/function-sdk-go/logging"
|
||||
v1 "github.com/crossplane/function-sdk-go/proto/v1"
|
||||
"github.com/crossplane/function-sdk-go/proto/v1beta1"
|
||||
)
|
||||
|
||||
// Default ServeOptions.
|
||||
const (
|
||||
DefaultNetwork = "tcp"
|
||||
DefaultAddress = ":9443"
|
||||
DefaultNetwork = "tcp"
|
||||
DefaultAddress = ":9443"
|
||||
DefaultMaxRecvMsgSize = 1024 * 1024 * 4
|
||||
)
|
||||
|
||||
// ServeOptions configure how a Function is served.
|
||||
type ServeOptions struct {
|
||||
Network string
|
||||
Address string
|
||||
Credentials credentials.TransportCredentials
|
||||
Network string
|
||||
Address string
|
||||
MaxRecvMsgSize int
|
||||
Credentials credentials.TransportCredentials
|
||||
}
|
||||
|
||||
// A ServeOption configures how a Function is served.
|
||||
type ServeOption func(o *ServeOptions) error
|
||||
|
||||
// Listen configures the network and address on which the Function will
|
||||
// Listen configures the network, address and maximum message size on which the Function will
|
||||
// listen for RunFunctionRequests.
|
||||
func Listen(network, address string) ServeOption {
|
||||
return func(o *ServeOptions) error {
|
||||
|
@ -114,12 +119,22 @@ func Insecure(insecure bool) ServeOption {
|
|||
}
|
||||
}
|
||||
|
||||
// MaxRecvMessageSize returns a ServeOption to set the max message size in bytes the server can receive.
|
||||
// If this is not set, gRPC uses the default limit.
|
||||
func MaxRecvMessageSize(sz int) ServeOption {
|
||||
return func(o *ServeOptions) error {
|
||||
o.MaxRecvMsgSize = sz
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Serve the supplied Function by creating a gRPC server and listening for
|
||||
// RunFunctionRequests. Blocks until the server returns an error.
|
||||
func Serve(fn v1beta1.FunctionRunnerServiceServer, o ...ServeOption) error {
|
||||
func Serve(fn v1.FunctionRunnerServiceServer, o ...ServeOption) error {
|
||||
so := &ServeOptions{
|
||||
Network: DefaultNetwork,
|
||||
Address: DefaultAddress,
|
||||
Network: DefaultNetwork,
|
||||
Address: DefaultAddress,
|
||||
MaxRecvMsgSize: DefaultMaxRecvMsgSize,
|
||||
}
|
||||
|
||||
for _, fn := range o {
|
||||
|
@ -137,9 +152,10 @@ func Serve(fn v1beta1.FunctionRunnerServiceServer, o ...ServeOption) error {
|
|||
return errors.Wrapf(err, "cannot listen for %s connections at address %q", so.Network, so.Address)
|
||||
}
|
||||
|
||||
srv := grpc.NewServer(grpc.Creds(so.Credentials))
|
||||
srv := grpc.NewServer(grpc.MaxRecvMsgSize(so.MaxRecvMsgSize), grpc.Creds(so.Credentials))
|
||||
reflection.Register(srv)
|
||||
v1beta1.RegisterFunctionRunnerServiceServer(srv, fn)
|
||||
v1.RegisterFunctionRunnerServiceServer(srv, fn)
|
||||
v1beta1.RegisterFunctionRunnerServiceServer(srv, ServeBeta(fn))
|
||||
return errors.Wrap(srv.Serve(lis), "cannot serve mTLS gRPC connections")
|
||||
}
|
||||
|
||||
|
@ -147,3 +163,55 @@ func Serve(fn v1beta1.FunctionRunnerServiceServer, o ...ServeOption) error {
|
|||
func NewLogger(debug bool) (logging.Logger, error) {
|
||||
return logging.NewLogger(debug)
|
||||
}
|
||||
|
||||
// A BetaServer is a v1beta1 FunctionRunnerServiceServer that wraps an identical
|
||||
// v1 FunctionRunnerServiceServer. This requires the v1 and v1beta1 protos to be
|
||||
// identical.
|
||||
//
|
||||
// Functions were promoted from v1beta1 to v1 in Crossplane v1.17. Crossplane
|
||||
// v1.16 and earlier only sends v1beta1 RunFunctionRequests. Functions should
|
||||
// use the BetaServer for backward compatibility, to support Crossplane v1.16
|
||||
// and earlier.
|
||||
type BetaServer struct {
|
||||
wrapped v1.FunctionRunnerServiceServer
|
||||
|
||||
v1beta1.UnimplementedFunctionRunnerServiceServer
|
||||
}
|
||||
|
||||
// ServeBeta returns a v1beta1.FunctionRunnerServiceServer that wraps the
|
||||
// suppled v1.FunctionRunnerServiceServer.
|
||||
func ServeBeta(s v1.FunctionRunnerServiceServer) *BetaServer {
|
||||
return &BetaServer{wrapped: s}
|
||||
}
|
||||
|
||||
// RunFunction calls the RunFunction method of the wrapped
|
||||
// v1.FunctionRunnerServiceServer. It converts from v1beta1 to v1 and back by
|
||||
// round-tripping through protobuf marshaling.
|
||||
func (s *BetaServer) RunFunction(ctx context.Context, req *v1beta1.RunFunctionRequest) (*v1beta1.RunFunctionResponse, error) {
|
||||
gareq := &v1.RunFunctionRequest{}
|
||||
|
||||
b, err := proto.Marshal(req)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "cannot marshal v1beta1 RunFunctionRequest to protobuf bytes")
|
||||
}
|
||||
|
||||
if err := proto.Unmarshal(b, gareq); err != nil {
|
||||
return nil, errors.Wrap(err, "cannot unmarshal v1 RunFunctionRequest from v1beta1 protobuf bytes")
|
||||
}
|
||||
|
||||
garsp, err := s.wrapped.RunFunction(ctx, gareq)
|
||||
if err != nil {
|
||||
// This error is intentionally not wrapped. This middleware is just
|
||||
// calling an underlying RunFunction.
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b, err = proto.Marshal(garsp)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "cannot marshal v1beta1 RunFunctionResponse to protobuf bytes")
|
||||
}
|
||||
|
||||
rsp := &v1beta1.RunFunctionResponse{}
|
||||
err = proto.Unmarshal(b, rsp)
|
||||
return rsp, errors.Wrap(err, "cannot unmarshal v1 RunFunctionResponse from v1beta1 protobuf bytes")
|
||||
}
|
||||
|
|
122
sdk_test.go
122
sdk_test.go
|
@ -17,10 +17,17 @@ limitations under the License.
|
|||
package function
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
"google.golang.org/protobuf/encoding/protojson"
|
||||
"google.golang.org/protobuf/testing/protocmp"
|
||||
|
||||
"github.com/crossplane/function-sdk-go/errors"
|
||||
v1 "github.com/crossplane/function-sdk-go/proto/v1"
|
||||
"github.com/crossplane/function-sdk-go/proto/v1beta1"
|
||||
"github.com/crossplane/function-sdk-go/request"
|
||||
"github.com/crossplane/function-sdk-go/resource"
|
||||
|
@ -28,9 +35,11 @@ import (
|
|||
"github.com/crossplane/function-sdk-go/response"
|
||||
)
|
||||
|
||||
var req = &v1beta1.RunFunctionRequest{
|
||||
Observed: &v1beta1.State{
|
||||
Composite: &v1beta1.Resource{
|
||||
var _ v1beta1.FunctionRunnerServiceServer = &BetaServer{}
|
||||
|
||||
var req = &v1.RunFunctionRequest{
|
||||
Observed: &v1.State{
|
||||
Composite: &v1.Resource{
|
||||
Resource: resource.MustStructJSON(`{"spec":{"widgets":9001}}`),
|
||||
},
|
||||
},
|
||||
|
@ -61,7 +70,7 @@ func Example() {
|
|||
desired["new"].Resource.SetInteger("spec.widgets", widgets)
|
||||
|
||||
// Create a desired composed resource using structured data.
|
||||
// db, _ := composed.From(&v1beta1.Instance{})
|
||||
// db, _ := composed.From(&v1.Instance{})
|
||||
// desired["database"] = &resource.DesiredComposed{Resource: db}
|
||||
|
||||
// Add a label to our new desired resource, and any other.
|
||||
|
@ -70,11 +79,112 @@ func Example() {
|
|||
}
|
||||
|
||||
// Set our updated desired composed resource in the response we'll return.
|
||||
_ = response.SetDesiredComposedResources(rsp, desired)
|
||||
if err := response.SetDesiredComposedResources(rsp, desired); err != nil {
|
||||
// You can set a custom status condition on the claim. This allows you to
|
||||
// communicate with the user. See the link below for status condition
|
||||
// guidance.
|
||||
// https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties
|
||||
response.ConditionFalse(rsp, "FunctionSuccess", "InternalError").
|
||||
WithMessage("Something went wrong.").
|
||||
TargetCompositeAndClaim()
|
||||
|
||||
// You can emit an event regarding the claim. This allows you to communicate
|
||||
// with the user. Note that events should be used sparingly and are subject
|
||||
// to throttling; see the issue below for more information.
|
||||
// https://github.com/crossplane/crossplane/issues/5802
|
||||
response.Warning(rsp, errors.New("something went wrong")).
|
||||
TargetCompositeAndClaim()
|
||||
} else {
|
||||
response.ConditionTrue(rsp, "FunctionSuccess", "Success").
|
||||
TargetCompositeAndClaim()
|
||||
}
|
||||
|
||||
j, _ := protojson.Marshal(rsp)
|
||||
fmt.Println(string(j))
|
||||
|
||||
// Output:
|
||||
// {"meta":{"ttl":"60s"},"desired":{"resources":{"new":{"resource":{"apiVersion":"example.org/v1","kind":"CoolResource","metadata":{"labels":{"coolness":"high"}},"spec":{"widgets":9001}}}}}}
|
||||
// {"meta":{"ttl":"60s"},"desired":{"resources":{"new":{"resource":{"apiVersion":"example.org/v1","kind":"CoolResource","metadata":{"labels":{"coolness":"high"}},"spec":{"widgets":9001}}}}},"conditions":[{"type":"FunctionSuccess","status":"STATUS_CONDITION_TRUE","reason":"Success","target":"TARGET_COMPOSITE_AND_CLAIM"}]}
|
||||
}
|
||||
|
||||
func TestBetaServer(t *testing.T) {
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
req *v1beta1.RunFunctionRequest
|
||||
}
|
||||
type want struct {
|
||||
rsp *v1beta1.RunFunctionResponse
|
||||
err error
|
||||
}
|
||||
|
||||
cases := map[string]struct {
|
||||
reason string
|
||||
wrapped v1.FunctionRunnerServiceServer
|
||||
args args
|
||||
want want
|
||||
}{
|
||||
"RunFunctionError": {
|
||||
reason: "We should return any error the wrapped server encounters",
|
||||
wrapped: &MockFunctionServer{err: errors.New("boom")},
|
||||
args: args{
|
||||
req: &v1beta1.RunFunctionRequest{
|
||||
Meta: &v1beta1.RequestMeta{
|
||||
Tag: "hi",
|
||||
},
|
||||
},
|
||||
},
|
||||
want: want{
|
||||
err: cmpopts.AnyError,
|
||||
},
|
||||
},
|
||||
"Success": {
|
||||
reason: "We should return the response the wrapped server returns",
|
||||
wrapped: &MockFunctionServer{
|
||||
rsp: &v1.RunFunctionResponse{
|
||||
Meta: &v1.ResponseMeta{
|
||||
Tag: "hello",
|
||||
},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
req: &v1beta1.RunFunctionRequest{
|
||||
Meta: &v1beta1.RequestMeta{
|
||||
Tag: "hi",
|
||||
},
|
||||
},
|
||||
},
|
||||
want: want{
|
||||
rsp: &v1beta1.RunFunctionResponse{
|
||||
Meta: &v1beta1.ResponseMeta{
|
||||
Tag: "hello",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range cases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
s := ServeBeta(tc.wrapped)
|
||||
rsp, err := s.RunFunction(tc.args.ctx, tc.args.req)
|
||||
|
||||
if diff := cmp.Diff(tc.want.rsp, rsp, protocmp.Transform()); diff != "" {
|
||||
t.Errorf("\n%s\ns.RunFunction(...): -want rsp, +got rsp:\n%s", tc.reason, diff)
|
||||
}
|
||||
if diff := cmp.Diff(tc.want.err, err, cmpopts.EquateErrors()); diff != "" {
|
||||
t.Errorf("\n%s\ns.RunFunction(...): -want err, +got err:\n%s", tc.reason, diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
type MockFunctionServer struct {
|
||||
v1.UnimplementedFunctionRunnerServiceServer
|
||||
|
||||
rsp *v1.RunFunctionResponse
|
||||
err error
|
||||
}
|
||||
|
||||
func (s *MockFunctionServer) RunFunction(context.Context, *v1.RunFunctionRequest) (*v1.RunFunctionResponse, error) {
|
||||
return s.rsp, s.err
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue