crossplane-function-pythonic 0.5.0__py3-none-any.whl → 0.6.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,306 @@
1
+ import datetime
2
+
3
+ from google.protobuf import duration_pb2 as _duration_pb2
4
+ from google.protobuf import struct_pb2 as _struct_pb2
5
+ from google.protobuf.internal import containers as _containers
6
+ from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper
7
+ from google.protobuf import descriptor as _descriptor
8
+ from google.protobuf import message as _message
9
+ from collections.abc import Iterable as _Iterable, Mapping as _Mapping
10
+ from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union
11
+
12
+ DESCRIPTOR: _descriptor.FileDescriptor
13
+
14
+ class Capability(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
15
+ __slots__ = ()
16
+ CAPABILITY_UNSPECIFIED: _ClassVar[Capability]
17
+ CAPABILITY_CAPABILITIES: _ClassVar[Capability]
18
+ CAPABILITY_REQUIRED_RESOURCES: _ClassVar[Capability]
19
+ CAPABILITY_CREDENTIALS: _ClassVar[Capability]
20
+ CAPABILITY_CONDITIONS: _ClassVar[Capability]
21
+ CAPABILITY_REQUIRED_SCHEMAS: _ClassVar[Capability]
22
+
23
+ class Ready(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
24
+ __slots__ = ()
25
+ READY_UNSPECIFIED: _ClassVar[Ready]
26
+ READY_TRUE: _ClassVar[Ready]
27
+ READY_FALSE: _ClassVar[Ready]
28
+
29
+ class Severity(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
30
+ __slots__ = ()
31
+ SEVERITY_UNSPECIFIED: _ClassVar[Severity]
32
+ SEVERITY_FATAL: _ClassVar[Severity]
33
+ SEVERITY_WARNING: _ClassVar[Severity]
34
+ SEVERITY_NORMAL: _ClassVar[Severity]
35
+
36
+ class Target(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
37
+ __slots__ = ()
38
+ TARGET_UNSPECIFIED: _ClassVar[Target]
39
+ TARGET_COMPOSITE: _ClassVar[Target]
40
+ TARGET_COMPOSITE_AND_CLAIM: _ClassVar[Target]
41
+
42
+ class Status(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
43
+ __slots__ = ()
44
+ STATUS_CONDITION_UNSPECIFIED: _ClassVar[Status]
45
+ STATUS_CONDITION_UNKNOWN: _ClassVar[Status]
46
+ STATUS_CONDITION_TRUE: _ClassVar[Status]
47
+ STATUS_CONDITION_FALSE: _ClassVar[Status]
48
+ CAPABILITY_UNSPECIFIED: Capability
49
+ CAPABILITY_CAPABILITIES: Capability
50
+ CAPABILITY_REQUIRED_RESOURCES: Capability
51
+ CAPABILITY_CREDENTIALS: Capability
52
+ CAPABILITY_CONDITIONS: Capability
53
+ CAPABILITY_REQUIRED_SCHEMAS: Capability
54
+ READY_UNSPECIFIED: Ready
55
+ READY_TRUE: Ready
56
+ READY_FALSE: Ready
57
+ SEVERITY_UNSPECIFIED: Severity
58
+ SEVERITY_FATAL: Severity
59
+ SEVERITY_WARNING: Severity
60
+ SEVERITY_NORMAL: Severity
61
+ TARGET_UNSPECIFIED: Target
62
+ TARGET_COMPOSITE: Target
63
+ TARGET_COMPOSITE_AND_CLAIM: Target
64
+ STATUS_CONDITION_UNSPECIFIED: Status
65
+ STATUS_CONDITION_UNKNOWN: Status
66
+ STATUS_CONDITION_TRUE: Status
67
+ STATUS_CONDITION_FALSE: Status
68
+
69
+ class RunFunctionRequest(_message.Message):
70
+ __slots__ = ("meta", "observed", "desired", "input", "context", "extra_resources", "credentials", "required_resources", "required_schemas")
71
+ class ExtraResourcesEntry(_message.Message):
72
+ __slots__ = ("key", "value")
73
+ KEY_FIELD_NUMBER: _ClassVar[int]
74
+ VALUE_FIELD_NUMBER: _ClassVar[int]
75
+ key: str
76
+ value: Resources
77
+ def __init__(self, key: _Optional[str] = ..., value: _Optional[_Union[Resources, _Mapping]] = ...) -> None: ...
78
+ class CredentialsEntry(_message.Message):
79
+ __slots__ = ("key", "value")
80
+ KEY_FIELD_NUMBER: _ClassVar[int]
81
+ VALUE_FIELD_NUMBER: _ClassVar[int]
82
+ key: str
83
+ value: Credentials
84
+ def __init__(self, key: _Optional[str] = ..., value: _Optional[_Union[Credentials, _Mapping]] = ...) -> None: ...
85
+ class RequiredResourcesEntry(_message.Message):
86
+ __slots__ = ("key", "value")
87
+ KEY_FIELD_NUMBER: _ClassVar[int]
88
+ VALUE_FIELD_NUMBER: _ClassVar[int]
89
+ key: str
90
+ value: Resources
91
+ def __init__(self, key: _Optional[str] = ..., value: _Optional[_Union[Resources, _Mapping]] = ...) -> None: ...
92
+ class RequiredSchemasEntry(_message.Message):
93
+ __slots__ = ("key", "value")
94
+ KEY_FIELD_NUMBER: _ClassVar[int]
95
+ VALUE_FIELD_NUMBER: _ClassVar[int]
96
+ key: str
97
+ value: Schema
98
+ def __init__(self, key: _Optional[str] = ..., value: _Optional[_Union[Schema, _Mapping]] = ...) -> None: ...
99
+ META_FIELD_NUMBER: _ClassVar[int]
100
+ OBSERVED_FIELD_NUMBER: _ClassVar[int]
101
+ DESIRED_FIELD_NUMBER: _ClassVar[int]
102
+ INPUT_FIELD_NUMBER: _ClassVar[int]
103
+ CONTEXT_FIELD_NUMBER: _ClassVar[int]
104
+ EXTRA_RESOURCES_FIELD_NUMBER: _ClassVar[int]
105
+ CREDENTIALS_FIELD_NUMBER: _ClassVar[int]
106
+ REQUIRED_RESOURCES_FIELD_NUMBER: _ClassVar[int]
107
+ REQUIRED_SCHEMAS_FIELD_NUMBER: _ClassVar[int]
108
+ meta: RequestMeta
109
+ observed: State
110
+ desired: State
111
+ input: _struct_pb2.Struct
112
+ context: _struct_pb2.Struct
113
+ extra_resources: _containers.MessageMap[str, Resources]
114
+ credentials: _containers.MessageMap[str, Credentials]
115
+ required_resources: _containers.MessageMap[str, Resources]
116
+ required_schemas: _containers.MessageMap[str, Schema]
117
+ def __init__(self, meta: _Optional[_Union[RequestMeta, _Mapping]] = ..., observed: _Optional[_Union[State, _Mapping]] = ..., desired: _Optional[_Union[State, _Mapping]] = ..., input: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ..., context: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ..., extra_resources: _Optional[_Mapping[str, Resources]] = ..., credentials: _Optional[_Mapping[str, Credentials]] = ..., required_resources: _Optional[_Mapping[str, Resources]] = ..., required_schemas: _Optional[_Mapping[str, Schema]] = ...) -> None: ...
118
+
119
+ class Credentials(_message.Message):
120
+ __slots__ = ("credential_data",)
121
+ CREDENTIAL_DATA_FIELD_NUMBER: _ClassVar[int]
122
+ credential_data: CredentialData
123
+ def __init__(self, credential_data: _Optional[_Union[CredentialData, _Mapping]] = ...) -> None: ...
124
+
125
+ class CredentialData(_message.Message):
126
+ __slots__ = ("data",)
127
+ class DataEntry(_message.Message):
128
+ __slots__ = ("key", "value")
129
+ KEY_FIELD_NUMBER: _ClassVar[int]
130
+ VALUE_FIELD_NUMBER: _ClassVar[int]
131
+ key: str
132
+ value: bytes
133
+ def __init__(self, key: _Optional[str] = ..., value: _Optional[bytes] = ...) -> None: ...
134
+ DATA_FIELD_NUMBER: _ClassVar[int]
135
+ data: _containers.ScalarMap[str, bytes]
136
+ def __init__(self, data: _Optional[_Mapping[str, bytes]] = ...) -> None: ...
137
+
138
+ class Resources(_message.Message):
139
+ __slots__ = ("items",)
140
+ ITEMS_FIELD_NUMBER: _ClassVar[int]
141
+ items: _containers.RepeatedCompositeFieldContainer[Resource]
142
+ def __init__(self, items: _Optional[_Iterable[_Union[Resource, _Mapping]]] = ...) -> None: ...
143
+
144
+ class RunFunctionResponse(_message.Message):
145
+ __slots__ = ("meta", "desired", "results", "context", "requirements", "conditions", "output")
146
+ META_FIELD_NUMBER: _ClassVar[int]
147
+ DESIRED_FIELD_NUMBER: _ClassVar[int]
148
+ RESULTS_FIELD_NUMBER: _ClassVar[int]
149
+ CONTEXT_FIELD_NUMBER: _ClassVar[int]
150
+ REQUIREMENTS_FIELD_NUMBER: _ClassVar[int]
151
+ CONDITIONS_FIELD_NUMBER: _ClassVar[int]
152
+ OUTPUT_FIELD_NUMBER: _ClassVar[int]
153
+ meta: ResponseMeta
154
+ desired: State
155
+ results: _containers.RepeatedCompositeFieldContainer[Result]
156
+ context: _struct_pb2.Struct
157
+ requirements: Requirements
158
+ conditions: _containers.RepeatedCompositeFieldContainer[Condition]
159
+ output: _struct_pb2.Struct
160
+ def __init__(self, meta: _Optional[_Union[ResponseMeta, _Mapping]] = ..., desired: _Optional[_Union[State, _Mapping]] = ..., results: _Optional[_Iterable[_Union[Result, _Mapping]]] = ..., context: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ..., requirements: _Optional[_Union[Requirements, _Mapping]] = ..., conditions: _Optional[_Iterable[_Union[Condition, _Mapping]]] = ..., output: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ...) -> None: ...
161
+
162
+ class RequestMeta(_message.Message):
163
+ __slots__ = ("tag", "capabilities")
164
+ TAG_FIELD_NUMBER: _ClassVar[int]
165
+ CAPABILITIES_FIELD_NUMBER: _ClassVar[int]
166
+ tag: str
167
+ capabilities: _containers.RepeatedScalarFieldContainer[Capability]
168
+ def __init__(self, tag: _Optional[str] = ..., capabilities: _Optional[_Iterable[_Union[Capability, str]]] = ...) -> None: ...
169
+
170
+ class Requirements(_message.Message):
171
+ __slots__ = ("extra_resources", "resources", "schemas")
172
+ class ExtraResourcesEntry(_message.Message):
173
+ __slots__ = ("key", "value")
174
+ KEY_FIELD_NUMBER: _ClassVar[int]
175
+ VALUE_FIELD_NUMBER: _ClassVar[int]
176
+ key: str
177
+ value: ResourceSelector
178
+ def __init__(self, key: _Optional[str] = ..., value: _Optional[_Union[ResourceSelector, _Mapping]] = ...) -> None: ...
179
+ class ResourcesEntry(_message.Message):
180
+ __slots__ = ("key", "value")
181
+ KEY_FIELD_NUMBER: _ClassVar[int]
182
+ VALUE_FIELD_NUMBER: _ClassVar[int]
183
+ key: str
184
+ value: ResourceSelector
185
+ def __init__(self, key: _Optional[str] = ..., value: _Optional[_Union[ResourceSelector, _Mapping]] = ...) -> None: ...
186
+ class SchemasEntry(_message.Message):
187
+ __slots__ = ("key", "value")
188
+ KEY_FIELD_NUMBER: _ClassVar[int]
189
+ VALUE_FIELD_NUMBER: _ClassVar[int]
190
+ key: str
191
+ value: SchemaSelector
192
+ def __init__(self, key: _Optional[str] = ..., value: _Optional[_Union[SchemaSelector, _Mapping]] = ...) -> None: ...
193
+ EXTRA_RESOURCES_FIELD_NUMBER: _ClassVar[int]
194
+ RESOURCES_FIELD_NUMBER: _ClassVar[int]
195
+ SCHEMAS_FIELD_NUMBER: _ClassVar[int]
196
+ extra_resources: _containers.MessageMap[str, ResourceSelector]
197
+ resources: _containers.MessageMap[str, ResourceSelector]
198
+ schemas: _containers.MessageMap[str, SchemaSelector]
199
+ def __init__(self, extra_resources: _Optional[_Mapping[str, ResourceSelector]] = ..., resources: _Optional[_Mapping[str, ResourceSelector]] = ..., schemas: _Optional[_Mapping[str, SchemaSelector]] = ...) -> None: ...
200
+
201
+ class SchemaSelector(_message.Message):
202
+ __slots__ = ("api_version", "kind")
203
+ API_VERSION_FIELD_NUMBER: _ClassVar[int]
204
+ KIND_FIELD_NUMBER: _ClassVar[int]
205
+ api_version: str
206
+ kind: str
207
+ def __init__(self, api_version: _Optional[str] = ..., kind: _Optional[str] = ...) -> None: ...
208
+
209
+ class Schema(_message.Message):
210
+ __slots__ = ("openapi_v3",)
211
+ OPENAPI_V3_FIELD_NUMBER: _ClassVar[int]
212
+ openapi_v3: _struct_pb2.Struct
213
+ def __init__(self, openapi_v3: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ...) -> None: ...
214
+
215
+ class ResourceSelector(_message.Message):
216
+ __slots__ = ("api_version", "kind", "match_name", "match_labels", "namespace")
217
+ API_VERSION_FIELD_NUMBER: _ClassVar[int]
218
+ KIND_FIELD_NUMBER: _ClassVar[int]
219
+ MATCH_NAME_FIELD_NUMBER: _ClassVar[int]
220
+ MATCH_LABELS_FIELD_NUMBER: _ClassVar[int]
221
+ NAMESPACE_FIELD_NUMBER: _ClassVar[int]
222
+ api_version: str
223
+ kind: str
224
+ match_name: str
225
+ match_labels: MatchLabels
226
+ namespace: str
227
+ def __init__(self, api_version: _Optional[str] = ..., kind: _Optional[str] = ..., match_name: _Optional[str] = ..., match_labels: _Optional[_Union[MatchLabels, _Mapping]] = ..., namespace: _Optional[str] = ...) -> None: ...
228
+
229
+ class MatchLabels(_message.Message):
230
+ __slots__ = ("labels",)
231
+ class LabelsEntry(_message.Message):
232
+ __slots__ = ("key", "value")
233
+ KEY_FIELD_NUMBER: _ClassVar[int]
234
+ VALUE_FIELD_NUMBER: _ClassVar[int]
235
+ key: str
236
+ value: str
237
+ def __init__(self, key: _Optional[str] = ..., value: _Optional[str] = ...) -> None: ...
238
+ LABELS_FIELD_NUMBER: _ClassVar[int]
239
+ labels: _containers.ScalarMap[str, str]
240
+ def __init__(self, labels: _Optional[_Mapping[str, str]] = ...) -> None: ...
241
+
242
+ class ResponseMeta(_message.Message):
243
+ __slots__ = ("tag", "ttl")
244
+ TAG_FIELD_NUMBER: _ClassVar[int]
245
+ TTL_FIELD_NUMBER: _ClassVar[int]
246
+ tag: str
247
+ ttl: _duration_pb2.Duration
248
+ def __init__(self, tag: _Optional[str] = ..., ttl: _Optional[_Union[datetime.timedelta, _duration_pb2.Duration, _Mapping]] = ...) -> None: ...
249
+
250
+ class State(_message.Message):
251
+ __slots__ = ("composite", "resources")
252
+ class ResourcesEntry(_message.Message):
253
+ __slots__ = ("key", "value")
254
+ KEY_FIELD_NUMBER: _ClassVar[int]
255
+ VALUE_FIELD_NUMBER: _ClassVar[int]
256
+ key: str
257
+ value: Resource
258
+ def __init__(self, key: _Optional[str] = ..., value: _Optional[_Union[Resource, _Mapping]] = ...) -> None: ...
259
+ COMPOSITE_FIELD_NUMBER: _ClassVar[int]
260
+ RESOURCES_FIELD_NUMBER: _ClassVar[int]
261
+ composite: Resource
262
+ resources: _containers.MessageMap[str, Resource]
263
+ def __init__(self, composite: _Optional[_Union[Resource, _Mapping]] = ..., resources: _Optional[_Mapping[str, Resource]] = ...) -> None: ...
264
+
265
+ class Resource(_message.Message):
266
+ __slots__ = ("resource", "connection_details", "ready")
267
+ class ConnectionDetailsEntry(_message.Message):
268
+ __slots__ = ("key", "value")
269
+ KEY_FIELD_NUMBER: _ClassVar[int]
270
+ VALUE_FIELD_NUMBER: _ClassVar[int]
271
+ key: str
272
+ value: bytes
273
+ def __init__(self, key: _Optional[str] = ..., value: _Optional[bytes] = ...) -> None: ...
274
+ RESOURCE_FIELD_NUMBER: _ClassVar[int]
275
+ CONNECTION_DETAILS_FIELD_NUMBER: _ClassVar[int]
276
+ READY_FIELD_NUMBER: _ClassVar[int]
277
+ resource: _struct_pb2.Struct
278
+ connection_details: _containers.ScalarMap[str, bytes]
279
+ ready: Ready
280
+ def __init__(self, resource: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ..., connection_details: _Optional[_Mapping[str, bytes]] = ..., ready: _Optional[_Union[Ready, str]] = ...) -> None: ...
281
+
282
+ class Result(_message.Message):
283
+ __slots__ = ("severity", "message", "reason", "target")
284
+ SEVERITY_FIELD_NUMBER: _ClassVar[int]
285
+ MESSAGE_FIELD_NUMBER: _ClassVar[int]
286
+ REASON_FIELD_NUMBER: _ClassVar[int]
287
+ TARGET_FIELD_NUMBER: _ClassVar[int]
288
+ severity: Severity
289
+ message: str
290
+ reason: str
291
+ target: Target
292
+ def __init__(self, severity: _Optional[_Union[Severity, str]] = ..., message: _Optional[str] = ..., reason: _Optional[str] = ..., target: _Optional[_Union[Target, str]] = ...) -> None: ...
293
+
294
+ class Condition(_message.Message):
295
+ __slots__ = ("type", "status", "reason", "message", "target")
296
+ TYPE_FIELD_NUMBER: _ClassVar[int]
297
+ STATUS_FIELD_NUMBER: _ClassVar[int]
298
+ REASON_FIELD_NUMBER: _ClassVar[int]
299
+ MESSAGE_FIELD_NUMBER: _ClassVar[int]
300
+ TARGET_FIELD_NUMBER: _ClassVar[int]
301
+ type: str
302
+ status: Status
303
+ reason: str
304
+ message: str
305
+ target: Target
306
+ 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,101 @@
1
+ # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
2
+ """Client and server classes corresponding to protobuf-defined services."""
3
+ import grpc
4
+ import warnings
5
+
6
+ from crossplane.pythonic.proto.v1 import run_function_pb2 as crossplane_dot_pythonic_dot_proto_dot_v1_dot_run__function__pb2
7
+
8
+ GRPC_GENERATED_VERSION = '1.80.0'
9
+ GRPC_VERSION = grpc.__version__
10
+ _version_not_supported = False
11
+
12
+ try:
13
+ from grpc._utilities import first_version_is_lower
14
+ _version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION)
15
+ except ImportError:
16
+ _version_not_supported = True
17
+
18
+ if _version_not_supported:
19
+ raise RuntimeError(
20
+ f'The grpc package installed is at version {GRPC_VERSION},'
21
+ + ' but the generated code in crossplane/pythonic/proto/v1/run_function_pb2_grpc.py depends on'
22
+ + f' grpcio>={GRPC_GENERATED_VERSION}.'
23
+ + f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}'
24
+ + f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.'
25
+ )
26
+
27
+
28
+ class FunctionRunnerServiceStub(object):
29
+ """A FunctionRunnerService is a function.
30
+ """
31
+
32
+ def __init__(self, channel):
33
+ """Constructor.
34
+
35
+ Args:
36
+ channel: A grpc.Channel.
37
+ """
38
+ self.RunFunction = channel.unary_unary(
39
+ '/apiextensions.fn.proto.v1.FunctionRunnerService/RunFunction',
40
+ request_serializer=crossplane_dot_pythonic_dot_proto_dot_v1_dot_run__function__pb2.RunFunctionRequest.SerializeToString,
41
+ response_deserializer=crossplane_dot_pythonic_dot_proto_dot_v1_dot_run__function__pb2.RunFunctionResponse.FromString,
42
+ _registered_method=True)
43
+
44
+
45
+ class FunctionRunnerServiceServicer(object):
46
+ """A FunctionRunnerService is a function.
47
+ """
48
+
49
+ def RunFunction(self, request, context):
50
+ """RunFunction runs the function.
51
+ """
52
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
53
+ context.set_details('Method not implemented!')
54
+ raise NotImplementedError('Method not implemented!')
55
+
56
+
57
+ def add_FunctionRunnerServiceServicer_to_server(servicer, server):
58
+ rpc_method_handlers = {
59
+ 'RunFunction': grpc.unary_unary_rpc_method_handler(
60
+ servicer.RunFunction,
61
+ request_deserializer=crossplane_dot_pythonic_dot_proto_dot_v1_dot_run__function__pb2.RunFunctionRequest.FromString,
62
+ response_serializer=crossplane_dot_pythonic_dot_proto_dot_v1_dot_run__function__pb2.RunFunctionResponse.SerializeToString,
63
+ ),
64
+ }
65
+ generic_handler = grpc.method_handlers_generic_handler(
66
+ 'apiextensions.fn.proto.v1.FunctionRunnerService', rpc_method_handlers)
67
+ server.add_generic_rpc_handlers((generic_handler,))
68
+ server.add_registered_method_handlers('apiextensions.fn.proto.v1.FunctionRunnerService', rpc_method_handlers)
69
+
70
+
71
+ # This class is part of an EXPERIMENTAL API.
72
+ class FunctionRunnerService(object):
73
+ """A FunctionRunnerService is a function.
74
+ """
75
+
76
+ @staticmethod
77
+ def RunFunction(request,
78
+ target,
79
+ options=(),
80
+ channel_credentials=None,
81
+ call_credentials=None,
82
+ insecure=False,
83
+ compression=None,
84
+ wait_for_ready=None,
85
+ timeout=None,
86
+ metadata=None):
87
+ return grpc.experimental.unary_unary(
88
+ request,
89
+ target,
90
+ '/apiextensions.fn.proto.v1.FunctionRunnerService/RunFunction',
91
+ crossplane_dot_pythonic_dot_proto_dot_v1_dot_run__function__pb2.RunFunctionRequest.SerializeToString,
92
+ crossplane_dot_pythonic_dot_proto_dot_v1_dot_run__function__pb2.RunFunctionResponse.FromString,
93
+ options,
94
+ channel_credentials,
95
+ insecure,
96
+ call_credentials,
97
+ compression,
98
+ wait_for_ready,
99
+ timeout,
100
+ metadata,
101
+ _registered_method=True)
@@ -897,6 +897,32 @@ class Value:
897
897
  return False
898
898
  return False
899
899
 
900
+ def __or__(self, other):
901
+ kind = self._kind
902
+ if kind not in ('struct_value', 'Struct'):
903
+ return NotImplemented
904
+ if not isinstance(other, (Value, dict)):
905
+ return NotImplemented
906
+ result = Map()
907
+ for key, value in self:
908
+ result[key] = value
909
+ items = other.items() if isinstance(other, dict) else iter(other)
910
+ for key, value in items:
911
+ result[key] = value
912
+ return result
913
+
914
+ def __ror__(self, other):
915
+ if not isinstance(other, dict):
916
+ return NotImplemented
917
+ result = Map()
918
+ for key, value in other.items():
919
+ result[key] = value
920
+ if self._kind not in ('struct_value', 'Struct'):
921
+ return NotImplemented
922
+ for key, value in self:
923
+ result[key] = value
924
+ return result
925
+
900
926
  def __str__(self):
901
927
  return format(self, '')
902
928
 
@@ -986,6 +1012,8 @@ class Value:
986
1012
  elif len(args):
987
1013
  for key in range(len(args)):
988
1014
  self[key] = args[key]
1015
+ else:
1016
+ self._ensure_map()
989
1017
  return self
990
1018
 
991
1019
  def __setattr__(self, key, value):
@@ -3,19 +3,21 @@ import asyncio
3
3
  import importlib
4
4
  import inflect
5
5
  import inspect
6
+ import json
6
7
  import kr8s
7
8
  import logging
8
9
  import pathlib
9
10
  import sys
10
11
  import yaml
11
- from crossplane.function.proto.v1 import run_function_pb2 as fnv1
12
12
 
13
13
  from . import (
14
14
  command,
15
- composite,
16
15
  function,
17
16
  protobuf,
18
17
  )
18
+ from .composite import BaseComposite
19
+ from .proto.v1 import run_function_pb2 as fnv1
20
+
19
21
 
20
22
  INFLECT = inflect.engine()
21
23
  INFLECT.classical(all=False)
@@ -58,7 +60,7 @@ class Command(command.Command):
58
60
  action='append',
59
61
  default=[],
60
62
  metavar='KEY=VALUE',
61
- help='Context key-value pairs to pass to the Function pipeline. Values must be sYAML/JSON. Keys take precedence over --context-files.',
63
+ help='Context key-value pairs to pass to the Function pipeline. Values must be YAML/JSON. Keys take precedence over --context-files.',
62
64
  )
63
65
  parser.add_argument(
64
66
  '--observed-resources', '-o',
@@ -77,12 +79,12 @@ class Command(command.Command):
77
79
  help='A YAML file or directory of YAML files specifying required resources to pass to the Function pipeline.',
78
80
  )
79
81
  parser.add_argument(
80
- '--secret-store', '-s',
82
+ '--required-schemas', '-s',
81
83
  action='append',
82
84
  type=pathlib.Path,
83
85
  default=[],
84
86
  metavar='PATH',
85
- help='A YAML file or directory of YAML files specifying Secrets to use to resolve connections and credentials.',
87
+ help='A JSON file or directory of JSON files specifying required schemas to pass to the Function pipeline.',
86
88
  )
87
89
  parser.add_argument(
88
90
  '--include-full-xr', '-x',
@@ -119,11 +121,10 @@ class Command(command.Command):
119
121
  observed = self.collect_resources(self.args.observed_resources)
120
122
  composition = await self.setup_composition(composite, api)
121
123
  resources = self.collect_resources(self.args.required_resources)
122
- resources += self.collect_resources(self.args.secret_store)
123
- resources.sort(key=lambda resource: str(resource.metadata.name))
124
+ schemas = self.collect_schemas(self.args.required_schemas)
124
125
  context = self.setup_context()
125
126
 
126
- render = await self.render(composite, observed, composition, resources, context, api, self.args.render_unknowns, self.args.crossplane_v1)
127
+ render = await self.render(composite, observed, composition, resources, schemas, context, api, self.args.render_unknowns, self.args.crossplane_v1)
127
128
  if not render:
128
129
  sys.exit(1)
129
130
 
@@ -212,7 +213,7 @@ class Command(command.Command):
212
213
  if not inspect.isclass(clazz):
213
214
  print(f"Composition class {self.args.composition} is not a class", file=sys.stderr)
214
215
  sys.exit(1)
215
- if not issubclass(clazz, composite.BaseComposite):
216
+ if not issubclass(clazz, BaseComposite):
216
217
  print(f"Composition class {self.args.composition} is not a subclass of BaseComposite", file=sys.stderr)
217
218
  sys.exit(1)
218
219
  return self.create_composition(composite, self.args.composition)
@@ -246,8 +247,25 @@ class Command(command.Command):
246
247
  else:
247
248
  print(f"Specified resource is not a file or a directory: {entry}", file=sys.stderr)
248
249
  sys.exit(1)
250
+ resources.sort(key=lambda resource: str(resource.metadata.name))
249
251
  return resources
250
252
 
253
+ def collect_schemas(self, entries):
254
+ schemas = []
255
+ for entry in entries:
256
+ if entry.is_file():
257
+ document = json.loads(entry.read_text())
258
+ schemas.append(protobuf.Value(None, None, document))
259
+ elif entry.is_dir():
260
+ for file in entry.iterdir():
261
+ if file.suffix == '.json':
262
+ document = json.loads(file.read_text())
263
+ schemas.append(protobuf.Value(None, None, document))
264
+ else:
265
+ print(f"Specified resource is not a file or a directory: {entry}", file=sys.stderr)
266
+ sys.exit(1)
267
+ return schemas
268
+
251
269
  def setup_context(self):
252
270
  # Load the request context with any specified command line options.
253
271
  context = protobuf.Map()
@@ -269,7 +287,7 @@ class Command(command.Command):
269
287
  context[key_value[0]] = protobuf.Yaml(key_value[1])
270
288
  return context
271
289
 
272
- async def render(self, composite, observed=[], composition=None, resources=[], context=None, api=None, render_unknowns=False, crossplane_v1=False, composite_observeds=True):
290
+ async def render(self, composite, observed=[], composition=None, resources=[], schemas=[], context=None, api=None, render_unknowns=False, crossplane_v1=False, composite_observeds=True):
273
291
  # Create the request used when running Composition steps.
274
292
  request = protobuf.Message(None, 'request', fnv1.RunFunctionRequest.DESCRIPTOR, fnv1.RunFunctionRequest())
275
293
  if context is not None:
@@ -362,6 +380,10 @@ class Command(command.Command):
362
380
  request.extra_resources()
363
381
  for name, selector in requirements.extra_resources:
364
382
  await self.set_required(name, selector, request.extra_resources, resources, api)
383
+ # Fetch the schemas requested.
384
+ request.required_schemas()
385
+ for name, selector in requirements.schemas:
386
+ await self.set_schema(name, selector, request.required_schemas, schemas, api)
365
387
  # Run the step using the function-pythonic function runner.
366
388
  response = protobuf.Message(
367
389
  None,
@@ -546,6 +568,81 @@ class Command(command.Command):
546
568
  for key, value in connection.data:
547
569
  destination.connection_details[key] = protobuf.B64Decode(value)
548
570
 
571
+ async def set_schema(self, name, selector, schemas, documents=[], api=None):
572
+ if not name:
573
+ return
574
+ name = str(name)
575
+ schema = schemas[name].openapi_v3
576
+ schema() # Force this to get created
577
+ gvk = protobuf.Map(kind=selector.kind)
578
+ version = str(selector.api_version)
579
+ if '/' in version:
580
+ gvk.group, gvk.version = version.split('/', 1)
581
+ else:
582
+ gvk.group = ''
583
+ gvk.version = version
584
+ for document in documents:
585
+ if self.find_schema(gvk, document, schema):
586
+ return
587
+ if api:
588
+ if gvk.group == '':
589
+ url = f"api/{gvk.version}"
590
+ else:
591
+ url = f"apis/{gvk.group}/{gvk.version}"
592
+ try:
593
+ async with api.call_api(base='/openapi/v3', version='', url=url) as response:
594
+ document = protobuf.Value(None, None, response.json())
595
+ except kr8s.NotFoundError:
596
+ return
597
+ self.find_schema(gvk, document, schema)
598
+
599
+ def find_schema(self, gvk, document, schema):
600
+ for name, s in document.components.schemas:
601
+ gvks = s['x-kubernetes-group-version-kind']
602
+ if len(gvks) == 1 and gvks[0] == gvk:
603
+ self.resolve_ref(document, set(), f"#/components/schemas/{name}", schema)
604
+ return True
605
+ return False
606
+
607
+ def resolve_ref(self, document, visiting, ref, schema):
608
+ if not ref:
609
+ return
610
+ ref = str(ref)
611
+ if ref in visiting:
612
+ return
613
+ d = None
614
+ for segment in ref.split('/'):
615
+ if segment == '#':
616
+ d = document
617
+ else:
618
+ d = d[segment]
619
+ if not d:
620
+ return
621
+ visiting.add(ref)
622
+ try:
623
+ for name, value in d:
624
+ self.copy_schema(document, visiting, name, value, schema)
625
+ finally:
626
+ visiting.remove(ref)
627
+
628
+ def copy_schema(self, document, visiting, key, value, schema):
629
+ if key == '$ref':
630
+ self.resolve_ref(document, visiting, value, schema)
631
+ elif key == 'allOf':
632
+ if value._isList and len(value) == 1:
633
+ self.resolve_ref(document, visiting, value[0]['$ref'], schema)
634
+ else:
635
+ if value._isMap:
636
+ s = schema[key]
637
+ for n, v in value:
638
+ self.copy_schema(document, visiting, n, v, s)
639
+ elif value._isList:
640
+ s = schema[key]
641
+ for ix, v in enumerate(value):
642
+ self.copy_schema(document, visiting, ix, v, s)
643
+ else:
644
+ schema[key] = value
645
+
549
646
  def copy_resource(self, source, destination):
550
647
  destination.resource = source.resource
551
648
  destination.connection_details()