Promote composition functions to v1
Signed-off-by: Nic Cope <nicc@rk0n.org>
This commit is contained in:
parent
7837143425
commit
0f7d85f43d
|
@ -0,0 +1,326 @@
|
|||
/*
|
||||
Copyright 2022 The Crossplane Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
import "google/protobuf/struct.proto";
|
||||
import "google/protobuf/duration.proto";
|
||||
|
||||
package apiextensions.fn.proto.v1;
|
||||
|
||||
option go_package = "github.com/crossplane/crossplane/apis/apiextensions/fn/proto/v1";
|
||||
|
||||
// A FunctionRunnerService is a Composition Function.
|
||||
service FunctionRunnerService {
|
||||
// RunFunction runs the Composition Function.
|
||||
rpc RunFunction(RunFunctionRequest) returns (RunFunctionResponse) {}
|
||||
}
|
||||
|
||||
// A RunFunctionRequest requests that the Composition Function be run.
|
||||
message RunFunctionRequest {
|
||||
// Metadata pertaining to this request.
|
||||
RequestMeta meta = 1;
|
||||
|
||||
// The observed state prior to invocation of a Function pipeline. State passed
|
||||
// to each Function is fresh as of the time the pipeline was invoked, not as
|
||||
// of the time each Function was invoked.
|
||||
State observed = 2;
|
||||
|
||||
// Desired state according to a Function pipeline. The state passed to a
|
||||
// particular Function may have been accumulated by previous Functions in the
|
||||
// pipeline.
|
||||
//
|
||||
// Note that the desired state must be a partial object with only the fields
|
||||
// that this function (and its predecessors in the pipeline) wants to have
|
||||
// set in the object. Copying a non-partial observed state to desired is most
|
||||
// likely not what you want to do. Leaving out fields that had been returned
|
||||
// as desired before will result in them being deleted from the objects in the
|
||||
// cluster.
|
||||
State desired = 3;
|
||||
|
||||
// Optional input specific to this Function invocation. A JSON representation
|
||||
// of the 'input' block of the relevant entry in a Composition's pipeline.
|
||||
optional google.protobuf.Struct input = 4;
|
||||
|
||||
// Optional context. Crossplane may pass 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 google.protobuf.Struct context = 5;
|
||||
|
||||
// Optional extra resources that the Function required.
|
||||
// Note that extra resources is a map to Resources, plural.
|
||||
// The map key corresponds to the key in a RunFunctionResponse's
|
||||
// extra_resources field. If a Function requested extra resources that
|
||||
// did not exist, Crossplane sets the map key to an empty Resources message to
|
||||
// indicate that it attempted to satisfy the request.
|
||||
map<string, Resources> extra_resources = 6;
|
||||
|
||||
// Optional credentials that this Function may use to communicate with an
|
||||
// external system.
|
||||
map <string, Credentials> credentials = 7;
|
||||
}
|
||||
|
||||
// Credentials that a Function may use to communicate with an external system.
|
||||
message Credentials {
|
||||
// Source of the credentials.
|
||||
oneof source {
|
||||
// Credential data loaded by Crossplane, for example from a Secret.
|
||||
CredentialData credential_data = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// CredentialData loaded by Crossplane, for example from a Secret.
|
||||
message CredentialData {
|
||||
map<string, bytes> data = 1;
|
||||
}
|
||||
|
||||
// Resources represents the state of several Crossplane resources.
|
||||
message Resources {
|
||||
repeated Resource items = 1;
|
||||
}
|
||||
|
||||
// A RunFunctionResponse contains the result of a Composition Function run.
|
||||
message RunFunctionResponse {
|
||||
// Metadata pertaining to this response.
|
||||
ResponseMeta meta = 1;
|
||||
|
||||
// Desired state according to a Function pipeline. Functions may add desired
|
||||
// state, and may mutate or delete any part of the desired state they are
|
||||
// concerned with. A Function must pass through any part of the desired state
|
||||
// that it is not concerned with.
|
||||
//
|
||||
//
|
||||
// Note that the desired state must be a partial object with only the fields
|
||||
// that this function (and its predecessors in the pipeline) wants to have
|
||||
// set in the object. Copying a non-partial observed state to desired is most
|
||||
// likely not what you want to do. Leaving out fields that had been returned
|
||||
// as desired before will result in them being deleted from the objects in the
|
||||
// cluster.
|
||||
State desired = 2;
|
||||
|
||||
// Results of the Function run. Results are used for observability purposes.
|
||||
repeated Result results = 3;
|
||||
|
||||
// Optional context to be passed to the next Function in the pipeline as part
|
||||
// of the RunFunctionRequest. Dropped on the last function in the pipeline.
|
||||
optional google.protobuf.Struct context = 4;
|
||||
|
||||
// Requirements that must be satisfied for this Function to run successfully.
|
||||
Requirements requirements = 5;
|
||||
|
||||
// Status conditions to be applied to the composite resource. Conditions may also
|
||||
// optionally be applied to the composite resource's associated claim.
|
||||
repeated Condition conditions = 6;
|
||||
}
|
||||
|
||||
// RequestMeta contains metadata pertaining to a RunFunctionRequest.
|
||||
message RequestMeta {
|
||||
// An opaque string identifying the content of the request. Two identical
|
||||
// requests should have the same tag.
|
||||
string tag = 1;
|
||||
}
|
||||
|
||||
// Requirements that must be satisfied for a Function to run successfully.
|
||||
message Requirements {
|
||||
// Extra resources that this Function requires.
|
||||
// The map key uniquely identifies the group of resources.
|
||||
map<string, ResourceSelector> extra_resources = 1;
|
||||
}
|
||||
|
||||
// ResourceSelector selects a group of resources, either by name or by label.
|
||||
message ResourceSelector {
|
||||
// API version of resources to select.
|
||||
string api_version = 1;
|
||||
|
||||
// Kind of resources to select.
|
||||
string kind = 2;
|
||||
|
||||
// Resources to match.
|
||||
oneof match {
|
||||
// Match the resource with this name.
|
||||
string match_name = 3;
|
||||
|
||||
// Match all resources with these labels.
|
||||
MatchLabels match_labels = 4;
|
||||
}
|
||||
}
|
||||
|
||||
// MatchLabels defines a set of labels to match resources against.
|
||||
message MatchLabels {
|
||||
map<string, string> labels = 1;
|
||||
}
|
||||
|
||||
// ResponseMeta contains metadata pertaining to a RunFunctionResponse.
|
||||
message ResponseMeta {
|
||||
// An opaque string identifying the content of the request. Must match the
|
||||
// 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.
|
||||
optional google.protobuf.Duration ttl = 2;
|
||||
}
|
||||
|
||||
// State of the composite resource (XR) and any composed resources.
|
||||
message State {
|
||||
// The state of the composite resource (XR).
|
||||
Resource composite = 1;
|
||||
|
||||
// The state of any composed resources.
|
||||
map<string, Resource> resources = 2;
|
||||
}
|
||||
|
||||
// A Resource represents the state of a composite or composed resource.
|
||||
message Resource {
|
||||
// The JSON representation of the resource.
|
||||
//
|
||||
// * Crossplane will set this field in a RunFunctionRequest to the entire
|
||||
// observed state of a resource - including its metadata, spec, and status.
|
||||
//
|
||||
// * A Function should set this field in a RunFunctionRequest to communicate
|
||||
// the desired state of a composite or composed resource.
|
||||
//
|
||||
// * A Function may only specify the desired status of a composite resource -
|
||||
// not its metadata or spec. A Function should not return desired metadata
|
||||
// or spec for a composite resource. This will be ignored.
|
||||
//
|
||||
// * A Function may not specify the desired status of a composed resource -
|
||||
// only its metadata and spec. A Function should not return desired status
|
||||
// for a composed resource. This will be ignored.
|
||||
google.protobuf.Struct resource = 1;
|
||||
|
||||
// The resource's connection details.
|
||||
//
|
||||
// * Crossplane will set this field in a RunFunctionRequest to communicate the
|
||||
// the observed connection details of a composite or composed resource.
|
||||
//
|
||||
// * A Function should set this field in a RunFunctionResponse to indicate the
|
||||
// desired connection details of the composite resource.
|
||||
//
|
||||
// * A Function should not set this field in a RunFunctionResponse to indicate
|
||||
// the desired connection details of a composed resource. This will be
|
||||
// ignored.
|
||||
map<string, bytes> connection_details = 2;
|
||||
|
||||
// Ready indicates whether the resource should be considered ready.
|
||||
//
|
||||
// * Crossplane will never set this field in a RunFunctionRequest.
|
||||
//
|
||||
// * A Function should set this field to READY_TRUE in a RunFunctionResponse
|
||||
// to indicate that a desired composed resource is ready.
|
||||
//
|
||||
// * A Function should not set this field in a RunFunctionResponse to indicate
|
||||
// that the desired composite resource is ready. This will be ignored.
|
||||
Ready ready = 3;
|
||||
}
|
||||
|
||||
// Ready indicates whether a composed resource should be considered ready.
|
||||
enum Ready {
|
||||
READY_UNSPECIFIED = 0;
|
||||
|
||||
// True means the composed resource has been observed to be ready.
|
||||
READY_TRUE = 1;
|
||||
|
||||
// False means the composed resource has not been observed to be ready.
|
||||
READY_FALSE = 2;
|
||||
}
|
||||
|
||||
// A Result of running a Function.
|
||||
message Result {
|
||||
// Severity of this result.
|
||||
Severity severity = 1;
|
||||
|
||||
// Human-readable details about the result.
|
||||
string message = 2;
|
||||
|
||||
// Optional PascalCase, machine-readable reason for this result. If omitted,
|
||||
// the value will be ComposeResources.
|
||||
optional string reason = 3;
|
||||
|
||||
// The resources this result targets.
|
||||
optional Target target = 4;
|
||||
}
|
||||
|
||||
// Severity of Function results.
|
||||
enum Severity {
|
||||
SEVERITY_UNSPECIFIED = 0;
|
||||
|
||||
// Fatal results are fatal; subsequent Composition Functions may run, but
|
||||
// the Composition Function pipeline run will be considered a failure and
|
||||
// the first fatal result will be returned as an error.
|
||||
SEVERITY_FATAL = 1;
|
||||
|
||||
// Warning results are non-fatal; the entire Composition will run to
|
||||
// completion but warning events and debug logs associated with the
|
||||
// composite resource will be emitted.
|
||||
SEVERITY_WARNING = 2;
|
||||
|
||||
// Normal results are emitted as normal events and debug logs associated
|
||||
// with the composite resource.
|
||||
SEVERITY_NORMAL = 3;
|
||||
}
|
||||
|
||||
// Target of Function results and conditions.
|
||||
enum Target {
|
||||
// If the target is unspecified, the result targets the composite resource.
|
||||
TARGET_UNSPECIFIED = 0;
|
||||
|
||||
// Target the composite resource. Results that target the composite resource
|
||||
// should include detailed, advanced information.
|
||||
TARGET_COMPOSITE = 1;
|
||||
|
||||
// Target the composite and the claim. Results that target the composite and
|
||||
// the claim should include only end-user friendly information.
|
||||
TARGET_COMPOSITE_AND_CLAIM = 2;
|
||||
}
|
||||
|
||||
// Status condition to be applied to the composite resource. Condition may also
|
||||
// optionally be applied to the composite resource's associated claim. For
|
||||
// detailed information on proper usage of status conditions, please see
|
||||
// https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties.
|
||||
message Condition {
|
||||
// Type of condition in PascalCase.
|
||||
string type = 1;
|
||||
|
||||
// Status of the condition.
|
||||
Status status = 2;
|
||||
|
||||
// Reason contains a programmatic identifier indicating the reason for the
|
||||
// condition's last transition. Producers of specific condition types may
|
||||
// define expected values and meanings for this field, and whether the values
|
||||
// are considered a guaranteed API. The value should be a PascalCase string.
|
||||
// This field may not be empty.
|
||||
string reason = 3;
|
||||
|
||||
// Message is a human readable message indicating details about the
|
||||
// transition. This may be an empty string.
|
||||
optional string message = 4;
|
||||
|
||||
// The resources this condition targets.
|
||||
optional Target target = 5;
|
||||
}
|
||||
|
||||
enum Status {
|
||||
STATUS_CONDITION_UNSPECIFIED = 0;
|
||||
|
||||
STATUS_CONDITION_UNKNOWN = 1;
|
||||
|
||||
STATUS_CONDITION_TRUE = 2;
|
||||
|
||||
STATUS_CONDITION_FALSE = 3;
|
||||
}
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,232 @@
|
|||
from google.protobuf import struct_pb2 as _struct_pb2
|
||||
from google.protobuf import duration_pb2 as _duration_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
|
||||
|
||||
DESCRIPTOR: _descriptor.FileDescriptor
|
||||
|
||||
class Ready(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
|
||||
__slots__ = ()
|
||||
READY_UNSPECIFIED: _ClassVar[Ready]
|
||||
READY_TRUE: _ClassVar[Ready]
|
||||
READY_FALSE: _ClassVar[Ready]
|
||||
|
||||
class Severity(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
|
||||
__slots__ = ()
|
||||
SEVERITY_UNSPECIFIED: _ClassVar[Severity]
|
||||
SEVERITY_FATAL: _ClassVar[Severity]
|
||||
SEVERITY_WARNING: _ClassVar[Severity]
|
||||
SEVERITY_NORMAL: _ClassVar[Severity]
|
||||
|
||||
class Target(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
|
||||
__slots__ = ()
|
||||
TARGET_UNSPECIFIED: _ClassVar[Target]
|
||||
TARGET_COMPOSITE: _ClassVar[Target]
|
||||
TARGET_COMPOSITE_AND_CLAIM: _ClassVar[Target]
|
||||
|
||||
class Status(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
|
||||
__slots__ = ()
|
||||
STATUS_CONDITION_UNSPECIFIED: _ClassVar[Status]
|
||||
STATUS_CONDITION_UNKNOWN: _ClassVar[Status]
|
||||
STATUS_CONDITION_TRUE: _ClassVar[Status]
|
||||
STATUS_CONDITION_FALSE: _ClassVar[Status]
|
||||
READY_UNSPECIFIED: Ready
|
||||
READY_TRUE: Ready
|
||||
READY_FALSE: Ready
|
||||
SEVERITY_UNSPECIFIED: Severity
|
||||
SEVERITY_FATAL: Severity
|
||||
SEVERITY_WARNING: Severity
|
||||
SEVERITY_NORMAL: Severity
|
||||
TARGET_UNSPECIFIED: Target
|
||||
TARGET_COMPOSITE: Target
|
||||
TARGET_COMPOSITE_AND_CLAIM: Target
|
||||
STATUS_CONDITION_UNSPECIFIED: Status
|
||||
STATUS_CONDITION_UNKNOWN: Status
|
||||
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__ = ("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: ...
|
||||
class CredentialsEntry(_message.Message):
|
||||
__slots__ = ("key", "value")
|
||||
KEY_FIELD_NUMBER: _ClassVar[int]
|
||||
VALUE_FIELD_NUMBER: _ClassVar[int]
|
||||
key: str
|
||||
value: Credentials
|
||||
def __init__(self, key: _Optional[str] = ..., value: _Optional[_Union[Credentials, _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]
|
||||
EXTRA_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]
|
||||
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: ...
|
||||
|
||||
class Credentials(_message.Message):
|
||||
__slots__ = ("credential_data",)
|
||||
CREDENTIAL_DATA_FIELD_NUMBER: _ClassVar[int]
|
||||
credential_data: CredentialData
|
||||
def __init__(self, credential_data: _Optional[_Union[CredentialData, _Mapping]] = ...) -> None: ...
|
||||
|
||||
class CredentialData(_message.Message):
|
||||
__slots__ = ("data",)
|
||||
class DataEntry(_message.Message):
|
||||
__slots__ = ("key", "value")
|
||||
KEY_FIELD_NUMBER: _ClassVar[int]
|
||||
VALUE_FIELD_NUMBER: _ClassVar[int]
|
||||
key: str
|
||||
value: bytes
|
||||
def __init__(self, key: _Optional[str] = ..., value: _Optional[bytes] = ...) -> None: ...
|
||||
DATA_FIELD_NUMBER: _ClassVar[int]
|
||||
data: _containers.ScalarMap[str, bytes]
|
||||
def __init__(self, data: _Optional[_Mapping[str, bytes]] = ...) -> None: ...
|
||||
|
||||
class Resources(_message.Message):
|
||||
__slots__ = ("items",)
|
||||
ITEMS_FIELD_NUMBER: _ClassVar[int]
|
||||
items: _containers.RepeatedCompositeFieldContainer[Resource]
|
||||
def __init__(self, items: _Optional[_Iterable[_Union[Resource, _Mapping]]] = ...) -> None: ...
|
||||
|
||||
class RunFunctionResponse(_message.Message):
|
||||
__slots__ = ("meta", "desired", "results", "context", "requirements", "conditions")
|
||||
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]
|
||||
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: ...
|
||||
|
||||
class RequestMeta(_message.Message):
|
||||
__slots__ = ("tag",)
|
||||
TAG_FIELD_NUMBER: _ClassVar[int]
|
||||
tag: str
|
||||
def __init__(self, tag: _Optional[str] = ...) -> None: ...
|
||||
|
||||
class Requirements(_message.Message):
|
||||
__slots__ = ("extra_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: ...
|
||||
EXTRA_RESOURCES_FIELD_NUMBER: _ClassVar[int]
|
||||
extra_resources: _containers.MessageMap[str, ResourceSelector]
|
||||
def __init__(self, extra_resources: _Optional[_Mapping[str, ResourceSelector]] = ...) -> None: ...
|
||||
|
||||
class ResourceSelector(_message.Message):
|
||||
__slots__ = ("api_version", "kind", "match_name", "match_labels")
|
||||
API_VERSION_FIELD_NUMBER: _ClassVar[int]
|
||||
KIND_FIELD_NUMBER: _ClassVar[int]
|
||||
MATCH_NAME_FIELD_NUMBER: _ClassVar[int]
|
||||
MATCH_LABELS_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: ...
|
||||
|
||||
class MatchLabels(_message.Message):
|
||||
__slots__ = ("labels",)
|
||||
class LabelsEntry(_message.Message):
|
||||
__slots__ = ("key", "value")
|
||||
KEY_FIELD_NUMBER: _ClassVar[int]
|
||||
VALUE_FIELD_NUMBER: _ClassVar[int]
|
||||
key: str
|
||||
value: str
|
||||
def __init__(self, key: _Optional[str] = ..., value: _Optional[str] = ...) -> None: ...
|
||||
LABELS_FIELD_NUMBER: _ClassVar[int]
|
||||
labels: _containers.ScalarMap[str, str]
|
||||
def __init__(self, labels: _Optional[_Mapping[str, str]] = ...) -> None: ...
|
||||
|
||||
class ResponseMeta(_message.Message):
|
||||
__slots__ = ("tag", "ttl")
|
||||
TAG_FIELD_NUMBER: _ClassVar[int]
|
||||
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: ...
|
||||
|
||||
class State(_message.Message):
|
||||
__slots__ = ("composite", "resources")
|
||||
class ResourcesEntry(_message.Message):
|
||||
__slots__ = ("key", "value")
|
||||
KEY_FIELD_NUMBER: _ClassVar[int]
|
||||
VALUE_FIELD_NUMBER: _ClassVar[int]
|
||||
key: str
|
||||
value: Resource
|
||||
def __init__(self, key: _Optional[str] = ..., value: _Optional[_Union[Resource, _Mapping]] = ...) -> None: ...
|
||||
COMPOSITE_FIELD_NUMBER: _ClassVar[int]
|
||||
RESOURCES_FIELD_NUMBER: _ClassVar[int]
|
||||
composite: Resource
|
||||
resources: _containers.MessageMap[str, Resource]
|
||||
def __init__(self, composite: _Optional[_Union[Resource, _Mapping]] = ..., resources: _Optional[_Mapping[str, Resource]] = ...) -> None: ...
|
||||
|
||||
class Resource(_message.Message):
|
||||
__slots__ = ("resource", "connection_details", "ready")
|
||||
class ConnectionDetailsEntry(_message.Message):
|
||||
__slots__ = ("key", "value")
|
||||
KEY_FIELD_NUMBER: _ClassVar[int]
|
||||
VALUE_FIELD_NUMBER: _ClassVar[int]
|
||||
key: str
|
||||
value: bytes
|
||||
def __init__(self, key: _Optional[str] = ..., value: _Optional[bytes] = ...) -> None: ...
|
||||
RESOURCE_FIELD_NUMBER: _ClassVar[int]
|
||||
CONNECTION_DETAILS_FIELD_NUMBER: _ClassVar[int]
|
||||
READY_FIELD_NUMBER: _ClassVar[int]
|
||||
resource: _struct_pb2.Struct
|
||||
connection_details: _containers.ScalarMap[str, bytes]
|
||||
ready: Ready
|
||||
def __init__(self, resource: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ..., connection_details: _Optional[_Mapping[str, bytes]] = ..., ready: _Optional[_Union[Ready, str]] = ...) -> None: ...
|
||||
|
||||
class Result(_message.Message):
|
||||
__slots__ = ("severity", "message", "reason", "target")
|
||||
SEVERITY_FIELD_NUMBER: _ClassVar[int]
|
||||
MESSAGE_FIELD_NUMBER: _ClassVar[int]
|
||||
REASON_FIELD_NUMBER: _ClassVar[int]
|
||||
TARGET_FIELD_NUMBER: _ClassVar[int]
|
||||
severity: Severity
|
||||
message: str
|
||||
reason: str
|
||||
target: Target
|
||||
def __init__(self, severity: _Optional[_Union[Severity, str]] = ..., message: _Optional[str] = ..., reason: _Optional[str] = ..., target: _Optional[_Union[Target, str]] = ...) -> None: ...
|
||||
|
||||
class Condition(_message.Message):
|
||||
__slots__ = ("type", "status", "reason", "message", "target")
|
||||
TYPE_FIELD_NUMBER: _ClassVar[int]
|
||||
STATUS_FIELD_NUMBER: _ClassVar[int]
|
||||
REASON_FIELD_NUMBER: _ClassVar[int]
|
||||
MESSAGE_FIELD_NUMBER: _ClassVar[int]
|
||||
TARGET_FIELD_NUMBER: _ClassVar[int]
|
||||
type: str
|
||||
status: Status
|
||||
reason: str
|
||||
message: str
|
||||
target: Target
|
||||
def __init__(self, type: _Optional[str] = ..., status: _Optional[_Union[Status, str]] = ..., reason: _Optional[str] = ..., message: _Optional[str] = ..., target: _Optional[_Union[Target, str]] = ...) -> None: ...
|
|
@ -0,0 +1,106 @@
|
|||
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
|
||||
"""Client and server classes corresponding to protobuf-defined services."""
|
||||
import grpc
|
||||
import warnings
|
||||
|
||||
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.65.4'
|
||||
GRPC_VERSION = grpc.__version__
|
||||
EXPECTED_ERROR_RELEASE = '1.66.0'
|
||||
SCHEDULED_RELEASE_DATE = 'August 6, 2024'
|
||||
_version_not_supported = False
|
||||
|
||||
try:
|
||||
from grpc._utilities import first_version_is_lower
|
||||
_version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION)
|
||||
except ImportError:
|
||||
_version_not_supported = True
|
||||
|
||||
if _version_not_supported:
|
||||
warnings.warn(
|
||||
f'The grpc package installed is at version {GRPC_VERSION},'
|
||||
+ f' but the generated code in crossplane/function/proto/v1/run_function_pb2_grpc.py depends on'
|
||||
+ f' grpcio>={GRPC_GENERATED_VERSION}.'
|
||||
+ f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}'
|
||||
+ f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.'
|
||||
+ f' This warning will become an error in {EXPECTED_ERROR_RELEASE},'
|
||||
+ f' scheduled for release on {SCHEDULED_RELEASE_DATE}.',
|
||||
RuntimeWarning
|
||||
)
|
||||
|
||||
|
||||
class FunctionRunnerServiceStub(object):
|
||||
"""A FunctionRunnerService is a Composition Function.
|
||||
"""
|
||||
|
||||
def __init__(self, channel):
|
||||
"""Constructor.
|
||||
|
||||
Args:
|
||||
channel: A grpc.Channel.
|
||||
"""
|
||||
self.RunFunction = channel.unary_unary(
|
||||
'/apiextensions.fn.proto.v1.FunctionRunnerService/RunFunction',
|
||||
request_serializer=crossplane_dot_function_dot_proto_dot_v1_dot_run__function__pb2.RunFunctionRequest.SerializeToString,
|
||||
response_deserializer=crossplane_dot_function_dot_proto_dot_v1_dot_run__function__pb2.RunFunctionResponse.FromString,
|
||||
_registered_method=True)
|
||||
|
||||
|
||||
class FunctionRunnerServiceServicer(object):
|
||||
"""A FunctionRunnerService is a Composition Function.
|
||||
"""
|
||||
|
||||
def RunFunction(self, request, context):
|
||||
"""RunFunction runs the Composition Function.
|
||||
"""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
|
||||
def add_FunctionRunnerServiceServicer_to_server(servicer, server):
|
||||
rpc_method_handlers = {
|
||||
'RunFunction': grpc.unary_unary_rpc_method_handler(
|
||||
servicer.RunFunction,
|
||||
request_deserializer=crossplane_dot_function_dot_proto_dot_v1_dot_run__function__pb2.RunFunctionRequest.FromString,
|
||||
response_serializer=crossplane_dot_function_dot_proto_dot_v1_dot_run__function__pb2.RunFunctionResponse.SerializeToString,
|
||||
),
|
||||
}
|
||||
generic_handler = grpc.method_handlers_generic_handler(
|
||||
'apiextensions.fn.proto.v1.FunctionRunnerService', rpc_method_handlers)
|
||||
server.add_generic_rpc_handlers((generic_handler,))
|
||||
server.add_registered_method_handlers('apiextensions.fn.proto.v1.FunctionRunnerService', rpc_method_handlers)
|
||||
|
||||
|
||||
# This class is part of an EXPERIMENTAL API.
|
||||
class FunctionRunnerService(object):
|
||||
"""A FunctionRunnerService is a Composition Function.
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def RunFunction(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_unary(
|
||||
request,
|
||||
target,
|
||||
'/apiextensions.fn.proto.v1.FunctionRunnerService/RunFunction',
|
||||
crossplane_dot_function_dot_proto_dot_v1_dot_run__function__pb2.RunFunctionRequest.SerializeToString,
|
||||
crossplane_dot_function_dot_proto_dot_v1_dot_run__function__pb2.RunFunctionResponse.FromString,
|
||||
options,
|
||||
channel_credentials,
|
||||
insecure,
|
||||
call_credentials,
|
||||
compression,
|
||||
wait_for_ready,
|
||||
timeout,
|
||||
metadata,
|
||||
_registered_method=True)
|
|
@ -19,11 +19,12 @@ syntax = "proto3";
|
|||
import "google/protobuf/struct.proto";
|
||||
import "google/protobuf/duration.proto";
|
||||
|
||||
// Note that the authoritative Composition Functions protobuf definition lives
|
||||
// at the below URL. Each SDK maintains and manually syncs its own copy.
|
||||
// https://github.com/crossplane/crossplane/tree/master/apis/apiextensions/fn/proto
|
||||
// Generated from apiextensions/fn/proto/v1/run_function.proto by ../hack/duplicate_proto_type.sh. DO NOT EDIT.
|
||||
|
||||
package apiextensions.fn.proto.v1beta1;
|
||||
|
||||
option go_package = "github.com/crossplane/crossplane/apis/apiextensions/fn/proto/v1beta1";
|
||||
|
||||
// A FunctionRunnerService is a Composition Function.
|
||||
service FunctionRunnerService {
|
||||
// RunFunction runs the Composition Function.
|
||||
|
@ -122,6 +123,10 @@ message RunFunctionResponse {
|
|||
|
||||
// Requirements that must be satisfied for this Function to run successfully.
|
||||
Requirements requirements = 5;
|
||||
|
||||
// Status conditions to be applied to the composite resource. Conditions may also
|
||||
// optionally be applied to the composite resource's associated claim.
|
||||
repeated Condition conditions = 6;
|
||||
}
|
||||
|
||||
// RequestMeta contains metadata pertaining to a RunFunctionRequest.
|
||||
|
@ -140,11 +145,18 @@ message Requirements {
|
|||
|
||||
// ResourceSelector selects a group of resources, either by name or by label.
|
||||
message ResourceSelector {
|
||||
// API version of resources to select.
|
||||
string api_version = 1;
|
||||
|
||||
// Kind of resources to select.
|
||||
string kind = 2;
|
||||
|
||||
// Resources to match.
|
||||
oneof match {
|
||||
// Match the resource with this name.
|
||||
string match_name = 3;
|
||||
|
||||
// Match all resources with these labels.
|
||||
MatchLabels match_labels = 4;
|
||||
}
|
||||
}
|
||||
|
@ -237,6 +249,13 @@ message Result {
|
|||
|
||||
// Human-readable details about the result.
|
||||
string message = 2;
|
||||
|
||||
// Optional PascalCase, machine-readable reason for this result. If omitted,
|
||||
// the value will be ComposeResources.
|
||||
optional string reason = 3;
|
||||
|
||||
// The resources this result targets.
|
||||
optional Target target = 4;
|
||||
}
|
||||
|
||||
// Severity of Function results.
|
||||
|
@ -257,3 +276,53 @@ enum Severity {
|
|||
// with the composite resource.
|
||||
SEVERITY_NORMAL = 3;
|
||||
}
|
||||
|
||||
// Target of Function results and conditions.
|
||||
enum Target {
|
||||
// If the target is unspecified, the result targets the composite resource.
|
||||
TARGET_UNSPECIFIED = 0;
|
||||
|
||||
// Target the composite resource. Results that target the composite resource
|
||||
// should include detailed, advanced information.
|
||||
TARGET_COMPOSITE = 1;
|
||||
|
||||
// Target the composite and the claim. Results that target the composite and
|
||||
// the claim should include only end-user friendly information.
|
||||
TARGET_COMPOSITE_AND_CLAIM = 2;
|
||||
}
|
||||
|
||||
// Status condition to be applied to the composite resource. Condition may also
|
||||
// optionally be applied to the composite resource's associated claim. For
|
||||
// detailed information on proper usage of status conditions, please see
|
||||
// https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties.
|
||||
message Condition {
|
||||
// Type of condition in PascalCase.
|
||||
string type = 1;
|
||||
|
||||
// Status of the condition.
|
||||
Status status = 2;
|
||||
|
||||
// Reason contains a programmatic identifier indicating the reason for the
|
||||
// condition's last transition. Producers of specific condition types may
|
||||
// define expected values and meanings for this field, and whether the values
|
||||
// are considered a guaranteed API. The value should be a PascalCase string.
|
||||
// This field may not be empty.
|
||||
string reason = 3;
|
||||
|
||||
// Message is a human readable message indicating details about the
|
||||
// transition. This may be an empty string.
|
||||
optional string message = 4;
|
||||
|
||||
// The resources this condition targets.
|
||||
optional Target target = 5;
|
||||
}
|
||||
|
||||
enum Status {
|
||||
STATUS_CONDITION_UNSPECIFIED = 0;
|
||||
|
||||
STATUS_CONDITION_UNKNOWN = 1;
|
||||
|
||||
STATUS_CONDITION_TRUE = 2;
|
||||
|
||||
STATUS_CONDITION_FALSE = 3;
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -20,6 +20,19 @@ class Severity(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
|
|||
SEVERITY_FATAL: _ClassVar[Severity]
|
||||
SEVERITY_WARNING: _ClassVar[Severity]
|
||||
SEVERITY_NORMAL: _ClassVar[Severity]
|
||||
|
||||
class Target(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
|
||||
__slots__ = ()
|
||||
TARGET_UNSPECIFIED: _ClassVar[Target]
|
||||
TARGET_COMPOSITE: _ClassVar[Target]
|
||||
TARGET_COMPOSITE_AND_CLAIM: _ClassVar[Target]
|
||||
|
||||
class Status(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
|
||||
__slots__ = ()
|
||||
STATUS_CONDITION_UNSPECIFIED: _ClassVar[Status]
|
||||
STATUS_CONDITION_UNKNOWN: _ClassVar[Status]
|
||||
STATUS_CONDITION_TRUE: _ClassVar[Status]
|
||||
STATUS_CONDITION_FALSE: _ClassVar[Status]
|
||||
READY_UNSPECIFIED: Ready
|
||||
READY_TRUE: Ready
|
||||
READY_FALSE: Ready
|
||||
|
@ -27,6 +40,13 @@ SEVERITY_UNSPECIFIED: Severity
|
|||
SEVERITY_FATAL: Severity
|
||||
SEVERITY_WARNING: Severity
|
||||
SEVERITY_NORMAL: Severity
|
||||
TARGET_UNSPECIFIED: Target
|
||||
TARGET_COMPOSITE: Target
|
||||
TARGET_COMPOSITE_AND_CLAIM: Target
|
||||
STATUS_CONDITION_UNSPECIFIED: Status
|
||||
STATUS_CONDITION_UNKNOWN: Status
|
||||
STATUS_CONDITION_TRUE: Status
|
||||
STATUS_CONDITION_FALSE: Status
|
||||
|
||||
class RunFunctionRequest(_message.Message):
|
||||
__slots__ = ("meta", "observed", "desired", "input", "context", "extra_resources", "credentials")
|
||||
|
@ -86,18 +106,20 @@ class Resources(_message.Message):
|
|||
def __init__(self, items: _Optional[_Iterable[_Union[Resource, _Mapping]]] = ...) -> None: ...
|
||||
|
||||
class RunFunctionResponse(_message.Message):
|
||||
__slots__ = ("meta", "desired", "results", "context", "requirements")
|
||||
__slots__ = ("meta", "desired", "results", "context", "requirements", "conditions")
|
||||
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]
|
||||
meta: ResponseMeta
|
||||
desired: State
|
||||
results: _containers.RepeatedCompositeFieldContainer[Result]
|
||||
context: _struct_pb2.Struct
|
||||
requirements: Requirements
|
||||
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]] = ...) -> None: ...
|
||||
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: ...
|
||||
|
||||
class RequestMeta(_message.Message):
|
||||
__slots__ = ("tag",)
|
||||
|
@ -184,9 +206,27 @@ class Resource(_message.Message):
|
|||
def __init__(self, resource: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ..., connection_details: _Optional[_Mapping[str, bytes]] = ..., ready: _Optional[_Union[Ready, str]] = ...) -> None: ...
|
||||
|
||||
class Result(_message.Message):
|
||||
__slots__ = ("severity", "message")
|
||||
__slots__ = ("severity", "message", "reason", "target")
|
||||
SEVERITY_FIELD_NUMBER: _ClassVar[int]
|
||||
MESSAGE_FIELD_NUMBER: _ClassVar[int]
|
||||
REASON_FIELD_NUMBER: _ClassVar[int]
|
||||
TARGET_FIELD_NUMBER: _ClassVar[int]
|
||||
severity: Severity
|
||||
message: str
|
||||
def __init__(self, severity: _Optional[_Union[Severity, str]] = ..., message: _Optional[str] = ...) -> None: ...
|
||||
reason: str
|
||||
target: Target
|
||||
def __init__(self, severity: _Optional[_Union[Severity, str]] = ..., message: _Optional[str] = ..., reason: _Optional[str] = ..., target: _Optional[_Union[Target, str]] = ...) -> None: ...
|
||||
|
||||
class Condition(_message.Message):
|
||||
__slots__ = ("type", "status", "reason", "message", "target")
|
||||
TYPE_FIELD_NUMBER: _ClassVar[int]
|
||||
STATUS_FIELD_NUMBER: _ClassVar[int]
|
||||
REASON_FIELD_NUMBER: _ClassVar[int]
|
||||
MESSAGE_FIELD_NUMBER: _ClassVar[int]
|
||||
TARGET_FIELD_NUMBER: _ClassVar[int]
|
||||
type: str
|
||||
status: Status
|
||||
reason: str
|
||||
message: str
|
||||
target: Target
|
||||
def __init__(self, type: _Optional[str] = ..., status: _Optional[_Union[Status, str]] = ..., reason: _Optional[str] = ..., message: _Optional[str] = ..., target: _Optional[_Union[Target, str]] = ...) -> None: ...
|
||||
|
|
|
@ -1,9 +1,34 @@
|
|||
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
|
||||
"""Client and server classes corresponding to protobuf-defined services."""
|
||||
import grpc
|
||||
import warnings
|
||||
|
||||
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.65.4'
|
||||
GRPC_VERSION = grpc.__version__
|
||||
EXPECTED_ERROR_RELEASE = '1.66.0'
|
||||
SCHEDULED_RELEASE_DATE = 'August 6, 2024'
|
||||
_version_not_supported = False
|
||||
|
||||
try:
|
||||
from grpc._utilities import first_version_is_lower
|
||||
_version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION)
|
||||
except ImportError:
|
||||
_version_not_supported = True
|
||||
|
||||
if _version_not_supported:
|
||||
warnings.warn(
|
||||
f'The grpc package installed is at version {GRPC_VERSION},'
|
||||
+ f' but the generated code in crossplane/function/proto/v1beta1/run_function_pb2_grpc.py depends on'
|
||||
+ f' grpcio>={GRPC_GENERATED_VERSION}.'
|
||||
+ f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}'
|
||||
+ f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.'
|
||||
+ f' This warning will become an error in {EXPECTED_ERROR_RELEASE},'
|
||||
+ f' scheduled for release on {SCHEDULED_RELEASE_DATE}.',
|
||||
RuntimeWarning
|
||||
)
|
||||
|
||||
|
||||
class FunctionRunnerServiceStub(object):
|
||||
"""A FunctionRunnerService is a Composition Function.
|
||||
|
@ -19,7 +44,7 @@ class FunctionRunnerServiceStub(object):
|
|||
'/apiextensions.fn.proto.v1beta1.FunctionRunnerService/RunFunction',
|
||||
request_serializer=crossplane_dot_function_dot_proto_dot_v1beta1_dot_run__function__pb2.RunFunctionRequest.SerializeToString,
|
||||
response_deserializer=crossplane_dot_function_dot_proto_dot_v1beta1_dot_run__function__pb2.RunFunctionResponse.FromString,
|
||||
)
|
||||
_registered_method=True)
|
||||
|
||||
|
||||
class FunctionRunnerServiceServicer(object):
|
||||
|
@ -45,6 +70,7 @@ def add_FunctionRunnerServiceServicer_to_server(servicer, server):
|
|||
generic_handler = grpc.method_handlers_generic_handler(
|
||||
'apiextensions.fn.proto.v1beta1.FunctionRunnerService', rpc_method_handlers)
|
||||
server.add_generic_rpc_handlers((generic_handler,))
|
||||
server.add_registered_method_handlers('apiextensions.fn.proto.v1beta1.FunctionRunnerService', rpc_method_handlers)
|
||||
|
||||
|
||||
# This class is part of an EXPERIMENTAL API.
|
||||
|
@ -63,8 +89,18 @@ class FunctionRunnerService(object):
|
|||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_unary(request, target, '/apiextensions.fn.proto.v1beta1.FunctionRunnerService/RunFunction',
|
||||
return grpc.experimental.unary_unary(
|
||||
request,
|
||||
target,
|
||||
'/apiextensions.fn.proto.v1beta1.FunctionRunnerService/RunFunction',
|
||||
crossplane_dot_function_dot_proto_dot_v1beta1_dot_run__function__pb2.RunFunctionRequest.SerializeToString,
|
||||
crossplane_dot_function_dot_proto_dot_v1beta1_dot_run__function__pb2.RunFunctionResponse.FromString,
|
||||
options, channel_credentials,
|
||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
||||
options,
|
||||
channel_credentials,
|
||||
insecure,
|
||||
call_credentials,
|
||||
compression,
|
||||
wait_for_ready,
|
||||
timeout,
|
||||
metadata,
|
||||
_registered_method=True)
|
||||
|
|
|
@ -18,16 +18,16 @@ import datetime
|
|||
|
||||
from google.protobuf import duration_pb2 as durationpb
|
||||
|
||||
import crossplane.function.proto.v1beta1.run_function_pb2 as fnv1beta1
|
||||
import crossplane.function.proto.v1.run_function_pb2 as fnv1
|
||||
|
||||
"""The default TTL for which a RunFunctionResponse may be cached."""
|
||||
DEFAULT_TTL = datetime.timedelta(minutes=1)
|
||||
|
||||
|
||||
def to(
|
||||
req: fnv1beta1.RunFunctionRequest,
|
||||
req: fnv1.RunFunctionRequest,
|
||||
ttl: datetime.timedelta = DEFAULT_TTL,
|
||||
) -> fnv1beta1.RunFunctionResponse:
|
||||
) -> fnv1.RunFunctionResponse:
|
||||
"""Create a response to the supplied request.
|
||||
|
||||
Args:
|
||||
|
@ -42,38 +42,38 @@ def to(
|
|||
"""
|
||||
dttl = durationpb.Duration()
|
||||
dttl.FromTimedelta(ttl)
|
||||
return fnv1beta1.RunFunctionResponse(
|
||||
meta=fnv1beta1.ResponseMeta(tag=req.meta.tag, ttl=dttl),
|
||||
return fnv1.RunFunctionResponse(
|
||||
meta=fnv1.ResponseMeta(tag=req.meta.tag, ttl=dttl),
|
||||
desired=req.desired,
|
||||
context=req.context,
|
||||
)
|
||||
|
||||
|
||||
def normal(rsp: fnv1beta1.RunFunctionResponse, message: str) -> None:
|
||||
def normal(rsp: fnv1.RunFunctionResponse, message: str) -> None:
|
||||
"""Add a normal result to the response."""
|
||||
rsp.results.append(
|
||||
fnv1beta1.Result(
|
||||
severity=fnv1beta1.SEVERITY_NORMAL,
|
||||
fnv1.Result(
|
||||
severity=fnv1.SEVERITY_NORMAL,
|
||||
message=message,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def warning(rsp: fnv1beta1.RunFunctionResponse, message: str) -> None:
|
||||
def warning(rsp: fnv1.RunFunctionResponse, message: str) -> None:
|
||||
"""Add a warning result to the response."""
|
||||
rsp.results.append(
|
||||
fnv1beta1.Result(
|
||||
severity=fnv1beta1.SEVERITY_WARNING,
|
||||
fnv1.Result(
|
||||
severity=fnv1.SEVERITY_WARNING,
|
||||
message=message,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def fatal(rsp: fnv1beta1.RunFunctionResponse, message: str) -> None:
|
||||
def fatal(rsp: fnv1.RunFunctionResponse, message: str) -> None:
|
||||
"""Add a fatal result to the response."""
|
||||
rsp.results.append(
|
||||
fnv1beta1.Result(
|
||||
severity=fnv1beta1.SEVERITY_FATAL,
|
||||
fnv1.Result(
|
||||
severity=fnv1.SEVERITY_FATAL,
|
||||
message=message,
|
||||
)
|
||||
)
|
||||
|
|
|
@ -20,11 +20,14 @@ import os
|
|||
import grpc
|
||||
from grpc_reflection.v1alpha import reflection
|
||||
|
||||
import crossplane.function.proto.v1.run_function_pb2 as fnv1
|
||||
import crossplane.function.proto.v1.run_function_pb2_grpc as grpcv1
|
||||
import crossplane.function.proto.v1beta1.run_function_pb2 as fnv1beta1
|
||||
import crossplane.function.proto.v1beta1.run_function_pb2_grpc as grpcv1beta1
|
||||
|
||||
SERVICE_NAMES = (
|
||||
reflection.SERVICE_NAME,
|
||||
fnv1.DESCRIPTOR.services_by_name["FunctionRunnerService"].full_name,
|
||||
fnv1beta1.DESCRIPTOR.services_by_name["FunctionRunnerService"].full_name,
|
||||
)
|
||||
|
||||
|
@ -62,7 +65,7 @@ def load_credentials(tls_certs_dir: str) -> grpc.ServerCredentials:
|
|||
|
||||
|
||||
def serve(
|
||||
function: grpcv1beta1.FunctionRunnerService,
|
||||
function: grpcv1.FunctionRunnerService,
|
||||
address: str,
|
||||
*,
|
||||
creds: grpc.ServerCredentials,
|
||||
|
@ -87,7 +90,10 @@ def serve(
|
|||
|
||||
server = grpc.aio.server()
|
||||
|
||||
grpcv1beta1.add_FunctionRunnerServiceServicer_to_server(function, server)
|
||||
grpcv1.add_FunctionRunnerServiceServicer_to_server(function, server)
|
||||
grpcv1beta1.add_FunctionRunnerServiceServicer_to_server(
|
||||
BetaFunctionRunner(wrapped=function), server
|
||||
)
|
||||
reflection.enable_server_reflection(SERVICE_NAMES, server)
|
||||
|
||||
if creds is None and insecure is False:
|
||||
|
@ -112,3 +118,30 @@ def serve(
|
|||
finally:
|
||||
loop.run_until_complete(server.stop(grace=5))
|
||||
loop.close()
|
||||
|
||||
|
||||
class BetaFunctionRunner(grpcv1beta1.FunctionRunnerService):
|
||||
"""A BetaFunctionRunner handles beta gRPC RunFunctionRequests.
|
||||
|
||||
It handles requests by passing them to a wrapped v1.FunctionRunnerService.
|
||||
Incoming v1beta1 requests are converted to v1 by round-tripping them through
|
||||
serialization. Outgoing requests are converted from v1 to v1beta1 the same
|
||||
way.
|
||||
"""
|
||||
|
||||
def __init__(self, wrapped: grpcv1.FunctionRunnerService):
|
||||
"""Create a new BetaFunctionRunner."""
|
||||
self.wrapped = wrapped
|
||||
|
||||
async def RunFunction( # noqa: N802 # gRPC requires this name.
|
||||
self, req: fnv1beta1.RunFunctionRequest, context: grpc.aio.ServicerContext
|
||||
) -> fnv1beta1.RunFunctionResponse:
|
||||
"""Run the underlying function."""
|
||||
gareq = fnv1.RunFunctionRequest()
|
||||
gareq.ParseFromString(req.SerializeToString())
|
||||
|
||||
garsp = await self.wrapped.RunFunction(gareq, context)
|
||||
rsp = fnv1beta1.RunFunctionRequest()
|
||||
rsp.ParseFromString(garsp.SerializeToString())
|
||||
|
||||
return rsp
|
||||
|
|
|
@ -41,7 +41,7 @@ path = ".venv-generate"
|
|||
dependencies = ["grpcio-tools==1.65.4"]
|
||||
|
||||
[tool.hatch.envs.generate.scripts]
|
||||
protoc = "python -m grpc_tools.protoc --proto_path=. --python_out=. --pyi_out=. --grpc_python_out=. crossplane/function/proto/v1beta1/run_function.proto"
|
||||
protoc = "python -m grpc_tools.protoc --proto_path=. --python_out=. --pyi_out=. --grpc_python_out=. crossplane/function/proto/v1beta1/run_function.proto crossplane/function/proto/v1/run_function.proto"
|
||||
|
||||
[tool.hatch.envs.lint]
|
||||
type = "virtual"
|
||||
|
@ -50,7 +50,8 @@ path = ".venv-lint"
|
|||
dependencies = ["ruff==0.6.1"]
|
||||
|
||||
[tool.hatch.envs.lint.scripts]
|
||||
check = "ruff check crossplane tests && ruff format --diff crossplane tests"
|
||||
check = "ruff format crossplane tests && ruff check --fix crossplane tests"
|
||||
|
||||
|
||||
[tool.hatch.envs.test]
|
||||
type = "virtual"
|
||||
|
|
|
@ -20,7 +20,7 @@ from google.protobuf import duration_pb2 as durationpb
|
|||
from google.protobuf import json_format
|
||||
|
||||
from crossplane.function import logging, resource, response
|
||||
from crossplane.function.proto.v1beta1 import run_function_pb2 as fnv1beta1
|
||||
from crossplane.function.proto.v1 import run_function_pb2 as fnv1
|
||||
|
||||
|
||||
class TestResponse(unittest.TestCase):
|
||||
|
@ -31,30 +31,30 @@ class TestResponse(unittest.TestCase):
|
|||
@dataclasses.dataclass
|
||||
class TestCase:
|
||||
reason: str
|
||||
req: fnv1beta1.RunFunctionRequest
|
||||
req: fnv1.RunFunctionRequest
|
||||
ttl: datetime.timedelta
|
||||
want: fnv1beta1.RunFunctionResponse
|
||||
want: fnv1.RunFunctionResponse
|
||||
|
||||
cases = [
|
||||
TestCase(
|
||||
reason="Tag, desired, and context should be copied.",
|
||||
req=fnv1beta1.RunFunctionRequest(
|
||||
meta=fnv1beta1.RequestMeta(tag="hi"),
|
||||
desired=fnv1beta1.State(
|
||||
req=fnv1.RunFunctionRequest(
|
||||
meta=fnv1.RequestMeta(tag="hi"),
|
||||
desired=fnv1.State(
|
||||
resources={
|
||||
"ready-composed-resource": fnv1beta1.Resource(),
|
||||
"ready-composed-resource": fnv1.Resource(),
|
||||
}
|
||||
),
|
||||
context=resource.dict_to_struct({"cool-key": "cool-value"}),
|
||||
),
|
||||
ttl=datetime.timedelta(minutes=10),
|
||||
want=fnv1beta1.RunFunctionResponse(
|
||||
meta=fnv1beta1.ResponseMeta(
|
||||
want=fnv1.RunFunctionResponse(
|
||||
meta=fnv1.ResponseMeta(
|
||||
tag="hi", ttl=durationpb.Duration(seconds=60 * 10)
|
||||
),
|
||||
desired=fnv1beta1.State(
|
||||
desired=fnv1.State(
|
||||
resources={
|
||||
"ready-composed-resource": fnv1beta1.Resource(),
|
||||
"ready-composed-resource": fnv1.Resource(),
|
||||
}
|
||||
),
|
||||
context=resource.dict_to_struct({"cool-key": "cool-value"}),
|
||||
|
|
Loading…
Reference in New Issue