From 349877ddf967f49c357c35a476e86dadb17cad45 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 17 Jul 2025 23:54:41 +0000 Subject: [PATCH 01/11] chore(deps): update dependency ruff to v0.12.4 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 6b2e071..cbfc76f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -66,7 +66,7 @@ packages = ["crossplane"] # This special environment is used by hatch fmt. [tool.hatch.envs.hatch-static-analysis] -dependencies = ["ruff==0.12.3"] +dependencies = ["ruff==0.12.4"] config-path = "none" # Disable Hatch's default Ruff config. [tool.ruff] From 5700d4e17b02eb6922656886c9ab44a1882ac3de Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 24 Jul 2025 16:54:19 +0000 Subject: [PATCH 02/11] chore(deps): update dependency ruff to v0.12.5 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index cbfc76f..204fa37 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -66,7 +66,7 @@ packages = ["crossplane"] # This special environment is used by hatch fmt. [tool.hatch.envs.hatch-static-analysis] -dependencies = ["ruff==0.12.4"] +dependencies = ["ruff==0.12.5"] config-path = "none" # Disable Hatch's default Ruff config. [tool.ruff] From 8545053f1946b7e26fcae00b74ecc966242882b4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 24 Jul 2025 21:59:12 +0000 Subject: [PATCH 03/11] chore(deps): update dependency grpcio-tools to v1.74.0 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 204fa37..e9ba81d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -46,7 +46,7 @@ type = "virtual" detached = true path = ".venv-generate" dependencies = [ - "grpcio-tools==1.73.1", + "grpcio-tools==1.74.0", "protobuf==6.31.1", ] From bdde6992f3a9f20c82d9619b0d6a440379a85e9f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 24 Jul 2025 21:59:15 +0000 Subject: [PATCH 04/11] fix(deps): update dependency grpcio to v1.74.0 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 204fa37..83d6c3c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,7 +18,7 @@ classifiers = [ ] dependencies = [ - "grpcio==1.73.1", + "grpcio==1.74.0", "grpcio-reflection==1.*", "protobuf==6.31.1", # Must be compatible with grpcio-tools. "pydantic==2.*", From 0551df7922b83763012b076ff69f3196596c91ce Mon Sep 17 00:00:00 2001 From: Nic Cope Date: Fri, 18 Jul 2025 17:04:35 -0700 Subject: [PATCH 05/11] Add operation protos from c/c Signed-off-by: Nic Cope --- .../function/proto/v1/run_function.proto | 238 +++++++++-------- .../function/proto/v1/run_function_pb2.py | 122 ++++----- .../function/proto/v1/run_function_pb2.pyi | 39 +-- .../proto/v1/run_function_pb2_grpc.py | 10 +- .../function/proto/v1beta1/run_function.proto | 242 ++++++++++-------- .../proto/v1beta1/run_function_pb2.py | 122 ++++----- .../proto/v1beta1/run_function_pb2.pyi | 39 +-- .../proto/v1beta1/run_function_pb2_grpc.py | 10 +- 8 files changed, 442 insertions(+), 380 deletions(-) diff --git a/crossplane/function/proto/v1/run_function.proto b/crossplane/function/proto/v1/run_function.proto index b66e970..b67c085 100644 --- a/crossplane/function/proto/v1/run_function.proto +++ b/crossplane/function/proto/v1/run_function.proto @@ -1,80 +1,86 @@ /* -Copyright 2022 The Crossplane Authors. + 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 + 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 + 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. + 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"; -import "google/protobuf/struct.proto"; -import "google/protobuf/duration.proto"; +// This package defines the RPC for both composition and operation functions. +// Only composition functions are part of the 'apiextensions' API group. In +// retrospect this package should've been crossplane.proto.fn.v1, but it's too +// late to change it now. +//buf:lint:ignore PACKAGE_DIRECTORY_MATCH package apiextensions.fn.proto.v1; -option go_package = "github.com/crossplane/crossplane/apis/apiextensions/fn/proto/v1"; +import "google/protobuf/duration.proto"; +import "google/protobuf/struct.proto"; -// A FunctionRunnerService is a Composition Function. +option go_package = "github.com/crossplane/crossplane/proto/fn/v1"; + +// A FunctionRunnerService is a function. service FunctionRunnerService { - // RunFunction runs the Composition Function. + // RunFunction runs the function. rpc RunFunction(RunFunctionRequest) returns (RunFunctionResponse) {} } -// A RunFunctionRequest requests that the Composition Function be run. +// A RunFunctionRequest requests that the 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. + // 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 + // 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 + // 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 input specific to this function invocation. A JSON representation + // of the 'input' block of the relevant entry in a function pipeline. optional google.protobuf.Struct input = 4; - // Optional context. Crossplane may pass arbitary 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 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 extra_resources = 6; + // Optional resources that the function specified in its requirements. Note + // that resources is a map to Resources, plural. The map key corresponds to + // the key in a RunFunctionResponse's requirements.resources field. If a + // function requested required 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 required_resources = 6; - // Optional credentials that this Function may use to communicate with an + // Optional credentials that this function may use to communicate with an // external system. - map credentials = 7; + map credentials = 7; } -// Credentials that a Function may use to communicate with an external system. +// Credentials that a function may use to communicate with an external system. message Credentials { // Source of the credentials. oneof source { @@ -93,52 +99,58 @@ message Resources { repeated Resource items = 1; } -// A RunFunctionResponse contains the result of a Composition Function run. +// A RunFunctionResponse contains the result of a function run. message RunFunctionResponse { // Metadata pertaining to this response. ResponseMeta meta = 1; - // Desired state according to a Function pipeline. Functions may add desired + // 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 + // 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 + // 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. + // 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 + // 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 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. + // Status conditions to be applied to the XR. Conditions may also optionally + // be applied to the XR's associated claim. + // + // Conditions are only used for composition. They're ignored by Operations. repeated Condition conditions = 6; + + // Optional output specific to this function invocation. + // + // Only Operations use function output. XRs will discard any function output. + optional google.protobuf.Struct output = 7; } // RequestMeta contains metadata pertaining to a RunFunctionRequest. message RequestMeta { - // An opaque string identifying the content of the request. Two identical - // requests should have the same tag. + // 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. +// 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 extra_resources = 1; + // Resources that this function requires. The map key uniquely identifies the + // group of resources. + map resources = 1; } // ResourceSelector selects a group of resources, either by name or by label. @@ -157,6 +169,11 @@ message ResourceSelector { // 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. @@ -170,77 +187,86 @@ message ResponseMeta { // meta.tag of the corresponding RunFunctionRequest. string tag = 1; - // Time-to-live of this response. Deterministic Functions with no side-effects - // (e.g. simple templating Functions) may specify a TTL. Crossplane may choose - // to cache responses until the TTL expires. + // 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. +// State of the XR (XR) and any resources. message State { - // The state of the composite resource (XR). + // The state of the XR (XR). Resource composite = 1; - // The state of any composed resources. + // The state of any other resources. In composition functions these are the + // composed resources. In operation functions they're arbitrary resources that + // the operation wants to create or update. map resources = 2; } -// A Resource represents the state of a composite or composed resource. +// A Resource represents the state of a Kubernetes 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. + // 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 should set this field in a RunFunctionRequest to communicate + // the desired state of the 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 only specify the desired status of a XR - not its metadata + // or spec. A function should not return desired metadata or spec for a XR. + // 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. + // * A function may not specify the desired status of any other resource - + // e.g. composed resources. It may only specify their metadata and spec. + // Status 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. + // 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 set this field in a RunFunctionResponse to indicate the + // desired connection details of the XR. // - // * A Function should not set this field in a RunFunctionResponse to indicate - // the desired connection details of a composed resource. This will be - // ignored. + // * A function should not set this field in a RunFunctionResponse to indicate + // the desired connection details of a composed resource. This will be + // ignored. + // + // Connection details are only used for composition. They're ignored by + // Operations. map 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 resource is ready. + // + // * A function should set this field to READY_TRUE in a RunFunctionResponse + // to indicate that a desired XR 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. // - // * A Function should not set this field in a RunFunctionResponse to indicate - // that the desired composite resource is ready. This will be ignored. + // Ready is only used for composition. It's ignored by Operations. Ready ready = 3; } -// Ready indicates whether a composed resource should be considered ready. +// Ready indicates whether a resource should be considered ready. enum Ready { READY_UNSPECIFIED = 0; - // True means the composed resource has been observed to be ready. + // True means the resource has been observed to be ready. READY_TRUE = 1; - // False means the composed resource has not been observed to be ready. + // False means the resource has not been observed to be ready. READY_FALSE = 2; } -// A Result of running a Function. +// A Result of running a function. message Result { // Severity of this result. Severity severity = 1; @@ -256,42 +282,42 @@ message Result { optional Target target = 4; } -// Severity of Function results. +// 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. + // Fatal results are fatal; subsequent functions may run, but the 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. + // Warning results are non-fatal; the entire pipeline will run to completion + // but warning events and debug logs associated with the XR or Operation will + // be emitted. SEVERITY_WARNING = 2; - // Normal results are emitted as normal events and debug logs associated - // with the composite resource. + // Normal results are emitted as normal events and debug logs associated with + // the XR or operation. SEVERITY_NORMAL = 3; } -// Target of Function results and conditions. +// Target of function results and conditions. enum Target { - // If the target is unspecified, the result targets the composite resource. + // If the target is unspecified, the result targets the XR. TARGET_UNSPECIFIED = 0; - // Target the composite resource. Results that target the composite resource - // should include detailed, advanced information. + // Target the XR. Results that target the XR 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 the XR and the claim. Results that target the XR 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 +// Status condition to be applied to the XR. Condition may also optionally be +// applied to the XR'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. diff --git a/crossplane/function/proto/v1/run_function_pb2.py b/crossplane/function/proto/v1/run_function_pb2.py index 8a3947d..18336c7 100644 --- a/crossplane/function/proto/v1/run_function_pb2.py +++ b/crossplane/function/proto/v1/run_function_pb2.py @@ -2,7 +2,7 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! # NO CHECKED-IN PROTOBUF GENCODE # source: crossplane/function/proto/v1/run_function.proto -# Protobuf Python Version: 5.29.0 +# Protobuf Python Version: 6.31.0 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool @@ -11,8 +11,8 @@ from google.protobuf.internal import builder as _builder _runtime_version.ValidateProtobufRuntimeVersion( _runtime_version.Domain.PUBLIC, - 5, - 29, + 6, + 31, 0, '', 'crossplane/function/proto/v1/run_function.proto' @@ -22,82 +22,82 @@ _sym_db = _symbol_database.Default() -from google.protobuf import struct_pb2 as google_dot_protobuf_dot_struct__pb2 from google.protobuf import duration_pb2 as google_dot_protobuf_dot_duration__pb2 +from google.protobuf import struct_pb2 as google_dot_protobuf_dot_struct__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n/crossplane/function/proto/v1/run_function.proto\x12\x19\x61piextensions.fn.proto.v1\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1egoogle/protobuf/duration.proto\"\x8d\x05\n\x12RunFunctionRequest\x12\x34\n\x04meta\x18\x01 \x01(\x0b\x32&.apiextensions.fn.proto.v1.RequestMeta\x12\x32\n\x08observed\x18\x02 \x01(\x0b\x32 .apiextensions.fn.proto.v1.State\x12\x31\n\x07\x64\x65sired\x18\x03 \x01(\x0b\x32 .apiextensions.fn.proto.v1.State\x12+\n\x05input\x18\x04 \x01(\x0b\x32\x17.google.protobuf.StructH\x00\x88\x01\x01\x12-\n\x07\x63ontext\x18\x05 \x01(\x0b\x32\x17.google.protobuf.StructH\x01\x88\x01\x01\x12Z\n\x0f\x65xtra_resources\x18\x06 \x03(\x0b\x32\x41.apiextensions.fn.proto.v1.RunFunctionRequest.ExtraResourcesEntry\x12S\n\x0b\x63redentials\x18\x07 \x03(\x0b\x32>.apiextensions.fn.proto.v1.RunFunctionRequest.CredentialsEntry\x1a[\n\x13\x45xtraResourcesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x33\n\x05value\x18\x02 \x01(\x0b\x32$.apiextensions.fn.proto.v1.Resources:\x02\x38\x01\x1aZ\n\x10\x43redentialsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x35\n\x05value\x18\x02 \x01(\x0b\x32&.apiextensions.fn.proto.v1.Credentials:\x02\x38\x01\x42\x08\n\x06_inputB\n\n\x08_context\"]\n\x0b\x43redentials\x12\x44\n\x0f\x63redential_data\x18\x01 \x01(\x0b\x32).apiextensions.fn.proto.v1.CredentialDataH\x00\x42\x08\n\x06source\"\x80\x01\n\x0e\x43redentialData\x12\x41\n\x04\x64\x61ta\x18\x01 \x03(\x0b\x32\x33.apiextensions.fn.proto.v1.CredentialData.DataEntry\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\"?\n\tResources\x12\x32\n\x05items\x18\x01 \x03(\x0b\x32#.apiextensions.fn.proto.v1.Resource\"\xe7\x02\n\x13RunFunctionResponse\x12\x35\n\x04meta\x18\x01 \x01(\x0b\x32\'.apiextensions.fn.proto.v1.ResponseMeta\x12\x31\n\x07\x64\x65sired\x18\x02 \x01(\x0b\x32 .apiextensions.fn.proto.v1.State\x12\x32\n\x07results\x18\x03 \x03(\x0b\x32!.apiextensions.fn.proto.v1.Result\x12-\n\x07\x63ontext\x18\x04 \x01(\x0b\x32\x17.google.protobuf.StructH\x00\x88\x01\x01\x12=\n\x0crequirements\x18\x05 \x01(\x0b\x32\'.apiextensions.fn.proto.v1.Requirements\x12\x38\n\nconditions\x18\x06 \x03(\x0b\x32$.apiextensions.fn.proto.v1.ConditionB\n\n\x08_context\"\x1a\n\x0bRequestMeta\x12\x0b\n\x03tag\x18\x01 \x01(\t\"\xc8\x01\n\x0cRequirements\x12T\n\x0f\x65xtra_resources\x18\x01 \x03(\x0b\x32;.apiextensions.fn.proto.v1.Requirements.ExtraResourcesEntry\x1a\x62\n\x13\x45xtraResourcesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12:\n\x05value\x18\x02 \x01(\x0b\x32+.apiextensions.fn.proto.v1.ResourceSelector:\x02\x38\x01\"\x94\x01\n\x10ResourceSelector\x12\x13\n\x0b\x61pi_version\x18\x01 \x01(\t\x12\x0c\n\x04kind\x18\x02 \x01(\t\x12\x14\n\nmatch_name\x18\x03 \x01(\tH\x00\x12>\n\x0cmatch_labels\x18\x04 \x01(\x0b\x32&.apiextensions.fn.proto.v1.MatchLabelsH\x00\x42\x07\n\x05match\"\x80\x01\n\x0bMatchLabels\x12\x42\n\x06labels\x18\x01 \x03(\x0b\x32\x32.apiextensions.fn.proto.v1.MatchLabels.LabelsEntry\x1a-\n\x0bLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"P\n\x0cResponseMeta\x12\x0b\n\x03tag\x18\x01 \x01(\t\x12+\n\x03ttl\x18\x02 \x01(\x0b\x32\x19.google.protobuf.DurationH\x00\x88\x01\x01\x42\x06\n\x04_ttl\"\xda\x01\n\x05State\x12\x36\n\tcomposite\x18\x01 \x01(\x0b\x32#.apiextensions.fn.proto.v1.Resource\x12\x42\n\tresources\x18\x02 \x03(\x0b\x32/.apiextensions.fn.proto.v1.State.ResourcesEntry\x1aU\n\x0eResourcesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x32\n\x05value\x18\x02 \x01(\x0b\x32#.apiextensions.fn.proto.v1.Resource:\x02\x38\x01\"\xf8\x01\n\x08Resource\x12)\n\x08resource\x18\x01 \x01(\x0b\x32\x17.google.protobuf.Struct\x12V\n\x12\x63onnection_details\x18\x02 \x03(\x0b\x32:.apiextensions.fn.proto.v1.Resource.ConnectionDetailsEntry\x12/\n\x05ready\x18\x03 \x01(\x0e\x32 .apiextensions.fn.proto.v1.Ready\x1a\x38\n\x16\x43onnectionDetailsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\"\xb3\x01\n\x06Result\x12\x35\n\x08severity\x18\x01 \x01(\x0e\x32#.apiextensions.fn.proto.v1.Severity\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x13\n\x06reason\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x36\n\x06target\x18\x04 \x01(\x0e\x32!.apiextensions.fn.proto.v1.TargetH\x01\x88\x01\x01\x42\t\n\x07_reasonB\t\n\x07_target\"\xc1\x01\n\tCondition\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x31\n\x06status\x18\x02 \x01(\x0e\x32!.apiextensions.fn.proto.v1.Status\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x14\n\x07message\x18\x04 \x01(\tH\x00\x88\x01\x01\x12\x36\n\x06target\x18\x05 \x01(\x0e\x32!.apiextensions.fn.proto.v1.TargetH\x01\x88\x01\x01\x42\n\n\x08_messageB\t\n\x07_target*?\n\x05Ready\x12\x15\n\x11READY_UNSPECIFIED\x10\x00\x12\x0e\n\nREADY_TRUE\x10\x01\x12\x0f\n\x0bREADY_FALSE\x10\x02*c\n\x08Severity\x12\x18\n\x14SEVERITY_UNSPECIFIED\x10\x00\x12\x12\n\x0eSEVERITY_FATAL\x10\x01\x12\x14\n\x10SEVERITY_WARNING\x10\x02\x12\x13\n\x0fSEVERITY_NORMAL\x10\x03*V\n\x06Target\x12\x16\n\x12TARGET_UNSPECIFIED\x10\x00\x12\x14\n\x10TARGET_COMPOSITE\x10\x01\x12\x1e\n\x1aTARGET_COMPOSITE_AND_CLAIM\x10\x02*\x7f\n\x06Status\x12 \n\x1cSTATUS_CONDITION_UNSPECIFIED\x10\x00\x12\x1c\n\x18STATUS_CONDITION_UNKNOWN\x10\x01\x12\x19\n\x15STATUS_CONDITION_TRUE\x10\x02\x12\x1a\n\x16STATUS_CONDITION_FALSE\x10\x03\x32\x87\x01\n\x15\x46unctionRunnerService\x12n\n\x0bRunFunction\x12-.apiextensions.fn.proto.v1.RunFunctionRequest\x1a..apiextensions.fn.proto.v1.RunFunctionResponse\"\x00\x42\x41Z?github.com/crossplane/crossplane/apis/apiextensions/fn/proto/v1b\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n/crossplane/function/proto/v1/run_function.proto\x12\x19\x61piextensions.fn.proto.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1cgoogle/protobuf/struct.proto\"\x96\x05\n\x12RunFunctionRequest\x12\x34\n\x04meta\x18\x01 \x01(\x0b\x32&.apiextensions.fn.proto.v1.RequestMeta\x12\x32\n\x08observed\x18\x02 \x01(\x0b\x32 .apiextensions.fn.proto.v1.State\x12\x31\n\x07\x64\x65sired\x18\x03 \x01(\x0b\x32 .apiextensions.fn.proto.v1.State\x12+\n\x05input\x18\x04 \x01(\x0b\x32\x17.google.protobuf.StructH\x00\x88\x01\x01\x12-\n\x07\x63ontext\x18\x05 \x01(\x0b\x32\x17.google.protobuf.StructH\x01\x88\x01\x01\x12`\n\x12required_resources\x18\x06 \x03(\x0b\x32\x44.apiextensions.fn.proto.v1.RunFunctionRequest.RequiredResourcesEntry\x12S\n\x0b\x63redentials\x18\x07 \x03(\x0b\x32>.apiextensions.fn.proto.v1.RunFunctionRequest.CredentialsEntry\x1a^\n\x16RequiredResourcesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x33\n\x05value\x18\x02 \x01(\x0b\x32$.apiextensions.fn.proto.v1.Resources:\x02\x38\x01\x1aZ\n\x10\x43redentialsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x35\n\x05value\x18\x02 \x01(\x0b\x32&.apiextensions.fn.proto.v1.Credentials:\x02\x38\x01\x42\x08\n\x06_inputB\n\n\x08_context\"]\n\x0b\x43redentials\x12\x44\n\x0f\x63redential_data\x18\x01 \x01(\x0b\x32).apiextensions.fn.proto.v1.CredentialDataH\x00\x42\x08\n\x06source\"\x80\x01\n\x0e\x43redentialData\x12\x41\n\x04\x64\x61ta\x18\x01 \x03(\x0b\x32\x33.apiextensions.fn.proto.v1.CredentialData.DataEntry\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\"?\n\tResources\x12\x32\n\x05items\x18\x01 \x03(\x0b\x32#.apiextensions.fn.proto.v1.Resource\"\xa0\x03\n\x13RunFunctionResponse\x12\x35\n\x04meta\x18\x01 \x01(\x0b\x32\'.apiextensions.fn.proto.v1.ResponseMeta\x12\x31\n\x07\x64\x65sired\x18\x02 \x01(\x0b\x32 .apiextensions.fn.proto.v1.State\x12\x32\n\x07results\x18\x03 \x03(\x0b\x32!.apiextensions.fn.proto.v1.Result\x12-\n\x07\x63ontext\x18\x04 \x01(\x0b\x32\x17.google.protobuf.StructH\x00\x88\x01\x01\x12=\n\x0crequirements\x18\x05 \x01(\x0b\x32\'.apiextensions.fn.proto.v1.Requirements\x12\x38\n\nconditions\x18\x06 \x03(\x0b\x32$.apiextensions.fn.proto.v1.Condition\x12,\n\x06output\x18\x07 \x01(\x0b\x32\x17.google.protobuf.StructH\x01\x88\x01\x01\x42\n\n\x08_contextB\t\n\x07_output\"\x1a\n\x0bRequestMeta\x12\x0b\n\x03tag\x18\x01 \x01(\t\"\xb8\x01\n\x0cRequirements\x12I\n\tresources\x18\x01 \x03(\x0b\x32\x36.apiextensions.fn.proto.v1.Requirements.ResourcesEntry\x1a]\n\x0eResourcesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12:\n\x05value\x18\x02 \x01(\x0b\x32+.apiextensions.fn.proto.v1.ResourceSelector:\x02\x38\x01\"\xba\x01\n\x10ResourceSelector\x12\x13\n\x0b\x61pi_version\x18\x01 \x01(\t\x12\x0c\n\x04kind\x18\x02 \x01(\t\x12\x14\n\nmatch_name\x18\x03 \x01(\tH\x00\x12>\n\x0cmatch_labels\x18\x04 \x01(\x0b\x32&.apiextensions.fn.proto.v1.MatchLabelsH\x00\x12\x16\n\tnamespace\x18\x05 \x01(\tH\x01\x88\x01\x01\x42\x07\n\x05matchB\x0c\n\n_namespace\"\x80\x01\n\x0bMatchLabels\x12\x42\n\x06labels\x18\x01 \x03(\x0b\x32\x32.apiextensions.fn.proto.v1.MatchLabels.LabelsEntry\x1a-\n\x0bLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"P\n\x0cResponseMeta\x12\x0b\n\x03tag\x18\x01 \x01(\t\x12+\n\x03ttl\x18\x02 \x01(\x0b\x32\x19.google.protobuf.DurationH\x00\x88\x01\x01\x42\x06\n\x04_ttl\"\xda\x01\n\x05State\x12\x36\n\tcomposite\x18\x01 \x01(\x0b\x32#.apiextensions.fn.proto.v1.Resource\x12\x42\n\tresources\x18\x02 \x03(\x0b\x32/.apiextensions.fn.proto.v1.State.ResourcesEntry\x1aU\n\x0eResourcesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x32\n\x05value\x18\x02 \x01(\x0b\x32#.apiextensions.fn.proto.v1.Resource:\x02\x38\x01\"\xf8\x01\n\x08Resource\x12)\n\x08resource\x18\x01 \x01(\x0b\x32\x17.google.protobuf.Struct\x12V\n\x12\x63onnection_details\x18\x02 \x03(\x0b\x32:.apiextensions.fn.proto.v1.Resource.ConnectionDetailsEntry\x12/\n\x05ready\x18\x03 \x01(\x0e\x32 .apiextensions.fn.proto.v1.Ready\x1a\x38\n\x16\x43onnectionDetailsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\"\xb3\x01\n\x06Result\x12\x35\n\x08severity\x18\x01 \x01(\x0e\x32#.apiextensions.fn.proto.v1.Severity\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x13\n\x06reason\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x36\n\x06target\x18\x04 \x01(\x0e\x32!.apiextensions.fn.proto.v1.TargetH\x01\x88\x01\x01\x42\t\n\x07_reasonB\t\n\x07_target\"\xc1\x01\n\tCondition\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x31\n\x06status\x18\x02 \x01(\x0e\x32!.apiextensions.fn.proto.v1.Status\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x14\n\x07message\x18\x04 \x01(\tH\x00\x88\x01\x01\x12\x36\n\x06target\x18\x05 \x01(\x0e\x32!.apiextensions.fn.proto.v1.TargetH\x01\x88\x01\x01\x42\n\n\x08_messageB\t\n\x07_target*?\n\x05Ready\x12\x15\n\x11READY_UNSPECIFIED\x10\x00\x12\x0e\n\nREADY_TRUE\x10\x01\x12\x0f\n\x0bREADY_FALSE\x10\x02*c\n\x08Severity\x12\x18\n\x14SEVERITY_UNSPECIFIED\x10\x00\x12\x12\n\x0eSEVERITY_FATAL\x10\x01\x12\x14\n\x10SEVERITY_WARNING\x10\x02\x12\x13\n\x0fSEVERITY_NORMAL\x10\x03*V\n\x06Target\x12\x16\n\x12TARGET_UNSPECIFIED\x10\x00\x12\x14\n\x10TARGET_COMPOSITE\x10\x01\x12\x1e\n\x1aTARGET_COMPOSITE_AND_CLAIM\x10\x02*\x7f\n\x06Status\x12 \n\x1cSTATUS_CONDITION_UNSPECIFIED\x10\x00\x12\x1c\n\x18STATUS_CONDITION_UNKNOWN\x10\x01\x12\x19\n\x15STATUS_CONDITION_TRUE\x10\x02\x12\x1a\n\x16STATUS_CONDITION_FALSE\x10\x03\x32\x87\x01\n\x15\x46unctionRunnerService\x12n\n\x0bRunFunction\x12-.apiextensions.fn.proto.v1.RunFunctionRequest\x1a..apiextensions.fn.proto.v1.RunFunctionResponse\"\x00\x42.Z,github.com/crossplane/crossplane/proto/fn/v1b\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'crossplane.function.proto.v1.run_function_pb2', _globals) if not _descriptor._USE_C_DESCRIPTORS: _globals['DESCRIPTOR']._loaded_options = None - _globals['DESCRIPTOR']._serialized_options = b'Z?github.com/crossplane/crossplane/apis/apiextensions/fn/proto/v1' - _globals['_RUNFUNCTIONREQUEST_EXTRARESOURCESENTRY']._loaded_options = None - _globals['_RUNFUNCTIONREQUEST_EXTRARESOURCESENTRY']._serialized_options = b'8\001' + _globals['DESCRIPTOR']._serialized_options = b'Z,github.com/crossplane/crossplane/proto/fn/v1' + _globals['_RUNFUNCTIONREQUEST_REQUIREDRESOURCESENTRY']._loaded_options = None + _globals['_RUNFUNCTIONREQUEST_REQUIREDRESOURCESENTRY']._serialized_options = b'8\001' _globals['_RUNFUNCTIONREQUEST_CREDENTIALSENTRY']._loaded_options = None _globals['_RUNFUNCTIONREQUEST_CREDENTIALSENTRY']._serialized_options = b'8\001' _globals['_CREDENTIALDATA_DATAENTRY']._loaded_options = None _globals['_CREDENTIALDATA_DATAENTRY']._serialized_options = b'8\001' - _globals['_REQUIREMENTS_EXTRARESOURCESENTRY']._loaded_options = None - _globals['_REQUIREMENTS_EXTRARESOURCESENTRY']._serialized_options = b'8\001' + _globals['_REQUIREMENTS_RESOURCESENTRY']._loaded_options = None + _globals['_REQUIREMENTS_RESOURCESENTRY']._serialized_options = b'8\001' _globals['_MATCHLABELS_LABELSENTRY']._loaded_options = None _globals['_MATCHLABELS_LABELSENTRY']._serialized_options = b'8\001' _globals['_STATE_RESOURCESENTRY']._loaded_options = None _globals['_STATE_RESOURCESENTRY']._serialized_options = b'8\001' _globals['_RESOURCE_CONNECTIONDETAILSENTRY']._loaded_options = None _globals['_RESOURCE_CONNECTIONDETAILSENTRY']._serialized_options = b'8\001' - _globals['_READY']._serialized_start=2894 - _globals['_READY']._serialized_end=2957 - _globals['_SEVERITY']._serialized_start=2959 - _globals['_SEVERITY']._serialized_end=3058 - _globals['_TARGET']._serialized_start=3060 - _globals['_TARGET']._serialized_end=3146 - _globals['_STATUS']._serialized_start=3148 - _globals['_STATUS']._serialized_end=3275 + _globals['_READY']._serialized_start=2982 + _globals['_READY']._serialized_end=3045 + _globals['_SEVERITY']._serialized_start=3047 + _globals['_SEVERITY']._serialized_end=3146 + _globals['_TARGET']._serialized_start=3148 + _globals['_TARGET']._serialized_end=3234 + _globals['_STATUS']._serialized_start=3236 + _globals['_STATUS']._serialized_end=3363 _globals['_RUNFUNCTIONREQUEST']._serialized_start=141 - _globals['_RUNFUNCTIONREQUEST']._serialized_end=794 - _globals['_RUNFUNCTIONREQUEST_EXTRARESOURCESENTRY']._serialized_start=589 - _globals['_RUNFUNCTIONREQUEST_EXTRARESOURCESENTRY']._serialized_end=680 - _globals['_RUNFUNCTIONREQUEST_CREDENTIALSENTRY']._serialized_start=682 - _globals['_RUNFUNCTIONREQUEST_CREDENTIALSENTRY']._serialized_end=772 - _globals['_CREDENTIALS']._serialized_start=796 - _globals['_CREDENTIALS']._serialized_end=889 - _globals['_CREDENTIALDATA']._serialized_start=892 - _globals['_CREDENTIALDATA']._serialized_end=1020 - _globals['_CREDENTIALDATA_DATAENTRY']._serialized_start=977 - _globals['_CREDENTIALDATA_DATAENTRY']._serialized_end=1020 - _globals['_RESOURCES']._serialized_start=1022 - _globals['_RESOURCES']._serialized_end=1085 - _globals['_RUNFUNCTIONRESPONSE']._serialized_start=1088 - _globals['_RUNFUNCTIONRESPONSE']._serialized_end=1447 - _globals['_REQUESTMETA']._serialized_start=1449 - _globals['_REQUESTMETA']._serialized_end=1475 - _globals['_REQUIREMENTS']._serialized_start=1478 - _globals['_REQUIREMENTS']._serialized_end=1678 - _globals['_REQUIREMENTS_EXTRARESOURCESENTRY']._serialized_start=1580 - _globals['_REQUIREMENTS_EXTRARESOURCESENTRY']._serialized_end=1678 - _globals['_RESOURCESELECTOR']._serialized_start=1681 - _globals['_RESOURCESELECTOR']._serialized_end=1829 - _globals['_MATCHLABELS']._serialized_start=1832 - _globals['_MATCHLABELS']._serialized_end=1960 - _globals['_MATCHLABELS_LABELSENTRY']._serialized_start=1915 - _globals['_MATCHLABELS_LABELSENTRY']._serialized_end=1960 - _globals['_RESPONSEMETA']._serialized_start=1962 - _globals['_RESPONSEMETA']._serialized_end=2042 - _globals['_STATE']._serialized_start=2045 - _globals['_STATE']._serialized_end=2263 - _globals['_STATE_RESOURCESENTRY']._serialized_start=2178 - _globals['_STATE_RESOURCESENTRY']._serialized_end=2263 - _globals['_RESOURCE']._serialized_start=2266 - _globals['_RESOURCE']._serialized_end=2514 - _globals['_RESOURCE_CONNECTIONDETAILSENTRY']._serialized_start=2458 - _globals['_RESOURCE_CONNECTIONDETAILSENTRY']._serialized_end=2514 - _globals['_RESULT']._serialized_start=2517 - _globals['_RESULT']._serialized_end=2696 - _globals['_CONDITION']._serialized_start=2699 - _globals['_CONDITION']._serialized_end=2892 - _globals['_FUNCTIONRUNNERSERVICE']._serialized_start=3278 - _globals['_FUNCTIONRUNNERSERVICE']._serialized_end=3413 + _globals['_RUNFUNCTIONREQUEST']._serialized_end=803 + _globals['_RUNFUNCTIONREQUEST_REQUIREDRESOURCESENTRY']._serialized_start=595 + _globals['_RUNFUNCTIONREQUEST_REQUIREDRESOURCESENTRY']._serialized_end=689 + _globals['_RUNFUNCTIONREQUEST_CREDENTIALSENTRY']._serialized_start=691 + _globals['_RUNFUNCTIONREQUEST_CREDENTIALSENTRY']._serialized_end=781 + _globals['_CREDENTIALS']._serialized_start=805 + _globals['_CREDENTIALS']._serialized_end=898 + _globals['_CREDENTIALDATA']._serialized_start=901 + _globals['_CREDENTIALDATA']._serialized_end=1029 + _globals['_CREDENTIALDATA_DATAENTRY']._serialized_start=986 + _globals['_CREDENTIALDATA_DATAENTRY']._serialized_end=1029 + _globals['_RESOURCES']._serialized_start=1031 + _globals['_RESOURCES']._serialized_end=1094 + _globals['_RUNFUNCTIONRESPONSE']._serialized_start=1097 + _globals['_RUNFUNCTIONRESPONSE']._serialized_end=1513 + _globals['_REQUESTMETA']._serialized_start=1515 + _globals['_REQUESTMETA']._serialized_end=1541 + _globals['_REQUIREMENTS']._serialized_start=1544 + _globals['_REQUIREMENTS']._serialized_end=1728 + _globals['_REQUIREMENTS_RESOURCESENTRY']._serialized_start=1635 + _globals['_REQUIREMENTS_RESOURCESENTRY']._serialized_end=1728 + _globals['_RESOURCESELECTOR']._serialized_start=1731 + _globals['_RESOURCESELECTOR']._serialized_end=1917 + _globals['_MATCHLABELS']._serialized_start=1920 + _globals['_MATCHLABELS']._serialized_end=2048 + _globals['_MATCHLABELS_LABELSENTRY']._serialized_start=2003 + _globals['_MATCHLABELS_LABELSENTRY']._serialized_end=2048 + _globals['_RESPONSEMETA']._serialized_start=2050 + _globals['_RESPONSEMETA']._serialized_end=2130 + _globals['_STATE']._serialized_start=2133 + _globals['_STATE']._serialized_end=2351 + _globals['_STATE_RESOURCESENTRY']._serialized_start=2266 + _globals['_STATE_RESOURCESENTRY']._serialized_end=2351 + _globals['_RESOURCE']._serialized_start=2354 + _globals['_RESOURCE']._serialized_end=2602 + _globals['_RESOURCE_CONNECTIONDETAILSENTRY']._serialized_start=2546 + _globals['_RESOURCE_CONNECTIONDETAILSENTRY']._serialized_end=2602 + _globals['_RESULT']._serialized_start=2605 + _globals['_RESULT']._serialized_end=2784 + _globals['_CONDITION']._serialized_start=2787 + _globals['_CONDITION']._serialized_end=2980 + _globals['_FUNCTIONRUNNERSERVICE']._serialized_start=3366 + _globals['_FUNCTIONRUNNERSERVICE']._serialized_end=3501 # @@protoc_insertion_point(module_scope) diff --git a/crossplane/function/proto/v1/run_function_pb2.pyi b/crossplane/function/proto/v1/run_function_pb2.pyi index 5ba6180..c0dd5d8 100644 --- a/crossplane/function/proto/v1/run_function_pb2.pyi +++ b/crossplane/function/proto/v1/run_function_pb2.pyi @@ -1,10 +1,11 @@ -from google.protobuf import struct_pb2 as _struct_pb2 from google.protobuf import duration_pb2 as _duration_pb2 +from google.protobuf import struct_pb2 as _struct_pb2 from google.protobuf.internal import containers as _containers from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message -from typing import ClassVar as _ClassVar, Iterable as _Iterable, Mapping as _Mapping, Optional as _Optional, Union as _Union +from collections.abc import Iterable as _Iterable, Mapping as _Mapping +from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union DESCRIPTOR: _descriptor.FileDescriptor @@ -49,8 +50,8 @@ STATUS_CONDITION_TRUE: Status STATUS_CONDITION_FALSE: Status class RunFunctionRequest(_message.Message): - __slots__ = ("meta", "observed", "desired", "input", "context", "extra_resources", "credentials") - class ExtraResourcesEntry(_message.Message): + __slots__ = ("meta", "observed", "desired", "input", "context", "required_resources", "credentials") + class RequiredResourcesEntry(_message.Message): __slots__ = ("key", "value") KEY_FIELD_NUMBER: _ClassVar[int] VALUE_FIELD_NUMBER: _ClassVar[int] @@ -69,16 +70,16 @@ class RunFunctionRequest(_message.Message): DESIRED_FIELD_NUMBER: _ClassVar[int] INPUT_FIELD_NUMBER: _ClassVar[int] CONTEXT_FIELD_NUMBER: _ClassVar[int] - EXTRA_RESOURCES_FIELD_NUMBER: _ClassVar[int] + REQUIRED_RESOURCES_FIELD_NUMBER: _ClassVar[int] CREDENTIALS_FIELD_NUMBER: _ClassVar[int] meta: RequestMeta observed: State desired: State input: _struct_pb2.Struct context: _struct_pb2.Struct - extra_resources: _containers.MessageMap[str, Resources] + required_resources: _containers.MessageMap[str, Resources] credentials: _containers.MessageMap[str, Credentials] - def __init__(self, meta: _Optional[_Union[RequestMeta, _Mapping]] = ..., observed: _Optional[_Union[State, _Mapping]] = ..., desired: _Optional[_Union[State, _Mapping]] = ..., input: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ..., context: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ..., extra_resources: _Optional[_Mapping[str, Resources]] = ..., credentials: _Optional[_Mapping[str, Credentials]] = ...) -> None: ... + def __init__(self, meta: _Optional[_Union[RequestMeta, _Mapping]] = ..., observed: _Optional[_Union[State, _Mapping]] = ..., desired: _Optional[_Union[State, _Mapping]] = ..., input: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ..., context: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ..., required_resources: _Optional[_Mapping[str, Resources]] = ..., credentials: _Optional[_Mapping[str, Credentials]] = ...) -> None: ... class Credentials(_message.Message): __slots__ = ("credential_data",) @@ -106,20 +107,22 @@ class Resources(_message.Message): def __init__(self, items: _Optional[_Iterable[_Union[Resource, _Mapping]]] = ...) -> None: ... class RunFunctionResponse(_message.Message): - __slots__ = ("meta", "desired", "results", "context", "requirements", "conditions") + __slots__ = ("meta", "desired", "results", "context", "requirements", "conditions", "output") META_FIELD_NUMBER: _ClassVar[int] DESIRED_FIELD_NUMBER: _ClassVar[int] RESULTS_FIELD_NUMBER: _ClassVar[int] CONTEXT_FIELD_NUMBER: _ClassVar[int] REQUIREMENTS_FIELD_NUMBER: _ClassVar[int] CONDITIONS_FIELD_NUMBER: _ClassVar[int] + OUTPUT_FIELD_NUMBER: _ClassVar[int] meta: ResponseMeta desired: State results: _containers.RepeatedCompositeFieldContainer[Result] context: _struct_pb2.Struct requirements: Requirements conditions: _containers.RepeatedCompositeFieldContainer[Condition] - def __init__(self, meta: _Optional[_Union[ResponseMeta, _Mapping]] = ..., desired: _Optional[_Union[State, _Mapping]] = ..., results: _Optional[_Iterable[_Union[Result, _Mapping]]] = ..., context: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ..., requirements: _Optional[_Union[Requirements, _Mapping]] = ..., conditions: _Optional[_Iterable[_Union[Condition, _Mapping]]] = ...) -> None: ... + output: _struct_pb2.Struct + def __init__(self, meta: _Optional[_Union[ResponseMeta, _Mapping]] = ..., desired: _Optional[_Union[State, _Mapping]] = ..., results: _Optional[_Iterable[_Union[Result, _Mapping]]] = ..., context: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ..., requirements: _Optional[_Union[Requirements, _Mapping]] = ..., conditions: _Optional[_Iterable[_Union[Condition, _Mapping]]] = ..., output: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ...) -> None: ... class RequestMeta(_message.Message): __slots__ = ("tag",) @@ -128,29 +131,31 @@ class RequestMeta(_message.Message): def __init__(self, tag: _Optional[str] = ...) -> None: ... class Requirements(_message.Message): - __slots__ = ("extra_resources",) - class ExtraResourcesEntry(_message.Message): + __slots__ = ("resources",) + class ResourcesEntry(_message.Message): __slots__ = ("key", "value") KEY_FIELD_NUMBER: _ClassVar[int] VALUE_FIELD_NUMBER: _ClassVar[int] key: str value: ResourceSelector def __init__(self, key: _Optional[str] = ..., value: _Optional[_Union[ResourceSelector, _Mapping]] = ...) -> None: ... - EXTRA_RESOURCES_FIELD_NUMBER: _ClassVar[int] - extra_resources: _containers.MessageMap[str, ResourceSelector] - def __init__(self, extra_resources: _Optional[_Mapping[str, ResourceSelector]] = ...) -> None: ... + RESOURCES_FIELD_NUMBER: _ClassVar[int] + resources: _containers.MessageMap[str, ResourceSelector] + def __init__(self, resources: _Optional[_Mapping[str, ResourceSelector]] = ...) -> None: ... class ResourceSelector(_message.Message): - __slots__ = ("api_version", "kind", "match_name", "match_labels") + __slots__ = ("api_version", "kind", "match_name", "match_labels", "namespace") API_VERSION_FIELD_NUMBER: _ClassVar[int] KIND_FIELD_NUMBER: _ClassVar[int] MATCH_NAME_FIELD_NUMBER: _ClassVar[int] MATCH_LABELS_FIELD_NUMBER: _ClassVar[int] + NAMESPACE_FIELD_NUMBER: _ClassVar[int] api_version: str kind: str match_name: str match_labels: MatchLabels - def __init__(self, api_version: _Optional[str] = ..., kind: _Optional[str] = ..., match_name: _Optional[str] = ..., match_labels: _Optional[_Union[MatchLabels, _Mapping]] = ...) -> None: ... + namespace: str + def __init__(self, api_version: _Optional[str] = ..., kind: _Optional[str] = ..., match_name: _Optional[str] = ..., match_labels: _Optional[_Union[MatchLabels, _Mapping]] = ..., namespace: _Optional[str] = ...) -> None: ... class MatchLabels(_message.Message): __slots__ = ("labels",) @@ -171,7 +176,7 @@ class ResponseMeta(_message.Message): TTL_FIELD_NUMBER: _ClassVar[int] tag: str ttl: _duration_pb2.Duration - def __init__(self, tag: _Optional[str] = ..., ttl: _Optional[_Union[_duration_pb2.Duration, _Mapping]] = ...) -> None: ... + def __init__(self, tag: _Optional[str] = ..., ttl: _Optional[_Union[datetime.timedelta, _duration_pb2.Duration, _Mapping]] = ...) -> None: ... class State(_message.Message): __slots__ = ("composite", "resources") diff --git a/crossplane/function/proto/v1/run_function_pb2_grpc.py b/crossplane/function/proto/v1/run_function_pb2_grpc.py index bc3a415..ecc0ec8 100644 --- a/crossplane/function/proto/v1/run_function_pb2_grpc.py +++ b/crossplane/function/proto/v1/run_function_pb2_grpc.py @@ -5,7 +5,7 @@ from crossplane.function.proto.v1 import run_function_pb2 as crossplane_dot_function_dot_proto_dot_v1_dot_run__function__pb2 -GRPC_GENERATED_VERSION = '1.71.0' +GRPC_GENERATED_VERSION = '1.73.1' GRPC_VERSION = grpc.__version__ _version_not_supported = False @@ -26,7 +26,7 @@ class FunctionRunnerServiceStub(object): - """A FunctionRunnerService is a Composition Function. + """A FunctionRunnerService is a function. """ def __init__(self, channel): @@ -43,11 +43,11 @@ def __init__(self, channel): class FunctionRunnerServiceServicer(object): - """A FunctionRunnerService is a Composition Function. + """A FunctionRunnerService is a function. """ def RunFunction(self, request, context): - """RunFunction runs the Composition Function. + """RunFunction runs the function. """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') @@ -70,7 +70,7 @@ def add_FunctionRunnerServiceServicer_to_server(servicer, server): # This class is part of an EXPERIMENTAL API. class FunctionRunnerService(object): - """A FunctionRunnerService is a Composition Function. + """A FunctionRunnerService is a function. """ @staticmethod diff --git a/crossplane/function/proto/v1beta1/run_function.proto b/crossplane/function/proto/v1beta1/run_function.proto index 52ab926..1332ae5 100644 --- a/crossplane/function/proto/v1beta1/run_function.proto +++ b/crossplane/function/proto/v1beta1/run_function.proto @@ -1,82 +1,88 @@ /* -Copyright 2022 The Crossplane Authors. + 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 + 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 + 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. + 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"; +// Generated from proto/fn/v1/run_function.proto by ./hack/duplicate_proto_type.sh. DO NOT EDIT. -import "google/protobuf/struct.proto"; -import "google/protobuf/duration.proto"; +syntax = "proto3"; -// Generated from apiextensions/fn/proto/v1/run_function.proto by ../hack/duplicate_proto_type.sh. DO NOT EDIT. +// This package defines the RPC for both composition and operation functions. +// Only composition functions are part of the 'apiextensions' API group. In +// retrospect this package should've been crossplane.proto.fn.v1, but it's too +// late to change it now. +//buf:lint:ignore PACKAGE_DIRECTORY_MATCH package apiextensions.fn.proto.v1beta1; -option go_package = "github.com/crossplane/crossplane/apis/apiextensions/fn/proto/v1beta1"; +import "google/protobuf/duration.proto"; +import "google/protobuf/struct.proto"; -// A FunctionRunnerService is a Composition Function. +option go_package = "github.com/crossplane/crossplane/proto/fn/v1beta1"; + +// A FunctionRunnerService is a function. service FunctionRunnerService { - // RunFunction runs the Composition Function. + // RunFunction runs the function. rpc RunFunction(RunFunctionRequest) returns (RunFunctionResponse) {} } -// A RunFunctionRequest requests that the Composition Function be run. +// A RunFunctionRequest requests that the 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. + // 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 + // 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 + // 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 input specific to this function invocation. A JSON representation + // of the 'input' block of the relevant entry in a function pipeline. optional google.protobuf.Struct input = 4; - // Optional context. Crossplane may pass arbitary 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 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 extra_resources = 6; + // Optional resources that the function specified in its requirements. Note + // that resources is a map to Resources, plural. The map key corresponds to + // the key in a RunFunctionResponse's requirements.resources field. If a + // function requested required 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 required_resources = 6; - // Optional credentials that this Function may use to communicate with an + // Optional credentials that this function may use to communicate with an // external system. - map credentials = 7; + map credentials = 7; } -// Credentials that a Function may use to communicate with an external system. +// Credentials that a function may use to communicate with an external system. message Credentials { // Source of the credentials. oneof source { @@ -95,52 +101,58 @@ message Resources { repeated Resource items = 1; } -// A RunFunctionResponse contains the result of a Composition Function run. +// A RunFunctionResponse contains the result of a function run. message RunFunctionResponse { // Metadata pertaining to this response. ResponseMeta meta = 1; - // Desired state according to a Function pipeline. Functions may add desired + // 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 + // 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 + // 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. + // 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 + // 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 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. + // Status conditions to be applied to the XR. Conditions may also optionally + // be applied to the XR's associated claim. + // + // Conditions are only used for composition. They're ignored by Operations. repeated Condition conditions = 6; + + // Optional output specific to this function invocation. + // + // Only Operations use function output. XRs will discard any function output. + optional google.protobuf.Struct output = 7; } // RequestMeta contains metadata pertaining to a RunFunctionRequest. message RequestMeta { - // An opaque string identifying the content of the request. Two identical - // requests should have the same tag. + // 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. +// 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 extra_resources = 1; + // Resources that this function requires. The map key uniquely identifies the + // group of resources. + map resources = 1; } // ResourceSelector selects a group of resources, either by name or by label. @@ -159,6 +171,11 @@ message ResourceSelector { // 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. @@ -172,77 +189,86 @@ message ResponseMeta { // meta.tag of the corresponding RunFunctionRequest. string tag = 1; - // Time-to-live of this response. Deterministic Functions with no side-effects - // (e.g. simple templating Functions) may specify a TTL. Crossplane may choose - // to cache responses until the TTL expires. + // 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. +// State of the XR (XR) and any resources. message State { - // The state of the composite resource (XR). + // The state of the XR (XR). Resource composite = 1; - // The state of any composed resources. + // The state of any other resources. In composition functions these are the + // composed resources. In operation functions they're arbitrary resources that + // the operation wants to create or update. map resources = 2; } -// A Resource represents the state of a composite or composed resource. +// A Resource represents the state of a Kubernetes 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. + // 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 should set this field in a RunFunctionRequest to communicate + // the desired state of the 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 only specify the desired status of a XR - not its metadata + // or spec. A function should not return desired metadata or spec for a XR. + // 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. + // * A function may not specify the desired status of any other resource - + // e.g. composed resources. It may only specify their metadata and spec. + // Status 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. + // 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 XR. // - // * 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. // - // * A Function should not set this field in a RunFunctionResponse to indicate - // the desired connection details of a composed resource. This will be - // ignored. + // Connection details are only used for composition. They're ignored by + // Operations. map 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 resource is ready. + // + // * A function should set this field to READY_TRUE in a RunFunctionResponse + // to indicate that a desired XR 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. // - // * A Function should not set this field in a RunFunctionResponse to indicate - // that the desired composite resource is ready. This will be ignored. + // Ready is only used for composition. It's ignored by Operations. Ready ready = 3; } -// Ready indicates whether a composed resource should be considered ready. +// Ready indicates whether a resource should be considered ready. enum Ready { READY_UNSPECIFIED = 0; - // True means the composed resource has been observed to be ready. + // True means the resource has been observed to be ready. READY_TRUE = 1; - // False means the composed resource has not been observed to be ready. + // False means the resource has not been observed to be ready. READY_FALSE = 2; } -// A Result of running a Function. +// A Result of running a function. message Result { // Severity of this result. Severity severity = 1; @@ -258,42 +284,42 @@ message Result { optional Target target = 4; } -// Severity of Function results. +// 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. + // Fatal results are fatal; subsequent functions may run, but the 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. + // Warning results are non-fatal; the entire pipeline will run to completion + // but warning events and debug logs associated with the XR or Operation will + // be emitted. SEVERITY_WARNING = 2; - // Normal results are emitted as normal events and debug logs associated - // with the composite resource. + // Normal results are emitted as normal events and debug logs associated with + // the XR or operation. SEVERITY_NORMAL = 3; } -// Target of Function results and conditions. +// Target of function results and conditions. enum Target { - // If the target is unspecified, the result targets the composite resource. + // If the target is unspecified, the result targets the XR. TARGET_UNSPECIFIED = 0; - // Target the composite resource. Results that target the composite resource - // should include detailed, advanced information. + // Target the XR. Results that target the XR 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 the XR and the claim. Results that target the XR 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 +// Status condition to be applied to the XR. Condition may also optionally be +// applied to the XR'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. diff --git a/crossplane/function/proto/v1beta1/run_function_pb2.py b/crossplane/function/proto/v1beta1/run_function_pb2.py index dcd2eb0..6499a56 100644 --- a/crossplane/function/proto/v1beta1/run_function_pb2.py +++ b/crossplane/function/proto/v1beta1/run_function_pb2.py @@ -2,7 +2,7 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! # NO CHECKED-IN PROTOBUF GENCODE # source: crossplane/function/proto/v1beta1/run_function.proto -# Protobuf Python Version: 5.29.0 +# Protobuf Python Version: 6.31.0 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool @@ -11,8 +11,8 @@ from google.protobuf.internal import builder as _builder _runtime_version.ValidateProtobufRuntimeVersion( _runtime_version.Domain.PUBLIC, - 5, - 29, + 6, + 31, 0, '', 'crossplane/function/proto/v1beta1/run_function.proto' @@ -22,82 +22,82 @@ _sym_db = _symbol_database.Default() -from google.protobuf import struct_pb2 as google_dot_protobuf_dot_struct__pb2 from google.protobuf import duration_pb2 as google_dot_protobuf_dot_duration__pb2 +from google.protobuf import struct_pb2 as google_dot_protobuf_dot_struct__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n4crossplane/function/proto/v1beta1/run_function.proto\x12\x1e\x61piextensions.fn.proto.v1beta1\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1egoogle/protobuf/duration.proto\"\xb0\x05\n\x12RunFunctionRequest\x12\x39\n\x04meta\x18\x01 \x01(\x0b\x32+.apiextensions.fn.proto.v1beta1.RequestMeta\x12\x37\n\x08observed\x18\x02 \x01(\x0b\x32%.apiextensions.fn.proto.v1beta1.State\x12\x36\n\x07\x64\x65sired\x18\x03 \x01(\x0b\x32%.apiextensions.fn.proto.v1beta1.State\x12+\n\x05input\x18\x04 \x01(\x0b\x32\x17.google.protobuf.StructH\x00\x88\x01\x01\x12-\n\x07\x63ontext\x18\x05 \x01(\x0b\x32\x17.google.protobuf.StructH\x01\x88\x01\x01\x12_\n\x0f\x65xtra_resources\x18\x06 \x03(\x0b\x32\x46.apiextensions.fn.proto.v1beta1.RunFunctionRequest.ExtraResourcesEntry\x12X\n\x0b\x63redentials\x18\x07 \x03(\x0b\x32\x43.apiextensions.fn.proto.v1beta1.RunFunctionRequest.CredentialsEntry\x1a`\n\x13\x45xtraResourcesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x38\n\x05value\x18\x02 \x01(\x0b\x32).apiextensions.fn.proto.v1beta1.Resources:\x02\x38\x01\x1a_\n\x10\x43redentialsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12:\n\x05value\x18\x02 \x01(\x0b\x32+.apiextensions.fn.proto.v1beta1.Credentials:\x02\x38\x01\x42\x08\n\x06_inputB\n\n\x08_context\"b\n\x0b\x43redentials\x12I\n\x0f\x63redential_data\x18\x01 \x01(\x0b\x32..apiextensions.fn.proto.v1beta1.CredentialDataH\x00\x42\x08\n\x06source\"\x85\x01\n\x0e\x43redentialData\x12\x46\n\x04\x64\x61ta\x18\x01 \x03(\x0b\x32\x38.apiextensions.fn.proto.v1beta1.CredentialData.DataEntry\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\"D\n\tResources\x12\x37\n\x05items\x18\x01 \x03(\x0b\x32(.apiextensions.fn.proto.v1beta1.Resource\"\x80\x03\n\x13RunFunctionResponse\x12:\n\x04meta\x18\x01 \x01(\x0b\x32,.apiextensions.fn.proto.v1beta1.ResponseMeta\x12\x36\n\x07\x64\x65sired\x18\x02 \x01(\x0b\x32%.apiextensions.fn.proto.v1beta1.State\x12\x37\n\x07results\x18\x03 \x03(\x0b\x32&.apiextensions.fn.proto.v1beta1.Result\x12-\n\x07\x63ontext\x18\x04 \x01(\x0b\x32\x17.google.protobuf.StructH\x00\x88\x01\x01\x12\x42\n\x0crequirements\x18\x05 \x01(\x0b\x32,.apiextensions.fn.proto.v1beta1.Requirements\x12=\n\nconditions\x18\x06 \x03(\x0b\x32).apiextensions.fn.proto.v1beta1.ConditionB\n\n\x08_context\"\x1a\n\x0bRequestMeta\x12\x0b\n\x03tag\x18\x01 \x01(\t\"\xd2\x01\n\x0cRequirements\x12Y\n\x0f\x65xtra_resources\x18\x01 \x03(\x0b\x32@.apiextensions.fn.proto.v1beta1.Requirements.ExtraResourcesEntry\x1ag\n\x13\x45xtraResourcesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12?\n\x05value\x18\x02 \x01(\x0b\x32\x30.apiextensions.fn.proto.v1beta1.ResourceSelector:\x02\x38\x01\"\x99\x01\n\x10ResourceSelector\x12\x13\n\x0b\x61pi_version\x18\x01 \x01(\t\x12\x0c\n\x04kind\x18\x02 \x01(\t\x12\x14\n\nmatch_name\x18\x03 \x01(\tH\x00\x12\x43\n\x0cmatch_labels\x18\x04 \x01(\x0b\x32+.apiextensions.fn.proto.v1beta1.MatchLabelsH\x00\x42\x07\n\x05match\"\x85\x01\n\x0bMatchLabels\x12G\n\x06labels\x18\x01 \x03(\x0b\x32\x37.apiextensions.fn.proto.v1beta1.MatchLabels.LabelsEntry\x1a-\n\x0bLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"P\n\x0cResponseMeta\x12\x0b\n\x03tag\x18\x01 \x01(\t\x12+\n\x03ttl\x18\x02 \x01(\x0b\x32\x19.google.protobuf.DurationH\x00\x88\x01\x01\x42\x06\n\x04_ttl\"\xe9\x01\n\x05State\x12;\n\tcomposite\x18\x01 \x01(\x0b\x32(.apiextensions.fn.proto.v1beta1.Resource\x12G\n\tresources\x18\x02 \x03(\x0b\x32\x34.apiextensions.fn.proto.v1beta1.State.ResourcesEntry\x1aZ\n\x0eResourcesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x37\n\x05value\x18\x02 \x01(\x0b\x32(.apiextensions.fn.proto.v1beta1.Resource:\x02\x38\x01\"\x82\x02\n\x08Resource\x12)\n\x08resource\x18\x01 \x01(\x0b\x32\x17.google.protobuf.Struct\x12[\n\x12\x63onnection_details\x18\x02 \x03(\x0b\x32?.apiextensions.fn.proto.v1beta1.Resource.ConnectionDetailsEntry\x12\x34\n\x05ready\x18\x03 \x01(\x0e\x32%.apiextensions.fn.proto.v1beta1.Ready\x1a\x38\n\x16\x43onnectionDetailsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\"\xbd\x01\n\x06Result\x12:\n\x08severity\x18\x01 \x01(\x0e\x32(.apiextensions.fn.proto.v1beta1.Severity\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x13\n\x06reason\x18\x03 \x01(\tH\x00\x88\x01\x01\x12;\n\x06target\x18\x04 \x01(\x0e\x32&.apiextensions.fn.proto.v1beta1.TargetH\x01\x88\x01\x01\x42\t\n\x07_reasonB\t\n\x07_target\"\xcb\x01\n\tCondition\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x36\n\x06status\x18\x02 \x01(\x0e\x32&.apiextensions.fn.proto.v1beta1.Status\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x14\n\x07message\x18\x04 \x01(\tH\x00\x88\x01\x01\x12;\n\x06target\x18\x05 \x01(\x0e\x32&.apiextensions.fn.proto.v1beta1.TargetH\x01\x88\x01\x01\x42\n\n\x08_messageB\t\n\x07_target*?\n\x05Ready\x12\x15\n\x11READY_UNSPECIFIED\x10\x00\x12\x0e\n\nREADY_TRUE\x10\x01\x12\x0f\n\x0bREADY_FALSE\x10\x02*c\n\x08Severity\x12\x18\n\x14SEVERITY_UNSPECIFIED\x10\x00\x12\x12\n\x0eSEVERITY_FATAL\x10\x01\x12\x14\n\x10SEVERITY_WARNING\x10\x02\x12\x13\n\x0fSEVERITY_NORMAL\x10\x03*V\n\x06Target\x12\x16\n\x12TARGET_UNSPECIFIED\x10\x00\x12\x14\n\x10TARGET_COMPOSITE\x10\x01\x12\x1e\n\x1aTARGET_COMPOSITE_AND_CLAIM\x10\x02*\x7f\n\x06Status\x12 \n\x1cSTATUS_CONDITION_UNSPECIFIED\x10\x00\x12\x1c\n\x18STATUS_CONDITION_UNKNOWN\x10\x01\x12\x19\n\x15STATUS_CONDITION_TRUE\x10\x02\x12\x1a\n\x16STATUS_CONDITION_FALSE\x10\x03\x32\x91\x01\n\x15\x46unctionRunnerService\x12x\n\x0bRunFunction\x12\x32.apiextensions.fn.proto.v1beta1.RunFunctionRequest\x1a\x33.apiextensions.fn.proto.v1beta1.RunFunctionResponse\"\x00\x42\x46ZDgithub.com/crossplane/crossplane/apis/apiextensions/fn/proto/v1beta1b\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n4crossplane/function/proto/v1beta1/run_function.proto\x12\x1e\x61piextensions.fn.proto.v1beta1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1cgoogle/protobuf/struct.proto\"\xb9\x05\n\x12RunFunctionRequest\x12\x39\n\x04meta\x18\x01 \x01(\x0b\x32+.apiextensions.fn.proto.v1beta1.RequestMeta\x12\x37\n\x08observed\x18\x02 \x01(\x0b\x32%.apiextensions.fn.proto.v1beta1.State\x12\x36\n\x07\x64\x65sired\x18\x03 \x01(\x0b\x32%.apiextensions.fn.proto.v1beta1.State\x12+\n\x05input\x18\x04 \x01(\x0b\x32\x17.google.protobuf.StructH\x00\x88\x01\x01\x12-\n\x07\x63ontext\x18\x05 \x01(\x0b\x32\x17.google.protobuf.StructH\x01\x88\x01\x01\x12\x65\n\x12required_resources\x18\x06 \x03(\x0b\x32I.apiextensions.fn.proto.v1beta1.RunFunctionRequest.RequiredResourcesEntry\x12X\n\x0b\x63redentials\x18\x07 \x03(\x0b\x32\x43.apiextensions.fn.proto.v1beta1.RunFunctionRequest.CredentialsEntry\x1a\x63\n\x16RequiredResourcesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x38\n\x05value\x18\x02 \x01(\x0b\x32).apiextensions.fn.proto.v1beta1.Resources:\x02\x38\x01\x1a_\n\x10\x43redentialsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12:\n\x05value\x18\x02 \x01(\x0b\x32+.apiextensions.fn.proto.v1beta1.Credentials:\x02\x38\x01\x42\x08\n\x06_inputB\n\n\x08_context\"b\n\x0b\x43redentials\x12I\n\x0f\x63redential_data\x18\x01 \x01(\x0b\x32..apiextensions.fn.proto.v1beta1.CredentialDataH\x00\x42\x08\n\x06source\"\x85\x01\n\x0e\x43redentialData\x12\x46\n\x04\x64\x61ta\x18\x01 \x03(\x0b\x32\x38.apiextensions.fn.proto.v1beta1.CredentialData.DataEntry\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\"D\n\tResources\x12\x37\n\x05items\x18\x01 \x03(\x0b\x32(.apiextensions.fn.proto.v1beta1.Resource\"\xb9\x03\n\x13RunFunctionResponse\x12:\n\x04meta\x18\x01 \x01(\x0b\x32,.apiextensions.fn.proto.v1beta1.ResponseMeta\x12\x36\n\x07\x64\x65sired\x18\x02 \x01(\x0b\x32%.apiextensions.fn.proto.v1beta1.State\x12\x37\n\x07results\x18\x03 \x03(\x0b\x32&.apiextensions.fn.proto.v1beta1.Result\x12-\n\x07\x63ontext\x18\x04 \x01(\x0b\x32\x17.google.protobuf.StructH\x00\x88\x01\x01\x12\x42\n\x0crequirements\x18\x05 \x01(\x0b\x32,.apiextensions.fn.proto.v1beta1.Requirements\x12=\n\nconditions\x18\x06 \x03(\x0b\x32).apiextensions.fn.proto.v1beta1.Condition\x12,\n\x06output\x18\x07 \x01(\x0b\x32\x17.google.protobuf.StructH\x01\x88\x01\x01\x42\n\n\x08_contextB\t\n\x07_output\"\x1a\n\x0bRequestMeta\x12\x0b\n\x03tag\x18\x01 \x01(\t\"\xc2\x01\n\x0cRequirements\x12N\n\tresources\x18\x01 \x03(\x0b\x32;.apiextensions.fn.proto.v1beta1.Requirements.ResourcesEntry\x1a\x62\n\x0eResourcesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12?\n\x05value\x18\x02 \x01(\x0b\x32\x30.apiextensions.fn.proto.v1beta1.ResourceSelector:\x02\x38\x01\"\xbf\x01\n\x10ResourceSelector\x12\x13\n\x0b\x61pi_version\x18\x01 \x01(\t\x12\x0c\n\x04kind\x18\x02 \x01(\t\x12\x14\n\nmatch_name\x18\x03 \x01(\tH\x00\x12\x43\n\x0cmatch_labels\x18\x04 \x01(\x0b\x32+.apiextensions.fn.proto.v1beta1.MatchLabelsH\x00\x12\x16\n\tnamespace\x18\x05 \x01(\tH\x01\x88\x01\x01\x42\x07\n\x05matchB\x0c\n\n_namespace\"\x85\x01\n\x0bMatchLabels\x12G\n\x06labels\x18\x01 \x03(\x0b\x32\x37.apiextensions.fn.proto.v1beta1.MatchLabels.LabelsEntry\x1a-\n\x0bLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"P\n\x0cResponseMeta\x12\x0b\n\x03tag\x18\x01 \x01(\t\x12+\n\x03ttl\x18\x02 \x01(\x0b\x32\x19.google.protobuf.DurationH\x00\x88\x01\x01\x42\x06\n\x04_ttl\"\xe9\x01\n\x05State\x12;\n\tcomposite\x18\x01 \x01(\x0b\x32(.apiextensions.fn.proto.v1beta1.Resource\x12G\n\tresources\x18\x02 \x03(\x0b\x32\x34.apiextensions.fn.proto.v1beta1.State.ResourcesEntry\x1aZ\n\x0eResourcesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x37\n\x05value\x18\x02 \x01(\x0b\x32(.apiextensions.fn.proto.v1beta1.Resource:\x02\x38\x01\"\x82\x02\n\x08Resource\x12)\n\x08resource\x18\x01 \x01(\x0b\x32\x17.google.protobuf.Struct\x12[\n\x12\x63onnection_details\x18\x02 \x03(\x0b\x32?.apiextensions.fn.proto.v1beta1.Resource.ConnectionDetailsEntry\x12\x34\n\x05ready\x18\x03 \x01(\x0e\x32%.apiextensions.fn.proto.v1beta1.Ready\x1a\x38\n\x16\x43onnectionDetailsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\"\xbd\x01\n\x06Result\x12:\n\x08severity\x18\x01 \x01(\x0e\x32(.apiextensions.fn.proto.v1beta1.Severity\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x13\n\x06reason\x18\x03 \x01(\tH\x00\x88\x01\x01\x12;\n\x06target\x18\x04 \x01(\x0e\x32&.apiextensions.fn.proto.v1beta1.TargetH\x01\x88\x01\x01\x42\t\n\x07_reasonB\t\n\x07_target\"\xcb\x01\n\tCondition\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x36\n\x06status\x18\x02 \x01(\x0e\x32&.apiextensions.fn.proto.v1beta1.Status\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x14\n\x07message\x18\x04 \x01(\tH\x00\x88\x01\x01\x12;\n\x06target\x18\x05 \x01(\x0e\x32&.apiextensions.fn.proto.v1beta1.TargetH\x01\x88\x01\x01\x42\n\n\x08_messageB\t\n\x07_target*?\n\x05Ready\x12\x15\n\x11READY_UNSPECIFIED\x10\x00\x12\x0e\n\nREADY_TRUE\x10\x01\x12\x0f\n\x0bREADY_FALSE\x10\x02*c\n\x08Severity\x12\x18\n\x14SEVERITY_UNSPECIFIED\x10\x00\x12\x12\n\x0eSEVERITY_FATAL\x10\x01\x12\x14\n\x10SEVERITY_WARNING\x10\x02\x12\x13\n\x0fSEVERITY_NORMAL\x10\x03*V\n\x06Target\x12\x16\n\x12TARGET_UNSPECIFIED\x10\x00\x12\x14\n\x10TARGET_COMPOSITE\x10\x01\x12\x1e\n\x1aTARGET_COMPOSITE_AND_CLAIM\x10\x02*\x7f\n\x06Status\x12 \n\x1cSTATUS_CONDITION_UNSPECIFIED\x10\x00\x12\x1c\n\x18STATUS_CONDITION_UNKNOWN\x10\x01\x12\x19\n\x15STATUS_CONDITION_TRUE\x10\x02\x12\x1a\n\x16STATUS_CONDITION_FALSE\x10\x03\x32\x91\x01\n\x15\x46unctionRunnerService\x12x\n\x0bRunFunction\x12\x32.apiextensions.fn.proto.v1beta1.RunFunctionRequest\x1a\x33.apiextensions.fn.proto.v1beta1.RunFunctionResponse\"\x00\x42\x33Z1github.com/crossplane/crossplane/proto/fn/v1beta1b\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'crossplane.function.proto.v1beta1.run_function_pb2', _globals) if not _descriptor._USE_C_DESCRIPTORS: _globals['DESCRIPTOR']._loaded_options = None - _globals['DESCRIPTOR']._serialized_options = b'ZDgithub.com/crossplane/crossplane/apis/apiextensions/fn/proto/v1beta1' - _globals['_RUNFUNCTIONREQUEST_EXTRARESOURCESENTRY']._loaded_options = None - _globals['_RUNFUNCTIONREQUEST_EXTRARESOURCESENTRY']._serialized_options = b'8\001' + _globals['DESCRIPTOR']._serialized_options = b'Z1github.com/crossplane/crossplane/proto/fn/v1beta1' + _globals['_RUNFUNCTIONREQUEST_REQUIREDRESOURCESENTRY']._loaded_options = None + _globals['_RUNFUNCTIONREQUEST_REQUIREDRESOURCESENTRY']._serialized_options = b'8\001' _globals['_RUNFUNCTIONREQUEST_CREDENTIALSENTRY']._loaded_options = None _globals['_RUNFUNCTIONREQUEST_CREDENTIALSENTRY']._serialized_options = b'8\001' _globals['_CREDENTIALDATA_DATAENTRY']._loaded_options = None _globals['_CREDENTIALDATA_DATAENTRY']._serialized_options = b'8\001' - _globals['_REQUIREMENTS_EXTRARESOURCESENTRY']._loaded_options = None - _globals['_REQUIREMENTS_EXTRARESOURCESENTRY']._serialized_options = b'8\001' + _globals['_REQUIREMENTS_RESOURCESENTRY']._loaded_options = None + _globals['_REQUIREMENTS_RESOURCESENTRY']._serialized_options = b'8\001' _globals['_MATCHLABELS_LABELSENTRY']._loaded_options = None _globals['_MATCHLABELS_LABELSENTRY']._serialized_options = b'8\001' _globals['_STATE_RESOURCESENTRY']._loaded_options = None _globals['_STATE_RESOURCESENTRY']._serialized_options = b'8\001' _globals['_RESOURCE_CONNECTIONDETAILSENTRY']._loaded_options = None _globals['_RESOURCE_CONNECTIONDETAILSENTRY']._serialized_options = b'8\001' - _globals['_READY']._serialized_start=3044 - _globals['_READY']._serialized_end=3107 - _globals['_SEVERITY']._serialized_start=3109 - _globals['_SEVERITY']._serialized_end=3208 - _globals['_TARGET']._serialized_start=3210 - _globals['_TARGET']._serialized_end=3296 - _globals['_STATUS']._serialized_start=3298 - _globals['_STATUS']._serialized_end=3425 + _globals['_READY']._serialized_start=3132 + _globals['_READY']._serialized_end=3195 + _globals['_SEVERITY']._serialized_start=3197 + _globals['_SEVERITY']._serialized_end=3296 + _globals['_TARGET']._serialized_start=3298 + _globals['_TARGET']._serialized_end=3384 + _globals['_STATUS']._serialized_start=3386 + _globals['_STATUS']._serialized_end=3513 _globals['_RUNFUNCTIONREQUEST']._serialized_start=151 - _globals['_RUNFUNCTIONREQUEST']._serialized_end=839 - _globals['_RUNFUNCTIONREQUEST_EXTRARESOURCESENTRY']._serialized_start=624 - _globals['_RUNFUNCTIONREQUEST_EXTRARESOURCESENTRY']._serialized_end=720 - _globals['_RUNFUNCTIONREQUEST_CREDENTIALSENTRY']._serialized_start=722 - _globals['_RUNFUNCTIONREQUEST_CREDENTIALSENTRY']._serialized_end=817 - _globals['_CREDENTIALS']._serialized_start=841 - _globals['_CREDENTIALS']._serialized_end=939 - _globals['_CREDENTIALDATA']._serialized_start=942 - _globals['_CREDENTIALDATA']._serialized_end=1075 - _globals['_CREDENTIALDATA_DATAENTRY']._serialized_start=1032 - _globals['_CREDENTIALDATA_DATAENTRY']._serialized_end=1075 - _globals['_RESOURCES']._serialized_start=1077 - _globals['_RESOURCES']._serialized_end=1145 - _globals['_RUNFUNCTIONRESPONSE']._serialized_start=1148 - _globals['_RUNFUNCTIONRESPONSE']._serialized_end=1532 - _globals['_REQUESTMETA']._serialized_start=1534 - _globals['_REQUESTMETA']._serialized_end=1560 - _globals['_REQUIREMENTS']._serialized_start=1563 - _globals['_REQUIREMENTS']._serialized_end=1773 - _globals['_REQUIREMENTS_EXTRARESOURCESENTRY']._serialized_start=1670 - _globals['_REQUIREMENTS_EXTRARESOURCESENTRY']._serialized_end=1773 - _globals['_RESOURCESELECTOR']._serialized_start=1776 - _globals['_RESOURCESELECTOR']._serialized_end=1929 - _globals['_MATCHLABELS']._serialized_start=1932 - _globals['_MATCHLABELS']._serialized_end=2065 - _globals['_MATCHLABELS_LABELSENTRY']._serialized_start=2020 - _globals['_MATCHLABELS_LABELSENTRY']._serialized_end=2065 - _globals['_RESPONSEMETA']._serialized_start=2067 - _globals['_RESPONSEMETA']._serialized_end=2147 - _globals['_STATE']._serialized_start=2150 - _globals['_STATE']._serialized_end=2383 - _globals['_STATE_RESOURCESENTRY']._serialized_start=2293 - _globals['_STATE_RESOURCESENTRY']._serialized_end=2383 - _globals['_RESOURCE']._serialized_start=2386 - _globals['_RESOURCE']._serialized_end=2644 - _globals['_RESOURCE_CONNECTIONDETAILSENTRY']._serialized_start=2588 - _globals['_RESOURCE_CONNECTIONDETAILSENTRY']._serialized_end=2644 - _globals['_RESULT']._serialized_start=2647 - _globals['_RESULT']._serialized_end=2836 - _globals['_CONDITION']._serialized_start=2839 - _globals['_CONDITION']._serialized_end=3042 - _globals['_FUNCTIONRUNNERSERVICE']._serialized_start=3428 - _globals['_FUNCTIONRUNNERSERVICE']._serialized_end=3573 + _globals['_RUNFUNCTIONREQUEST']._serialized_end=848 + _globals['_RUNFUNCTIONREQUEST_REQUIREDRESOURCESENTRY']._serialized_start=630 + _globals['_RUNFUNCTIONREQUEST_REQUIREDRESOURCESENTRY']._serialized_end=729 + _globals['_RUNFUNCTIONREQUEST_CREDENTIALSENTRY']._serialized_start=731 + _globals['_RUNFUNCTIONREQUEST_CREDENTIALSENTRY']._serialized_end=826 + _globals['_CREDENTIALS']._serialized_start=850 + _globals['_CREDENTIALS']._serialized_end=948 + _globals['_CREDENTIALDATA']._serialized_start=951 + _globals['_CREDENTIALDATA']._serialized_end=1084 + _globals['_CREDENTIALDATA_DATAENTRY']._serialized_start=1041 + _globals['_CREDENTIALDATA_DATAENTRY']._serialized_end=1084 + _globals['_RESOURCES']._serialized_start=1086 + _globals['_RESOURCES']._serialized_end=1154 + _globals['_RUNFUNCTIONRESPONSE']._serialized_start=1157 + _globals['_RUNFUNCTIONRESPONSE']._serialized_end=1598 + _globals['_REQUESTMETA']._serialized_start=1600 + _globals['_REQUESTMETA']._serialized_end=1626 + _globals['_REQUIREMENTS']._serialized_start=1629 + _globals['_REQUIREMENTS']._serialized_end=1823 + _globals['_REQUIREMENTS_RESOURCESENTRY']._serialized_start=1725 + _globals['_REQUIREMENTS_RESOURCESENTRY']._serialized_end=1823 + _globals['_RESOURCESELECTOR']._serialized_start=1826 + _globals['_RESOURCESELECTOR']._serialized_end=2017 + _globals['_MATCHLABELS']._serialized_start=2020 + _globals['_MATCHLABELS']._serialized_end=2153 + _globals['_MATCHLABELS_LABELSENTRY']._serialized_start=2108 + _globals['_MATCHLABELS_LABELSENTRY']._serialized_end=2153 + _globals['_RESPONSEMETA']._serialized_start=2155 + _globals['_RESPONSEMETA']._serialized_end=2235 + _globals['_STATE']._serialized_start=2238 + _globals['_STATE']._serialized_end=2471 + _globals['_STATE_RESOURCESENTRY']._serialized_start=2381 + _globals['_STATE_RESOURCESENTRY']._serialized_end=2471 + _globals['_RESOURCE']._serialized_start=2474 + _globals['_RESOURCE']._serialized_end=2732 + _globals['_RESOURCE_CONNECTIONDETAILSENTRY']._serialized_start=2676 + _globals['_RESOURCE_CONNECTIONDETAILSENTRY']._serialized_end=2732 + _globals['_RESULT']._serialized_start=2735 + _globals['_RESULT']._serialized_end=2924 + _globals['_CONDITION']._serialized_start=2927 + _globals['_CONDITION']._serialized_end=3130 + _globals['_FUNCTIONRUNNERSERVICE']._serialized_start=3516 + _globals['_FUNCTIONRUNNERSERVICE']._serialized_end=3661 # @@protoc_insertion_point(module_scope) diff --git a/crossplane/function/proto/v1beta1/run_function_pb2.pyi b/crossplane/function/proto/v1beta1/run_function_pb2.pyi index 5ba6180..c0dd5d8 100644 --- a/crossplane/function/proto/v1beta1/run_function_pb2.pyi +++ b/crossplane/function/proto/v1beta1/run_function_pb2.pyi @@ -1,10 +1,11 @@ -from google.protobuf import struct_pb2 as _struct_pb2 from google.protobuf import duration_pb2 as _duration_pb2 +from google.protobuf import struct_pb2 as _struct_pb2 from google.protobuf.internal import containers as _containers from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message -from typing import ClassVar as _ClassVar, Iterable as _Iterable, Mapping as _Mapping, Optional as _Optional, Union as _Union +from collections.abc import Iterable as _Iterable, Mapping as _Mapping +from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union DESCRIPTOR: _descriptor.FileDescriptor @@ -49,8 +50,8 @@ STATUS_CONDITION_TRUE: Status STATUS_CONDITION_FALSE: Status class RunFunctionRequest(_message.Message): - __slots__ = ("meta", "observed", "desired", "input", "context", "extra_resources", "credentials") - class ExtraResourcesEntry(_message.Message): + __slots__ = ("meta", "observed", "desired", "input", "context", "required_resources", "credentials") + class RequiredResourcesEntry(_message.Message): __slots__ = ("key", "value") KEY_FIELD_NUMBER: _ClassVar[int] VALUE_FIELD_NUMBER: _ClassVar[int] @@ -69,16 +70,16 @@ class RunFunctionRequest(_message.Message): DESIRED_FIELD_NUMBER: _ClassVar[int] INPUT_FIELD_NUMBER: _ClassVar[int] CONTEXT_FIELD_NUMBER: _ClassVar[int] - EXTRA_RESOURCES_FIELD_NUMBER: _ClassVar[int] + REQUIRED_RESOURCES_FIELD_NUMBER: _ClassVar[int] CREDENTIALS_FIELD_NUMBER: _ClassVar[int] meta: RequestMeta observed: State desired: State input: _struct_pb2.Struct context: _struct_pb2.Struct - extra_resources: _containers.MessageMap[str, Resources] + required_resources: _containers.MessageMap[str, Resources] credentials: _containers.MessageMap[str, Credentials] - def __init__(self, meta: _Optional[_Union[RequestMeta, _Mapping]] = ..., observed: _Optional[_Union[State, _Mapping]] = ..., desired: _Optional[_Union[State, _Mapping]] = ..., input: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ..., context: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ..., extra_resources: _Optional[_Mapping[str, Resources]] = ..., credentials: _Optional[_Mapping[str, Credentials]] = ...) -> None: ... + def __init__(self, meta: _Optional[_Union[RequestMeta, _Mapping]] = ..., observed: _Optional[_Union[State, _Mapping]] = ..., desired: _Optional[_Union[State, _Mapping]] = ..., input: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ..., context: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ..., required_resources: _Optional[_Mapping[str, Resources]] = ..., credentials: _Optional[_Mapping[str, Credentials]] = ...) -> None: ... class Credentials(_message.Message): __slots__ = ("credential_data",) @@ -106,20 +107,22 @@ class Resources(_message.Message): def __init__(self, items: _Optional[_Iterable[_Union[Resource, _Mapping]]] = ...) -> None: ... class RunFunctionResponse(_message.Message): - __slots__ = ("meta", "desired", "results", "context", "requirements", "conditions") + __slots__ = ("meta", "desired", "results", "context", "requirements", "conditions", "output") META_FIELD_NUMBER: _ClassVar[int] DESIRED_FIELD_NUMBER: _ClassVar[int] RESULTS_FIELD_NUMBER: _ClassVar[int] CONTEXT_FIELD_NUMBER: _ClassVar[int] REQUIREMENTS_FIELD_NUMBER: _ClassVar[int] CONDITIONS_FIELD_NUMBER: _ClassVar[int] + OUTPUT_FIELD_NUMBER: _ClassVar[int] meta: ResponseMeta desired: State results: _containers.RepeatedCompositeFieldContainer[Result] context: _struct_pb2.Struct requirements: Requirements conditions: _containers.RepeatedCompositeFieldContainer[Condition] - def __init__(self, meta: _Optional[_Union[ResponseMeta, _Mapping]] = ..., desired: _Optional[_Union[State, _Mapping]] = ..., results: _Optional[_Iterable[_Union[Result, _Mapping]]] = ..., context: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ..., requirements: _Optional[_Union[Requirements, _Mapping]] = ..., conditions: _Optional[_Iterable[_Union[Condition, _Mapping]]] = ...) -> None: ... + output: _struct_pb2.Struct + def __init__(self, meta: _Optional[_Union[ResponseMeta, _Mapping]] = ..., desired: _Optional[_Union[State, _Mapping]] = ..., results: _Optional[_Iterable[_Union[Result, _Mapping]]] = ..., context: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ..., requirements: _Optional[_Union[Requirements, _Mapping]] = ..., conditions: _Optional[_Iterable[_Union[Condition, _Mapping]]] = ..., output: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ...) -> None: ... class RequestMeta(_message.Message): __slots__ = ("tag",) @@ -128,29 +131,31 @@ class RequestMeta(_message.Message): def __init__(self, tag: _Optional[str] = ...) -> None: ... class Requirements(_message.Message): - __slots__ = ("extra_resources",) - class ExtraResourcesEntry(_message.Message): + __slots__ = ("resources",) + class ResourcesEntry(_message.Message): __slots__ = ("key", "value") KEY_FIELD_NUMBER: _ClassVar[int] VALUE_FIELD_NUMBER: _ClassVar[int] key: str value: ResourceSelector def __init__(self, key: _Optional[str] = ..., value: _Optional[_Union[ResourceSelector, _Mapping]] = ...) -> None: ... - EXTRA_RESOURCES_FIELD_NUMBER: _ClassVar[int] - extra_resources: _containers.MessageMap[str, ResourceSelector] - def __init__(self, extra_resources: _Optional[_Mapping[str, ResourceSelector]] = ...) -> None: ... + RESOURCES_FIELD_NUMBER: _ClassVar[int] + resources: _containers.MessageMap[str, ResourceSelector] + def __init__(self, resources: _Optional[_Mapping[str, ResourceSelector]] = ...) -> None: ... class ResourceSelector(_message.Message): - __slots__ = ("api_version", "kind", "match_name", "match_labels") + __slots__ = ("api_version", "kind", "match_name", "match_labels", "namespace") API_VERSION_FIELD_NUMBER: _ClassVar[int] KIND_FIELD_NUMBER: _ClassVar[int] MATCH_NAME_FIELD_NUMBER: _ClassVar[int] MATCH_LABELS_FIELD_NUMBER: _ClassVar[int] + NAMESPACE_FIELD_NUMBER: _ClassVar[int] api_version: str kind: str match_name: str match_labels: MatchLabels - def __init__(self, api_version: _Optional[str] = ..., kind: _Optional[str] = ..., match_name: _Optional[str] = ..., match_labels: _Optional[_Union[MatchLabels, _Mapping]] = ...) -> None: ... + namespace: str + def __init__(self, api_version: _Optional[str] = ..., kind: _Optional[str] = ..., match_name: _Optional[str] = ..., match_labels: _Optional[_Union[MatchLabels, _Mapping]] = ..., namespace: _Optional[str] = ...) -> None: ... class MatchLabels(_message.Message): __slots__ = ("labels",) @@ -171,7 +176,7 @@ class ResponseMeta(_message.Message): TTL_FIELD_NUMBER: _ClassVar[int] tag: str ttl: _duration_pb2.Duration - def __init__(self, tag: _Optional[str] = ..., ttl: _Optional[_Union[_duration_pb2.Duration, _Mapping]] = ...) -> None: ... + def __init__(self, tag: _Optional[str] = ..., ttl: _Optional[_Union[datetime.timedelta, _duration_pb2.Duration, _Mapping]] = ...) -> None: ... class State(_message.Message): __slots__ = ("composite", "resources") diff --git a/crossplane/function/proto/v1beta1/run_function_pb2_grpc.py b/crossplane/function/proto/v1beta1/run_function_pb2_grpc.py index 1bd4f5d..281cd23 100644 --- a/crossplane/function/proto/v1beta1/run_function_pb2_grpc.py +++ b/crossplane/function/proto/v1beta1/run_function_pb2_grpc.py @@ -5,7 +5,7 @@ from crossplane.function.proto.v1beta1 import run_function_pb2 as crossplane_dot_function_dot_proto_dot_v1beta1_dot_run__function__pb2 -GRPC_GENERATED_VERSION = '1.71.0' +GRPC_GENERATED_VERSION = '1.73.1' GRPC_VERSION = grpc.__version__ _version_not_supported = False @@ -26,7 +26,7 @@ class FunctionRunnerServiceStub(object): - """A FunctionRunnerService is a Composition Function. + """A FunctionRunnerService is a function. """ def __init__(self, channel): @@ -43,11 +43,11 @@ def __init__(self, channel): class FunctionRunnerServiceServicer(object): - """A FunctionRunnerService is a Composition Function. + """A FunctionRunnerService is a function. """ def RunFunction(self, request, context): - """RunFunction runs the Composition Function. + """RunFunction runs the function. """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') @@ -70,7 +70,7 @@ def add_FunctionRunnerServiceServicer_to_server(servicer, server): # This class is part of an EXPERIMENTAL API. class FunctionRunnerService(object): - """A FunctionRunnerService is a Composition Function. + """A FunctionRunnerService is a function. """ @staticmethod From 12be880f52a092e1ea5780daed01c5387c106c14 Mon Sep 17 00:00:00 2001 From: Nic Cope Date: Fri, 18 Jul 2025 17:19:08 -0700 Subject: [PATCH 06/11] Add support for operation functions This PR adds helpers to the Python SDK to make writing operation functions easier. Operation functions use the same FunctionRunnerService RPC as composition functions, but they have different patterns for accessing required resources and returning output data. The new request.py module provides functions to get required resources (previously called "extra resources" in composition functions) and includes a helper specifically for accessing watched resources in WatchOperations. The response.py module gets new functions to set operation output and build resource requirements Signed-off-by: Nic Cope --- .gitignore | 3 + crossplane/function/request.py | 75 +++++++++++ crossplane/function/response.py | 72 +++++++++++ tests/test_request.py | 217 ++++++++++++++++++++++++++++++++ tests/test_response.py | 145 +++++++++++++++++++++ 5 files changed, 512 insertions(+) create mode 100644 crossplane/function/request.py create mode 100644 tests/test_request.py diff --git a/.gitignore b/.gitignore index 9527b70..9c08e8b 100644 --- a/.gitignore +++ b/.gitignore @@ -161,3 +161,6 @@ cython_debug/ # We don't commit our docs - instead we generate them and upload to GitHub pages. docs + +# AIs +.claude/ diff --git a/crossplane/function/request.py b/crossplane/function/request.py new file mode 100644 index 0000000..c4516e6 --- /dev/null +++ b/crossplane/function/request.py @@ -0,0 +1,75 @@ +# Copyright 2025 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. + +"""Utilities for working with RunFunctionRequests.""" + +import crossplane.function.proto.v1.run_function_pb2 as fnv1 +from crossplane.function import resource + + +def get_required_resources(req: fnv1.RunFunctionRequest, name: str) -> list[dict]: + """Get required resources by name from the request. + + Args: + req: The RunFunctionRequest containing required resources. + name: The name of the required resource set to get. + + Returns: + A list of resources as dictionaries. Empty list if not found. + + Required resources are previously called "extra resources" in composition + functions. For operation functions, there are no observed resources, so + all resources are "required" resources that the function requested. + """ + if name not in req.required_resources: + return [] + + return [ + resource.struct_to_dict(item.resource) + for item in req.required_resources[name].items + ] + + +def get_watched_resource(req: fnv1.RunFunctionRequest) -> dict | None: + """Get the watched resource that triggered this operation. + + Args: + req: The RunFunctionRequest to check for a watched resource. + + Returns: + The watched resource as a dictionary, or None if not found. + + When a WatchOperation creates an Operation, it injects the resource that + changed using the special requirement name 'ops.crossplane.io/watched-resource'. + This helper makes it easy to access that resource. + """ + watched = get_required_resources(req, "ops.crossplane.io/watched-resource") + return watched[0] if watched else None + + +def get_required_resource(req: fnv1.RunFunctionRequest, name: str) -> dict | None: + """Get a single required resource by name from the request. + + Args: + req: The RunFunctionRequest containing required resources. + name: The name of the required resource to get. + + Returns: + The first resource as a dictionary, or None if not found. + + This is a convenience function for when you know there should be exactly + one resource with the given requirement name. + """ + resources = get_required_resources(req, name) + return resources[0] if resources else None diff --git a/crossplane/function/response.py b/crossplane/function/response.py index b37fd8d..72222b6 100644 --- a/crossplane/function/response.py +++ b/crossplane/function/response.py @@ -17,8 +17,10 @@ import datetime from google.protobuf import duration_pb2 as durationpb +from google.protobuf import struct_pb2 as structpb import crossplane.function.proto.v1.run_function_pb2 as fnv1 +from crossplane.function import resource """The default TTL for which a RunFunctionResponse may be cached.""" DEFAULT_TTL = datetime.timedelta(minutes=1) @@ -77,3 +79,73 @@ def fatal(rsp: fnv1.RunFunctionResponse, message: str) -> None: message=message, ) ) + + +def set_output(rsp: fnv1.RunFunctionResponse, output: dict | structpb.Struct) -> None: + """Set the output field in a RunFunctionResponse for operation functions. + + Args: + rsp: The RunFunctionResponse to update. + output: The output data as a dictionary or protobuf Struct. + + Operation functions can return arbitrary output data that will be written + to the Operation's status.pipeline field. This function sets that output + on the response. + """ + match output: + case dict(): + rsp.output.CopyFrom(resource.dict_to_struct(output)) + case structpb.Struct(): + rsp.output.CopyFrom(output) + case _: + t = type(output) + msg = f"Unsupported output type: {t}" + raise TypeError(msg) + + +def require_resources( # noqa: PLR0913 + rsp: fnv1.RunFunctionResponse, + name: str, + api_version: str, + kind: str, + *, + match_name: str | None = None, + match_labels: dict[str, str] | None = None, + namespace: str | None = None, +) -> None: + """Add a resource requirement to the response. + + Args: + rsp: The RunFunctionResponse to update. + name: The name to use for this requirement. + api_version: The API version of resources to require. + kind: The kind of resources to require. + match_name: Match a resource by name (mutually exclusive with match_labels). + match_labels: Match resources by labels (mutually exclusive with match_name). + namespace: The namespace to search in (optional). + + Raises: + ValueError: If both match_name and match_labels are provided, or neither. + + This tells Crossplane to fetch the specified resources and include them + in the next call to the function in req.required_resources[name]. + """ + if (match_name is None) == (match_labels is None): + msg = "Exactly one of match_name or match_labels must be provided" + raise ValueError(msg) + + selector = fnv1.ResourceSelector( + api_version=api_version, + kind=kind, + ) + + if match_name is not None: + selector.match_name = match_name + + if match_labels is not None: + selector.match_labels.labels.update(match_labels) + + if namespace is not None: + selector.namespace = namespace + + rsp.requirements.resources[name].CopyFrom(selector) diff --git a/tests/test_request.py b/tests/test_request.py new file mode 100644 index 0000000..f8079d3 --- /dev/null +++ b/tests/test_request.py @@ -0,0 +1,217 @@ +# Copyright 2025 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. + +import dataclasses +import unittest + +import crossplane.function.proto.v1.run_function_pb2 as fnv1 +from crossplane.function import logging, request, resource + + +class TestRequest(unittest.TestCase): + def setUp(self) -> None: + logging.configure(level=logging.Level.DISABLED) + + def test_get_required_resources(self) -> None: + @dataclasses.dataclass + class TestCase: + reason: str + req: fnv1.RunFunctionRequest + name: str + want: list[dict] + + cases = [ + TestCase( + reason="Should return empty list when requirement name not found.", + req=fnv1.RunFunctionRequest(), + name="non-existent", + want=[], + ), + TestCase( + reason="Should return resources when requirement name exists.", + req=fnv1.RunFunctionRequest( + required_resources={ + "test-resources": fnv1.Resources( + items=[ + fnv1.Resource( + resource=resource.dict_to_struct( + { + "apiVersion": "v1", + "kind": "Pod", + "metadata": {"name": "test-pod"}, + } + ) + ), + fnv1.Resource( + resource=resource.dict_to_struct( + { + "apiVersion": "v1", + "kind": "Service", + "metadata": {"name": "test-svc"}, + } + ) + ), + ] + ) + } + ), + name="test-resources", + want=[ + { + "apiVersion": "v1", + "kind": "Pod", + "metadata": {"name": "test-pod"}, + }, + { + "apiVersion": "v1", + "kind": "Service", + "metadata": {"name": "test-svc"}, + }, + ], + ), + ] + + for case in cases: + got = request.get_required_resources(case.req, case.name) + self.assertEqual(case.want, got, case.reason) + + def test_get_watched_resource(self) -> None: + @dataclasses.dataclass + class TestCase: + reason: str + req: fnv1.RunFunctionRequest + want: dict | None + + cases = [ + TestCase( + reason="Should return None when no watched resource exists.", + req=fnv1.RunFunctionRequest(), + want=None, + ), + TestCase( + reason="Should return watched resource when it exists.", + req=fnv1.RunFunctionRequest( + required_resources={ + "ops.crossplane.io/watched-resource": fnv1.Resources( + items=[ + fnv1.Resource( + resource=resource.dict_to_struct( + { + "apiVersion": "example.org/v1", + "kind": "App", + "metadata": {"name": "watched-app"}, + } + ) + ) + ] + ) + } + ), + want={ + "apiVersion": "example.org/v1", + "kind": "App", + "metadata": {"name": "watched-app"}, + }, + ), + ] + + for case in cases: + got = request.get_watched_resource(case.req) + self.assertEqual(case.want, got, case.reason) + + def test_get_required_resource(self) -> None: + @dataclasses.dataclass + class TestCase: + reason: str + req: fnv1.RunFunctionRequest + name: str + want: dict | None + + cases = [ + TestCase( + reason="Should return None when requirement name not found.", + req=fnv1.RunFunctionRequest(), + name="non-existent", + want=None, + ), + TestCase( + reason="Should return first resource when requirement name exists.", + req=fnv1.RunFunctionRequest( + required_resources={ + "single-resource": fnv1.Resources( + items=[ + fnv1.Resource( + resource=resource.dict_to_struct( + { + "apiVersion": "v1", + "kind": "ConfigMap", + "metadata": {"name": "test-cm"}, + } + ) + ) + ] + ) + } + ), + name="single-resource", + want={ + "apiVersion": "v1", + "kind": "ConfigMap", + "metadata": {"name": "test-cm"}, + }, + ), + TestCase( + reason="Should return first resource when multiple resources exist.", + req=fnv1.RunFunctionRequest( + required_resources={ + "multi-resource": fnv1.Resources( + items=[ + fnv1.Resource( + resource=resource.dict_to_struct( + { + "apiVersion": "v1", + "kind": "Secret", + "metadata": {"name": "first-secret"}, + } + ) + ), + fnv1.Resource( + resource=resource.dict_to_struct( + { + "apiVersion": "v1", + "kind": "Secret", + "metadata": {"name": "second-secret"}, + } + ) + ), + ] + ) + } + ), + name="multi-resource", + want={ + "apiVersion": "v1", + "kind": "Secret", + "metadata": {"name": "first-secret"}, + }, + ), + ] + + for case in cases: + got = request.get_required_resource(case.req, case.name) + self.assertEqual(case.want, got, case.reason) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_response.py b/tests/test_response.py index 8273c50..4930592 100644 --- a/tests/test_response.py +++ b/tests/test_response.py @@ -18,6 +18,7 @@ from google.protobuf import duration_pb2 as durationpb from google.protobuf import json_format +from google.protobuf import struct_pb2 as structpb from crossplane.function import logging, resource, response from crossplane.function.proto.v1 import run_function_pb2 as fnv1 @@ -70,6 +71,150 @@ class TestCase: "-want, +got", ) + def test_set_output(self) -> None: + @dataclasses.dataclass + class TestCase: + reason: str + rsp: fnv1.RunFunctionResponse + output: dict | structpb.Struct + want_output: dict + + cases = [ + TestCase( + reason="Setting output from dict should work.", + rsp=fnv1.RunFunctionResponse(), + output={"status": "success", "processed": 42}, + want_output={"status": "success", "processed": 42}, + ), + TestCase( + reason="Setting output from Struct should work.", + rsp=fnv1.RunFunctionResponse(), + output=resource.dict_to_struct({"result": "completed", "count": 3}), + want_output={"result": "completed", "count": 3}, + ), + ] + + for case in cases: + response.set_output(case.rsp, case.output) + got_output = resource.struct_to_dict(case.rsp.output) + self.assertEqual(case.want_output, got_output, case.reason) + + def test_set_output_invalid_type(self) -> None: + rsp = fnv1.RunFunctionResponse() + with self.assertRaises(TypeError): + response.set_output(rsp, "invalid-string-type") + + def test_require_resources(self) -> None: + @dataclasses.dataclass + class TestCase: + reason: str + rsp: fnv1.RunFunctionResponse + name: str + api_version: str + kind: str + match_name: str | None + match_labels: dict[str, str] | None + namespace: str | None + want_selector: fnv1.ResourceSelector + + cases = [ + TestCase( + reason="Should create requirement with match_name.", + rsp=fnv1.RunFunctionResponse(), + name="test-pods", + api_version="v1", + kind="Pod", + match_name="my-pod", + match_labels=None, + namespace="default", + want_selector=fnv1.ResourceSelector( + api_version="v1", + kind="Pod", + match_name="my-pod", + namespace="default", + ), + ), + TestCase( + reason="Should create requirement with match_labels.", + rsp=fnv1.RunFunctionResponse(), + name="app-pods", + api_version="v1", + kind="Pod", + match_name=None, + match_labels={"app": "web", "version": "v1.2.3"}, + namespace="production", + want_selector=fnv1.ResourceSelector( + api_version="v1", + kind="Pod", + match_labels=fnv1.MatchLabels( + labels={"app": "web", "version": "v1.2.3"} + ), + namespace="production", + ), + ), + TestCase( + reason="Should create requirement without namespace.", + rsp=fnv1.RunFunctionResponse(), + name="cluster-resources", + api_version="v1", + kind="Node", + match_name="worker-1", + match_labels=None, + namespace=None, + want_selector=fnv1.ResourceSelector( + api_version="v1", + kind="Node", + match_name="worker-1", + ), + ), + ] + + for case in cases: + response.require_resources( + case.rsp, + case.name, + case.api_version, + case.kind, + match_name=case.match_name, + match_labels=case.match_labels, + namespace=case.namespace, + ) + + # Check that the requirement was added + self.assertIn(case.name, case.rsp.requirements.resources, case.reason) + got_selector = case.rsp.requirements.resources[case.name] + + self.assertEqual( + json_format.MessageToJson(case.want_selector), + json_format.MessageToJson(got_selector), + case.reason, + ) + + def test_require_resources_invalid_args(self) -> None: + rsp = fnv1.RunFunctionResponse() + + # Should raise ValueError if both match_name and match_labels are provided + with self.assertRaises(ValueError): + response.require_resources( + rsp, + "test", + "v1", + "Pod", + match_name="pod-name", + match_labels={"app": "test"}, + ) + + # Should raise ValueError if neither match_name nor match_labels are provided + with self.assertRaises(ValueError): + response.require_resources( + rsp, + "test", + "v1", + "Pod", + match_name=None, + match_labels=None, + ) + if __name__ == "__main__": unittest.main() From 711fad09d9945816cf8076ebbf3abd460f9b4e43 Mon Sep 17 00:00:00 2001 From: Nic Cope Date: Mon, 4 Aug 2025 19:44:12 -0700 Subject: [PATCH 07/11] Keep extra_resources support at the proto level We still add required_resources though, as the new (preferred) way to do the same thing. Signed-off-by: Nic Cope --- .../function/proto/v1/run_function.proto | 32 ++++- .../function/proto/v1/run_function_pb2.py | 122 ++++++++++-------- .../function/proto/v1/run_function_pb2.pyi | 32 ++++- .../function/proto/v1beta1/run_function.proto | 30 ++++- .../proto/v1beta1/run_function_pb2.py | 122 ++++++++++-------- .../proto/v1beta1/run_function_pb2.pyi | 32 ++++- 6 files changed, 233 insertions(+), 137 deletions(-) diff --git a/crossplane/function/proto/v1/run_function.proto b/crossplane/function/proto/v1/run_function.proto index b67c085..557fd34 100644 --- a/crossplane/function/proto/v1/run_function.proto +++ b/crossplane/function/proto/v1/run_function.proto @@ -27,7 +27,7 @@ package apiextensions.fn.proto.v1; import "google/protobuf/duration.proto"; import "google/protobuf/struct.proto"; -option go_package = "github.com/crossplane/crossplane/proto/fn/v1"; +option go_package = "github.com/crossplane/crossplane/v2/proto/fn/v1"; // A FunctionRunnerService is a function. service FunctionRunnerService { @@ -69,15 +69,27 @@ message RunFunctionRequest { // Optional resources that the function specified in its requirements. Note // that resources is a map to Resources, plural. The map key corresponds to - // the key in a RunFunctionResponse's requirements.resources field. If a - // function requested required resources that did not exist, Crossplane sets + // the key in a RunFunctionResponse's requirements.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 required_resources = 6; + // satisfy the request. This field is only populated when the function uses + // extra_resources in its requirements. + // + // Deprecated: Use required_resources instead. + map extra_resources = 6 [deprecated = true]; // Optional credentials that this function may use to communicate with an // external system. map credentials = 7; + + // Optional resources that the function specified in its requirements. Note + // that resources is a map to Resources, plural. The map key corresponds to + // the key in a RunFunctionResponse's requirements.resources field. If a + // function requested required resources that did not exist, Crossplane sets + // the map key to an empty Resources message to indicate that it attempted to + // satisfy the request. This field is only populated when the function uses + // resources in its requirements. + map required_resources = 8; } // Credentials that a function may use to communicate with an external system. @@ -150,7 +162,13 @@ message RequestMeta { message Requirements { // Resources that this function requires. The map key uniquely identifies the // group of resources. - map resources = 1; + // + // Deprecated: Use resources instead. + map extra_resources = 1 [deprecated = true]; + + // Resources that this function requires. The map key uniquely identifies the + // group of resources. + map resources = 2; } // ResourceSelector selects a group of resources, either by name or by label. @@ -349,4 +367,4 @@ enum Status { STATUS_CONDITION_TRUE = 2; STATUS_CONDITION_FALSE = 3; -} +} \ No newline at end of file diff --git a/crossplane/function/proto/v1/run_function_pb2.py b/crossplane/function/proto/v1/run_function_pb2.py index 18336c7..17eb5d0 100644 --- a/crossplane/function/proto/v1/run_function_pb2.py +++ b/crossplane/function/proto/v1/run_function_pb2.py @@ -26,78 +26,90 @@ from google.protobuf import struct_pb2 as google_dot_protobuf_dot_struct__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n/crossplane/function/proto/v1/run_function.proto\x12\x19\x61piextensions.fn.proto.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1cgoogle/protobuf/struct.proto\"\x96\x05\n\x12RunFunctionRequest\x12\x34\n\x04meta\x18\x01 \x01(\x0b\x32&.apiextensions.fn.proto.v1.RequestMeta\x12\x32\n\x08observed\x18\x02 \x01(\x0b\x32 .apiextensions.fn.proto.v1.State\x12\x31\n\x07\x64\x65sired\x18\x03 \x01(\x0b\x32 .apiextensions.fn.proto.v1.State\x12+\n\x05input\x18\x04 \x01(\x0b\x32\x17.google.protobuf.StructH\x00\x88\x01\x01\x12-\n\x07\x63ontext\x18\x05 \x01(\x0b\x32\x17.google.protobuf.StructH\x01\x88\x01\x01\x12`\n\x12required_resources\x18\x06 \x03(\x0b\x32\x44.apiextensions.fn.proto.v1.RunFunctionRequest.RequiredResourcesEntry\x12S\n\x0b\x63redentials\x18\x07 \x03(\x0b\x32>.apiextensions.fn.proto.v1.RunFunctionRequest.CredentialsEntry\x1a^\n\x16RequiredResourcesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x33\n\x05value\x18\x02 \x01(\x0b\x32$.apiextensions.fn.proto.v1.Resources:\x02\x38\x01\x1aZ\n\x10\x43redentialsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x35\n\x05value\x18\x02 \x01(\x0b\x32&.apiextensions.fn.proto.v1.Credentials:\x02\x38\x01\x42\x08\n\x06_inputB\n\n\x08_context\"]\n\x0b\x43redentials\x12\x44\n\x0f\x63redential_data\x18\x01 \x01(\x0b\x32).apiextensions.fn.proto.v1.CredentialDataH\x00\x42\x08\n\x06source\"\x80\x01\n\x0e\x43redentialData\x12\x41\n\x04\x64\x61ta\x18\x01 \x03(\x0b\x32\x33.apiextensions.fn.proto.v1.CredentialData.DataEntry\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\"?\n\tResources\x12\x32\n\x05items\x18\x01 \x03(\x0b\x32#.apiextensions.fn.proto.v1.Resource\"\xa0\x03\n\x13RunFunctionResponse\x12\x35\n\x04meta\x18\x01 \x01(\x0b\x32\'.apiextensions.fn.proto.v1.ResponseMeta\x12\x31\n\x07\x64\x65sired\x18\x02 \x01(\x0b\x32 .apiextensions.fn.proto.v1.State\x12\x32\n\x07results\x18\x03 \x03(\x0b\x32!.apiextensions.fn.proto.v1.Result\x12-\n\x07\x63ontext\x18\x04 \x01(\x0b\x32\x17.google.protobuf.StructH\x00\x88\x01\x01\x12=\n\x0crequirements\x18\x05 \x01(\x0b\x32\'.apiextensions.fn.proto.v1.Requirements\x12\x38\n\nconditions\x18\x06 \x03(\x0b\x32$.apiextensions.fn.proto.v1.Condition\x12,\n\x06output\x18\x07 \x01(\x0b\x32\x17.google.protobuf.StructH\x01\x88\x01\x01\x42\n\n\x08_contextB\t\n\x07_output\"\x1a\n\x0bRequestMeta\x12\x0b\n\x03tag\x18\x01 \x01(\t\"\xb8\x01\n\x0cRequirements\x12I\n\tresources\x18\x01 \x03(\x0b\x32\x36.apiextensions.fn.proto.v1.Requirements.ResourcesEntry\x1a]\n\x0eResourcesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12:\n\x05value\x18\x02 \x01(\x0b\x32+.apiextensions.fn.proto.v1.ResourceSelector:\x02\x38\x01\"\xba\x01\n\x10ResourceSelector\x12\x13\n\x0b\x61pi_version\x18\x01 \x01(\t\x12\x0c\n\x04kind\x18\x02 \x01(\t\x12\x14\n\nmatch_name\x18\x03 \x01(\tH\x00\x12>\n\x0cmatch_labels\x18\x04 \x01(\x0b\x32&.apiextensions.fn.proto.v1.MatchLabelsH\x00\x12\x16\n\tnamespace\x18\x05 \x01(\tH\x01\x88\x01\x01\x42\x07\n\x05matchB\x0c\n\n_namespace\"\x80\x01\n\x0bMatchLabels\x12\x42\n\x06labels\x18\x01 \x03(\x0b\x32\x32.apiextensions.fn.proto.v1.MatchLabels.LabelsEntry\x1a-\n\x0bLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"P\n\x0cResponseMeta\x12\x0b\n\x03tag\x18\x01 \x01(\t\x12+\n\x03ttl\x18\x02 \x01(\x0b\x32\x19.google.protobuf.DurationH\x00\x88\x01\x01\x42\x06\n\x04_ttl\"\xda\x01\n\x05State\x12\x36\n\tcomposite\x18\x01 \x01(\x0b\x32#.apiextensions.fn.proto.v1.Resource\x12\x42\n\tresources\x18\x02 \x03(\x0b\x32/.apiextensions.fn.proto.v1.State.ResourcesEntry\x1aU\n\x0eResourcesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x32\n\x05value\x18\x02 \x01(\x0b\x32#.apiextensions.fn.proto.v1.Resource:\x02\x38\x01\"\xf8\x01\n\x08Resource\x12)\n\x08resource\x18\x01 \x01(\x0b\x32\x17.google.protobuf.Struct\x12V\n\x12\x63onnection_details\x18\x02 \x03(\x0b\x32:.apiextensions.fn.proto.v1.Resource.ConnectionDetailsEntry\x12/\n\x05ready\x18\x03 \x01(\x0e\x32 .apiextensions.fn.proto.v1.Ready\x1a\x38\n\x16\x43onnectionDetailsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\"\xb3\x01\n\x06Result\x12\x35\n\x08severity\x18\x01 \x01(\x0e\x32#.apiextensions.fn.proto.v1.Severity\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x13\n\x06reason\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x36\n\x06target\x18\x04 \x01(\x0e\x32!.apiextensions.fn.proto.v1.TargetH\x01\x88\x01\x01\x42\t\n\x07_reasonB\t\n\x07_target\"\xc1\x01\n\tCondition\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x31\n\x06status\x18\x02 \x01(\x0e\x32!.apiextensions.fn.proto.v1.Status\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x14\n\x07message\x18\x04 \x01(\tH\x00\x88\x01\x01\x12\x36\n\x06target\x18\x05 \x01(\x0e\x32!.apiextensions.fn.proto.v1.TargetH\x01\x88\x01\x01\x42\n\n\x08_messageB\t\n\x07_target*?\n\x05Ready\x12\x15\n\x11READY_UNSPECIFIED\x10\x00\x12\x0e\n\nREADY_TRUE\x10\x01\x12\x0f\n\x0bREADY_FALSE\x10\x02*c\n\x08Severity\x12\x18\n\x14SEVERITY_UNSPECIFIED\x10\x00\x12\x12\n\x0eSEVERITY_FATAL\x10\x01\x12\x14\n\x10SEVERITY_WARNING\x10\x02\x12\x13\n\x0fSEVERITY_NORMAL\x10\x03*V\n\x06Target\x12\x16\n\x12TARGET_UNSPECIFIED\x10\x00\x12\x14\n\x10TARGET_COMPOSITE\x10\x01\x12\x1e\n\x1aTARGET_COMPOSITE_AND_CLAIM\x10\x02*\x7f\n\x06Status\x12 \n\x1cSTATUS_CONDITION_UNSPECIFIED\x10\x00\x12\x1c\n\x18STATUS_CONDITION_UNKNOWN\x10\x01\x12\x19\n\x15STATUS_CONDITION_TRUE\x10\x02\x12\x1a\n\x16STATUS_CONDITION_FALSE\x10\x03\x32\x87\x01\n\x15\x46unctionRunnerService\x12n\n\x0bRunFunction\x12-.apiextensions.fn.proto.v1.RunFunctionRequest\x1a..apiextensions.fn.proto.v1.RunFunctionResponse\"\x00\x42.Z,github.com/crossplane/crossplane/proto/fn/v1b\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n/crossplane/function/proto/v1/run_function.proto\x12\x19\x61piextensions.fn.proto.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1cgoogle/protobuf/struct.proto\"\xd3\x06\n\x12RunFunctionRequest\x12\x34\n\x04meta\x18\x01 \x01(\x0b\x32&.apiextensions.fn.proto.v1.RequestMeta\x12\x32\n\x08observed\x18\x02 \x01(\x0b\x32 .apiextensions.fn.proto.v1.State\x12\x31\n\x07\x64\x65sired\x18\x03 \x01(\x0b\x32 .apiextensions.fn.proto.v1.State\x12+\n\x05input\x18\x04 \x01(\x0b\x32\x17.google.protobuf.StructH\x00\x88\x01\x01\x12-\n\x07\x63ontext\x18\x05 \x01(\x0b\x32\x17.google.protobuf.StructH\x01\x88\x01\x01\x12^\n\x0f\x65xtra_resources\x18\x06 \x03(\x0b\x32\x41.apiextensions.fn.proto.v1.RunFunctionRequest.ExtraResourcesEntryB\x02\x18\x01\x12S\n\x0b\x63redentials\x18\x07 \x03(\x0b\x32>.apiextensions.fn.proto.v1.RunFunctionRequest.CredentialsEntry\x12`\n\x12required_resources\x18\x08 \x03(\x0b\x32\x44.apiextensions.fn.proto.v1.RunFunctionRequest.RequiredResourcesEntry\x1a[\n\x13\x45xtraResourcesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x33\n\x05value\x18\x02 \x01(\x0b\x32$.apiextensions.fn.proto.v1.Resources:\x02\x38\x01\x1aZ\n\x10\x43redentialsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x35\n\x05value\x18\x02 \x01(\x0b\x32&.apiextensions.fn.proto.v1.Credentials:\x02\x38\x01\x1a^\n\x16RequiredResourcesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x33\n\x05value\x18\x02 \x01(\x0b\x32$.apiextensions.fn.proto.v1.Resources:\x02\x38\x01\x42\x08\n\x06_inputB\n\n\x08_context\"]\n\x0b\x43redentials\x12\x44\n\x0f\x63redential_data\x18\x01 \x01(\x0b\x32).apiextensions.fn.proto.v1.CredentialDataH\x00\x42\x08\n\x06source\"\x80\x01\n\x0e\x43redentialData\x12\x41\n\x04\x64\x61ta\x18\x01 \x03(\x0b\x32\x33.apiextensions.fn.proto.v1.CredentialData.DataEntry\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\"?\n\tResources\x12\x32\n\x05items\x18\x01 \x03(\x0b\x32#.apiextensions.fn.proto.v1.Resource\"\xa0\x03\n\x13RunFunctionResponse\x12\x35\n\x04meta\x18\x01 \x01(\x0b\x32\'.apiextensions.fn.proto.v1.ResponseMeta\x12\x31\n\x07\x64\x65sired\x18\x02 \x01(\x0b\x32 .apiextensions.fn.proto.v1.State\x12\x32\n\x07results\x18\x03 \x03(\x0b\x32!.apiextensions.fn.proto.v1.Result\x12-\n\x07\x63ontext\x18\x04 \x01(\x0b\x32\x17.google.protobuf.StructH\x00\x88\x01\x01\x12=\n\x0crequirements\x18\x05 \x01(\x0b\x32\'.apiextensions.fn.proto.v1.Requirements\x12\x38\n\nconditions\x18\x06 \x03(\x0b\x32$.apiextensions.fn.proto.v1.Condition\x12,\n\x06output\x18\x07 \x01(\x0b\x32\x17.google.protobuf.StructH\x01\x88\x01\x01\x42\n\n\x08_contextB\t\n\x07_output\"\x1a\n\x0bRequestMeta\x12\x0b\n\x03tag\x18\x01 \x01(\t\"\xf6\x02\n\x0cRequirements\x12X\n\x0f\x65xtra_resources\x18\x01 \x03(\x0b\x32;.apiextensions.fn.proto.v1.Requirements.ExtraResourcesEntryB\x02\x18\x01\x12I\n\tresources\x18\x02 \x03(\x0b\x32\x36.apiextensions.fn.proto.v1.Requirements.ResourcesEntry\x1a\x62\n\x13\x45xtraResourcesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12:\n\x05value\x18\x02 \x01(\x0b\x32+.apiextensions.fn.proto.v1.ResourceSelector:\x02\x38\x01\x1a]\n\x0eResourcesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12:\n\x05value\x18\x02 \x01(\x0b\x32+.apiextensions.fn.proto.v1.ResourceSelector:\x02\x38\x01\"\xba\x01\n\x10ResourceSelector\x12\x13\n\x0b\x61pi_version\x18\x01 \x01(\t\x12\x0c\n\x04kind\x18\x02 \x01(\t\x12\x14\n\nmatch_name\x18\x03 \x01(\tH\x00\x12>\n\x0cmatch_labels\x18\x04 \x01(\x0b\x32&.apiextensions.fn.proto.v1.MatchLabelsH\x00\x12\x16\n\tnamespace\x18\x05 \x01(\tH\x01\x88\x01\x01\x42\x07\n\x05matchB\x0c\n\n_namespace\"\x80\x01\n\x0bMatchLabels\x12\x42\n\x06labels\x18\x01 \x03(\x0b\x32\x32.apiextensions.fn.proto.v1.MatchLabels.LabelsEntry\x1a-\n\x0bLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"P\n\x0cResponseMeta\x12\x0b\n\x03tag\x18\x01 \x01(\t\x12+\n\x03ttl\x18\x02 \x01(\x0b\x32\x19.google.protobuf.DurationH\x00\x88\x01\x01\x42\x06\n\x04_ttl\"\xda\x01\n\x05State\x12\x36\n\tcomposite\x18\x01 \x01(\x0b\x32#.apiextensions.fn.proto.v1.Resource\x12\x42\n\tresources\x18\x02 \x03(\x0b\x32/.apiextensions.fn.proto.v1.State.ResourcesEntry\x1aU\n\x0eResourcesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x32\n\x05value\x18\x02 \x01(\x0b\x32#.apiextensions.fn.proto.v1.Resource:\x02\x38\x01\"\xf8\x01\n\x08Resource\x12)\n\x08resource\x18\x01 \x01(\x0b\x32\x17.google.protobuf.Struct\x12V\n\x12\x63onnection_details\x18\x02 \x03(\x0b\x32:.apiextensions.fn.proto.v1.Resource.ConnectionDetailsEntry\x12/\n\x05ready\x18\x03 \x01(\x0e\x32 .apiextensions.fn.proto.v1.Ready\x1a\x38\n\x16\x43onnectionDetailsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\"\xb3\x01\n\x06Result\x12\x35\n\x08severity\x18\x01 \x01(\x0e\x32#.apiextensions.fn.proto.v1.Severity\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x13\n\x06reason\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x36\n\x06target\x18\x04 \x01(\x0e\x32!.apiextensions.fn.proto.v1.TargetH\x01\x88\x01\x01\x42\t\n\x07_reasonB\t\n\x07_target\"\xc1\x01\n\tCondition\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x31\n\x06status\x18\x02 \x01(\x0e\x32!.apiextensions.fn.proto.v1.Status\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x14\n\x07message\x18\x04 \x01(\tH\x00\x88\x01\x01\x12\x36\n\x06target\x18\x05 \x01(\x0e\x32!.apiextensions.fn.proto.v1.TargetH\x01\x88\x01\x01\x42\n\n\x08_messageB\t\n\x07_target*?\n\x05Ready\x12\x15\n\x11READY_UNSPECIFIED\x10\x00\x12\x0e\n\nREADY_TRUE\x10\x01\x12\x0f\n\x0bREADY_FALSE\x10\x02*c\n\x08Severity\x12\x18\n\x14SEVERITY_UNSPECIFIED\x10\x00\x12\x12\n\x0eSEVERITY_FATAL\x10\x01\x12\x14\n\x10SEVERITY_WARNING\x10\x02\x12\x13\n\x0fSEVERITY_NORMAL\x10\x03*V\n\x06Target\x12\x16\n\x12TARGET_UNSPECIFIED\x10\x00\x12\x14\n\x10TARGET_COMPOSITE\x10\x01\x12\x1e\n\x1aTARGET_COMPOSITE_AND_CLAIM\x10\x02*\x7f\n\x06Status\x12 \n\x1cSTATUS_CONDITION_UNSPECIFIED\x10\x00\x12\x1c\n\x18STATUS_CONDITION_UNKNOWN\x10\x01\x12\x19\n\x15STATUS_CONDITION_TRUE\x10\x02\x12\x1a\n\x16STATUS_CONDITION_FALSE\x10\x03\x32\x87\x01\n\x15\x46unctionRunnerService\x12n\n\x0bRunFunction\x12-.apiextensions.fn.proto.v1.RunFunctionRequest\x1a..apiextensions.fn.proto.v1.RunFunctionResponse\"\x00\x42\x31Z/github.com/crossplane/crossplane/v2/proto/fn/v1b\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'crossplane.function.proto.v1.run_function_pb2', _globals) if not _descriptor._USE_C_DESCRIPTORS: _globals['DESCRIPTOR']._loaded_options = None - _globals['DESCRIPTOR']._serialized_options = b'Z,github.com/crossplane/crossplane/proto/fn/v1' - _globals['_RUNFUNCTIONREQUEST_REQUIREDRESOURCESENTRY']._loaded_options = None - _globals['_RUNFUNCTIONREQUEST_REQUIREDRESOURCESENTRY']._serialized_options = b'8\001' + _globals['DESCRIPTOR']._serialized_options = b'Z/github.com/crossplane/crossplane/v2/proto/fn/v1' + _globals['_RUNFUNCTIONREQUEST_EXTRARESOURCESENTRY']._loaded_options = None + _globals['_RUNFUNCTIONREQUEST_EXTRARESOURCESENTRY']._serialized_options = b'8\001' _globals['_RUNFUNCTIONREQUEST_CREDENTIALSENTRY']._loaded_options = None _globals['_RUNFUNCTIONREQUEST_CREDENTIALSENTRY']._serialized_options = b'8\001' + _globals['_RUNFUNCTIONREQUEST_REQUIREDRESOURCESENTRY']._loaded_options = None + _globals['_RUNFUNCTIONREQUEST_REQUIREDRESOURCESENTRY']._serialized_options = b'8\001' + _globals['_RUNFUNCTIONREQUEST'].fields_by_name['extra_resources']._loaded_options = None + _globals['_RUNFUNCTIONREQUEST'].fields_by_name['extra_resources']._serialized_options = b'\030\001' _globals['_CREDENTIALDATA_DATAENTRY']._loaded_options = None _globals['_CREDENTIALDATA_DATAENTRY']._serialized_options = b'8\001' + _globals['_REQUIREMENTS_EXTRARESOURCESENTRY']._loaded_options = None + _globals['_REQUIREMENTS_EXTRARESOURCESENTRY']._serialized_options = b'8\001' _globals['_REQUIREMENTS_RESOURCESENTRY']._loaded_options = None _globals['_REQUIREMENTS_RESOURCESENTRY']._serialized_options = b'8\001' + _globals['_REQUIREMENTS'].fields_by_name['extra_resources']._loaded_options = None + _globals['_REQUIREMENTS'].fields_by_name['extra_resources']._serialized_options = b'\030\001' _globals['_MATCHLABELS_LABELSENTRY']._loaded_options = None _globals['_MATCHLABELS_LABELSENTRY']._serialized_options = b'8\001' _globals['_STATE_RESOURCESENTRY']._loaded_options = None _globals['_STATE_RESOURCESENTRY']._serialized_options = b'8\001' _globals['_RESOURCE_CONNECTIONDETAILSENTRY']._loaded_options = None _globals['_RESOURCE_CONNECTIONDETAILSENTRY']._serialized_options = b'8\001' - _globals['_READY']._serialized_start=2982 - _globals['_READY']._serialized_end=3045 - _globals['_SEVERITY']._serialized_start=3047 - _globals['_SEVERITY']._serialized_end=3146 - _globals['_TARGET']._serialized_start=3148 - _globals['_TARGET']._serialized_end=3234 - _globals['_STATUS']._serialized_start=3236 - _globals['_STATUS']._serialized_end=3363 + _globals['_READY']._serialized_start=3361 + _globals['_READY']._serialized_end=3424 + _globals['_SEVERITY']._serialized_start=3426 + _globals['_SEVERITY']._serialized_end=3525 + _globals['_TARGET']._serialized_start=3527 + _globals['_TARGET']._serialized_end=3613 + _globals['_STATUS']._serialized_start=3615 + _globals['_STATUS']._serialized_end=3742 _globals['_RUNFUNCTIONREQUEST']._serialized_start=141 - _globals['_RUNFUNCTIONREQUEST']._serialized_end=803 - _globals['_RUNFUNCTIONREQUEST_REQUIREDRESOURCESENTRY']._serialized_start=595 - _globals['_RUNFUNCTIONREQUEST_REQUIREDRESOURCESENTRY']._serialized_end=689 - _globals['_RUNFUNCTIONREQUEST_CREDENTIALSENTRY']._serialized_start=691 - _globals['_RUNFUNCTIONREQUEST_CREDENTIALSENTRY']._serialized_end=781 - _globals['_CREDENTIALS']._serialized_start=805 - _globals['_CREDENTIALS']._serialized_end=898 - _globals['_CREDENTIALDATA']._serialized_start=901 - _globals['_CREDENTIALDATA']._serialized_end=1029 - _globals['_CREDENTIALDATA_DATAENTRY']._serialized_start=986 - _globals['_CREDENTIALDATA_DATAENTRY']._serialized_end=1029 - _globals['_RESOURCES']._serialized_start=1031 - _globals['_RESOURCES']._serialized_end=1094 - _globals['_RUNFUNCTIONRESPONSE']._serialized_start=1097 - _globals['_RUNFUNCTIONRESPONSE']._serialized_end=1513 - _globals['_REQUESTMETA']._serialized_start=1515 - _globals['_REQUESTMETA']._serialized_end=1541 - _globals['_REQUIREMENTS']._serialized_start=1544 - _globals['_REQUIREMENTS']._serialized_end=1728 - _globals['_REQUIREMENTS_RESOURCESENTRY']._serialized_start=1635 - _globals['_REQUIREMENTS_RESOURCESENTRY']._serialized_end=1728 - _globals['_RESOURCESELECTOR']._serialized_start=1731 - _globals['_RESOURCESELECTOR']._serialized_end=1917 - _globals['_MATCHLABELS']._serialized_start=1920 - _globals['_MATCHLABELS']._serialized_end=2048 - _globals['_MATCHLABELS_LABELSENTRY']._serialized_start=2003 - _globals['_MATCHLABELS_LABELSENTRY']._serialized_end=2048 - _globals['_RESPONSEMETA']._serialized_start=2050 - _globals['_RESPONSEMETA']._serialized_end=2130 - _globals['_STATE']._serialized_start=2133 - _globals['_STATE']._serialized_end=2351 - _globals['_STATE_RESOURCESENTRY']._serialized_start=2266 - _globals['_STATE_RESOURCESENTRY']._serialized_end=2351 - _globals['_RESOURCE']._serialized_start=2354 - _globals['_RESOURCE']._serialized_end=2602 - _globals['_RESOURCE_CONNECTIONDETAILSENTRY']._serialized_start=2546 - _globals['_RESOURCE_CONNECTIONDETAILSENTRY']._serialized_end=2602 - _globals['_RESULT']._serialized_start=2605 - _globals['_RESULT']._serialized_end=2784 - _globals['_CONDITION']._serialized_start=2787 - _globals['_CONDITION']._serialized_end=2980 - _globals['_FUNCTIONRUNNERSERVICE']._serialized_start=3366 - _globals['_FUNCTIONRUNNERSERVICE']._serialized_end=3501 + _globals['_RUNFUNCTIONREQUEST']._serialized_end=992 + _globals['_RUNFUNCTIONREQUEST_EXTRARESOURCESENTRY']._serialized_start=691 + _globals['_RUNFUNCTIONREQUEST_EXTRARESOURCESENTRY']._serialized_end=782 + _globals['_RUNFUNCTIONREQUEST_CREDENTIALSENTRY']._serialized_start=784 + _globals['_RUNFUNCTIONREQUEST_CREDENTIALSENTRY']._serialized_end=874 + _globals['_RUNFUNCTIONREQUEST_REQUIREDRESOURCESENTRY']._serialized_start=876 + _globals['_RUNFUNCTIONREQUEST_REQUIREDRESOURCESENTRY']._serialized_end=970 + _globals['_CREDENTIALS']._serialized_start=994 + _globals['_CREDENTIALS']._serialized_end=1087 + _globals['_CREDENTIALDATA']._serialized_start=1090 + _globals['_CREDENTIALDATA']._serialized_end=1218 + _globals['_CREDENTIALDATA_DATAENTRY']._serialized_start=1175 + _globals['_CREDENTIALDATA_DATAENTRY']._serialized_end=1218 + _globals['_RESOURCES']._serialized_start=1220 + _globals['_RESOURCES']._serialized_end=1283 + _globals['_RUNFUNCTIONRESPONSE']._serialized_start=1286 + _globals['_RUNFUNCTIONRESPONSE']._serialized_end=1702 + _globals['_REQUESTMETA']._serialized_start=1704 + _globals['_REQUESTMETA']._serialized_end=1730 + _globals['_REQUIREMENTS']._serialized_start=1733 + _globals['_REQUIREMENTS']._serialized_end=2107 + _globals['_REQUIREMENTS_EXTRARESOURCESENTRY']._serialized_start=1914 + _globals['_REQUIREMENTS_EXTRARESOURCESENTRY']._serialized_end=2012 + _globals['_REQUIREMENTS_RESOURCESENTRY']._serialized_start=2014 + _globals['_REQUIREMENTS_RESOURCESENTRY']._serialized_end=2107 + _globals['_RESOURCESELECTOR']._serialized_start=2110 + _globals['_RESOURCESELECTOR']._serialized_end=2296 + _globals['_MATCHLABELS']._serialized_start=2299 + _globals['_MATCHLABELS']._serialized_end=2427 + _globals['_MATCHLABELS_LABELSENTRY']._serialized_start=2382 + _globals['_MATCHLABELS_LABELSENTRY']._serialized_end=2427 + _globals['_RESPONSEMETA']._serialized_start=2429 + _globals['_RESPONSEMETA']._serialized_end=2509 + _globals['_STATE']._serialized_start=2512 + _globals['_STATE']._serialized_end=2730 + _globals['_STATE_RESOURCESENTRY']._serialized_start=2645 + _globals['_STATE_RESOURCESENTRY']._serialized_end=2730 + _globals['_RESOURCE']._serialized_start=2733 + _globals['_RESOURCE']._serialized_end=2981 + _globals['_RESOURCE_CONNECTIONDETAILSENTRY']._serialized_start=2925 + _globals['_RESOURCE_CONNECTIONDETAILSENTRY']._serialized_end=2981 + _globals['_RESULT']._serialized_start=2984 + _globals['_RESULT']._serialized_end=3163 + _globals['_CONDITION']._serialized_start=3166 + _globals['_CONDITION']._serialized_end=3359 + _globals['_FUNCTIONRUNNERSERVICE']._serialized_start=3745 + _globals['_FUNCTIONRUNNERSERVICE']._serialized_end=3880 # @@protoc_insertion_point(module_scope) diff --git a/crossplane/function/proto/v1/run_function_pb2.pyi b/crossplane/function/proto/v1/run_function_pb2.pyi index c0dd5d8..ed96678 100644 --- a/crossplane/function/proto/v1/run_function_pb2.pyi +++ b/crossplane/function/proto/v1/run_function_pb2.pyi @@ -50,8 +50,8 @@ STATUS_CONDITION_TRUE: Status STATUS_CONDITION_FALSE: Status class RunFunctionRequest(_message.Message): - __slots__ = ("meta", "observed", "desired", "input", "context", "required_resources", "credentials") - class RequiredResourcesEntry(_message.Message): + __slots__ = ("meta", "observed", "desired", "input", "context", "extra_resources", "credentials", "required_resources") + class ExtraResourcesEntry(_message.Message): __slots__ = ("key", "value") KEY_FIELD_NUMBER: _ClassVar[int] VALUE_FIELD_NUMBER: _ClassVar[int] @@ -65,21 +65,30 @@ class RunFunctionRequest(_message.Message): key: str value: Credentials def __init__(self, key: _Optional[str] = ..., value: _Optional[_Union[Credentials, _Mapping]] = ...) -> None: ... + class RequiredResourcesEntry(_message.Message): + __slots__ = ("key", "value") + KEY_FIELD_NUMBER: _ClassVar[int] + VALUE_FIELD_NUMBER: _ClassVar[int] + key: str + value: Resources + def __init__(self, key: _Optional[str] = ..., value: _Optional[_Union[Resources, _Mapping]] = ...) -> None: ... META_FIELD_NUMBER: _ClassVar[int] OBSERVED_FIELD_NUMBER: _ClassVar[int] DESIRED_FIELD_NUMBER: _ClassVar[int] INPUT_FIELD_NUMBER: _ClassVar[int] CONTEXT_FIELD_NUMBER: _ClassVar[int] - REQUIRED_RESOURCES_FIELD_NUMBER: _ClassVar[int] + EXTRA_RESOURCES_FIELD_NUMBER: _ClassVar[int] CREDENTIALS_FIELD_NUMBER: _ClassVar[int] + REQUIRED_RESOURCES_FIELD_NUMBER: _ClassVar[int] meta: RequestMeta observed: State desired: State input: _struct_pb2.Struct context: _struct_pb2.Struct - required_resources: _containers.MessageMap[str, Resources] + extra_resources: _containers.MessageMap[str, Resources] credentials: _containers.MessageMap[str, Credentials] - def __init__(self, meta: _Optional[_Union[RequestMeta, _Mapping]] = ..., observed: _Optional[_Union[State, _Mapping]] = ..., desired: _Optional[_Union[State, _Mapping]] = ..., input: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ..., context: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ..., required_resources: _Optional[_Mapping[str, Resources]] = ..., credentials: _Optional[_Mapping[str, Credentials]] = ...) -> None: ... + required_resources: _containers.MessageMap[str, Resources] + def __init__(self, meta: _Optional[_Union[RequestMeta, _Mapping]] = ..., observed: _Optional[_Union[State, _Mapping]] = ..., desired: _Optional[_Union[State, _Mapping]] = ..., input: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ..., context: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ..., extra_resources: _Optional[_Mapping[str, Resources]] = ..., credentials: _Optional[_Mapping[str, Credentials]] = ..., required_resources: _Optional[_Mapping[str, Resources]] = ...) -> None: ... class Credentials(_message.Message): __slots__ = ("credential_data",) @@ -131,7 +140,14 @@ class RequestMeta(_message.Message): def __init__(self, tag: _Optional[str] = ...) -> None: ... class Requirements(_message.Message): - __slots__ = ("resources",) + __slots__ = ("extra_resources", "resources") + class ExtraResourcesEntry(_message.Message): + __slots__ = ("key", "value") + KEY_FIELD_NUMBER: _ClassVar[int] + VALUE_FIELD_NUMBER: _ClassVar[int] + key: str + value: ResourceSelector + def __init__(self, key: _Optional[str] = ..., value: _Optional[_Union[ResourceSelector, _Mapping]] = ...) -> None: ... class ResourcesEntry(_message.Message): __slots__ = ("key", "value") KEY_FIELD_NUMBER: _ClassVar[int] @@ -139,9 +155,11 @@ class Requirements(_message.Message): key: str value: ResourceSelector def __init__(self, key: _Optional[str] = ..., value: _Optional[_Union[ResourceSelector, _Mapping]] = ...) -> None: ... + EXTRA_RESOURCES_FIELD_NUMBER: _ClassVar[int] RESOURCES_FIELD_NUMBER: _ClassVar[int] + extra_resources: _containers.MessageMap[str, ResourceSelector] resources: _containers.MessageMap[str, ResourceSelector] - def __init__(self, resources: _Optional[_Mapping[str, ResourceSelector]] = ...) -> None: ... + def __init__(self, extra_resources: _Optional[_Mapping[str, ResourceSelector]] = ..., resources: _Optional[_Mapping[str, ResourceSelector]] = ...) -> None: ... class ResourceSelector(_message.Message): __slots__ = ("api_version", "kind", "match_name", "match_labels", "namespace") diff --git a/crossplane/function/proto/v1beta1/run_function.proto b/crossplane/function/proto/v1beta1/run_function.proto index 1332ae5..f0ab5b6 100644 --- a/crossplane/function/proto/v1beta1/run_function.proto +++ b/crossplane/function/proto/v1beta1/run_function.proto @@ -29,7 +29,7 @@ package apiextensions.fn.proto.v1beta1; import "google/protobuf/duration.proto"; import "google/protobuf/struct.proto"; -option go_package = "github.com/crossplane/crossplane/proto/fn/v1beta1"; +option go_package = "github.com/crossplane/crossplane/v2/proto/fn/v1beta1"; // A FunctionRunnerService is a function. service FunctionRunnerService { @@ -71,15 +71,27 @@ message RunFunctionRequest { // Optional resources that the function specified in its requirements. Note // that resources is a map to Resources, plural. The map key corresponds to - // the key in a RunFunctionResponse's requirements.resources field. If a - // function requested required resources that did not exist, Crossplane sets + // the key in a RunFunctionResponse's requirements.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 required_resources = 6; + // satisfy the request. This field is only populated when the function uses + // extra_resources in its requirements. + // + // Deprecated: Use required_resources instead. + map extra_resources = 6 [deprecated = true]; // Optional credentials that this function may use to communicate with an // external system. map credentials = 7; + + // Optional resources that the function specified in its requirements. Note + // that resources is a map to Resources, plural. The map key corresponds to + // the key in a RunFunctionResponse's requirements.resources field. If a + // function requested required resources that did not exist, Crossplane sets + // the map key to an empty Resources message to indicate that it attempted to + // satisfy the request. This field is only populated when the function uses + // resources in its requirements. + map required_resources = 8; } // Credentials that a function may use to communicate with an external system. @@ -152,7 +164,13 @@ message RequestMeta { message Requirements { // Resources that this function requires. The map key uniquely identifies the // group of resources. - map resources = 1; + // + // Deprecated: Use resources instead. + map extra_resources = 1 [deprecated = true]; + + // Resources that this function requires. The map key uniquely identifies the + // group of resources. + map resources = 2; } // ResourceSelector selects a group of resources, either by name or by label. diff --git a/crossplane/function/proto/v1beta1/run_function_pb2.py b/crossplane/function/proto/v1beta1/run_function_pb2.py index 6499a56..4a6f64b 100644 --- a/crossplane/function/proto/v1beta1/run_function_pb2.py +++ b/crossplane/function/proto/v1beta1/run_function_pb2.py @@ -26,78 +26,90 @@ from google.protobuf import struct_pb2 as google_dot_protobuf_dot_struct__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n4crossplane/function/proto/v1beta1/run_function.proto\x12\x1e\x61piextensions.fn.proto.v1beta1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1cgoogle/protobuf/struct.proto\"\xb9\x05\n\x12RunFunctionRequest\x12\x39\n\x04meta\x18\x01 \x01(\x0b\x32+.apiextensions.fn.proto.v1beta1.RequestMeta\x12\x37\n\x08observed\x18\x02 \x01(\x0b\x32%.apiextensions.fn.proto.v1beta1.State\x12\x36\n\x07\x64\x65sired\x18\x03 \x01(\x0b\x32%.apiextensions.fn.proto.v1beta1.State\x12+\n\x05input\x18\x04 \x01(\x0b\x32\x17.google.protobuf.StructH\x00\x88\x01\x01\x12-\n\x07\x63ontext\x18\x05 \x01(\x0b\x32\x17.google.protobuf.StructH\x01\x88\x01\x01\x12\x65\n\x12required_resources\x18\x06 \x03(\x0b\x32I.apiextensions.fn.proto.v1beta1.RunFunctionRequest.RequiredResourcesEntry\x12X\n\x0b\x63redentials\x18\x07 \x03(\x0b\x32\x43.apiextensions.fn.proto.v1beta1.RunFunctionRequest.CredentialsEntry\x1a\x63\n\x16RequiredResourcesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x38\n\x05value\x18\x02 \x01(\x0b\x32).apiextensions.fn.proto.v1beta1.Resources:\x02\x38\x01\x1a_\n\x10\x43redentialsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12:\n\x05value\x18\x02 \x01(\x0b\x32+.apiextensions.fn.proto.v1beta1.Credentials:\x02\x38\x01\x42\x08\n\x06_inputB\n\n\x08_context\"b\n\x0b\x43redentials\x12I\n\x0f\x63redential_data\x18\x01 \x01(\x0b\x32..apiextensions.fn.proto.v1beta1.CredentialDataH\x00\x42\x08\n\x06source\"\x85\x01\n\x0e\x43redentialData\x12\x46\n\x04\x64\x61ta\x18\x01 \x03(\x0b\x32\x38.apiextensions.fn.proto.v1beta1.CredentialData.DataEntry\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\"D\n\tResources\x12\x37\n\x05items\x18\x01 \x03(\x0b\x32(.apiextensions.fn.proto.v1beta1.Resource\"\xb9\x03\n\x13RunFunctionResponse\x12:\n\x04meta\x18\x01 \x01(\x0b\x32,.apiextensions.fn.proto.v1beta1.ResponseMeta\x12\x36\n\x07\x64\x65sired\x18\x02 \x01(\x0b\x32%.apiextensions.fn.proto.v1beta1.State\x12\x37\n\x07results\x18\x03 \x03(\x0b\x32&.apiextensions.fn.proto.v1beta1.Result\x12-\n\x07\x63ontext\x18\x04 \x01(\x0b\x32\x17.google.protobuf.StructH\x00\x88\x01\x01\x12\x42\n\x0crequirements\x18\x05 \x01(\x0b\x32,.apiextensions.fn.proto.v1beta1.Requirements\x12=\n\nconditions\x18\x06 \x03(\x0b\x32).apiextensions.fn.proto.v1beta1.Condition\x12,\n\x06output\x18\x07 \x01(\x0b\x32\x17.google.protobuf.StructH\x01\x88\x01\x01\x42\n\n\x08_contextB\t\n\x07_output\"\x1a\n\x0bRequestMeta\x12\x0b\n\x03tag\x18\x01 \x01(\t\"\xc2\x01\n\x0cRequirements\x12N\n\tresources\x18\x01 \x03(\x0b\x32;.apiextensions.fn.proto.v1beta1.Requirements.ResourcesEntry\x1a\x62\n\x0eResourcesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12?\n\x05value\x18\x02 \x01(\x0b\x32\x30.apiextensions.fn.proto.v1beta1.ResourceSelector:\x02\x38\x01\"\xbf\x01\n\x10ResourceSelector\x12\x13\n\x0b\x61pi_version\x18\x01 \x01(\t\x12\x0c\n\x04kind\x18\x02 \x01(\t\x12\x14\n\nmatch_name\x18\x03 \x01(\tH\x00\x12\x43\n\x0cmatch_labels\x18\x04 \x01(\x0b\x32+.apiextensions.fn.proto.v1beta1.MatchLabelsH\x00\x12\x16\n\tnamespace\x18\x05 \x01(\tH\x01\x88\x01\x01\x42\x07\n\x05matchB\x0c\n\n_namespace\"\x85\x01\n\x0bMatchLabels\x12G\n\x06labels\x18\x01 \x03(\x0b\x32\x37.apiextensions.fn.proto.v1beta1.MatchLabels.LabelsEntry\x1a-\n\x0bLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"P\n\x0cResponseMeta\x12\x0b\n\x03tag\x18\x01 \x01(\t\x12+\n\x03ttl\x18\x02 \x01(\x0b\x32\x19.google.protobuf.DurationH\x00\x88\x01\x01\x42\x06\n\x04_ttl\"\xe9\x01\n\x05State\x12;\n\tcomposite\x18\x01 \x01(\x0b\x32(.apiextensions.fn.proto.v1beta1.Resource\x12G\n\tresources\x18\x02 \x03(\x0b\x32\x34.apiextensions.fn.proto.v1beta1.State.ResourcesEntry\x1aZ\n\x0eResourcesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x37\n\x05value\x18\x02 \x01(\x0b\x32(.apiextensions.fn.proto.v1beta1.Resource:\x02\x38\x01\"\x82\x02\n\x08Resource\x12)\n\x08resource\x18\x01 \x01(\x0b\x32\x17.google.protobuf.Struct\x12[\n\x12\x63onnection_details\x18\x02 \x03(\x0b\x32?.apiextensions.fn.proto.v1beta1.Resource.ConnectionDetailsEntry\x12\x34\n\x05ready\x18\x03 \x01(\x0e\x32%.apiextensions.fn.proto.v1beta1.Ready\x1a\x38\n\x16\x43onnectionDetailsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\"\xbd\x01\n\x06Result\x12:\n\x08severity\x18\x01 \x01(\x0e\x32(.apiextensions.fn.proto.v1beta1.Severity\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x13\n\x06reason\x18\x03 \x01(\tH\x00\x88\x01\x01\x12;\n\x06target\x18\x04 \x01(\x0e\x32&.apiextensions.fn.proto.v1beta1.TargetH\x01\x88\x01\x01\x42\t\n\x07_reasonB\t\n\x07_target\"\xcb\x01\n\tCondition\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x36\n\x06status\x18\x02 \x01(\x0e\x32&.apiextensions.fn.proto.v1beta1.Status\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x14\n\x07message\x18\x04 \x01(\tH\x00\x88\x01\x01\x12;\n\x06target\x18\x05 \x01(\x0e\x32&.apiextensions.fn.proto.v1beta1.TargetH\x01\x88\x01\x01\x42\n\n\x08_messageB\t\n\x07_target*?\n\x05Ready\x12\x15\n\x11READY_UNSPECIFIED\x10\x00\x12\x0e\n\nREADY_TRUE\x10\x01\x12\x0f\n\x0bREADY_FALSE\x10\x02*c\n\x08Severity\x12\x18\n\x14SEVERITY_UNSPECIFIED\x10\x00\x12\x12\n\x0eSEVERITY_FATAL\x10\x01\x12\x14\n\x10SEVERITY_WARNING\x10\x02\x12\x13\n\x0fSEVERITY_NORMAL\x10\x03*V\n\x06Target\x12\x16\n\x12TARGET_UNSPECIFIED\x10\x00\x12\x14\n\x10TARGET_COMPOSITE\x10\x01\x12\x1e\n\x1aTARGET_COMPOSITE_AND_CLAIM\x10\x02*\x7f\n\x06Status\x12 \n\x1cSTATUS_CONDITION_UNSPECIFIED\x10\x00\x12\x1c\n\x18STATUS_CONDITION_UNKNOWN\x10\x01\x12\x19\n\x15STATUS_CONDITION_TRUE\x10\x02\x12\x1a\n\x16STATUS_CONDITION_FALSE\x10\x03\x32\x91\x01\n\x15\x46unctionRunnerService\x12x\n\x0bRunFunction\x12\x32.apiextensions.fn.proto.v1beta1.RunFunctionRequest\x1a\x33.apiextensions.fn.proto.v1beta1.RunFunctionResponse\"\x00\x42\x33Z1github.com/crossplane/crossplane/proto/fn/v1beta1b\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n4crossplane/function/proto/v1beta1/run_function.proto\x12\x1e\x61piextensions.fn.proto.v1beta1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1cgoogle/protobuf/struct.proto\"\x80\x07\n\x12RunFunctionRequest\x12\x39\n\x04meta\x18\x01 \x01(\x0b\x32+.apiextensions.fn.proto.v1beta1.RequestMeta\x12\x37\n\x08observed\x18\x02 \x01(\x0b\x32%.apiextensions.fn.proto.v1beta1.State\x12\x36\n\x07\x64\x65sired\x18\x03 \x01(\x0b\x32%.apiextensions.fn.proto.v1beta1.State\x12+\n\x05input\x18\x04 \x01(\x0b\x32\x17.google.protobuf.StructH\x00\x88\x01\x01\x12-\n\x07\x63ontext\x18\x05 \x01(\x0b\x32\x17.google.protobuf.StructH\x01\x88\x01\x01\x12\x63\n\x0f\x65xtra_resources\x18\x06 \x03(\x0b\x32\x46.apiextensions.fn.proto.v1beta1.RunFunctionRequest.ExtraResourcesEntryB\x02\x18\x01\x12X\n\x0b\x63redentials\x18\x07 \x03(\x0b\x32\x43.apiextensions.fn.proto.v1beta1.RunFunctionRequest.CredentialsEntry\x12\x65\n\x12required_resources\x18\x08 \x03(\x0b\x32I.apiextensions.fn.proto.v1beta1.RunFunctionRequest.RequiredResourcesEntry\x1a`\n\x13\x45xtraResourcesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x38\n\x05value\x18\x02 \x01(\x0b\x32).apiextensions.fn.proto.v1beta1.Resources:\x02\x38\x01\x1a_\n\x10\x43redentialsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12:\n\x05value\x18\x02 \x01(\x0b\x32+.apiextensions.fn.proto.v1beta1.Credentials:\x02\x38\x01\x1a\x63\n\x16RequiredResourcesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x38\n\x05value\x18\x02 \x01(\x0b\x32).apiextensions.fn.proto.v1beta1.Resources:\x02\x38\x01\x42\x08\n\x06_inputB\n\n\x08_context\"b\n\x0b\x43redentials\x12I\n\x0f\x63redential_data\x18\x01 \x01(\x0b\x32..apiextensions.fn.proto.v1beta1.CredentialDataH\x00\x42\x08\n\x06source\"\x85\x01\n\x0e\x43redentialData\x12\x46\n\x04\x64\x61ta\x18\x01 \x03(\x0b\x32\x38.apiextensions.fn.proto.v1beta1.CredentialData.DataEntry\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\"D\n\tResources\x12\x37\n\x05items\x18\x01 \x03(\x0b\x32(.apiextensions.fn.proto.v1beta1.Resource\"\xb9\x03\n\x13RunFunctionResponse\x12:\n\x04meta\x18\x01 \x01(\x0b\x32,.apiextensions.fn.proto.v1beta1.ResponseMeta\x12\x36\n\x07\x64\x65sired\x18\x02 \x01(\x0b\x32%.apiextensions.fn.proto.v1beta1.State\x12\x37\n\x07results\x18\x03 \x03(\x0b\x32&.apiextensions.fn.proto.v1beta1.Result\x12-\n\x07\x63ontext\x18\x04 \x01(\x0b\x32\x17.google.protobuf.StructH\x00\x88\x01\x01\x12\x42\n\x0crequirements\x18\x05 \x01(\x0b\x32,.apiextensions.fn.proto.v1beta1.Requirements\x12=\n\nconditions\x18\x06 \x03(\x0b\x32).apiextensions.fn.proto.v1beta1.Condition\x12,\n\x06output\x18\x07 \x01(\x0b\x32\x17.google.protobuf.StructH\x01\x88\x01\x01\x42\n\n\x08_contextB\t\n\x07_output\"\x1a\n\x0bRequestMeta\x12\x0b\n\x03tag\x18\x01 \x01(\t\"\x8a\x03\n\x0cRequirements\x12]\n\x0f\x65xtra_resources\x18\x01 \x03(\x0b\x32@.apiextensions.fn.proto.v1beta1.Requirements.ExtraResourcesEntryB\x02\x18\x01\x12N\n\tresources\x18\x02 \x03(\x0b\x32;.apiextensions.fn.proto.v1beta1.Requirements.ResourcesEntry\x1ag\n\x13\x45xtraResourcesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12?\n\x05value\x18\x02 \x01(\x0b\x32\x30.apiextensions.fn.proto.v1beta1.ResourceSelector:\x02\x38\x01\x1a\x62\n\x0eResourcesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12?\n\x05value\x18\x02 \x01(\x0b\x32\x30.apiextensions.fn.proto.v1beta1.ResourceSelector:\x02\x38\x01\"\xbf\x01\n\x10ResourceSelector\x12\x13\n\x0b\x61pi_version\x18\x01 \x01(\t\x12\x0c\n\x04kind\x18\x02 \x01(\t\x12\x14\n\nmatch_name\x18\x03 \x01(\tH\x00\x12\x43\n\x0cmatch_labels\x18\x04 \x01(\x0b\x32+.apiextensions.fn.proto.v1beta1.MatchLabelsH\x00\x12\x16\n\tnamespace\x18\x05 \x01(\tH\x01\x88\x01\x01\x42\x07\n\x05matchB\x0c\n\n_namespace\"\x85\x01\n\x0bMatchLabels\x12G\n\x06labels\x18\x01 \x03(\x0b\x32\x37.apiextensions.fn.proto.v1beta1.MatchLabels.LabelsEntry\x1a-\n\x0bLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"P\n\x0cResponseMeta\x12\x0b\n\x03tag\x18\x01 \x01(\t\x12+\n\x03ttl\x18\x02 \x01(\x0b\x32\x19.google.protobuf.DurationH\x00\x88\x01\x01\x42\x06\n\x04_ttl\"\xe9\x01\n\x05State\x12;\n\tcomposite\x18\x01 \x01(\x0b\x32(.apiextensions.fn.proto.v1beta1.Resource\x12G\n\tresources\x18\x02 \x03(\x0b\x32\x34.apiextensions.fn.proto.v1beta1.State.ResourcesEntry\x1aZ\n\x0eResourcesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x37\n\x05value\x18\x02 \x01(\x0b\x32(.apiextensions.fn.proto.v1beta1.Resource:\x02\x38\x01\"\x82\x02\n\x08Resource\x12)\n\x08resource\x18\x01 \x01(\x0b\x32\x17.google.protobuf.Struct\x12[\n\x12\x63onnection_details\x18\x02 \x03(\x0b\x32?.apiextensions.fn.proto.v1beta1.Resource.ConnectionDetailsEntry\x12\x34\n\x05ready\x18\x03 \x01(\x0e\x32%.apiextensions.fn.proto.v1beta1.Ready\x1a\x38\n\x16\x43onnectionDetailsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\"\xbd\x01\n\x06Result\x12:\n\x08severity\x18\x01 \x01(\x0e\x32(.apiextensions.fn.proto.v1beta1.Severity\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x13\n\x06reason\x18\x03 \x01(\tH\x00\x88\x01\x01\x12;\n\x06target\x18\x04 \x01(\x0e\x32&.apiextensions.fn.proto.v1beta1.TargetH\x01\x88\x01\x01\x42\t\n\x07_reasonB\t\n\x07_target\"\xcb\x01\n\tCondition\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x36\n\x06status\x18\x02 \x01(\x0e\x32&.apiextensions.fn.proto.v1beta1.Status\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x14\n\x07message\x18\x04 \x01(\tH\x00\x88\x01\x01\x12;\n\x06target\x18\x05 \x01(\x0e\x32&.apiextensions.fn.proto.v1beta1.TargetH\x01\x88\x01\x01\x42\n\n\x08_messageB\t\n\x07_target*?\n\x05Ready\x12\x15\n\x11READY_UNSPECIFIED\x10\x00\x12\x0e\n\nREADY_TRUE\x10\x01\x12\x0f\n\x0bREADY_FALSE\x10\x02*c\n\x08Severity\x12\x18\n\x14SEVERITY_UNSPECIFIED\x10\x00\x12\x12\n\x0eSEVERITY_FATAL\x10\x01\x12\x14\n\x10SEVERITY_WARNING\x10\x02\x12\x13\n\x0fSEVERITY_NORMAL\x10\x03*V\n\x06Target\x12\x16\n\x12TARGET_UNSPECIFIED\x10\x00\x12\x14\n\x10TARGET_COMPOSITE\x10\x01\x12\x1e\n\x1aTARGET_COMPOSITE_AND_CLAIM\x10\x02*\x7f\n\x06Status\x12 \n\x1cSTATUS_CONDITION_UNSPECIFIED\x10\x00\x12\x1c\n\x18STATUS_CONDITION_UNKNOWN\x10\x01\x12\x19\n\x15STATUS_CONDITION_TRUE\x10\x02\x12\x1a\n\x16STATUS_CONDITION_FALSE\x10\x03\x32\x91\x01\n\x15\x46unctionRunnerService\x12x\n\x0bRunFunction\x12\x32.apiextensions.fn.proto.v1beta1.RunFunctionRequest\x1a\x33.apiextensions.fn.proto.v1beta1.RunFunctionResponse\"\x00\x42\x36Z4github.com/crossplane/crossplane/v2/proto/fn/v1beta1b\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'crossplane.function.proto.v1beta1.run_function_pb2', _globals) if not _descriptor._USE_C_DESCRIPTORS: _globals['DESCRIPTOR']._loaded_options = None - _globals['DESCRIPTOR']._serialized_options = b'Z1github.com/crossplane/crossplane/proto/fn/v1beta1' - _globals['_RUNFUNCTIONREQUEST_REQUIREDRESOURCESENTRY']._loaded_options = None - _globals['_RUNFUNCTIONREQUEST_REQUIREDRESOURCESENTRY']._serialized_options = b'8\001' + _globals['DESCRIPTOR']._serialized_options = b'Z4github.com/crossplane/crossplane/v2/proto/fn/v1beta1' + _globals['_RUNFUNCTIONREQUEST_EXTRARESOURCESENTRY']._loaded_options = None + _globals['_RUNFUNCTIONREQUEST_EXTRARESOURCESENTRY']._serialized_options = b'8\001' _globals['_RUNFUNCTIONREQUEST_CREDENTIALSENTRY']._loaded_options = None _globals['_RUNFUNCTIONREQUEST_CREDENTIALSENTRY']._serialized_options = b'8\001' + _globals['_RUNFUNCTIONREQUEST_REQUIREDRESOURCESENTRY']._loaded_options = None + _globals['_RUNFUNCTIONREQUEST_REQUIREDRESOURCESENTRY']._serialized_options = b'8\001' + _globals['_RUNFUNCTIONREQUEST'].fields_by_name['extra_resources']._loaded_options = None + _globals['_RUNFUNCTIONREQUEST'].fields_by_name['extra_resources']._serialized_options = b'\030\001' _globals['_CREDENTIALDATA_DATAENTRY']._loaded_options = None _globals['_CREDENTIALDATA_DATAENTRY']._serialized_options = b'8\001' + _globals['_REQUIREMENTS_EXTRARESOURCESENTRY']._loaded_options = None + _globals['_REQUIREMENTS_EXTRARESOURCESENTRY']._serialized_options = b'8\001' _globals['_REQUIREMENTS_RESOURCESENTRY']._loaded_options = None _globals['_REQUIREMENTS_RESOURCESENTRY']._serialized_options = b'8\001' + _globals['_REQUIREMENTS'].fields_by_name['extra_resources']._loaded_options = None + _globals['_REQUIREMENTS'].fields_by_name['extra_resources']._serialized_options = b'\030\001' _globals['_MATCHLABELS_LABELSENTRY']._loaded_options = None _globals['_MATCHLABELS_LABELSENTRY']._serialized_options = b'8\001' _globals['_STATE_RESOURCESENTRY']._loaded_options = None _globals['_STATE_RESOURCESENTRY']._serialized_options = b'8\001' _globals['_RESOURCE_CONNECTIONDETAILSENTRY']._loaded_options = None _globals['_RESOURCE_CONNECTIONDETAILSENTRY']._serialized_options = b'8\001' - _globals['_READY']._serialized_start=3132 - _globals['_READY']._serialized_end=3195 - _globals['_SEVERITY']._serialized_start=3197 - _globals['_SEVERITY']._serialized_end=3296 - _globals['_TARGET']._serialized_start=3298 - _globals['_TARGET']._serialized_end=3384 - _globals['_STATUS']._serialized_start=3386 - _globals['_STATUS']._serialized_end=3513 + _globals['_READY']._serialized_start=3531 + _globals['_READY']._serialized_end=3594 + _globals['_SEVERITY']._serialized_start=3596 + _globals['_SEVERITY']._serialized_end=3695 + _globals['_TARGET']._serialized_start=3697 + _globals['_TARGET']._serialized_end=3783 + _globals['_STATUS']._serialized_start=3785 + _globals['_STATUS']._serialized_end=3912 _globals['_RUNFUNCTIONREQUEST']._serialized_start=151 - _globals['_RUNFUNCTIONREQUEST']._serialized_end=848 - _globals['_RUNFUNCTIONREQUEST_REQUIREDRESOURCESENTRY']._serialized_start=630 - _globals['_RUNFUNCTIONREQUEST_REQUIREDRESOURCESENTRY']._serialized_end=729 - _globals['_RUNFUNCTIONREQUEST_CREDENTIALSENTRY']._serialized_start=731 - _globals['_RUNFUNCTIONREQUEST_CREDENTIALSENTRY']._serialized_end=826 - _globals['_CREDENTIALS']._serialized_start=850 - _globals['_CREDENTIALS']._serialized_end=948 - _globals['_CREDENTIALDATA']._serialized_start=951 - _globals['_CREDENTIALDATA']._serialized_end=1084 - _globals['_CREDENTIALDATA_DATAENTRY']._serialized_start=1041 - _globals['_CREDENTIALDATA_DATAENTRY']._serialized_end=1084 - _globals['_RESOURCES']._serialized_start=1086 - _globals['_RESOURCES']._serialized_end=1154 - _globals['_RUNFUNCTIONRESPONSE']._serialized_start=1157 - _globals['_RUNFUNCTIONRESPONSE']._serialized_end=1598 - _globals['_REQUESTMETA']._serialized_start=1600 - _globals['_REQUESTMETA']._serialized_end=1626 - _globals['_REQUIREMENTS']._serialized_start=1629 - _globals['_REQUIREMENTS']._serialized_end=1823 - _globals['_REQUIREMENTS_RESOURCESENTRY']._serialized_start=1725 - _globals['_REQUIREMENTS_RESOURCESENTRY']._serialized_end=1823 - _globals['_RESOURCESELECTOR']._serialized_start=1826 - _globals['_RESOURCESELECTOR']._serialized_end=2017 - _globals['_MATCHLABELS']._serialized_start=2020 - _globals['_MATCHLABELS']._serialized_end=2153 - _globals['_MATCHLABELS_LABELSENTRY']._serialized_start=2108 - _globals['_MATCHLABELS_LABELSENTRY']._serialized_end=2153 - _globals['_RESPONSEMETA']._serialized_start=2155 - _globals['_RESPONSEMETA']._serialized_end=2235 - _globals['_STATE']._serialized_start=2238 - _globals['_STATE']._serialized_end=2471 - _globals['_STATE_RESOURCESENTRY']._serialized_start=2381 - _globals['_STATE_RESOURCESENTRY']._serialized_end=2471 - _globals['_RESOURCE']._serialized_start=2474 - _globals['_RESOURCE']._serialized_end=2732 - _globals['_RESOURCE_CONNECTIONDETAILSENTRY']._serialized_start=2676 - _globals['_RESOURCE_CONNECTIONDETAILSENTRY']._serialized_end=2732 - _globals['_RESULT']._serialized_start=2735 - _globals['_RESULT']._serialized_end=2924 - _globals['_CONDITION']._serialized_start=2927 - _globals['_CONDITION']._serialized_end=3130 - _globals['_FUNCTIONRUNNERSERVICE']._serialized_start=3516 - _globals['_FUNCTIONRUNNERSERVICE']._serialized_end=3661 + _globals['_RUNFUNCTIONREQUEST']._serialized_end=1047 + _globals['_RUNFUNCTIONREQUEST_EXTRARESOURCESENTRY']._serialized_start=731 + _globals['_RUNFUNCTIONREQUEST_EXTRARESOURCESENTRY']._serialized_end=827 + _globals['_RUNFUNCTIONREQUEST_CREDENTIALSENTRY']._serialized_start=829 + _globals['_RUNFUNCTIONREQUEST_CREDENTIALSENTRY']._serialized_end=924 + _globals['_RUNFUNCTIONREQUEST_REQUIREDRESOURCESENTRY']._serialized_start=926 + _globals['_RUNFUNCTIONREQUEST_REQUIREDRESOURCESENTRY']._serialized_end=1025 + _globals['_CREDENTIALS']._serialized_start=1049 + _globals['_CREDENTIALS']._serialized_end=1147 + _globals['_CREDENTIALDATA']._serialized_start=1150 + _globals['_CREDENTIALDATA']._serialized_end=1283 + _globals['_CREDENTIALDATA_DATAENTRY']._serialized_start=1240 + _globals['_CREDENTIALDATA_DATAENTRY']._serialized_end=1283 + _globals['_RESOURCES']._serialized_start=1285 + _globals['_RESOURCES']._serialized_end=1353 + _globals['_RUNFUNCTIONRESPONSE']._serialized_start=1356 + _globals['_RUNFUNCTIONRESPONSE']._serialized_end=1797 + _globals['_REQUESTMETA']._serialized_start=1799 + _globals['_REQUESTMETA']._serialized_end=1825 + _globals['_REQUIREMENTS']._serialized_start=1828 + _globals['_REQUIREMENTS']._serialized_end=2222 + _globals['_REQUIREMENTS_EXTRARESOURCESENTRY']._serialized_start=2019 + _globals['_REQUIREMENTS_EXTRARESOURCESENTRY']._serialized_end=2122 + _globals['_REQUIREMENTS_RESOURCESENTRY']._serialized_start=2124 + _globals['_REQUIREMENTS_RESOURCESENTRY']._serialized_end=2222 + _globals['_RESOURCESELECTOR']._serialized_start=2225 + _globals['_RESOURCESELECTOR']._serialized_end=2416 + _globals['_MATCHLABELS']._serialized_start=2419 + _globals['_MATCHLABELS']._serialized_end=2552 + _globals['_MATCHLABELS_LABELSENTRY']._serialized_start=2507 + _globals['_MATCHLABELS_LABELSENTRY']._serialized_end=2552 + _globals['_RESPONSEMETA']._serialized_start=2554 + _globals['_RESPONSEMETA']._serialized_end=2634 + _globals['_STATE']._serialized_start=2637 + _globals['_STATE']._serialized_end=2870 + _globals['_STATE_RESOURCESENTRY']._serialized_start=2780 + _globals['_STATE_RESOURCESENTRY']._serialized_end=2870 + _globals['_RESOURCE']._serialized_start=2873 + _globals['_RESOURCE']._serialized_end=3131 + _globals['_RESOURCE_CONNECTIONDETAILSENTRY']._serialized_start=3075 + _globals['_RESOURCE_CONNECTIONDETAILSENTRY']._serialized_end=3131 + _globals['_RESULT']._serialized_start=3134 + _globals['_RESULT']._serialized_end=3323 + _globals['_CONDITION']._serialized_start=3326 + _globals['_CONDITION']._serialized_end=3529 + _globals['_FUNCTIONRUNNERSERVICE']._serialized_start=3915 + _globals['_FUNCTIONRUNNERSERVICE']._serialized_end=4060 # @@protoc_insertion_point(module_scope) diff --git a/crossplane/function/proto/v1beta1/run_function_pb2.pyi b/crossplane/function/proto/v1beta1/run_function_pb2.pyi index c0dd5d8..ed96678 100644 --- a/crossplane/function/proto/v1beta1/run_function_pb2.pyi +++ b/crossplane/function/proto/v1beta1/run_function_pb2.pyi @@ -50,8 +50,8 @@ STATUS_CONDITION_TRUE: Status STATUS_CONDITION_FALSE: Status class RunFunctionRequest(_message.Message): - __slots__ = ("meta", "observed", "desired", "input", "context", "required_resources", "credentials") - class RequiredResourcesEntry(_message.Message): + __slots__ = ("meta", "observed", "desired", "input", "context", "extra_resources", "credentials", "required_resources") + class ExtraResourcesEntry(_message.Message): __slots__ = ("key", "value") KEY_FIELD_NUMBER: _ClassVar[int] VALUE_FIELD_NUMBER: _ClassVar[int] @@ -65,21 +65,30 @@ class RunFunctionRequest(_message.Message): key: str value: Credentials def __init__(self, key: _Optional[str] = ..., value: _Optional[_Union[Credentials, _Mapping]] = ...) -> None: ... + class RequiredResourcesEntry(_message.Message): + __slots__ = ("key", "value") + KEY_FIELD_NUMBER: _ClassVar[int] + VALUE_FIELD_NUMBER: _ClassVar[int] + key: str + value: Resources + def __init__(self, key: _Optional[str] = ..., value: _Optional[_Union[Resources, _Mapping]] = ...) -> None: ... META_FIELD_NUMBER: _ClassVar[int] OBSERVED_FIELD_NUMBER: _ClassVar[int] DESIRED_FIELD_NUMBER: _ClassVar[int] INPUT_FIELD_NUMBER: _ClassVar[int] CONTEXT_FIELD_NUMBER: _ClassVar[int] - REQUIRED_RESOURCES_FIELD_NUMBER: _ClassVar[int] + EXTRA_RESOURCES_FIELD_NUMBER: _ClassVar[int] CREDENTIALS_FIELD_NUMBER: _ClassVar[int] + REQUIRED_RESOURCES_FIELD_NUMBER: _ClassVar[int] meta: RequestMeta observed: State desired: State input: _struct_pb2.Struct context: _struct_pb2.Struct - required_resources: _containers.MessageMap[str, Resources] + extra_resources: _containers.MessageMap[str, Resources] credentials: _containers.MessageMap[str, Credentials] - def __init__(self, meta: _Optional[_Union[RequestMeta, _Mapping]] = ..., observed: _Optional[_Union[State, _Mapping]] = ..., desired: _Optional[_Union[State, _Mapping]] = ..., input: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ..., context: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ..., required_resources: _Optional[_Mapping[str, Resources]] = ..., credentials: _Optional[_Mapping[str, Credentials]] = ...) -> None: ... + required_resources: _containers.MessageMap[str, Resources] + def __init__(self, meta: _Optional[_Union[RequestMeta, _Mapping]] = ..., observed: _Optional[_Union[State, _Mapping]] = ..., desired: _Optional[_Union[State, _Mapping]] = ..., input: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ..., context: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ..., extra_resources: _Optional[_Mapping[str, Resources]] = ..., credentials: _Optional[_Mapping[str, Credentials]] = ..., required_resources: _Optional[_Mapping[str, Resources]] = ...) -> None: ... class Credentials(_message.Message): __slots__ = ("credential_data",) @@ -131,7 +140,14 @@ class RequestMeta(_message.Message): def __init__(self, tag: _Optional[str] = ...) -> None: ... class Requirements(_message.Message): - __slots__ = ("resources",) + __slots__ = ("extra_resources", "resources") + class ExtraResourcesEntry(_message.Message): + __slots__ = ("key", "value") + KEY_FIELD_NUMBER: _ClassVar[int] + VALUE_FIELD_NUMBER: _ClassVar[int] + key: str + value: ResourceSelector + def __init__(self, key: _Optional[str] = ..., value: _Optional[_Union[ResourceSelector, _Mapping]] = ...) -> None: ... class ResourcesEntry(_message.Message): __slots__ = ("key", "value") KEY_FIELD_NUMBER: _ClassVar[int] @@ -139,9 +155,11 @@ class Requirements(_message.Message): key: str value: ResourceSelector def __init__(self, key: _Optional[str] = ..., value: _Optional[_Union[ResourceSelector, _Mapping]] = ...) -> None: ... + EXTRA_RESOURCES_FIELD_NUMBER: _ClassVar[int] RESOURCES_FIELD_NUMBER: _ClassVar[int] + extra_resources: _containers.MessageMap[str, ResourceSelector] resources: _containers.MessageMap[str, ResourceSelector] - def __init__(self, resources: _Optional[_Mapping[str, ResourceSelector]] = ...) -> None: ... + def __init__(self, extra_resources: _Optional[_Mapping[str, ResourceSelector]] = ..., resources: _Optional[_Mapping[str, ResourceSelector]] = ...) -> None: ... class ResourceSelector(_message.Message): __slots__ = ("api_version", "kind", "match_name", "match_labels", "namespace") From 3fd547c27577b3a2621b62e47ef414270a5bae8f Mon Sep 17 00:00:00 2001 From: Nic Cope Date: Tue, 5 Aug 2025 11:08:57 -0700 Subject: [PATCH 08/11] Use deterministic JSON ordering in tests Signed-off-by: Nic Cope --- tests/test_response.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test_response.py b/tests/test_response.py index 4930592..9e33153 100644 --- a/tests/test_response.py +++ b/tests/test_response.py @@ -66,8 +66,8 @@ class TestCase: for case in cases: got = response.to(case.req, case.ttl) self.assertEqual( - json_format.MessageToJson(case.want), - json_format.MessageToJson(got), + json_format.MessageToJson(case.want, sort_keys=True), + json_format.MessageToJson(got, sort_keys=True), "-want, +got", ) @@ -185,8 +185,8 @@ class TestCase: got_selector = case.rsp.requirements.resources[case.name] self.assertEqual( - json_format.MessageToJson(case.want_selector), - json_format.MessageToJson(got_selector), + json_format.MessageToJson(case.want_selector, sort_keys=True), + json_format.MessageToJson(got_selector, sort_keys=True), case.reason, ) From eed39d527ba1744a2eb9dd74e4f9a395b3fd0865 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 5 Aug 2025 18:33:04 +0000 Subject: [PATCH 09/11] chore(deps): update dependency ruff to v0.12.7 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 204fa37..c91ae4c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -66,7 +66,7 @@ packages = ["crossplane"] # This special environment is used by hatch fmt. [tool.hatch.envs.hatch-static-analysis] -dependencies = ["ruff==0.12.5"] +dependencies = ["ruff==0.12.7"] config-path = "none" # Disable Hatch's default Ruff config. [tool.ruff] From a4b06533be8780cac4c0bb4b4e5eb575fa74c459 Mon Sep 17 00:00:00 2001 From: Nic Cope Date: Tue, 5 Aug 2025 14:17:13 -0700 Subject: [PATCH 10/11] Fix get_credentials, and move it to request I don't think this would've ever worked if passed a RunFunctionRequest due to the way field presence works in most protobuf messages. In practice I can't think why req would ever be a Struct and not a RunFunctionRequest. Signed-off-by: Nic Cope --- crossplane/function/request.py | 43 +++++++++++++++++++++++++++ crossplane/function/resource.py | 21 ------------- tests/test_request.py | 52 +++++++++++++++++++++++++++++++++ tests/test_resource.py | 43 --------------------------- 4 files changed, 95 insertions(+), 64 deletions(-) diff --git a/crossplane/function/request.py b/crossplane/function/request.py index c4516e6..ad408c9 100644 --- a/crossplane/function/request.py +++ b/crossplane/function/request.py @@ -14,10 +14,20 @@ """Utilities for working with RunFunctionRequests.""" +import dataclasses + import crossplane.function.proto.v1.run_function_pb2 as fnv1 from crossplane.function import resource +@dataclasses.dataclass +class Credentials: + """Credentials.""" + + type: str + data: dict + + def get_required_resources(req: fnv1.RunFunctionRequest, name: str) -> list[dict]: """Get required resources by name from the request. @@ -73,3 +83,36 @@ def get_required_resource(req: fnv1.RunFunctionRequest, name: str) -> dict | Non """ resources = get_required_resources(req, name) return resources[0] if resources else None + + +def get_credentials(req: fnv1.RunFunctionRequest, name: str) -> Credentials: + """Get the supplied credentials from the request. + + Args: + req: The RunFunctionRequest containing credentials. + name: The name of the credentials to get. + + Returns: + The requested credentials with type and data. + + If the credentials don't exist, returns empty credentials with type "data" + and empty data dictionary. + """ + empty = Credentials(type="data", data={}) + + if not req or name not in req.credentials: + return empty + + cred = req.credentials[name] + + # Use WhichOneof to determine which field in the oneof is set + source_type = cred.WhichOneof("source") + if source_type == "credential_data": + # Convert bytes data to string data for backward compatibility + data = {} + for key, value in cred.credential_data.data.items(): + data[key] = value.decode("utf-8") + return Credentials(type="credential_data", data=data) + + # If no recognized source type is set, return empty + return empty diff --git a/crossplane/function/resource.py b/crossplane/function/resource.py index c9bfc69..fae7be6 100644 --- a/crossplane/function/resource.py +++ b/crossplane/function/resource.py @@ -140,24 +140,3 @@ def get_condition(resource: structpb.Struct, typ: str) -> Condition: return condition return unknown - - -@dataclasses.dataclass -class Credentials: - """Credentials.""" - - type: str - data: dict - - -def get_credentials(req: structpb.Struct, name: str) -> Credentials: - """Get the supplied credentials.""" - empty = Credentials(type="data", data={}) - if not req or "credentials" not in req: - return empty - if not req["credentials"] or name not in req["credentials"]: - return empty - return Credentials( - type=req["credentials"][name]["type"], - data=struct_to_dict(req["credentials"][name]["data"]), - ) diff --git a/tests/test_request.py b/tests/test_request.py index f8079d3..a517814 100644 --- a/tests/test_request.py +++ b/tests/test_request.py @@ -212,6 +212,58 @@ class TestCase: got = request.get_required_resource(case.req, case.name) self.assertEqual(case.want, got, case.reason) + def test_get_credentials(self) -> None: + @dataclasses.dataclass + class TestCase: + reason: str + req: fnv1.RunFunctionRequest + name: str + want: request.Credentials + + cases = [ + TestCase( + reason="Should return empty credentials when no credentials exist.", + req=fnv1.RunFunctionRequest(), + name="test", + want=request.Credentials(type="data", data={}), + ), + TestCase( + reason="Should return empty credentials when specified name not found.", + req=fnv1.RunFunctionRequest( + credentials={ + "other-cred": fnv1.Credentials( + credential_data=fnv1.CredentialData(data={"key": b"value"}) + ) + } + ), + name="test", + want=request.Credentials(type="data", data={}), + ), + TestCase( + reason="Should return credentials when they exist.", + req=fnv1.RunFunctionRequest( + credentials={ + "test": fnv1.Credentials( + credential_data=fnv1.CredentialData( + data={"username": b"admin", "password": b"secret"} + ) + ) + } + ), + name="test", + want=request.Credentials( + type="credential_data", + data={"username": "admin", "password": "secret"}, + ), + ), + ] + + for case in cases: + got = request.get_credentials(case.req, case.name) + self.assertEqual( + dataclasses.asdict(case.want), dataclasses.asdict(got), case.reason + ) + if __name__ == "__main__": unittest.main() diff --git a/tests/test_resource.py b/tests/test_resource.py index 010fed8..004295f 100644 --- a/tests/test_resource.py +++ b/tests/test_resource.py @@ -205,49 +205,6 @@ class TestCase: dataclasses.asdict(case.want), dataclasses.asdict(got), "-want, +got" ) - def test_get_credentials(self) -> None: - @dataclasses.dataclass - class TestCase: - reason: str - req: structpb.Struct - name: str - want: resource.Credentials - - cases = [ - TestCase( - reason="Return the specified credentials if they exist.", - req=resource.dict_to_struct( - {"credentials": {"test": {"type": "data", "data": {"foo": "bar"}}}} - ), - name="test", - want=resource.Credentials(type="data", data={"foo": "bar"}), - ), - TestCase( - reason="Return empty credentials if no credentials section exists.", - req=resource.dict_to_struct({}), - name="test", - want=resource.Credentials(type="data", data={}), - ), - TestCase( - reason="Return empty credentials if the specified name does not exist.", - req=resource.dict_to_struct( - { - "credentials": { - "nottest": {"type": "data", "data": {"foo": "bar"}} - } - } - ), - name="test", - want=resource.Credentials(type="data", data={}), - ), - ] - - for case in cases: - got = resource.get_credentials(case.req, case.name) - self.assertEqual( - dataclasses.asdict(case.want), dataclasses.asdict(got), "-want, +got" - ) - def test_dict_to_struct(self) -> None: @dataclasses.dataclass class TestCase: From 70b3c3c6d33736da2b1f270d493b4444f32ae710 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 6 Aug 2025 01:31:10 +0000 Subject: [PATCH 11/11] chore(deps): update actions/download-artifact action to v5 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4533d8f..c03d08e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -114,7 +114,7 @@ jobs: runs-on: ubuntu-24.04 steps: - name: Download Sdist and Wheel from GitHub - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v5 with: name: dist path: "dist"