Merge pull request #91 from negz/hatchery

Update hatch, and use a more illustrative example
This commit is contained in:
Nic Cope 2024-10-09 21:47:40 -07:00 committed by GitHub
commit bef4c0459f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 56 additions and 42 deletions

View File

@ -14,7 +14,8 @@ on:
env: env:
# Common versions # Common versions
PYTHON_VERSION: '3.11.5' PYTHON_VERSION: '3.11'
HATCH_VERSION: '1.12.0'
DOCKER_BUILDX_VERSION: 'v0.11.2' DOCKER_BUILDX_VERSION: 'v0.11.2'
# These environment variables are important to the Crossplane CLI install.sh # These environment variables are important to the Crossplane CLI install.sh
@ -47,10 +48,10 @@ jobs:
python-version: ${{ env.PYTHON_VERSION }} python-version: ${{ env.PYTHON_VERSION }}
- name: Setup Hatch - name: Setup Hatch
run: pipx install hatch==1.7.0 run: pipx install hatch==${{ env.HATCH_VERSION }}
- name: Lint - name: Lint
run: hatch run lint:check run: hatch fmt
unit-test: unit-test:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
@ -64,10 +65,10 @@ jobs:
python-version: ${{ env.PYTHON_VERSION }} python-version: ${{ env.PYTHON_VERSION }}
- name: Setup Hatch - name: Setup Hatch
run: pipx install hatch==1.7.0 run: pipx install hatch==${{ env.HATCH_VERSION }}
- name: Run Unit Tests - name: Run Unit Tests
run: hatch run test:unit run: hatch test --all --randomize
# We want to build most packages for the amd64 and arm64 architectures. To # We want to build most packages for the amd64 and arm64 architectures. To
# speed this up we build single-platform packages in parallel. We then upload # speed this up we build single-platform packages in parallel. We then upload

View File

@ -25,11 +25,11 @@ CLI][cli] to build functions.
# Run the code in development mode, for crossplane beta render # Run the code in development mode, for crossplane beta render
hatch run development hatch run development
# Lint the code - see pyproject.toml # Lint and format the code - see pyproject.toml
hatch run lint:check hatch fmt
# Run unit tests - see tests/test_fn.py # Run unit tests - see tests/test_fn.py
hatch run test:unit hatch test
# Build the function's runtime image - see Dockerfile # Build the function's runtime image - see Dockerfile
$ docker build . --tag=runtime $ docker build . --tag=runtime

View File

@ -14,4 +14,4 @@ spec:
input: input:
apiVersion: template.fn.crossplane.io/v1beta1 apiVersion: template.fn.crossplane.io/v1beta1
kind: Input kind: Input
example: "Hello world" version: v1beta2

View File

@ -1,7 +1,7 @@
"""A Crossplane composition function.""" """A Crossplane composition function."""
import grpc import grpc
from crossplane.function import logging, response from crossplane.function import logging, resource, response
from crossplane.function.proto.v1 import run_function_pb2 as fnv1 from crossplane.function.proto.v1 import run_function_pb2 as fnv1
from crossplane.function.proto.v1 import run_function_pb2_grpc as grpcv1 from crossplane.function.proto.v1 import run_function_pb2_grpc as grpcv1
@ -22,12 +22,18 @@ class FunctionRunner(grpcv1.FunctionRunnerService):
rsp = response.to(req) rsp = response.to(req)
example = "" version = req.input["version"]
if "example" in req.input: region = req.observed.composite.resource["spec"]["region"]
example = req.input["example"]
# TODO: Add your function logic here! resource.update(
response.normal(rsp, f"I was run with input {example}!") rsp.desired.resources["bucket"],
log.info("I was run!", input=example) {
"apiVersion": f"s3.aws.upbound.io/{version}",
"kind": "Bucket",
"spec": {
"forProvider": {"region": region},
},
},
)
return rsp return rsp

View File

@ -24,9 +24,8 @@ spec:
of an object. Servers should convert recognized schemas to the latest of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string type: string
example: version:
description: Example is an example field. Replace it with whatever input description: The bucket version to compose (e.g. v1beta2).
you need. :)
type: string type: string
kind: kind:
description: 'Kind is a string value representing the REST resource this description: 'Kind is a string value representing the REST resource this
@ -36,7 +35,7 @@ spec:
metadata: metadata:
type: object type: object
required: required:
- example - version
type: object type: object
served: true served: true
storage: true storage: true

View File

@ -48,21 +48,10 @@ dependencies = ["ipython==8.28.0"]
[tool.hatch.envs.default.scripts] [tool.hatch.envs.default.scripts]
development = "python function/main.py --insecure --debug" development = "python function/main.py --insecure --debug"
[tool.hatch.envs.lint] # This special environment is used by hatch fmt.
type = "virtual" [tool.hatch.envs.hatch-static-analysis]
detached = true
path = ".venv-lint"
dependencies = ["ruff==0.6.9"] dependencies = ["ruff==0.6.9"]
config-path = "none" # Disable Hatch's default Ruff config.
[tool.hatch.envs.lint.scripts]
check = "ruff check function tests && ruff format --diff function tests"
[tool.hatch.envs.test]
type = "virtual"
path = ".venv-test"
[tool.hatch.envs.test.scripts]
unit = "python -m unittest tests/*.py"
[tool.ruff] [tool.ruff]
target-version = "py311" target-version = "py311"

View File

@ -28,17 +28,36 @@ class TestFunctionRunner(unittest.IsolatedAsyncioTestCase):
TestCase( TestCase(
reason="The function should return the input as a result.", reason="The function should return the input as a result.",
req=fnv1.RunFunctionRequest( req=fnv1.RunFunctionRequest(
input=resource.dict_to_struct({"example": "Hello, world"}) input=resource.dict_to_struct({"version": "v1beta2"}),
observed=fnv1.State(
composite=fnv1.Resource(
resource=resource.dict_to_struct(
{
"apiVersion": "example.crossplane.io/v1",
"kind": "XR",
"spec": {"region": "us-west-2"},
}
),
),
),
), ),
want=fnv1.RunFunctionResponse( want=fnv1.RunFunctionResponse(
meta=fnv1.ResponseMeta(ttl=durationpb.Duration(seconds=60)), meta=fnv1.ResponseMeta(ttl=durationpb.Duration(seconds=60)),
desired=fnv1.State(), desired=fnv1.State(
results=[ resources={
fnv1.Result( "bucket": fnv1.Resource(
severity=fnv1.SEVERITY_NORMAL, resource=resource.dict_to_struct(
message="I was run with input Hello, world!", {
) "apiVersion": "s3.aws.upbound.io/v1beta2",
], "kind": "Bucket",
"spec": {
"forProvider": {"region": "us-west-2"},
},
}
),
),
},
),
context=structpb.Struct(), context=structpb.Struct(),
), ),
), ),