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/struct.proto";
|
||||||
import "google/protobuf/duration.proto";
|
import "google/protobuf/duration.proto";
|
||||||
|
|
||||||
// Note that the authoritative Composition Functions protobuf definition lives
|
// Generated from apiextensions/fn/proto/v1/run_function.proto by ../hack/duplicate_proto_type.sh. DO NOT EDIT.
|
||||||
// at the below URL. Each SDK maintains and manually syncs its own copy.
|
|
||||||
// https://github.com/crossplane/crossplane/tree/master/apis/apiextensions/fn/proto
|
|
||||||
package apiextensions.fn.proto.v1beta1;
|
package apiextensions.fn.proto.v1beta1;
|
||||||
|
|
||||||
|
option go_package = "github.com/crossplane/crossplane/apis/apiextensions/fn/proto/v1beta1";
|
||||||
|
|
||||||
// A FunctionRunnerService is a Composition Function.
|
// A FunctionRunnerService is a Composition Function.
|
||||||
service FunctionRunnerService {
|
service FunctionRunnerService {
|
||||||
// RunFunction runs the Composition Function.
|
// RunFunction runs the Composition Function.
|
||||||
|
@ -122,6 +123,10 @@ message RunFunctionResponse {
|
||||||
|
|
||||||
// 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;
|
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.
|
// 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.
|
// ResourceSelector selects a group of resources, either by name or by label.
|
||||||
message ResourceSelector {
|
message ResourceSelector {
|
||||||
|
// API version of resources to select.
|
||||||
string api_version = 1;
|
string api_version = 1;
|
||||||
|
|
||||||
|
// Kind of resources to select.
|
||||||
string kind = 2;
|
string kind = 2;
|
||||||
|
|
||||||
|
// Resources to match.
|
||||||
oneof match {
|
oneof match {
|
||||||
|
// Match the resource with this name.
|
||||||
string match_name = 3;
|
string match_name = 3;
|
||||||
|
|
||||||
|
// Match all resources with these labels.
|
||||||
MatchLabels match_labels = 4;
|
MatchLabels match_labels = 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -237,6 +249,13 @@ message Result {
|
||||||
|
|
||||||
// Human-readable details about the result.
|
// Human-readable details about the result.
|
||||||
string message = 2;
|
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.
|
// Severity of Function results.
|
||||||
|
@ -257,3 +276,53 @@ enum Severity {
|
||||||
// with the composite resource.
|
// with the composite resource.
|
||||||
SEVERITY_NORMAL = 3;
|
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_FATAL: _ClassVar[Severity]
|
||||||
SEVERITY_WARNING: _ClassVar[Severity]
|
SEVERITY_WARNING: _ClassVar[Severity]
|
||||||
SEVERITY_NORMAL: _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_UNSPECIFIED: Ready
|
||||||
READY_TRUE: Ready
|
READY_TRUE: Ready
|
||||||
READY_FALSE: Ready
|
READY_FALSE: Ready
|
||||||
|
@ -27,6 +40,13 @@ SEVERITY_UNSPECIFIED: Severity
|
||||||
SEVERITY_FATAL: Severity
|
SEVERITY_FATAL: Severity
|
||||||
SEVERITY_WARNING: Severity
|
SEVERITY_WARNING: Severity
|
||||||
SEVERITY_NORMAL: 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):
|
class RunFunctionRequest(_message.Message):
|
||||||
__slots__ = ("meta", "observed", "desired", "input", "context", "extra_resources", "credentials")
|
__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: ...
|
def __init__(self, items: _Optional[_Iterable[_Union[Resource, _Mapping]]] = ...) -> None: ...
|
||||||
|
|
||||||
class RunFunctionResponse(_message.Message):
|
class RunFunctionResponse(_message.Message):
|
||||||
__slots__ = ("meta", "desired", "results", "context", "requirements")
|
__slots__ = ("meta", "desired", "results", "context", "requirements", "conditions")
|
||||||
META_FIELD_NUMBER: _ClassVar[int]
|
META_FIELD_NUMBER: _ClassVar[int]
|
||||||
DESIRED_FIELD_NUMBER: _ClassVar[int]
|
DESIRED_FIELD_NUMBER: _ClassVar[int]
|
||||||
RESULTS_FIELD_NUMBER: _ClassVar[int]
|
RESULTS_FIELD_NUMBER: _ClassVar[int]
|
||||||
CONTEXT_FIELD_NUMBER: _ClassVar[int]
|
CONTEXT_FIELD_NUMBER: _ClassVar[int]
|
||||||
REQUIREMENTS_FIELD_NUMBER: _ClassVar[int]
|
REQUIREMENTS_FIELD_NUMBER: _ClassVar[int]
|
||||||
|
CONDITIONS_FIELD_NUMBER: _ClassVar[int]
|
||||||
meta: ResponseMeta
|
meta: ResponseMeta
|
||||||
desired: State
|
desired: State
|
||||||
results: _containers.RepeatedCompositeFieldContainer[Result]
|
results: _containers.RepeatedCompositeFieldContainer[Result]
|
||||||
context: _struct_pb2.Struct
|
context: _struct_pb2.Struct
|
||||||
requirements: Requirements
|
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):
|
class RequestMeta(_message.Message):
|
||||||
__slots__ = ("tag",)
|
__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: ...
|
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):
|
class Result(_message.Message):
|
||||||
__slots__ = ("severity", "message")
|
__slots__ = ("severity", "message", "reason", "target")
|
||||||
SEVERITY_FIELD_NUMBER: _ClassVar[int]
|
SEVERITY_FIELD_NUMBER: _ClassVar[int]
|
||||||
MESSAGE_FIELD_NUMBER: _ClassVar[int]
|
MESSAGE_FIELD_NUMBER: _ClassVar[int]
|
||||||
|
REASON_FIELD_NUMBER: _ClassVar[int]
|
||||||
|
TARGET_FIELD_NUMBER: _ClassVar[int]
|
||||||
severity: Severity
|
severity: Severity
|
||||||
message: str
|
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!
|
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
|
||||||
"""Client and server classes corresponding to protobuf-defined services."""
|
"""Client and server classes corresponding to protobuf-defined services."""
|
||||||
import grpc
|
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
|
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):
|
class FunctionRunnerServiceStub(object):
|
||||||
"""A FunctionRunnerService is a Composition Function.
|
"""A FunctionRunnerService is a Composition Function.
|
||||||
|
@ -19,7 +44,7 @@ class FunctionRunnerServiceStub(object):
|
||||||
'/apiextensions.fn.proto.v1beta1.FunctionRunnerService/RunFunction',
|
'/apiextensions.fn.proto.v1beta1.FunctionRunnerService/RunFunction',
|
||||||
request_serializer=crossplane_dot_function_dot_proto_dot_v1beta1_dot_run__function__pb2.RunFunctionRequest.SerializeToString,
|
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,
|
response_deserializer=crossplane_dot_function_dot_proto_dot_v1beta1_dot_run__function__pb2.RunFunctionResponse.FromString,
|
||||||
)
|
_registered_method=True)
|
||||||
|
|
||||||
|
|
||||||
class FunctionRunnerServiceServicer(object):
|
class FunctionRunnerServiceServicer(object):
|
||||||
|
@ -45,6 +70,7 @@ def add_FunctionRunnerServiceServicer_to_server(servicer, server):
|
||||||
generic_handler = grpc.method_handlers_generic_handler(
|
generic_handler = grpc.method_handlers_generic_handler(
|
||||||
'apiextensions.fn.proto.v1beta1.FunctionRunnerService', rpc_method_handlers)
|
'apiextensions.fn.proto.v1beta1.FunctionRunnerService', rpc_method_handlers)
|
||||||
server.add_generic_rpc_handlers((generic_handler,))
|
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.
|
# This class is part of an EXPERIMENTAL API.
|
||||||
|
@ -63,8 +89,18 @@ class FunctionRunnerService(object):
|
||||||
wait_for_ready=None,
|
wait_for_ready=None,
|
||||||
timeout=None,
|
timeout=None,
|
||||||
metadata=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.RunFunctionRequest.SerializeToString,
|
||||||
crossplane_dot_function_dot_proto_dot_v1beta1_dot_run__function__pb2.RunFunctionResponse.FromString,
|
crossplane_dot_function_dot_proto_dot_v1beta1_dot_run__function__pb2.RunFunctionResponse.FromString,
|
||||||
options, channel_credentials,
|
options,
|
||||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
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
|
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."""
|
"""The default TTL for which a RunFunctionResponse may be cached."""
|
||||||
DEFAULT_TTL = datetime.timedelta(minutes=1)
|
DEFAULT_TTL = datetime.timedelta(minutes=1)
|
||||||
|
|
||||||
|
|
||||||
def to(
|
def to(
|
||||||
req: fnv1beta1.RunFunctionRequest,
|
req: fnv1.RunFunctionRequest,
|
||||||
ttl: datetime.timedelta = DEFAULT_TTL,
|
ttl: datetime.timedelta = DEFAULT_TTL,
|
||||||
) -> fnv1beta1.RunFunctionResponse:
|
) -> fnv1.RunFunctionResponse:
|
||||||
"""Create a response to the supplied request.
|
"""Create a response to the supplied request.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
@ -42,38 +42,38 @@ def to(
|
||||||
"""
|
"""
|
||||||
dttl = durationpb.Duration()
|
dttl = durationpb.Duration()
|
||||||
dttl.FromTimedelta(ttl)
|
dttl.FromTimedelta(ttl)
|
||||||
return fnv1beta1.RunFunctionResponse(
|
return fnv1.RunFunctionResponse(
|
||||||
meta=fnv1beta1.ResponseMeta(tag=req.meta.tag, ttl=dttl),
|
meta=fnv1.ResponseMeta(tag=req.meta.tag, ttl=dttl),
|
||||||
desired=req.desired,
|
desired=req.desired,
|
||||||
context=req.context,
|
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."""
|
"""Add a normal result to the response."""
|
||||||
rsp.results.append(
|
rsp.results.append(
|
||||||
fnv1beta1.Result(
|
fnv1.Result(
|
||||||
severity=fnv1beta1.SEVERITY_NORMAL,
|
severity=fnv1.SEVERITY_NORMAL,
|
||||||
message=message,
|
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."""
|
"""Add a warning result to the response."""
|
||||||
rsp.results.append(
|
rsp.results.append(
|
||||||
fnv1beta1.Result(
|
fnv1.Result(
|
||||||
severity=fnv1beta1.SEVERITY_WARNING,
|
severity=fnv1.SEVERITY_WARNING,
|
||||||
message=message,
|
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."""
|
"""Add a fatal result to the response."""
|
||||||
rsp.results.append(
|
rsp.results.append(
|
||||||
fnv1beta1.Result(
|
fnv1.Result(
|
||||||
severity=fnv1beta1.SEVERITY_FATAL,
|
severity=fnv1.SEVERITY_FATAL,
|
||||||
message=message,
|
message=message,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -20,11 +20,14 @@ import os
|
||||||
import grpc
|
import grpc
|
||||||
from grpc_reflection.v1alpha import reflection
|
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 as fnv1beta1
|
||||||
import crossplane.function.proto.v1beta1.run_function_pb2_grpc as grpcv1beta1
|
import crossplane.function.proto.v1beta1.run_function_pb2_grpc as grpcv1beta1
|
||||||
|
|
||||||
SERVICE_NAMES = (
|
SERVICE_NAMES = (
|
||||||
reflection.SERVICE_NAME,
|
reflection.SERVICE_NAME,
|
||||||
|
fnv1.DESCRIPTOR.services_by_name["FunctionRunnerService"].full_name,
|
||||||
fnv1beta1.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(
|
def serve(
|
||||||
function: grpcv1beta1.FunctionRunnerService,
|
function: grpcv1.FunctionRunnerService,
|
||||||
address: str,
|
address: str,
|
||||||
*,
|
*,
|
||||||
creds: grpc.ServerCredentials,
|
creds: grpc.ServerCredentials,
|
||||||
|
@ -87,7 +90,10 @@ def serve(
|
||||||
|
|
||||||
server = grpc.aio.server()
|
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)
|
reflection.enable_server_reflection(SERVICE_NAMES, server)
|
||||||
|
|
||||||
if creds is None and insecure is False:
|
if creds is None and insecure is False:
|
||||||
|
@ -112,3 +118,30 @@ def serve(
|
||||||
finally:
|
finally:
|
||||||
loop.run_until_complete(server.stop(grace=5))
|
loop.run_until_complete(server.stop(grace=5))
|
||||||
loop.close()
|
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"]
|
dependencies = ["grpcio-tools==1.65.4"]
|
||||||
|
|
||||||
[tool.hatch.envs.generate.scripts]
|
[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]
|
[tool.hatch.envs.lint]
|
||||||
type = "virtual"
|
type = "virtual"
|
||||||
|
@ -50,7 +50,8 @@ path = ".venv-lint"
|
||||||
dependencies = ["ruff==0.6.1"]
|
dependencies = ["ruff==0.6.1"]
|
||||||
|
|
||||||
[tool.hatch.envs.lint.scripts]
|
[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]
|
[tool.hatch.envs.test]
|
||||||
type = "virtual"
|
type = "virtual"
|
||||||
|
|
|
@ -20,7 +20,7 @@ from google.protobuf import duration_pb2 as durationpb
|
||||||
from google.protobuf import json_format
|
from google.protobuf import json_format
|
||||||
|
|
||||||
from crossplane.function import logging, resource, response
|
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):
|
class TestResponse(unittest.TestCase):
|
||||||
|
@ -31,30 +31,30 @@ class TestResponse(unittest.TestCase):
|
||||||
@dataclasses.dataclass
|
@dataclasses.dataclass
|
||||||
class TestCase:
|
class TestCase:
|
||||||
reason: str
|
reason: str
|
||||||
req: fnv1beta1.RunFunctionRequest
|
req: fnv1.RunFunctionRequest
|
||||||
ttl: datetime.timedelta
|
ttl: datetime.timedelta
|
||||||
want: fnv1beta1.RunFunctionResponse
|
want: fnv1.RunFunctionResponse
|
||||||
|
|
||||||
cases = [
|
cases = [
|
||||||
TestCase(
|
TestCase(
|
||||||
reason="Tag, desired, and context should be copied.",
|
reason="Tag, desired, and context should be copied.",
|
||||||
req=fnv1beta1.RunFunctionRequest(
|
req=fnv1.RunFunctionRequest(
|
||||||
meta=fnv1beta1.RequestMeta(tag="hi"),
|
meta=fnv1.RequestMeta(tag="hi"),
|
||||||
desired=fnv1beta1.State(
|
desired=fnv1.State(
|
||||||
resources={
|
resources={
|
||||||
"ready-composed-resource": fnv1beta1.Resource(),
|
"ready-composed-resource": fnv1.Resource(),
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
context=resource.dict_to_struct({"cool-key": "cool-value"}),
|
context=resource.dict_to_struct({"cool-key": "cool-value"}),
|
||||||
),
|
),
|
||||||
ttl=datetime.timedelta(minutes=10),
|
ttl=datetime.timedelta(minutes=10),
|
||||||
want=fnv1beta1.RunFunctionResponse(
|
want=fnv1.RunFunctionResponse(
|
||||||
meta=fnv1beta1.ResponseMeta(
|
meta=fnv1.ResponseMeta(
|
||||||
tag="hi", ttl=durationpb.Duration(seconds=60 * 10)
|
tag="hi", ttl=durationpb.Duration(seconds=60 * 10)
|
||||||
),
|
),
|
||||||
desired=fnv1beta1.State(
|
desired=fnv1.State(
|
||||||
resources={
|
resources={
|
||||||
"ready-composed-resource": fnv1beta1.Resource(),
|
"ready-composed-resource": fnv1.Resource(),
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
context=resource.dict_to_struct({"cool-key": "cool-value"}),
|
context=resource.dict_to_struct({"cool-key": "cool-value"}),
|
||||||
|
|
Loading…
Reference in New Issue